RetroArch
nuklear.h
Go to the documentation of this file.
1 /*
2  Nuklear - 2.00.0 - public domain
3  no warranty implied; use at your own risk.
4  authored from 2015-2017 by Micha Mettke
5 
6 ABOUT:
7  This is a minimal state graphical user interface single header toolkit
8  written in ANSI C and licensed under public domain.
9  It was designed as a simple embeddable user interface for application and does
10  not have any dependencies, a default renderbackend or OS window and input handling
11  but instead provides a very modular library approach by using simple input state
12  for input and draw commands describing primitive shapes as output.
13  So instead of providing a layered library that tries to abstract over a number
14  of platform and render backends it only focuses on the actual UI.
15 
16 VALUES:
17  - Graphical user interface toolkit
18  - Single header library
19  - Written in C89 (a.k.a. ANSI C or ISO C90)
20  - Small codebase (~18kLOC)
21  - Focus on portability, efficiency and simplicity
22  - No dependencies (not even the standard library if not wanted)
23  - Fully skinnable and customizable
24  - Low memory footprint with total memory control if needed or wanted
25  - UTF-8 support
26  - No global or hidden state
27  - Customizable library modules (you can compile and use only what you need)
28  - Optional font baker and vertex buffer output
29 
30 USAGE:
31  This library is self contained in one single header file and can be used either
32  in header only mode or in implementation mode. The header only mode is used
33  by default when included and allows including this header in other headers
34  and does not contain the actual implementation.
35 
36  The implementation mode requires to define the preprocessor macro
37  NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.:
38 
39  #define NK_IMPLEMENTATION
40  #include "nuklear.h"
41 
42  Also optionally define the symbols listed in the section "OPTIONAL DEFINES"
43  below in header and implementation mode if you want to use additional functionality
44  or need more control over the library.
45  IMPORTANT: Every time you include "nuklear.h" you have to define the same flags.
46  This is very important not doing it either leads to compiler errors
47  or even worse stack corruptions.
48 
49 FEATURES:
50  - Absolutely no platform dependent code
51  - Memory management control ranging from/to
52  - Ease of use by allocating everything from standard library
53  - Control every byte of memory inside the library
54  - Font handling control ranging from/to
55  - Use your own font implementation for everything
56  - Use this libraries internal font baking and handling API
57  - Drawing output control ranging from/to
58  - Simple shapes for more high level APIs which already have drawing capabilities
59  - Hardware accessible anti-aliased vertex buffer output
60  - Customizable colors and properties ranging from/to
61  - Simple changes to color by filling a simple color table
62  - Complete control with ability to use skinning to decorate widgets
63  - Bendable UI library with widget ranging from/to
64  - Basic widgets like buttons, checkboxes, slider, ...
65  - Advanced widget like abstract comboboxes, contextual menus,...
66  - Compile time configuration to only compile what you need
67  - Subset which can be used if you do not want to link or use the standard library
68  - Can be easily modified to only update on user input instead of frame updates
69 
70 OPTIONAL DEFINES:
71  NK_PRIVATE
72  If defined declares all functions as static, so they can only be accessed
73  inside the file that contains the implementation
74 
75  NK_INCLUDE_FIXED_TYPES
76  If defined it will include header <stdint.h> for fixed sized types
77  otherwise nuklear tries to select the correct type. If that fails it will
78  throw a compiler error and you have to select the correct types yourself.
79  <!> If used needs to be defined for implementation and header <!>
80 
81  NK_INCLUDE_DEFAULT_ALLOCATOR
82  if defined it will include header <stdlib.h> and provide additional functions
83  to use this library without caring for memory allocation control and therefore
84  ease memory management.
85  <!> Adds the standard library with malloc and free so don't define if you
86  don't want to link to the standard library <!>
87  <!> If used needs to be defined for implementation and header <!>
88 
89  NK_INCLUDE_STANDARD_IO
90  if defined it will include header <stdio.h> and provide
91  additional functions depending on file loading.
92  <!> Adds the standard library with fopen, fclose,... so don't define this
93  if you don't want to link to the standard library <!>
94  <!> If used needs to be defined for implementation and header <!>
95 
96  NK_INCLUDE_STANDARD_VARARGS
97  if defined it will include header <stdarg.h> and provide
98  additional functions depending on variable arguments
99  <!> Adds the standard library with va_list and so don't define this if
100  you don't want to link to the standard library<!>
101  <!> If used needs to be defined for implementation and header <!>
102 
103  NK_INCLUDE_VERTEX_BUFFER_OUTPUT
104  Defining this adds a vertex draw command list backend to this
105  library, which allows you to convert queue commands into vertex draw commands.
106  This is mainly if you need a hardware accessible format for OpenGL, DirectX,
107  Vulkan, Metal,...
108  <!> If used needs to be defined for implementation and header <!>
109 
110  NK_INCLUDE_FONT_BAKING
111  Defining this adds `stb_truetype` and `stb_rect_pack` implementation
112  to this library and provides font baking and rendering.
113  If you already have font handling or do not want to use this font handler
114  you don't have to define it.
115  <!> If used needs to be defined for implementation and header <!>
116 
117  NK_INCLUDE_DEFAULT_FONT
118  Defining this adds the default font: ProggyClean.ttf into this library
119  which can be loaded into a font atlas and allows using this library without
120  having a truetype font
121  <!> Enabling this adds ~12kb to global stack memory <!>
122  <!> If used needs to be defined for implementation and header <!>
123 
124  NK_INCLUDE_COMMAND_USERDATA
125  Defining this adds a userdata pointer into each command. Can be useful for
126  example if you want to provide custom shaders depending on the used widget.
127  Can be combined with the style structures.
128  <!> If used needs to be defined for implementation and header <!>
129 
130  NK_BUTTON_TRIGGER_ON_RELEASE
131  Different platforms require button clicks occurring either on buttons being
132  pressed (up to down) or released (down to up).
133  By default this library will react on buttons being pressed, but if you
134  define this it will only trigger if a button is released.
135  <!> If used it is only required to be defined for the implementation part <!>
136 
137  NK_ZERO_COMMAND_MEMORY
138  Defining this will zero out memory for each drawing command added to a
139  drawing queue (inside nk_command_buffer_push). Zeroing command memory
140  is very useful for fast checking (using memcmp) if command buffers are
141  equal and avoid drawing frames when nothing on screen has changed since
142  previous frame.
143 
144  NK_ASSERT
145  If you don't define this, nuklear will use <assert.h> with assert().
146  <!> Adds the standard library so define to nothing of not wanted <!>
147  <!> If used needs to be defined for implementation and header <!>
148 
149  NK_BUFFER_DEFAULT_INITIAL_SIZE
150  Initial buffer size allocated by all buffers while using the default allocator
151  functions included by defining NK_INCLUDE_DEFAULT_ALLOCATOR. If you don't
152  want to allocate the default 4k memory then redefine it.
153  <!> If used needs to be defined for implementation and header <!>
154 
155  NK_MAX_NUMBER_BUFFER
156  Maximum buffer size for the conversion buffer between float and string
157  Under normal circumstances this should be more than sufficient.
158  <!> If used needs to be defined for implementation and header <!>
159 
160  NK_INPUT_MAX
161  Defines the max number of bytes which can be added as text input in one frame.
162  Under normal circumstances this should be more than sufficient.
163  <!> If used it is only required to be defined for the implementation part <!>
164 
165  NK_MEMSET
166  You can define this to 'memset' or your own memset implementation
167  replacement. If not nuklear will use its own version.
168  <!> If used it is only required to be defined for the implementation part <!>
169 
170  NK_MEMCPY
171  You can define this to 'memcpy' or your own memcpy implementation
172  replacement. If not nuklear will use its own version.
173  <!> If used it is only required to be defined for the implementation part <!>
174 
175  NK_SQRT
176  You can define this to 'sqrt' or your own sqrt implementation
177  replacement. If not nuklear will use its own slow and not highly
178  accurate version.
179  <!> If used it is only required to be defined for the implementation part <!>
180 
181  NK_SIN
182  You can define this to 'sinf' or your own sine implementation
183  replacement. If not nuklear will use its own approximation implementation.
184  <!> If used it is only required to be defined for the implementation part <!>
185 
186  NK_COS
187  You can define this to 'cosf' or your own cosine implementation
188  replacement. If not nuklear will use its own approximation implementation.
189  <!> If used it is only required to be defined for the implementation part <!>
190 
191  NK_STRTOD
192  You can define this to `strtod` or your own string to double conversion
193  implementation replacement. If not defined nuklear will use its own
194  imprecise and possibly unsafe version (does not handle nan or infinity!).
195  <!> If used it is only required to be defined for the implementation part <!>
196 
197  NK_DTOA
198  You can define this to `dtoa` or your own double to string conversion
199  implementation replacement. If not defined nuklear will use its own
200  imprecise and possibly unsafe version (does not handle nan or infinity!).
201  <!> If used it is only required to be defined for the implementation part <!>
202 
203  NK_VSNPRINTF
204  If you define `NK_INCLUDE_STANDARD_VARARGS` as well as `NK_INCLUDE_STANDARD_IO`
205  and want to be safe define this to `vsnprintf` on compilers supporting
206  later versions of C or C++. By default nuklear will check for your stdlib version
207  in C as well as compiler version in C++. if `vsnprintf` is available
208  it will define it to `vsnprintf` directly. If not defined and if you have
209  older versions of C or C++ it will be defined to `vsprintf` which is unsafe.
210  <!> If used it is only required to be defined for the implementation part <!>
211 
212  NK_BYTE
213  NK_INT16
214  NK_UINT16
215  NK_INT32
216  NK_UINT32
217  NK_SIZE_TYPE
218  NK_POINTER_TYPE
219  If you compile without NK_USE_FIXED_TYPE then a number of standard types
220  will be selected and compile time validated. If they are incorrect you can
221  define the correct types by overloading these type defines.
222 
223 CREDITS:
224  Developed by Micha Mettke and every direct or indirect contributor.
225 
226  Embeds stb_texedit, stb_truetype and stb_rectpack by Sean Barret (public domain)
227  Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license).
228 
229  Big thank you to Omar Cornut (ocornut@github) for his imgui library and
230  giving me the inspiration for this library, Casey Muratori for handmade hero
231  and his original immediate mode graphical user interface idea and Sean
232  Barret for his amazing single header libraries which restored my faith
233  in libraries and brought me to create some of my own.
234 
235 LICENSE:
236  This software is dual-licensed to the public domain and under the following
237  license: you are granted a perpetual, irrevocable license to copy, modify,
238  publish and distribute this file as you see fit.
239 */
240 #ifndef NK_NUKLEAR_H_
241 #define NK_NUKLEAR_H_
242 
243 #ifdef __cplusplus
244 extern "C" {
245 #endif
246 /*
247  * ==============================================================
248  *
249  * CONSTANTS
250  *
251  * ===============================================================
252  */
253 #define NK_UNDEFINED (-1.0f)
254 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */
255 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/
256 #ifndef NK_INPUT_MAX
257 #define NK_INPUT_MAX 16
258 #endif
259 #ifndef NK_MAX_NUMBER_BUFFER
260 #define NK_MAX_NUMBER_BUFFER 64
261 #endif
262 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT
263 #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f
264 #endif
265 /*
266  * ==============================================================
267  *
268  * HELPER
269  *
270  * ===============================================================
271  */
272 #ifndef NK_API
273  #ifdef NK_PRIVATE
274  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L))
275  #define NK_API static inline
276  #elif defined(__cplusplus)
277  #define NK_API static inline
278  #else
279  #define NK_API static
280  #endif
281  #else
282  #define NK_API extern
283  #endif
284 #endif
285 
286 #define NK_INTERN static
287 #define NK_STORAGE static
288 #define NK_GLOBAL static
289 
290 #define NK_FLAG(x) (1 << (x))
291 #define NK_STRINGIFY(x) #x
292 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x)
293 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2
294 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2)
295 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2)
296 
297 #ifdef _MSC_VER
298 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__)
299 #else
300 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__)
301 #endif
302 
303 #ifndef NK_STATIC_ASSERT
304 #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1]
305 #endif
306 
307 #ifndef NK_FILE_LINE
308 #ifdef _MSC_VER
309 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__)
310 #else
311 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__)
312 #endif
313 #endif
314 
315 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b))
316 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a))
317 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i))
318 /*
319  * ===============================================================
320  *
321  * BASIC
322  *
323  * ===============================================================
324  */
325 #ifdef NK_INCLUDE_FIXED_TYPES
326  #include <stdint.h>
327  #define NK_INT8 int8_t
328  #define NK_UINT8 uint8_t
329  #define NK_INT16 int16_t
330  #define NK_UINT16 uint16_t
331  #define NK_INT32 int32_t
332  #define NK_UINT32 uint32_t
333  #define NK_SIZE_TYPE uintptr_t
334  #define NK_POINTER_TYPE uintptr_t
335 #else
336  #ifndef NK_INT8
337  #define NK_INT8 char
338  #endif
339  #ifndef NK_UINT8
340  #define NK_UINT8 unsigned char
341  #endif
342  #ifndef NK_INT16
343  #define NK_INT16 signed short
344  #endif
345  #ifndef NK_UINT16
346  #define NK_UINT16 unsigned short
347  #endif
348  #ifndef NK_INT32
349  #if defined(_MSC_VER)
350  #define NK_INT32 __int32
351  #else
352  #define NK_INT32 signed int
353  #endif
354  #endif
355  #ifndef NK_UINT32
356  #if defined(_MSC_VER)
357  #define NK_UINT32 unsigned __int32
358  #else
359  #define NK_UINT32 unsigned int
360  #endif
361  #endif
362  #ifndef NK_SIZE_TYPE
363  #if defined(_WIN64) && defined(_MSC_VER)
364  #define NK_SIZE_TYPE unsigned __int64
365  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
366  #define NK_SIZE_TYPE unsigned __int32
367  #elif defined(__GNUC__) || defined(__clang__)
368  #if defined(__x86_64__) || defined(__ppc64__)
369  #define NK_SIZE_TYPE unsigned long
370  #else
371  #define NK_SIZE_TYPE unsigned int
372  #endif
373  #else
374  #define NK_SIZE_TYPE unsigned long
375  #endif
376  #endif
377  #ifndef NK_POINTER_TYPE
378  #if defined(_WIN64) && defined(_MSC_VER)
379  #define NK_POINTER_TYPE unsigned __int64
380  #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER)
381  #define NK_POINTER_TYPE unsigned __int32
382  #elif defined(__GNUC__) || defined(__clang__)
383  #if defined(__x86_64__) || defined(__ppc64__)
384  #define NK_POINTER_TYPE unsigned long
385  #else
386  #define NK_POINTER_TYPE unsigned int
387  #endif
388  #else
389  #define NK_POINTER_TYPE unsigned long
390  #endif
391  #endif
392 #endif
393 
394 typedef NK_INT8 nk_char;
399 typedef NK_INT32 nk_int;
403 
404 typedef nk_uint nk_hash;
406 typedef nk_uint nk_rune;
407 
408 /* Make sure correct type size:
409  * This will fire with a negative subscript error if the type sizes
410  * are set incorrectly by the compiler, and compile out if not */
411 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
412 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
413 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
414 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
415 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
416 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
417 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
418 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
419 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*));
420 
421 /* ============================================================================
422  *
423  * API
424  *
425  * =========================================================================== */
426 struct nk_buffer;
427 struct nk_allocator;
428 struct nk_command_buffer;
429 struct nk_draw_command;
430 struct nk_convert_config;
431 struct nk_style_item;
432 struct nk_text_edit;
433 struct nk_draw_list;
434 struct nk_user_font;
435 struct nk_panel;
436 struct nk_context;
437 struct nk_draw_vertex_layout_element;
438 struct nk_style_button;
439 struct nk_style_toggle;
440 struct nk_style_selectable;
441 struct nk_style_slide;
442 struct nk_style_progress;
443 struct nk_style_scrollbar;
444 struct nk_style_edit;
445 struct nk_style_property;
446 struct nk_style_chart;
447 struct nk_style_combo;
448 struct nk_style_tab;
450 struct nk_style_window;
451 
453 struct nk_color {nk_byte r,g,b,a;};
454 struct nk_colorf {float r,g,b,a;};
455 struct nk_vec2 {float x,y;};
456 struct nk_vec2i {short x, y;};
457 struct nk_rect {float x,y,w,h;};
458 struct nk_recti {short x,y,w,h;};
459 typedef char nk_glyph[NK_UTF_SIZE];
460 typedef union {void *ptr; int id;} nk_handle;
461 struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];};
462 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;};
463 struct nk_scroll {nk_uint x, y;};
464 
477 
478 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size);
479 typedef void (*nk_plugin_free)(nk_handle, void *old);
480 typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode);
482 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len);
483 
484 struct nk_allocator {
488 };
504 };
505 /* =============================================================================
506  *
507  * CONTEXT
508  *
509  * =============================================================================*/
510 /* Contexts are the main entry point and the majestro of nuklear and contain all required state.
511  * They are used for window, memory, input, style, stack, commands and time management and need
512  * to be passed into all nuklear GUI specific functions.
513  *
514  * Usage
515  * -------------------
516  * To use a context it first has to be initialized which can be achieved by calling
517  * one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`.
518  * Each takes in a font handle and a specific way of handling memory. Memory control
519  * hereby ranges from standard library to just specifying a fixed sized block of memory
520  * which nuklear has to manage itself from.
521  *
522  * struct nk_context ctx;
523  * nk_init_xxx(&ctx, ...);
524  * while (1) {
525  * [...]
526  * nk_clear(&ctx);
527  * }
528  * nk_free(&ctx);
529  *
530  * Reference
531  * -------------------
532  * nk_init_default - Initializes context with standard library memory allocation (malloc,free)
533  * nk_init_fixed - Initializes context from single fixed size memory block
534  * nk_init - Initializes context with memory allocator callbacks for alloc and free
535  * nk_init_custom - Initializes context from two buffers. One for draw commands the other for window/panel/table allocations
536  * nk_clear - Called at the end of the frame to reset and prepare the context for the next frame
537  * nk_free - Shutdown and free all memory allocated inside the context
538  * nk_set_user_data - Utility function to pass user data to draw command
539  */
540 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
541 /* nk_init_default - Initializes a `nk_context` struct with a default standard library allocator.
542  * Should be used if you don't want to be bothered with memory management in nuklear.
543  * Parameters:
544  * @ctx must point to an either stack or heap allocated `nk_context` struct
545  * @font must point to a previously initialized font handle for more info look at font documentation
546  * Return values:
547  * true(1) on success
548  * false(0) on failure */
549 NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*);
550 #endif
551 /* nk_init_fixed - Initializes a `nk_context` struct from a single fixed size memory block
552  * Should be used if you want complete control over nuklear's memory management.
553  * Especially recommended for system with little memory or systems with virtual memory.
554  * For the later case you can just allocate for example 16MB of virtual memory
555  * and only the required amount of memory will actually be committed.
556  * IMPORTANT: make sure the passed memory block is aligned correctly for `nk_draw_commands`
557  * Parameters:
558  * @ctx must point to an either stack or heap allocated `nk_context` struct
559  * @memory must point to a previously allocated memory block
560  * @size must contain the total size of @memory
561  * @font must point to a previously initialized font handle for more info look at font documentation
562  * Return values:
563  * true(1) on success
564  * false(0) on failure */
565 NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*);
566 /* nk_init - Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate
567  * memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation
568  * interface to nuklear. Can be useful for cases like monitoring memory consumption.
569  * Parameters:
570  * @ctx must point to an either stack or heap allocated `nk_context` struct
571  * @alloc must point to a previously allocated memory allocator
572  * @font must point to a previously initialized font handle for more info look at font documentation
573  * Return values:
574  * true(1) on success
575  * false(0) on failure */
576 NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*);
577 /* nk_init_custom - Initializes a `nk_context` struct from two different either fixed or growing
578  * buffers. The first buffer is for allocating draw commands while the second buffer is
579  * used for allocating windows, panels and state tables.
580  * Parameters:
581  * @ctx must point to an either stack or heap allocated `nk_context` struct
582  * @cmds must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into
583  * @pool must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables
584  * @font must point to a previously initialized font handle for more info look at font documentation
585  * Return values:
586  * true(1) on success
587  * false(0) on failure */
588 NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*);
589 /* nk_clear - Resets the context state at the end of the frame. This includes mostly
590  * garbage collector tasks like removing windows or table not called and therefore
591  * used anymore.
592  * Parameters:
593  * @ctx must point to a previously initialized `nk_context` struct */
594 NK_API void nk_clear(struct nk_context*);
595 /* nk_free - Frees all memory allocated by nuklear. Not needed if context was
596  * initialized with `nk_init_fixed`.
597  * Parameters:
598  * @ctx must point to a previously initialized `nk_context` struct */
599 NK_API void nk_free(struct nk_context*);
600 #ifdef NK_INCLUDE_COMMAND_USERDATA
601 /* nk_set_user_data - Sets the currently passed userdata passed down into each draw command.
602  * Parameters:
603  * @ctx must point to a previously initialized `nk_context` struct
604  * @data handle with either pointer or index to be passed into every draw commands */
605 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle);
606 #endif
607 /* =============================================================================
608  *
609  * INPUT
610  *
611  * =============================================================================*/
612 /* The input API is responsible for holding the current input state composed of
613  * mouse, key and text input states.
614  * It is worth noting that no direct os or window handling is done in nuklear.
615  * Instead all input state has to be provided by platform specific code. This in one hand
616  * expects more work from the user and complicates usage but on the other hand
617  * provides simple abstraction over a big number of platforms, libraries and other
618  * already provided functionality.
619  *
620  * Usage
621  * -------------------
622  * Input state needs to be provided to nuklear by first calling `nk_input_begin`
623  * which resets internal state like delta mouse position and button transistions.
624  * After `nk_input_begin` all current input state needs to be provided. This includes
625  * mouse motion, button and key pressed and released, text input and scrolling.
626  * Both event- or state-based input handling are supported by this API
627  * and should work without problems. Finally after all input state has been
628  * mirrored `nk_input_end` needs to be called to finish input process.
629  *
630  * struct nk_context ctx;
631  * nk_init_xxx(&ctx, ...);
632  * while (1) {
633  * Event evt;
634  * nk_input_begin(&ctx);
635  * while (GetEvent(&evt)) {
636  * if (evt.type == MOUSE_MOVE)
637  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
638  * else if (evt.type == ...) {
639  * ...
640  * }
641  * }
642  * nk_input_end(&ctx);
643  * [...]
644  * nk_clear(&ctx);
645  * }
646  * nk_free(&ctx);
647  *
648  * Reference
649  * -------------------
650  * nk_input_begin - Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls
651  * nk_input_motion - Mirrors mouse cursor position
652  * nk_input_key - Mirrors key state with either pressed or released
653  * nk_input_button - Mirrors mouse button state with either pressed or released
654  * nk_input_scroll - Mirrors mouse scroll values
655  * nk_input_char - Adds a single ASCII text character into an internal text buffer
656  * nk_input_glyph - Adds a single multi-byte UTF-8 character into an internal text buffer
657  * nk_input_unicode - Adds a single unicode rune into an internal text buffer
658  * nk_input_end - Ends the input mirroring process by calculating state changes. Don't call any `nk_input_xxx` function referenced above after this call
659  */
660 enum nk_keys {
675  /* Shortcuts: text field */
688  /* Shortcuts: scrollbar */
694 };
701 };
702 /* nk_input_begin - Begins the input mirroring process by resetting text, scroll
703  * mouse previous mouse position and movement as well as key state transitions,
704  * Parameters:
705  * @ctx must point to an previously initialized `nk_context` struct */
706 NK_API void nk_input_begin(struct nk_context*);
707 /* nk_input_motion - Mirrors current mouse position to nuklear
708  * Parameters:
709  * @ctx must point to an previously initialized `nk_context` struct
710  * @x must contain an integer describing the current mouse cursor x-position
711  * @y must contain an integer describing the current mouse cursor y-position */
712 NK_API void nk_input_motion(struct nk_context*, int x, int y);
713 /* nk_input_key - Mirrors state of a specific key to nuklear
714  * Parameters:
715  * @ctx must point to an previously initialized `nk_context` struct
716  * @key must be any value specified in enum `nk_keys` that needs to be mirrored
717  * @down must be 0 for key is up and 1 for key is down */
718 NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down);
719 /* nk_input_button - Mirrors the state of a specific mouse button to nuklear
720  * Parameters:
721  * @ctx must point to an previously initialized `nk_context` struct
722  * @nk_buttons must be any value specified in enum `nk_buttons` that needs to be mirrored
723  * @x must contain an integer describing mouse cursor x-position on click up/down
724  * @y must contain an integer describing mouse cursor y-position on click up/down
725  * @down must be 0 for key is up and 1 for key is down */
726 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down);
727 /* nk_input_scroll - Copies the last mouse scroll value to nuklear. Is generally
728  * a scroll value. So does not have to come from mouse and could also originate
729  * from touch for example.
730  * Parameters:
731  * @ctx must point to an previously initialized `nk_context` struct
732  * @val vector with both X- as well as Y-scroll value */
733 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val);
734 /* nk_input_char - Copies a single ASCII character into an internal text buffer
735  * This is basically a helper function to quickly push ASCII characters into
736  * nuklear. Note that you can only push up to NK_INPUT_MAX bytes into
737  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
738  * Parameters:
739  * @ctx must point to an previously initialized `nk_context` struct
740  * @c must be a single ASCII character preferable one that can be printed */
741 NK_API void nk_input_char(struct nk_context*, char);
742 /* nk_input_unicode - Converts a encoded unicode rune into UTF-8 and copies the result
743  * into an internal text buffer.
744  * Note that you can only push up to NK_INPUT_MAX bytes into
745  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
746  * Parameters:
747  * @ctx must point to an previously initialized `nk_context` struct
748  * @glyph UTF-32 unicode codepoint */
749 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph);
750 /* nk_input_unicode - Converts a unicode rune into UTF-8 and copies the result
751  * into an internal text buffer.
752  * Note that you can only push up to NK_INPUT_MAX bytes into
753  * struct `nk_input` between `nk_input_begin` and `nk_input_end`.
754  * Parameters:
755  * @ctx must point to an previously initialized `nk_context` struct
756  * @glyph UTF-32 unicode codepoint */
758 /* nk_input_end - End the input mirroring process by resetting mouse grabbing
759  * state to ensure the mouse cursor is not grabbed indefinitely.
760  * Parameters:
761  * @ctx must point to an previously initialized `nk_context` struct */
762 NK_API void nk_input_end(struct nk_context*);
763 /* =============================================================================
764  *
765  * DRAWING
766  *
767  * =============================================================================*/
768 /* This library was designed to be render backend agnostic so it does
769  * not draw anything to screen directly. Instead all drawn shapes, widgets
770  * are made of, are buffered into memory and make up a command queue.
771  * Each frame therefore fills the command buffer with draw commands
772  * that then need to be executed by the user and his own render backend.
773  * After that the command buffer needs to be cleared and a new frame can be
774  * started. It is probably important to note that the command buffer is the main
775  * drawing API and the optional vertex buffer API only takes this format and
776  * converts it into a hardware accessible format.
777  *
778  * Usage
779  * -------------------
780  * To draw all draw commands accumulated over a frame you need your own render
781  * backend able to draw a number of 2D primitives. This includes at least
782  * filled and stroked rectangles, circles, text, lines, triangles and scissors.
783  * As soon as this criterion is met you can iterate over each draw command
784  * and execute each draw command in a interpreter like fashion:
785  *
786  * const struct nk_command *cmd = 0;
787  * nk_foreach(cmd, &ctx) {
788  * switch (cmd->type) {
789  * case NK_COMMAND_LINE:
790  * your_draw_line_function(...)
791  * break;
792  * case NK_COMMAND_RECT
793  * your_draw_rect_function(...)
794  * break;
795  * case ...:
796  * [...]
797  * }
798  *
799  * In program flow context draw commands need to be executed after input has been
800  * gathered and the complete UI with windows and their contained widgets have
801  * been executed and before calling `nk_clear` which frees all previously
802  * allocated draw commands.
803  *
804  * struct nk_context ctx;
805  * nk_init_xxx(&ctx, ...);
806  * while (1) {
807  * Event evt;
808  * nk_input_begin(&ctx);
809  * while (GetEvent(&evt)) {
810  * if (evt.type == MOUSE_MOVE)
811  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
812  * else if (evt.type == [...]) {
813  * [...]
814  * }
815  * }
816  * nk_input_end(&ctx);
817  *
818  * [...]
819  *
820  * const struct nk_command *cmd = 0;
821  * nk_foreach(cmd, &ctx) {
822  * switch (cmd->type) {
823  * case NK_COMMAND_LINE:
824  * your_draw_line_function(...)
825  * break;
826  * case NK_COMMAND_RECT
827  * your_draw_rect_function(...)
828  * break;
829  * case ...:
830  * [...]
831  * }
832  * nk_clear(&ctx);
833  * }
834  * nk_free(&ctx);
835  *
836  * You probably noticed that you have to draw all of the UI each frame which is
837  * quite wasteful. While the actual UI updating loop is quite fast rendering
838  * without actually needing it is not. So there are multiple things you could do.
839  *
840  * First is only update on input. This of course is only an option if your
841  * application only depends on the UI and does not require any outside calculations.
842  * If you actually only update on input make sure to update the UI two times each
843  * frame and call `nk_clear` directly after the first pass and only draw in
844  * the second pass. In addition it is recommended to also add additional timers
845  * to make sure the UI is not drawn more than a fixed number of frames per second.
846  *
847  * struct nk_context ctx;
848  * nk_init_xxx(&ctx, ...);
849  * while (1) {
850  * [...wait for input ]
851  *
852  * [...do two UI passes ...]
853  * do_ui(...)
854  * nk_clear(&ctx);
855  * do_ui(...)
856  *
857  * const struct nk_command *cmd = 0;
858  * nk_foreach(cmd, &ctx) {
859  * switch (cmd->type) {
860  * case NK_COMMAND_LINE:
861  * your_draw_line_function(...)
862  * break;
863  * case NK_COMMAND_RECT
864  * your_draw_rect_function(...)
865  * break;
866  * case ...:
867  * [...]
868  * }
869  * nk_clear(&ctx);
870  * }
871  * nk_free(&ctx);
872  *
873  * The second probably more applicable trick is to only draw if anything changed.
874  * It is not really useful for applications with continuous draw loop but
875  * quite useful for desktop applications. To actually get nuklear to only
876  * draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and
877  * allocate a memory buffer that will store each unique drawing output.
878  * After each frame you compare the draw command memory inside the library
879  * with your allocated buffer by memcmp. If memcmp detects differences
880  * you have to copy the command buffer into the allocated buffer
881  * and then draw like usual (this example uses fixed memory but you could
882  * use dynamically allocated memory).
883  *
884  * [... other defines ...]
885  * #define NK_ZERO_COMMAND_MEMORY
886  * #include "nuklear.h"
887  *
888  * struct nk_context ctx;
889  * void *last = calloc(1,64*1024);
890  * void *buf = calloc(1,64*1024);
891  * nk_init_fixed(&ctx, buf, 64*1024);
892  * while (1) {
893  * [...input...]
894  * [...ui...]
895  *
896  * void *cmds = nk_buffer_memory(&ctx.memory);
897  * if (memcmp(cmds, last, ctx.memory.allocated)) {
898  * memcpy(last,cmds,ctx.memory.allocated);
899  * const struct nk_command *cmd = 0;
900  * nk_foreach(cmd, &ctx) {
901  * switch (cmd->type) {
902  * case NK_COMMAND_LINE:
903  * your_draw_line_function(...)
904  * break;
905  * case NK_COMMAND_RECT
906  * your_draw_rect_function(...)
907  * break;
908  * case ...:
909  * [...]
910  * }
911  * }
912  * }
913  * nk_clear(&ctx);
914  * }
915  * nk_free(&ctx);
916  *
917  * Finally while using draw commands makes sense for higher abstracted platforms like
918  * X11 and Win32 or drawing libraries it is often desirable to use graphics
919  * hardware directly. Therefore it is possible to just define
920  * `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output.
921  * To access the vertex output you first have to convert all draw commands into
922  * vertexes by calling `nk_convert` which takes in your preferred vertex format.
923  * After successfully converting all draw commands just iterate over and execute all
924  * vertex draw commands:
925  *
926  * struct nk_convert_config cfg = {};
927  * static const struct nk_draw_vertex_layout_element vertex_layout[] = {
928  * {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)},
929  * {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)},
930  * {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)},
931  * {NK_VERTEX_LAYOUT_END}
932  * };
933  * cfg.shape_AA = NK_ANTI_ALIASING_ON;
934  * cfg.line_AA = NK_ANTI_ALIASING_ON;
935  * cfg.vertex_layout = vertex_layout;
936  * cfg.vertex_size = sizeof(struct your_vertex);
937  * cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex);
938  * cfg.circle_segment_count = 22;
939  * cfg.curve_segment_count = 22;
940  * cfg.arc_segment_count = 22;
941  * cfg.global_alpha = 1.0f;
942  * cfg.null = dev->null;
943  *
944  * struct nk_buffer cmds, verts, idx;
945  * nk_buffer_init_default(&cmds);
946  * nk_buffer_init_default(&verts);
947  * nk_buffer_init_default(&idx);
948  * nk_convert(&ctx, &cmds, &verts, &idx, &cfg);
949  * nk_draw_foreach(cmd, &ctx, &cmds) {
950  * if (!cmd->elem_count) continue;
951  * [...]
952  * }
953  * nk_buffer_free(&cms);
954  * nk_buffer_free(&verts);
955  * nk_buffer_free(&idx);
956  *
957  * Reference
958  * -------------------
959  * nk__begin - Returns the first draw command in the context draw command list to be drawn
960  * nk__next - Increments the draw command iterator to the next command inside the context draw command list
961  * nk_foreach - Iterates over each draw command inside the context draw command list
962  *
963  * nk_convert - Converts from the abstract draw commands list into a hardware accessible vertex format
964  * nk__draw_begin - Returns the first vertex command in the context vertex draw list to be executed
965  * nk__draw_next - Increments the vertex command iterator to the next command inside the context vertex command list
966  * nk__draw_end - Returns the end of the vertex draw list
967  * nk_draw_foreach - Iterates over each vertex draw command inside the vertex draw list
968  */
976 };
978  nk_handle texture; /* texture handle to a texture with a white pixel */
979  struct nk_vec2 uv; /* coordinates to a white pixel in the texture */
980 };
982  float global_alpha; /* global alpha value */
983  enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */
984  enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */
985  unsigned circle_segment_count; /* number of segments used for circles: default to 22 */
986  unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */
987  unsigned curve_segment_count; /* number of segments used for curves: default to 22 */
988  struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */
989  const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */
990  nk_size vertex_size; /* sizeof one vertex for vertex packing */
991  nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */
992 };
993 /* nk__begin - Returns a draw command list iterator to iterate all draw
994  * commands accumulated over one frame.
995  * Parameters:
996  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
997  * Return values:
998  * draw command pointer pointing to the first command inside the draw command list */
999 NK_API const struct nk_command* nk__begin(struct nk_context*);
1000 /* nk__next - Returns a draw command list iterator to iterate all draw
1001  * Parameters:
1002  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1003  * @cmd must point to an previously a draw command either returned by `nk__begin` or `nk__next`
1004  * Return values:
1005  * draw command pointer pointing to the next command inside the draw command list */
1006 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*);
1007 /* nk_foreach - Iterates over each draw command inside the context draw command list
1008  * Parameters:
1009  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1010  * @cmd pointer initialized to NULL */
1011 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c))
1012 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
1013 /* nk_convert - converts all internal draw command into vertex draw commands and fills
1014  * three buffers with vertexes, vertex draw commands and vertex indices. The vertex format
1015  * as well as some other configuration values have to be configured by filling out a
1016  * `nk_convert_config` struct.
1017  * Parameters:
1018  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1019  * @cmds must point to a previously initialized buffer to hold converted vertex draw commands
1020  * @vertices must point to a previously initialized buffer to hold all produced vertices
1021  * @elements must point to a previously initialized buffer to hold all produced vertex indices
1022  * @config must point to a filled out `nk_config` struct to configure the conversion process
1023  * Returns:
1024  * returns NK_CONVERT_SUCCESS on success and a enum nk_convert_result error values if not */
1025 NK_API nk_flags nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*);
1026 /* nk__draw_begin - Returns a draw vertex command buffer iterator to iterate each the vertex draw command buffer
1027  * Parameters:
1028  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1029  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1030  * Return values:
1031  * vertex draw command pointer pointing to the first command inside the vertex draw command buffer */
1032 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*);
1033 /* nk__draw_end - Returns the vertex draw command at the end of the vertex draw command buffer
1034  * Parameters:
1035  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1036  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1037  * Return values:
1038  * vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer */
1039 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*);
1040 /* nk__draw_next - Increments the vertex draw command buffer iterator
1041  * Parameters:
1042  * @cmd must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command
1043  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1044  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame
1045  * Return values:
1046  * vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer */
1047 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*);
1048 /* nk_draw_foreach - Iterates over each vertex draw command inside a vertex draw command buffer
1049  * Parameters:
1050  * @cmd nk_draw_command pointer set to NULL
1051  * @buf must point to an previously by `nk_convert` filled out vertex draw command buffer
1052  * @ctx must point to an previously initialized `nk_context` struct at the end of a frame */
1053 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx))
1054 #endif
1055 /* =============================================================================
1056  *
1057  * WINDOW
1058  *
1059  * =============================================================================
1060  * Windows are the main persistent state used inside nuklear and are life time
1061  * controlled by simply "retouching" (i.e. calling) each window each frame.
1062  * All widgets inside nuklear can only be added inside function pair `nk_begin_xxx`
1063  * and `nk_end`. Calling any widgets outside these two functions will result in an
1064  * assert in debug or no state change in release mode.
1065  *
1066  * Each window holds frame persistent state like position, size, flags, state tables,
1067  * and some garbage collected internal persistent widget state. Each window
1068  * is linked into a window stack list which determines the drawing and overlapping
1069  * order. The topmost window thereby is the currently active window.
1070  *
1071  * To change window position inside the stack occurs either automatically by
1072  * user input by being clicked on or programmatically by calling `nk_window_focus`.
1073  * Windows by default are visible unless explicitly being defined with flag
1074  * `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag
1075  * `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling
1076  * `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.
1077  *
1078  * Usage
1079  * -------------------
1080  * To create and keep a window you have to call one of the two `nk_begin_xxx`
1081  * functions to start window declarations and `nk_end` at the end. Furthermore it
1082  * is recommended to check the return value of `nk_begin_xxx` and only process
1083  * widgets inside the window if the value is not 0. Either way you have to call
1084  * `nk_end` at the end of window declarations. Furthermore, do not attempt to
1085  * nest `nk_begin_xxx` calls which will hopefully result in an assert or if not
1086  * in a segmentation fault.
1087  *
1088  * if (nk_begin_xxx(...) {
1089  * [... widgets ...]
1090  * }
1091  * nk_end(ctx);
1092  *
1093  * In the grand concept window and widget declarations need to occur after input
1094  * handling and before drawing to screen. Not doing so can result in higher
1095  * latency or at worst invalid behavior. Furthermore make sure that `nk_clear`
1096  * is called at the end of the frame. While nuklear's default platform backends
1097  * already call `nk_clear` for you if you write your own backend not calling
1098  * `nk_clear` can cause asserts or even worse undefined behavior.
1099  *
1100  * struct nk_context ctx;
1101  * nk_init_xxx(&ctx, ...);
1102  * while (1) {
1103  * Event evt;
1104  * nk_input_begin(&ctx);
1105  * while (GetEvent(&evt)) {
1106  * if (evt.type == MOUSE_MOVE)
1107  * nk_input_motion(&ctx, evt.motion.x, evt.motion.y);
1108  * else if (evt.type == [...]) {
1109  * nk_input_xxx(...);
1110  * }
1111  * }
1112  * nk_input_end(&ctx);
1113  *
1114  * if (nk_begin_xxx(...) {
1115  * [...]
1116  * }
1117  * nk_end(ctx);
1118  *
1119  * const struct nk_command *cmd = 0;
1120  * nk_foreach(cmd, &ctx) {
1121  * case NK_COMMAND_LINE:
1122  * your_draw_line_function(...)
1123  * break;
1124  * case NK_COMMAND_RECT
1125  * your_draw_rect_function(...)
1126  * break;
1127  * case ...:
1128  * [...]
1129  * }
1130  * nk_clear(&ctx);
1131  * }
1132  * nk_free(&ctx);
1133  *
1134  * Reference
1135  * -------------------
1136  * nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1137  * nk_begin_titled - extended window start with separated title and identifier to allow multiple windows with same name but not title
1138  * nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup
1139  *
1140  * nk_window_find - finds and returns the window with give name
1141  * nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window.
1142  * nk_window_get_position - returns the position of the currently processed window
1143  * nk_window_get_size - returns the size with width and height of the currently processed window
1144  * nk_window_get_width - returns the width of the currently processed window
1145  * nk_window_get_height - returns the height of the currently processed window
1146  * nk_window_get_panel - returns the underlying panel which contains all processing state of the current window
1147  * nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window
1148  * nk_window_get_content_region_min - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1149  * nk_window_get_content_region_max - returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window
1150  * nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window
1151  * nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets
1152  *
1153  * nk_window_has_focus - returns if the currently processed window is currently active
1154  * nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed
1155  * nk_window_is_closed - returns if the currently processed window was closed
1156  * nk_window_is_hidden - returns if the currently processed window was hidden
1157  * nk_window_is_active - same as nk_window_has_focus for some reason
1158  * nk_window_is_hovered - returns if the currently processed window is currently being hovered by mouse
1159  * nk_window_is_any_hovered - return if any window currently hovered
1160  * nk_item_is_any_active - returns if any window or widgets is currently hovered or active
1161  *
1162  * nk_window_set_bounds - updates position and size of the currently processed window
1163  * nk_window_set_position - updates position of the currently process window
1164  * nk_window_set_size - updates the size of the currently processed window
1165  * nk_window_set_focus - set the currently processed window as active window
1166  *
1167  * nk_window_close - closes the window with given window name which deletes the window at the end of the frame
1168  * nk_window_collapse - collapses the window with given window name
1169  * nk_window_collapse_if - collapses the window with given window name if the given condition was met
1170  * nk_window_show - hides a visible or reshows a hidden window
1171  * nk_window_show_if - hides/shows a window depending on condition
1172  */
1174  NK_WINDOW_BORDER = NK_FLAG(0), /* Draws a border around the window to visually separate window from the background */
1175  NK_WINDOW_MOVABLE = NK_FLAG(1), /* The movable flag indicates that a window can be moved by user input or by dragging the window header */
1176  NK_WINDOW_SCALABLE = NK_FLAG(2), /* The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window */
1177  NK_WINDOW_CLOSABLE = NK_FLAG(3), /* adds a closable icon into the header */
1178  NK_WINDOW_MINIMIZABLE = NK_FLAG(4), /* adds a minimize icon into the header */
1179  NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5), /* Removes the scrollbar from the window */
1180  NK_WINDOW_TITLE = NK_FLAG(6), /* Forces a header at the top at the window showing the title */
1181  NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7), /* Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame */
1182  NK_WINDOW_BACKGROUND = NK_FLAG(8), /* Always keep window in the background */
1183  NK_WINDOW_SCALE_LEFT = NK_FLAG(9), /* Puts window scaler in the left-ottom corner instead right-bottom*/
1184  NK_WINDOW_NO_INPUT = NK_FLAG(10) /* Prevents window of scaling, moving or getting focus */
1185 };
1186 /* nk_begin - starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed
1187  * Parameters:
1188  * @ctx must point to an previously initialized `nk_context` struct
1189  * @title window title and identifier. Needs to be persistent over frames to identify the window
1190  * @bounds initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
1191  * @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors
1192  * Return values:
1193  * returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise for example if minimized `*/
1194 NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags);
1195 /* nk_begin_titled - extended window start with separated title and identifier to allow multiple windows with same name but not title
1196  * Parameters:
1197  * @ctx must point to an previously initialized `nk_context` struct
1198  * @name window identifier. Needs to be persistent over frames to identify the window
1199  * @title window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set
1200  * @bounds initial position and window size. However if you do not define `NK_WINDOW_SCALABLE` or `NK_WINDOW_MOVABLE` you can set window position and size every frame
1201  * @flags window flags defined in `enum nk_panel_flags` with a number of different window behaviors
1202  * Return values:
1203  * returns 1 if the window can be filled up with widgets from this point until `nk_end or 0 otherwise `*/
1204 NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags);
1205 /* nk_end - needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup.
1206  * All widget calls after this functions will result in asserts or no state changes
1207  * Parameters:
1208  * @ctx must point to an previously initialized `nk_context` struct */
1209 NK_API void nk_end(struct nk_context *ctx);
1210 /* nk_window_find - finds and returns the window with give name
1211  * Parameters:
1212  * @ctx must point to an previously initialized `nk_context` struct
1213  * @name window identifier
1214  * Return values:
1215  * returns a `nk_window` struct pointing to the identified window or 0 if no window with given name was found */
1216 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name);
1217 /* nk_window_get_bounds - returns a rectangle with screen position and size of the currently processed window.
1218  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1219  * Parameters:
1220  * @ctx must point to an previously initialized `nk_context` struct
1221  * Return values:
1222  * returns a `nk_rect` struct with window upper left position and size */
1224 /* nk_window_get_position - returns the position of the currently processed window.
1225  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1226  * Parameters:
1227  * @ctx must point to an previously initialized `nk_context` struct
1228  * Return values:
1229  * returns a `nk_vec2` struct with window upper left position */
1231 /* nk_window_get_size - returns the size with width and height of the currently processed window.
1232  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1233  * Parameters:
1234  * @ctx must point to an previously initialized `nk_context` struct
1235  * Return values:
1236  * returns a `nk_vec2` struct with window size */
1238 /* nk_window_get_width - returns the width of the currently processed window.
1239  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1240  * Parameters:
1241  * @ctx must point to an previously initialized `nk_context` struct
1242  * Return values:
1243  * returns the window width */
1244 NK_API float nk_window_get_width(const struct nk_context*);
1245 /* nk_window_get_height - returns the height of the currently processed window.
1246  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1247  * Parameters:
1248  * @ctx must point to an previously initialized `nk_context` struct
1249  * Return values:
1250  * returns the window height */
1251 NK_API float nk_window_get_height(const struct nk_context*);
1252 /* nk_window_get_panel - returns the underlying panel which contains all processing state of the current window.
1253  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1254  * Parameters:
1255  * @ctx must point to an previously initialized `nk_context` struct
1256  * Return values:
1257  * returns a pointer to window internal `nk_panel` state. DO NOT keep this pointer around it is only valid until `nk_end` */
1259 /* nk_window_get_content_region - returns the position and size of the currently visible and non-clipped space inside the currently processed window.
1260  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1261  * Parameters:
1262  * @ctx must point to an previously initialized `nk_context` struct
1263  * Return values:
1264  * returns `nk_rect` struct with screen position and size (no scrollbar offset) of the visible space inside the current window */
1266 /* nk_window_get_content_region_min - returns the upper left position of the currently visible and non-clipped space inside the currently processed window.
1267  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1268  * Parameters:
1269  * @ctx must point to an previously initialized `nk_context` struct
1270  * Return values:
1271  * returns `nk_vec2` struct with upper left screen position (no scrollbar offset) of the visible space inside the current window */
1273 /* nk_window_get_content_region_max - returns the lower right screen position of the currently visible and non-clipped space inside the currently processed window.
1274  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1275  * Parameters:
1276  * @ctx must point to an previously initialized `nk_context` struct
1277  * Return values:
1278  * returns `nk_vec2` struct with lower right screen position (no scrollbar offset) of the visible space inside the current window */
1280 /* nk_window_get_content_region_size - returns the size of the currently visible and non-clipped space inside the currently processed window
1281  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1282  * Parameters:
1283  * @ctx must point to an previously initialized `nk_context` struct
1284  * Return values:
1285  * returns `nk_vec2` struct with size the visible space inside the current window */
1287 /* nk_window_get_canvas - returns the draw command buffer. Can be used to draw custom widgets
1288  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1289  * Parameters:
1290  * @ctx must point to an previously initialized `nk_context` struct
1291  * Return values:
1292  * returns a pointer to window internal `nk_command_buffer` struct used as drawing canvas. Can be used to do custom drawing */
1294 /* nk_window_has_focus - returns if the currently processed window is currently active
1295  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1296  * Parameters:
1297  * @ctx must point to an previously initialized `nk_context` struct
1298  * Return values:
1299  * returns 0 if current window is not active or 1 if it is */
1300 NK_API int nk_window_has_focus(const struct nk_context*);
1301 /* nk_window_is_collapsed - returns if the window with given name is currently minimized/collapsed
1302  * Parameters:
1303  * @ctx must point to an previously initialized `nk_context` struct
1304  * @name of window you want to check is collapsed
1305  * Return values:
1306  * returns 1 if current window is minimized and 0 if window not found or is not minimized */
1307 NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name);
1308 /* nk_window_is_closed - returns if the window with given name was closed by calling `nk_close`
1309  * Parameters:
1310  * @ctx must point to an previously initialized `nk_context` struct
1311  * @name of window you want to check is closed
1312  * Return values:
1313  * returns 1 if current window was closed or 0 window not found or not closed */
1314 NK_API int nk_window_is_closed(struct nk_context*, const char*);
1315 /* nk_window_is_hidden - returns if the window with given name is hidden
1316  * Parameters:
1317  * @ctx must point to an previously initialized `nk_context` struct
1318  * @name of window you want to check is hidden
1319  * Return values:
1320  * returns 1 if current window is hidden or 0 window not found or visible */
1321 NK_API int nk_window_is_hidden(struct nk_context*, const char*);
1322 /* nk_window_is_active - same as nk_window_has_focus for some reason
1323  * Parameters:
1324  * @ctx must point to an previously initialized `nk_context` struct
1325  * @name of window you want to check is hidden
1326  * Return values:
1327  * returns 1 if current window is active or 0 window not found or not active */
1328 NK_API int nk_window_is_active(struct nk_context*, const char*);
1329 /* nk_window_is_hovered - return if the current window is being hovered
1330  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1331  * Parameters:
1332  * @ctx must point to an previously initialized `nk_context` struct
1333  * Return values:
1334  * returns 1 if current window is hovered or 0 otherwise */
1336 /* nk_window_is_any_hovered - returns if the any window is being hovered
1337  * Parameters:
1338  * @ctx must point to an previously initialized `nk_context` struct
1339  * Return values:
1340  * returns 1 if any window is hovered or 0 otherwise */
1342 /* nk_item_is_any_active - returns if the any window is being hovered or any widget is currently active.
1343  * Can be used to decide if input should be processed by UI or your specific input handling.
1344  * Example could be UI and 3D camera to move inside a 3D space.
1345  * Parameters:
1346  * @ctx must point to an previously initialized `nk_context` struct
1347  * Return values:
1348  * returns 1 if any window is hovered or any item is active or 0 otherwise */
1350 /* nk_window_set_bounds - updates position and size of the currently processed window
1351  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1352  * Parameters:
1353  * @ctx must point to an previously initialized `nk_context` struct
1354  * @name of the window to modify both position and size
1355  * @bounds points to a `nk_rect` struct with the new position and size of currently active window */
1356 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds);
1357 /* nk_window_set_position - updates position of the currently processed window
1358  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1359  * Parameters:
1360  * @ctx must point to an previously initialized `nk_context` struct
1361  * @name of the window to modify position of
1362  * @pos points to a `nk_vec2` struct with the new position of currently active window */
1363 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos);
1364 /* nk_window_set_size - updates size of the currently processed window
1365  * IMPORTANT: only call this function between calls `nk_begin_xxx` and `nk_end`
1366  * Parameters:
1367  * @ctx must point to an previously initialized `nk_context` struct
1368  * @name of the window to modify size of
1369  * @size points to a `nk_vec2` struct with the new size of currently active window */
1370 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2);
1371 /* nk_window_set_focus - sets the window with given name as active
1372  * Parameters:
1373  * @ctx must point to an previously initialized `nk_context` struct
1374  * @name of the window to be set active */
1375 NK_API void nk_window_set_focus(struct nk_context*, const char *name);
1376 /* nk_window_close - closed a window and marks it for being freed at the end of the frame
1377  * Parameters:
1378  * @ctx must point to an previously initialized `nk_context` struct
1379  * @name of the window to be closed */
1380 NK_API void nk_window_close(struct nk_context *ctx, const char *name);
1381 /* nk_window_collapse - updates collapse state of a window with given name
1382  * Parameters:
1383  * @ctx must point to an previously initialized `nk_context` struct
1384  * @name of the window to be either collapse or maximize */
1385 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state);
1386 /* nk_window_collapse - updates collapse state of a window with given name if given condition is met
1387  * Parameters:
1388  * @ctx must point to an previously initialized `nk_context` struct
1389  * @name of the window to be either collapse or maximize
1390  * @state the window should be put into
1391  * @condition that has to be true to actually commit the collapse state change */
1392 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond);
1393 /* nk_window_show - updates visibility state of a window with given name
1394  * Parameters:
1395  * @ctx must point to an previously initialized `nk_context` struct
1396  * @name of the window to be either collapse or maximize
1397  * @state with either visible or hidden to modify the window with */
1398 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states);
1399 /* nk_window_show_if - updates visibility state of a window with given name if a given condition is met
1400  * Parameters:
1401  * @ctx must point to an previously initialized `nk_context` struct
1402  * @name of the window to be either collapse or maximize
1403  * @state with either visible or hidden to modify the window with
1404  * @condition that has to be true to actually commit the visible state change */
1405 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond);
1406 /* =============================================================================
1407  *
1408  * LAYOUT
1409  *
1410  * ============================================================================= */
1411 /* Layouting in general describes placing widget inside a window with position and size.
1412  * While in this particular implementation there are five different APIs for layouting
1413  * each with different trade offs between control and ease of use.
1414  *
1415  * All layouting methods in this library are based around the concept of a row.
1416  * A row has a height the window content grows by and a number of columns and each
1417  * layouting method specifies how each widget is placed inside the row.
1418  * After a row has been allocated by calling a layouting functions and then
1419  * filled with widgets will advance an internal pointer over the allocated row.
1420  *
1421  * To actually define a layout you just call the appropriate layouting function
1422  * and each subsequent widget call will place the widget as specified. Important
1423  * here is that if you define more widgets then columns defined inside the layout
1424  * functions it will allocate the next row without you having to make another layouting
1425  * call.
1426  *
1427  * Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API
1428  * is that you have to define the row height for each. However the row height
1429  * often depends on the height of the font.
1430  *
1431  * To fix that internally nuklear uses a minimum row height that is set to the
1432  * height plus padding of currently active font and overwrites the row height
1433  * value if zero.
1434  *
1435  * If you manually want to change the minimum row height then
1436  * use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to
1437  * reset it back to be derived from font height.
1438  *
1439  * Also if you change the font in nuklear it will automatically change the minimum
1440  * row height for you and. This means if you change the font but still want
1441  * a minimum row height smaller than the font you have to repush your value.
1442  *
1443  * For actually more advanced UI I would even recommend using the `nk_layout_space_xxx`
1444  * layouting method in combination with a cassowary constraint solver (there are
1445  * some versions on github with permissive license model) to take over all control over widget
1446  * layouting yourself. However for quick and dirty layouting using all the other layouting
1447  * functions should be fine.
1448  *
1449  * Usage
1450  * -------------------
1451  * 1.) nk_layout_row_dynamic
1452  * The easiest layouting function is `nk_layout_row_dynamic`. It provides each
1453  * widgets with same horizontal space inside the row and dynamically grows
1454  * if the owning window grows in width. So the number of columns dictates
1455  * the size of each widget dynamically by formula:
1456  *
1457  * widget_width = (window_width - padding - spacing) * (1/colum_count)
1458  *
1459  * Just like all other layouting APIs if you define more widget than columns this
1460  * library will allocate a new row and keep all layouting parameters previously
1461  * defined.
1462  *
1463  * if (nk_begin_xxx(...) {
1464  * // first row with height: 30 composed of two widgets
1465  * nk_layout_row_dynamic(&ctx, 30, 2);
1466  * nk_widget(...);
1467  * nk_widget(...);
1468  *
1469  * // second row with same parameter as defined above
1470  * nk_widget(...);
1471  * nk_widget(...);
1472  *
1473  * // third row uses 0 for height which will use auto layouting
1474  * nk_layout_row_dynamic(&ctx, 0, 2);
1475  * nk_widget(...);
1476  * nk_widget(...);
1477  * }
1478  * nk_end(...);
1479  *
1480  * 2.) nk_layout_row_static
1481  * Another easy layouting function is `nk_layout_row_static`. It provides each
1482  * widget with same horizontal pixel width inside the row and does not grow
1483  * if the owning window scales smaller or bigger.
1484  *
1485  * if (nk_begin_xxx(...) {
1486  * // first row with height: 30 composed of two widgets with width: 80
1487  * nk_layout_row_static(&ctx, 30, 80, 2);
1488  * nk_widget(...);
1489  * nk_widget(...);
1490  *
1491  * // second row with same parameter as defined above
1492  * nk_widget(...);
1493  * nk_widget(...);
1494  *
1495  * // third row uses 0 for height which will use auto layouting
1496  * nk_layout_row_static(&ctx, 0, 80, 2);
1497  * nk_widget(...);
1498  * nk_widget(...);
1499  * }
1500  * nk_end(...);
1501  *
1502  * 3.) nk_layout_row_xxx
1503  * A little bit more advanced layouting API are functions `nk_layout_row_begin`,
1504  * `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly
1505  * specify each column pixel or window ratio in a row. It supports either
1506  * directly setting per column pixel width or widget window ratio but not
1507  * both. Furthermore it is a immediate mode API so each value is directly
1508  * pushed before calling a widget. Therefore the layout is not automatically
1509  * repeating like the last two layouting functions.
1510  *
1511  * if (nk_begin_xxx(...) {
1512  * // first row with height: 25 composed of two widgets with width 60 and 40
1513  * nk_layout_row_begin(ctx, NK_STATIC, 25, 2);
1514  * nk_layout_row_push(ctx, 60);
1515  * nk_widget(...);
1516  * nk_layout_row_push(ctx, 40);
1517  * nk_widget(...);
1518  * nk_layout_row_end(ctx);
1519  *
1520  * // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75
1521  * nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2);
1522  * nk_layout_row_push(ctx, 0.25f);
1523  * nk_widget(...);
1524  * nk_layout_row_push(ctx, 0.75f);
1525  * nk_widget(...);
1526  * nk_layout_row_end(ctx);
1527  *
1528  * // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75
1529  * nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2);
1530  * nk_layout_row_push(ctx, 0.25f);
1531  * nk_widget(...);
1532  * nk_layout_row_push(ctx, 0.75f);
1533  * nk_widget(...);
1534  * nk_layout_row_end(ctx);
1535  * }
1536  * nk_end(...);
1537  *
1538  * 4.) nk_layout_row
1539  * The array counterpart to API nk_layout_row_xxx is the single nk_layout_row
1540  * functions. Instead of pushing either pixel or window ratio for every widget
1541  * it allows to define it by array. The trade of for less control is that
1542  * `nk_layout_row` is automatically repeating. Otherwise the behavior is the
1543  * same.
1544  *
1545  * if (nk_begin_xxx(...) {
1546  * // two rows with height: 30 composed of two widgets with width 60 and 40
1547  * const float size[] = {60,40};
1548  * nk_layout_row(ctx, NK_STATIC, 30, 2, ratio);
1549  * nk_widget(...);
1550  * nk_widget(...);
1551  * nk_widget(...);
1552  * nk_widget(...);
1553  *
1554  * // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75
1555  * const float ratio[] = {0.25, 0.75};
1556  * nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
1557  * nk_widget(...);
1558  * nk_widget(...);
1559  * nk_widget(...);
1560  * nk_widget(...);
1561  *
1562  * // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75
1563  * const float ratio[] = {0.25, 0.75};
1564  * nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio);
1565  * nk_widget(...);
1566  * nk_widget(...);
1567  * nk_widget(...);
1568  * nk_widget(...);
1569  * }
1570  * nk_end(...);
1571  *
1572  * 5.) nk_layout_row_template_xxx
1573  * The most complex and second most flexible API is a simplified flexbox version without
1574  * line wrapping and weights for dynamic widgets. It is an immediate mode API but
1575  * unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called
1576  * before calling the templated widgets.
1577  * The row template layout has three different per widget size specifier. The first
1578  * one is the static widget size specifier with fixed widget pixel width. They do
1579  * not grow if the row grows and will always stay the same. The second size
1580  * specifier is nk_layout_row_template_push_variable which defines a
1581  * minimum widget size but it also can grow if more space is available not taken
1582  * by other widgets. Finally there are dynamic widgets which are completely flexible
1583  * and unlike variable widgets can even shrink to zero if not enough space
1584  * is provided.
1585  *
1586  * if (nk_begin_xxx(...) {
1587  * // two rows with height: 30 composed of three widgets
1588  * nk_layout_row_template_begin(ctx, 30);
1589  * nk_layout_row_template_push_dynamic(ctx);
1590  * nk_layout_row_template_push_variable(ctx, 80);
1591  * nk_layout_row_template_push_static(ctx, 80);
1592  * nk_layout_row_template_end(ctx);
1593  *
1594  * nk_widget(...); // dynamic widget can go to zero if not enough space
1595  * nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space
1596  * nk_widget(...); // static widget with fixed 80 pixel width
1597  *
1598  * // second row same layout
1599  * nk_widget(...);
1600  * nk_widget(...);
1601  * nk_widget(...);
1602  * }
1603  * nk_end(...);
1604  *
1605  * 6.) nk_layout_space_xxx
1606  * Finally the most flexible API directly allows you to place widgets inside the
1607  * window. The space layout API is an immediate mode API which does not support
1608  * row auto repeat and directly sets position and size of a widget. Position
1609  * and size hereby can be either specified as ratio of allocated space or
1610  * allocated space local position and pixel size. Since this API is quite
1611  * powerful there are a number of utility functions to get the available space
1612  * and convert between local allocated space and screen space.
1613  *
1614  * if (nk_begin_xxx(...) {
1615  * // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
1616  * nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX);
1617  * nk_layout_space_push(ctx, nk_rect(0,0,150,200));
1618  * nk_widget(...);
1619  * nk_layout_space_push(ctx, nk_rect(200,200,100,200));
1620  * nk_widget(...);
1621  * nk_layout_space_end(ctx);
1622  *
1623  * // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered)
1624  * nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX);
1625  * nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1));
1626  * nk_widget(...);
1627  * nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1));
1628  * nk_widget(...);
1629  * }
1630  * nk_end(...);
1631  *
1632  * Reference
1633  * -------------------
1634  * nk_layout_set_min_row_height - set the currently used minimum row height to a specified value
1635  * nk_layout_reset_min_row_height - resets the currently used minimum row height to font height
1636  *
1637  * nk_layout_widget_bounds - calculates current width a static layout row can fit inside a window
1638  * nk_layout_ratio_from_pixel - utility functions to calculate window ratio from pixel size
1639  *
1640  * nk_layout_row_dynamic - current layout is divided into n same sized growing columns
1641  * nk_layout_row_static - current layout is divided into n same fixed sized columns
1642  * nk_layout_row_begin - starts a new row with given height and number of columns
1643  * nk_layout_row_push - pushes another column with given size or window ratio
1644  * nk_layout_row_end - finished previously started row
1645  * nk_layout_row - specifies row columns in array as either window ratio or size
1646  *
1647  * nk_layout_row_template_begin - begins the row template declaration
1648  * nk_layout_row_template_push_dynamic - adds a dynamic column that dynamically grows and can go to zero if not enough space
1649  * nk_layout_row_template_push_variable - adds a variable column that dynamically grows but does not shrink below specified pixel width
1650  * nk_layout_row_template_push_static - adds a static column that does not grow and will always have the same size
1651  * nk_layout_row_template_end - marks the end of the row template
1652  *
1653  * nk_layout_space_begin - begins a new layouting space that allows to specify each widgets position and size
1654  * nk_layout_space_push - pushes position and size of the next widget in own coordinate space either as pixel or ratio
1655  * nk_layout_space_end - marks the end of the layouting space
1656  *
1657  * nk_layout_space_bounds - callable after nk_layout_space_begin and returns total space allocated
1658  * nk_layout_space_to_screen - converts vector from nk_layout_space coordinate space into screen space
1659  * nk_layout_space_to_local - converts vector from screen space into nk_layout_space coordinates
1660  * nk_layout_space_rect_to_screen - converts rectangle from nk_layout_space coordinate space into screen space
1661  * nk_layout_space_rect_to_local - converts rectangle from screen space into nk_layout_space coordinates
1662  */
1663 /* nk_layout_set_min_row_height - sets the currently used minimum row height.
1664  * IMPORTANT: The passed height needs to include both your preferred row height
1665  * as well as padding. No internal padding is added.
1666  * Parameters:
1667  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1668  * @height new minimum row height to be used for auto generating the row height */
1670 /* nk_layout_reset_min_row_height - Reset the currently used minimum row height
1671  * back to font height + text padding + additional padding (style_window.min_row_height_padding)
1672  * Parameters:
1673  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` */
1675 /* nk_layout_widget_bounds - returns the width of the next row allocate by one of the layouting functions
1676  * Parameters:
1677  * @ctx must point to an previously initialized `nk_context` */
1679 /* nk_layout_ratio_from_pixel - utility functions to calculate window ratio from pixel size
1680  * Parameters:
1681  * @ctx must point to an previously initialized `nk_context`
1682  * @pixel_width to convert to window ratio */
1683 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width);
1684 /* nk_layout_row_dynamic - Sets current row layout to share horizontal space
1685  * between @cols number of widgets evenly. Once called all subsequent widget
1686  * calls greater than @cols will allocate a new row with same layout.
1687  * Parameters:
1688  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1689  * @row_height holds height of each widget in row or zero for auto layouting
1690  * @cols number of widget inside row */
1691 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols);
1692 /* nk_layout_row_static - Sets current row layout to fill @cols number of widgets
1693  * in row with same @item_width horizontal size. Once called all subsequent widget
1694  * calls greater than @cols will allocate a new row with same layout.
1695  * Parameters:
1696  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1697  * @height holds row height to allocate from panel for widget height
1698  * @item_width holds width of each widget in row
1699  * @cols number of widget inside row */
1700 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols);
1701 /* nk_layout_row_begin - Starts a new dynamic or fixed row with given height and columns.
1702  * Parameters:
1703  * @ctx must point to an previously initialized `nk_context` struct after call `nk_begin_xxx`
1704  * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1705  * @row_height holds height of each widget in row or zero for auto layouting
1706  * @cols number of widget inside row */
1707 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols);
1708 /* nk_layout_row_push - Specifies either window ratio or width of a single column
1709  * Parameters:
1710  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin`
1711  * @value either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call */
1712 NK_API void nk_layout_row_push(struct nk_context*, float value);
1713 /* nk_layout_row_end - finished previously started row
1714  * Parameters:
1715  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_begin` */
1716 NK_API void nk_layout_row_end(struct nk_context*);
1717 /* nk_layout_row - specifies row columns in array as either window ratio or size
1718  * Parameters:
1719  * @ctx must point to an previously initialized `nk_context`
1720  * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1721  * @row_height holds height of each widget in row or zero for auto layouting
1722  * @cols number of widget inside row */
1723 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio);
1724 /* nk_layout_row_template_begin - Begins the row template declaration
1725  * Parameters:
1726  * @ctx must point to an previously initialized `nk_context` struct
1727  * @row_height holds height of each widget in row or zero for auto layouting */
1728 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height);
1729 /* nk_layout_row_template_push_dynamic - adds a dynamic column that dynamically grows and can go to zero if not enough space
1730  * Parameters:
1731  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin` */
1733 /* nk_layout_row_template_push_variable - adds a variable column that dynamically grows but does not shrink below specified pixel width
1734  * Parameters:
1735  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin`
1736  * @min_width holds the minimum pixel width the next column must be */
1737 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width);
1738 /* nk_layout_row_template_push_static - adds a static column that does not grow and will always have the same size
1739  * Parameters:
1740  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin`
1741  * @width holds the absolute pixel width value the next column must be */
1743 /* nk_layout_row_template_end - marks the end of the row template
1744  * Parameters:
1745  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_row_template_begin` */
1747 /* nk_layout_space_begin - begins a new layouting space that allows to specify each widgets position and size.
1748  * Parameters:
1749  * @ctx must point to an previously initialized `nk_context` struct
1750  * @fmt either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns
1751  * @row_height holds height of each widget in row or zero for auto layouting
1752  * @widget_count number of widgets inside row */
1753 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count);
1754 /* nk_layout_space_push - pushes position and size of the next widget in own coordinate space either as pixel or ratio
1755  * Parameters:
1756  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1757  * @bounds position and size in laoyut space local coordinates */
1758 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect);
1759 /* nk_layout_space_end - marks the end of the layout space
1760  * Parameters:
1761  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` */
1762 NK_API void nk_layout_space_end(struct nk_context*);
1763 /* nk_layout_space_bounds - returns total space allocated for `nk_layout_space`
1764  * Parameters:
1765  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` */
1767 /* nk_layout_space_to_screen - converts vector from nk_layout_space coordinate space into screen space
1768  * Parameters:
1769  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1770  * @vec position to convert from layout space into screen coordinate space */
1772 /* nk_layout_space_to_screen - converts vector from layout space into screen space
1773  * Parameters:
1774  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1775  * @vec position to convert from screen space into layout coordinate space */
1776 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2);
1777 /* nk_layout_space_rect_to_screen - converts rectangle from screen space into layout space
1778  * Parameters:
1779  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1780  * @bounds rectangle to convert from layout space into screen space */
1782 /* nk_layout_space_rect_to_local - converts rectangle from layout space into screen space
1783  * Parameters:
1784  * @ctx must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin`
1785  * @bounds rectangle to convert from screen space into layout space */
1787 /* =============================================================================
1788  *
1789  * GROUP
1790  *
1791  * ============================================================================= */
1792 NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags);
1793 NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char*, nk_flags);
1794 NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll*, const char *title, nk_flags);
1796 NK_API void nk_group_end(struct nk_context*);
1797 /* =============================================================================
1798  *
1799  * LIST VIEW
1800  *
1801  * ============================================================================= */
1803 /* public: */
1804  int begin, end, count;
1805 /* private: */
1807  struct nk_context *ctx;
1810 };
1811 NK_API int nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count);
1812 NK_API void nk_list_view_end(struct nk_list_view*);
1813 /* =============================================================================
1814  *
1815  * TREE
1816  *
1817  * ============================================================================= */
1818 #define nk_tree_push(ctx, type, title, state) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
1819 #define nk_tree_push_id(ctx, type, title, state, id) nk_tree_push_hashed(ctx, type, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
1820 NK_API int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
1821 #define nk_tree_image_push(ctx, type, img, title, state) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__)
1822 #define nk_tree_image_push_id(ctx, type, img, title, state, id) nk_tree_image_push_hashed(ctx, type, img, title, state, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id)
1823 NK_API int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed);
1824 NK_API void nk_tree_pop(struct nk_context*);
1825 NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state);
1826 NK_API int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state);
1827 NK_API void nk_tree_state_pop(struct nk_context*);
1828 /* =============================================================================
1829  *
1830  * WIDGET
1831  *
1832  * ============================================================================= */
1834  NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */
1835  NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */
1836  NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */
1837 };
1840  NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */
1841  NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */
1842  NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */
1843  NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */
1844  NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */
1847 };
1848 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*);
1850 NK_API struct nk_rect nk_widget_bounds(struct nk_context*);
1852 NK_API struct nk_vec2 nk_widget_size(struct nk_context*);
1853 NK_API float nk_widget_width(struct nk_context*);
1854 NK_API float nk_widget_height(struct nk_context*);
1858 NK_API void nk_spacing(struct nk_context*, int cols);
1859 /* =============================================================================
1860  *
1861  * TEXT
1862  *
1863  * ============================================================================= */
1871 };
1876 };
1877 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags);
1878 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color);
1879 NK_API void nk_text_wrap(struct nk_context*, const char*, int);
1880 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color);
1881 NK_API void nk_label(struct nk_context*, const char*, nk_flags align);
1882 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color);
1883 NK_API void nk_label_wrap(struct nk_context*, const char*);
1884 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color);
1885 NK_API void nk_image(struct nk_context*, struct nk_image);
1886 #ifdef NK_INCLUDE_STANDARD_VARARGS
1887 NK_API void nk_labelf(struct nk_context*, nk_flags, const char*, ...);
1888 NK_API void nk_labelf_colored(struct nk_context*, nk_flags align, struct nk_color, const char*,...);
1889 NK_API void nk_labelf_wrap(struct nk_context*, const char*,...);
1890 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, const char*,...);
1891 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int);
1892 NK_API void nk_value_int(struct nk_context*, const char *prefix, int);
1893 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int);
1894 NK_API void nk_value_float(struct nk_context*, const char *prefix, float);
1895 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color);
1896 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color);
1897 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color);
1898 #endif
1899 /* =============================================================================
1900  *
1901  * BUTTON
1902  *
1903  * ============================================================================= */
1904 NK_API int nk_button_text(struct nk_context*, const char *title, int len);
1905 NK_API int nk_button_label(struct nk_context*, const char *title);
1906 NK_API int nk_button_color(struct nk_context*, struct nk_color);
1908 NK_API int nk_button_image(struct nk_context*, struct nk_image img);
1910 NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1911 NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment);
1912 NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment);
1913 NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len);
1914 NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title);
1915 NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type);
1916 NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img);
1917 NK_API int nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment);
1918 NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align);
1919 NK_API int nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment);
1920 NK_API int nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment);
1924 /* =============================================================================
1925  *
1926  * CHECKBOX
1927  *
1928  * ============================================================================= */
1929 NK_API int nk_check_label(struct nk_context*, const char*, int active);
1930 NK_API int nk_check_text(struct nk_context*, const char*, int,int active);
1931 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value);
1932 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value);
1933 NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active);
1934 NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active);
1935 NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value);
1936 NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value);
1937 /* =============================================================================
1938  *
1939  * RADIO BUTTON
1940  *
1941  * ============================================================================= */
1942 NK_API int nk_radio_label(struct nk_context*, const char*, int *active);
1943 NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active);
1944 NK_API int nk_option_label(struct nk_context*, const char*, int active);
1945 NK_API int nk_option_text(struct nk_context*, const char*, int, int active);
1946 /* =============================================================================
1947  *
1948  * SELECTABLE
1949  *
1950  * ============================================================================= */
1951 NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value);
1952 NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value);
1953 NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value);
1954 NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value);
1955 NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value);
1956 NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value);
1957 NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value);
1958 NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value);
1959 /* =============================================================================
1960  *
1961  * SLIDER
1962  *
1963  * ============================================================================= */
1964 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step);
1965 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step);
1966 NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step);
1967 NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step);
1968 /* =============================================================================
1969  *
1970  * PROGRESSBAR
1971  *
1972  * ============================================================================= */
1973 NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable);
1974 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable);
1975 
1976 /* =============================================================================
1977  *
1978  * COLOR PICKER
1979  *
1980  * ============================================================================= */
1981 NK_API struct nk_color nk_color_picker(struct nk_context*, struct nk_color, enum nk_color_format);
1982 NK_API int nk_color_pick(struct nk_context*, struct nk_color*, enum nk_color_format);
1983 /* =============================================================================
1984  *
1985  * PROPERTIES
1986  *
1987  * ============================================================================= */
1988 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel);
1989 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel);
1990 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel);
1991 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel);
1992 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel);
1993 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel);
1994 /* =============================================================================
1995  *
1996  * TEXT EDIT
1997  *
1998  * ============================================================================= */
2013 };
2019 };
2021  NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */
2022  NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */
2023  NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */
2024  NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */
2025  NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */
2026 };
2027 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter);
2031 NK_API void nk_edit_unfocus(struct nk_context*);
2032 /* =============================================================================
2033  *
2034  * CHART
2035  *
2036  * ============================================================================= */
2037 NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max);
2038 NK_API int nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max);
2039 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value);
2040 NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value);
2041 NK_API nk_flags nk_chart_push(struct nk_context*, float);
2042 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int);
2043 NK_API void nk_chart_end(struct nk_context*);
2044 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset);
2045 NK_API void nk_plot_function(struct nk_context*, enum nk_chart_type, void *userdata, float(*value_getter)(void* user, int index), int count, int offset);
2046 /* =============================================================================
2047  *
2048  * POPUP
2049  *
2050  * ============================================================================= */
2051 NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds);
2052 NK_API void nk_popup_close(struct nk_context*);
2053 NK_API void nk_popup_end(struct nk_context*);
2054 /* =============================================================================
2055  *
2056  * COMBOBOX
2057  *
2058  * ============================================================================= */
2059 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size);
2060 NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size);
2061 NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size);
2062 NK_API int nk_combo_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void *userdata, int selected, int count, int item_height, struct nk_vec2 size);
2063 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size);
2064 NK_API void nk_combobox_string(struct nk_context*, const char *items_separated_by_zeros, int *selected, int count, int item_height, struct nk_vec2 size);
2065 NK_API void nk_combobox_separator(struct nk_context*, const char *items_separated_by_separator, int separator,int *selected, int count, int item_height, struct nk_vec2 size);
2066 NK_API void nk_combobox_callback(struct nk_context*, void(*item_getter)(void*, int, const char**), void*, int *selected, int count, int item_height, struct nk_vec2 size);
2067 /* =============================================================================
2068  *
2069  * ABSTRACT COMBOBOX
2070  *
2071  * ============================================================================= */
2072 NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size);
2073 NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size);
2074 NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size);
2076 NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size);
2077 NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size);
2078 NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size);
2079 NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size);
2080 NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size);
2081 NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment);
2082 NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment);
2083 NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2084 NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment);
2085 NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2086 NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2087 NK_API void nk_combo_close(struct nk_context*);
2088 NK_API void nk_combo_end(struct nk_context*);
2089 /* =============================================================================
2090  *
2091  * CONTEXTUAL
2092  *
2093  * ============================================================================= */
2094 NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds);
2095 NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align);
2096 NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align);
2097 NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2098 NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
2099 NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2100 NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2101 NK_API void nk_contextual_close(struct nk_context*);
2102 NK_API void nk_contextual_end(struct nk_context*);
2103 /* =============================================================================
2104  *
2105  * TOOLTIP
2106  *
2107  * ============================================================================= */
2108 NK_API void nk_tooltip(struct nk_context*, const char*);
2109 NK_API int nk_tooltip_begin(struct nk_context*, float width);
2110 NK_API void nk_tooltip_end(struct nk_context*);
2111 /* =============================================================================
2112  *
2113  * MENU
2114  *
2115  * ============================================================================= */
2116 NK_API void nk_menubar_begin(struct nk_context*);
2117 NK_API void nk_menubar_end(struct nk_context*);
2118 NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size);
2119 NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size);
2120 NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size);
2121 NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size);
2122 NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size);
2123 NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size);
2124 NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
2125 NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size);
2126 NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align);
2127 NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment);
2128 NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment);
2129 NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment);
2130 NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment);
2131 NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment);
2132 NK_API void nk_menu_close(struct nk_context*);
2133 NK_API void nk_menu_end(struct nk_context*);
2134 /* =============================================================================
2135  *
2136  * STYLE
2137  *
2138  * ============================================================================= */
2169 };
2179 };
2180 NK_API void nk_style_default(struct nk_context*);
2181 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*);
2182 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*);
2183 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*);
2185 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*);
2187 NK_API void nk_style_show_cursor(struct nk_context*);
2188 NK_API void nk_style_hide_cursor(struct nk_context*);
2189 
2190 NK_API int nk_style_push_font(struct nk_context*, const struct nk_user_font*);
2191 NK_API int nk_style_push_float(struct nk_context*, float*, float);
2192 NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2);
2195 NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color);
2196 
2197 NK_API int nk_style_pop_font(struct nk_context*);
2198 NK_API int nk_style_pop_float(struct nk_context*);
2199 NK_API int nk_style_pop_vec2(struct nk_context*);
2201 NK_API int nk_style_pop_flags(struct nk_context*);
2202 NK_API int nk_style_pop_color(struct nk_context*);
2203 /* =============================================================================
2204  *
2205  * COLOR
2206  *
2207  * ============================================================================= */
2208 NK_API struct nk_color nk_rgb(int r, int g, int b);
2209 NK_API struct nk_color nk_rgb_iv(const int *rgb);
2210 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb);
2211 NK_API struct nk_color nk_rgb_f(float r, float g, float b);
2212 NK_API struct nk_color nk_rgb_fv(const float *rgb);
2213 NK_API struct nk_color nk_rgb_hex(const char *rgb);
2214 
2215 NK_API struct nk_color nk_rgba(int r, int g, int b, int a);
2217 NK_API struct nk_color nk_rgba_iv(const int *rgba);
2218 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba);
2219 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a);
2220 NK_API struct nk_color nk_rgba_fv(const float *rgba);
2221 NK_API struct nk_color nk_rgba_hex(const char *rgb);
2222 
2223 NK_API struct nk_color nk_hsv(int h, int s, int v);
2224 NK_API struct nk_color nk_hsv_iv(const int *hsv);
2225 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv);
2226 NK_API struct nk_color nk_hsv_f(float h, float s, float v);
2227 NK_API struct nk_color nk_hsv_fv(const float *hsv);
2228 
2229 NK_API struct nk_color nk_hsva(int h, int s, int v, int a);
2230 NK_API struct nk_color nk_hsva_iv(const int *hsva);
2231 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva);
2232 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a);
2233 NK_API struct nk_color nk_hsva_fv(const float *hsva);
2234 
2235 /* color (conversion nuklear --> user) */
2236 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color);
2237 NK_API void nk_color_fv(float *rgba_out, struct nk_color);
2238 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color);
2239 NK_API void nk_color_dv(double *rgba_out, struct nk_color);
2240 
2242 NK_API void nk_color_hex_rgba(char *output, struct nk_color);
2243 NK_API void nk_color_hex_rgb(char *output, struct nk_color);
2244 
2245 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color);
2246 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color);
2247 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color);
2248 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color);
2249 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color);
2250 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color);
2251 
2252 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color);
2254 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color);
2255 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color);
2256 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color);
2257 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color);
2258 /* =============================================================================
2259  *
2260  * IMAGE
2261  *
2262  * ============================================================================= */
2266 NK_API struct nk_image nk_image_ptr(void*);
2267 NK_API struct nk_image nk_image_id(int);
2268 NK_API int nk_image_is_subimage(const struct nk_image* img);
2269 NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region);
2270 NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region);
2271 NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region);
2272 /* =============================================================================
2273  *
2274  * MATH
2275  *
2276  * ============================================================================= */
2277 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed);
2278 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading);
2279 
2280 NK_API struct nk_vec2 nk_vec2(float x, float y);
2281 NK_API struct nk_vec2 nk_vec2i(int x, int y);
2282 NK_API struct nk_vec2 nk_vec2v(const float *xy);
2283 NK_API struct nk_vec2 nk_vec2iv(const int *xy);
2284 
2286 NK_API struct nk_rect nk_rect(float x, float y, float w, float h);
2287 NK_API struct nk_rect nk_recti(int x, int y, int w, int h);
2288 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size);
2289 NK_API struct nk_rect nk_rectv(const float *xywh);
2290 NK_API struct nk_rect nk_rectiv(const int *xywh);
2291 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect);
2292 NK_API struct nk_vec2 nk_rect_size(struct nk_rect);
2293 /* =============================================================================
2294  *
2295  * STRING
2296  *
2297  * ============================================================================= */
2298 NK_API int nk_strlen(const char *str);
2299 NK_API int nk_stricmp(const char *s1, const char *s2);
2300 NK_API int nk_stricmpn(const char *s1, const char *s2, int n);
2301 NK_API int nk_strtoi(const char *str, const char **endptr);
2302 NK_API float nk_strtof(const char *str, const char **endptr);
2303 NK_API double nk_strtod(const char *str, const char **endptr);
2304 NK_API int nk_strfilter(const char *text, const char *regexp);
2305 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score);
2306 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score);
2307 /* =============================================================================
2308  *
2309  * UTF-8
2310  *
2311  * ============================================================================= */
2312 NK_API int nk_utf_decode(const char*, nk_rune*, int);
2313 NK_API int nk_utf_encode(nk_rune, char*, int);
2314 NK_API int nk_utf_len(const char*, int byte_len);
2315 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len);
2316 /* ===============================================================
2317  *
2318  * FONT
2319  *
2320  * ===============================================================*/
2321 /* Font handling in this library was designed to be quite customizable and lets
2322  you decide what you want to use and what you want to provide. There are three
2323  different ways to use the font atlas. The first two will use your font
2324  handling scheme and only requires essential data to run nuklear. The next
2325  slightly more advanced features is font handling with vertex buffer output.
2326  Finally the most complex API wise is using nuklear's font baking API.
2327 
2328  1.) Using your own implementation without vertex buffer output
2329  --------------------------------------------------------------
2330  So first up the easiest way to do font handling is by just providing a
2331  `nk_user_font` struct which only requires the height in pixel of the used
2332  font and a callback to calculate the width of a string. This way of handling
2333  fonts is best fitted for using the normal draw shape command API where you
2334  do all the text drawing yourself and the library does not require any kind
2335  of deeper knowledge about which font handling mechanism you use.
2336  IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist
2337  over the complete life time! I know this sucks but it is currently the only
2338  way to switch between fonts.
2339 
2340  float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
2341  {
2342  your_font_type *type = handle.ptr;
2343  float text_width = ...;
2344  return text_width;
2345  }
2346 
2347  struct nk_user_font font;
2348  font.userdata.ptr = &your_font_class_or_struct;
2349  font.height = your_font_height;
2350  font.width = your_text_width_calculation;
2351 
2352  struct nk_context ctx;
2353  nk_init_default(&ctx, &font);
2354 
2355  2.) Using your own implementation with vertex buffer output
2356  --------------------------------------------------------------
2357  While the first approach works fine if you don't want to use the optional
2358  vertex buffer output it is not enough if you do. To get font handling working
2359  for these cases you have to provide two additional parameters inside the
2360  `nk_user_font`. First a texture atlas handle used to draw text as subimages
2361  of a bigger font atlas texture and a callback to query a character's glyph
2362  information (offset, size, ...). So it is still possible to provide your own
2363  font and use the vertex buffer output.
2364 
2365  float your_text_width_calculation(nk_handle handle, float height, const char *text, int len)
2366  {
2367  your_font_type *type = handle.ptr;
2368  float text_width = ...;
2369  return text_width;
2370  }
2371  void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
2372  {
2373  your_font_type *type = handle.ptr;
2374  glyph.width = ...;
2375  glyph.height = ...;
2376  glyph.xadvance = ...;
2377  glyph.uv[0].x = ...;
2378  glyph.uv[0].y = ...;
2379  glyph.uv[1].x = ...;
2380  glyph.uv[1].y = ...;
2381  glyph.offset.x = ...;
2382  glyph.offset.y = ...;
2383  }
2384 
2385  struct nk_user_font font;
2386  font.userdata.ptr = &your_font_class_or_struct;
2387  font.height = your_font_height;
2388  font.width = your_text_width_calculation;
2389  font.query = query_your_font_glyph;
2390  font.texture.id = your_font_texture;
2391 
2392  struct nk_context ctx;
2393  nk_init_default(&ctx, &font);
2394 
2395  3.) Nuklear font baker
2396  ------------------------------------
2397  The final approach if you do not have a font handling functionality or don't
2398  want to use it in this library is by using the optional font baker.
2399  The font baker APIs can be used to create a font plus font atlas texture
2400  and can be used with or without the vertex buffer output.
2401 
2402  It still uses the `nk_user_font` struct and the two different approaches
2403  previously stated still work. The font baker is not located inside
2404  `nk_context` like all other systems since it can be understood as more of
2405  an extension to nuklear and does not really depend on any `nk_context` state.
2406 
2407  Font baker need to be initialized first by one of the nk_font_atlas_init_xxx
2408  functions. If you don't care about memory just call the default version
2409  `nk_font_atlas_init_default` which will allocate all memory from the standard library.
2410  If you want to control memory allocation but you don't care if the allocated
2411  memory is temporary and therefore can be freed directly after the baking process
2412  is over or permanent you can call `nk_font_atlas_init`.
2413 
2414  After successfully initializing the font baker you can add Truetype(.ttf) fonts from
2415  different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`.
2416  functions. Adding font will permanently store each font, font config and ttf memory block(!)
2417  inside the font atlas and allows to reuse the font atlas. If you don't want to reuse
2418  the font baker by for example adding additional fonts you can call
2419  `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end).
2420 
2421  As soon as you added all fonts you wanted you can now start the baking process
2422  for every selected glyph to image by calling `nk_font_atlas_bake`.
2423  The baking process returns image memory, width and height which can be used to
2424  either create your own image object or upload it to any graphics library.
2425  No matter which case you finally have to call `nk_font_atlas_end` which
2426  will free all temporary memory including the font atlas image so make sure
2427  you created our texture beforehand. `nk_font_atlas_end` requires a handle
2428  to your font texture or object and optionally fills a `struct nk_draw_null_texture`
2429  which can be used for the optional vertex output. If you don't want it just
2430  set the argument to `NULL`.
2431 
2432  At this point you are done and if you don't want to reuse the font atlas you
2433  can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration
2434  memory. Finally if you don't use the font atlas and any of it's fonts anymore
2435  you need to call `nk_font_atlas_clear` to free all memory still being used.
2436 
2437  struct nk_font_atlas atlas;
2438  nk_font_atlas_init_default(&atlas);
2439  nk_font_atlas_begin(&atlas);
2440  nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0);
2441  nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0);
2442  const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32);
2443  nk_font_atlas_end(&atlas, nk_handle_id(texture), 0);
2444 
2445  struct nk_context ctx;
2446  nk_init_default(&ctx, &font->handle);
2447  while (1) {
2448 
2449  }
2450  nk_font_atlas_clear(&atlas);
2451 
2452  The font baker API is probably the most complex API inside this library and
2453  I would suggest reading some of my examples `example/` to get a grip on how
2454  to use the font atlas. There are a number of details I left out. For example
2455  how to merge fonts, configure a font with `nk_font_config` to use other languages,
2456  use another texture coordinate format and a lot more:
2457 
2458  struct nk_font_config cfg = nk_font_config(font_pixel_height);
2459  cfg.merge_mode = nk_false or nk_true;
2460  cfg.range = nk_font_korean_glyph_ranges();
2461  cfg.coord_type = NK_COORD_PIXEL;
2462  nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg);
2463 
2464 */
2465 struct nk_user_font_glyph;
2466 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len);
2467 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height,
2468  struct nk_user_font_glyph *glyph,
2469  nk_rune codepoint, nk_rune next_codepoint);
2470 
2471 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
2472 struct nk_user_font_glyph {
2473  struct nk_vec2 uv[2];
2474  /* texture coordinates */
2475  struct nk_vec2 offset;
2476  /* offset between top left and glyph */
2477  float width, height;
2478  /* size of the glyph */
2479  float xadvance;
2480  /* offset to the next glyph */
2481 };
2482 #endif
2483 
2486  /* user provided font handle */
2487  float height;
2488  /* max height of the font */
2490  /* font string width in pixel callback */
2491 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
2493  /* font glyph callback to query drawing info */
2495  /* texture handle to the used font atlas or texture */
2496 #endif
2497 };
2498 
2499 #ifdef NK_INCLUDE_FONT_BAKING
2500 enum nk_font_coord_type {
2501  NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */
2502  NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */
2503 };
2504 
2505 struct nk_baked_font {
2506  float height;
2507  /* height of the font */
2508  float ascent, descent;
2509  /* font glyphs ascent and descent */
2510  nk_rune glyph_offset;
2511  /* glyph array offset inside the font glyph baking output array */
2512  nk_rune glyph_count;
2513  /* number of glyphs of this font inside the glyph baking array output */
2514  const nk_rune *ranges;
2515  /* font codepoint ranges as pairs of (from/to) and 0 as last element */
2516 };
2517 
2518 struct nk_font_config {
2519  struct nk_font_config *next;
2520  /* NOTE: only used internally */
2521  void *ttf_blob;
2522  /* pointer to loaded TTF file memory block.
2523  * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
2524  nk_size ttf_size;
2525  /* size of the loaded TTF file memory block
2526  * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */
2527 
2528  unsigned char ttf_data_owned_by_atlas;
2529  /* used inside font atlas: default to: 0*/
2530  unsigned char merge_mode;
2531  /* merges this font into the last font */
2532  unsigned char pixel_snap;
2533  /* align every character to pixel boundary (if true set oversample (1,1)) */
2534  unsigned char oversample_v, oversample_h;
2535  /* rasterize at hight quality for sub-pixel position */
2536  unsigned char padding[3];
2537 
2538  float size;
2539  /* baked pixel height of the font */
2540  enum nk_font_coord_type coord_type;
2541  /* texture coordinate format with either pixel or UV coordinates */
2542  struct nk_vec2 spacing;
2543  /* extra pixel spacing between glyphs */
2544  const nk_rune *range;
2545  /* list of unicode ranges (2 values per range, zero terminated) */
2546  struct nk_baked_font *font;
2547  /* font to setup in the baking process: NOTE: not needed for font atlas */
2548  nk_rune fallback_glyph;
2549  /* fallback glyph to use if a given rune is not found */
2550 };
2551 
2552 struct nk_font_glyph {
2554  float xadvance;
2555  float x0, y0, x1, y1, w, h;
2556  float u0, v0, u1, v1;
2557 };
2558 
2559 struct nk_font {
2560  struct nk_font *next;
2561  struct nk_user_font handle;
2562  struct nk_baked_font info;
2563  float scale;
2564  struct nk_font_glyph *glyphs;
2565  const struct nk_font_glyph *fallback;
2566  nk_rune fallback_codepoint;
2568  struct nk_font_config *config;
2569 };
2570 
2571 enum nk_font_atlas_format {
2572  NK_FONT_ATLAS_ALPHA8,
2573  NK_FONT_ATLAS_RGBA32
2574 };
2575 
2576 struct nk_font_atlas {
2577  void *pixel;
2578  int tex_width;
2579  int tex_height;
2580 
2581  struct nk_allocator permanent;
2582  struct nk_allocator temporary;
2583 
2584  struct nk_recti custom;
2585  struct nk_cursor cursors[NK_CURSOR_COUNT];
2586 
2587  int glyph_count;
2588  struct nk_font_glyph *glyphs;
2589  struct nk_font *default_font;
2590  struct nk_font *fonts;
2591  struct nk_font_config *config;
2592  int font_num;
2593 };
2594 
2595 /* some language glyph codepoint ranges */
2596 NK_API const nk_rune *nk_font_default_glyph_ranges(void);
2597 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void);
2598 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void);
2599 NK_API const nk_rune *nk_font_korean_glyph_ranges(void);
2600 
2601 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2602 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*);
2603 #endif
2604 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*);
2605 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient);
2606 NK_API void nk_font_atlas_begin(struct nk_font_atlas*);
2607 NK_API struct nk_font_config nk_font_config(float pixel_height);
2608 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*);
2609 #ifdef NK_INCLUDE_DEFAULT_FONT
2610 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*);
2611 #endif
2612 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);
2613 #ifdef NK_INCLUDE_STANDARD_IO
2614 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*);
2615 #endif
2616 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*);
2617 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);
2618 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format);
2619 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*);
2620 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode);
2621 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas);
2622 NK_API void nk_font_atlas_clear(struct nk_font_atlas*);
2623 
2624 #endif
2625 
2626 /* ==============================================================
2627  *
2628  * MEMORY BUFFER
2629  *
2630  * ===============================================================*/
2631 /* A basic (double)-buffer with linear allocation and resetting as only
2632  freeing policy. The buffer's main purpose is to control all memory management
2633  inside the GUI toolkit and still leave memory control as much as possible in
2634  the hand of the user while also making sure the library is easy to use if
2635  not as much control is needed.
2636  In general all memory inside this library can be provided from the user in
2637  three different ways.
2638 
2639  The first way and the one providing most control is by just passing a fixed
2640  size memory block. In this case all control lies in the hand of the user
2641  since he can exactly control where the memory comes from and how much memory
2642  the library should consume. Of course using the fixed size API removes the
2643  ability to automatically resize a buffer if not enough memory is provided so
2644  you have to take over the resizing. While being a fixed sized buffer sounds
2645  quite limiting, it is very effective in this library since the actual memory
2646  consumption is quite stable and has a fixed upper bound for a lot of cases.
2647 
2648  If you don't want to think about how much memory the library should allocate
2649  at all time or have a very dynamic UI with unpredictable memory consumption
2650  habits but still want control over memory allocation you can use the dynamic
2651  allocator based API. The allocator consists of two callbacks for allocating
2652  and freeing memory and optional userdata so you can plugin your own allocator.
2653 
2654  The final and easiest way can be used by defining
2655  NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory
2656  allocation functions malloc and free and takes over complete control over
2657  memory in this library.
2658 */
2660  void *memory;
2661  unsigned int type;
2666 };
2667 
2671 };
2672 
2677 };
2678 
2680  int active;
2682 };
2683 
2684 struct nk_memory {void *ptr;nk_size size;};
2685 struct nk_buffer {
2687  /* buffer marker to free a buffer to a certain offset */
2689  /* allocator callback for dynamic buffers */
2691  /* memory management type */
2693  /* memory and size of the current memory block */
2695  /* growing factor for dynamic memory management */
2697  /* total amount of memory allocated */
2699  /* totally consumed memory given that enough memory is present */
2701  /* number of allocation calls */
2703  /* current size of the buffer */
2704 };
2705 
2706 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2707 NK_API void nk_buffer_init_default(struct nk_buffer*);
2708 #endif
2709 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size);
2710 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size);
2711 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*);
2712 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align);
2715 NK_API void nk_buffer_clear(struct nk_buffer*);
2716 NK_API void nk_buffer_free(struct nk_buffer*);
2717 NK_API void *nk_buffer_memory(struct nk_buffer*);
2718 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*);
2720 
2721 /* ==============================================================
2722  *
2723  * STRING
2724  *
2725  * ===============================================================*/
2726 /* Basic string buffer which is only used in context with the text editor
2727  * to manage and manipulate dynamic or fixed size string content. This is _NOT_
2728  * the default string handling method. The only instance you should have any contact
2729  * with this API is if you interact with an `nk_text_edit` object inside one of the
2730  * copy and paste functions and even there only for more advanced cases. */
2731 struct nk_str {
2733  int len; /* in codepoints/runes/glyphs */
2734 };
2735 
2736 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2737 NK_API void nk_str_init_default(struct nk_str*);
2738 #endif
2739 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size);
2740 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size);
2741 NK_API void nk_str_clear(struct nk_str*);
2742 NK_API void nk_str_free(struct nk_str*);
2743 
2744 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int);
2745 NK_API int nk_str_append_str_char(struct nk_str*, const char*);
2746 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int);
2747 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*);
2748 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int);
2749 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*);
2750 
2751 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int);
2752 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int);
2753 
2754 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int);
2755 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*);
2756 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int);
2757 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*);
2758 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int);
2759 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*);
2760 
2761 NK_API void nk_str_remove_chars(struct nk_str*, int len);
2762 NK_API void nk_str_remove_runes(struct nk_str *str, int len);
2763 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len);
2764 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len);
2765 
2766 NK_API char *nk_str_at_char(struct nk_str*, int pos);
2767 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len);
2768 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos);
2769 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos);
2770 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len);
2771 
2772 NK_API char *nk_str_get(struct nk_str*);
2773 NK_API const char *nk_str_get_const(const struct nk_str*);
2774 NK_API int nk_str_len(struct nk_str*);
2775 NK_API int nk_str_len_char(struct nk_str*);
2776 
2777 /*===============================================================
2778  *
2779  * TEXT EDITOR
2780  *
2781  * ===============================================================*/
2782 /* Editing text in this library is handled by either `nk_edit_string` or
2783  * `nk_edit_buffer`. But like almost everything in this library there are multiple
2784  * ways of doing it and a balance between control and ease of use with memory
2785  * as well as functionality controlled by flags.
2786  *
2787  * This library generally allows three different levels of memory control:
2788  * First of is the most basic way of just providing a simple char array with
2789  * string length. This method is probably the easiest way of handling simple
2790  * user text input. Main upside is complete control over memory while the biggest
2791  * downside in comparison with the other two approaches is missing undo/redo.
2792  *
2793  * For UIs that require undo/redo the second way was created. It is based on
2794  * a fixed size nk_text_edit struct, which has an internal undo/redo stack.
2795  * This is mainly useful if you want something more like a text editor but don't want
2796  * to have a dynamically growing buffer.
2797  *
2798  * The final way is using a dynamically growing nk_text_edit struct, which
2799  * has both a default version if you don't care where memory comes from and an
2800  * allocator version if you do. While the text editor is quite powerful for its
2801  * complexity I would not recommend editing gigabytes of data with it.
2802  * It is rather designed for uses cases which make sense for a GUI library not for
2803  * an full blown text editor.
2804  */
2805 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT
2806 #define NK_TEXTEDIT_UNDOSTATECOUNT 99
2807 #endif
2808 
2809 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT
2810 #define NK_TEXTEDIT_UNDOCHARCOUNT 999
2811 #endif
2812 
2813 struct nk_text_edit;
2818 };
2819 
2821  int where;
2825 };
2826 
2830  short undo_point;
2831  short redo_point;
2834 };
2835 
2839 };
2840 
2845 };
2846 
2849  struct nk_str string;
2852 
2853  int cursor;
2856  unsigned char mode;
2857  unsigned char cursor_at_end_of_line;
2858  unsigned char initialized;
2859  unsigned char has_preferred_x;
2860  unsigned char single_line;
2861  unsigned char active;
2862  unsigned char padding1;
2865 };
2866 
2867 /* filter function */
2868 NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode);
2869 NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode);
2870 NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode);
2871 NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode);
2872 NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode);
2873 NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode);
2874 NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode);
2875 
2876 /* text editor */
2877 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
2878 NK_API void nk_textedit_init_default(struct nk_text_edit*);
2879 #endif
2881 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size);
2882 NK_API void nk_textedit_free(struct nk_text_edit*);
2883 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len);
2884 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len);
2887 NK_API int nk_textedit_cut(struct nk_text_edit*);
2888 NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len);
2889 NK_API void nk_textedit_undo(struct nk_text_edit*);
2890 NK_API void nk_textedit_redo(struct nk_text_edit*);
2891 
2892 /* ===============================================================
2893  *
2894  * DRAWING
2895  *
2896  * ===============================================================*/
2897 /* This library was designed to be render backend agnostic so it does
2898  not draw anything to screen. Instead all drawn shapes, widgets
2899  are made of, are buffered into memory and make up a command queue.
2900  Each frame therefore fills the command buffer with draw commands
2901  that then need to be executed by the user and his own render backend.
2902  After that the command buffer needs to be cleared and a new frame can be
2903  started. It is probably important to note that the command buffer is the main
2904  drawing API and the optional vertex buffer API only takes this format and
2905  converts it into a hardware accessible format.
2906 
2907  To use the command queue to draw your own widgets you can access the
2908  command buffer of each window by calling `nk_window_get_canvas` after
2909  previously having called `nk_begin`:
2910 
2911  void draw_red_rectangle_widget(struct nk_context *ctx)
2912  {
2913  struct nk_command_buffer *canvas;
2914  struct nk_input *input = &ctx->input;
2915  canvas = nk_window_get_canvas(ctx);
2916 
2917  struct nk_rect space;
2918  enum nk_widget_layout_states state;
2919  state = nk_widget(&space, ctx);
2920  if (!state) return;
2921 
2922  if (state != NK_WIDGET_ROM)
2923  update_your_widget_by_user_input(...);
2924  nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0));
2925  }
2926 
2927  if (nk_begin(...)) {
2928  nk_layout_row_dynamic(ctx, 25, 1);
2929  draw_red_rectangle_widget(ctx);
2930  }
2931  nk_end(..)
2932 
2933  Important to know if you want to create your own widgets is the `nk_widget`
2934  call. It allocates space on the panel reserved for this widget to be used,
2935  but also returns the state of the widget space. If your widget is not seen and does
2936  not have to be updated it is '0' and you can just return. If it only has
2937  to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both
2938  update and draw your widget. The reason for separating is to only draw and
2939  update what is actually necessary which is crucial for performance.
2940 */
2961 };
2962 
2963 /* command base and header of every command inside the buffer */
2964 struct nk_command {
2967 #ifdef NK_INCLUDE_COMMAND_USERDATA
2968  nk_handle userdata;
2969 #endif
2970 };
2971 
2974  short x, y;
2975  unsigned short w, h;
2976 };
2977 
2980  unsigned short line_thickness;
2981  struct nk_vec2i begin;
2982  struct nk_vec2i end;
2983  struct nk_color color;
2984 };
2985 
2988  unsigned short line_thickness;
2989  struct nk_vec2i begin;
2990  struct nk_vec2i end;
2991  struct nk_vec2i ctrl[2];
2992  struct nk_color color;
2993 };
2994 
2997  unsigned short rounding;
2998  unsigned short line_thickness;
2999  short x, y;
3000  unsigned short w, h;
3001  struct nk_color color;
3002 };
3003 
3006  unsigned short rounding;
3007  short x, y;
3008  unsigned short w, h;
3009  struct nk_color color;
3010 };
3011 
3014  short x, y;
3015  unsigned short w, h;
3016  struct nk_color left;
3017  struct nk_color top;
3019  struct nk_color right;
3020 };
3021 
3024  unsigned short line_thickness;
3025  struct nk_vec2i a;
3026  struct nk_vec2i b;
3027  struct nk_vec2i c;
3028  struct nk_color color;
3029 };
3030 
3033  struct nk_vec2i a;
3034  struct nk_vec2i b;
3035  struct nk_vec2i c;
3036  struct nk_color color;
3037 };
3038 
3041  short x, y;
3042  unsigned short line_thickness;
3043  unsigned short w, h;
3044  struct nk_color color;
3045 };
3046 
3049  short x, y;
3050  unsigned short w, h;
3051  struct nk_color color;
3052 };
3053 
3056  short cx, cy;
3057  unsigned short r;
3058  unsigned short line_thickness;
3059  float a[2];
3060  struct nk_color color;
3061 };
3062 
3065  short cx, cy;
3066  unsigned short r;
3067  float a[2];
3068  struct nk_color color;
3069 };
3070 
3073  struct nk_color color;
3074  unsigned short line_thickness;
3075  unsigned short point_count;
3076  struct nk_vec2i points[1];
3077 };
3078 
3081  struct nk_color color;
3082  unsigned short point_count;
3083  struct nk_vec2i points[1];
3084 };
3085 
3088  struct nk_color color;
3089  unsigned short line_thickness;
3090  unsigned short point_count;
3091  struct nk_vec2i points[1];
3092 };
3093 
3096  short x, y;
3097  unsigned short w, h;
3098  struct nk_image img;
3099  struct nk_color col;
3100 };
3101 
3102 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y,
3103  unsigned short w, unsigned short h, nk_handle callback_data);
3106  short x, y;
3107  unsigned short w, h;
3110 };
3111 
3114  const struct nk_user_font *font;
3117  short x, y;
3118  unsigned short w, h;
3119  float height;
3120  int length;
3121  char string[1];
3122 };
3123 
3127 };
3128 
3130  struct nk_buffer *base;
3131  struct nk_rect clip;
3135 };
3136 
3137 /* shape outlines */
3138 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);
3139 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color);
3140 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color);
3141 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color);
3142 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);
3143 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color);
3144 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col);
3145 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color);
3146 
3147 /* filled shades */
3148 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color);
3149 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);
3150 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color);
3151 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);
3152 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);
3153 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color);
3154 
3155 /* misc */
3156 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color);
3157 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);
3158 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect);
3160 
3161 /* ===============================================================
3162  *
3163  * INPUT
3164  *
3165  * ===============================================================*/
3167  int down;
3168  unsigned int clicked;
3170 };
3171 struct nk_mouse {
3173  struct nk_vec2 pos;
3174  struct nk_vec2 prev;
3175  struct nk_vec2 delta;
3177  unsigned char grab;
3178  unsigned char grabbed;
3179  unsigned char ungrab;
3180 };
3181 
3182 struct nk_key {
3183  int down;
3184  unsigned int clicked;
3185 };
3186 struct nk_keyboard {
3190 };
3191 
3192 struct nk_input {
3194  struct nk_mouse mouse;
3195 };
3196 
3197 NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons);
3198 NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
3199 NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down);
3200 NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect);
3201 NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down);
3202 NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect);
3203 NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect);
3204 NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect);
3205 NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect);
3206 NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons);
3207 NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons);
3208 NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons);
3209 NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys);
3210 NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys);
3211 NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys);
3212 
3213 /* ===============================================================
3214  *
3215  * DRAW LIST
3216  *
3217  * ===============================================================*/
3218 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
3219 /* The optional vertex buffer draw list provides a 2D drawing context
3220  with antialiasing functionality which takes basic filled or outlined shapes
3221  or a path and outputs vertexes, elements and draw commands.
3222  The actual draw list API is not required to be used directly while using this
3223  library since converting the default library draw command output is done by
3224  just calling `nk_convert` but I decided to still make this library accessible
3225  since it can be useful.
3226 
3227  The draw list is based on a path buffering and polygon and polyline
3228  rendering API which allows a lot of ways to draw 2D content to screen.
3229  In fact it is probably more powerful than needed but allows even more crazy
3230  things than this library provides by default.
3231 */
3232 typedef nk_ushort nk_draw_index;
3233 enum nk_draw_list_stroke {
3234  NK_STROKE_OPEN = nk_false,
3235  /* build up path has no connection back to the beginning */
3236  NK_STROKE_CLOSED = nk_true
3237  /* build up path has a connection back to the beginning */
3238 };
3239 
3240 enum nk_draw_vertex_layout_attribute {
3241  NK_VERTEX_POSITION,
3242  NK_VERTEX_COLOR,
3243  NK_VERTEX_TEXCOORD,
3244  NK_VERTEX_ATTRIBUTE_COUNT
3245 };
3246 
3247 enum nk_draw_vertex_layout_format {
3248  NK_FORMAT_SCHAR,
3249  NK_FORMAT_SSHORT,
3250  NK_FORMAT_SINT,
3251  NK_FORMAT_UCHAR,
3252  NK_FORMAT_USHORT,
3253  NK_FORMAT_UINT,
3254  NK_FORMAT_FLOAT,
3255  NK_FORMAT_DOUBLE,
3256 
3257 NK_FORMAT_COLOR_BEGIN,
3258  NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN,
3259  NK_FORMAT_R16G15B16,
3260  NK_FORMAT_R32G32B32,
3261 
3262  NK_FORMAT_R8G8B8A8,
3263  NK_FORMAT_B8G8R8A8,
3264  NK_FORMAT_R16G15B16A16,
3265  NK_FORMAT_R32G32B32A32,
3266  NK_FORMAT_R32G32B32A32_FLOAT,
3267  NK_FORMAT_R32G32B32A32_DOUBLE,
3268 
3269  NK_FORMAT_RGB32,
3270  NK_FORMAT_RGBA32,
3271 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32,
3272  NK_FORMAT_COUNT
3273 };
3274 
3275 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0
3276 struct nk_draw_vertex_layout_element {
3277  enum nk_draw_vertex_layout_attribute attribute;
3278  enum nk_draw_vertex_layout_format format;
3279  nk_size offset;
3280 };
3281 
3282 struct nk_draw_command {
3283  unsigned int elem_count;
3284  /* number of elements in the current draw batch */
3285  struct nk_rect clip_rect;
3286  /* current screen clipping rectangle */
3288  /* current texture to set */
3289 #ifdef NK_INCLUDE_COMMAND_USERDATA
3290  nk_handle userdata;
3291 #endif
3292 };
3293 
3294 struct nk_draw_list {
3295  struct nk_rect clip_rect;
3296  struct nk_vec2 circle_vtx[12];
3297  struct nk_convert_config config;
3298 
3299  struct nk_buffer *buffer;
3300  struct nk_buffer *vertices;
3301  struct nk_buffer *elements;
3302 
3303  unsigned int element_count;
3304  unsigned int vertex_count;
3305  unsigned int cmd_count;
3306  nk_size cmd_offset;
3307 
3308  unsigned int path_count;
3309  unsigned int path_offset;
3310 
3311  enum nk_anti_aliasing line_AA;
3312  enum nk_anti_aliasing shape_AA;
3313 
3314 #ifdef NK_INCLUDE_COMMAND_USERDATA
3315  nk_handle userdata;
3316 #endif
3317 };
3318 
3319 /* draw list */
3320 NK_API void nk_draw_list_init(struct nk_draw_list*);
3321 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);
3322 NK_API void nk_draw_list_clear(struct nk_draw_list*);
3323 
3324 /* drawing */
3325 #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))
3326 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*);
3327 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*);
3328 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*);
3329 NK_API void nk_draw_list_clear(struct nk_draw_list *list);
3330 
3331 /* path */
3332 NK_API void nk_draw_list_path_clear(struct nk_draw_list*);
3333 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos);
3334 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);
3335 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);
3336 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding);
3337 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);
3338 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color);
3339 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness);
3340 
3341 /* stroke */
3342 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);
3343 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness);
3344 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);
3345 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);
3346 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);
3347 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);
3348 
3349 /* fill */
3350 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding);
3351 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);
3352 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);
3353 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);
3354 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);
3355 
3356 /* misc */
3357 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color);
3358 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);
3359 #ifdef NK_INCLUDE_COMMAND_USERDATA
3360 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata);
3361 #endif
3362 
3363 #endif
3364 
3365 /* ===============================================================
3366  *
3367  * GUI
3368  *
3369  * ===============================================================*/
3373 };
3374 
3376  struct nk_image image;
3377  struct nk_color color;
3378 };
3379 
3383 };
3384 
3386  struct nk_color color;
3388 };
3389 
3391  /* background */
3396 
3397  /* text */
3403 
3404  /* properties */
3405  float border;
3406  float rounding;
3410 
3411  /* optional user callbacks */
3415 };
3416 
3418  /* background */
3423 
3424  /* cursor */
3427 
3428  /* text */
3434 
3435  /* properties */
3438  float spacing;
3439  float border;
3440 
3441  /* optional user callbacks */
3445 };
3446 
3448  /* background (inactive) */
3452 
3453  /* background (active) */
3457 
3458  /* text color (inactive) */
3462 
3463  /* text color (active) */
3469 
3470  /* properties */
3471  float rounding;
3475 
3476  /* optional user callbacks */
3480 };
3481 
3483  /* background */
3488 
3489  /* background bar */
3494 
3495  /* cursor */
3499 
3500  /* properties */
3501  float border;
3502  float rounding;
3503  float bar_height;
3507 
3508  /* optional buttons */
3514 
3515  /* optional user callbacks */
3519 };
3520 
3522  /* background */
3527 
3528  /* cursor */
3533 
3534  /* properties */
3535  float rounding;
3536  float border;
3540 
3541  /* optional user callbacks */
3545 };
3546 
3548  /* background */
3553 
3554  /* cursor */
3559 
3560  /* properties */
3561  float border;
3562  float rounding;
3566 
3567  /* optional buttons */
3573 
3574  /* optional user callbacks */
3578 };
3579 
3581  /* background */
3587 
3588  /* cursor */
3593 
3594  /* text (unselected) */
3598 
3599  /* text (selected) */
3604 
3605  /* properties */
3606  float border;
3607  float rounding;
3612 };
3613 
3615  /* background */
3620 
3621  /* text */
3625 
3626  /* symbols */
3629 
3630  /* properties */
3631  float border;
3632  float rounding;
3634 
3638 
3639  /* optional user callbacks */
3643 };
3644 
3646  /* colors */
3650  struct nk_color color;
3651 
3652  /* properties */
3653  float border;
3654  float rounding;
3656 };
3657 
3659  /* background */
3664 
3665  /* label */
3669 
3670  /* symbol */
3674 
3675  /* button */
3680 
3681  /* properties */
3682  float border;
3683  float rounding;
3687 };
3688 
3690  /* background */
3693  struct nk_color text;
3694 
3695  /* button */
3702 
3703  /* properties */
3704  float border;
3705  float rounding;
3706  float indent;
3709 };
3710 
3714 };
3716  /* background */
3720 
3721  /* button */
3727 
3728  /* title */
3732 
3733  /* properties */
3738 };
3739 
3744 
3753 
3754  float border;
3762 
3763  float rounding;
3767 
3775 };
3776 
3777 struct nk_style {
3778  const struct nk_user_font *font;
3780  const struct nk_cursor *cursor_active;
3783 
3801 };
3802 
3806 
3807 /*==============================================================
3808  * PANEL
3809  * =============================================================*/
3810 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
3811 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16
3812 #endif
3813 #ifndef NK_CHART_MAX_SLOT
3814 #define NK_CHART_MAX_SLOT 4
3815 #endif
3816 
3825 };
3830 };
3831 
3834  struct nk_color color;
3836  float min, max, range;
3837  int count;
3838  struct nk_vec2 last;
3839  int index;
3840 };
3841 
3842 struct nk_chart {
3843  int slot;
3844  float x, y, w, h;
3846 };
3847 
3859 };
3862  int index;
3863  float height;
3864  float min_height;
3865  int columns;
3866  const float *ratio;
3867  float item_width;
3870  float filled;
3871  struct nk_rect item;
3874 };
3875 
3881  int active;
3882 };
3883 
3885  float x, y, w, h;
3887 };
3888 
3889 struct nk_panel {
3892  struct nk_rect bounds;
3895  float at_x, at_y, max_x;
3898  float border;
3899  unsigned int has_scrolling;
3900  struct nk_rect clip;
3903  struct nk_chart chart;
3905  struct nk_panel *parent;
3906 };
3907 
3908 /*==============================================================
3909  * WINDOW
3910  * =============================================================*/
3911 #ifndef NK_WINDOW_MAX_NAME
3912 #define NK_WINDOW_MAX_NAME 64
3913 #endif
3914 
3915 struct nk_table;
3919  /* special window type growing up in height while being filled to a certain maximum height */
3921  /* sets window widgets into a read only mode and does not allow input changes */
3923  /* prevents all interaction caused by input to either window or widgets inside */
3925  /* Hides window and stops any window interaction and drawing */
3927  /* Directly closes and frees the window at the end of the frame */
3929  /* marks the window as minimized */
3931  /* Removes read only mode at the end of the window */
3932 };
3933 
3935  struct nk_window *win;
3939  int active;
3940  unsigned combo_count;
3941  unsigned con_count, con_old;
3942  unsigned active_con;
3943  struct nk_rect header;
3944 };
3945 
3948  unsigned int seq;
3949  unsigned int old;
3950  int active, prev;
3951  int cursor;
3953  int sel_end;
3955  unsigned char mode;
3956  unsigned char single_line;
3957 };
3958 
3960  int active, prev;
3962  int length;
3963  int cursor;
3967  unsigned int seq;
3968  unsigned int old;
3969  int state;
3970 };
3971 
3972 struct nk_window {
3973  unsigned int seq;
3977 
3978  struct nk_rect bounds;
3981  struct nk_panel *layout;
3983 
3984  /* persistent widget state */
3988  unsigned int scrolled;
3989 
3990  struct nk_table *tables;
3991  unsigned int table_count;
3992 
3993  /* window list hooks */
3994  struct nk_window *next;
3995  struct nk_window *prev;
3997 };
3998 
3999 /*==============================================================
4000  * STACK
4001  * =============================================================*/
4002 /* The style modifier stack can be used to temporarily change a
4003  * property inside `nk_style`. For example if you want a special
4004  * red button you can temporarily push the old button color onto a stack
4005  * draw the button with a red color and then you just pop the old color
4006  * back from the stack:
4007  *
4008  * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0)));
4009  * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0)));
4010  * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0)));
4011  * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2));
4012  *
4013  * nk_button(...);
4014  *
4015  * nk_style_pop_style_item(ctx);
4016  * nk_style_pop_style_item(ctx);
4017  * nk_style_pop_style_item(ctx);
4018  * nk_style_pop_vec2(ctx);
4019  *
4020  * Nuklear has a stack for style_items, float properties, vector properties,
4021  * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack
4022  * which can be changed at compile time.
4023  */
4024 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE
4025 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8
4026 #endif
4027 
4028 #ifndef NK_FONT_STACK_SIZE
4029 #define NK_FONT_STACK_SIZE 8
4030 #endif
4031 
4032 #ifndef NK_STYLE_ITEM_STACK_SIZE
4033 #define NK_STYLE_ITEM_STACK_SIZE 16
4034 #endif
4035 
4036 #ifndef NK_FLOAT_STACK_SIZE
4037 #define NK_FLOAT_STACK_SIZE 32
4038 #endif
4039 
4040 #ifndef NK_VECTOR_STACK_SIZE
4041 #define NK_VECTOR_STACK_SIZE 16
4042 #endif
4043 
4044 #ifndef NK_FLAGS_STACK_SIZE
4045 #define NK_FLAGS_STACK_SIZE 32
4046 #endif
4047 
4048 #ifndef NK_COLOR_STACK_SIZE
4049 #define NK_COLOR_STACK_SIZE 32
4050 #endif
4051 
4052 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\
4053  struct nk_config_stack_##name##_element {\
4054  prefix##_##type *address;\
4055  prefix##_##type old_value;\
4056  }
4057 #define NK_CONFIG_STACK(type,size)\
4058  struct nk_config_stack_##type {\
4059  int head;\
4060  struct nk_config_stack_##type##_element elements[size];\
4061  }
4062 
4063 #define nk_float float
4064 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item);
4065 NK_CONFIGURATION_STACK_TYPE(nk ,float, float);
4066 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2);
4069 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*);
4070 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior);
4071 
4079 
4081  struct nk_config_stack_style_item style_items;
4082  struct nk_config_stack_float floats;
4083  struct nk_config_stack_vec2 vectors;
4084  struct nk_config_stack_flags flags;
4085  struct nk_config_stack_color colors;
4086  struct nk_config_stack_user_font fonts;
4087  struct nk_config_stack_button_behavior button_behaviors;
4088 };
4089 
4090 /*==============================================================
4091  * CONTEXT
4092  * =============================================================*/
4093 #define NK_VALUE_PAGE_CAPACITY \
4094  (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2)
4095 
4096 struct nk_table {
4097  unsigned int seq;
4098  unsigned int size;
4101  struct nk_table *next, *prev;
4102 };
4103 
4105  struct nk_table tbl;
4106  struct nk_panel pan;
4107  struct nk_window win;
4108 };
4109 
4114 };
4115 
4116 struct nk_page {
4117  unsigned int size;
4118  struct nk_page *next;
4120 };
4121 
4122 struct nk_pool {
4125  unsigned int page_count;
4126  struct nk_page *pages;
4128  unsigned capacity;
4131 };
4132 
4133 struct nk_context {
4134 /* public: can be accessed freely */
4135  struct nk_input input;
4136  struct nk_style style;
4143 
4144 /* private:
4145  should only be accessed if you
4146  know what you are doing */
4147 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
4148  struct nk_draw_list draw_list;
4149 #endif
4150 #ifdef NK_INCLUDE_COMMAND_USERDATA
4151  nk_handle userdata;
4152 #endif
4153  /* text editor objects are quite big because of an internal
4154  * undo/redo stack. Therefore it does not make sense to have one for
4155  * each window for temporary use cases, so I only provide *one* instance
4156  * for all windows. This works because the content is cleared anyway */
4158  /* draw buffer used for overlay drawing operation like cursor */
4160 
4161  /* windows */
4162  int build;
4164  struct nk_pool pool;
4165  struct nk_window *begin;
4166  struct nk_window *end;
4170  unsigned int count;
4171  unsigned int seq;
4172 };
4173 
4174 /* ==============================================================
4175  * MATH
4176  * =============================================================== */
4177 #define NK_PI 3.141592654f
4178 #define NK_UTF_INVALID 0xFFFD
4179 #define NK_MAX_FLOAT_PRECISION 2
4180 
4181 #define NK_UNUSED(x) ((void)(x))
4182 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x)))
4183 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0])
4184 #define NK_ABS(a) (((a) < 0) ? -(a) : (a))
4185 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b))
4186 #define NK_INBOX(px, py, x, y, w, h)\
4187  (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h))
4188 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \
4189  (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0)))
4190 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\
4191  (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh))
4192 
4193 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y)
4194 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y)
4195 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y)
4196 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t))
4197 
4198 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i))))
4199 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i))))
4200 #define nk_zero_struct(s) nk_zero(&s, sizeof(s))
4201 
4202 /* ==============================================================
4203  * ALIGNMENT
4204  * =============================================================== */
4205 /* Pointer to Integer type conversion for pointer alignment */
4206 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/
4207 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x))
4208 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x))
4209 #elif !defined(__GNUC__) /* works for compilers other than LLVM */
4210 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x])
4211 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0))
4212 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */
4213 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x))
4214 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x))
4215 #else /* generates warning but works */
4216 # define NK_UINT_TO_PTR(x) ((void*)(x))
4217 # define NK_PTR_TO_UINT(x) ((nk_size)(x))
4218 #endif
4219 
4220 #define NK_ALIGN_PTR(x, mask)\
4221  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1))))
4222 #define NK_ALIGN_PTR_BACK(x, mask)\
4223  (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1))))
4224 
4225 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m))
4226 #define NK_CONTAINER_OF(ptr,type,member)\
4227  (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member)))
4228 
4229 #ifdef __cplusplus
4230 }
4231 #endif
4232 
4233 #ifdef __cplusplus
4234 template<typename T> struct nk_alignof;
4235 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};};
4236 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};};
4237 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum {
4238  diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};};
4239 #define NK_ALIGNOF(t) (nk_alignof<t>::value)
4240 #elif defined(_MSC_VER)
4241 #define NK_ALIGNOF(t) (__alignof(t))
4242 #else
4243 #define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0)
4244 #endif
4245 
4246 #endif /* NK_NUKLEAR_H_ */
4247 /*
4248  * ==============================================================
4249  *
4250  * IMPLEMENTATION
4251  *
4252  * ===============================================================
4253  */
4254 #ifdef NK_IMPLEMENTATION
4255 
4256 #ifndef NK_POOL_DEFAULT_CAPACITY
4257 #define NK_POOL_DEFAULT_CAPACITY 16
4258 #endif
4259 
4260 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE
4261 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024)
4262 #endif
4263 
4264 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE
4265 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024)
4266 #endif
4267 
4268 /* standard library headers */
4269 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
4270 #include <stdlib.h> /* malloc, free */
4271 #endif
4272 #ifdef NK_INCLUDE_STANDARD_IO
4273 #include <stdio.h> /* fopen, fclose,... */
4274 #endif
4275 #ifdef NK_INCLUDE_STANDARD_VARARGS
4276 #include <stdarg.h> /* valist, va_start, va_end, ... */
4277 #endif
4278 #ifndef NK_ASSERT
4279 #include <assert.h>
4280 #define NK_ASSERT(expr) assert(expr)
4281 #endif
4282 
4283 #ifndef NK_MEMSET
4284 #define NK_MEMSET nk_memset
4285 #endif
4286 #ifndef NK_MEMCPY
4287 #define NK_MEMCPY nk_memcopy
4288 #endif
4289 #ifndef NK_SQRT
4290 #define NK_SQRT nk_sqrt
4291 #endif
4292 #ifndef NK_SIN
4293 #define NK_SIN nk_sin
4294 #endif
4295 #ifndef NK_COS
4296 #define NK_COS nk_cos
4297 #endif
4298 #ifndef NK_STRTOD
4299 #define NK_STRTOD nk_strtod
4300 #endif
4301 #ifndef NK_DTOA
4302 #define NK_DTOA nk_dtoa
4303 #endif
4304 
4305 #define NK_DEFAULT (-1)
4306 
4307 #ifndef NK_VSNPRINTF
4308 /* If your compiler does support `vsnprintf` I would highly recommend
4309  * defining this to vsnprintf instead since `vsprintf` is basically
4310  * unbelievable unsafe and should *NEVER* be used. But I have to support
4311  * it since C89 only provides this unsafe version. */
4312  #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\
4313  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
4314  (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\
4315  (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\
4316  defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE)
4317  #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a)
4318  #else
4319  #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a)
4320  #endif
4321 #endif
4322 
4323 #define NK_SCHAR_MIN (-127)
4324 #define NK_SCHAR_MAX 127
4325 #define NK_UCHAR_MIN 0
4326 #define NK_UCHAR_MAX 256
4327 #define NK_SSHORT_MIN (-32767)
4328 #define NK_SSHORT_MAX 32767
4329 #define NK_USHORT_MIN 0
4330 #define NK_USHORT_MAX 65535
4331 #define NK_SINT_MIN (-2147483647)
4332 #define NK_SINT_MAX 2147483647
4333 #define NK_UINT_MIN 0
4334 #define NK_UINT_MAX 4294967295u
4335 
4336 /* Make sure correct type size:
4337  * This will fire with a negative subscript error if the type sizes
4338  * are set incorrectly by the compiler, and compile out if not */
4339 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*));
4340 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*));
4341 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4);
4342 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4);
4343 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2);
4344 NK_STATIC_ASSERT(sizeof(nk_short) == 2);
4345 NK_STATIC_ASSERT(sizeof(nk_uint) == 4);
4346 NK_STATIC_ASSERT(sizeof(nk_int) == 4);
4347 NK_STATIC_ASSERT(sizeof(nk_byte) == 1);
4348 
4349 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384};
4350 #define NK_FLOAT_PRECISION 0.00000000000001
4351 
4352 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255};
4353 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255};
4354 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255};
4355 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255};
4356 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255};
4357 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255};
4358 
4359 /*
4360  * ==============================================================
4361  *
4362  * MATH
4363  *
4364  * ===============================================================
4365  */
4366 /* Since nuklear is supposed to work on all systems providing floating point
4367  math without any dependencies I also had to implement my own math functions
4368  for sqrt, sin and cos. Since the actual highly accurate implementations for
4369  the standard library functions are quite complex and I do not need high
4370  precision for my use cases I use approximations.
4371 
4372  Sqrt
4373  ----
4374  For square root nuklear uses the famous fast inverse square root:
4375  https://en.wikipedia.org/wiki/Fast_inverse_square_root with
4376  slightly tweaked magic constant. While on today's hardware it is
4377  probably not faster it is still fast and accurate enough for
4378  nuklear's use cases. IMPORTANT: this requires float format IEEE 754
4379 
4380  Sine/Cosine
4381  -----------
4382  All constants inside both function are generated Remez's minimax
4383  approximations for value range 0...2*PI. The reason why I decided to
4384  approximate exactly that range is that nuklear only needs sine and
4385  cosine to generate circles which only requires that exact range.
4386  In addition I used Remez instead of Taylor for additional precision:
4387  www.lolengine.net/blog/2011/12/21/better-function-approximations.
4388 
4389  The tool I used to generate constants for both sine and cosine
4390  (it can actually approximate a lot more functions) can be
4391  found here: www.lolengine.net/wiki/oss/lolremez
4392 */
4393 NK_INTERN float
4394 nk_inv_sqrt(float number)
4395 {
4396  float x2;
4397  const float threehalfs = 1.5f;
4398  union {nk_uint i; float f;} conv = {0};
4399  conv.f = number;
4400  x2 = number * 0.5f;
4401  conv.i = 0x5f375A84 - (conv.i >> 1);
4402  conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f));
4403  return conv.f;
4404 }
4405 
4406 NK_INTERN float
4407 nk_sqrt(float x)
4408 {
4409  return x * nk_inv_sqrt(x);
4410 }
4411 
4412 NK_INTERN float
4413 nk_sin(float x)
4414 {
4415  NK_STORAGE const float a0 = +1.91059300966915117e-31f;
4416  NK_STORAGE const float a1 = +1.00086760103908896f;
4417  NK_STORAGE const float a2 = -1.21276126894734565e-2f;
4418  NK_STORAGE const float a3 = -1.38078780785773762e-1f;
4419  NK_STORAGE const float a4 = -2.67353392911981221e-2f;
4420  NK_STORAGE const float a5 = +2.08026600266304389e-2f;
4421  NK_STORAGE const float a6 = -3.03996055049204407e-3f;
4422  NK_STORAGE const float a7 = +1.38235642404333740e-4f;
4423  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
4424 }
4425 
4426 NK_INTERN float
4427 nk_cos(float x)
4428 {
4429  NK_STORAGE const float a0 = +1.00238601909309722f;
4430  NK_STORAGE const float a1 = -3.81919947353040024e-2f;
4431  NK_STORAGE const float a2 = -3.94382342128062756e-1f;
4432  NK_STORAGE const float a3 = -1.18134036025221444e-1f;
4433  NK_STORAGE const float a4 = +1.07123798512170878e-1f;
4434  NK_STORAGE const float a5 = -1.86637164165180873e-2f;
4435  NK_STORAGE const float a6 = +9.90140908664079833e-4f;
4436  NK_STORAGE const float a7 = -5.23022132118824778e-14f;
4437  return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7))))));
4438 }
4439 
4441 nk_round_up_pow2(nk_uint v)
4442 {
4443  v--;
4444  v |= v >> 1;
4445  v |= v >> 2;
4446  v |= v >> 4;
4447  v |= v >> 8;
4448  v |= v >> 16;
4449  v++;
4450  return v;
4451 }
4452 
4453 NK_API struct nk_rect
4455 {
4456  return nk_null_rect;
4457 }
4458 
4459 NK_API struct nk_rect
4460 nk_rect(float x, float y, float w, float h)
4461 {
4462  struct nk_rect r;
4463  r.x = x; r.y = y;
4464  r.w = w; r.h = h;
4465  return r;
4466 }
4467 
4468 NK_API struct nk_rect
4469 nk_recti(int x, int y, int w, int h)
4470 {
4471  struct nk_rect r;
4472  r.x = (float)x;
4473  r.y = (float)y;
4474  r.w = (float)w;
4475  r.h = (float)h;
4476  return r;
4477 }
4478 
4479 NK_API struct nk_rect
4480 nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
4481 {
4482  return nk_rect(pos.x, pos.y, size.x, size.y);
4483 }
4484 
4485 NK_API struct nk_rect
4486 nk_rectv(const float *r)
4487 {
4488  return nk_rect(r[0], r[1], r[2], r[3]);
4489 }
4490 
4491 NK_API struct nk_rect
4492 nk_rectiv(const int *r)
4493 {
4494  return nk_recti(r[0], r[1], r[2], r[3]);
4495 }
4496 
4497 NK_API struct nk_vec2
4498 nk_rect_pos(struct nk_rect r)
4499 {
4500  struct nk_vec2 ret;
4501  ret.x = r.x; ret.y = r.y;
4502  return ret;
4503 }
4504 
4505 NK_API struct nk_vec2
4506 nk_rect_size(struct nk_rect r)
4507 {
4508  struct nk_vec2 ret;
4509  ret.x = r.w; ret.y = r.h;
4510  return ret;
4511 }
4512 
4513 NK_INTERN struct nk_rect
4514 nk_shrink_rect(struct nk_rect r, float amount)
4515 {
4516  struct nk_rect res;
4517  r.w = NK_MAX(r.w, 2 * amount);
4518  r.h = NK_MAX(r.h, 2 * amount);
4519  res.x = r.x + amount;
4520  res.y = r.y + amount;
4521  res.w = r.w - 2 * amount;
4522  res.h = r.h - 2 * amount;
4523  return res;
4524 }
4525 
4526 NK_INTERN struct nk_rect
4527 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad)
4528 {
4529  r.w = NK_MAX(r.w, 2 * pad.x);
4530  r.h = NK_MAX(r.h, 2 * pad.y);
4531  r.x += pad.x; r.y += pad.y;
4532  r.w -= 2 * pad.x;
4533  r.h -= 2 * pad.y;
4534  return r;
4535 }
4536 
4537 NK_API struct nk_vec2
4538 nk_vec2(float x, float y)
4539 {
4540  struct nk_vec2 ret;
4541  ret.x = x; ret.y = y;
4542  return ret;
4543 }
4544 
4545 NK_API struct nk_vec2
4546 nk_vec2i(int x, int y)
4547 {
4548  struct nk_vec2 ret;
4549  ret.x = (float)x;
4550  ret.y = (float)y;
4551  return ret;
4552 }
4553 
4554 NK_API struct nk_vec2
4555 nk_vec2v(const float *v)
4556 {
4557  return nk_vec2(v[0], v[1]);
4558 }
4559 
4560 NK_API struct nk_vec2
4561 nk_vec2iv(const int *v)
4562 {
4563  return nk_vec2i(v[0], v[1]);
4564 }
4565 
4566 /*
4567  * ==============================================================
4568  *
4569  * UTIL
4570  *
4571  * ===============================================================
4572  */
4573 NK_INTERN int nk_str_match_here(const char *regexp, const char *text);
4574 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text);
4575 NK_INTERN int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);}
4576 NK_INTERN int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);}
4577 NK_INTERN int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;}
4578 NK_INTERN int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;}
4579 
4580 NK_INTERN void*
4581 nk_memcopy(void *dst0, const void *src0, nk_size length)
4582 {
4583  nk_ptr t;
4584  char *dst = (char*)dst0;
4585  const char *src = (const char*)src0;
4586  if (length == 0 || dst == src)
4587  goto done;
4588 
4589  #define nk_word int
4590  #define nk_wsize sizeof(nk_word)
4591  #define nk_wmask (nk_wsize-1)
4592  #define NK_TLOOP(s) if (t) NK_TLOOP1(s)
4593  #define NK_TLOOP1(s) do { s; } while (--t)
4594 
4595  if (dst < src) {
4596  t = (nk_ptr)src; /* only need low bits */
4597  if ((t | (nk_ptr)dst) & nk_wmask) {
4598  if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize)
4599  t = length;
4600  else
4601  t = nk_wsize - (t & nk_wmask);
4602  length -= t;
4603  NK_TLOOP1(*dst++ = *src++);
4604  }
4605  t = length / nk_wsize;
4606  NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src;
4607  src += nk_wsize; dst += nk_wsize);
4608  t = length & nk_wmask;
4609  NK_TLOOP(*dst++ = *src++);
4610  } else {
4611  src += length;
4612  dst += length;
4613  t = (nk_ptr)src;
4614  if ((t | (nk_ptr)dst) & nk_wmask) {
4615  if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize)
4616  t = length;
4617  else
4618  t &= nk_wmask;
4619  length -= t;
4620  NK_TLOOP1(*--dst = *--src);
4621  }
4622  t = length / nk_wsize;
4623  NK_TLOOP(src -= nk_wsize; dst -= nk_wsize;
4624  *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src);
4625  t = length & nk_wmask;
4626  NK_TLOOP(*--dst = *--src);
4627  }
4628  #undef nk_word
4629  #undef nk_wsize
4630  #undef nk_wmask
4631  #undef NK_TLOOP
4632  #undef NK_TLOOP1
4633 done:
4634  return (dst0);
4635 }
4636 
4637 NK_INTERN void
4638 nk_memset(void *ptr, int c0, nk_size size)
4639 {
4640  #define nk_word unsigned
4641  #define nk_wsize sizeof(nk_word)
4642  #define nk_wmask (nk_wsize - 1)
4643  nk_byte *dst = (nk_byte*)ptr;
4644  unsigned c = 0;
4645  nk_size t = 0;
4646 
4647  if ((c = (nk_byte)c0) != 0) {
4648  c = (c << 8) | c; /* at least 16-bits */
4649  if (sizeof(unsigned int) > 2)
4650  c = (c << 16) | c; /* at least 32-bits*/
4651  }
4652 
4653  /* too small of a word count */
4654  dst = (nk_byte*)ptr;
4655  if (size < 3 * nk_wsize) {
4656  while (size--) *dst++ = (nk_byte)c0;
4657  return;
4658  }
4659 
4660  /* align destination */
4661  if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) {
4662  t = nk_wsize -t;
4663  size -= t;
4664  do {
4665  *dst++ = (nk_byte)c0;
4666  } while (--t != 0);
4667  }
4668 
4669  /* fill word */
4670  t = size / nk_wsize;
4671  do {
4672  *(nk_word*)((void*)dst) = c;
4673  dst += nk_wsize;
4674  } while (--t != 0);
4675 
4676  /* fill trailing bytes */
4677  t = (size & nk_wmask);
4678  if (t != 0) {
4679  do {
4680  *dst++ = (nk_byte)c0;
4681  } while (--t != 0);
4682  }
4683 
4684  #undef nk_word
4685  #undef nk_wsize
4686  #undef nk_wmask
4687 }
4688 
4689 NK_INTERN void
4690 nk_zero(void *ptr, nk_size size)
4691 {
4692  NK_ASSERT(ptr);
4693  NK_MEMSET(ptr, 0, size);
4694 }
4695 
4696 NK_API int
4697 nk_strlen(const char *str)
4698 {
4699  int siz = 0;
4700  NK_ASSERT(str);
4701  while (str && *str++ != '\0') siz++;
4702  return siz;
4703 }
4704 
4705 NK_API int
4706 nk_strtoi(const char *str, const char **endptr)
4707 {
4708  int neg = 1;
4709  const char *p = str;
4710  int value = 0;
4711 
4712  NK_ASSERT(str);
4713  if (!str) return 0;
4714 
4715  /* skip whitespace */
4716  while (*p == ' ') p++;
4717  if (*p == '-') {
4718  neg = -1;
4719  p++;
4720  }
4721  while (*p && *p >= '0' && *p <= '9') {
4722  value = value * 10 + (int) (*p - '0');
4723  p++;
4724  }
4725  if (endptr)
4726  *endptr = p;
4727  return neg*value;
4728 }
4729 
4730 NK_API double
4731 nk_strtod(const char *str, const char **endptr)
4732 {
4733  double m;
4734  double neg = 1.0;
4735  const char *p = str;
4736  double value = 0;
4737  double number = 0;
4738 
4739  NK_ASSERT(str);
4740  if (!str) return 0;
4741 
4742  /* skip whitespace */
4743  while (*p == ' ') p++;
4744  if (*p == '-') {
4745  neg = -1.0;
4746  p++;
4747  }
4748 
4749  while (*p && *p != '.' && *p != 'e') {
4750  value = value * 10.0 + (double) (*p - '0');
4751  p++;
4752  }
4753 
4754  if (*p == '.') {
4755  p++;
4756  for(m = 0.1; *p && *p != 'e'; p++ ) {
4757  value = value + (double) (*p - '0') * m;
4758  m *= 0.1;
4759  }
4760  }
4761  if (*p == 'e') {
4762  int i, pow, div;
4763  p++;
4764  if (*p == '-') {
4765  div = nk_true;
4766  p++;
4767  } else if (*p == '+') {
4768  div = nk_false;
4769  p++;
4770  } else div = nk_false;
4771 
4772  for (pow = 0; *p; p++)
4773  pow = pow * 10 + (int) (*p - '0');
4774 
4775  for (m = 1.0, i = 0; i < pow; i++)
4776  m *= 10.0;
4777 
4778  if (div)
4779  value /= m;
4780  else value *= m;
4781  }
4782  number = value * neg;
4783  if (endptr)
4784  *endptr = p;
4785  return number;
4786 }
4787 
4788 NK_API float
4789 nk_strtof(const char *str, const char **endptr)
4790 {
4791  float float_value;
4792  double double_value;
4793  double_value = NK_STRTOD(str, endptr);
4794  float_value = (float)double_value;
4795  return float_value;
4796 }
4797 
4798 NK_API int
4799 nk_stricmp(const char *s1, const char *s2)
4800 {
4801  nk_int c1,c2,d;
4802  do {
4803  c1 = *s1++;
4804  c2 = *s2++;
4805  d = c1 - c2;
4806  while (d) {
4807  if (c1 <= 'Z' && c1 >= 'A') {
4808  d += ('a' - 'A');
4809  if (!d) break;
4810  }
4811  if (c2 <= 'Z' && c2 >= 'A') {
4812  d -= ('a' - 'A');
4813  if (!d) break;
4814  }
4815  return ((d >= 0) << 1) - 1;
4816  }
4817  } while (c1);
4818  return 0;
4819 }
4820 
4821 NK_API int
4822 nk_stricmpn(const char *s1, const char *s2, int n)
4823 {
4824  int c1,c2,d;
4825  NK_ASSERT(n >= 0);
4826  do {
4827  c1 = *s1++;
4828  c2 = *s2++;
4829  if (!n--) return 0;
4830 
4831  d = c1 - c2;
4832  while (d) {
4833  if (c1 <= 'Z' && c1 >= 'A') {
4834  d += ('a' - 'A');
4835  if (!d) break;
4836  }
4837  if (c2 <= 'Z' && c2 >= 'A') {
4838  d -= ('a' - 'A');
4839  if (!d) break;
4840  }
4841  return ((d >= 0) << 1) - 1;
4842  }
4843  } while (c1);
4844  return 0;
4845 }
4846 
4847 NK_INTERN int
4848 nk_str_match_here(const char *regexp, const char *text)
4849 {
4850  if (regexp[0] == '\0')
4851  return 1;
4852  if (regexp[1] == '*')
4853  return nk_str_match_star(regexp[0], regexp+2, text);
4854  if (regexp[0] == '$' && regexp[1] == '\0')
4855  return *text == '\0';
4856  if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text))
4857  return nk_str_match_here(regexp+1, text+1);
4858  return 0;
4859 }
4860 
4861 NK_INTERN int
4862 nk_str_match_star(int c, const char *regexp, const char *text)
4863 {
4864  do {/* a '* matches zero or more instances */
4865  if (nk_str_match_here(regexp, text))
4866  return 1;
4867  } while (*text != '\0' && (*text++ == c || c == '.'));
4868  return 0;
4869 }
4870 
4871 NK_API int
4872 nk_strfilter(const char *text, const char *regexp)
4873 {
4874  /*
4875  c matches any literal character c
4876  . matches any single character
4877  ^ matches the beginning of the input string
4878  $ matches the end of the input string
4879  * matches zero or more occurrences of the previous character*/
4880  if (regexp[0] == '^')
4881  return nk_str_match_here(regexp+1, text);
4882  do { /* must look even if string is empty */
4883  if (nk_str_match_here(regexp, text))
4884  return 1;
4885  } while (*text++ != '\0');
4886  return 0;
4887 }
4888 
4889 NK_API int
4890 nk_strmatch_fuzzy_text(const char *str, int str_len,
4891  const char *pattern, int *out_score)
4892 {
4893  /* Returns true if each character in pattern is found sequentially within str
4894  * if found then out_score is also set. Score value has no intrinsic meaning.
4895  * Range varies with pattern. Can only compare scores with same search pattern. */
4896 
4897  /* ------- scores --------- */
4898  /* bonus for adjacent matches */
4899  #define NK_ADJACENCY_BONUS 5
4900  /* bonus if match occurs after a separator */
4901  #define NK_SEPARATOR_BONUS 10
4902  /* bonus if match is uppercase and prev is lower */
4903  #define NK_CAMEL_BONUS 10
4904  /* penalty applied for every letter in str before the first match */
4905  #define NK_LEADING_LETTER_PENALTY (-3)
4906  /* maximum penalty for leading letters */
4907  #define NK_MAX_LEADING_LETTER_PENALTY (-9)
4908  /* penalty for every letter that doesn't matter */
4909  #define NK_UNMATCHED_LETTER_PENALTY (-1)
4910 
4911  /* loop variables */
4912  int score = 0;
4913  char const * pattern_iter = pattern;
4914  int str_iter = 0;
4915  int prev_matched = nk_false;
4916  int prev_lower = nk_false;
4917  /* true so if first letter match gets separator bonus*/
4918  int prev_separator = nk_true;
4919 
4920  /* use "best" matched letter if multiple string letters match the pattern */
4921  char const * best_letter = 0;
4922  int best_letter_score = 0;
4923 
4924  /* loop over strings */
4925  NK_ASSERT(str);
4926  NK_ASSERT(pattern);
4927  if (!str || !str_len || !pattern) return 0;
4928  while (str_iter < str_len)
4929  {
4930  const char pattern_letter = *pattern_iter;
4931  const char str_letter = str[str_iter];
4932 
4933  int next_match = *pattern_iter != '\0' &&
4934  nk_to_lower(pattern_letter) == nk_to_lower(str_letter);
4935  int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter);
4936 
4937  int advanced = next_match && best_letter;
4938  int pattern_repeat = best_letter && *pattern_iter != '\0';
4939  pattern_repeat = pattern_repeat &&
4940  nk_to_lower(*best_letter) == nk_to_lower(pattern_letter);
4941 
4942  if (advanced || pattern_repeat) {
4943  score += best_letter_score;
4944  best_letter = 0;
4945  best_letter_score = 0;
4946  }
4947 
4948  if (next_match || rematch)
4949  {
4950  int new_score = 0;
4951  /* Apply penalty for each letter before the first pattern match */
4952  if (pattern_iter == pattern) {
4953  int count = (int)(&str[str_iter] - str);
4954  int penalty = NK_LEADING_LETTER_PENALTY * count;
4955  if (penalty < NK_MAX_LEADING_LETTER_PENALTY)
4956  penalty = NK_MAX_LEADING_LETTER_PENALTY;
4957 
4958  score += penalty;
4959  }
4960 
4961  /* apply bonus for consecutive bonuses */
4962  if (prev_matched)
4963  new_score += NK_ADJACENCY_BONUS;
4964 
4965  /* apply bonus for matches after a separator */
4966  if (prev_separator)
4967  new_score += NK_SEPARATOR_BONUS;
4968 
4969  /* apply bonus across camel case boundaries */
4970  if (prev_lower && nk_is_upper(str_letter))
4971  new_score += NK_CAMEL_BONUS;
4972 
4973  /* update pattern iter IFF the next pattern letter was matched */
4974  if (next_match)
4975  ++pattern_iter;
4976 
4977  /* update best letter in str which may be for a "next" letter or a rematch */
4978  if (new_score >= best_letter_score) {
4979  /* apply penalty for now skipped letter */
4980  if (best_letter != 0)
4981  score += NK_UNMATCHED_LETTER_PENALTY;
4982 
4983  best_letter = &str[str_iter];
4984  best_letter_score = new_score;
4985  }
4986  prev_matched = nk_true;
4987  } else {
4988  score += NK_UNMATCHED_LETTER_PENALTY;
4989  prev_matched = nk_false;
4990  }
4991 
4992  /* separators should be more easily defined */
4993  prev_lower = nk_is_lower(str_letter) != 0;
4994  prev_separator = str_letter == '_' || str_letter == ' ';
4995 
4996  ++str_iter;
4997  }
4998 
4999  /* apply score for last match */
5000  if (best_letter)
5001  score += best_letter_score;
5002 
5003  /* did not match full pattern */
5004  if (*pattern_iter != '\0')
5005  return nk_false;
5006 
5007  if (out_score)
5008  *out_score = score;
5009  return nk_true;
5010 }
5011 
5012 NK_API int
5013 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
5014 {return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);}
5015 
5016 NK_INTERN int
5017 nk_string_float_limit(char *string, int prec)
5018 {
5019  int dot = 0;
5020  char *c = string;
5021  while (*c) {
5022  if (*c == '.') {
5023  dot = 1;
5024  c++;
5025  continue;
5026  }
5027  if (dot == (prec+1)) {
5028  *c = 0;
5029  break;
5030  }
5031  if (dot > 0) dot++;
5032  c++;
5033  }
5034  return (int)(c - string);
5035 }
5036 
5037 NK_INTERN double
5038 nk_pow(double x, int n)
5039 {
5040  /* check the sign of n */
5041  double r = 1;
5042  int plus = n >= 0;
5043  n = (plus) ? n : -n;
5044  while (n > 0) {
5045  if ((n & 1) == 1)
5046  r *= x;
5047  n /= 2;
5048  x *= x;
5049  }
5050  return plus ? r : 1.0 / r;
5051 }
5052 
5053 NK_INTERN int
5054 nk_ifloord(double x)
5055 {
5056  x = (double)((int)x - ((x < 0.0) ? 1 : 0));
5057  return (int)x;
5058 }
5059 
5060 NK_INTERN int
5061 nk_ifloorf(float x)
5062 {
5063  x = (float)((int)x - ((x < 0.0f) ? 1 : 0));
5064  return (int)x;
5065 }
5066 
5067 NK_INTERN int
5068 nk_iceilf(float x)
5069 {
5070  if (x >= 0) {
5071  int i = (int)x;
5072  return (x > i) ? i+1: i;
5073  } else {
5074  int t = (int)x;
5075  float r = x - (float)t;
5076  return (r > 0.0f) ? t+1: t;
5077  }
5078 }
5079 
5080 NK_INTERN int
5081 nk_log10(double n)
5082 {
5083  int neg;
5084  int ret;
5085  int exp = 0;
5086 
5087  neg = (n < 0) ? 1 : 0;
5088  ret = (neg) ? (int)-n : (int)n;
5089  while ((ret / 10) > 0) {
5090  ret /= 10;
5091  exp++;
5092  }
5093  if (neg) exp = -exp;
5094  return exp;
5095 }
5096 
5097 NK_INTERN void
5098 nk_strrev_ascii(char *s)
5099 {
5100  int len = nk_strlen(s);
5101  int end = len / 2;
5102  int i = 0;
5103  char t;
5104  for (; i < end; ++i) {
5105  t = s[i];
5106  s[i] = s[len - 1 - i];
5107  s[len -1 - i] = t;
5108  }
5109 }
5110 
5111 NK_INTERN char*
5112 nk_itoa(char *s, long n)
5113 {
5114  long i = 0;
5115  if (n == 0) {
5116  s[i++] = '0';
5117  s[i] = 0;
5118  return s;
5119  }
5120  if (n < 0) {
5121  s[i++] = '-';
5122  n = -n;
5123  }
5124  while (n > 0) {
5125  s[i++] = (char)('0' + (n % 10));
5126  n /= 10;
5127  }
5128  s[i] = 0;
5129  if (s[0] == '-')
5130  ++s;
5131 
5132  nk_strrev_ascii(s);
5133  return s;
5134 }
5135 
5136 NK_INTERN char*
5137 nk_dtoa(char *s, double n)
5138 {
5139  int useExp = 0;
5140  int digit = 0, m = 0, m1 = 0;
5141  char *c = s;
5142  int neg = 0;
5143 
5144  NK_ASSERT(s);
5145  if (!s) return 0;
5146 
5147  if (n == 0.0) {
5148  s[0] = '0'; s[1] = '\0';
5149  return s;
5150  }
5151 
5152  neg = (n < 0);
5153  if (neg) n = -n;
5154 
5155  /* calculate magnitude */
5156  m = nk_log10(n);
5157  useExp = (m >= 14 || (neg && m >= 9) || m <= -9);
5158  if (neg) *(c++) = '-';
5159 
5160  /* set up for scientific notation */
5161  if (useExp) {
5162  if (m < 0)
5163  m -= 1;
5164  n = n / (double)nk_pow(10.0, m);
5165  m1 = m;
5166  m = 0;
5167  }
5168  if (m < 1.0) {
5169  m = 0;
5170  }
5171 
5172  /* convert the number */
5173  while (n > NK_FLOAT_PRECISION || m >= 0) {
5174  double weight = nk_pow(10.0, m);
5175  if (weight > 0) {
5176  double t = (double)n / weight;
5177  digit = nk_ifloord(t);
5178  n -= ((double)digit * weight);
5179  *(c++) = (char)('0' + (char)digit);
5180  }
5181  if (m == 0 && n > 0)
5182  *(c++) = '.';
5183  m--;
5184  }
5185 
5186  if (useExp) {
5187  /* convert the exponent */
5188  int i, j;
5189  *(c++) = 'e';
5190  if (m1 > 0) {
5191  *(c++) = '+';
5192  } else {
5193  *(c++) = '-';
5194  m1 = -m1;
5195  }
5196  m = 0;
5197  while (m1 > 0) {
5198  *(c++) = (char)('0' + (char)(m1 % 10));
5199  m1 /= 10;
5200  m++;
5201  }
5202  c -= m;
5203  for (i = 0, j = m-1; i<j; i++, j--) {
5204  /* swap without temporary */
5205  c[i] ^= c[j];
5206  c[j] ^= c[i];
5207  c[i] ^= c[j];
5208  }
5209  c += m;
5210  }
5211  *(c) = '\0';
5212  return s;
5213 }
5214 
5215 #ifdef NK_INCLUDE_STANDARD_VARARGS
5216 #ifndef NK_INCLUDE_STANDARD_IO
5217 static int
5218 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args)
5219 {
5220  enum nk_arg_type {
5221  NK_ARG_TYPE_CHAR,
5222  NK_ARG_TYPE_SHORT,
5223  NK_ARG_TYPE_DEFAULT,
5224  NK_ARG_TYPE_LONG
5225  };
5226  enum nk_arg_flags {
5227  NK_ARG_FLAG_LEFT = 0x01,
5228  NK_ARG_FLAG_PLUS = 0x02,
5229  NK_ARG_FLAG_SPACE = 0x04,
5230  NK_ARG_FLAG_NUM = 0x10,
5231  NK_ARG_FLAG_ZERO = 0x20
5232  };
5233 
5234  char number_buffer[NK_MAX_NUMBER_BUFFER];
5235  enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT;
5236  int precision = NK_DEFAULT;
5237  int width = NK_DEFAULT;
5238  nk_flags flag = 0;
5239 
5240  int len = 0;
5241  int result = -1;
5242  const char *iter = fmt;
5243 
5244  NK_ASSERT(buf);
5245  NK_ASSERT(buf_size);
5246  if (!buf || !buf_size || !fmt) return 0;
5247  for (iter = fmt; *iter && len < buf_size; iter++) {
5248  /* copy all non-format characters */
5249  while (*iter && (*iter != '%') && (len < buf_size))
5250  buf[len++] = *iter++;
5251  if (!(*iter) || len >= buf_size) break;
5252  iter++;
5253 
5254  /* flag arguments */
5255  while (*iter) {
5256  if (*iter == '-') flag |= NK_ARG_FLAG_LEFT;
5257  else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS;
5258  else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE;
5259  else if (*iter == '#') flag |= NK_ARG_FLAG_NUM;
5260  else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO;
5261  else break;
5262  iter++;
5263  }
5264 
5265  /* width argument */
5266  width = NK_DEFAULT;
5267  if (*iter >= '1' && *iter <= '9') {
5268  const char *end;
5269  width = nk_strtoi(iter, &end);
5270  if (end == iter)
5271  width = -1;
5272  else iter = end;
5273  } else if (*iter == '*') {
5274  width = va_arg(args, int);
5275  iter++;
5276  }
5277 
5278  /* precision argument */
5279  precision = NK_DEFAULT;
5280  if (*iter == '.') {
5281  iter++;
5282  if (*iter == '*') {
5283  precision = va_arg(args, int);
5284  iter++;
5285  } else {
5286  const char *end;
5287  precision = nk_strtoi(iter, &end);
5288  if (end == iter)
5289  precision = -1;
5290  else iter = end;
5291  }
5292  }
5293 
5294  /* length modifier */
5295  if (*iter == 'h') {
5296  if (*(iter+1) == 'h') {
5297  arg_type = NK_ARG_TYPE_CHAR;
5298  iter++;
5299  } else arg_type = NK_ARG_TYPE_SHORT;
5300  iter++;
5301  } else if (*iter == 'l') {
5302  arg_type = NK_ARG_TYPE_LONG;
5303  iter++;
5304  } else arg_type = NK_ARG_TYPE_DEFAULT;
5305 
5306  /* specifier */
5307  if (*iter == '%') {
5308  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5309  NK_ASSERT(precision == NK_DEFAULT);
5310  NK_ASSERT(width == NK_DEFAULT);
5311  if (len < buf_size)
5312  buf[len++] = '%';
5313  } else if (*iter == 's') {
5314  /* string */
5315  const char *str = va_arg(args, const char*);
5316  NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!");
5317  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5318  NK_ASSERT(precision == NK_DEFAULT);
5319  NK_ASSERT(width == NK_DEFAULT);
5320  if (str == buf) return -1;
5321  while (str && *str && len < buf_size)
5322  buf[len++] = *str++;
5323  } else if (*iter == 'n') {
5324  /* current length callback */
5325  signed int *n = va_arg(args, int*);
5326  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5327  NK_ASSERT(precision == NK_DEFAULT);
5328  NK_ASSERT(width == NK_DEFAULT);
5329  if (n) *n = len;
5330  } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') {
5331  /* signed integer */
5332  long value = 0;
5333  const char *num_iter;
5334  int num_len, num_print, padding;
5335  int cur_precision = NK_MAX(precision, 1);
5336  int cur_width = NK_MAX(width, 0);
5337 
5338  /* retrieve correct value type */
5339  if (arg_type == NK_ARG_TYPE_CHAR)
5340  value = (signed char)va_arg(args, int);
5341  else if (arg_type == NK_ARG_TYPE_SHORT)
5342  value = (signed short)va_arg(args, int);
5343  else if (arg_type == NK_ARG_TYPE_LONG)
5344  value = va_arg(args, signed long);
5345  else if (*iter == 'c')
5346  value = (unsigned char)va_arg(args, int);
5347  else value = va_arg(args, signed int);
5348 
5349  /* convert number to string */
5350  nk_itoa(number_buffer, value);
5351  num_len = nk_strlen(number_buffer);
5352  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
5353  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
5354  padding = NK_MAX(padding-1, 0);
5355 
5356  /* fill left padding up to a total of `width` characters */
5357  if (!(flag & NK_ARG_FLAG_LEFT)) {
5358  while (padding-- > 0 && (len < buf_size)) {
5359  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
5360  buf[len++] = '0';
5361  else buf[len++] = ' ';
5362  }
5363  }
5364 
5365  /* copy string value representation into buffer */
5366  if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size)
5367  buf[len++] = '+';
5368  else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size)
5369  buf[len++] = ' ';
5370 
5371  /* fill up to precision number of digits with '0' */
5372  num_print = NK_MAX(cur_precision, num_len);
5373  while (precision && (num_print > num_len) && (len < buf_size)) {
5374  buf[len++] = '0';
5375  num_print--;
5376  }
5377 
5378  /* copy string value representation into buffer */
5379  num_iter = number_buffer;
5380  while (precision && *num_iter && len < buf_size)
5381  buf[len++] = *num_iter++;
5382 
5383  /* fill right padding up to width characters */
5384  if (flag & NK_ARG_FLAG_LEFT) {
5385  while ((padding-- > 0) && (len < buf_size))
5386  buf[len++] = ' ';
5387  }
5388  } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') {
5389  /* unsigned integer */
5390  unsigned long value = 0;
5391  int num_len = 0, num_print, padding = 0;
5392  int cur_precision = NK_MAX(precision, 1);
5393  int cur_width = NK_MAX(width, 0);
5394  unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16;
5395 
5396  /* print oct/hex/dec value */
5397  const char *upper_output_format = "0123456789ABCDEF";
5398  const char *lower_output_format = "0123456789abcdef";
5399  const char *output_format = (*iter == 'x') ?
5400  lower_output_format: upper_output_format;
5401 
5402  /* retrieve correct value type */
5403  if (arg_type == NK_ARG_TYPE_CHAR)
5404  value = (unsigned char)va_arg(args, int);
5405  else if (arg_type == NK_ARG_TYPE_SHORT)
5406  value = (unsigned short)va_arg(args, int);
5407  else if (arg_type == NK_ARG_TYPE_LONG)
5408  value = va_arg(args, unsigned long);
5409  else value = va_arg(args, unsigned int);
5410 
5411  do {
5412  /* convert decimal number into hex/oct number */
5413  int digit = output_format[value % base];
5414  if (num_len < NK_MAX_NUMBER_BUFFER)
5415  number_buffer[num_len++] = (char)digit;
5416  value /= base;
5417  } while (value > 0);
5418 
5419  num_print = NK_MAX(cur_precision, num_len);
5420  padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0);
5421  if (flag & NK_ARG_FLAG_NUM)
5422  padding = NK_MAX(padding-1, 0);
5423 
5424  /* fill left padding up to a total of `width` characters */
5425  if (!(flag & NK_ARG_FLAG_LEFT)) {
5426  while ((padding-- > 0) && (len < buf_size)) {
5427  if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT))
5428  buf[len++] = '0';
5429  else buf[len++] = ' ';
5430  }
5431  }
5432 
5433  /* fill up to precision number of digits */
5434  if (num_print && (flag & NK_ARG_FLAG_NUM)) {
5435  if ((*iter == 'o') && (len < buf_size)) {
5436  buf[len++] = '0';
5437  } else if ((*iter == 'x') && ((len+1) < buf_size)) {
5438  buf[len++] = '0';
5439  buf[len++] = 'x';
5440  } else if ((*iter == 'X') && ((len+1) < buf_size)) {
5441  buf[len++] = '0';
5442  buf[len++] = 'X';
5443  }
5444  }
5445  while (precision && (num_print > num_len) && (len < buf_size)) {
5446  buf[len++] = '0';
5447  num_print--;
5448  }
5449 
5450  /* reverse number direction */
5451  while (num_len > 0) {
5452  if (precision && (len < buf_size))
5453  buf[len++] = number_buffer[num_len-1];
5454  num_len--;
5455  }
5456 
5457  /* fill right padding up to width characters */
5458  if (flag & NK_ARG_FLAG_LEFT) {
5459  while ((padding-- > 0) && (len < buf_size))
5460  buf[len++] = ' ';
5461  }
5462  } else if (*iter == 'f') {
5463  /* floating point */
5464  const char *num_iter;
5465  int cur_precision = (precision < 0) ? 6: precision;
5466  int prefix, cur_width = NK_MAX(width, 0);
5467  double value = va_arg(args, double);
5468  int num_len = 0, frac_len = 0, dot = 0;
5469  int padding = 0;
5470 
5471  NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT);
5472  NK_DTOA(number_buffer, value);
5473  num_len = nk_strlen(number_buffer);
5474 
5475  /* calculate padding */
5476  num_iter = number_buffer;
5477  while (*num_iter && *num_iter != '.')
5478  num_iter++;
5479 
5480  prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0;
5481  padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0);
5482  if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE))
5483  padding = NK_MAX(padding-1, 0);
5484 
5485  /* fill left padding up to a total of `width` characters */
5486  if (!(flag & NK_ARG_FLAG_LEFT)) {
5487  while (padding-- > 0 && (len < buf_size)) {
5488  if (flag & NK_ARG_FLAG_ZERO)
5489  buf[len++] = '0';
5490  else buf[len++] = ' ';
5491  }
5492  }
5493 
5494  /* copy string value representation into buffer */
5495  num_iter = number_buffer;
5496  if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size))
5497  buf[len++] = '+';
5498  else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size))
5499  buf[len++] = ' ';
5500  while (*num_iter) {
5501  if (dot) frac_len++;
5502  if (len < buf_size)
5503  buf[len++] = *num_iter;
5504  if (*num_iter == '.') dot = 1;
5505  if (frac_len >= cur_precision) break;
5506  num_iter++;
5507  }
5508 
5509  /* fill number up to precision */
5510  while (frac_len < cur_precision) {
5511  if (!dot && len < buf_size) {
5512  buf[len++] = '.';
5513  dot = 1;
5514  }
5515  if (len < buf_size)
5516  buf[len++] = '0';
5517  frac_len++;
5518  }
5519 
5520  /* fill right padding up to width characters */
5521  if (flag & NK_ARG_FLAG_LEFT) {
5522  while ((padding-- > 0) && (len < buf_size))
5523  buf[len++] = ' ';
5524  }
5525  } else {
5526  /* Specifier not supported: g,G,e,E,p,z */
5527  NK_ASSERT(0 && "specifier is not supported!");
5528  return result;
5529  }
5530  }
5531  buf[(len >= buf_size)?(buf_size-1):len] = 0;
5532  result = (len >= buf_size)?-1:len;
5533  return result;
5534 }
5535 #endif
5536 
5537 NK_INTERN int
5538 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args)
5539 {
5540  int result = -1;
5541  NK_ASSERT(buf);
5542  NK_ASSERT(buf_size);
5543  if (!buf || !buf_size || !fmt) return 0;
5544 #ifdef NK_INCLUDE_STANDARD_IO
5545  result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args);
5546  result = (result >= buf_size) ? -1: result;
5547  buf[buf_size-1] = 0;
5548 #else
5549  result = nk_vsnprintf(buf, buf_size, fmt, args);
5550 #endif
5551  return result;
5552 }
5553 #endif
5554 
5556 nk_murmur_hash(const void * key, int len, nk_hash seed)
5557 {
5558  /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/
5559  #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r)))
5560  union {const nk_uint *i; const nk_byte *b;} conv = {0};
5561  const nk_byte *data = (const nk_byte*)key;
5562  const int nblocks = len/4;
5563  nk_uint h1 = seed;
5564  const nk_uint c1 = 0xcc9e2d51;
5565  const nk_uint c2 = 0x1b873593;
5566  const nk_byte *tail;
5567  const nk_uint *blocks;
5568  nk_uint k1;
5569  int i;
5570 
5571  /* body */
5572  if (!key) return 0;
5573  conv.b = (data + nblocks*4);
5574  blocks = (const nk_uint*)conv.i;
5575  for (i = -nblocks; i; ++i) {
5576  k1 = blocks[i];
5577  k1 *= c1;
5578  k1 = NK_ROTL(k1,15);
5579  k1 *= c2;
5580 
5581  h1 ^= k1;
5582  h1 = NK_ROTL(h1,13);
5583  h1 = h1*5+0xe6546b64;
5584  }
5585 
5586  /* tail */
5587  tail = (const nk_byte*)(data + nblocks*4);
5588  k1 = 0;
5589  switch (len & 3) {
5590  case 3: k1 ^= (nk_uint)(tail[2] << 16);
5591  case 2: k1 ^= (nk_uint)(tail[1] << 8u);
5592  case 1: k1 ^= tail[0];
5593  k1 *= c1;
5594  k1 = NK_ROTL(k1,15);
5595  k1 *= c2;
5596  h1 ^= k1;
5597  default: break;
5598  }
5599 
5600  /* finalization */
5601  h1 ^= (nk_uint)len;
5602  /* fmix32 */
5603  h1 ^= h1 >> 16;
5604  h1 *= 0x85ebca6b;
5605  h1 ^= h1 >> 13;
5606  h1 *= 0xc2b2ae35;
5607  h1 ^= h1 >> 16;
5608 
5609  #undef NK_ROTL
5610  return h1;
5611 }
5612 
5613 #ifdef NK_INCLUDE_STANDARD_IO
5614 NK_INTERN char*
5615 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc)
5616 {
5617  char *buf;
5618  FILE *fd;
5619  long ret;
5620 
5621  NK_ASSERT(path);
5622  NK_ASSERT(siz);
5623  NK_ASSERT(alloc);
5624  if (!path || !siz || !alloc)
5625  return 0;
5626 
5627  fd = fopen(path, "rb");
5628  if (!fd) return 0;
5629  fseek(fd, 0, SEEK_END);
5630  ret = ftell(fd);
5631  if (ret < 0) {
5632  fclose(fd);
5633  return 0;
5634  }
5635  *siz = (nk_size)ret;
5636  fseek(fd, 0, SEEK_SET);
5637  buf = (char*)alloc->alloc(alloc->userdata,0, *siz);
5638  NK_ASSERT(buf);
5639  if (!buf) {
5640  fclose(fd);
5641  return 0;
5642  }
5643  *siz = (nk_size)fread(buf, *siz, 1, fd);
5644  fclose(fd);
5645  return buf;
5646 }
5647 #endif
5648 
5649 /*
5650  * ==============================================================
5651  *
5652  * COLOR
5653  *
5654  * ===============================================================
5655  */
5656 NK_INTERN int
5657 nk_parse_hex(const char *p, int length)
5658 {
5659  int i = 0;
5660  int len = 0;
5661  while (len < length) {
5662  i <<= 4;
5663  if (p[len] >= 'a' && p[len] <= 'f')
5664  i += ((p[len] - 'a') + 10);
5665  else if (p[len] >= 'A' && p[len] <= 'F')
5666  i += ((p[len] - 'A') + 10);
5667  else i += (p[len] - '0');
5668  len++;
5669  }
5670  return i;
5671 }
5672 
5673 NK_API struct nk_color
5674 nk_rgba(int r, int g, int b, int a)
5675 {
5676  struct nk_color ret;
5677  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
5678  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
5679  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
5680  ret.a = (nk_byte)NK_CLAMP(0, a, 255);
5681  return ret;
5682 }
5683 
5684 NK_API struct nk_color
5685 nk_rgb_hex(const char *rgb)
5686 {
5687  struct nk_color col;
5688  const char *c = rgb;
5689  if (*c == '#') c++;
5690  col.r = (nk_byte)nk_parse_hex(c, 2);
5691  col.g = (nk_byte)nk_parse_hex(c+2, 2);
5692  col.b = (nk_byte)nk_parse_hex(c+4, 2);
5693  col.a = 255;
5694  return col;
5695 }
5696 
5697 NK_API struct nk_color
5698 nk_rgba_hex(const char *rgb)
5699 {
5700  struct nk_color col;
5701  const char *c = rgb;
5702  if (*c == '#') c++;
5703  col.r = (nk_byte)nk_parse_hex(c, 2);
5704  col.g = (nk_byte)nk_parse_hex(c+2, 2);
5705  col.b = (nk_byte)nk_parse_hex(c+4, 2);
5706  col.a = (nk_byte)nk_parse_hex(c+6, 2);
5707  return col;
5708 }
5709 
5710 NK_API void
5711 nk_color_hex_rgba(char *output, struct nk_color col)
5712 {
5713  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
5714  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
5715  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
5716  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
5717  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
5718  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
5719  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
5720  output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4);
5721  output[7] = (char)NK_TO_HEX((col.a & 0x0F));
5722  output[8] = '\0';
5723  #undef NK_TO_HEX
5724 }
5725 
5726 NK_API void
5727 nk_color_hex_rgb(char *output, struct nk_color col)
5728 {
5729  #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i))
5730  output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4);
5731  output[1] = (char)NK_TO_HEX((col.r & 0x0F));
5732  output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4);
5733  output[3] = (char)NK_TO_HEX((col.g & 0x0F));
5734  output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4);
5735  output[5] = (char)NK_TO_HEX((col.b & 0x0F));
5736  output[6] = '\0';
5737  #undef NK_TO_HEX
5738 }
5739 
5740 NK_API struct nk_color
5741 nk_rgba_iv(const int *c)
5742 {
5743  return nk_rgba(c[0], c[1], c[2], c[3]);
5744 }
5745 
5746 NK_API struct nk_color
5748 {
5749  return nk_rgba(c[0], c[1], c[2], c[3]);
5750 }
5751 
5752 NK_API struct nk_color
5753 nk_rgb(int r, int g, int b)
5754 {
5755  struct nk_color ret;
5756  ret.r = (nk_byte)NK_CLAMP(0, r, 255);
5757  ret.g = (nk_byte)NK_CLAMP(0, g, 255);
5758  ret.b = (nk_byte)NK_CLAMP(0, b, 255);
5759  ret.a = (nk_byte)255;
5760  return ret;
5761 }
5762 
5763 NK_API struct nk_color
5764 nk_rgb_iv(const int *c)
5765 {
5766  return nk_rgb(c[0], c[1], c[2]);
5767 }
5768 
5769 NK_API struct nk_color
5771 {
5772  return nk_rgb(c[0], c[1], c[2]);
5773 }
5774 
5775 NK_API struct nk_color
5777 {
5778  struct nk_color ret;
5779  ret.r = (in & 0xFF);
5780  ret.g = ((in >> 8) & 0xFF);
5781  ret.b = ((in >> 16) & 0xFF);
5782  ret.a = (nk_byte)((in >> 24) & 0xFF);
5783  return ret;
5784 }
5785 
5786 NK_API struct nk_color
5787 nk_rgba_f(float r, float g, float b, float a)
5788 {
5789  struct nk_color ret;
5790  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
5791  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
5792  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
5793  ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f);
5794  return ret;
5795 }
5796 
5797 NK_API struct nk_color
5798 nk_rgba_fv(const float *c)
5799 {
5800  return nk_rgba_f(c[0], c[1], c[2], c[3]);
5801 }
5802 
5803 NK_API struct nk_color
5804 nk_rgb_f(float r, float g, float b)
5805 {
5806  struct nk_color ret;
5807  ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f);
5808  ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f);
5809  ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f);
5810  ret.a = 255;
5811  return ret;
5812 }
5813 
5814 NK_API struct nk_color
5815 nk_rgb_fv(const float *c)
5816 {
5817  return nk_rgb_f(c[0], c[1], c[2]);
5818 }
5819 
5820 NK_API struct nk_color
5821 nk_hsv(int h, int s, int v)
5822 {
5823  return nk_hsva(h, s, v, 255);
5824 }
5825 
5826 NK_API struct nk_color
5827 nk_hsv_iv(const int *c)
5828 {
5829  return nk_hsv(c[0], c[1], c[2]);
5830 }
5831 
5832 NK_API struct nk_color
5834 {
5835  return nk_hsv(c[0], c[1], c[2]);
5836 }
5837 
5838 NK_API struct nk_color
5839 nk_hsv_f(float h, float s, float v)
5840 {
5841  return nk_hsva_f(h, s, v, 1.0f);
5842 }
5843 
5844 NK_API struct nk_color
5845 nk_hsv_fv(const float *c)
5846 {
5847  return nk_hsv_f(c[0], c[1], c[2]);
5848 }
5849 
5850 NK_API struct nk_color
5851 nk_hsva(int h, int s, int v, int a)
5852 {
5853  float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f;
5854  float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f;
5855  float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f;
5856  float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f;
5857  return nk_hsva_f(hf, sf, vf, af);
5858 }
5859 
5860 NK_API struct nk_color
5861 nk_hsva_iv(const int *c)
5862 {
5863  return nk_hsva(c[0], c[1], c[2], c[3]);
5864 }
5865 
5866 NK_API struct nk_color
5868 {
5869  return nk_hsva(c[0], c[1], c[2], c[3]);
5870 }
5871 
5872 NK_API struct nk_color
5873 nk_hsva_f(float h, float s, float v, float a)
5874 {
5875  struct nk_colorf out = {0,0,0,0};
5876  float p, q, t, f;
5877  int i;
5878 
5879  if (s <= 0.0f) {
5880  out.r = v; out.g = v; out.b = v;
5881  return nk_rgb_f(out.r, out.g, out.b);
5882  }
5883 
5884  h = h / (60.0f/360.0f);
5885  i = (int)h;
5886  f = h - (float)i;
5887  p = v * (1.0f - s);
5888  q = v * (1.0f - (s * f));
5889  t = v * (1.0f - s * (1.0f - f));
5890 
5891  switch (i) {
5892  case 0: default: out.r = v; out.g = t; out.b = p; break;
5893  case 1: out.r = q; out.g = v; out.b = p; break;
5894  case 2: out.r = p; out.g = v; out.b = t; break;
5895  case 3: out.r = p; out.g = q; out.b = v; break;
5896  case 4: out.r = t; out.g = p; out.b = v; break;
5897  case 5: out.r = v; out.g = p; out.b = q; break;
5898  }
5899  return nk_rgba_f(out.r, out.g, out.b, a);
5900 }
5901 
5902 NK_API struct nk_color
5903 nk_hsva_fv(const float *c)
5904 {
5905  return nk_hsva_f(c[0], c[1], c[2], c[3]);
5906 }
5907 
5909 nk_color_u32(struct nk_color in)
5910 {
5911  nk_uint out = (nk_uint)in.r;
5912  out |= ((nk_uint)in.g << 8);
5913  out |= ((nk_uint)in.b << 16);
5914  out |= ((nk_uint)in.a << 24);
5915  return out;
5916 }
5917 
5918 NK_API void
5919 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in)
5920 {
5921  NK_STORAGE const float s = 1.0f/255.0f;
5922  *r = (float)in.r * s;
5923  *g = (float)in.g * s;
5924  *b = (float)in.b * s;
5925  *a = (float)in.a * s;
5926 }
5927 
5928 NK_API void
5929 nk_color_fv(float *c, struct nk_color in)
5930 {
5931  nk_color_f(&c[0], &c[1], &c[2], &c[3], in);
5932 }
5933 
5934 NK_API void
5935 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in)
5936 {
5937  NK_STORAGE const double s = 1.0/255.0;
5938  *r = (double)in.r * s;
5939  *g = (double)in.g * s;
5940  *b = (double)in.b * s;
5941  *a = (double)in.a * s;
5942 }
5943 
5944 NK_API void
5945 nk_color_dv(double *c, struct nk_color in)
5946 {
5947  nk_color_d(&c[0], &c[1], &c[2], &c[3], in);
5948 }
5949 
5950 NK_API void
5951 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in)
5952 {
5953  float a;
5954  nk_color_hsva_f(out_h, out_s, out_v, &a, in);
5955 }
5956 
5957 NK_API void
5958 nk_color_hsv_fv(float *out, struct nk_color in)
5959 {
5960  float a;
5961  nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in);
5962 }
5963 
5964 NK_API void
5965 nk_color_hsva_f(float *out_h, float *out_s,
5966  float *out_v, float *out_a, struct nk_color in)
5967 {
5968  float chroma;
5969  float K = 0.0f;
5970  float r,g,b,a;
5971 
5972  nk_color_f(&r,&g,&b,&a, in);
5973  if (g < b) {
5974  const float t = g; g = b; b = t;
5975  K = -1.f;
5976  }
5977  if (r < g) {
5978  const float t = r; r = g; g = t;
5979  K = -2.f/6.0f - K;
5980  }
5981  chroma = r - ((g < b) ? g: b);
5982  *out_h = NK_ABS(K + (g - b)/(6.0f * chroma + 1e-20f));
5983  *out_s = chroma / (r + 1e-20f);
5984  *out_v = r;
5985  *out_a = (float)in.a / 255.0f;
5986 }
5987 
5988 NK_API void
5989 nk_color_hsva_fv(float *out, struct nk_color in)
5990 {
5991  nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in);
5992 }
5993 
5994 NK_API void
5995 nk_color_hsva_i(int *out_h, int *out_s, int *out_v,
5996  int *out_a, struct nk_color in)
5997 {
5998  float h,s,v,a;
5999  nk_color_hsva_f(&h, &s, &v, &a, in);
6000  *out_h = (nk_byte)(h * 255.0f);
6001  *out_s = (nk_byte)(s * 255.0f);
6002  *out_v = (nk_byte)(v * 255.0f);
6003  *out_a = (nk_byte)(a * 255.0f);
6004 }
6005 
6006 NK_API void
6007 nk_color_hsva_iv(int *out, struct nk_color in)
6008 {
6009  nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in);
6010 }
6011 
6012 NK_API void
6014 {
6015  int tmp[4];
6016  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
6017  out[0] = (nk_byte)tmp[0];
6018  out[1] = (nk_byte)tmp[1];
6019  out[2] = (nk_byte)tmp[2];
6020  out[3] = (nk_byte)tmp[3];
6021 }
6022 
6023 NK_API void
6025 {
6026  int tmp[4];
6027  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
6028  *h = (nk_byte)tmp[0];
6029  *s = (nk_byte)tmp[1];
6030  *v = (nk_byte)tmp[2];
6031  *a = (nk_byte)tmp[3];
6032 }
6033 
6034 NK_API void
6035 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in)
6036 {
6037  int a;
6038  nk_color_hsva_i(out_h, out_s, out_v, &a, in);
6039 }
6040 
6041 NK_API void
6042 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in)
6043 {
6044  int tmp[4];
6045  nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in);
6046  *out_h = (nk_byte)tmp[0];
6047  *out_s = (nk_byte)tmp[1];
6048  *out_v = (nk_byte)tmp[2];
6049 }
6050 
6051 NK_API void
6052 nk_color_hsv_iv(int *out, struct nk_color in)
6053 {
6054  nk_color_hsv_i(&out[0], &out[1], &out[2], in);
6055 }
6056 
6057 NK_API void
6059 {
6060  int tmp[4];
6061  nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in);
6062  out[0] = (nk_byte)tmp[0];
6063  out[1] = (nk_byte)tmp[1];
6064  out[2] = (nk_byte)tmp[2];
6065 }
6066 /*
6067  * ==============================================================
6068  *
6069  * IMAGE
6070  *
6071  * ===============================================================
6072  */
6074 nk_handle_ptr(void *ptr)
6075 {
6076  nk_handle handle = {0};
6077  handle.ptr = ptr;
6078  return handle;
6079 }
6080 
6082 nk_handle_id(int id)
6083 {
6084  nk_handle handle;
6085  nk_zero_struct(handle);
6086  handle.id = id;
6087  return handle;
6088 }
6089 
6090 NK_API struct nk_image
6091 nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r)
6092 {
6093  struct nk_image s;
6094  nk_zero(&s, sizeof(s));
6095  s.handle.ptr = ptr;
6096  s.w = w; s.h = h;
6097  s.region[0] = (unsigned short)r.x;
6098  s.region[1] = (unsigned short)r.y;
6099  s.region[2] = (unsigned short)r.w;
6100  s.region[3] = (unsigned short)r.h;
6101  return s;
6102 }
6103 
6104 NK_API struct nk_image
6105 nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r)
6106 {
6107  struct nk_image s;
6108  nk_zero(&s, sizeof(s));
6109  s.handle.id = id;
6110  s.w = w; s.h = h;
6111  s.region[0] = (unsigned short)r.x;
6112  s.region[1] = (unsigned short)r.y;
6113  s.region[2] = (unsigned short)r.w;
6114  s.region[3] = (unsigned short)r.h;
6115  return s;
6116 }
6117 
6118 NK_API struct nk_image
6119 nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h,
6120  struct nk_rect r)
6121 {
6122  struct nk_image s;
6123  nk_zero(&s, sizeof(s));
6124  s.handle = handle;
6125  s.w = w; s.h = h;
6126  s.region[0] = (unsigned short)r.x;
6127  s.region[1] = (unsigned short)r.y;
6128  s.region[2] = (unsigned short)r.w;
6129  s.region[3] = (unsigned short)r.h;
6130  return s;
6131 }
6132 
6133 NK_API struct nk_image
6135 {
6136  struct nk_image s;
6137  nk_zero(&s, sizeof(s));
6138  s.handle = handle;
6139  s.w = 0; s.h = 0;
6140  s.region[0] = 0;
6141  s.region[1] = 0;
6142  s.region[2] = 0;
6143  s.region[3] = 0;
6144  return s;
6145 }
6146 
6147 NK_API struct nk_image
6149 {
6150  struct nk_image s;
6151  nk_zero(&s, sizeof(s));
6152  NK_ASSERT(ptr);
6153  s.handle.ptr = ptr;
6154  s.w = 0; s.h = 0;
6155  s.region[0] = 0;
6156  s.region[1] = 0;
6157  s.region[2] = 0;
6158  s.region[3] = 0;
6159  return s;
6160 }
6161 
6162 NK_API struct nk_image
6163 nk_image_id(int id)
6164 {
6165  struct nk_image s;
6166  nk_zero(&s, sizeof(s));
6167  s.handle.id = id;
6168  s.w = 0; s.h = 0;
6169  s.region[0] = 0;
6170  s.region[1] = 0;
6171  s.region[2] = 0;
6172  s.region[3] = 0;
6173  return s;
6174 }
6175 
6176 NK_API int
6177 nk_image_is_subimage(const struct nk_image* img)
6178 {
6179  NK_ASSERT(img);
6180  return !(img->w == 0 && img->h == 0);
6181 }
6182 
6183 NK_INTERN void
6184 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0,
6185  float x1, float y1)
6186 {
6187  NK_ASSERT(a);
6188  NK_ASSERT(clip);
6189  clip->x = NK_MAX(a->x, x0);
6190  clip->y = NK_MAX(a->y, y0);
6191  clip->w = NK_MIN(a->x + a->w, x1) - clip->x;
6192  clip->h = NK_MIN(a->y + a->h, y1) - clip->y;
6193  clip->w = NK_MAX(0, clip->w);
6194  clip->h = NK_MAX(0, clip->h);
6195 }
6196 
6197 NK_API void
6199  float pad_x, float pad_y, enum nk_heading direction)
6200 {
6201  float w_half, h_half;
6202  NK_ASSERT(result);
6203 
6204  r.w = NK_MAX(2 * pad_x, r.w);
6205  r.h = NK_MAX(2 * pad_y, r.h);
6206  r.w = r.w - 2 * pad_x;
6207  r.h = r.h - 2 * pad_y;
6208 
6209  r.x = r.x + pad_x;
6210  r.y = r.y + pad_y;
6211 
6212  w_half = r.w / 2.0f;
6213  h_half = r.h / 2.0f;
6214 
6215  if (direction == NK_UP) {
6216  result[0] = nk_vec2(r.x + w_half, r.y);
6217  result[1] = nk_vec2(r.x + r.w, r.y + r.h);
6218  result[2] = nk_vec2(r.x, r.y + r.h);
6219  } else if (direction == NK_RIGHT) {
6220  result[0] = nk_vec2(r.x, r.y);
6221  result[1] = nk_vec2(r.x + r.w, r.y + h_half);
6222  result[2] = nk_vec2(r.x, r.y + r.h);
6223  } else if (direction == NK_DOWN) {
6224  result[0] = nk_vec2(r.x, r.y);
6225  result[1] = nk_vec2(r.x + r.w, r.y);
6226  result[2] = nk_vec2(r.x + w_half, r.y + r.h);
6227  } else {
6228  result[0] = nk_vec2(r.x, r.y + h_half);
6229  result[1] = nk_vec2(r.x + r.w, r.y);
6230  result[2] = nk_vec2(r.x + r.w, r.y + r.h);
6231  }
6232 }
6233 
6234 NK_INTERN int
6235 nk_text_clamp(const struct nk_user_font *font, const char *text,
6236  int text_len, float space, int *glyphs, float *text_width,
6237  nk_rune *sep_list, int sep_count)
6238 {
6239  int i = 0;
6240  int glyph_len = 0;
6241  float last_width = 0;
6242  nk_rune unicode = 0;
6243  float width = 0;
6244  int len = 0;
6245  int g = 0;
6246  float s;
6247 
6248  int sep_len = 0;
6249  int sep_g = 0;
6250  float sep_width = 0;
6251  sep_count = NK_MAX(sep_count,0);
6252 
6253  glyph_len = nk_utf_decode(text, &unicode, text_len);
6254  while (glyph_len && (width < space) && (len < text_len)) {
6255  len += glyph_len;
6256  s = font->width(font->userdata, font->height, text, len);
6257  for (i = 0; i < sep_count; ++i) {
6258  if (unicode != sep_list[i]) continue;
6259  sep_width = last_width = width;
6260  sep_g = g+1;
6261  sep_len = len;
6262  break;
6263  }
6264  if (i == sep_count){
6265  last_width = sep_width = width;
6266  sep_g = g+1;
6267  }
6268  width = s;
6269  glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len);
6270  g++;
6271  }
6272  if (len >= text_len) {
6273  *glyphs = g;
6274  *text_width = last_width;
6275  return len;
6276  } else {
6277  *glyphs = sep_g;
6278  *text_width = sep_width;
6279  return (!sep_len) ? len: sep_len;
6280  }
6281 }
6282 
6283 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE};
6284 NK_INTERN struct nk_vec2
6285 nk_text_calculate_text_bounds(const struct nk_user_font *font,
6286  const char *begin, int byte_len, float row_height, const char **remaining,
6287  struct nk_vec2 *out_offset, int *glyphs, int op)
6288 {
6289  float line_height = row_height;
6290  struct nk_vec2 text_size = nk_vec2(0,0);
6291  float line_width = 0.0f;
6292 
6293  float glyph_width;
6294  int glyph_len = 0;
6295  nk_rune unicode = 0;
6296  int text_len = 0;
6297  if (!begin || byte_len <= 0 || !font)
6298  return nk_vec2(0,row_height);
6299 
6300  glyph_len = nk_utf_decode(begin, &unicode, byte_len);
6301  if (!glyph_len) return text_size;
6302  glyph_width = font->width(font->userdata, font->height, begin, glyph_len);
6303 
6304  *glyphs = 0;
6305  while ((text_len < byte_len) && glyph_len) {
6306  if (unicode == '\n') {
6307  text_size.x = NK_MAX(text_size.x, line_width);
6308  text_size.y += line_height;
6309  line_width = 0;
6310  *glyphs+=1;
6311  if (op == NK_STOP_ON_NEW_LINE)
6312  break;
6313 
6314  text_len++;
6315  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6316  continue;
6317  }
6318 
6319  if (unicode == '\r') {
6320  text_len++;
6321  *glyphs+=1;
6322  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6323  continue;
6324  }
6325 
6326  *glyphs = *glyphs + 1;
6327  text_len += glyph_len;
6328  line_width += (float)glyph_width;
6329  glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len);
6330  glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len);
6331  continue;
6332  }
6333 
6334  if (text_size.x < line_width)
6335  text_size.x = line_width;
6336  if (out_offset)
6337  *out_offset = nk_vec2(line_width, text_size.y + line_height);
6338  if (line_width > 0 || text_size.y == 0.0f)
6339  text_size.y += line_height;
6340  if (remaining)
6341  *remaining = begin+text_len;
6342  return text_size;
6343 }
6344 
6345 /* ==============================================================
6346  *
6347  * UTF-8
6348  *
6349  * ===============================================================*/
6350 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0};
6351 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8};
6352 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000};
6353 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF};
6354 
6355 NK_INTERN int
6356 nk_utf_validate(nk_rune *u, int i)
6357 {
6358  NK_ASSERT(u);
6359  if (!u) return 0;
6360  if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) ||
6361  NK_BETWEEN(*u, 0xD800, 0xDFFF))
6362  *u = NK_UTF_INVALID;
6363  for (i = 1; *u > nk_utfmax[i]; ++i);
6364  return i;
6365 }
6366 
6368 nk_utf_decode_byte(char c, int *i)
6369 {
6370  NK_ASSERT(i);
6371  if (!i) return 0;
6372  for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) {
6373  if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i])
6374  return (nk_byte)(c & ~nk_utfmask[*i]);
6375  }
6376  return 0;
6377 }
6378 
6379 NK_API int
6380 nk_utf_decode(const char *c, nk_rune *u, int clen)
6381 {
6382  int i, j, len, type=0;
6383  nk_rune udecoded;
6384 
6385  NK_ASSERT(c);
6386  NK_ASSERT(u);
6387 
6388  if (!c || !u) return 0;
6389  if (!clen) return 0;
6390  *u = NK_UTF_INVALID;
6391 
6392  udecoded = nk_utf_decode_byte(c[0], &len);
6393  if (!NK_BETWEEN(len, 1, NK_UTF_SIZE))
6394  return 1;
6395 
6396  for (i = 1, j = 1; i < clen && j < len; ++i, ++j) {
6397  udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type);
6398  if (type != 0)
6399  return j;
6400  }
6401  if (j < len)
6402  return 0;
6403  *u = udecoded;
6404  nk_utf_validate(u, len);
6405  return len;
6406 }
6407 
6408 NK_INTERN char
6409 nk_utf_encode_byte(nk_rune u, int i)
6410 {
6411  return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i]));
6412 }
6413 
6414 NK_API int
6415 nk_utf_encode(nk_rune u, char *c, int clen)
6416 {
6417  int len, i;
6418  len = nk_utf_validate(&u, 0);
6419  if (clen < len || !len || len > NK_UTF_SIZE)
6420  return 0;
6421 
6422  for (i = len - 1; i != 0; --i) {
6423  c[i] = nk_utf_encode_byte(u, 0);
6424  u >>= 6;
6425  }
6426  c[0] = nk_utf_encode_byte(u, len);
6427  return len;
6428 }
6429 
6430 NK_API int
6431 nk_utf_len(const char *str, int len)
6432 {
6433  const char *text;
6434  int glyphs = 0;
6435  int text_len;
6436  int glyph_len;
6437  int src_len = 0;
6438  nk_rune unicode;
6439 
6440  NK_ASSERT(str);
6441  if (!str || !len) return 0;
6442 
6443  text = str;
6444  text_len = len;
6445  glyph_len = nk_utf_decode(text, &unicode, text_len);
6446  while (glyph_len && src_len < len) {
6447  glyphs++;
6448  src_len = src_len + glyph_len;
6449  glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len);
6450  }
6451  return glyphs;
6452 }
6453 
6454 NK_API const char*
6455 nk_utf_at(const char *buffer, int length, int index,
6456  nk_rune *unicode, int *len)
6457 {
6458  int i = 0;
6459  int src_len = 0;
6460  int glyph_len = 0;
6461  const char *text;
6462  int text_len;
6463 
6464  NK_ASSERT(buffer);
6465  NK_ASSERT(unicode);
6466  NK_ASSERT(len);
6467 
6468  if (!buffer || !unicode || !len) return 0;
6469  if (index < 0) {
6470  *unicode = NK_UTF_INVALID;
6471  *len = 0;
6472  return 0;
6473  }
6474 
6475  text = buffer;
6476  text_len = length;
6477  glyph_len = nk_utf_decode(text, unicode, text_len);
6478  while (glyph_len) {
6479  if (i == index) {
6480  *len = glyph_len;
6481  break;
6482  }
6483 
6484  i++;
6485  src_len = src_len + glyph_len;
6486  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
6487  }
6488  if (i != index) return 0;
6489  return buffer + src_len;
6490 }
6491 
6492 /* ==============================================================
6493  *
6494  * BUFFER
6495  *
6496  * ===============================================================*/
6497 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
6498 NK_INTERN void* nk_malloc(nk_handle unused, void *old,nk_size size)
6499 {NK_UNUSED(unused); NK_UNUSED(old); return malloc(size);}
6500 NK_INTERN void nk_mfree(nk_handle unused, void *ptr)
6501 {NK_UNUSED(unused); free(ptr);}
6502 
6503 NK_API void
6504 nk_buffer_init_default(struct nk_buffer *buffer)
6505 {
6506  struct nk_allocator alloc;
6507  alloc.userdata.ptr = 0;
6508  alloc.alloc = nk_malloc;
6509  alloc.free = nk_mfree;
6510  nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE);
6511 }
6512 #endif
6513 
6514 NK_API void
6515 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a,
6516  nk_size initial_size)
6517 {
6518  NK_ASSERT(b);
6519  NK_ASSERT(a);
6520  NK_ASSERT(initial_size);
6521  if (!b || !a || !initial_size) return;
6522 
6523  nk_zero(b, sizeof(*b));
6524  b->type = NK_BUFFER_DYNAMIC;
6525  b->memory.ptr = a->alloc(a->userdata,0, initial_size);
6526  b->memory.size = initial_size;
6527  b->size = initial_size;
6528  b->grow_factor = 2.0f;
6529  b->pool = *a;
6530 }
6531 
6532 NK_API void
6533 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size)
6534 {
6535  NK_ASSERT(b);
6536  NK_ASSERT(m);
6537  NK_ASSERT(size);
6538  if (!b || !m || !size) return;
6539 
6540  nk_zero(b, sizeof(*b));
6541  b->type = NK_BUFFER_FIXED;
6542  b->memory.ptr = m;
6543  b->memory.size = size;
6544  b->size = size;
6545 }
6546 
6547 NK_INTERN void*
6548 nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment,
6550 {
6551  void *memory = 0;
6552  switch (type) {
6553  default:
6554  case NK_BUFFER_MAX:
6555  case NK_BUFFER_FRONT:
6556  if (align) {
6557  memory = NK_ALIGN_PTR(unaligned, align);
6558  *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
6559  } else {
6560  memory = unaligned;
6561  *alignment = 0;
6562  }
6563  break;
6564  case NK_BUFFER_BACK:
6565  if (align) {
6566  memory = NK_ALIGN_PTR_BACK(unaligned, align);
6567  *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory);
6568  } else {
6569  memory = unaligned;
6570  *alignment = 0;
6571  }
6572  break;
6573  }
6574  return memory;
6575 }
6576 
6577 NK_INTERN void*
6578 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size)
6579 {
6580  void *temp;
6581  nk_size buffer_size;
6582 
6583  NK_ASSERT(b);
6584  NK_ASSERT(size);
6585  if (!b || !size || !b->pool.alloc || !b->pool.free)
6586  return 0;
6587 
6588  buffer_size = b->memory.size;
6589  temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity);
6590  NK_ASSERT(temp);
6591  if (!temp) return 0;
6592 
6593  *size = capacity;
6594  if (temp != b->memory.ptr) {
6595  NK_MEMCPY(temp, b->memory.ptr, buffer_size);
6596  b->pool.free(b->pool.userdata, b->memory.ptr);
6597  }
6598 
6599  if (b->size == buffer_size) {
6600  /* no back buffer so just set correct size */
6601  b->size = capacity;
6602  return temp;
6603  } else {
6604  /* copy back buffer to the end of the new buffer */
6605  void *dst, *src;
6606  nk_size back_size;
6607  back_size = buffer_size - b->size;
6608  dst = nk_ptr_add(void, temp, capacity - back_size);
6609  src = nk_ptr_add(void, temp, b->size);
6610  NK_MEMCPY(dst, src, back_size);
6611  b->size = capacity - back_size;
6612  }
6613  return temp;
6614 }
6615 
6616 NK_INTERN void*
6617 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type,
6619 {
6620  int full;
6621  nk_size alignment;
6622  void *unaligned;
6623  void *memory;
6624 
6625  NK_ASSERT(b);
6626  NK_ASSERT(size);
6627  if (!b || !size) return 0;
6628  b->needed += size;
6629 
6630  /* calculate total size with needed alignment + size */
6631  if (type == NK_BUFFER_FRONT)
6632  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
6633  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
6634  memory = nk_buffer_align(unaligned, align, &alignment, type);
6635 
6636  /* check if buffer has enough memory*/
6637  if (type == NK_BUFFER_FRONT)
6638  full = ((b->allocated + size + alignment) > b->size);
6639  else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated);
6640 
6641  if (full) {
6642  nk_size capacity;
6643  if (b->type != NK_BUFFER_DYNAMIC)
6644  return 0;
6645  NK_ASSERT(b->pool.alloc && b->pool.free);
6646  if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free)
6647  return 0;
6648 
6649  /* buffer is full so allocate bigger buffer if dynamic */
6650  capacity = (nk_size)((float)b->memory.size * b->grow_factor);
6651  capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size)));
6652  b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size);
6653  if (!b->memory.ptr) return 0;
6654 
6655  /* align newly allocated pointer */
6656  if (type == NK_BUFFER_FRONT)
6657  unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated);
6658  else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size);
6659  memory = nk_buffer_align(unaligned, align, &alignment, type);
6660  }
6661  if (type == NK_BUFFER_FRONT)
6662  b->allocated += size + alignment;
6663  else b->size -= (size + alignment);
6664  b->needed += alignment;
6665  b->calls++;
6666  return memory;
6667 }
6668 
6669 NK_API void
6671  const void *memory, nk_size size, nk_size align)
6672 {
6673  void *mem = nk_buffer_alloc(b, type, size, align);
6674  if (!mem) return;
6675  NK_MEMCPY(mem, memory, size);
6676 }
6677 
6678 NK_API void
6680 {
6681  NK_ASSERT(buffer);
6682  if (!buffer) return;
6683  buffer->marker[type].active = nk_true;
6684  if (type == NK_BUFFER_BACK)
6685  buffer->marker[type].offset = buffer->size;
6686  else buffer->marker[type].offset = buffer->allocated;
6687 }
6688 
6689 NK_API void
6691 {
6692  NK_ASSERT(buffer);
6693  if (!buffer) return;
6694  if (type == NK_BUFFER_BACK) {
6695  /* reset back buffer either back to marker or empty */
6696  buffer->needed -= (buffer->memory.size - buffer->marker[type].offset);
6697  if (buffer->marker[type].active)
6698  buffer->size = buffer->marker[type].offset;
6699  else buffer->size = buffer->memory.size;
6700  buffer->marker[type].active = nk_false;
6701  } else {
6702  /* reset front buffer either back to back marker or empty */
6703  buffer->needed -= (buffer->allocated - buffer->marker[type].offset);
6704  if (buffer->marker[type].active)
6705  buffer->allocated = buffer->marker[type].offset;
6706  else buffer->allocated = 0;
6707  buffer->marker[type].active = nk_false;
6708  }
6709 }
6710 
6711 NK_API void
6712 nk_buffer_clear(struct nk_buffer *b)
6713 {
6714  NK_ASSERT(b);
6715  if (!b) return;
6716  b->allocated = 0;
6717  b->size = b->memory.size;
6718  b->calls = 0;
6719  b->needed = 0;
6720 }
6721 
6722 NK_API void
6723 nk_buffer_free(struct nk_buffer *b)
6724 {
6725  NK_ASSERT(b);
6726  if (!b || !b->memory.ptr) return;
6727  if (b->type == NK_BUFFER_FIXED) return;
6728  if (!b->pool.free) return;
6729  NK_ASSERT(b->pool.free);
6730  b->pool.free(b->pool.userdata, b->memory.ptr);
6731 }
6732 
6733 NK_API void
6734 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b)
6735 {
6736  NK_ASSERT(b);
6737  NK_ASSERT(s);
6738  if (!s || !b) return;
6739  s->allocated = b->allocated;
6740  s->size = b->memory.size;
6741  s->needed = b->needed;
6742  s->memory = b->memory.ptr;
6743  s->calls = b->calls;
6744 }
6745 
6746 NK_API void*
6748 {
6749  NK_ASSERT(buffer);
6750  if (!buffer) return 0;
6751  return buffer->memory.ptr;
6752 }
6753 
6754 NK_API const void*
6756 {
6757  NK_ASSERT(buffer);
6758  if (!buffer) return 0;
6759  return buffer->memory.ptr;
6760 }
6761 
6764 {
6765  NK_ASSERT(buffer);
6766  if (!buffer) return 0;
6767  return buffer->memory.size;
6768 }
6769 
6770 /*
6771  * ==============================================================
6772  *
6773  * STRING
6774  *
6775  * ===============================================================
6776  */
6777 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
6778 NK_API void
6779 nk_str_init_default(struct nk_str *str)
6780 {
6781  struct nk_allocator alloc;
6782  alloc.userdata.ptr = 0;
6783  alloc.alloc = nk_malloc;
6784  alloc.free = nk_mfree;
6785  nk_buffer_init(&str->buffer, &alloc, 32);
6786  str->len = 0;
6787 }
6788 #endif
6789 
6790 NK_API void
6791 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size)
6792 {
6793  nk_buffer_init(&str->buffer, alloc, size);
6794  str->len = 0;
6795 }
6796 
6797 NK_API void
6798 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size)
6799 {
6800  nk_buffer_init_fixed(&str->buffer, memory, size);
6801  str->len = 0;
6802 }
6803 
6804 NK_API int
6805 nk_str_append_text_char(struct nk_str *s, const char *str, int len)
6806 {
6807  char *mem;
6808  NK_ASSERT(s);
6809  NK_ASSERT(str);
6810  if (!s || !str || !len) return 0;
6811  mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
6812  if (!mem) return 0;
6813  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
6814  s->len += nk_utf_len(str, len);
6815  return len;
6816 }
6817 
6818 NK_API int
6819 nk_str_append_str_char(struct nk_str *s, const char *str)
6820 {
6822 }
6823 
6824 NK_API int
6825 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len)
6826 {
6827  int i = 0;
6828  int byte_len = 0;
6829  nk_rune unicode;
6830  if (!str || !text || !len) return 0;
6831  for (i = 0; i < len; ++i)
6832  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
6833  nk_str_append_text_char(str, text, byte_len);
6834  return len;
6835 }
6836 
6837 NK_API int
6838 nk_str_append_str_utf8(struct nk_str *str, const char *text)
6839 {
6840  int runes = 0;
6841  int byte_len = 0;
6842  int num_runes = 0;
6843  int glyph_len = 0;
6844  nk_rune unicode;
6845  if (!str || !text) return 0;
6846 
6847  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
6848  while (unicode != '\0' && glyph_len) {
6849  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
6850  byte_len += glyph_len;
6851  num_runes++;
6852  }
6853  nk_str_append_text_char(str, text, byte_len);
6854  return runes;
6855 }
6856 
6857 NK_API int
6858 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len)
6859 {
6860  int i = 0;
6861  int byte_len = 0;
6862  nk_glyph glyph;
6863 
6864  NK_ASSERT(str);
6865  if (!str || !text || !len) return 0;
6866  for (i = 0; i < len; ++i) {
6867  byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE);
6868  if (!byte_len) break;
6869  nk_str_append_text_char(str, glyph, byte_len);
6870  }
6871  return len;
6872 }
6873 
6874 NK_API int
6875 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes)
6876 {
6877  int i = 0;
6878  nk_glyph glyph;
6879  int byte_len;
6880  NK_ASSERT(str);
6881  if (!str || !runes) return 0;
6882  while (runes[i] != '\0') {
6883  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
6884  nk_str_append_text_char(str, glyph, byte_len);
6885  i++;
6886  }
6887  return i;
6888 }
6889 
6890 NK_API int
6891 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len)
6892 {
6893  int i;
6894  void *mem;
6895  char *src;
6896  char *dst;
6897 
6898  int copylen;
6899  NK_ASSERT(s);
6900  NK_ASSERT(str);
6901  NK_ASSERT(len >= 0);
6902  if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0;
6903  if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) &&
6904  (s->buffer.type == NK_BUFFER_FIXED)) return 0;
6905 
6906  copylen = (int)s->buffer.allocated - pos;
6907  if (!copylen) {
6909  return 1;
6910  }
6911  mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0);
6912  if (!mem) return 0;
6913 
6914  /* memmove */
6915  NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0);
6916  NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0);
6917  dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1));
6918  src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1));
6919  for (i = 0; i < copylen; ++i) *dst-- = *src--;
6920  mem = nk_ptr_add(void, s->buffer.memory.ptr, pos);
6921  NK_MEMCPY(mem, str, (nk_size)len * sizeof(char));
6922  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
6923  return 1;
6924 }
6925 
6926 NK_API int
6927 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len)
6928 {
6929  int glyph_len;
6930  nk_rune unicode;
6931  const char *begin;
6932  const char *buffer;
6933 
6934  NK_ASSERT(str);
6935  NK_ASSERT(cstr);
6936  NK_ASSERT(len);
6937  if (!str || !cstr || !len) return 0;
6938  begin = nk_str_at_rune(str, pos, &unicode, &glyph_len);
6939  if (!str->len)
6940  return nk_str_append_text_char(str, cstr, len);
6942  if (!begin) return 0;
6943  return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len);
6944 }
6945 
6946 NK_API int
6947 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len)
6948 {
6949  return nk_str_insert_text_utf8(str, pos, text, len);
6950 }
6951 
6952 NK_API int
6953 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text)
6954 {
6955  return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text));
6956 }
6957 
6958 NK_API int
6959 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len)
6960 {
6961  int i = 0;
6962  int byte_len = 0;
6963  nk_rune unicode;
6964 
6965  NK_ASSERT(str);
6966  NK_ASSERT(text);
6967  if (!str || !text || !len) return 0;
6968  for (i = 0; i < len; ++i)
6969  byte_len += nk_utf_decode(text+byte_len, &unicode, 4);
6970  nk_str_insert_at_rune(str, pos, text, byte_len);
6971  return len;
6972 }
6973 
6974 NK_API int
6975 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text)
6976 {
6977  int runes = 0;
6978  int byte_len = 0;
6979  int num_runes = 0;
6980  int glyph_len = 0;
6981  nk_rune unicode;
6982  if (!str || !text) return 0;
6983 
6984  glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4);
6985  while (unicode != '\0' && glyph_len) {
6986  glyph_len = nk_utf_decode(text+byte_len, &unicode, 4);
6987  byte_len += glyph_len;
6988  num_runes++;
6989  }
6990  nk_str_insert_at_rune(str, pos, text, byte_len);
6991  return runes;
6992 }
6993 
6994 NK_API int
6995 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len)
6996 {
6997  int i = 0;
6998  int byte_len = 0;
6999  nk_glyph glyph;
7000 
7001  NK_ASSERT(str);
7002  if (!str || !runes || !len) return 0;
7003  for (i = 0; i < len; ++i) {
7004  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
7005  if (!byte_len) break;
7006  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
7007  }
7008  return len;
7009 }
7010 
7011 NK_API int
7012 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes)
7013 {
7014  int i = 0;
7015  nk_glyph glyph;
7016  int byte_len;
7017  NK_ASSERT(str);
7018  if (!str || !runes) return 0;
7019  while (runes[i] != '\0') {
7020  byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE);
7021  nk_str_insert_at_rune(str, pos+i, glyph, byte_len);
7022  i++;
7023  }
7024  return i;
7025 }
7026 
7027 NK_API void
7028 nk_str_remove_chars(struct nk_str *s, int len)
7029 {
7030  NK_ASSERT(s);
7031  NK_ASSERT(len >= 0);
7032  if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return;
7033  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
7034  s->buffer.allocated -= (nk_size)len;
7035  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
7036 }
7037 
7038 NK_API void
7039 nk_str_remove_runes(struct nk_str *str, int len)
7040 {
7041  int index;
7042  const char *begin;
7043  const char *end;
7044  nk_rune unicode;
7045 
7046  NK_ASSERT(str);
7047  NK_ASSERT(len >= 0);
7048  if (!str || len < 0) return;
7049  if (len >= str->len) {
7050  str->len = 0;
7051  return;
7052  }
7053 
7054  index = str->len - len;
7055  begin = nk_str_at_rune(str, index, &unicode, &len);
7056  end = (const char*)str->buffer.memory.ptr + str->buffer.allocated;
7057  nk_str_remove_chars(str, (int)(end-begin)+1);
7058 }
7059 
7060 NK_API void
7061 nk_str_delete_chars(struct nk_str *s, int pos, int len)
7062 {
7063  NK_ASSERT(s);
7064  if (!s || !len || (nk_size)pos > s->buffer.allocated ||
7065  (nk_size)(pos + len) > s->buffer.allocated) return;
7066 
7067  if ((nk_size)(pos + len) < s->buffer.allocated) {
7068  /* memmove */
7069  char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos);
7070  char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len);
7071  NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len));
7072  NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0);
7073  s->buffer.allocated -= (nk_size)len;
7074  } else nk_str_remove_chars(s, len);
7075  s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated);
7076 }
7077 
7078 NK_API void
7079 nk_str_delete_runes(struct nk_str *s, int pos, int len)
7080 {
7081  char *temp;
7082  nk_rune unicode;
7083  char *begin;
7084  char *end;
7085  int unused;
7086 
7087  NK_ASSERT(s);
7088  NK_ASSERT(s->len >= pos + len);
7089  if (s->len < pos + len)
7090  len = NK_CLAMP(0, (s->len - pos), s->len);
7091  if (!len) return;
7092 
7093  temp = (char *)s->buffer.memory.ptr;
7094  begin = nk_str_at_rune(s, pos, &unicode, &unused);
7095  if (!begin) return;
7096  s->buffer.memory.ptr = begin;
7097  end = nk_str_at_rune(s, len, &unicode, &unused);
7098  s->buffer.memory.ptr = temp;
7099  if (!end) return;
7100  nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin));
7101 }
7102 
7103 NK_API char*
7104 nk_str_at_char(struct nk_str *s, int pos)
7105 {
7106  NK_ASSERT(s);
7107  if (!s || pos > (int)s->buffer.allocated) return 0;
7108  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
7109 }
7110 
7111 NK_API char*
7112 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len)
7113 {
7114  int i = 0;
7115  int src_len = 0;
7116  int glyph_len = 0;
7117  char *text;
7118  int text_len;
7119 
7120  NK_ASSERT(str);
7121  NK_ASSERT(unicode);
7122  NK_ASSERT(len);
7123 
7124  if (!str || !unicode || !len) return 0;
7125  if (pos < 0) {
7126  *unicode = 0;
7127  *len = 0;
7128  return 0;
7129  }
7130 
7131  text = (char*)str->buffer.memory.ptr;
7132  text_len = (int)str->buffer.allocated;
7133  glyph_len = nk_utf_decode(text, unicode, text_len);
7134  while (glyph_len) {
7135  if (i == pos) {
7136  *len = glyph_len;
7137  break;
7138  }
7139 
7140  i++;
7141  src_len = src_len + glyph_len;
7142  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7143  }
7144  if (i != pos) return 0;
7145  return text + src_len;
7146 }
7147 
7148 NK_API const char*
7149 nk_str_at_char_const(const struct nk_str *s, int pos)
7150 {
7151  NK_ASSERT(s);
7152  if (!s || pos > (int)s->buffer.allocated) return 0;
7153  return nk_ptr_add(char, s->buffer.memory.ptr, pos);
7154 }
7155 
7156 NK_API const char*
7157 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len)
7158 {
7159  int i = 0;
7160  int src_len = 0;
7161  int glyph_len = 0;
7162  char *text;
7163  int text_len;
7164 
7165  NK_ASSERT(str);
7166  NK_ASSERT(unicode);
7167  NK_ASSERT(len);
7168 
7169  if (!str || !unicode || !len) return 0;
7170  if (pos < 0) {
7171  *unicode = 0;
7172  *len = 0;
7173  return 0;
7174  }
7175 
7176  text = (char*)str->buffer.memory.ptr;
7177  text_len = (int)str->buffer.allocated;
7178  glyph_len = nk_utf_decode(text, unicode, text_len);
7179  while (glyph_len) {
7180  if (i == pos) {
7181  *len = glyph_len;
7182  break;
7183  }
7184 
7185  i++;
7186  src_len = src_len + glyph_len;
7187  glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len);
7188  }
7189  if (i != pos) return 0;
7190  return text + src_len;
7191 }
7192 
7194 nk_str_rune_at(const struct nk_str *str, int pos)
7195 {
7196  int len;
7197  nk_rune unicode = 0;
7198  nk_str_at_const(str, pos, &unicode, &len);
7199  return unicode;
7200 }
7201 
7202 NK_API char*
7203 nk_str_get(struct nk_str *s)
7204 {
7205  NK_ASSERT(s);
7206  if (!s || !s->len || !s->buffer.allocated) return 0;
7207  return (char*)s->buffer.memory.ptr;
7208 }
7209 
7210 NK_API const char*
7211 nk_str_get_const(const struct nk_str *s)
7212 {
7213  NK_ASSERT(s);
7214  if (!s || !s->len || !s->buffer.allocated) return 0;
7215  return (const char*)s->buffer.memory.ptr;
7216 }
7217 
7218 NK_API int
7219 nk_str_len(struct nk_str *s)
7220 {
7221  NK_ASSERT(s);
7222  if (!s || !s->len || !s->buffer.allocated) return 0;
7223  return s->len;
7224 }
7225 
7226 NK_API int
7227 nk_str_len_char(struct nk_str *s)
7228 {
7229  NK_ASSERT(s);
7230  if (!s || !s->len || !s->buffer.allocated) return 0;
7231  return (int)s->buffer.allocated;
7232 }
7233 
7234 NK_API void
7235 nk_str_clear(struct nk_str *str)
7236 {
7237  NK_ASSERT(str);
7238  nk_buffer_clear(&str->buffer);
7239  str->len = 0;
7240 }
7241 
7242 NK_API void
7243 nk_str_free(struct nk_str *str)
7244 {
7245  NK_ASSERT(str);
7246  nk_buffer_free(&str->buffer);
7247  str->len = 0;
7248 }
7249 
7250 /*
7251  * ==============================================================
7252  *
7253  * Command buffer
7254  *
7255  * ===============================================================
7256 */
7257 NK_INTERN void
7258 nk_command_buffer_init(struct nk_command_buffer *cmdbuf,
7259  struct nk_buffer *buffer, enum nk_command_clipping clip)
7260 {
7261  NK_ASSERT(cmdbuf);
7262  NK_ASSERT(buffer);
7263  if (!cmdbuf || !buffer) return;
7264  cmdbuf->base = buffer;
7265  cmdbuf->use_clipping = clip;
7266  cmdbuf->begin = buffer->allocated;
7267  cmdbuf->end = buffer->allocated;
7268  cmdbuf->last = buffer->allocated;
7269 }
7270 
7271 NK_INTERN void
7272 nk_command_buffer_reset(struct nk_command_buffer *buffer)
7273 {
7274  NK_ASSERT(buffer);
7275  if (!buffer) return;
7276  buffer->begin = 0;
7277  buffer->end = 0;
7278  buffer->last = 0;
7279  buffer->clip = nk_null_rect;
7280 #ifdef NK_INCLUDE_COMMAND_USERDATA
7281  buffer->userdata.ptr = 0;
7282 #endif
7283 }
7284 
7285 NK_INTERN void*
7286 nk_command_buffer_push(struct nk_command_buffer* b,
7287  enum nk_command_type t, nk_size size)
7288 {
7289  NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command);
7290  struct nk_command *cmd;
7291  nk_size alignment;
7292  void *unaligned;
7293  void *memory;
7294 
7295  NK_ASSERT(b);
7296  NK_ASSERT(b->base);
7297  if (!b) return 0;
7298  cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align);
7299  if (!cmd) return 0;
7300 
7301  /* make sure the offset to the next command is aligned */
7302  b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr);
7303  unaligned = (nk_byte*)cmd + size;
7304  memory = NK_ALIGN_PTR(unaligned, align);
7305  alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned);
7306 #ifdef NK_ZERO_COMMAND_MEMORY
7307  NK_MEMSET(cmd, 0, size + alignment);
7308 #endif
7309 
7310  cmd->type = t;
7311  cmd->next = b->base->allocated + alignment;
7312 #ifdef NK_INCLUDE_COMMAND_USERDATA
7313  cmd->userdata = b->userdata;
7314 #endif
7315  b->end = cmd->next;
7316  return cmd;
7317 }
7318 
7319 NK_API void
7320 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r)
7321 {
7322  struct nk_command_scissor *cmd;
7323  NK_ASSERT(b);
7324  if (!b) return;
7325 
7326  b->clip.x = r.x;
7327  b->clip.y = r.y;
7328  b->clip.w = r.w;
7329  b->clip.h = r.h;
7330  cmd = (struct nk_command_scissor*)
7331  nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd));
7332 
7333  if (!cmd) return;
7334  cmd->x = (short)r.x;
7335  cmd->y = (short)r.y;
7336  cmd->w = (unsigned short)NK_MAX(0, r.w);
7337  cmd->h = (unsigned short)NK_MAX(0, r.h);
7338 }
7339 
7340 NK_API void
7341 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0,
7342  float x1, float y1, float line_thickness, struct nk_color c)
7343 {
7344  struct nk_command_line *cmd;
7345  NK_ASSERT(b);
7346  if (!b || line_thickness <= 0) return;
7347  cmd = (struct nk_command_line*)
7348  nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd));
7349  if (!cmd) return;
7350  cmd->line_thickness = (unsigned short)line_thickness;
7351  cmd->begin.x = (short)x0;
7352  cmd->begin.y = (short)y0;
7353  cmd->end.x = (short)x1;
7354  cmd->end.y = (short)y1;
7355  cmd->color = c;
7356 }
7357 
7358 NK_API void
7359 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay,
7360  float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y,
7361  float bx, float by, float line_thickness, struct nk_color col)
7362 {
7363  struct nk_command_curve *cmd;
7364  NK_ASSERT(b);
7365  if (!b || col.a == 0 || line_thickness <= 0) return;
7366 
7367  cmd = (struct nk_command_curve*)
7368  nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd));
7369  if (!cmd) return;
7370  cmd->line_thickness = (unsigned short)line_thickness;
7371  cmd->begin.x = (short)ax;
7372  cmd->begin.y = (short)ay;
7373  cmd->ctrl[0].x = (short)ctrl0x;
7374  cmd->ctrl[0].y = (short)ctrl0y;
7375  cmd->ctrl[1].x = (short)ctrl1x;
7376  cmd->ctrl[1].y = (short)ctrl1y;
7377  cmd->end.x = (short)bx;
7378  cmd->end.y = (short)by;
7379  cmd->color = col;
7380 }
7381 
7382 NK_API void
7383 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect,
7384  float rounding, float line_thickness, struct nk_color c)
7385 {
7386  struct nk_command_rect *cmd;
7387  NK_ASSERT(b);
7388  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return;
7389  if (b->use_clipping) {
7390  const struct nk_rect *clip = &b->clip;
7391  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7392  clip->x, clip->y, clip->w, clip->h)) return;
7393  }
7394  cmd = (struct nk_command_rect*)
7395  nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd));
7396  if (!cmd) return;
7397  cmd->rounding = (unsigned short)rounding;
7398  cmd->line_thickness = (unsigned short)line_thickness;
7399  cmd->x = (short)rect.x;
7400  cmd->y = (short)rect.y;
7401  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7402  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7403  cmd->color = c;
7404 }
7405 
7406 NK_API void
7407 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect,
7408  float rounding, struct nk_color c)
7409 {
7410  struct nk_command_rect_filled *cmd;
7411  NK_ASSERT(b);
7412  if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return;
7413  if (b->use_clipping) {
7414  const struct nk_rect *clip = &b->clip;
7415  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7416  clip->x, clip->y, clip->w, clip->h)) return;
7417  }
7418 
7419  cmd = (struct nk_command_rect_filled*)
7420  nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd));
7421  if (!cmd) return;
7422  cmd->rounding = (unsigned short)rounding;
7423  cmd->x = (short)rect.x;
7424  cmd->y = (short)rect.y;
7425  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7426  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7427  cmd->color = c;
7428 }
7429 
7430 NK_API void
7432  struct nk_color left, struct nk_color top, struct nk_color right,
7433  struct nk_color bottom)
7434 {
7436  NK_ASSERT(b);
7437  if (!b || rect.w == 0 || rect.h == 0) return;
7438  if (b->use_clipping) {
7439  const struct nk_rect *clip = &b->clip;
7440  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
7441  clip->x, clip->y, clip->w, clip->h)) return;
7442  }
7443 
7444  cmd = (struct nk_command_rect_multi_color*)
7445  nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd));
7446  if (!cmd) return;
7447  cmd->x = (short)rect.x;
7448  cmd->y = (short)rect.y;
7449  cmd->w = (unsigned short)NK_MAX(0, rect.w);
7450  cmd->h = (unsigned short)NK_MAX(0, rect.h);
7451  cmd->left = left;
7452  cmd->top = top;
7453  cmd->right = right;
7454  cmd->bottom = bottom;
7455 }
7456 
7457 NK_API void
7458 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r,
7459  float line_thickness, struct nk_color c)
7460 {
7461  struct nk_command_circle *cmd;
7462  if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return;
7463  if (b->use_clipping) {
7464  const struct nk_rect *clip = &b->clip;
7465  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
7466  return;
7467  }
7468 
7469  cmd = (struct nk_command_circle*)
7470  nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd));
7471  if (!cmd) return;
7472  cmd->line_thickness = (unsigned short)line_thickness;
7473  cmd->x = (short)r.x;
7474  cmd->y = (short)r.y;
7475  cmd->w = (unsigned short)NK_MAX(r.w, 0);
7476  cmd->h = (unsigned short)NK_MAX(r.h, 0);
7477  cmd->color = c;
7478 }
7479 
7480 NK_API void
7481 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c)
7482 {
7483  struct nk_command_circle_filled *cmd;
7484  NK_ASSERT(b);
7485  if (!b || c.a == 0 || r.w == 0 || r.h == 0) return;
7486  if (b->use_clipping) {
7487  const struct nk_rect *clip = &b->clip;
7488  if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h))
7489  return;
7490  }
7491 
7492  cmd = (struct nk_command_circle_filled*)
7493  nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd));
7494  if (!cmd) return;
7495  cmd->x = (short)r.x;
7496  cmd->y = (short)r.y;
7497  cmd->w = (unsigned short)NK_MAX(r.w, 0);
7498  cmd->h = (unsigned short)NK_MAX(r.h, 0);
7499  cmd->color = c;
7500 }
7501 
7502 NK_API void
7503 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
7504  float a_min, float a_max, float line_thickness, struct nk_color c)
7505 {
7506  struct nk_command_arc *cmd;
7507  if (!b || c.a == 0 || line_thickness <= 0) return;
7508  cmd = (struct nk_command_arc*)
7509  nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd));
7510  if (!cmd) return;
7511  cmd->line_thickness = (unsigned short)line_thickness;
7512  cmd->cx = (short)cx;
7513  cmd->cy = (short)cy;
7514  cmd->r = (unsigned short)radius;
7515  cmd->a[0] = a_min;
7516  cmd->a[1] = a_max;
7517  cmd->color = c;
7518 }
7519 
7520 NK_API void
7521 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius,
7522  float a_min, float a_max, struct nk_color c)
7523 {
7524  struct nk_command_arc_filled *cmd;
7525  NK_ASSERT(b);
7526  if (!b || c.a == 0) return;
7527  cmd = (struct nk_command_arc_filled*)
7528  nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd));
7529  if (!cmd) return;
7530  cmd->cx = (short)cx;
7531  cmd->cy = (short)cy;
7532  cmd->r = (unsigned short)radius;
7533  cmd->a[0] = a_min;
7534  cmd->a[1] = a_max;
7535  cmd->color = c;
7536 }
7537 
7538 NK_API void
7539 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
7540  float y1, float x2, float y2, float line_thickness, struct nk_color c)
7541 {
7542  struct nk_command_triangle *cmd;
7543  NK_ASSERT(b);
7544  if (!b || c.a == 0 || line_thickness <= 0) return;
7545  if (b->use_clipping) {
7546  const struct nk_rect *clip = &b->clip;
7547  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
7548  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
7549  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
7550  return;
7551  }
7552 
7553  cmd = (struct nk_command_triangle*)
7554  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd));
7555  if (!cmd) return;
7556  cmd->line_thickness = (unsigned short)line_thickness;
7557  cmd->a.x = (short)x0;
7558  cmd->a.y = (short)y0;
7559  cmd->b.x = (short)x1;
7560  cmd->b.y = (short)y1;
7561  cmd->c.x = (short)x2;
7562  cmd->c.y = (short)y2;
7563  cmd->color = c;
7564 }
7565 
7566 NK_API void
7567 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1,
7568  float y1, float x2, float y2, struct nk_color c)
7569 {
7571  NK_ASSERT(b);
7572  if (!b || c.a == 0) return;
7573  if (!b) return;
7574  if (b->use_clipping) {
7575  const struct nk_rect *clip = &b->clip;
7576  if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) &&
7577  !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) &&
7578  !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h))
7579  return;
7580  }
7581 
7582  cmd = (struct nk_command_triangle_filled*)
7583  nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd));
7584  if (!cmd) return;
7585  cmd->a.x = (short)x0;
7586  cmd->a.y = (short)y0;
7587  cmd->b.x = (short)x1;
7588  cmd->b.y = (short)y1;
7589  cmd->c.x = (short)x2;
7590  cmd->c.y = (short)y2;
7591  cmd->color = c;
7592 }
7593 
7594 NK_API void
7595 nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count,
7596  float line_thickness, struct nk_color col)
7597 {
7598  int i;
7599  nk_size size = 0;
7600  struct nk_command_polygon *cmd;
7601 
7602  NK_ASSERT(b);
7603  if (!b || col.a == 0 || line_thickness <= 0) return;
7604  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7605  cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size);
7606  if (!cmd) return;
7607  cmd->color = col;
7608  cmd->line_thickness = (unsigned short)line_thickness;
7609  cmd->point_count = (unsigned short)point_count;
7610  for (i = 0; i < point_count; ++i) {
7611  cmd->points[i].x = (short)points[i*2];
7612  cmd->points[i].y = (short)points[i*2+1];
7613  }
7614 }
7615 
7616 NK_API void
7618  struct nk_color col)
7619 {
7620  int i;
7621  nk_size size = 0;
7623 
7624  NK_ASSERT(b);
7625  if (!b || col.a == 0) return;
7626  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7627  cmd = (struct nk_command_polygon_filled*)
7628  nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size);
7629  if (!cmd) return;
7630  cmd->color = col;
7631  cmd->point_count = (unsigned short)point_count;
7632  for (i = 0; i < point_count; ++i) {
7633  cmd->points[i].x = (short)points[i*2+0];
7634  cmd->points[i].y = (short)points[i*2+1];
7635  }
7636 }
7637 
7638 NK_API void
7640  float line_thickness, struct nk_color col)
7641 {
7642  int i;
7643  nk_size size = 0;
7644  struct nk_command_polyline *cmd;
7645 
7646  NK_ASSERT(b);
7647  if (!b || col.a == 0 || line_thickness <= 0) return;
7648  size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count;
7649  cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size);
7650  if (!cmd) return;
7651  cmd->color = col;
7652  cmd->point_count = (unsigned short)point_count;
7653  cmd->line_thickness = (unsigned short)line_thickness;
7654  for (i = 0; i < point_count; ++i) {
7655  cmd->points[i].x = (short)points[i*2];
7656  cmd->points[i].y = (short)points[i*2+1];
7657  }
7658 }
7659 
7660 NK_API void
7661 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r,
7662  const struct nk_image *img, struct nk_color col)
7663 {
7664  struct nk_command_image *cmd;
7665  NK_ASSERT(b);
7666  if (!b) return;
7667  if (b->use_clipping) {
7668  const struct nk_rect *c = &b->clip;
7669  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))
7670  return;
7671  }
7672 
7673  cmd = (struct nk_command_image*)
7674  nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd));
7675  if (!cmd) return;
7676  cmd->x = (short)r.x;
7677  cmd->y = (short)r.y;
7678  cmd->w = (unsigned short)NK_MAX(0, r.w);
7679  cmd->h = (unsigned short)NK_MAX(0, r.h);
7680  cmd->img = *img;
7681  cmd->col = col;
7682 }
7683 
7684 NK_API void
7685 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r,
7687 {
7688  struct nk_command_custom *cmd;
7689  NK_ASSERT(b);
7690  if (!b) return;
7691  if (b->use_clipping) {
7692  const struct nk_rect *c = &b->clip;
7693  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))
7694  return;
7695  }
7696 
7697  cmd = (struct nk_command_custom*)
7698  nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd));
7699  if (!cmd) return;
7700  cmd->x = (short)r.x;
7701  cmd->y = (short)r.y;
7702  cmd->w = (unsigned short)NK_MAX(0, r.w);
7703  cmd->h = (unsigned short)NK_MAX(0, r.h);
7704  cmd->callback_data = usr;
7705  cmd->callback = cb;
7706 }
7707 
7708 NK_API void
7709 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r,
7710  const char *string, int length, const struct nk_user_font *font,
7711  struct nk_color bg, struct nk_color fg)
7712 {
7713  float text_width = 0;
7714  struct nk_command_text *cmd;
7715 
7716  NK_ASSERT(b);
7717  NK_ASSERT(font);
7718  if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return;
7719  if (b->use_clipping) {
7720  const struct nk_rect *c = &b->clip;
7721  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))
7722  return;
7723  }
7724 
7725  /* make sure text fits inside bounds */
7726  text_width = font->width(font->userdata, font->height, string, length);
7727  if (text_width > r.w){
7728  int glyphs = 0;
7729  float txt_width = (float)text_width;
7730  length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0);
7731  }
7732 
7733  if (!length) return;
7734  cmd = (struct nk_command_text*)
7735  nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1));
7736  if (!cmd) return;
7737  cmd->x = (short)r.x;
7738  cmd->y = (short)r.y;
7739  cmd->w = (unsigned short)r.w;
7740  cmd->h = (unsigned short)r.h;
7741  cmd->background = bg;
7742  cmd->foreground = fg;
7743  cmd->font = font;
7744  cmd->length = length;
7745  cmd->height = font->height;
7746  NK_MEMCPY(cmd->string, string, (nk_size)length);
7747  cmd->string[length] = '\0';
7748 }
7749 
7750 /* ==============================================================
7751  *
7752  * DRAW LIST
7753  *
7754  * ===============================================================*/
7755 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
7756 NK_API void
7757 nk_draw_list_init(struct nk_draw_list *list)
7758 {
7759  nk_size i = 0;
7760  NK_ASSERT(list);
7761  if (!list) return;
7762  nk_zero(list, sizeof(*list));
7763  for (i = 0; i < NK_LEN(list->circle_vtx); ++i) {
7764  const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI;
7765  list->circle_vtx[i].x = (float)NK_COS(a);
7766  list->circle_vtx[i].y = (float)NK_SIN(a);
7767  }
7768 }
7769 
7770 NK_API void
7771 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config,
7772  struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements,
7773  enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa)
7774 {
7775  NK_ASSERT(canvas);
7776  NK_ASSERT(config);
7777  NK_ASSERT(cmds);
7778  NK_ASSERT(vertices);
7779  NK_ASSERT(elements);
7780  if (!canvas || !config || !cmds || !vertices || !elements)
7781  return;
7782 
7783  canvas->buffer = cmds;
7784  canvas->config = *config;
7785  canvas->elements = elements;
7786  canvas->vertices = vertices;
7787  canvas->line_AA = line_aa;
7788  canvas->shape_AA = shape_aa;
7789  canvas->clip_rect = nk_null_rect;
7790 }
7791 
7792 NK_API const struct nk_draw_command*
7793 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
7794 {
7795  nk_byte *memory;
7796  nk_size offset;
7797  const struct nk_draw_command *cmd;
7798 
7799  NK_ASSERT(buffer);
7800  if (!buffer || !buffer->size || !canvas->cmd_count)
7801  return 0;
7802 
7803  memory = (nk_byte*)buffer->memory.ptr;
7804  offset = buffer->memory.size - canvas->cmd_offset;
7805  cmd = nk_ptr_add(const struct nk_draw_command, memory, offset);
7806  return cmd;
7807 }
7808 
7809 NK_API const struct nk_draw_command*
7810 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer)
7811 {
7812  nk_size size;
7813  nk_size offset;
7814  nk_byte *memory;
7815  const struct nk_draw_command *end;
7816 
7817  NK_ASSERT(buffer);
7818  NK_ASSERT(canvas);
7819  if (!buffer || !canvas)
7820  return 0;
7821 
7822  memory = (nk_byte*)buffer->memory.ptr;
7823  size = buffer->memory.size;
7824  offset = size - canvas->cmd_offset;
7825  end = nk_ptr_add(const struct nk_draw_command, memory, offset);
7826  end -= (canvas->cmd_count-1);
7827  return end;
7828 }
7829 
7830 NK_API const struct nk_draw_command*
7831 nk__draw_list_next(const struct nk_draw_command *cmd,
7832  const struct nk_buffer *buffer, const struct nk_draw_list *canvas)
7833 {
7834  const struct nk_draw_command *end;
7835  NK_ASSERT(buffer);
7836  NK_ASSERT(canvas);
7837  if (!cmd || !buffer || !canvas)
7838  return 0;
7839 
7840  end = nk__draw_list_end(canvas, buffer);
7841  if (cmd <= end) return 0;
7842  return (cmd-1);
7843 }
7844 
7845 NK_API void
7846 nk_draw_list_clear(struct nk_draw_list *list)
7847 {
7848  NK_ASSERT(list);
7849  if (!list) return;
7850  if (list->buffer)
7851  nk_buffer_clear(list->buffer);
7852  if (list->vertices)
7853  nk_buffer_clear(list->vertices);
7854  if (list->elements)
7855  nk_buffer_clear(list->elements);
7856 
7857  list->element_count = 0;
7858  list->vertex_count = 0;
7859  list->cmd_offset = 0;
7860  list->cmd_count = 0;
7861  list->path_count = 0;
7862  list->vertices = 0;
7863  list->elements = 0;
7864  list->clip_rect = nk_null_rect;
7865 }
7866 
7867 NK_INTERN struct nk_vec2*
7868 nk_draw_list_alloc_path(struct nk_draw_list *list, int count)
7869 {
7870  struct nk_vec2 *points;
7871  NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2);
7872  NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2);
7873  points = (struct nk_vec2*)
7874  nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT,
7875  point_size * (nk_size)count, point_align);
7876 
7877  if (!points) return 0;
7878  if (!list->path_offset) {
7879  void *memory = nk_buffer_memory(list->buffer);
7880  list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory);
7881  }
7882  list->path_count += (unsigned int)count;
7883  return points;
7884 }
7885 
7886 NK_INTERN struct nk_vec2
7887 nk_draw_list_path_last(struct nk_draw_list *list)
7888 {
7889  void *memory;
7890  struct nk_vec2 *point;
7891  NK_ASSERT(list->path_count);
7892  memory = nk_buffer_memory(list->buffer);
7893  point = nk_ptr_add(struct nk_vec2, memory, list->path_offset);
7894  point += (list->path_count-1);
7895  return *point;
7896 }
7897 
7898 NK_INTERN struct nk_draw_command*
7899 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip,
7901 {
7902  NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command);
7903  NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command);
7904  struct nk_draw_command *cmd;
7905 
7906  NK_ASSERT(list);
7907  cmd = (struct nk_draw_command*)
7908  nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align);
7909 
7910  if (!cmd) return 0;
7911  if (!list->cmd_count) {
7912  nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer);
7913  nk_size total = nk_buffer_total(list->buffer);
7914  memory = nk_ptr_add(nk_byte, memory, total);
7915  list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd);
7916  }
7917 
7918  cmd->elem_count = 0;
7919  cmd->clip_rect = clip;
7920  cmd->texture = texture;
7921 #ifdef NK_INCLUDE_COMMAND_USERDATA
7922  cmd->userdata = list->userdata;
7923 #endif
7924 
7925  list->cmd_count++;
7926  list->clip_rect = clip;
7927  return cmd;
7928 }
7929 
7930 NK_INTERN struct nk_draw_command*
7931 nk_draw_list_command_last(struct nk_draw_list *list)
7932 {
7933  void *memory;
7934  nk_size size;
7935  struct nk_draw_command *cmd;
7936  NK_ASSERT(list->cmd_count);
7937 
7938  memory = nk_buffer_memory(list->buffer);
7939  size = nk_buffer_total(list->buffer);
7940  cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset);
7941  return (cmd - (list->cmd_count-1));
7942 }
7943 
7944 NK_INTERN void
7945 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect)
7946 {
7947  NK_ASSERT(list);
7948  if (!list) return;
7949  if (!list->cmd_count) {
7950  nk_draw_list_push_command(list, rect, list->config.null.texture);
7951  } else {
7952  struct nk_draw_command *prev = nk_draw_list_command_last(list);
7953  if (prev->elem_count == 0)
7954  prev->clip_rect = rect;
7955  nk_draw_list_push_command(list, rect, prev->texture);
7956  }
7957 }
7958 
7959 NK_INTERN void
7960 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture)
7961 {
7962  NK_ASSERT(list);
7963  if (!list) return;
7964  if (!list->cmd_count) {
7965  nk_draw_list_push_command(list, nk_null_rect, texture);
7966  } else {
7967  struct nk_draw_command *prev = nk_draw_list_command_last(list);
7968  if (prev->elem_count == 0)
7969  prev->texture = texture;
7970  else if (prev->texture.id != texture.id)
7971  nk_draw_list_push_command(list, prev->clip_rect, texture);
7972  }
7973 }
7974 
7975 #ifdef NK_INCLUDE_COMMAND_USERDATA
7976 NK_API void
7977 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata)
7978 {
7979  list->userdata = userdata;
7980 }
7981 #endif
7982 
7983 NK_INTERN void*
7984 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count)
7985 {
7986  void *vtx;
7987  NK_ASSERT(list);
7988  if (!list) return 0;
7989  vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT,
7990  list->config.vertex_size*count, list->config.vertex_alignment);
7991  if (!vtx) return 0;
7992  list->vertex_count += (unsigned int)count;
7993  return vtx;
7994 }
7995 
7996 NK_INTERN nk_draw_index*
7997 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count)
7998 {
7999  nk_draw_index *ids;
8000  struct nk_draw_command *cmd;
8001  NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index);
8002  NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index);
8003  NK_ASSERT(list);
8004  if (!list) return 0;
8005 
8006  ids = (nk_draw_index*)
8007  nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align);
8008  if (!ids) return 0;
8009  cmd = nk_draw_list_command_last(list);
8010  list->element_count += (unsigned int)count;
8011  cmd->elem_count += (unsigned int)count;
8012  return ids;
8013 }
8014 
8015 NK_INTERN int
8016 nk_draw_vertex_layout_element_is_end_of_layout(
8017  const struct nk_draw_vertex_layout_element *element)
8018 {
8019  return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT ||
8020  element->format == NK_FORMAT_COUNT);
8021 }
8022 
8023 NK_INTERN void
8024 nk_draw_vertex_color(void *attribute, const float *values,
8025  enum nk_draw_vertex_layout_format format)
8026 {
8027  /* if this triggers you tried to provide a value format for a color */
8028  NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN);
8029  NK_ASSERT(format <= NK_FORMAT_COLOR_END);
8030  if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return;
8031 
8032  switch (format) {
8033  default: NK_ASSERT(0 && "Invalid vertex layout color format"); break;
8034  case NK_FORMAT_R8G8B8A8:
8035  case NK_FORMAT_R8G8B8: {
8036  struct nk_color col = nk_rgba_fv(values);
8037  NK_MEMCPY(attribute, &col.r, sizeof(col));
8038  } break;
8039  case NK_FORMAT_B8G8R8A8: {
8040  struct nk_color col = nk_rgba_fv(values);
8041  struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a);
8042  NK_MEMCPY(attribute, &bgra, sizeof(bgra));
8043  } break;
8044  case NK_FORMAT_R16G15B16: {
8045  nk_ushort col[3];
8046  col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);
8047  col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX);
8048  col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX);
8049  NK_MEMCPY(attribute, col, sizeof(col));
8050  } break;
8051  case NK_FORMAT_R16G15B16A16: {
8052  nk_ushort col[4];
8053  col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX);
8054  col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX);
8055  col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX);
8056  col[3] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[3] * NK_USHORT_MAX, NK_USHORT_MAX);
8057  NK_MEMCPY(attribute, col, sizeof(col));
8058  } break;
8059  case NK_FORMAT_R32G32B32: {
8060  nk_uint col[3];
8061  col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX);
8062  col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX);
8063  col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX);
8064  NK_MEMCPY(attribute, col, sizeof(col));
8065  } break;
8066  case NK_FORMAT_R32G32B32A32: {
8067  nk_uint col[4];
8068  col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX);
8069  col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX);
8070  col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX);
8071  col[3] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[3] * NK_UINT_MAX, NK_UINT_MAX);
8072  NK_MEMCPY(attribute, col, sizeof(col));
8073  } break;
8074  case NK_FORMAT_R32G32B32A32_FLOAT:
8075  NK_MEMCPY(attribute, values, sizeof(float)*4);
8076  break;
8077  case NK_FORMAT_R32G32B32A32_DOUBLE: {
8078  double col[4];
8079  col[0] = (double)NK_SATURATE(values[0]);
8080  col[1] = (double)NK_SATURATE(values[1]);
8081  col[2] = (double)NK_SATURATE(values[2]);
8082  col[3] = (double)NK_SATURATE(values[3]);
8083  NK_MEMCPY(attribute, col, sizeof(col));
8084  } break;
8085  case NK_FORMAT_RGB32:
8086  case NK_FORMAT_RGBA32: {
8087  struct nk_color col = nk_rgba_fv(values);
8089  NK_MEMCPY(attribute, &color, sizeof(color));
8090  } break;
8091  }
8092 }
8093 
8094 NK_INTERN void
8095 nk_draw_vertex_element(void *dst, const float *values, int value_count,
8096  enum nk_draw_vertex_layout_format format)
8097 {
8098  int value_index;
8099  void *attribute = dst;
8100  /* if this triggers you tried to provide a color format for a value */
8101  NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN);
8102  if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return;
8103  for (value_index = 0; value_index < value_count; ++value_index) {
8104  switch (format) {
8105  default: NK_ASSERT(0 && "invalid vertex layout format"); break;
8106  case NK_FORMAT_SCHAR: {
8107  char value = (char)NK_CLAMP(NK_SCHAR_MIN, values[value_index], NK_SCHAR_MAX);
8108  NK_MEMCPY(attribute, &value, sizeof(value));
8109  attribute = (void*)((char*)attribute + sizeof(char));
8110  } break;
8111  case NK_FORMAT_SSHORT: {
8112  nk_short value = (nk_short)NK_CLAMP(NK_SSHORT_MIN, values[value_index], NK_SSHORT_MAX);
8113  NK_MEMCPY(attribute, &value, sizeof(value));
8114  attribute = (void*)((char*)attribute + sizeof(value));
8115  } break;
8116  case NK_FORMAT_SINT: {
8117  nk_int value = (nk_int)NK_CLAMP(NK_SINT_MIN, values[value_index], NK_SINT_MAX);
8118  NK_MEMCPY(attribute, &value, sizeof(value));
8119  attribute = (void*)((char*)attribute + sizeof(nk_int));
8120  } break;
8121  case NK_FORMAT_UCHAR: {
8122  unsigned char value = (unsigned char)NK_CLAMP(NK_UCHAR_MIN, values[value_index], NK_UCHAR_MAX);
8123  NK_MEMCPY(attribute, &value, sizeof(value));
8124  attribute = (void*)((char*)attribute + sizeof(unsigned char));
8125  } break;
8126  case NK_FORMAT_USHORT: {
8127  nk_ushort value = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[value_index], NK_USHORT_MAX);
8128  NK_MEMCPY(attribute, &value, sizeof(value));
8129  attribute = (void*)((char*)attribute + sizeof(value));
8130  } break;
8131  case NK_FORMAT_UINT: {
8132  nk_uint value = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[value_index], NK_UINT_MAX);
8133  NK_MEMCPY(attribute, &value, sizeof(value));
8134  attribute = (void*)((char*)attribute + sizeof(nk_uint));
8135  } break;
8136  case NK_FORMAT_FLOAT:
8137  NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index]));
8138  attribute = (void*)((char*)attribute + sizeof(float));
8139  break;
8140  case NK_FORMAT_DOUBLE: {
8141  double value = (double)values[value_index];
8142  NK_MEMCPY(attribute, &value, sizeof(value));
8143  attribute = (void*)((char*)attribute + sizeof(double));
8144  } break;
8145  }
8146  }
8147 }
8148 
8149 NK_INTERN void*
8150 nk_draw_vertex(void *dst, const struct nk_convert_config *config,
8151  struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color)
8152 {
8153  void *result = (void*)((char*)dst + config->vertex_size);
8154  const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout;
8155  while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) {
8156  void *address = (void*)((char*)dst + elem_iter->offset);
8157  switch (elem_iter->attribute) {
8158  case NK_VERTEX_ATTRIBUTE_COUNT:
8159  default: NK_ASSERT(0 && "wrong element attribute");
8160  case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break;
8161  case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break;
8162  case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break;
8163  }
8164  elem_iter++;
8165  }
8166  return result;
8167 }
8168 
8169 NK_API void
8170 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points,
8171  const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed,
8172  float thickness, enum nk_anti_aliasing aliasing)
8173 {
8174  nk_size count;
8175  int thick_line;
8176  struct nk_colorf col;
8177  struct nk_colorf col_trans;
8178  NK_ASSERT(list);
8179  if (!list || points_count < 2) return;
8180 
8181  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8182  count = points_count;
8183  if (!closed) count = points_count-1;
8184  thick_line = thickness > 1.0f;
8185 
8186 #ifdef NK_INCLUDE_COMMAND_USERDATA
8187  nk_draw_list_push_userdata(list, list->userdata);
8188 #endif
8189 
8190  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8191  nk_color_fv(&col.r, color);
8192  col_trans = col;
8193  col_trans.a = 0;
8194 
8195  if (aliasing == NK_ANTI_ALIASING_ON) {
8196  /* ANTI-ALIASED STROKE */
8197  const float AA_SIZE = 1.0f;
8198  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
8199  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
8200 
8201  /* allocate vertices and elements */
8202  nk_size i1 = 0;
8203  nk_size vertex_offset;
8204  nk_size index = list->vertex_count;
8205 
8206  const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12);
8207  const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3);
8208 
8209  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8210  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8211 
8212  nk_size size;
8213  struct nk_vec2 *normals, *temp;
8214  if (!vtx || !ids) return;
8215 
8216  /* temporary allocate normals + points */
8217  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
8218  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
8219  size = pnt_size * ((thick_line) ? 5 : 3) * points_count;
8220  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
8221  NK_ASSERT(normals);
8222  if (!normals) return;
8223  temp = normals + points_count;
8224 
8225  /* make sure vertex pointer is still correct */
8226  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
8227 
8228  /* calculate normals */
8229  for (i1 = 0; i1 < count; ++i1) {
8230  const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
8231  struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]);
8232  float len;
8233 
8234  /* vec2 inverted length */
8235  len = nk_vec2_len_sqr(diff);
8236  if (len != 0.0f)
8237  len = nk_inv_sqrt(len);
8238  else len = 1.0f;
8239 
8240  diff = nk_vec2_muls(diff, len);
8241  normals[i1].x = diff.y;
8242  normals[i1].y = -diff.x;
8243  }
8244 
8245  if (!closed)
8246  normals[points_count-1] = normals[points_count-2];
8247 
8248  if (!thick_line) {
8249  nk_size idx1, i;
8250  if (!closed) {
8251  struct nk_vec2 d;
8252  temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE));
8253  temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE));
8254  d = nk_vec2_muls(normals[points_count-1], AA_SIZE);
8255  temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d);
8256  temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d);
8257  }
8258 
8259  /* fill elements */
8260  idx1 = index;
8261  for (i1 = 0; i1 < count; i1++) {
8262  struct nk_vec2 dm;
8263  float dmr2;
8264  nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1);
8265  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3);
8266 
8267  /* average normals */
8268  dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
8269  dmr2 = dm.x * dm.x + dm.y* dm.y;
8270  if (dmr2 > 0.000001f) {
8271  float scale = 1.0f/dmr2;
8272  scale = NK_MIN(100.0f, scale);
8273  dm = nk_vec2_muls(dm, scale);
8274  }
8275 
8276  dm = nk_vec2_muls(dm, AA_SIZE);
8277  temp[i2*2+0] = nk_vec2_add(points[i2], dm);
8278  temp[i2*2+1] = nk_vec2_sub(points[i2], dm);
8279 
8280  ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0);
8281  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
8282  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0);
8283  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
8284  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
8285  ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1);
8286  ids += 12;
8287  idx1 = idx2;
8288  }
8289 
8290  /* fill vertices */
8291  for (i = 0; i < points_count; ++i) {
8292  const struct nk_vec2 uv = list->config.null.uv;
8293  vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col);
8294  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans);
8295  vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans);
8296  }
8297  } else {
8298  nk_size idx1, i;
8299  const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f;
8300  if (!closed) {
8301  struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE);
8302  struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness);
8303 
8304  temp[0] = nk_vec2_add(points[0], d1);
8305  temp[1] = nk_vec2_add(points[0], d2);
8306  temp[2] = nk_vec2_sub(points[0], d2);
8307  temp[3] = nk_vec2_sub(points[0], d1);
8308 
8309  d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE);
8310  d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness);
8311 
8312  temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1);
8313  temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2);
8314  temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2);
8315  temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1);
8316  }
8317 
8318  /* add all elements */
8319  idx1 = index;
8320  for (i1 = 0; i1 < count; ++i1) {
8321  struct nk_vec2 dm_out, dm_in;
8322  const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1);
8323  nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4);
8324 
8325  /* average normals */
8326  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f);
8327  float dmr2 = dm.x * dm.x + dm.y* dm.y;
8328  if (dmr2 > 0.000001f) {
8329  float scale = 1.0f/dmr2;
8330  scale = NK_MIN(100.0f, scale);
8331  dm = nk_vec2_muls(dm, scale);
8332  }
8333 
8334  dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE));
8335  dm_in = nk_vec2_muls(dm, half_inner_thickness);
8336  temp[i2*4+0] = nk_vec2_add(points[i2], dm_out);
8337  temp[i2*4+1] = nk_vec2_add(points[i2], dm_in);
8338  temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in);
8339  temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out);
8340 
8341  /* add indexes */
8342  ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1);
8343  ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2);
8344  ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1);
8345  ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1);
8346  ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0);
8347  ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1);
8348  ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2);
8349  ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3);
8350  ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2);
8351  ids += 18;
8352  idx1 = idx2;
8353  }
8354 
8355  /* add vertices */
8356  for (i = 0; i < points_count; ++i) {
8357  const struct nk_vec2 uv = list->config.null.uv;
8358  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans);
8359  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col);
8360  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col);
8361  vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans);
8362  }
8363  }
8364  /* free temporary normals + points */
8365  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
8366  } else {
8367  /* NON ANTI-ALIASED STROKE */
8368  nk_size i1 = 0;
8369  nk_size idx = list->vertex_count;
8370  const nk_size idx_count = count * 6;
8371  const nk_size vtx_count = count * 4;
8372  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8373  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8374  if (!vtx || !ids) return;
8375 
8376  for (i1 = 0; i1 < count; ++i1) {
8377  float dx, dy;
8378  const struct nk_vec2 uv = list->config.null.uv;
8379  const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1;
8380  const struct nk_vec2 p1 = points[i1];
8381  const struct nk_vec2 p2 = points[i2];
8382  struct nk_vec2 diff = nk_vec2_sub(p2, p1);
8383  float len;
8384 
8385  /* vec2 inverted length */
8386  len = nk_vec2_len_sqr(diff);
8387  if (len != 0.0f)
8388  len = nk_inv_sqrt(len);
8389  else len = 1.0f;
8390  diff = nk_vec2_muls(diff, len);
8391 
8392  /* add vertices */
8393  dx = diff.x * (thickness * 0.5f);
8394  dy = diff.y * (thickness * 0.5f);
8395 
8396  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col);
8397  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col);
8398  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col);
8399  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col);
8400 
8401  ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1);
8402  ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0);
8403  ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3);
8404 
8405  ids += 6;
8406  idx += 4;
8407  }
8408  }
8409 }
8410 
8411 NK_API void
8412 nk_draw_list_fill_poly_convex(struct nk_draw_list *list,
8413  const struct nk_vec2 *points, const unsigned int points_count,
8414  struct nk_color color, enum nk_anti_aliasing aliasing)
8415 {
8416  struct nk_colorf col;
8417  struct nk_colorf col_trans;
8418 
8419  NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2);
8420  NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2);
8421  NK_ASSERT(list);
8422  if (!list || points_count < 3) return;
8423 
8424 #ifdef NK_INCLUDE_COMMAND_USERDATA
8425  nk_draw_list_push_userdata(list, list->userdata);
8426 #endif
8427 
8428  color.a = (nk_byte)((float)color.a * list->config.global_alpha);
8429  nk_color_fv(&col.r, color);
8430  col_trans = col;
8431  col_trans.a = 0;
8432 
8433  if (aliasing == NK_ANTI_ALIASING_ON) {
8434  nk_size i = 0;
8435  nk_size i0 = 0;
8436  nk_size i1 = 0;
8437 
8438  const float AA_SIZE = 1.0f;
8439  nk_size vertex_offset = 0;
8440  nk_size index = list->vertex_count;
8441 
8442  const nk_size idx_count = (points_count-2)*3 + points_count*6;
8443  const nk_size vtx_count = (points_count*2);
8444 
8445  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8446  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8447 
8448  nk_size size = 0;
8449  struct nk_vec2 *normals = 0;
8450  unsigned int vtx_inner_idx = (unsigned int)(index + 0);
8451  unsigned int vtx_outer_idx = (unsigned int)(index + 1);
8452  if (!vtx || !ids) return;
8453 
8454  /* temporary allocate normals */
8455  vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr);
8456  nk_buffer_mark(list->vertices, NK_BUFFER_FRONT);
8457  size = pnt_size * points_count;
8458  normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align);
8459  NK_ASSERT(normals);
8460  if (!normals) return;
8461  vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset);
8462 
8463  /* add elements */
8464  for (i = 2; i < points_count; i++) {
8465  ids[0] = (nk_draw_index)(vtx_inner_idx);
8466  ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1));
8467  ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1));
8468  ids += 3;
8469  }
8470 
8471  /* compute normals */
8472  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
8473  struct nk_vec2 p0 = points[i0];
8474  struct nk_vec2 p1 = points[i1];
8475  struct nk_vec2 diff = nk_vec2_sub(p1, p0);
8476 
8477  /* vec2 inverted length */
8478  float len = nk_vec2_len_sqr(diff);
8479  if (len != 0.0f)
8480  len = nk_inv_sqrt(len);
8481  else len = 1.0f;
8482  diff = nk_vec2_muls(diff, len);
8483 
8484  normals[i0].x = diff.y;
8485  normals[i0].y = -diff.x;
8486  }
8487 
8488  /* add vertices + indexes */
8489  for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) {
8490  const struct nk_vec2 uv = list->config.null.uv;
8491  struct nk_vec2 n0 = normals[i0];
8492  struct nk_vec2 n1 = normals[i1];
8493  struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f);
8494  float dmr2 = dm.x*dm.x + dm.y*dm.y;
8495  if (dmr2 > 0.000001f) {
8496  float scale = 1.0f / dmr2;
8497  scale = NK_MIN(scale, 100.0f);
8498  dm = nk_vec2_muls(dm, scale);
8499  }
8500  dm = nk_vec2_muls(dm, AA_SIZE * 0.5f);
8501 
8502  /* add vertices */
8503  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col);
8504  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans);
8505 
8506  /* add indexes */
8507  ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
8508  ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1));
8509  ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
8510  ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1));
8511  ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1));
8512  ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1));
8513  ids += 6;
8514  }
8515  /* free temporary normals + points */
8516  nk_buffer_reset(list->vertices, NK_BUFFER_FRONT);
8517  } else {
8518  nk_size i = 0;
8519  nk_size index = list->vertex_count;
8520  const nk_size idx_count = (points_count-2)*3;
8521  const nk_size vtx_count = points_count;
8522  void *vtx = nk_draw_list_alloc_vertices(list, vtx_count);
8523  nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count);
8524 
8525  if (!vtx || !ids) return;
8526  for (i = 0; i < vtx_count; ++i)
8527  vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col);
8528  for (i = 2; i < points_count; ++i) {
8529  ids[0] = (nk_draw_index)index;
8530  ids[1] = (nk_draw_index)(index+ i - 1);
8531  ids[2] = (nk_draw_index)(index+i);
8532  ids += 3;
8533  }
8534  }
8535 }
8536 
8537 NK_API void
8538 nk_draw_list_path_clear(struct nk_draw_list *list)
8539 {
8540  NK_ASSERT(list);
8541  if (!list) return;
8542  nk_buffer_reset(list->buffer, NK_BUFFER_FRONT);
8543  list->path_count = 0;
8544  list->path_offset = 0;
8545 }
8546 
8547 NK_API void
8548 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos)
8549 {
8550  struct nk_vec2 *points = 0;
8551  struct nk_draw_command *cmd = 0;
8552  NK_ASSERT(list);
8553  if (!list) return;
8554  if (!list->cmd_count)
8555  nk_draw_list_add_clip(list, nk_null_rect);
8556 
8557  cmd = nk_draw_list_command_last(list);
8558  if (cmd && cmd->texture.ptr != list->config.null.texture.ptr)
8559  nk_draw_list_push_image(list, list->config.null.texture);
8560 
8561  points = nk_draw_list_alloc_path(list, 1);
8562  if (!points) return;
8563  points[0] = pos;
8564 }
8565 
8566 NK_API void
8567 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center,
8568  float radius, int a_min, int a_max)
8569 {
8570  int a = 0;
8571  NK_ASSERT(list);
8572  if (!list) return;
8573  if (a_min <= a_max) {
8574  for (a = a_min; a <= a_max; a++) {
8575  const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)];
8576  const float x = center.x + c.x * radius;
8577  const float y = center.y + c.y * radius;
8578  nk_draw_list_path_line_to(list, nk_vec2(x, y));
8579  }
8580  }
8581 }
8582 
8583 NK_API void
8584 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center,
8585  float radius, float a_min, float a_max, unsigned int segments)
8586 {
8587  unsigned int i = 0;
8588  NK_ASSERT(list);
8589  if (!list) return;
8590  if (radius == 0.0f) return;
8591 
8592  /* This algorithm for arc drawing relies on these two trigonometric identities[1]:
8593  sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b)
8594  cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b)
8595 
8596  Two coordinates (x, y) of a point on a circle centered on
8597  the origin can be written in polar form as:
8598  x = r * cos(a)
8599  y = r * sin(a)
8600  where r is the radius of the circle,
8601  a is the angle between (x, y) and the origin.
8602 
8603  This allows us to rotate the coordinates around the
8604  origin by an angle b using the following transformation:
8605  x' = r * cos(a + b) = x * cos(b) - y * sin(b)
8606  y' = r * sin(a + b) = y * cos(b) + x * sin(b)
8607 
8608  [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities
8609  */
8610  const float d_angle = (a_max - a_min) / (float)segments;
8611  const float sin_d = (float)NK_SIN(d_angle);
8612  const float cos_d = (float)NK_COS(d_angle);
8613 
8614  float cx = (float)NK_COS(a_min) * radius;
8615  float cy = (float)NK_SIN(a_min) * radius;
8616  for(i = 0; i <= segments; ++i) {
8617  const float x = center.x + cx;
8618  const float y = center.y + cy;
8619  nk_draw_list_path_line_to(list, nk_vec2(x, y));
8620 
8621  const float new_cx = cx * cos_d - cy * sin_d;
8622  const float new_cy = cy * cos_d + cx * sin_d;
8623  cx = new_cx;
8624  cy = new_cy;
8625  }
8626 }
8627 
8628 NK_API void
8629 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a,
8630  struct nk_vec2 b, float rounding)
8631 {
8632  float r;
8633  NK_ASSERT(list);
8634  if (!list) return;
8635  r = rounding;
8636  r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x));
8637  r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y));
8638 
8639  if (r == 0.0f) {
8640  nk_draw_list_path_line_to(list, a);
8641  nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y));
8642  nk_draw_list_path_line_to(list, b);
8643  nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y));
8644  } else {
8645  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9);
8646  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12);
8647  nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3);
8648  nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6);
8649  }
8650 }
8651 
8652 NK_API void
8653 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2,
8654  struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments)
8655 {
8656  float t_step;
8657  unsigned int i_step;
8658  struct nk_vec2 p1;
8659 
8660  NK_ASSERT(list);
8661  NK_ASSERT(list->path_count);
8662  if (!list || !list->path_count) return;
8663  num_segments = NK_MAX(num_segments, 1);
8664 
8665  p1 = nk_draw_list_path_last(list);
8666  t_step = 1.0f/(float)num_segments;
8667  for (i_step = 1; i_step <= num_segments; ++i_step) {
8668  float t = t_step * (float)i_step;
8669  float u = 1.0f - t;
8670  float w1 = u*u*u;
8671  float w2 = 3*u*u*t;
8672  float w3 = 3*u*t*t;
8673  float w4 = t * t *t;
8674  float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x;
8675  float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y;
8676  nk_draw_list_path_line_to(list, nk_vec2(x,y));
8677  }
8678 }
8679 
8680 NK_API void
8681 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color)
8682 {
8683  struct nk_vec2 *points;
8684  NK_ASSERT(list);
8685  if (!list) return;
8686  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
8687  nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA);
8688  nk_draw_list_path_clear(list);
8689 }
8690 
8691 NK_API void
8692 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color,
8693  enum nk_draw_list_stroke closed, float thickness)
8694 {
8695  struct nk_vec2 *points;
8696  NK_ASSERT(list);
8697  if (!list) return;
8698  points = (struct nk_vec2*)nk_buffer_memory(list->buffer);
8699  nk_draw_list_stroke_poly_line(list, points, list->path_count, color,
8700  closed, thickness, list->config.line_AA);
8701  nk_draw_list_path_clear(list);
8702 }
8703 
8704 NK_API void
8705 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a,
8706  struct nk_vec2 b, struct nk_color col, float thickness)
8707 {
8708  NK_ASSERT(list);
8709  if (!list || !col.a) return;
8710  if (list->line_AA == NK_ANTI_ALIASING_ON) {
8711  nk_draw_list_path_line_to(list, a);
8712  nk_draw_list_path_line_to(list, b);
8713  } else {
8714  nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f)));
8715  nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f)));
8716  }
8717  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
8718 }
8719 
8720 NK_API void
8721 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect,
8722  struct nk_color col, float rounding)
8723 {
8724  NK_ASSERT(list);
8725  if (!list || !col.a) return;
8726 
8727  if (list->line_AA == NK_ANTI_ALIASING_ON) {
8728  nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
8729  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8730  } else {
8731  nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
8732  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8733  } nk_draw_list_path_fill(list, col);
8734 }
8735 
8736 NK_API void
8737 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect,
8738  struct nk_color col, float rounding, float thickness)
8739 {
8740  NK_ASSERT(list);
8741  if (!list || !col.a) return;
8742  if (list->line_AA == NK_ANTI_ALIASING_ON) {
8743  nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y),
8744  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8745  } else {
8746  nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f),
8747  nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding);
8748  } nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8749 }
8750 
8751 NK_API void
8752 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect,
8753  struct nk_color left, struct nk_color top, struct nk_color right,
8754  struct nk_color bottom)
8755 {
8756  void *vtx;
8757  struct nk_colorf col_left, col_top;
8758  struct nk_colorf col_right, col_bottom;
8759  nk_draw_index *idx;
8760  nk_draw_index index;
8761 
8762  nk_color_fv(&col_left.r, left);
8763  nk_color_fv(&col_right.r, right);
8764  nk_color_fv(&col_top.r, top);
8765  nk_color_fv(&col_bottom.r, bottom);
8766 
8767  NK_ASSERT(list);
8768  if (!list) return;
8769 
8770  nk_draw_list_push_image(list, list->config.null.texture);
8771  index = (nk_draw_index)list->vertex_count;
8772  vtx = nk_draw_list_alloc_vertices(list, 4);
8773  idx = nk_draw_list_alloc_elements(list, 6);
8774  if (!vtx || !idx) return;
8775 
8776  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
8777  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
8778  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
8779 
8780  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left);
8781  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top);
8782  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right);
8783  vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom);
8784 }
8785 
8786 NK_API void
8787 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a,
8788  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col)
8789 {
8790  NK_ASSERT(list);
8791  if (!list || !col.a) return;
8792  nk_draw_list_path_line_to(list, a);
8793  nk_draw_list_path_line_to(list, b);
8794  nk_draw_list_path_line_to(list, c);
8795  nk_draw_list_path_fill(list, col);
8796 }
8797 
8798 NK_API void
8799 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a,
8800  struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness)
8801 {
8802  NK_ASSERT(list);
8803  if (!list || !col.a) return;
8804  nk_draw_list_path_line_to(list, a);
8805  nk_draw_list_path_line_to(list, b);
8806  nk_draw_list_path_line_to(list, c);
8807  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8808 }
8809 
8810 NK_API void
8811 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center,
8812  float radius, struct nk_color col, unsigned int segs)
8813 {
8814  float a_max;
8815  NK_ASSERT(list);
8816  if (!list || !col.a) return;
8817  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
8818  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
8819  nk_draw_list_path_fill(list, col);
8820 }
8821 
8822 NK_API void
8823 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center,
8824  float radius, struct nk_color col, unsigned int segs, float thickness)
8825 {
8826  float a_max;
8827  NK_ASSERT(list);
8828  if (!list || !col.a) return;
8829  a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs;
8830  nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs);
8831  nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness);
8832 }
8833 
8834 NK_API void
8835 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0,
8836  struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1,
8837  struct nk_color col, unsigned int segments, float thickness)
8838 {
8839  NK_ASSERT(list);
8840  if (!list || !col.a) return;
8841  nk_draw_list_path_line_to(list, p0);
8842  nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments);
8843  nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness);
8844 }
8845 
8846 NK_INTERN void
8847 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a,
8848  struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc,
8849  struct nk_color color)
8850 {
8851  void *vtx;
8852  struct nk_vec2 uvb;
8853  struct nk_vec2 uvd;
8854  struct nk_vec2 b;
8855  struct nk_vec2 d;
8856 
8857  struct nk_colorf col;
8858  nk_draw_index *idx;
8859  nk_draw_index index;
8860  NK_ASSERT(list);
8861  if (!list) return;
8862 
8863  nk_color_fv(&col.r, color);
8864  uvb = nk_vec2(uvc.x, uva.y);
8865  uvd = nk_vec2(uva.x, uvc.y);
8866  b = nk_vec2(c.x, a.y);
8867  d = nk_vec2(a.x, c.y);
8868 
8869  index = (nk_draw_index)list->vertex_count;
8870  vtx = nk_draw_list_alloc_vertices(list, 4);
8871  idx = nk_draw_list_alloc_elements(list, 6);
8872  if (!vtx || !idx) return;
8873 
8874  idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1);
8875  idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0);
8876  idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3);
8877 
8878  vtx = nk_draw_vertex(vtx, &list->config, a, uva, col);
8879  vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col);
8880  vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col);
8881  vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col);
8882 }
8883 
8884 NK_API void
8885 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture,
8886  struct nk_rect rect, struct nk_color color)
8887 {
8888  NK_ASSERT(list);
8889  if (!list) return;
8890  /* push new command with given texture */
8891  nk_draw_list_push_image(list, texture.handle);
8892  if (nk_image_is_subimage(&texture)) {
8893  /* add region inside of the texture */
8894  struct nk_vec2 uv[2];
8895  uv[0].x = (float)texture.region[0]/(float)texture.w;
8896  uv[0].y = (float)texture.region[1]/(float)texture.h;
8897  uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w;
8898  uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h;
8899  nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
8900  nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color);
8901  } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y),
8902  nk_vec2(rect.x + rect.w, rect.y + rect.h),
8903  nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color);
8904 }
8905 
8906 NK_API void
8907 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font,
8908  struct nk_rect rect, const char *text, int len, float font_height,
8909  struct nk_color fg)
8910 {
8911  float x = 0;
8912  int text_len = 0;
8913  nk_rune unicode = 0;
8914  nk_rune next = 0;
8915  int glyph_len = 0;
8916  int next_glyph_len = 0;
8917  struct nk_user_font_glyph g;
8918 
8919  NK_ASSERT(list);
8920  if (!list || !len || !text) return;
8921  if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h,
8922  list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return;
8923 
8924  nk_draw_list_push_image(list, font->texture);
8925  x = rect.x;
8926  glyph_len = nk_utf_decode(text, &unicode, len);
8927  if (!glyph_len) return;
8928 
8929  /* draw every glyph image */
8930  fg.a = (nk_byte)((float)fg.a * list->config.global_alpha);
8931  while (text_len < len && glyph_len) {
8932  float gx, gy, gh, gw;
8933  float char_width = 0;
8934  if (unicode == NK_UTF_INVALID) break;
8935 
8936  /* query currently drawn glyph information */
8937  next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len);
8938  font->query(font->userdata, font_height, &g, unicode,
8939  (next == NK_UTF_INVALID) ? '\0' : next);
8940 
8941  /* calculate and draw glyph drawing rectangle and image */
8942  gx = x + g.offset.x;
8943  gy = rect.y + g.offset.y;
8944  gw = g.width; gh = g.height;
8945  char_width = g.xadvance;
8946  nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh),
8947  g.uv[0], g.uv[1], fg);
8948 
8949  /* offset next glyph */
8950  text_len += glyph_len;
8951  x += char_width;
8952  glyph_len = next_glyph_len;
8953  unicode = next;
8954  }
8955 }
8956 
8958 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds,
8959  struct nk_buffer *vertices, struct nk_buffer *elements,
8960  const struct nk_convert_config *config)
8961 {
8963  const struct nk_command *cmd;
8964  NK_ASSERT(ctx);
8965  NK_ASSERT(cmds);
8966  NK_ASSERT(vertices);
8967  NK_ASSERT(elements);
8968  NK_ASSERT(config);
8969  NK_ASSERT(config->vertex_layout);
8970  NK_ASSERT(config->vertex_size);
8971  if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout)
8972  return NK_CONVERT_INVALID_PARAM;
8973 
8974  nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements,
8975  config->line_AA, config->shape_AA);
8976  nk_foreach(cmd, ctx)
8977  {
8978 #ifdef NK_INCLUDE_COMMAND_USERDATA
8979  ctx->draw_list.userdata = cmd->userdata;
8980 #endif
8981  switch (cmd->type) {
8982  case NK_COMMAND_NOP: break;
8983  case NK_COMMAND_SCISSOR: {
8984  const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd;
8985  nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h));
8986  } break;
8987  case NK_COMMAND_LINE: {
8988  const struct nk_command_line *l = (const struct nk_command_line*)cmd;
8989  nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y),
8990  nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness);
8991  } break;
8992  case NK_COMMAND_CURVE: {
8993  const struct nk_command_curve *q = (const struct nk_command_curve*)cmd;
8994  nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y),
8995  nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x,
8996  q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color,
8997  config->curve_segment_count, q->line_thickness);
8998  } break;
8999  case NK_COMMAND_RECT: {
9000  const struct nk_command_rect *r = (const struct nk_command_rect*)cmd;
9001  nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
9002  r->color, (float)r->rounding, r->line_thickness);
9003  } break;
9004  case NK_COMMAND_RECT_FILLED: {
9005  const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd;
9006  nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
9007  r->color, (float)r->rounding);
9008  } break;
9010  const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd;
9011  nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h),
9012  r->left, r->top, r->right, r->bottom);
9013  } break;
9014  case NK_COMMAND_CIRCLE: {
9015  const struct nk_command_circle *c = (const struct nk_command_circle*)cmd;
9016  nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
9017  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
9018  config->circle_segment_count, c->line_thickness);
9019  } break;
9020  case NK_COMMAND_CIRCLE_FILLED: {
9021  const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd;
9022  nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2,
9023  (float)c->y + (float)c->h/2), (float)c->w/2, c->color,
9024  config->circle_segment_count);
9025  } break;
9026  case NK_COMMAND_ARC: {
9027  const struct nk_command_arc *c = (const struct nk_command_arc*)cmd;
9028  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
9029  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
9030  c->a[0], c->a[1], config->arc_segment_count);
9031  nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness);
9032  } break;
9033  case NK_COMMAND_ARC_FILLED: {
9034  const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd;
9035  nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy));
9036  nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r,
9037  c->a[0], c->a[1], config->arc_segment_count);
9038  nk_draw_list_path_fill(&ctx->draw_list, c->color);
9039  } break;
9040  case NK_COMMAND_TRIANGLE: {
9041  const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd;
9042  nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
9043  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color,
9044  t->line_thickness);
9045  } break;
9047  const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd;
9048  nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y),
9049  nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color);
9050  } break;
9051  case NK_COMMAND_POLYGON: {
9052  int i;
9053  const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd;
9054  for (i = 0; i < p->point_count; ++i) {
9055  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
9056  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
9057  }
9058  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness);
9059  } break;
9061  int i;
9062  const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd;
9063  for (i = 0; i < p->point_count; ++i) {
9064  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
9065  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
9066  }
9067  nk_draw_list_path_fill(&ctx->draw_list, p->color);
9068  } break;
9069  case NK_COMMAND_POLYLINE: {
9070  int i;
9071  const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd;
9072  for (i = 0; i < p->point_count; ++i) {
9073  struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y);
9074  nk_draw_list_path_line_to(&ctx->draw_list, pnt);
9075  }
9076  nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness);
9077  } break;
9078  case NK_COMMAND_TEXT: {
9079  const struct nk_command_text *t = (const struct nk_command_text*)cmd;
9080  nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h),
9081  t->string, t->length, t->height, t->foreground);
9082  } break;
9083  case NK_COMMAND_IMAGE: {
9084  const struct nk_command_image *i = (const struct nk_command_image*)cmd;
9085  nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col);
9086  } break;
9087  case NK_COMMAND_CUSTOM: {
9088  const struct nk_command_custom *c = (const struct nk_command_custom*)cmd;
9089  c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data);
9090  } break;
9091  default: break;
9092  }
9093  }
9094  res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0;
9095  res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0;
9096  res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0;
9097  return res;
9098 }
9099 NK_API const struct nk_draw_command*
9100 nk__draw_begin(const struct nk_context *ctx,
9101  const struct nk_buffer *buffer)
9102 {return nk__draw_list_begin(&ctx->draw_list, buffer);}
9103 
9104 NK_API const struct nk_draw_command*
9105 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer)
9106 {return nk__draw_list_end(&ctx->draw_list, buffer);}
9107 
9108 NK_API const struct nk_draw_command*
9109 nk__draw_next(const struct nk_draw_command *cmd,
9110  const struct nk_buffer *buffer, const struct nk_context *ctx)
9111 {return nk__draw_list_next(cmd, buffer, &ctx->draw_list);}
9112 
9113 #endif
9114 
9115 /*
9116  * ==============================================================
9117  *
9118  * FONT HANDLING
9119  *
9120  * ===============================================================
9121  */
9122 #ifdef NK_INCLUDE_FONT_BAKING
9123 /* -------------------------------------------------------------
9124  *
9125  * RECT PACK
9126  *
9127  * --------------------------------------------------------------*/
9128 /* stb_rect_pack.h - v0.05 - public domain - rectangle packing */
9129 /* Sean Barrett 2014 */
9130 #define NK_RP__MAXVAL 0xffff
9131 typedef unsigned short nk_rp_coord;
9132 
9133 struct nk_rp_rect {
9134  /* reserved for your use: */
9135  int id;
9136  /* input: */
9137  nk_rp_coord w, h;
9138  /* output: */
9139  nk_rp_coord x, y;
9140  int was_packed;
9141  /* non-zero if valid packing */
9142 }; /* 16 bytes, nominally */
9143 
9144 struct nk_rp_node {
9145  nk_rp_coord x,y;
9146  struct nk_rp_node *next;
9147 };
9148 
9149 struct nk_rp_context {
9150  int width;
9151  int height;
9152  int align;
9153  int init_mode;
9154  int heuristic;
9155  int num_nodes;
9156  struct nk_rp_node *active_head;
9157  struct nk_rp_node *free_head;
9158  struct nk_rp_node extra[2];
9159  /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */
9160 };
9161 
9162 struct nk_rp__findresult {
9163  int x,y;
9164  struct nk_rp_node **prev_link;
9165 };
9166 
9167 enum NK_RP_HEURISTIC {
9168  NK_RP_HEURISTIC_Skyline_default=0,
9169  NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default,
9170  NK_RP_HEURISTIC_Skyline_BF_sortHeight
9171 };
9172 enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1};
9173 
9174 NK_INTERN void
9175 nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem)
9176 {
9177  if (allow_out_of_mem)
9178  /* if it's ok to run out of memory, then don't bother aligning them; */
9179  /* this gives better packing, but may fail due to OOM (even though */
9180  /* the rectangles easily fit). @TODO a smarter approach would be to only */
9181  /* quantize once we've hit OOM, then we could get rid of this parameter. */
9182  context->align = 1;
9183  else {
9184  /* if it's not ok to run out of memory, then quantize the widths */
9185  /* so that num_nodes is always enough nodes. */
9186  /* */
9187  /* I.e. num_nodes * align >= width */
9188  /* align >= width / num_nodes */
9189  /* align = ceil(width/num_nodes) */
9190  context->align = (context->width + context->num_nodes-1) / context->num_nodes;
9191  }
9192 }
9193 
9194 NK_INTERN void
9195 nk_rp_init_target(struct nk_rp_context *context, int width, int height,
9196  struct nk_rp_node *nodes, int num_nodes)
9197 {
9198  int i;
9199 #ifndef STBRP_LARGE_RECTS
9200  NK_ASSERT(width <= 0xffff && height <= 0xffff);
9201 #endif
9202 
9203  for (i=0; i < num_nodes-1; ++i)
9204  nodes[i].next = &nodes[i+1];
9205  nodes[i].next = 0;
9206  context->init_mode = NK_RP__INIT_skyline;
9207  context->heuristic = NK_RP_HEURISTIC_Skyline_default;
9208  context->free_head = &nodes[0];
9209  context->active_head = &context->extra[0];
9210  context->width = width;
9211  context->height = height;
9212  context->num_nodes = num_nodes;
9213  nk_rp_setup_allow_out_of_mem(context, 0);
9214 
9215  /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */
9216  context->extra[0].x = 0;
9217  context->extra[0].y = 0;
9218  context->extra[0].next = &context->extra[1];
9219  context->extra[1].x = (nk_rp_coord) width;
9220  context->extra[1].y = 65535;
9221  context->extra[1].next = 0;
9222 }
9223 
9224 /* find minimum y position if it starts at x1 */
9225 NK_INTERN int
9226 nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first,
9227  int x0, int width, int *pwaste)
9228 {
9229  struct nk_rp_node *node = first;
9230  int x1 = x0 + width;
9231  int min_y, visited_width, waste_area;
9232  NK_ASSERT(first->x <= x0);
9233  NK_UNUSED(c);
9234 
9235  NK_ASSERT(node->next->x > x0);
9236  /* we ended up handling this in the caller for efficiency */
9237  NK_ASSERT(node->x <= x0);
9238 
9239  min_y = 0;
9240  waste_area = 0;
9241  visited_width = 0;
9242  while (node->x < x1)
9243  {
9244  if (node->y > min_y) {
9245  /* raise min_y higher. */
9246  /* we've accounted for all waste up to min_y, */
9247  /* but we'll now add more waste for everything we've visited */
9248  waste_area += visited_width * (node->y - min_y);
9249  min_y = node->y;
9250  /* the first time through, visited_width might be reduced */
9251  if (node->x < x0)
9252  visited_width += node->next->x - x0;
9253  else
9254  visited_width += node->next->x - node->x;
9255  } else {
9256  /* add waste area */
9257  int under_width = node->next->x - node->x;
9258  if (under_width + visited_width > width)
9259  under_width = width - visited_width;
9260  waste_area += under_width * (min_y - node->y);
9261  visited_width += under_width;
9262  }
9263  node = node->next;
9264  }
9265  *pwaste = waste_area;
9266  return min_y;
9267 }
9268 
9269 NK_INTERN struct nk_rp__findresult
9270 nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height)
9271 {
9272  int best_waste = (1<<30), best_x, best_y = (1 << 30);
9273  struct nk_rp__findresult fr;
9274  struct nk_rp_node **prev, *node, *tail, **best = 0;
9275 
9276  /* align to multiple of c->align */
9277  width = (width + c->align - 1);
9278  width -= width % c->align;
9279  NK_ASSERT(width % c->align == 0);
9280 
9281  node = c->active_head;
9282  prev = &c->active_head;
9283  while (node->x + width <= c->width) {
9284  int y,waste;
9285  y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste);
9286  /* actually just want to test BL */
9287  if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) {
9288  /* bottom left */
9289  if (y < best_y) {
9290  best_y = y;
9291  best = prev;
9292  }
9293  } else {
9294  /* best-fit */
9295  if (y + height <= c->height) {
9296  /* can only use it if it first vertically */
9297  if (y < best_y || (y == best_y && waste < best_waste)) {
9298  best_y = y;
9299  best_waste = waste;
9300  best = prev;
9301  }
9302  }
9303  }
9304  prev = &node->next;
9305  node = node->next;
9306  }
9307  best_x = (best == 0) ? 0 : (*best)->x;
9308 
9309  /* if doing best-fit (BF), we also have to try aligning right edge to each node position */
9310  /* */
9311  /* e.g, if fitting */
9312  /* */
9313  /* ____________________ */
9314  /* |____________________| */
9315  /* */
9316  /* into */
9317  /* */
9318  /* | | */
9319  /* | ____________| */
9320  /* |____________| */
9321  /* */
9322  /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */
9323  /* */
9324  /* This makes BF take about 2x the time */
9325  if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight)
9326  {
9327  tail = c->active_head;
9328  node = c->active_head;
9329  prev = &c->active_head;
9330  /* find first node that's admissible */
9331  while (tail->x < width)
9332  tail = tail->next;
9333  while (tail)
9334  {
9335  int xpos = tail->x - width;
9336  int y,waste;
9337  NK_ASSERT(xpos >= 0);
9338  /* find the left position that matches this */
9339  while (node->next->x <= xpos) {
9340  prev = &node->next;
9341  node = node->next;
9342  }
9343  NK_ASSERT(node->next->x > xpos && node->x <= xpos);
9344  y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste);
9345  if (y + height < c->height) {
9346  if (y <= best_y) {
9347  if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) {
9348  best_x = xpos;
9349  NK_ASSERT(y <= best_y);
9350  best_y = y;
9351  best_waste = waste;
9352  best = prev;
9353  }
9354  }
9355  }
9356  tail = tail->next;
9357  }
9358  }
9359  fr.prev_link = best;
9360  fr.x = best_x;
9361  fr.y = best_y;
9362  return fr;
9363 }
9364 
9365 NK_INTERN struct nk_rp__findresult
9366 nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height)
9367 {
9368  /* find best position according to heuristic */
9369  struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height);
9370  struct nk_rp_node *node, *cur;
9371 
9372  /* bail if: */
9373  /* 1. it failed */
9374  /* 2. the best node doesn't fit (we don't always check this) */
9375  /* 3. we're out of memory */
9376  if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) {
9377  res.prev_link = 0;
9378  return res;
9379  }
9380 
9381  /* on success, create new node */
9382  node = context->free_head;
9383  node->x = (nk_rp_coord) res.x;
9384  node->y = (nk_rp_coord) (res.y + height);
9385 
9386  context->free_head = node->next;
9387 
9388  /* insert the new node into the right starting point, and */
9389  /* let 'cur' point to the remaining nodes needing to be */
9390  /* stitched back in */
9391  cur = *res.prev_link;
9392  if (cur->x < res.x) {
9393  /* preserve the existing one, so start testing with the next one */
9394  struct nk_rp_node *next = cur->next;
9395  cur->next = node;
9396  cur = next;
9397  } else {
9398  *res.prev_link = node;
9399  }
9400 
9401  /* from here, traverse cur and free the nodes, until we get to one */
9402  /* that shouldn't be freed */
9403  while (cur->next && cur->next->x <= res.x + width) {
9404  struct nk_rp_node *next = cur->next;
9405  /* move the current node to the free list */
9406  cur->next = context->free_head;
9407  context->free_head = cur;
9408  cur = next;
9409  }
9410  /* stitch the list back in */
9411  node->next = cur;
9412 
9413  if (cur->x < res.x + width)
9414  cur->x = (nk_rp_coord) (res.x + width);
9415  return res;
9416 }
9417 
9418 NK_INTERN int
9419 nk_rect_height_compare(const void *a, const void *b)
9420 {
9421  const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
9422  const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
9423  if (p->h > q->h)
9424  return -1;
9425  if (p->h < q->h)
9426  return 1;
9427  return (p->w > q->w) ? -1 : (p->w < q->w);
9428 }
9429 
9430 NK_INTERN int
9431 nk_rect_original_order(const void *a, const void *b)
9432 {
9433  const struct nk_rp_rect *p = (const struct nk_rp_rect *) a;
9434  const struct nk_rp_rect *q = (const struct nk_rp_rect *) b;
9435  return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed);
9436 }
9437 
9438 NK_INTERN void
9439 nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*))
9440 {
9441  /* iterative quick sort */
9442  #define NK_MAX_SORT_STACK 64
9443  unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0;
9444  unsigned seed = len/2 * 69069+1;
9445  for (;;) {
9446  for (; left+1 < len; len++) {
9447  struct nk_rp_rect pivot, tmp;
9448  if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0];
9449  pivot = array[left+seed%(len-left)];
9450  seed = seed * 69069 + 1;
9451  stack[pos++] = len;
9452  for (right = left-1;;) {
9453  while (cmp(&array[++right], &pivot) < 0);
9454  while (cmp(&pivot, &array[--len]) < 0);
9455  if (right >= len) break;
9456  tmp = array[right];
9457  array[right] = array[len];
9458  array[len] = tmp;
9459  }
9460  }
9461  if (pos == 0) break;
9462  left = len;
9463  len = stack[--pos];
9464  }
9465  #undef NK_MAX_SORT_STACK
9466 }
9467 
9468 NK_INTERN void
9469 nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects)
9470 {
9471  int i;
9472  /* we use the 'was_packed' field internally to allow sorting/unsorting */
9473  for (i=0; i < num_rects; ++i) {
9474  rects[i].was_packed = i;
9475  }
9476 
9477  /* sort according to heuristic */
9478  nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare);
9479 
9480  for (i=0; i < num_rects; ++i) {
9481  struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h);
9482  if (fr.prev_link) {
9483  rects[i].x = (nk_rp_coord) fr.x;
9484  rects[i].y = (nk_rp_coord) fr.y;
9485  } else {
9486  rects[i].x = rects[i].y = NK_RP__MAXVAL;
9487  }
9488  }
9489 
9490  /* unsort */
9491  nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order);
9492 
9493  /* set was_packed flags */
9494  for (i=0; i < num_rects; ++i)
9495  rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL);
9496 }
9497 
9498 /*
9499  * ==============================================================
9500  *
9501  * TRUETYPE
9502  *
9503  * ===============================================================
9504  */
9505 /* stb_truetype.h - v1.07 - public domain */
9506 #define NK_TT_MAX_OVERSAMPLE 8
9507 #define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1)
9508 
9509 struct nk_tt_bakedchar {
9510  unsigned short x0,y0,x1,y1;
9511  /* coordinates of bbox in bitmap */
9512  float xoff,yoff,xadvance;
9513 };
9514 
9515 struct nk_tt_aligned_quad{
9516  float x0,y0,s0,t0; /* top-left */
9517  float x1,y1,s1,t1; /* bottom-right */
9518 };
9519 
9520 struct nk_tt_packedchar {
9521  unsigned short x0,y0,x1,y1;
9522  /* coordinates of bbox in bitmap */
9523  float xoff,yoff,xadvance;
9524  float xoff2,yoff2;
9525 };
9526 
9527 struct nk_tt_pack_range {
9528  float font_size;
9529  int first_unicode_codepoint_in_range;
9530  /* if non-zero, then the chars are continuous, and this is the first codepoint */
9531  int *array_of_unicode_codepoints;
9532  /* if non-zero, then this is an array of unicode codepoints */
9533  int num_chars;
9534  struct nk_tt_packedchar *chardata_for_range; /* output */
9535  unsigned char h_oversample, v_oversample;
9536  /* don't set these, they're used internally */
9537 };
9538 
9539 struct nk_tt_pack_context {
9540  void *pack_info;
9541  int width;
9542  int height;
9543  int stride_in_bytes;
9544  int padding;
9545  unsigned int h_oversample, v_oversample;
9546  unsigned char *pixels;
9547  void *nodes;
9548 };
9549 
9550 struct nk_tt_fontinfo {
9551  const unsigned char* data; /* pointer to .ttf file */
9552  int fontstart;/* offset of start of font */
9553  int numGlyphs;/* number of glyphs, needed for range checking */
9554  int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */
9555  int index_map; /* a cmap mapping for our chosen character encoding */
9556  int indexToLocFormat; /* format needed to map from glyph index to glyph */
9557 };
9558 
9559 enum {
9560  NK_TT_vmove=1,
9561  NK_TT_vline,
9562  NK_TT_vcurve
9563 };
9564 
9565 struct nk_tt_vertex {
9566  short x,y,cx,cy;
9567  unsigned char type,padding;
9568 };
9569 
9570 struct nk_tt__bitmap{
9571  int w,h,stride;
9572  unsigned char *pixels;
9573 };
9574 
9575 struct nk_tt__hheap_chunk {
9576  struct nk_tt__hheap_chunk *next;
9577 };
9578 struct nk_tt__hheap {
9579  struct nk_allocator alloc;
9580  struct nk_tt__hheap_chunk *head;
9581  void *first_free;
9582  int num_remaining_in_head_chunk;
9583 };
9584 
9585 struct nk_tt__edge {
9586  float x0,y0, x1,y1;
9587  int invert;
9588 };
9589 
9590 struct nk_tt__active_edge {
9591  struct nk_tt__active_edge *next;
9592  float fx,fdx,fdy;
9593  float direction;
9594  float sy;
9595  float ey;
9596 };
9597 struct nk_tt__point {float x,y;};
9598 
9599 #define NK_TT_MACSTYLE_DONTCARE 0
9600 #define NK_TT_MACSTYLE_BOLD 1
9601 #define NK_TT_MACSTYLE_ITALIC 2
9602 #define NK_TT_MACSTYLE_UNDERSCORE 4
9603 #define NK_TT_MACSTYLE_NONE 8
9604 /* <= not same as 0, this makes us check the bitfield is 0 */
9605 
9606 enum { /* platformID */
9607  NK_TT_PLATFORM_ID_UNICODE =0,
9608  NK_TT_PLATFORM_ID_MAC =1,
9609  NK_TT_PLATFORM_ID_ISO =2,
9610  NK_TT_PLATFORM_ID_MICROSOFT =3
9611 };
9612 
9613 enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */
9614  NK_TT_UNICODE_EID_UNICODE_1_0 =0,
9615  NK_TT_UNICODE_EID_UNICODE_1_1 =1,
9616  NK_TT_UNICODE_EID_ISO_10646 =2,
9617  NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3,
9618  NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4
9619 };
9620 
9621 enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */
9622  NK_TT_MS_EID_SYMBOL =0,
9623  NK_TT_MS_EID_UNICODE_BMP =1,
9624  NK_TT_MS_EID_SHIFTJIS =2,
9625  NK_TT_MS_EID_UNICODE_FULL =10
9626 };
9627 
9628 enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */
9629  NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4,
9630  NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5,
9631  NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6,
9632  NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7
9633 };
9634 
9635 enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */
9636  /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */
9637  NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410,
9638  NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411,
9639  NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412,
9640  NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419,
9641  NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409,
9642  NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D
9643 };
9644 
9645 enum { /* languageID for NK_TT_PLATFORM_ID_MAC */
9646  NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11,
9647  NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23,
9648  NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32,
9649  NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 ,
9650  NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 ,
9651  NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33,
9652  NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19
9653 };
9654 
9655 #define nk_ttBYTE(p) (* (const nk_byte *) (p))
9656 #define nk_ttCHAR(p) (* (const char *) (p))
9657 
9658 #if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE)
9659  #define nk_ttUSHORT(p) (* (nk_ushort *) (p))
9660  #define nk_ttSHORT(p) (* (nk_short *) (p))
9661  #define nk_ttULONG(p) (* (nk_uint *) (p))
9662  #define nk_ttLONG(p) (* (nk_int *) (p))
9663 #else
9664  static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); }
9665  static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); }
9666  static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); }
9667 #endif
9668 
9669 #define nk_tt_tag4(p,c0,c1,c2,c3)\
9670  ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3))
9671 #define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3])
9672 
9673 NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
9674  int glyph_index, struct nk_tt_vertex **pvertices);
9675 
9677 nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag)
9678 {
9679  /* @OPTIMIZE: binary search */
9680  nk_int num_tables = nk_ttUSHORT(data+fontstart+4);
9681  nk_uint tabledir = fontstart + 12;
9682  nk_int i;
9683  for (i = 0; i < num_tables; ++i) {
9684  nk_uint loc = tabledir + (nk_uint)(16*i);
9685  if (nk_tt_tag(data+loc+0, tag))
9686  return nk_ttULONG(data+loc+8);
9687  }
9688  return 0;
9689 }
9690 
9691 NK_INTERN int
9692 nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart)
9693 {
9694  nk_uint cmap, t;
9695  nk_int i,numTables;
9696  const nk_byte *data = (const nk_byte *) data2;
9697 
9698  info->data = data;
9699  info->fontstart = fontstart;
9700 
9701  cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */
9702  info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */
9703  info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */
9704  info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */
9705  info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */
9706  info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */
9707  info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */
9708  if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx)
9709  return 0;
9710 
9711  t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp");
9712  if (t) info->numGlyphs = nk_ttUSHORT(data+t+4);
9713  else info->numGlyphs = 0xffff;
9714 
9715  /* find a cmap encoding table we understand *now* to avoid searching */
9716  /* later. (todo: could make this installable) */
9717  /* the same regardless of glyph. */
9718  numTables = nk_ttUSHORT(data + cmap + 2);
9719  info->index_map = 0;
9720  for (i=0; i < numTables; ++i)
9721  {
9722  nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i;
9723  /* find an encoding we understand: */
9724  switch(nk_ttUSHORT(data+encoding_record)) {
9725  case NK_TT_PLATFORM_ID_MICROSOFT:
9726  switch (nk_ttUSHORT(data+encoding_record+2)) {
9727  case NK_TT_MS_EID_UNICODE_BMP:
9728  case NK_TT_MS_EID_UNICODE_FULL:
9729  /* MS/Unicode */
9730  info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
9731  break;
9732  default: break;
9733  } break;
9734  case NK_TT_PLATFORM_ID_UNICODE:
9735  /* Mac/iOS has these */
9736  /* all the encodingIDs are unicode, so we don't bother to check it */
9737  info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4));
9738  break;
9739  default: break;
9740  }
9741  }
9742  if (info->index_map == 0)
9743  return 0;
9744  info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50);
9745  return 1;
9746 }
9747 
9748 NK_INTERN int
9749 nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint)
9750 {
9751  const nk_byte *data = info->data;
9752  nk_uint index_map = (nk_uint)info->index_map;
9753 
9754  nk_ushort format = nk_ttUSHORT(data + index_map + 0);
9755  if (format == 0) { /* apple byte encoding */
9756  nk_int bytes = nk_ttUSHORT(data + index_map + 2);
9757  if (unicode_codepoint < bytes-6)
9758  return nk_ttBYTE(data + index_map + 6 + unicode_codepoint);
9759  return 0;
9760  } else if (format == 6) {
9761  nk_uint first = nk_ttUSHORT(data + index_map + 6);
9762  nk_uint count = nk_ttUSHORT(data + index_map + 8);
9763  if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count)
9764  return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2);
9765  return 0;
9766  } else if (format == 2) {
9767  NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */
9768  return 0;
9769  } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */
9770  nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1;
9771  nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1;
9772  nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10);
9773  nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1;
9774 
9775  /* do a binary search of the segments */
9776  nk_uint endCount = index_map + 14;
9777  nk_uint search = endCount;
9778 
9779  if (unicode_codepoint > 0xffff)
9780  return 0;
9781 
9782  /* they lie from endCount .. endCount + segCount */
9783  /* but searchRange is the nearest power of two, so... */
9784  if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2))
9785  search += (nk_uint)(rangeShift*2);
9786 
9787  /* now decrement to bias correctly to find smallest */
9788  search -= 2;
9789  while (entrySelector) {
9790  nk_ushort end;
9791  searchRange >>= 1;
9792  end = nk_ttUSHORT(data + search + searchRange*2);
9793  if (unicode_codepoint > end)
9794  search += (nk_uint)(searchRange*2);
9795  --entrySelector;
9796  }
9797  search += 2;
9798 
9799  {
9801  nk_ushort item = (nk_ushort) ((search - endCount) >> 1);
9802 
9803  NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item));
9804  start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item);
9805  if (unicode_codepoint < start)
9806  return 0;
9807 
9808  offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item);
9809  if (offset == 0)
9810  return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item));
9811 
9812  return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item);
9813  }
9814  } else if (format == 12 || format == 13) {
9815  nk_uint ngroups = nk_ttULONG(data+index_map+12);
9816  nk_int low,high;
9817  low = 0; high = (nk_int)ngroups;
9818  /* Binary search the right group. */
9819  while (low < high) {
9820  nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */
9821  nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12);
9822  nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4);
9823  if ((nk_uint) unicode_codepoint < start_char)
9824  high = mid;
9825  else if ((nk_uint) unicode_codepoint > end_char)
9826  low = mid+1;
9827  else {
9828  nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8);
9829  if (format == 12)
9830  return (int)start_glyph + (int)unicode_codepoint - (int)start_char;
9831  else /* format == 13 */
9832  return (int)start_glyph;
9833  }
9834  }
9835  return 0; /* not found */
9836  }
9837  /* @TODO */
9838  NK_ASSERT(0);
9839  return 0;
9840 }
9841 
9842 NK_INTERN void
9843 nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy)
9844 {
9845  v->type = type;
9846  v->x = (nk_short) x;
9847  v->y = (nk_short) y;
9848  v->cx = (nk_short) cx;
9849  v->cy = (nk_short) cy;
9850 }
9851 
9852 NK_INTERN int
9853 nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index)
9854 {
9855  int g1,g2;
9856  if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */
9857  if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */
9858 
9859  if (info->indexToLocFormat == 0) {
9860  g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2;
9861  g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2;
9862  } else {
9863  g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4);
9864  g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4);
9865  }
9866  return g1==g2 ? -1 : g1; /* if length is 0, return -1 */
9867 }
9868 
9869 NK_INTERN int
9870 nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index,
9871  int *x0, int *y0, int *x1, int *y1)
9872 {
9873  int g = nk_tt__GetGlyfOffset(info, glyph_index);
9874  if (g < 0) return 0;
9875 
9876  if (x0) *x0 = nk_ttSHORT(info->data + g + 2);
9877  if (y0) *y0 = nk_ttSHORT(info->data + g + 4);
9878  if (x1) *x1 = nk_ttSHORT(info->data + g + 6);
9879  if (y1) *y1 = nk_ttSHORT(info->data + g + 8);
9880  return 1;
9881 }
9882 
9883 NK_INTERN int
9884 stbtt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off,
9885  int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy)
9886 {
9887  if (start_off) {
9888  if (was_off)
9889  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy);
9890  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy);
9891  } else {
9892  if (was_off)
9893  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy);
9894  else
9895  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0);
9896  }
9897  return num_vertices;
9898 }
9899 
9900 NK_INTERN int
9901 nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc,
9902  int glyph_index, struct nk_tt_vertex **pvertices)
9903 {
9904  nk_short numberOfContours;
9905  const nk_byte *endPtsOfContours;
9906  const nk_byte *data = info->data;
9907  struct nk_tt_vertex *vertices=0;
9908  int num_vertices=0;
9909  int g = nk_tt__GetGlyfOffset(info, glyph_index);
9910  *pvertices = 0;
9911 
9912  if (g < 0) return 0;
9913  numberOfContours = nk_ttSHORT(data + g);
9914  if (numberOfContours > 0) {
9915  nk_byte flags=0,flagcount;
9916  nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0;
9917  nk_int x,y,cx,cy,sx,sy, scx,scy;
9918  const nk_byte *points;
9919  endPtsOfContours = (data + g + 10);
9920  ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2);
9921  points = data + g + 10 + numberOfContours * 2 + 2 + ins;
9922 
9923  n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2);
9924  m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */
9925  vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0]));
9926  if (vertices == 0)
9927  return 0;
9928 
9929  next_move = 0;
9930  flagcount=0;
9931 
9932  /* in first pass, we load uninterpreted data into the allocated array */
9933  /* above, shifted to the end of the array so we won't overwrite it when */
9934  /* we create our final data starting from the front */
9935  off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */
9936 
9937  /* first load flags */
9938  for (i=0; i < n; ++i) {
9939  if (flagcount == 0) {
9940  flags = *points++;
9941  if (flags & 8)
9942  flagcount = *points++;
9943  } else --flagcount;
9944  vertices[off+i].type = flags;
9945  }
9946 
9947  /* now load x coordinates */
9948  x=0;
9949  for (i=0; i < n; ++i) {
9950  flags = vertices[off+i].type;
9951  if (flags & 2) {
9952  nk_short dx = *points++;
9953  x += (flags & 16) ? dx : -dx; /* ??? */
9954  } else {
9955  if (!(flags & 16)) {
9956  x = x + (nk_short) (points[0]*256 + points[1]);
9957  points += 2;
9958  }
9959  }
9960  vertices[off+i].x = (nk_short) x;
9961  }
9962 
9963  /* now load y coordinates */
9964  y=0;
9965  for (i=0; i < n; ++i) {
9966  flags = vertices[off+i].type;
9967  if (flags & 4) {
9968  nk_short dy = *points++;
9969  y += (flags & 32) ? dy : -dy; /* ??? */
9970  } else {
9971  if (!(flags & 32)) {
9972  y = y + (nk_short) (points[0]*256 + points[1]);
9973  points += 2;
9974  }
9975  }
9976  vertices[off+i].y = (nk_short) y;
9977  }
9978 
9979  /* now convert them to our format */
9980  num_vertices=0;
9981  sx = sy = cx = cy = scx = scy = 0;
9982  for (i=0; i < n; ++i)
9983  {
9984  flags = vertices[off+i].type;
9985  x = (nk_short) vertices[off+i].x;
9986  y = (nk_short) vertices[off+i].y;
9987 
9988  if (next_move == i) {
9989  if (i != 0)
9990  num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
9991 
9992  /* now start the new one */
9993  start_off = !(flags & 1);
9994  if (start_off) {
9995  /* if we start off with an off-curve point, then when we need to find a point on the curve */
9996  /* where we can start, and we need to save some state for when we wraparound. */
9997  scx = x;
9998  scy = y;
9999  if (!(vertices[off+i+1].type & 1)) {
10000  /* next point is also a curve point, so interpolate an on-point curve */
10001  sx = (x + (nk_int) vertices[off+i+1].x) >> 1;
10002  sy = (y + (nk_int) vertices[off+i+1].y) >> 1;
10003  } else {
10004  /* otherwise just use the next point as our start point */
10005  sx = (nk_int) vertices[off+i+1].x;
10006  sy = (nk_int) vertices[off+i+1].y;
10007  ++i; /* we're using point i+1 as the starting point, so skip it */
10008  }
10009  } else {
10010  sx = x;
10011  sy = y;
10012  }
10013  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0);
10014  was_off = 0;
10015  next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2);
10016  ++j;
10017  } else {
10018  if (!(flags & 1))
10019  { /* if it's a curve */
10020  if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */
10021  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy);
10022  cx = x;
10023  cy = y;
10024  was_off = 1;
10025  } else {
10026  if (was_off)
10027  nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy);
10028  else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0);
10029  was_off = 0;
10030  }
10031  }
10032  }
10033  num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy);
10034  } else if (numberOfContours == -1) {
10035  /* Compound shapes. */
10036  int more = 1;
10037  const nk_byte *comp = data + g + 10;
10038  num_vertices = 0;
10039  vertices = 0;
10040 
10041  while (more)
10042  {
10043  nk_ushort flags, gidx;
10044  int comp_num_verts = 0, i;
10045  struct nk_tt_vertex *comp_verts = 0, *tmp = 0;
10046  float mtx[6] = {1,0,0,1,0,0}, m, n;
10047 
10048  flags = (nk_ushort)nk_ttSHORT(comp); comp+=2;
10049  gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2;
10050 
10051  if (flags & 2) { /* XY values */
10052  if (flags & 1) { /* shorts */
10053  mtx[4] = nk_ttSHORT(comp); comp+=2;
10054  mtx[5] = nk_ttSHORT(comp); comp+=2;
10055  } else {
10056  mtx[4] = nk_ttCHAR(comp); comp+=1;
10057  mtx[5] = nk_ttCHAR(comp); comp+=1;
10058  }
10059  } else {
10060  /* @TODO handle matching point */
10061  NK_ASSERT(0);
10062  }
10063  if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */
10064  mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10065  mtx[1] = mtx[2] = 0;
10066  } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */
10067  mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10068  mtx[1] = mtx[2] = 0;
10069  mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10070  } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */
10071  mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10072  mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10073  mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10074  mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2;
10075  }
10076 
10077  /* Find transformation scales. */
10078  m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]);
10079  n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]);
10080 
10081  /* Get indexed glyph. */
10082  comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts);
10083  if (comp_num_verts > 0)
10084  {
10085  /* Transform vertices. */
10086  for (i = 0; i < comp_num_verts; ++i) {
10087  struct nk_tt_vertex* v = &comp_verts[i];
10088  short x,y;
10089  x=v->x; y=v->y;
10090  v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
10091  v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
10092  x=v->cx; y=v->cy;
10093  v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4]));
10094  v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5]));
10095  }
10096  /* Append vertices. */
10097  tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0,
10098  (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex));
10099  if (!tmp) {
10100  if (vertices) alloc->free(alloc->userdata, vertices);
10101  if (comp_verts) alloc->free(alloc->userdata, comp_verts);
10102  return 0;
10103  }
10104  if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex));
10105  NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex));
10106  if (vertices) alloc->free(alloc->userdata,vertices);
10107  vertices = tmp;
10108  alloc->free(alloc->userdata,comp_verts);
10109  num_vertices += comp_num_verts;
10110  }
10111  /* More components ? */
10112  more = flags & (1<<5);
10113  }
10114  } else if (numberOfContours < 0) {
10115  /* @TODO other compound variations? */
10116  NK_ASSERT(0);
10117  } else {
10118  /* numberOfCounters == 0, do nothing */
10119  }
10120  *pvertices = vertices;
10121  return num_vertices;
10122 }
10123 
10124 NK_INTERN void
10125 nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index,
10126  int *advanceWidth, int *leftSideBearing)
10127 {
10128  nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34);
10129  if (glyph_index < numOfLongHorMetrics) {
10130  if (advanceWidth)
10131  *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index);
10132  if (leftSideBearing)
10133  *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2);
10134  } else {
10135  if (advanceWidth)
10136  *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1));
10137  if (leftSideBearing)
10138  *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics));
10139  }
10140 }
10141 
10142 NK_INTERN void
10143 nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info,
10144  int *ascent, int *descent, int *lineGap)
10145 {
10146  if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4);
10147  if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6);
10148  if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8);
10149 }
10150 
10151 NK_INTERN float
10152 nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height)
10153 {
10154  int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6);
10155  return (float) height / (float)fheight;
10156 }
10157 
10158 NK_INTERN float
10159 nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels)
10160 {
10161  int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18);
10162  return pixels / (float)unitsPerEm;
10163 }
10164 
10165 /*-------------------------------------------------------------
10166  * antialiasing software rasterizer
10167  * --------------------------------------------------------------*/
10168 NK_INTERN void
10169 nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font,
10170  int glyph, float scale_x, float scale_y,float shift_x, float shift_y,
10171  int *ix0, int *iy0, int *ix1, int *iy1)
10172 {
10173  int x0,y0,x1,y1;
10174  if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) {
10175  /* e.g. space character */
10176  if (ix0) *ix0 = 0;
10177  if (iy0) *iy0 = 0;
10178  if (ix1) *ix1 = 0;
10179  if (iy1) *iy1 = 0;
10180  } else {
10181  /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */
10182  if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x);
10183  if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y);
10184  if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x);
10185  if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y);
10186  }
10187 }
10188 
10189 NK_INTERN void
10190 nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph,
10191  float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1)
10192 {
10193  nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1);
10194 }
10195 
10196 /*-------------------------------------------------------------
10197  * Rasterizer
10198  * --------------------------------------------------------------*/
10199 NK_INTERN void*
10200 nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size)
10201 {
10202  if (hh->first_free) {
10203  void *p = hh->first_free;
10204  hh->first_free = * (void **) p;
10205  return p;
10206  } else {
10207  if (hh->num_remaining_in_head_chunk == 0) {
10208  int count = (size < 32 ? 2000 : size < 128 ? 800 : 100);
10209  struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *)
10210  hh->alloc.alloc(hh->alloc.userdata, 0,
10211  sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count);
10212  if (c == 0) return 0;
10213  c->next = hh->head;
10214  hh->head = c;
10215  hh->num_remaining_in_head_chunk = count;
10216  }
10217  --hh->num_remaining_in_head_chunk;
10218  return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk;
10219  }
10220 }
10221 
10222 NK_INTERN void
10223 nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p)
10224 {
10225  *(void **) p = hh->first_free;
10226  hh->first_free = p;
10227 }
10228 
10229 NK_INTERN void
10230 nk_tt__hheap_cleanup(struct nk_tt__hheap *hh)
10231 {
10232  struct nk_tt__hheap_chunk *c = hh->head;
10233  while (c) {
10234  struct nk_tt__hheap_chunk *n = c->next;
10235  hh->alloc.free(hh->alloc.userdata, c);
10236  c = n;
10237  }
10238 }
10239 
10240 NK_INTERN struct nk_tt__active_edge*
10241 nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e,
10242  int off_x, float start_point)
10243 {
10244  struct nk_tt__active_edge *z = (struct nk_tt__active_edge *)
10245  nk_tt__hheap_alloc(hh, sizeof(*z));
10246  float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0);
10247  /*STBTT_assert(e->y0 <= start_point); */
10248  if (!z) return z;
10249  z->fdx = dxdy;
10250  z->fdy = (dxdy != 0) ? (1/dxdy): 0;
10251  z->fx = e->x0 + dxdy * (start_point - e->y0);
10252  z->fx -= (float)off_x;
10253  z->direction = e->invert ? 1.0f : -1.0f;
10254  z->sy = e->y0;
10255  z->ey = e->y1;
10256  z->next = 0;
10257  return z;
10258 }
10259 
10260 NK_INTERN void
10261 nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e,
10262  float x0, float y0, float x1, float y1)
10263 {
10264  if (y0 == y1) return;
10265  NK_ASSERT(y0 < y1);
10266  NK_ASSERT(e->sy <= e->ey);
10267  if (y0 > e->ey) return;
10268  if (y1 < e->sy) return;
10269  if (y0 < e->sy) {
10270  x0 += (x1-x0) * (e->sy - y0) / (y1-y0);
10271  y0 = e->sy;
10272  }
10273  if (y1 > e->ey) {
10274  x1 += (x1-x0) * (e->ey - y1) / (y1-y0);
10275  y1 = e->ey;
10276  }
10277 
10278  if (x0 == x) NK_ASSERT(x1 <= x+1);
10279  else if (x0 == x+1) NK_ASSERT(x1 >= x);
10280  else if (x0 <= x) NK_ASSERT(x1 <= x);
10281  else if (x0 >= x+1) NK_ASSERT(x1 >= x+1);
10282  else NK_ASSERT(x1 >= x && x1 <= x+1);
10283 
10284  if (x0 <= x && x1 <= x)
10285  scanline[x] += e->direction * (y1-y0);
10286  else if (x0 >= x+1 && x1 >= x+1);
10287  else {
10288  NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1);
10289  /* coverage = 1 - average x position */
10290  scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f);
10291  }
10292 }
10293 
10294 NK_INTERN void
10295 nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len,
10296  struct nk_tt__active_edge *e, float y_top)
10297 {
10298  float y_bottom = y_top+1;
10299  while (e)
10300  {
10301  /* brute force every pixel */
10302  /* compute intersection points with top & bottom */
10303  NK_ASSERT(e->ey >= y_top);
10304  if (e->fdx == 0) {
10305  float x0 = e->fx;
10306  if (x0 < len) {
10307  if (x0 >= 0) {
10308  nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom);
10309  nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom);
10310  } else {
10311  nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom);
10312  }
10313  }
10314  } else {
10315  float x0 = e->fx;
10316  float dx = e->fdx;
10317  float xb = x0 + dx;
10318  float x_top, x_bottom;
10319  float y0,y1;
10320  float dy = e->fdy;
10321  NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top);
10322 
10323  /* compute endpoints of line segment clipped to this scanline (if the */
10324  /* line segment starts on this scanline. x0 is the intersection of the */
10325  /* line with y_top, but that may be off the line segment. */
10326  if (e->sy > y_top) {
10327  x_top = x0 + dx * (e->sy - y_top);
10328  y0 = e->sy;
10329  } else {
10330  x_top = x0;
10331  y0 = y_top;
10332  }
10333 
10334  if (e->ey < y_bottom) {
10335  x_bottom = x0 + dx * (e->ey - y_top);
10336  y1 = e->ey;
10337  } else {
10338  x_bottom = xb;
10339  y1 = y_bottom;
10340  }
10341 
10342  if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len)
10343  {
10344  /* from here on, we don't have to range check x values */
10345  if ((int) x_top == (int) x_bottom) {
10346  float height;
10347  /* simple case, only spans one pixel */
10348  int x = (int) x_top;
10349  height = y1 - y0;
10350  NK_ASSERT(x >= 0 && x < len);
10351  scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height;
10352  scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */
10353  } else {
10354  int x,x1,x2;
10355  float y_crossing, step, sign, area;
10356  /* covers 2+ pixels */
10357  if (x_top > x_bottom)
10358  {
10359  /* flip scanline vertically; signed area is the same */
10360  float t;
10361  y0 = y_bottom - (y0 - y_top);
10362  y1 = y_bottom - (y1 - y_top);
10363  t = y0; y0 = y1; y1 = t;
10364  t = x_bottom; x_bottom = x_top; x_top = t;
10365  dx = -dx;
10366  dy = -dy;
10367  t = x0; x0 = xb; xb = t;
10368  }
10369 
10370  x1 = (int) x_top;
10371  x2 = (int) x_bottom;
10372  /* compute intersection with y axis at x1+1 */
10373  y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top;
10374 
10375  sign = e->direction;
10376  /* area of the rectangle covered from y0..y_crossing */
10377  area = sign * (y_crossing-y0);
10378  /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */
10379  scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f);
10380 
10381  step = sign * dy;
10382  for (x = x1+1; x < x2; ++x) {
10383  scanline[x] += area + step/2;
10384  area += step;
10385  }
10386  y_crossing += (float)dy * (float)(x2 - (x1+1));
10387 
10388  scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing);
10389  scanline_fill[x2] += sign * (y1-y0);
10390  }
10391  }
10392  else
10393  {
10394  /* if edge goes outside of box we're drawing, we require */
10395  /* clipping logic. since this does not match the intended use */
10396  /* of this library, we use a different, very slow brute */
10397  /* force implementation */
10398  int x;
10399  for (x=0; x < len; ++x)
10400  {
10401  /* cases: */
10402  /* */
10403  /* there can be up to two intersections with the pixel. any intersection */
10404  /* with left or right edges can be handled by splitting into two (or three) */
10405  /* regions. intersections with top & bottom do not necessitate case-wise logic. */
10406  /* */
10407  /* the old way of doing this found the intersections with the left & right edges, */
10408  /* then used some simple logic to produce up to three segments in sorted order */
10409  /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */
10410  /* across the x border, then the corresponding y position might not be distinct */
10411  /* from the other y segment, and it might ignored as an empty segment. to avoid */
10412  /* that, we need to explicitly produce segments based on x positions. */
10413 
10414  /* rename variables to clear pairs */
10415  float ya = y_top;
10416  float x1 = (float) (x);
10417  float x2 = (float) (x+1);
10418  float x3 = xb;
10419  float y3 = y_bottom;
10420  float yb,y2;
10421 
10422  yb = ((float)x - x0) / dx + y_top;
10423  y2 = ((float)x+1 - x0) / dx + y_top;
10424 
10425  if (x0 < x1 && x3 > x2) { /* three segments descending down-right */
10426  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10427  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2);
10428  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10429  } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */
10430  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10431  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb);
10432  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10433  } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */
10434  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10435  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10436  } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */
10437  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb);
10438  nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3);
10439  } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */
10440  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10441  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10442  } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */
10443  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2);
10444  nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3);
10445  } else { /* one segment */
10446  nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3);
10447  }
10448  }
10449  }
10450  }
10451  e = e->next;
10452  }
10453 }
10454 
10455 /* directly AA rasterize edges w/o supersampling */
10456 NK_INTERN void
10457 nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e,
10458  int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc)
10459 {
10460  struct nk_tt__hheap hh;
10461  struct nk_tt__active_edge *active = 0;
10462  int y,j=0, i;
10463  float scanline_data[129], *scanline, *scanline2;
10464 
10465  NK_UNUSED(vsubsample);
10466  nk_zero_struct(hh);
10467  hh.alloc = *alloc;
10468 
10469  if (result->w > 64)
10470  scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float));
10471  else scanline = scanline_data;
10472 
10473  scanline2 = scanline + result->w;
10474  y = off_y;
10475  e[n].y0 = (float) (off_y + result->h) + 1;
10476 
10477  while (j < result->h)
10478  {
10479  /* find center of pixel for this scanline */
10480  float scan_y_top = (float)y + 0.0f;
10481  float scan_y_bottom = (float)y + 1.0f;
10482  struct nk_tt__active_edge **step = &active;
10483 
10484  NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0]));
10485  NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0]));
10486 
10487  /* update all active edges; */
10488  /* remove all active edges that terminate before the top of this scanline */
10489  while (*step) {
10490  struct nk_tt__active_edge * z = *step;
10491  if (z->ey <= scan_y_top) {
10492  *step = z->next; /* delete from list */
10493  NK_ASSERT(z->direction);
10494  z->direction = 0;
10495  nk_tt__hheap_free(&hh, z);
10496  } else {
10497  step = &((*step)->next); /* advance through list */
10498  }
10499  }
10500 
10501  /* insert all edges that start before the bottom of this scanline */
10502  while (e->y0 <= scan_y_bottom) {
10503  if (e->y0 != e->y1) {
10504  struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top);
10505  if (z != 0) {
10506  NK_ASSERT(z->ey >= scan_y_top);
10507  /* insert at front */
10508  z->next = active;
10509  active = z;
10510  }
10511  }
10512  ++e;
10513  }
10514 
10515  /* now process all active edges */
10516  if (active)
10517  nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top);
10518 
10519  {
10520  float sum = 0;
10521  for (i=0; i < result->w; ++i) {
10522  float k;
10523  int m;
10524  sum += scanline2[i];
10525  k = scanline[i] + sum;
10526  k = (float) NK_ABS(k) * 255.0f + 0.5f;
10527  m = (int) k;
10528  if (m > 255) m = 255;
10529  result->pixels[j*result->stride + i] = (unsigned char) m;
10530  }
10531  }
10532  /* advance all the edges */
10533  step = &active;
10534  while (*step) {
10535  struct nk_tt__active_edge *z = *step;
10536  z->fx += z->fdx; /* advance to position for current scanline */
10537  step = &((*step)->next); /* advance through list */
10538  }
10539  ++y;
10540  ++j;
10541  }
10542  nk_tt__hheap_cleanup(&hh);
10543  if (scanline != scanline_data)
10544  alloc->free(alloc->userdata, scanline);
10545 }
10546 
10547 #define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0)
10548 NK_INTERN void
10549 nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n)
10550 {
10551  int i,j;
10552  for (i=1; i < n; ++i) {
10553  struct nk_tt__edge t = p[i], *a = &t;
10554  j = i;
10555  while (j > 0) {
10556  struct nk_tt__edge *b = &p[j-1];
10557  int c = NK_TT__COMPARE(a,b);
10558  if (!c) break;
10559  p[j] = p[j-1];
10560  --j;
10561  }
10562  if (i != j)
10563  p[j] = t;
10564  }
10565 }
10566 
10567 NK_INTERN void
10568 nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n)
10569 {
10570  /* threshold for transitioning to insertion sort */
10571  while (n > 12) {
10572  struct nk_tt__edge t;
10573  int c01,c12,c,m,i,j;
10574 
10575  /* compute median of three */
10576  m = n >> 1;
10577  c01 = NK_TT__COMPARE(&p[0],&p[m]);
10578  c12 = NK_TT__COMPARE(&p[m],&p[n-1]);
10579 
10580  /* if 0 >= mid >= end, or 0 < mid < end, then use mid */
10581  if (c01 != c12) {
10582  /* otherwise, we'll need to swap something else to middle */
10583  int z;
10584  c = NK_TT__COMPARE(&p[0],&p[n-1]);
10585  /* 0>mid && mid<n: 0>n => n; 0<n => 0 */
10586  /* 0<mid && mid>n: 0>n => 0; 0<n => n */
10587  z = (c == c12) ? 0 : n-1;
10588  t = p[z];
10589  p[z] = p[m];
10590  p[m] = t;
10591  }
10592 
10593  /* now p[m] is the median-of-three */
10594  /* swap it to the beginning so it won't move around */
10595  t = p[0];
10596  p[0] = p[m];
10597  p[m] = t;
10598 
10599  /* partition loop */
10600  i=1;
10601  j=n-1;
10602  for(;;) {
10603  /* handling of equality is crucial here */
10604  /* for sentinels & efficiency with duplicates */
10605  for (;;++i) {
10606  if (!NK_TT__COMPARE(&p[i], &p[0])) break;
10607  }
10608  for (;;--j) {
10609  if (!NK_TT__COMPARE(&p[0], &p[j])) break;
10610  }
10611 
10612  /* make sure we haven't crossed */
10613  if (i >= j) break;
10614  t = p[i];
10615  p[i] = p[j];
10616  p[j] = t;
10617 
10618  ++i;
10619  --j;
10620 
10621  }
10622 
10623  /* recurse on smaller side, iterate on larger */
10624  if (j < (n-i)) {
10625  nk_tt__sort_edges_quicksort(p,j);
10626  p = p+i;
10627  n = n-i;
10628  } else {
10629  nk_tt__sort_edges_quicksort(p+i, n-i);
10630  n = j;
10631  }
10632  }
10633 }
10634 
10635 NK_INTERN void
10636 nk_tt__sort_edges(struct nk_tt__edge *p, int n)
10637 {
10638  nk_tt__sort_edges_quicksort(p, n);
10639  nk_tt__sort_edges_ins_sort(p, n);
10640 }
10641 
10642 NK_INTERN void
10643 nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__point *pts,
10644  int *wcount, int windings, float scale_x, float scale_y,
10645  float shift_x, float shift_y, int off_x, int off_y, int invert,
10646  struct nk_allocator *alloc)
10647 {
10648  float y_scale_inv = invert ? -scale_y : scale_y;
10649  struct nk_tt__edge *e;
10650  int n,i,j,k,m;
10651  int vsubsample = 1;
10652  /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */
10653 
10654  /* now we have to blow out the windings into explicit edge lists */
10655  n = 0;
10656  for (i=0; i < windings; ++i)
10657  n += wcount[i];
10658 
10659  e = (struct nk_tt__edge*)
10660  alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1)));
10661  if (e == 0) return;
10662  n = 0;
10663 
10664  m=0;
10665  for (i=0; i < windings; ++i)
10666  {
10667  struct nk_tt__point *p = pts + m;
10668  m += wcount[i];
10669  j = wcount[i]-1;
10670  for (k=0; k < wcount[i]; j=k++) {
10671  int a=k,b=j;
10672  /* skip the edge if horizontal */
10673  if (p[j].y == p[k].y)
10674  continue;
10675 
10676  /* add edge from j to k to the list */
10677  e[n].invert = 0;
10678  if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) {
10679  e[n].invert = 1;
10680  a=j,b=k;
10681  }
10682  e[n].x0 = p[a].x * scale_x + shift_x;
10683  e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample;
10684  e[n].x1 = p[b].x * scale_x + shift_x;
10685  e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample;
10686  ++n;
10687  }
10688  }
10689 
10690  /* now sort the edges by their highest point (should snap to integer, and then by x) */
10691  /*STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); */
10692  nk_tt__sort_edges(e, n);
10693  /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */
10694  nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc);
10695  alloc->free(alloc->userdata, e);
10696 }
10697 
10698 NK_INTERN void
10699 nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y)
10700 {
10701  if (!points) return; /* during first pass, it's unallocated */
10702  points[n].x = x;
10703  points[n].y = y;
10704 }
10705 
10706 NK_INTERN int
10707 nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points,
10708  float x0, float y0, float x1, float y1, float x2, float y2,
10709  float objspace_flatness_squared, int n)
10710 {
10711  /* tesselate until threshold p is happy...
10712  * @TODO warped to compensate for non-linear stretching */
10713  /* midpoint */
10714  float mx = (x0 + 2*x1 + x2)/4;
10715  float my = (y0 + 2*y1 + y2)/4;
10716  /* versus directly drawn line */
10717  float dx = (x0+x2)/2 - mx;
10718  float dy = (y0+y2)/2 - my;
10719  if (n > 16) /* 65536 segments on one curve better be enough! */
10720  return 1;
10721 
10722  /* half-pixel error allowed... need to be smaller if AA */
10723  if (dx*dx+dy*dy > objspace_flatness_squared) {
10724  nk_tt__tesselate_curve(points, num_points, x0,y0,
10725  (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1);
10726  nk_tt__tesselate_curve(points, num_points, mx,my,
10727  (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1);
10728  } else {
10729  nk_tt__add_point(points, *num_points,x2,y2);
10730  *num_points = *num_points+1;
10731  }
10732  return 1;
10733 }
10734 
10735 /* returns number of contours */
10736 NK_INTERN struct nk_tt__point*
10737 nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts,
10738  float objspace_flatness, int **contour_lengths, int *num_contours,
10739  struct nk_allocator *alloc)
10740 {
10741  struct nk_tt__point *points=0;
10742  int num_points=0;
10743  float objspace_flatness_squared = objspace_flatness * objspace_flatness;
10744  int i;
10745  int n=0;
10746  int start=0;
10747  int pass;
10748 
10749  /* count how many "moves" there are to get the contour count */
10750  for (i=0; i < num_verts; ++i)
10751  if (vertices[i].type == NK_TT_vmove) ++n;
10752 
10753  *num_contours = n;
10754  if (n == 0) return 0;
10755 
10756  *contour_lengths = (int *)
10757  alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n));
10758  if (*contour_lengths == 0) {
10759  *num_contours = 0;
10760  return 0;
10761  }
10762 
10763  /* make two passes through the points so we don't need to realloc */
10764  for (pass=0; pass < 2; ++pass)
10765  {
10766  float x=0,y=0;
10767  if (pass == 1) {
10768  points = (struct nk_tt__point *)
10769  alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0]));
10770  if (points == 0) goto error;
10771  }
10772  num_points = 0;
10773  n= -1;
10774 
10775  for (i=0; i < num_verts; ++i)
10776  {
10777  switch (vertices[i].type) {
10778  case NK_TT_vmove:
10779  /* start the next contour */
10780  if (n >= 0)
10781  (*contour_lengths)[n] = num_points - start;
10782  ++n;
10783  start = num_points;
10784 
10785  x = vertices[i].x, y = vertices[i].y;
10786  nk_tt__add_point(points, num_points++, x,y);
10787  break;
10788  case NK_TT_vline:
10789  x = vertices[i].x, y = vertices[i].y;
10790  nk_tt__add_point(points, num_points++, x, y);
10791  break;
10792  case NK_TT_vcurve:
10793  nk_tt__tesselate_curve(points, &num_points, x,y,
10794  vertices[i].cx, vertices[i].cy,
10795  vertices[i].x, vertices[i].y,
10796  objspace_flatness_squared, 0);
10797  x = vertices[i].x, y = vertices[i].y;
10798  break;
10799  default: break;
10800  }
10801  }
10802  (*contour_lengths)[n] = num_points - start;
10803  }
10804  return points;
10805 
10806 error:
10807  alloc->free(alloc->userdata, points);
10808  alloc->free(alloc->userdata, *contour_lengths);
10809  *contour_lengths = 0;
10810  *num_contours = 0;
10811  return 0;
10812 }
10813 
10814 NK_INTERN void
10815 nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels,
10816  struct nk_tt_vertex *vertices, int num_verts,
10817  float scale_x, float scale_y, float shift_x, float shift_y,
10818  int x_off, int y_off, int invert, struct nk_allocator *alloc)
10819 {
10820  float scale = scale_x > scale_y ? scale_y : scale_x;
10821  int winding_count, *winding_lengths;
10822  struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts,
10823  flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc);
10824 
10825  NK_ASSERT(alloc);
10826  if (windings) {
10827  nk_tt__rasterize(result, windings, winding_lengths, winding_count,
10828  scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc);
10829  alloc->free(alloc->userdata, winding_lengths);
10830  alloc->free(alloc->userdata, windings);
10831  }
10832 }
10833 
10834 NK_INTERN void
10835 nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_fontinfo *info, unsigned char *output,
10836  int out_w, int out_h, int out_stride, float scale_x, float scale_y,
10837  float shift_x, float shift_y, int glyph, struct nk_allocator *alloc)
10838 {
10839  int ix0,iy0;
10840  struct nk_tt_vertex *vertices;
10841  int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices);
10842  struct nk_tt__bitmap gbm;
10843 
10844  nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x,
10845  shift_y, &ix0,&iy0,0,0);
10846  gbm.pixels = output;
10847  gbm.w = out_w;
10848  gbm.h = out_h;
10849  gbm.stride = out_stride;
10850 
10851  if (gbm.w && gbm.h)
10852  nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y,
10853  shift_x, shift_y, ix0,iy0, 1, alloc);
10854  alloc->free(alloc->userdata, vertices);
10855 }
10856 
10857 /*-------------------------------------------------------------
10858  * Bitmap baking
10859  * --------------------------------------------------------------*/
10860 NK_INTERN int
10861 nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels,
10862  int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc)
10863 {
10864  int num_nodes = pw - padding;
10865  struct nk_rp_context *context = (struct nk_rp_context *)
10866  alloc->alloc(alloc->userdata,0, sizeof(*context));
10867  struct nk_rp_node *nodes = (struct nk_rp_node*)
10868  alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes));
10869 
10870  if (context == 0 || nodes == 0) {
10871  if (context != 0) alloc->free(alloc->userdata, context);
10872  if (nodes != 0) alloc->free(alloc->userdata, nodes);
10873  return 0;
10874  }
10875 
10876  spc->width = pw;
10877  spc->height = ph;
10878  spc->pixels = pixels;
10879  spc->pack_info = context;
10880  spc->nodes = nodes;
10881  spc->padding = padding;
10882  spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw;
10883  spc->h_oversample = 1;
10884  spc->v_oversample = 1;
10885 
10886  nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes);
10887  if (pixels)
10888  NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */
10889  return 1;
10890 }
10891 
10892 NK_INTERN void
10893 nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc)
10894 {
10895  alloc->free(alloc->userdata, spc->nodes);
10896  alloc->free(alloc->userdata, spc->pack_info);
10897 }
10898 
10899 NK_INTERN void
10900 nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc,
10901  unsigned int h_oversample, unsigned int v_oversample)
10902 {
10903  NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE);
10904  NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE);
10905  if (h_oversample <= NK_TT_MAX_OVERSAMPLE)
10906  spc->h_oversample = h_oversample;
10907  if (v_oversample <= NK_TT_MAX_OVERSAMPLE)
10908  spc->v_oversample = v_oversample;
10909 }
10910 
10911 NK_INTERN void
10912 nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
10913  int kernel_width)
10914 {
10915  unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
10916  int safe_w = w - kernel_width;
10917  int j;
10918 
10919  for (j=0; j < h; ++j)
10920  {
10921  int i;
10922  unsigned int total;
10923  NK_MEMSET(buffer, 0, (nk_size)kernel_width);
10924 
10925  total = 0;
10926 
10927  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
10928  switch (kernel_width) {
10929  case 2:
10930  for (i=0; i <= safe_w; ++i) {
10931  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10932  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10933  pixels[i] = (unsigned char) (total / 2);
10934  }
10935  break;
10936  case 3:
10937  for (i=0; i <= safe_w; ++i) {
10938  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10939  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10940  pixels[i] = (unsigned char) (total / 3);
10941  }
10942  break;
10943  case 4:
10944  for (i=0; i <= safe_w; ++i) {
10945  total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK];
10946  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10947  pixels[i] = (unsigned char) (total / 4);
10948  }
10949  break;
10950  case 5:
10951  for (i=0; i <= safe_w; ++i) {
10952  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10953  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10954  pixels[i] = (unsigned char) (total / 5);
10955  }
10956  break;
10957  default:
10958  for (i=0; i <= safe_w; ++i) {
10959  total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]);
10960  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i];
10961  pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
10962  }
10963  break;
10964  }
10965 
10966  for (; i < w; ++i) {
10967  NK_ASSERT(pixels[i] == 0);
10968  total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
10969  pixels[i] = (unsigned char) (total / (unsigned int)kernel_width);
10970  }
10971  pixels += stride_in_bytes;
10972  }
10973 }
10974 
10975 NK_INTERN void
10976 nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes,
10977  int kernel_width)
10978 {
10979  unsigned char buffer[NK_TT_MAX_OVERSAMPLE];
10980  int safe_h = h - kernel_width;
10981  int j;
10982 
10983  for (j=0; j < w; ++j)
10984  {
10985  int i;
10986  unsigned int total;
10987  NK_MEMSET(buffer, 0, (nk_size)kernel_width);
10988 
10989  total = 0;
10990 
10991  /* make kernel_width a constant in common cases so compiler can optimize out the divide */
10992  switch (kernel_width) {
10993  case 2:
10994  for (i=0; i <= safe_h; ++i) {
10995  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
10996  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
10997  pixels[i*stride_in_bytes] = (unsigned char) (total / 2);
10998  }
10999  break;
11000  case 3:
11001  for (i=0; i <= safe_h; ++i) {
11002  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11003  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11004  pixels[i*stride_in_bytes] = (unsigned char) (total / 3);
11005  }
11006  break;
11007  case 4:
11008  for (i=0; i <= safe_h; ++i) {
11009  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11010  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11011  pixels[i*stride_in_bytes] = (unsigned char) (total / 4);
11012  }
11013  break;
11014  case 5:
11015  for (i=0; i <= safe_h; ++i) {
11016  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11017  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11018  pixels[i*stride_in_bytes] = (unsigned char) (total / 5);
11019  }
11020  break;
11021  default:
11022  for (i=0; i <= safe_h; ++i) {
11023  total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]);
11024  buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes];
11025  pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
11026  }
11027  break;
11028  }
11029 
11030  for (; i < h; ++i) {
11031  NK_ASSERT(pixels[i*stride_in_bytes] == 0);
11032  total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]);
11033  pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width);
11034  }
11035  pixels += 1;
11036  }
11037 }
11038 
11039 NK_INTERN float
11040 nk_tt__oversample_shift(int oversample)
11041 {
11042  if (!oversample)
11043  return 0.0f;
11044 
11045  /* The prefilter is a box filter of width "oversample", */
11046  /* which shifts phase by (oversample - 1)/2 pixels in */
11047  /* oversampled space. We want to shift in the opposite */
11048  /* direction to counter this. */
11049  return (float)-(oversample - 1) / (2.0f * (float)oversample);
11050 }
11051 
11052 /* rects array must be big enough to accommodate all characters in the given ranges */
11053 NK_INTERN int
11054 nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc,
11055  struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
11056  int num_ranges, struct nk_rp_rect *rects)
11057 {
11058  int i,j,k;
11059  k = 0;
11060 
11061  for (i=0; i < num_ranges; ++i) {
11062  float fh = ranges[i].font_size;
11063  float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh):
11064  nk_tt_ScaleForMappingEmToPixels(info, -fh);
11065  ranges[i].h_oversample = (unsigned char) spc->h_oversample;
11066  ranges[i].v_oversample = (unsigned char) spc->v_oversample;
11067  for (j=0; j < ranges[i].num_chars; ++j) {
11068  int x0,y0,x1,y1;
11069  int codepoint = ranges[i].first_unicode_codepoint_in_range ?
11070  ranges[i].first_unicode_codepoint_in_range + j :
11071  ranges[i].array_of_unicode_codepoints[j];
11072 
11073  int glyph = nk_tt_FindGlyphIndex(info, codepoint);
11074  nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample,
11075  scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1);
11076  rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1);
11077  rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1);
11078  ++k;
11079  }
11080  }
11081  return k;
11082 }
11083 
11084 NK_INTERN int
11085 nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc,
11086  struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges,
11087  int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc)
11088 {
11089  int i,j,k, return_value = 1;
11090  /* save current values */
11091  int old_h_over = (int)spc->h_oversample;
11092  int old_v_over = (int)spc->v_oversample;
11093  /* rects array must be big enough to accommodate all characters in the given ranges */
11094 
11095  k = 0;
11096  for (i=0; i < num_ranges; ++i)
11097  {
11098  float fh = ranges[i].font_size;
11099  float recip_h,recip_v,sub_x,sub_y;
11100  float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh):
11101  nk_tt_ScaleForMappingEmToPixels(info, -fh);
11102 
11103  spc->h_oversample = ranges[i].h_oversample;
11104  spc->v_oversample = ranges[i].v_oversample;
11105 
11106  recip_h = 1.0f / (float)spc->h_oversample;
11107  recip_v = 1.0f / (float)spc->v_oversample;
11108 
11109  sub_x = nk_tt__oversample_shift((int)spc->h_oversample);
11110  sub_y = nk_tt__oversample_shift((int)spc->v_oversample);
11111 
11112  for (j=0; j < ranges[i].num_chars; ++j)
11113  {
11114  struct nk_rp_rect *r = &rects[k];
11115  if (r->was_packed)
11116  {
11117  struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j];
11118  int advance, lsb, x0,y0,x1,y1;
11119  int codepoint = ranges[i].first_unicode_codepoint_in_range ?
11120  ranges[i].first_unicode_codepoint_in_range + j :
11121  ranges[i].array_of_unicode_codepoints[j];
11122  int glyph = nk_tt_FindGlyphIndex(info, codepoint);
11123  nk_rp_coord pad = (nk_rp_coord) spc->padding;
11124 
11125  /* pad on left and top */
11126  r->x = (nk_rp_coord)((int)r->x + (int)pad);
11127  r->y = (nk_rp_coord)((int)r->y + (int)pad);
11128  r->w = (nk_rp_coord)((int)r->w - (int)pad);
11129  r->h = (nk_rp_coord)((int)r->h - (int)pad);
11130 
11131  nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb);
11132  nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample,
11133  (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1);
11134  nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes,
11135  (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1),
11136  spc->stride_in_bytes, scale * (float)spc->h_oversample,
11137  scale * (float)spc->v_oversample, 0,0, glyph, alloc);
11138 
11139  if (spc->h_oversample > 1)
11140  nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
11141  r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample);
11142 
11143  if (spc->v_oversample > 1)
11144  nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes,
11145  r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample);
11146 
11147  bc->x0 = (nk_ushort) r->x;
11148  bc->y0 = (nk_ushort) r->y;
11149  bc->x1 = (nk_ushort) (r->x + r->w);
11150  bc->y1 = (nk_ushort) (r->y + r->h);
11151  bc->xadvance = scale * (float)advance;
11152  bc->xoff = (float) x0 * recip_h + sub_x;
11153  bc->yoff = (float) y0 * recip_v + sub_y;
11154  bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x;
11155  bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y;
11156  } else {
11157  return_value = 0; /* if any fail, report failure */
11158  }
11159  ++k;
11160  }
11161  }
11162  /* restore original values */
11163  spc->h_oversample = (unsigned int)old_h_over;
11164  spc->v_oversample = (unsigned int)old_v_over;
11165  return return_value;
11166 }
11167 
11168 NK_INTERN void
11169 nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph,
11170  int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q,
11171  int align_to_integer)
11172 {
11173  float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph;
11174  struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index);
11175  if (align_to_integer) {
11176  int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f);
11177  int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f);
11178 
11179  float x = (float)tx;
11180  float y = (float)ty;
11181 
11182  q->x0 = x;
11183  q->y0 = y;
11184  q->x1 = x + b->xoff2 - b->xoff;
11185  q->y1 = y + b->yoff2 - b->yoff;
11186  } else {
11187  q->x0 = *xpos + b->xoff;
11188  q->y0 = *ypos + b->yoff;
11189  q->x1 = *xpos + b->xoff2;
11190  q->y1 = *ypos + b->yoff2;
11191  }
11192  q->s0 = b->x0 * ipw;
11193  q->t0 = b->y0 * iph;
11194  q->s1 = b->x1 * ipw;
11195  q->t1 = b->y1 * iph;
11196  *xpos += b->xadvance;
11197 }
11198 
11199 /* -------------------------------------------------------------
11200  *
11201  * FONT BAKING
11202  *
11203  * --------------------------------------------------------------*/
11204 struct nk_font_bake_data {
11205  struct nk_tt_fontinfo info;
11206  struct nk_rp_rect *rects;
11207  struct nk_tt_pack_range *ranges;
11208  nk_rune range_count;
11209 };
11210 
11211 struct nk_font_baker {
11212  struct nk_allocator alloc;
11213  struct nk_tt_pack_context spc;
11214  struct nk_font_bake_data *build;
11215  struct nk_tt_packedchar *packed_chars;
11216  struct nk_rp_rect *rects;
11217  struct nk_tt_pack_range *ranges;
11218 };
11219 
11220 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect);
11221 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range);
11222 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar);
11223 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data);
11224 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker);
11225 
11226 NK_INTERN int
11227 nk_range_count(const nk_rune *range)
11228 {
11229  const nk_rune *iter = range;
11230  NK_ASSERT(range);
11231  if (!range) return 0;
11232  while (*(iter++) != 0);
11233  return (iter == range) ? 0 : (int)((iter - range)/2);
11234 }
11235 
11236 NK_INTERN int
11237 nk_range_glyph_count(const nk_rune *range, int count)
11238 {
11239  int i = 0;
11240  int total_glyphs = 0;
11241  for (i = 0; i < count; ++i) {
11242  int diff;
11243  nk_rune f = range[(i*2)+0];
11244  nk_rune t = range[(i*2)+1];
11245  NK_ASSERT(t >= f);
11246  diff = (int)((t - f) + 1);
11247  total_glyphs += diff;
11248  }
11249  return total_glyphs;
11250 }
11251 
11252 NK_API const nk_rune*
11253 nk_font_default_glyph_ranges(void)
11254 {
11255  NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0};
11256  return ranges;
11257 }
11258 
11259 NK_API const nk_rune*
11260 nk_font_chinese_glyph_ranges(void)
11261 {
11262  NK_STORAGE const nk_rune ranges[] = {
11263  0x0020, 0x00FF,
11264  0x3000, 0x30FF,
11265  0x31F0, 0x31FF,
11266  0xFF00, 0xFFEF,
11267  0x4e00, 0x9FAF,
11268  0
11269  };
11270  return ranges;
11271 }
11272 
11273 NK_API const nk_rune*
11274 nk_font_cyrillic_glyph_ranges(void)
11275 {
11276  NK_STORAGE const nk_rune ranges[] = {
11277  0x0020, 0x00FF,
11278  0x0400, 0x052F,
11279  0x2DE0, 0x2DFF,
11280  0xA640, 0xA69F,
11281  0
11282  };
11283  return ranges;
11284 }
11285 
11286 NK_API const nk_rune*
11287 nk_font_korean_glyph_ranges(void)
11288 {
11289  NK_STORAGE const nk_rune ranges[] = {
11290  0x0020, 0x00FF,
11291  0x3131, 0x3163,
11292  0xAC00, 0xD79D,
11293  0
11294  };
11295  return ranges;
11296 }
11297 
11298 NK_INTERN void
11299 nk_font_baker_memory(nk_size *temp, int *glyph_count,
11300  struct nk_font_config *config_list, int count)
11301 {
11302  int range_count = 0;
11303  int total_range_count = 0;
11304  struct nk_font_config *iter;
11305 
11306  NK_ASSERT(config_list);
11307  NK_ASSERT(glyph_count);
11308  if (!config_list) {
11309  *temp = 0;
11310  *glyph_count = 0;
11311  return;
11312  }
11313 
11314  *glyph_count = 0;
11315  if (!config_list->range)
11316  config_list->range = nk_font_default_glyph_ranges();
11317  for (iter = config_list; iter; iter = iter->next) {
11318  range_count = nk_range_count(iter->range);
11319  total_range_count += range_count;
11320  *glyph_count += nk_range_glyph_count(iter->range, range_count);
11321  }
11322 
11323  *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect);
11324  *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range);
11325  *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar);
11326  *temp += (nk_size)count * sizeof(struct nk_font_bake_data);
11327  *temp += sizeof(struct nk_font_baker);
11328  *temp += nk_rect_align + nk_range_align + nk_char_align;
11329  *temp += nk_build_align + nk_baker_align;
11330 }
11331 
11332 NK_INTERN struct nk_font_baker*
11333 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc)
11334 {
11335  struct nk_font_baker *baker;
11336  if (!memory) return 0;
11337  /* setup baker inside a memory block */
11338  baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align);
11339  baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align);
11340  baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align);
11341  baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align);
11342  baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align);
11343  baker->alloc = *alloc;
11344  return baker;
11345 }
11346 
11347 NK_INTERN int
11348 nk_font_bake_pack(struct nk_font_baker *baker,
11349  nk_size *image_memory, int *width, int *height, struct nk_recti *custom,
11350  const struct nk_font_config *config_list, int count,
11351  struct nk_allocator *alloc)
11352 {
11353  NK_STORAGE const nk_size max_height = 1024 * 32;
11354  const struct nk_font_config *config_iter;
11355  int total_glyph_count = 0;
11356  int total_range_count = 0;
11357  int range_count = 0;
11358  int i = 0;
11359 
11360  NK_ASSERT(image_memory);
11361  NK_ASSERT(width);
11362  NK_ASSERT(height);
11363  NK_ASSERT(config_list);
11364  NK_ASSERT(count);
11365  NK_ASSERT(alloc);
11366 
11367  if (!image_memory || !width || !height || !config_list || !count) return nk_false;
11368  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
11369  range_count = nk_range_count(config_iter->range);
11370  total_range_count += range_count;
11371  total_glyph_count += nk_range_glyph_count(config_iter->range, range_count);
11372  }
11373 
11374  /* setup font baker from temporary memory */
11375  for (config_iter = config_list; config_iter; config_iter = config_iter->next) {
11376  const struct nk_font_config *cfg = config_iter;
11377  if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)cfg->ttf_blob, 0))
11378  return nk_false;
11379  }
11380 
11381  *height = 0;
11382  *width = (total_glyph_count > 1000) ? 1024 : 512;
11383  nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc);
11384  {
11385  int input_i = 0;
11386  int range_n = 0;
11387  int rect_n = 0;
11388  int char_n = 0;
11389 
11390  if (custom) {
11391  /* pack custom user data first so it will be in the upper left corner*/
11392  struct nk_rp_rect custom_space;
11393  nk_zero(&custom_space, sizeof(custom_space));
11394  custom_space.w = (nk_rp_coord)((custom->w * 2) + 1);
11395  custom_space.h = (nk_rp_coord)(custom->h + 1);
11396 
11397  nk_tt_PackSetOversampling(&baker->spc, 1, 1);
11398  nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1);
11399  *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h));
11400 
11401  custom->x = (short)custom_space.x;
11402  custom->y = (short)custom_space.y;
11403  custom->w = (short)custom_space.w;
11404  custom->h = (short)custom_space.h;
11405  }
11406 
11407  /* first font pass: pack all glyphs */
11408  for (input_i = 0, config_iter = config_list; input_i < count && config_iter;
11409  input_i++, config_iter = config_iter->next)
11410  {
11411  int n = 0;
11412  int glyph_count;
11413  const nk_rune *in_range;
11414  const struct nk_font_config *cfg = config_iter;
11415  struct nk_font_bake_data *tmp = &baker->build[input_i];
11416 
11417  /* count glyphs + ranges in current font */
11418  glyph_count = 0; range_count = 0;
11419  for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) {
11420  glyph_count += (int)(in_range[1] - in_range[0]) + 1;
11421  range_count++;
11422  }
11423 
11424  /* setup ranges */
11425  tmp->ranges = baker->ranges + range_n;
11426  tmp->range_count = (nk_rune)range_count;
11427  range_n += range_count;
11428  for (i = 0; i < range_count; ++i) {
11429  in_range = &cfg->range[i * 2];
11430  tmp->ranges[i].font_size = cfg->size;
11431  tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0];
11432  tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1;
11433  tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n;
11434  char_n += tmp->ranges[i].num_chars;
11435  }
11436 
11437  /* pack */
11438  tmp->rects = baker->rects + rect_n;
11439  rect_n += glyph_count;
11440  nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
11441  n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info,
11442  tmp->ranges, (int)tmp->range_count, tmp->rects);
11443  nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n);
11444 
11445  /* texture height */
11446  for (i = 0; i < n; ++i) {
11447  if (tmp->rects[i].was_packed)
11448  *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h);
11449  }
11450  }
11451  NK_ASSERT(rect_n == total_glyph_count);
11452  NK_ASSERT(char_n == total_glyph_count);
11453  NK_ASSERT(range_n == total_range_count);
11454  }
11455  *height = (int)nk_round_up_pow2((nk_uint)*height);
11456  *image_memory = (nk_size)(*width) * (nk_size)(*height);
11457  return nk_true;
11458 }
11459 
11460 NK_INTERN void
11461 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height,
11462  struct nk_font_glyph *glyphs, int glyphs_count,
11463  const struct nk_font_config *config_list, int font_count)
11464 {
11465  int input_i = 0;
11466  nk_rune glyph_n = 0;
11467  const struct nk_font_config *config_iter;
11468 
11469  NK_ASSERT(image_memory);
11470  NK_ASSERT(width);
11471  NK_ASSERT(height);
11472  NK_ASSERT(config_list);
11473  NK_ASSERT(baker);
11474  NK_ASSERT(font_count);
11475  NK_ASSERT(glyphs_count);
11476  if (!image_memory || !width || !height || !config_list ||
11477  !font_count || !glyphs || !glyphs_count)
11478  return;
11479 
11480  /* second font pass: render glyphs */
11481  nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height));
11482  baker->spc.pixels = (unsigned char*)image_memory;
11483  baker->spc.height = (int)height;
11484  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
11485  ++input_i, config_iter = config_iter->next)
11486  {
11487  const struct nk_font_config *cfg = config_iter;
11488  struct nk_font_bake_data *tmp = &baker->build[input_i];
11489  nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v);
11490  nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges,
11491  (int)tmp->range_count, tmp->rects, &baker->alloc);
11492  }
11493  nk_tt_PackEnd(&baker->spc, &baker->alloc);
11494 
11495  /* third pass: setup font and glyphs */
11496  for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter;
11497  ++input_i, config_iter = config_iter->next)
11498  {
11499  nk_size i = 0;
11500  int char_idx = 0;
11501  nk_rune glyph_count = 0;
11502  const struct nk_font_config *cfg = config_iter;
11503  struct nk_font_bake_data *tmp = &baker->build[input_i];
11504  struct nk_baked_font *dst_font = cfg->font;
11505 
11506  float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size);
11507  int unscaled_ascent, unscaled_descent, unscaled_line_gap;
11508  nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent,
11509  &unscaled_line_gap);
11510 
11511  /* fill baked font */
11512  if (!cfg->merge_mode) {
11513  dst_font->ranges = cfg->range;
11514  dst_font->height = cfg->size;
11515  dst_font->ascent = ((float)unscaled_ascent * font_scale);
11516  dst_font->descent = ((float)unscaled_descent * font_scale);
11517  dst_font->glyph_offset = glyph_n;
11518  }
11519 
11520  /* fill own baked font glyph array */
11521  for (i = 0; i < tmp->range_count; ++i)
11522  {
11523  struct nk_tt_pack_range *range = &tmp->ranges[i];
11524  for (char_idx = 0; char_idx < range->num_chars; char_idx++)
11525  {
11526  nk_rune codepoint = 0;
11527  float dummy_x = 0, dummy_y = 0;
11528  struct nk_tt_aligned_quad q;
11529  struct nk_font_glyph *glyph;
11530 
11531  /* query glyph bounds from stb_truetype */
11532  const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx];
11533  if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue;
11534  codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx);
11535  nk_tt_GetPackedQuad(range->chardata_for_range, (int)width,
11536  (int)height, char_idx, &dummy_x, &dummy_y, &q, 0);
11537 
11538  /* fill own glyph type with data */
11539  glyph = &glyphs[dst_font->glyph_offset + (unsigned int)glyph_count];
11540  glyph->codepoint = codepoint;
11541  glyph->x0 = q.x0; glyph->y0 = q.y0;
11542  glyph->x1 = q.x1; glyph->y1 = q.y1;
11543  glyph->y0 += (dst_font->ascent + 0.5f);
11544  glyph->y1 += (dst_font->ascent + 0.5f);
11545  glyph->w = glyph->x1 - glyph->x0 + 0.5f;
11546  glyph->h = glyph->y1 - glyph->y0;
11547 
11548  if (cfg->coord_type == NK_COORD_PIXEL) {
11549  glyph->u0 = q.s0 * (float)width;
11550  glyph->v0 = q.t0 * (float)height;
11551  glyph->u1 = q.s1 * (float)width;
11552  glyph->v1 = q.t1 * (float)height;
11553  } else {
11554  glyph->u0 = q.s0;
11555  glyph->v0 = q.t0;
11556  glyph->u1 = q.s1;
11557  glyph->v1 = q.t1;
11558  }
11559  glyph->xadvance = (pc->xadvance + cfg->spacing.x);
11560  if (cfg->pixel_snap)
11561  glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f);
11562  glyph_count++;
11563  }
11564  }
11565  dst_font->glyph_count = glyph_count;
11566  glyph_n += dst_font->glyph_count;
11567  }
11568 }
11569 
11570 NK_INTERN void
11571 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height,
11572  struct nk_recti img_dst, const char *texture_data_mask, int tex_width,
11573  int tex_height, char white, char black)
11574 {
11575  nk_byte *pixels;
11576  int y = 0;
11577  int x = 0;
11578  int n = 0;
11579 
11580  NK_ASSERT(img_memory);
11581  NK_ASSERT(img_width);
11582  NK_ASSERT(img_height);
11583  NK_ASSERT(texture_data_mask);
11584  NK_UNUSED(tex_height);
11585  if (!img_memory || !img_width || !img_height || !texture_data_mask)
11586  return;
11587 
11588  pixels = (nk_byte*)img_memory;
11589  for (y = 0, n = 0; y < tex_height; ++y) {
11590  for (x = 0; x < tex_width; ++x, ++n) {
11591  const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width);
11592  const int off1 = off0 + 1 + tex_width;
11593  pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00;
11594  pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00;
11595  }
11596  }
11597 }
11598 
11599 NK_INTERN void
11600 nk_font_bake_convert(void *out_memory, int img_width, int img_height,
11601  const void *in_memory)
11602 {
11603  int n = 0;
11604  nk_rune *dst;
11605  const nk_byte *src;
11606 
11607  NK_ASSERT(out_memory);
11608  NK_ASSERT(in_memory);
11609  NK_ASSERT(img_width);
11610  NK_ASSERT(img_height);
11611  if (!out_memory || !in_memory || !img_height || !img_width) return;
11612 
11613  dst = (nk_rune*)out_memory;
11614  src = (const nk_byte*)in_memory;
11615  for (n = (int)(img_width * img_height); n > 0; n--)
11616  *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF;
11617 }
11618 
11619 /* -------------------------------------------------------------
11620  *
11621  * FONT
11622  *
11623  * --------------------------------------------------------------*/
11624 NK_INTERN float
11625 nk_font_text_width(nk_handle handle, float height, const char *text, int len)
11626 {
11627  nk_rune unicode;
11628  int text_len = 0;
11629  float text_width = 0;
11630  int glyph_len = 0;
11631  float scale = 0;
11632 
11633  struct nk_font *font = (struct nk_font*)handle.ptr;
11634  NK_ASSERT(font);
11635  NK_ASSERT(font->glyphs);
11636  if (!font || !text || !len)
11637  return 0;
11638 
11639  scale = height/font->info.height;
11640  glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len);
11641  if (!glyph_len) return 0;
11642  while (text_len <= (int)len && glyph_len) {
11643  const struct nk_font_glyph *g;
11644  if (unicode == NK_UTF_INVALID) break;
11645 
11646  /* query currently drawn glyph information */
11647  g = nk_font_find_glyph(font, unicode);
11648  text_width += g->xadvance * scale;
11649 
11650  /* offset next glyph */
11651  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len);
11652  text_len += glyph_len;
11653  }
11654  return text_width;
11655 }
11656 
11657 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11658 NK_INTERN void
11659 nk_font_query_font_glyph(nk_handle handle, float height,
11660  struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
11661 {
11662  float scale;
11663  const struct nk_font_glyph *g;
11664  struct nk_font *font;
11665 
11666  NK_ASSERT(glyph);
11667  NK_UNUSED(next_codepoint);
11668 
11669  font = (struct nk_font*)handle.ptr;
11670  NK_ASSERT(font);
11671  NK_ASSERT(font->glyphs);
11672  if (!font || !glyph)
11673  return;
11674 
11675  scale = height/font->info.height;
11676  g = nk_font_find_glyph(font, codepoint);
11677  glyph->width = (g->x1 - g->x0) * scale;
11678  glyph->height = (g->y1 - g->y0) * scale;
11679  glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale);
11680  glyph->xadvance = (g->xadvance * scale);
11681  glyph->uv[0] = nk_vec2(g->u0, g->v0);
11682  glyph->uv[1] = nk_vec2(g->u1, g->v1);
11683 }
11684 #endif
11685 
11686 NK_API const struct nk_font_glyph*
11687 nk_font_find_glyph(struct nk_font *font, nk_rune unicode)
11688 {
11689  int i = 0;
11690  int count;
11691  int total_glyphs = 0;
11692  const struct nk_font_glyph *glyph = 0;
11693 
11694  NK_ASSERT(font);
11695  NK_ASSERT(font->glyphs);
11696  NK_ASSERT(font->info.ranges);
11697  if (!font || !font->glyphs) return 0;
11698 
11699  glyph = font->fallback;
11700  count = nk_range_count(font->info.ranges);
11701  for (i = 0; i < count; ++i) {
11702  nk_rune f = font->info.ranges[(i*2)+0];
11703  nk_rune t = font->info.ranges[(i*2)+1];
11704  int diff = (int)((t - f) + 1);
11705  if (unicode >= f && unicode <= t)
11706  return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))];
11707  total_glyphs += diff;
11708  }
11709  return glyph;
11710 }
11711 
11712 NK_INTERN void
11713 nk_font_init(struct nk_font *font, float pixel_height,
11714  nk_rune fallback_codepoint, struct nk_font_glyph *glyphs,
11715  const struct nk_baked_font *baked_font, nk_handle atlas)
11716 {
11717  struct nk_baked_font baked;
11718  NK_ASSERT(font);
11719  NK_ASSERT(glyphs);
11720  NK_ASSERT(baked_font);
11721  if (!font || !glyphs || !baked_font)
11722  return;
11723 
11724  baked = *baked_font;
11725  font->fallback = 0;
11726  font->info = baked;
11727  font->scale = (float)pixel_height / (float)font->info.height;
11728  font->glyphs = &glyphs[baked_font->glyph_offset];
11729  font->texture = atlas;
11730  font->fallback_codepoint = fallback_codepoint;
11731  font->fallback = nk_font_find_glyph(font, fallback_codepoint);
11732 
11733  font->handle.height = font->info.height * font->scale;
11734  font->handle.width = nk_font_text_width;
11735  font->handle.userdata.ptr = font;
11736 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
11737  font->handle.query = nk_font_query_font_glyph;
11738  font->handle.texture = font->texture;
11739 #endif
11740 }
11741 
11742 /* ---------------------------------------------------------------------------
11743  *
11744  * DEFAULT FONT
11745  *
11746  * ProggyClean.ttf
11747  * Copyright (c) 2004, 2005 Tristan Grimmer
11748  * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip)
11749  * Download and more information at http://upperbounds.net
11750  *-----------------------------------------------------------------------------*/
11751 #ifdef NK_INCLUDE_DEFAULT_FONT
11752 
11753  #ifdef __clang__
11754 #pragma clang diagnostic push
11755 
11756 #pragma clang diagnostic ignored "-Woverlength-strings"
11757 #elif defined(__GNUC__) || defined(__GNUG__)
11758 #pragma GCC diagnostic push
11759 #pragma GCC diagnostic ignored "-Woverlength-strings"
11760 #endif
11761 
11762 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] =
11763  "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/"
11764  "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#"
11765  "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#[email protected]<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL"
11766  "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#[email protected]'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N"
11767  "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"
11768  "*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)"
11769  "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"
11770  "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."
11771  "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"
11772  "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(,)"
11773  "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#"
11774  "'/###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"
11775  "_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"
11776  "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/"
11777  "/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"
11778  "%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&#"
11779  "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)("
11780  "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"
11781  "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"
11782  "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^-"
11783  "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-"
11784  "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"
11785  "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%"
11786  "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]"
11787  "%(?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"
11788  "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:"
11789  "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("
11790  "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<[email protected];x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<"
11791  "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'?"
11792  "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/;"
11793  ")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"
11794  "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("
11795  "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"
11796  "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTG&#1T5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q"
11797  "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<-"
11798  "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;[email protected]$m%#QvQS8U@)2Z+3K:AKM5i"
11799  "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"
11800  ".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@@"
11801  "$&)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*"
11802  "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"
11803  "@-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&#"
11804  "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#"
11805  "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"
11806  "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"
11807  "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&#"
11808  "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"
11809  ":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+"
11810  "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*"
11811  "$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"
11812  ":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"
11813  "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"
11814  "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"
11815  "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"
11816  ":^#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@&]>"
11817  "_>@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%"
11818  "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;"
11819  "^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:"
11820  "+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%"
11821  "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-"
11822  "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*"
11823  "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"
11824  "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-"
11825  "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`"
11826  "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]%/"
11827  "+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"
11828  "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"
11829  "?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"
11830  "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"
11831  ">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'>"
11832  "[%$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"
11833  "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#"
11834  "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$"
11835  "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,)"
11836  "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"
11837  "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"
11838  "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"
11839  "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(#"
11840  ";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&>"
11841  "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#"
11842  "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"
11843  "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#"
11844  "/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-#"
11845  "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#"
11846  "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP"
11847  "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp"
11848  "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#";
11849 #endif /* NK_INCLUDE_DEFAULT_FONT */
11850 
11851 #define NK_CURSOR_DATA_W 90
11852 #define NK_CURSOR_DATA_H 27
11853 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] =
11854 {
11855  "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX"
11856  "..- -X.....X- X.X - X.X -X.....X - X.....X"
11857  "--- -XXX.XXX- X...X - X...X -X....X - X....X"
11858  "X - X.X - X.....X - X.....X -X...X - X...X"
11859  "XX - X.X -X.......X- X.......X -X..X.X - X.X..X"
11860  "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X"
11861  "X..X - X.X - X.X - X.X -XX X.X - X.X XX"
11862  "X...X - X.X - X.X - XX X.X XX - X.X - X.X "
11863  "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X "
11864  "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X "
11865  "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X "
11866  "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X "
11867  "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X "
11868  "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X "
11869  "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X "
11870  "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X "
11871  "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX "
11872  "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------"
11873  "X.X X..X - -X.......X- X.......X - XX XX - "
11874  "XX X..X - - X.....X - X.....X - X.X X.X - "
11875  " X..X - X...X - X...X - X..X X..X - "
11876  " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - "
11877  "------------ - X - X -X.....................X- "
11878  " ----------------------------------- X...XXXXXXXXXXXXX...X - "
11879  " - X..X X..X - "
11880  " - X.X X.X - "
11881  " - XX XX - "
11882 };
11883 
11884 #ifdef __clang__
11885 #pragma clang diagnostic pop
11886 #elif defined(__GNUC__) || defined(__GNUG__)
11887 #pragma GCC diagnostic pop
11888 #endif
11889 
11890 NK_INTERN unsigned int
11891 nk_decompress_length(unsigned char *input)
11892 {
11893  return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]);
11894 }
11895 
11896 NK_GLOBAL unsigned char *nk__barrier;
11897 NK_GLOBAL unsigned char *nk__barrier2;
11898 NK_GLOBAL unsigned char *nk__barrier3;
11899 NK_GLOBAL unsigned char *nk__barrier4;
11900 NK_GLOBAL unsigned char *nk__dout;
11901 
11902 NK_INTERN void
11903 nk__match(unsigned char *data, unsigned int length)
11904 {
11905  /* INVERSE of memmove... write each byte before copying the next...*/
11906  NK_ASSERT (nk__dout + length <= nk__barrier);
11907  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
11908  if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; }
11909  while (length--) *nk__dout++ = *data++;
11910 }
11911 
11912 NK_INTERN void
11913 nk__lit(unsigned char *data, unsigned int length)
11914 {
11915  NK_ASSERT (nk__dout + length <= nk__barrier);
11916  if (nk__dout + length > nk__barrier) { nk__dout += length; return; }
11917  if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; }
11918  NK_MEMCPY(nk__dout, data, length);
11919  nk__dout += length;
11920 }
11921 
11922 #define nk__in2(x) ((i[x] << 8) + i[(x)+1])
11923 #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1))
11924 #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1))
11925 
11926 NK_INTERN unsigned char*
11927 nk_decompress_token(unsigned char *i)
11928 {
11929  if (*i >= 0x20) { /* use fewer if's for cases that expand small */
11930  if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2;
11931  else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3;
11932  else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1);
11933  } else { /* more ifs for cases that expand large, since overhead is amortized */
11934  if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4;
11935  else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5;
11936  else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1);
11937  else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1);
11938  else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5;
11939  else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6;
11940  }
11941  return i;
11942 }
11943 
11944 NK_INTERN unsigned int
11945 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen)
11946 {
11947  const unsigned long ADLER_MOD = 65521;
11948  unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16;
11949  unsigned long blocklen, i;
11950 
11951  blocklen = buflen % 5552;
11952  while (buflen) {
11953  for (i=0; i + 7 < blocklen; i += 8) {
11954  s1 += buffer[0]; s2 += s1;
11955  s1 += buffer[1]; s2 += s1;
11956  s1 += buffer[2]; s2 += s1;
11957  s1 += buffer[3]; s2 += s1;
11958  s1 += buffer[4]; s2 += s1;
11959  s1 += buffer[5]; s2 += s1;
11960  s1 += buffer[6]; s2 += s1;
11961  s1 += buffer[7]; s2 += s1;
11962  buffer += 8;
11963  }
11964  for (; i < blocklen; ++i) {
11965  s1 += *buffer++; s2 += s1;
11966  }
11967 
11968  s1 %= ADLER_MOD; s2 %= ADLER_MOD;
11969  buflen -= (unsigned int)blocklen;
11970  blocklen = 5552;
11971  }
11972  return (unsigned int)(s2 << 16) + (unsigned int)s1;
11973 }
11974 
11975 NK_INTERN unsigned int
11976 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length)
11977 {
11978  unsigned int olen;
11979  if (nk__in4(0) != 0x57bC0000) return 0;
11980  if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */
11981  olen = nk_decompress_length(i);
11982  nk__barrier2 = i;
11983  nk__barrier3 = i+length;
11984  nk__barrier = output + olen;
11985  nk__barrier4 = output;
11986  i += 16;
11987 
11988  nk__dout = output;
11989  for (;;) {
11990  unsigned char *old_i = i;
11991  i = nk_decompress_token(i);
11992  if (i == old_i) {
11993  if (*i == 0x05 && i[1] == 0xfa) {
11994  NK_ASSERT(nk__dout == output + olen);
11995  if (nk__dout != output + olen) return 0;
11996  if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2))
11997  return 0;
11998  return olen;
11999  } else {
12000  NK_ASSERT(0); /* NOTREACHED */
12001  return 0;
12002  }
12003  }
12004  NK_ASSERT(nk__dout <= output + olen);
12005  if (nk__dout > output + olen)
12006  return 0;
12007  }
12008 }
12009 
12010 NK_INTERN unsigned int
12011 nk_decode_85_byte(char c)
12012 { return (unsigned int)((c >= '\\') ? c-36 : c-35); }
12013 
12014 NK_INTERN void
12015 nk_decode_85(unsigned char* dst, const unsigned char* src)
12016 {
12017  while (*src)
12018  {
12019  unsigned int tmp =
12020  nk_decode_85_byte((char)src[0]) +
12021  85 * (nk_decode_85_byte((char)src[1]) +
12022  85 * (nk_decode_85_byte((char)src[2]) +
12023  85 * (nk_decode_85_byte((char)src[3]) +
12024  85 * nk_decode_85_byte((char)src[4]))));
12025 
12026  /* we can't assume little-endianess. */
12027  dst[0] = (unsigned char)((tmp >> 0) & 0xFF);
12028  dst[1] = (unsigned char)((tmp >> 8) & 0xFF);
12029  dst[2] = (unsigned char)((tmp >> 16) & 0xFF);
12030  dst[3] = (unsigned char)((tmp >> 24) & 0xFF);
12031 
12032  src += 5;
12033  dst += 4;
12034  }
12035 }
12036 
12037 /* -------------------------------------------------------------
12038  *
12039  * FONT ATLAS
12040  *
12041  * --------------------------------------------------------------*/
12042 NK_API struct nk_font_config
12043 nk_font_config(float pixel_height)
12044 {
12045  struct nk_font_config cfg;
12046  nk_zero_struct(cfg);
12047  cfg.ttf_blob = 0;
12048  cfg.ttf_size = 0;
12049  cfg.ttf_data_owned_by_atlas = 0;
12050  cfg.size = pixel_height;
12051  cfg.oversample_h = 3;
12052  cfg.oversample_v = 1;
12053  cfg.pixel_snap = 0;
12054  cfg.coord_type = NK_COORD_UV;
12055  cfg.spacing = nk_vec2(0,0);
12056  cfg.range = nk_font_default_glyph_ranges();
12057  cfg.merge_mode = 0;
12058  cfg.fallback_glyph = '?';
12059  cfg.font = 0;
12060  return cfg;
12061 }
12062 
12063 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
12064 NK_API void
12065 nk_font_atlas_init_default(struct nk_font_atlas *atlas)
12066 {
12067  NK_ASSERT(atlas);
12068  if (!atlas) return;
12070  atlas->temporary.userdata.ptr = 0;
12071  atlas->temporary.alloc = nk_malloc;
12072  atlas->temporary.free = nk_mfree;
12073  atlas->permanent.userdata.ptr = 0;
12074  atlas->permanent.alloc = nk_malloc;
12075  atlas->permanent.free = nk_mfree;
12076 }
12077 #endif
12078 
12079 NK_API void
12080 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc)
12081 {
12082  NK_ASSERT(atlas);
12083  NK_ASSERT(alloc);
12084  if (!atlas || !alloc) return;
12086  atlas->permanent = *alloc;
12087  atlas->temporary = *alloc;
12088 }
12089 
12090 NK_API void
12091 nk_font_atlas_init_custom(struct nk_font_atlas *atlas,
12092  struct nk_allocator *permanent, struct nk_allocator *temporary)
12093 {
12094  NK_ASSERT(atlas);
12095  NK_ASSERT(permanent);
12096  NK_ASSERT(temporary);
12097  if (!atlas || !permanent || !temporary) return;
12099  atlas->permanent = *permanent;
12100  atlas->temporary = *temporary;
12101 }
12102 
12103 NK_API void
12104 nk_font_atlas_begin(struct nk_font_atlas *atlas)
12105 {
12106  NK_ASSERT(atlas);
12107  NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free);
12108  NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free);
12109  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free ||
12110  !atlas->temporary.alloc || !atlas->temporary.free) return;
12111  if (atlas->glyphs) {
12112  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12113  atlas->glyphs = 0;
12114  }
12115  if (atlas->pixel) {
12116  atlas->permanent.free(atlas->permanent.userdata, atlas->pixel);
12117  atlas->pixel = 0;
12118  }
12119 }
12120 
12121 NK_API struct nk_font*
12122 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config)
12123 {
12124  struct nk_font *font = 0;
12125  struct nk_font_config *cfg;
12126 
12127  NK_ASSERT(atlas);
12128  NK_ASSERT(atlas->permanent.alloc);
12129  NK_ASSERT(atlas->permanent.free);
12130  NK_ASSERT(atlas->temporary.alloc);
12131  NK_ASSERT(atlas->temporary.free);
12132 
12133  NK_ASSERT(config);
12134  NK_ASSERT(config->ttf_blob);
12135  NK_ASSERT(config->ttf_size);
12136  NK_ASSERT(config->size > 0.0f);
12137 
12138  if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f||
12139  !atlas->permanent.alloc || !atlas->permanent.free ||
12140  !atlas->temporary.alloc || !atlas->temporary.free)
12141  return 0;
12142 
12143  /* allocate and insert font config into list */
12144  cfg = (struct nk_font_config*)
12145  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config));
12146  NK_MEMCPY(cfg, config, sizeof(*config));
12147  if (!atlas->config) {
12148  atlas->config = cfg;
12149  cfg->next = 0;
12150  } else {
12151  cfg->next = atlas->config;
12152  atlas->config = cfg;
12153  }
12154 
12155  /* allocate new font */
12156  if (!config->merge_mode) {
12157  font = (struct nk_font*)
12158  atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font));
12159  NK_ASSERT(font);
12160  if (!font) return 0;
12161  font->config = cfg;
12162  } else {
12163  NK_ASSERT(atlas->font_num);
12164  font = atlas->fonts;
12165  font->config = cfg;
12166  }
12167 
12168  /* insert font into list */
12169  if (!config->merge_mode) {
12170  if (!atlas->fonts) {
12171  atlas->fonts = font;
12172  font->next = 0;
12173  } else {
12174  font->next = atlas->fonts;
12175  atlas->fonts = font;
12176  }
12177  cfg->font = &font->info;
12178  }
12179 
12180  /* create own copy of .TTF font blob */
12181  if (!config->ttf_data_owned_by_atlas) {
12182  cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size);
12183  NK_ASSERT(cfg->ttf_blob);
12184  if (!cfg->ttf_blob) {
12185  atlas->font_num++;
12186  return 0;
12187  }
12188  NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size);
12189  cfg->ttf_data_owned_by_atlas = 1;
12190  }
12191  atlas->font_num++;
12192  return font;
12193 }
12194 
12195 NK_API struct nk_font*
12196 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory,
12197  nk_size size, float height, const struct nk_font_config *config)
12198 {
12199  struct nk_font_config cfg;
12200  NK_ASSERT(memory);
12201  NK_ASSERT(size);
12202 
12203  NK_ASSERT(atlas);
12204  NK_ASSERT(atlas->temporary.alloc);
12205  NK_ASSERT(atlas->temporary.free);
12206  NK_ASSERT(atlas->permanent.alloc);
12207  NK_ASSERT(atlas->permanent.free);
12208  if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size ||
12209  !atlas->permanent.alloc || !atlas->permanent.free)
12210  return 0;
12211 
12212  cfg = (config) ? *config: nk_font_config(height);
12213  cfg.ttf_blob = memory;
12214  cfg.ttf_size = size;
12215  cfg.size = height;
12216  cfg.ttf_data_owned_by_atlas = 0;
12217  return nk_font_atlas_add(atlas, &cfg);
12218 }
12219 
12220 #ifdef NK_INCLUDE_STANDARD_IO
12221 NK_API struct nk_font*
12222 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path,
12223  float height, const struct nk_font_config *config)
12224 {
12225  nk_size size;
12226  char *memory;
12227  struct nk_font_config cfg;
12228 
12229  NK_ASSERT(atlas);
12230  NK_ASSERT(atlas->temporary.alloc);
12231  NK_ASSERT(atlas->temporary.free);
12232  NK_ASSERT(atlas->permanent.alloc);
12233  NK_ASSERT(atlas->permanent.free);
12234 
12235  if (!atlas || !file_path) return 0;
12236  memory = nk_file_load(file_path, &size, &atlas->permanent);
12237  if (!memory) return 0;
12238 
12239  cfg = (config) ? *config: nk_font_config(height);
12240  cfg.ttf_blob = memory;
12241  cfg.ttf_size = size;
12242  cfg.size = height;
12243  cfg.ttf_data_owned_by_atlas = 1;
12244  return nk_font_atlas_add(atlas, &cfg);
12245 }
12246 #endif
12247 
12248 NK_API struct nk_font*
12249 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas,
12250  void *compressed_data, nk_size compressed_size, float height,
12251  const struct nk_font_config *config)
12252 {
12253  unsigned int decompressed_size;
12254  void *decompressed_data;
12255  struct nk_font_config cfg;
12256 
12257  NK_ASSERT(atlas);
12258  NK_ASSERT(atlas->temporary.alloc);
12259  NK_ASSERT(atlas->temporary.free);
12260  NK_ASSERT(atlas->permanent.alloc);
12261  NK_ASSERT(atlas->permanent.free);
12262 
12263  NK_ASSERT(compressed_data);
12264  NK_ASSERT(compressed_size);
12265  if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free ||
12266  !atlas->permanent.alloc || !atlas->permanent.free)
12267  return 0;
12268 
12269  decompressed_size = nk_decompress_length((unsigned char*)compressed_data);
12270  decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size);
12271  NK_ASSERT(decompressed_data);
12272  if (!decompressed_data) return 0;
12273  nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data,
12274  (unsigned int)compressed_size);
12275 
12276  cfg = (config) ? *config: nk_font_config(height);
12277  cfg.ttf_blob = decompressed_data;
12278  cfg.ttf_size = decompressed_size;
12279  cfg.size = height;
12280  cfg.ttf_data_owned_by_atlas = 1;
12281  return nk_font_atlas_add(atlas, &cfg);
12282 }
12283 
12284 NK_API struct nk_font*
12285 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas,
12286  const char *data_base85, float height, const struct nk_font_config *config)
12287 {
12288  int compressed_size;
12289  void *compressed_data;
12290  struct nk_font *font;
12291 
12292  NK_ASSERT(atlas);
12293  NK_ASSERT(atlas->temporary.alloc);
12294  NK_ASSERT(atlas->temporary.free);
12295  NK_ASSERT(atlas->permanent.alloc);
12296  NK_ASSERT(atlas->permanent.free);
12297 
12298  NK_ASSERT(data_base85);
12299  if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free ||
12300  !atlas->permanent.alloc || !atlas->permanent.free)
12301  return 0;
12302 
12303  compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4;
12304  compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size);
12305  NK_ASSERT(compressed_data);
12306  if (!compressed_data) return 0;
12307  nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85);
12308  font = nk_font_atlas_add_compressed(atlas, compressed_data,
12309  (nk_size)compressed_size, height, config);
12310  atlas->temporary.free(atlas->temporary.userdata, compressed_data);
12311  return font;
12312 }
12313 
12314 #ifdef NK_INCLUDE_DEFAULT_FONT
12315 NK_API struct nk_font*
12316 nk_font_atlas_add_default(struct nk_font_atlas *atlas,
12317  float pixel_height, const struct nk_font_config *config)
12318 {
12319  NK_ASSERT(atlas);
12320  NK_ASSERT(atlas->temporary.alloc);
12321  NK_ASSERT(atlas->temporary.free);
12322  NK_ASSERT(atlas->permanent.alloc);
12323  NK_ASSERT(atlas->permanent.free);
12324  return nk_font_atlas_add_compressed_base85(atlas,
12325  nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config);
12326 }
12327 #endif
12328 
12329 NK_API const void*
12330 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height,
12331  enum nk_font_atlas_format fmt)
12332 {
12333  int i = 0;
12334  void *tmp = 0;
12335  nk_size tmp_size, img_size;
12336  struct nk_font *font_iter;
12337  struct nk_font_baker *baker;
12338 
12339  NK_ASSERT(atlas);
12340  NK_ASSERT(atlas->temporary.alloc);
12341  NK_ASSERT(atlas->temporary.free);
12342  NK_ASSERT(atlas->permanent.alloc);
12343  NK_ASSERT(atlas->permanent.free);
12344 
12345  NK_ASSERT(width);
12346  NK_ASSERT(height);
12347  if (!atlas || !width || !height ||
12348  !atlas->temporary.alloc || !atlas->temporary.free ||
12349  !atlas->permanent.alloc || !atlas->permanent.free)
12350  return 0;
12351 
12352 #ifdef NK_INCLUDE_DEFAULT_FONT
12353  /* no font added so just use default font */
12354  if (!atlas->font_num)
12355  atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0);
12356 #endif
12357  NK_ASSERT(atlas->font_num);
12358  if (!atlas->font_num) return 0;
12359 
12360  /* allocate temporary baker memory required for the baking process */
12361  nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num);
12362  tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size);
12363  NK_ASSERT(tmp);
12364  if (!tmp) goto failed;
12365 
12366  /* allocate glyph memory for all fonts */
12367  baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary);
12368  atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc(
12369  atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count);
12370  NK_ASSERT(atlas->glyphs);
12371  if (!atlas->glyphs)
12372  goto failed;
12373 
12374  /* pack all glyphs into a tight fit space */
12375  atlas->custom.w = (NK_CURSOR_DATA_W*2)+1;
12376  atlas->custom.h = NK_CURSOR_DATA_H + 1;
12377  if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom,
12378  atlas->config, atlas->font_num, &atlas->temporary))
12379  goto failed;
12380 
12381  /* allocate memory for the baked image font atlas */
12382  atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size);
12383  NK_ASSERT(atlas->pixel);
12384  if (!atlas->pixel)
12385  goto failed;
12386 
12387  /* bake glyphs and custom white pixel into image */
12388  nk_font_bake(baker, atlas->pixel, *width, *height,
12389  atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num);
12390  nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom,
12391  nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X');
12392 
12393  if (fmt == NK_FONT_ATLAS_RGBA32) {
12394  /* convert alpha8 image into rgba32 image */
12395  void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0,
12396  (nk_size)(*width * *height * 4));
12397  NK_ASSERT(img_rgba);
12398  if (!img_rgba) goto failed;
12399  nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel);
12400  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12401  atlas->pixel = img_rgba;
12402  }
12403  atlas->tex_width = *width;
12404  atlas->tex_height = *height;
12405 
12406  /* initialize each font */
12407  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
12408  struct nk_font *font = font_iter;
12409  struct nk_font_config *config = font->config;
12410  nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs,
12411  config->font, nk_handle_ptr(0));
12412  }
12413 
12414  /* initialize each cursor */
12415  {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = {
12416  /* Pos ----- Size ------- Offset --*/
12417  {{ 0, 3}, {12,19}, { 0, 0}},
12418  {{13, 0}, { 7,16}, { 4, 8}},
12419  {{31, 0}, {23,23}, {11,11}},
12420  {{21, 0}, { 9, 23}, { 5,11}},
12421  {{55,18}, {23, 9}, {11, 5}},
12422  {{73, 0}, {17,17}, { 9, 9}},
12423  {{55, 0}, {17,17}, { 9, 9}}
12424  };
12425  for (i = 0; i < NK_CURSOR_COUNT; ++i) {
12426  struct nk_cursor *cursor = &atlas->cursors[i];
12427  cursor->img.w = (unsigned short)*width;
12428  cursor->img.h = (unsigned short)*height;
12429  cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x);
12430  cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y);
12431  cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x;
12432  cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y;
12433  cursor->size = nk_cursor_data[i][1];
12434  cursor->offset = nk_cursor_data[i][2];
12435  }}
12436  /* free temporary memory */
12437  atlas->temporary.free(atlas->temporary.userdata, tmp);
12438  return atlas->pixel;
12439 
12440 failed:
12441  /* error so cleanup all memory */
12442  if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp);
12443  if (atlas->glyphs) {
12444  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12445  atlas->glyphs = 0;
12446  }
12447  if (atlas->pixel) {
12448  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12449  atlas->pixel = 0;
12450  }
12451  return 0;
12452 }
12453 
12454 NK_API void
12455 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture,
12456  struct nk_draw_null_texture *null)
12457 {
12458  int i = 0;
12459  struct nk_font *font_iter;
12460  NK_ASSERT(atlas);
12461  if (!atlas) {
12462  if (!null) return;
12463  null->texture = texture;
12464  null->uv = nk_vec2(0.5f,0.5f);
12465  }
12466  if (null) {
12467  null->texture = texture;
12468  null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width;
12469  null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height;
12470  }
12471  for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) {
12472  font_iter->texture = texture;
12473 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
12474  font_iter->handle.texture = texture;
12475 #endif
12476  }
12477  for (i = 0; i < NK_CURSOR_COUNT; ++i)
12478  atlas->cursors[i].img.handle = texture;
12479 
12480  atlas->temporary.free(atlas->temporary.userdata, atlas->pixel);
12481  atlas->pixel = 0;
12482  atlas->tex_width = 0;
12483  atlas->tex_height = 0;
12484  atlas->custom.x = 0;
12485  atlas->custom.y = 0;
12486  atlas->custom.w = 0;
12487  atlas->custom.h = 0;
12488 }
12489 
12490 NK_API void
12491 nk_font_atlas_cleanup(struct nk_font_atlas *atlas)
12492 {
12493  NK_ASSERT(atlas);
12494  NK_ASSERT(atlas->temporary.alloc);
12495  NK_ASSERT(atlas->temporary.free);
12496  NK_ASSERT(atlas->permanent.alloc);
12497  NK_ASSERT(atlas->permanent.free);
12498 
12499  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
12500  if (atlas->config) {
12501  struct nk_font_config *iter, *next;
12502  for (iter = atlas->config; iter; iter = next) {
12503  next = iter->next;
12504  atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob);
12505  atlas->permanent.free(atlas->permanent.userdata, iter);
12506  }
12507  atlas->config = 0;
12508  }
12509 }
12510 
12511 NK_API void
12512 nk_font_atlas_clear(struct nk_font_atlas *atlas)
12513 {
12514  NK_ASSERT(atlas);
12515  NK_ASSERT(atlas->temporary.alloc);
12516  NK_ASSERT(atlas->temporary.free);
12517  NK_ASSERT(atlas->permanent.alloc);
12518  NK_ASSERT(atlas->permanent.free);
12519  if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return;
12520 
12521  nk_font_atlas_cleanup(atlas);
12522  if (atlas->fonts) {
12523  struct nk_font *iter, *next;
12524  for (iter = atlas->fonts; iter; iter = next) {
12525  next = iter->next;
12526  atlas->permanent.free(atlas->permanent.userdata, iter);
12527  }
12528  atlas->fonts = 0;
12529  }
12530  if (atlas->glyphs)
12531  atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs);
12533 }
12534 #endif
12535 /* ==============================================================
12536  *
12537  * INPUT
12538  *
12539  * ===============================================================*/
12540 NK_API void
12541 nk_input_begin(struct nk_context *ctx)
12542 {
12543  int i;
12544  struct nk_input *in;
12545  NK_ASSERT(ctx);
12546  if (!ctx) return;
12547  in = &ctx->input;
12548  for (i = 0; i < NK_BUTTON_MAX; ++i)
12549  in->mouse.buttons[i].clicked = 0;
12550 
12551  in->keyboard.text_len = 0;
12552  in->mouse.scroll_delta = nk_vec2(0,0);
12553  in->mouse.prev.x = in->mouse.pos.x;
12554  in->mouse.prev.y = in->mouse.pos.y;
12555  in->mouse.delta.x = 0;
12556  in->mouse.delta.y = 0;
12557  for (i = 0; i < NK_KEY_MAX; i++)
12558  in->keyboard.keys[i].clicked = 0;
12559 }
12560 
12561 NK_API void
12562 nk_input_end(struct nk_context *ctx)
12563 {
12564  struct nk_input *in;
12565  NK_ASSERT(ctx);
12566  if (!ctx) return;
12567  in = &ctx->input;
12568  if (in->mouse.grab)
12569  in->mouse.grab = 0;
12570  if (in->mouse.ungrab) {
12571  in->mouse.grabbed = 0;
12572  in->mouse.ungrab = 0;
12573  in->mouse.grab = 0;
12574  }
12575 }
12576 
12577 NK_API void
12578 nk_input_motion(struct nk_context *ctx, int x, int y)
12579 {
12580  struct nk_input *in;
12581  NK_ASSERT(ctx);
12582  if (!ctx) return;
12583  in = &ctx->input;
12584  in->mouse.pos.x = (float)x;
12585  in->mouse.pos.y = (float)y;
12586  in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x;
12587  in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y;
12588 }
12589 
12590 NK_API void
12591 nk_input_key(struct nk_context *ctx, enum nk_keys key, int down)
12592 {
12593  struct nk_input *in;
12594  NK_ASSERT(ctx);
12595  if (!ctx) return;
12596  in = &ctx->input;
12597  if (in->keyboard.keys[key].down != down)
12598  in->keyboard.keys[key].clicked++;
12599  in->keyboard.keys[key].down = down;
12600 }
12601 
12602 NK_API void
12603 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down)
12604 {
12605  struct nk_mouse_button *btn;
12606  struct nk_input *in;
12607  NK_ASSERT(ctx);
12608  if (!ctx) return;
12609  in = &ctx->input;
12610  if (in->mouse.buttons[id].down == down) return;
12611 
12612  btn = &in->mouse.buttons[id];
12613  btn->clicked_pos.x = (float)x;
12614  btn->clicked_pos.y = (float)y;
12615  btn->down = down;
12616  btn->clicked++;
12617 }
12618 
12619 NK_API void
12620 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val)
12621 {
12622  NK_ASSERT(ctx);
12623  if (!ctx) return;
12624  ctx->input.mouse.scroll_delta.x += val.x;
12625  ctx->input.mouse.scroll_delta.y += val.y;
12626 }
12627 
12628 NK_API void
12629 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph)
12630 {
12631  int len = 0;
12632  nk_rune unicode;
12633  struct nk_input *in;
12634 
12635  NK_ASSERT(ctx);
12636  if (!ctx) return;
12637  in = &ctx->input;
12638 
12639  len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE);
12640  if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) {
12641  nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len],
12642  NK_INPUT_MAX - in->keyboard.text_len);
12643  in->keyboard.text_len += len;
12644  }
12645 }
12646 
12647 NK_API void
12648 nk_input_char(struct nk_context *ctx, char c)
12649 {
12650  nk_glyph glyph;
12651  NK_ASSERT(ctx);
12652  if (!ctx) return;
12653  glyph[0] = c;
12654  nk_input_glyph(ctx, glyph);
12655 }
12656 
12657 NK_API void
12658 nk_input_unicode(struct nk_context *ctx, nk_rune unicode)
12659 {
12660  nk_glyph rune;
12661  NK_ASSERT(ctx);
12662  if (!ctx) return;
12663  nk_utf_encode(unicode, rune, NK_UTF_SIZE);
12664  nk_input_glyph(ctx, rune);
12665 }
12666 
12667 NK_API int
12668 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id)
12669 {
12670  const struct nk_mouse_button *btn;
12671  if (!i) return nk_false;
12672  btn = &i->mouse.buttons[id];
12673  return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false;
12674 }
12675 
12676 NK_API int
12677 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
12678  struct nk_rect b)
12679 {
12680  const struct nk_mouse_button *btn;
12681  if (!i) return nk_false;
12682  btn = &i->mouse.buttons[id];
12683  if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h))
12684  return nk_false;
12685  return nk_true;
12686 }
12687 
12688 NK_API int
12690  struct nk_rect b, int down)
12691 {
12692  const struct nk_mouse_button *btn;
12693  if (!i) return nk_false;
12694  btn = &i->mouse.buttons[id];
12695  return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down);
12696 }
12697 
12698 NK_API int
12699 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id,
12700  struct nk_rect b)
12701 {
12702  const struct nk_mouse_button *btn;
12703  if (!i) return nk_false;
12704  btn = &i->mouse.buttons[id];
12706  btn->clicked) ? nk_true : nk_false;
12707 }
12708 
12709 NK_API int
12711  struct nk_rect b, int down)
12712 {
12713  const struct nk_mouse_button *btn;
12714  if (!i) return nk_false;
12715  btn = &i->mouse.buttons[id];
12716  return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) &&
12717  btn->clicked) ? nk_true : nk_false;
12718 }
12719 
12720 NK_API int
12721 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b)
12722 {
12723  int i, down = 0;
12724  for (i = 0; i < NK_BUTTON_MAX; ++i)
12726  return down;
12727 }
12728 
12729 NK_API int
12730 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect)
12731 {
12732  if (!i) return nk_false;
12733  return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h);
12734 }
12735 
12736 NK_API int
12737 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect)
12738 {
12739  if (!i) return nk_false;
12740  return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h);
12741 }
12742 
12743 NK_API int
12744 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect)
12745 {
12746  if (!i) return nk_false;
12747  if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false;
12748  return nk_input_is_mouse_click_in_rect(i, id, rect);
12749 }
12750 
12751 NK_API int
12752 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id)
12753 {
12754  if (!i) return nk_false;
12755  return i->mouse.buttons[id].down;
12756 }
12757 
12758 NK_API int
12759 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id)
12760 {
12761  const struct nk_mouse_button *b;
12762  if (!i) return nk_false;
12763  b = &i->mouse.buttons[id];
12764  if (b->down && b->clicked)
12765  return nk_true;
12766  return nk_false;
12767 }
12768 
12769 NK_API int
12770 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id)
12771 {
12772  if (!i) return nk_false;
12773  return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked);
12774 }
12775 
12776 NK_API int
12777 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key)
12778 {
12779  const struct nk_key *k;
12780  if (!i) return nk_false;
12781  k = &i->keyboard.keys[key];
12782  if ((k->down && k->clicked) || (!k->down && k->clicked >= 2))
12783  return nk_true;
12784  return nk_false;
12785 }
12786 
12787 NK_API int
12788 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key)
12789 {
12790  const struct nk_key *k;
12791  if (!i) return nk_false;
12792  k = &i->keyboard.keys[key];
12793  if ((!k->down && k->clicked) || (k->down && k->clicked >= 2))
12794  return nk_true;
12795  return nk_false;
12796 }
12797 
12798 NK_API int
12799 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key)
12800 {
12801  const struct nk_key *k;
12802  if (!i) return nk_false;
12803  k = &i->keyboard.keys[key];
12804  if (k->down) return nk_true;
12805  return nk_false;
12806 }
12807 
12808 /*
12809  * ==============================================================
12810  *
12811  * TEXT EDITOR
12812  *
12813  * ===============================================================
12814  */
12815 /* stb_textedit.h - v1.8 - public domain - Sean Barrett */
12816 struct nk_text_find {
12817  float x,y; /* position of n'th character */
12818  float height; /* height of line */
12819  int first_char, length; /* first char of row, and length */
12820  int prev_first; /*_ first char of previous row */
12821 };
12822 
12823 struct nk_text_edit_row {
12824  float x0,x1;
12825  /* starting x location, end x location (allows for align=right, etc) */
12826  float baseline_y_delta;
12827  /* position of baseline relative to previous row's baseline*/
12828  float ymin,ymax;
12829  /* height of row above and below baseline */
12830  int num_chars;
12831 };
12832 
12833 /* forward declarations */
12834 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int);
12835 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int);
12836 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int);
12837 #define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end)
12838 
12839 NK_INTERN float
12840 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id,
12841  const struct nk_user_font *font)
12842 {
12843  int len = 0;
12844  nk_rune unicode = 0;
12845  const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len);
12846  return font->width(font->userdata, font->height, str, len);
12847 }
12848 
12849 NK_INTERN void
12850 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit,
12851  int line_start_id, float row_height, const struct nk_user_font *font)
12852 {
12853  int l;
12854  int glyphs = 0;
12855  nk_rune unicode;
12856  const char *remaining;
12857  int len = nk_str_len_char(&edit->string);
12858  const char *end = nk_str_get_const(&edit->string) + len;
12859  const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l);
12860  const struct nk_vec2 size = nk_text_calculate_text_bounds(font,
12861  text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE);
12862 
12863  r->x0 = 0.0f;
12864  r->x1 = size.x;
12865  r->baseline_y_delta = size.y;
12866  r->ymin = 0.0f;
12867  r->ymax = size.y;
12868  r->num_chars = glyphs;
12869 }
12870 
12871 NK_INTERN int
12872 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y,
12873  const struct nk_user_font *font, float row_height)
12874 {
12875  struct nk_text_edit_row r;
12876  int n = edit->string.len;
12877  float base_y = 0, prev_x;
12878  int i=0, k;
12879 
12880  r.x0 = r.x1 = 0;
12881  r.ymin = r.ymax = 0;
12882  r.num_chars = 0;
12883 
12884  /* search rows to find one that straddles 'y' */
12885  while (i < n) {
12886  nk_textedit_layout_row(&r, edit, i, row_height, font);
12887  if (r.num_chars <= 0)
12888  return n;
12889 
12890  if (i==0 && y < base_y + r.ymin)
12891  return 0;
12892 
12893  if (y < base_y + r.ymax)
12894  break;
12895 
12896  i += r.num_chars;
12897  base_y += r.baseline_y_delta;
12898  }
12899 
12900  /* below all text, return 'after' last character */
12901  if (i >= n)
12902  return n;
12903 
12904  /* check if it's before the beginning of the line */
12905  if (x < r.x0)
12906  return i;
12907 
12908  /* check if it's before the end of the line */
12909  if (x < r.x1) {
12910  /* search characters in row for one that straddles 'x' */
12911  k = i;
12912  prev_x = r.x0;
12913  for (i=0; i < r.num_chars; ++i) {
12914  float w = nk_textedit_get_width(edit, k, i, font);
12915  if (x < prev_x+w) {
12916  if (x < prev_x+w/2)
12917  return k+i;
12918  else return k+i+1;
12919  }
12920  prev_x += w;
12921  }
12922  /* shouldn't happen, but if it does, fall through to end-of-line case */
12923  }
12924 
12925  /* if the last character is a newline, return that.
12926  * otherwise return 'after' the last character */
12927  if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n')
12928  return i+r.num_chars-1;
12929  else return i+r.num_chars;
12930 }
12931 
12932 NK_INTERN void
12933 nk_textedit_click(struct nk_text_edit *state, float x, float y,
12934  const struct nk_user_font *font, float row_height)
12935 {
12936  /* API click: on mouse down, move the cursor to the clicked location,
12937  * and reset the selection */
12938  state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height);
12939  state->select_start = state->cursor;
12940  state->select_end = state->cursor;
12941  state->has_preferred_x = 0;
12942 }
12943 
12944 NK_INTERN void
12945 nk_textedit_drag(struct nk_text_edit *state, float x, float y,
12946  const struct nk_user_font *font, float row_height)
12947 {
12948  /* API drag: on mouse drag, move the cursor and selection endpoint
12949  * to the clicked location */
12950  int p = nk_textedit_locate_coord(state, x, y, font, row_height);
12951  if (state->select_start == state->select_end)
12952  state->select_start = state->cursor;
12953  state->cursor = state->select_end = p;
12954 }
12955 
12956 NK_INTERN void
12957 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state,
12958  int n, int single_line, const struct nk_user_font *font, float row_height)
12959 {
12960  /* find the x/y location of a character, and remember info about the previous
12961  * row in case we get a move-up event (for page up, we'll have to rescan) */
12962  struct nk_text_edit_row r;
12963  int prev_start = 0;
12964  int z = state->string.len;
12965  int i=0, first;
12966 
12967  nk_zero_struct(r);
12968  if (n == z) {
12969  /* if it's at the end, then find the last line -- simpler than trying to
12970  explicitly handle this case in the regular code */
12971  nk_textedit_layout_row(&r, state, 0, row_height, font);
12972  if (single_line) {
12973  find->first_char = 0;
12974  find->length = z;
12975  } else {
12976  while (i < z) {
12977  prev_start = i;
12978  i += r.num_chars;
12979  nk_textedit_layout_row(&r, state, i, row_height, font);
12980  }
12981 
12982  find->first_char = i;
12983  find->length = r.num_chars;
12984  }
12985  find->x = r.x1;
12986  find->y = r.ymin;
12987  find->height = r.ymax - r.ymin;
12988  find->prev_first = prev_start;
12989  return;
12990  }
12991 
12992  /* search rows to find the one that straddles character n */
12993  find->y = 0;
12994 
12995  for(;;) {
12996  nk_textedit_layout_row(&r, state, i, row_height, font);
12997  if (n < i + r.num_chars) break;
12998  prev_start = i;
12999  i += r.num_chars;
13000  find->y += r.baseline_y_delta;
13001  }
13002 
13003  find->first_char = first = i;
13004  find->length = r.num_chars;
13005  find->height = r.ymax - r.ymin;
13006  find->prev_first = prev_start;
13007 
13008  /* now scan to find xpos */
13009  find->x = r.x0;
13010  for (i=0; first+i < n; ++i)
13011  find->x += nk_textedit_get_width(state, first, i, font);
13012 }
13013 
13014 NK_INTERN void
13015 nk_textedit_clamp(struct nk_text_edit *state)
13016 {
13017  /* make the selection/cursor state valid if client altered the string */
13018  int n = state->string.len;
13019  if (NK_TEXT_HAS_SELECTION(state)) {
13020  if (state->select_start > n) state->select_start = n;
13021  if (state->select_end > n) state->select_end = n;
13022  /* if clamping forced them to be equal, move the cursor to match */
13023  if (state->select_start == state->select_end)
13024  state->cursor = state->select_start;
13025  }
13026  if (state->cursor > n) state->cursor = n;
13027 }
13028 
13029 NK_API void
13030 nk_textedit_delete(struct nk_text_edit *state, int where, int len)
13031 {
13032  /* delete characters while updating undo */
13033  nk_textedit_makeundo_delete(state, where, len);
13034  nk_str_delete_runes(&state->string, where, len);
13035  state->has_preferred_x = 0;
13036 }
13037 
13038 NK_API void
13040 {
13041  /* delete the section */
13042  nk_textedit_clamp(state);
13043  if (NK_TEXT_HAS_SELECTION(state)) {
13044  if (state->select_start < state->select_end) {
13045  nk_textedit_delete(state, state->select_start,
13046  state->select_end - state->select_start);
13047  state->select_end = state->cursor = state->select_start;
13048  } else {
13049  nk_textedit_delete(state, state->select_end,
13050  state->select_start - state->select_end);
13051  state->select_start = state->cursor = state->select_end;
13052  }
13053  state->has_preferred_x = 0;
13054  }
13055 }
13056 
13057 NK_INTERN void
13058 nk_textedit_sortselection(struct nk_text_edit *state)
13059 {
13060  /* canonicalize the selection so start <= end */
13061  if (state->select_end < state->select_start) {
13062  int temp = state->select_end;
13063  state->select_end = state->select_start;
13064  state->select_start = temp;
13065  }
13066 }
13067 
13068 NK_INTERN void
13069 nk_textedit_move_to_first(struct nk_text_edit *state)
13070 {
13071  /* move cursor to first character of selection */
13072  if (NK_TEXT_HAS_SELECTION(state)) {
13073  nk_textedit_sortselection(state);
13074  state->cursor = state->select_start;
13075  state->select_end = state->select_start;
13076  state->has_preferred_x = 0;
13077  }
13078 }
13079 
13080 NK_INTERN void
13081 nk_textedit_move_to_last(struct nk_text_edit *state)
13082 {
13083  /* move cursor to last character of selection */
13084  if (NK_TEXT_HAS_SELECTION(state)) {
13085  nk_textedit_sortselection(state);
13086  nk_textedit_clamp(state);
13087  state->cursor = state->select_end;
13088  state->select_start = state->select_end;
13089  state->has_preferred_x = 0;
13090  }
13091 }
13092 
13093 NK_INTERN int
13094 nk_is_word_boundary( struct nk_text_edit *state, int idx)
13095 {
13096  int len;
13097  nk_rune c;
13098  if (idx <= 0) return 1;
13099  if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1;
13100  return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' ||
13101  c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' ||
13102  c == '|');
13103 }
13104 
13105 NK_INTERN int
13106 nk_textedit_move_to_word_previous(struct nk_text_edit *state)
13107 {
13108  int c = state->cursor - 1;
13109  while( c >= 0 && !nk_is_word_boundary(state, c))
13110  --c;
13111 
13112  if( c < 0 )
13113  c = 0;
13114 
13115  return c;
13116 }
13117 
13118 NK_INTERN int
13119 nk_textedit_move_to_word_next(struct nk_text_edit *state)
13120 {
13121  const int len = state->string.len;
13122  int c = state->cursor+1;
13123  while( c < len && !nk_is_word_boundary(state, c))
13124  ++c;
13125 
13126  if( c > len )
13127  c = len;
13128 
13129  return c;
13130 }
13131 
13132 NK_INTERN void
13133 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state)
13134 {
13135  /* update selection and cursor to match each other */
13136  if (!NK_TEXT_HAS_SELECTION(state))
13137  state->select_start = state->select_end = state->cursor;
13138  else state->cursor = state->select_end;
13139 }
13140 
13141 NK_API int
13143 {
13144  /* API cut: delete selection */
13145  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13146  return 0;
13147  if (NK_TEXT_HAS_SELECTION(state)) {
13148  nk_textedit_delete_selection(state); /* implicitly clamps */
13149  state->has_preferred_x = 0;
13150  return 1;
13151  }
13152  return 0;
13153 }
13154 
13155 NK_API int
13156 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len)
13157 {
13158  /* API paste: replace existing selection with passed-in text */
13159  int glyphs;
13160  const char *text = (const char *) ctext;
13161  if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0;
13162 
13163  /* if there's a selection, the paste should delete it */
13164  nk_textedit_clamp(state);
13166 
13167  /* try to insert the characters */
13168  glyphs = nk_utf_len(ctext, len);
13169  if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) {
13170  nk_textedit_makeundo_insert(state, state->cursor, glyphs);
13171  state->cursor += len;
13172  state->has_preferred_x = 0;
13173  return 1;
13174  }
13175  /* remove the undo since we didn't actually insert the characters */
13176  if (state->undo.undo_point)
13177  --state->undo.undo_point;
13178  return 0;
13179 }
13180 
13181 NK_API void
13182 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len)
13183 {
13184  nk_rune unicode;
13185  int glyph_len;
13186  int text_len = 0;
13187 
13188  NK_ASSERT(state);
13189  NK_ASSERT(text);
13190  if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return;
13191 
13192  glyph_len = nk_utf_decode(text, &unicode, total_len);
13193  while ((text_len < total_len) && glyph_len)
13194  {
13195  /* don't insert a backward delete, just process the event */
13196  if (unicode == 127) goto next;
13197  /* can't add newline in single-line mode */
13198  if (unicode == '\n' && state->single_line) goto next;
13199  /* filter incoming text */
13200  if (state->filter && !state->filter(state, unicode)) goto next;
13201 
13202  if (!NK_TEXT_HAS_SELECTION(state) &&
13203  state->cursor < state->string.len)
13204  {
13205  if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) {
13206  nk_textedit_makeundo_replace(state, state->cursor, 1, 1);
13207  nk_str_delete_runes(&state->string, state->cursor, 1);
13208  }
13209  if (nk_str_insert_text_utf8(&state->string, state->cursor,
13210  text+text_len, 1))
13211  {
13212  ++state->cursor;
13213  state->has_preferred_x = 0;
13214  }
13215  } else {
13216  nk_textedit_delete_selection(state); /* implicitly clamps */
13217  if (nk_str_insert_text_utf8(&state->string, state->cursor,
13218  text+text_len, 1))
13219  {
13220  nk_textedit_makeundo_insert(state, state->cursor, 1);
13221  ++state->cursor;
13222  state->has_preferred_x = 0;
13223  }
13224  }
13225  next:
13226  text_len += glyph_len;
13227  glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len);
13228  }
13229 }
13230 
13231 NK_INTERN void
13232 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod,
13233  const struct nk_user_font *font, float row_height)
13234 {
13235 retry:
13236  switch (key)
13237  {
13238  case NK_KEY_NONE:
13239  case NK_KEY_CTRL:
13240  case NK_KEY_ENTER:
13241  case NK_KEY_SHIFT:
13242  case NK_KEY_TAB:
13243  case NK_KEY_COPY:
13244  case NK_KEY_CUT:
13245  case NK_KEY_PASTE:
13246  case NK_KEY_MAX:
13247  default: break;
13248  case NK_KEY_TEXT_UNDO:
13250  state->has_preferred_x = 0;
13251  break;
13252 
13253  case NK_KEY_TEXT_REDO:
13255  state->has_preferred_x = 0;
13256  break;
13257 
13260  state->has_preferred_x = 0;
13261  break;
13262 
13264  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13266  break;
13268  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13270  break;
13272  if (state->mode == NK_TEXT_EDIT_MODE_INSERT ||
13274  state->mode = NK_TEXT_EDIT_MODE_VIEW;
13275  break;
13276 
13277  case NK_KEY_LEFT:
13278  if (shift_mod) {
13279  nk_textedit_clamp(state);
13280  nk_textedit_prep_selection_at_cursor(state);
13281  /* move selection left */
13282  if (state->select_end > 0)
13283  --state->select_end;
13284  state->cursor = state->select_end;
13285  state->has_preferred_x = 0;
13286  } else {
13287  /* if currently there's a selection,
13288  * move cursor to start of selection */
13289  if (NK_TEXT_HAS_SELECTION(state))
13290  nk_textedit_move_to_first(state);
13291  else if (state->cursor > 0)
13292  --state->cursor;
13293  state->has_preferred_x = 0;
13294  } break;
13295 
13296  case NK_KEY_RIGHT:
13297  if (shift_mod) {
13298  nk_textedit_prep_selection_at_cursor(state);
13299  /* move selection right */
13300  ++state->select_end;
13301  nk_textedit_clamp(state);
13302  state->cursor = state->select_end;
13303  state->has_preferred_x = 0;
13304  } else {
13305  /* if currently there's a selection,
13306  * move cursor to end of selection */
13307  if (NK_TEXT_HAS_SELECTION(state))
13308  nk_textedit_move_to_last(state);
13309  else ++state->cursor;
13310  nk_textedit_clamp(state);
13311  state->has_preferred_x = 0;
13312  } break;
13313 
13314  case NK_KEY_TEXT_WORD_LEFT:
13315  if (shift_mod) {
13316  if( !NK_TEXT_HAS_SELECTION( state ) )
13317  nk_textedit_prep_selection_at_cursor(state);
13318  state->cursor = nk_textedit_move_to_word_previous(state);
13319  state->select_end = state->cursor;
13320  nk_textedit_clamp(state );
13321  } else {
13322  if (NK_TEXT_HAS_SELECTION(state))
13323  nk_textedit_move_to_first(state);
13324  else {
13325  state->cursor = nk_textedit_move_to_word_previous(state);
13326  nk_textedit_clamp(state );
13327  }
13328  } break;
13329 
13331  if (shift_mod) {
13332  if( !NK_TEXT_HAS_SELECTION( state ) )
13333  nk_textedit_prep_selection_at_cursor(state);
13334  state->cursor = nk_textedit_move_to_word_next(state);
13335  state->select_end = state->cursor;
13336  nk_textedit_clamp(state);
13337  } else {
13338  if (NK_TEXT_HAS_SELECTION(state))
13339  nk_textedit_move_to_last(state);
13340  else {
13341  state->cursor = nk_textedit_move_to_word_next(state);
13342  nk_textedit_clamp(state );
13343  }
13344  } break;
13345 
13346  case NK_KEY_DOWN: {
13347  struct nk_text_find find;
13348  struct nk_text_edit_row row;
13349  int i, sel = shift_mod;
13350 
13351  if (state->single_line) {
13352  /* on windows, up&down in single-line behave like left&right */
13353  key = NK_KEY_RIGHT;
13354  goto retry;
13355  }
13356 
13357  if (sel)
13358  nk_textedit_prep_selection_at_cursor(state);
13359  else if (NK_TEXT_HAS_SELECTION(state))
13360  nk_textedit_move_to_last(state);
13361 
13362  /* compute current position of cursor point */
13363  nk_textedit_clamp(state);
13364  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13365  font, row_height);
13366 
13367  /* now find character position down a row */
13368  if (find.length)
13369  {
13370  float x;
13371  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
13372  int start = find.first_char + find.length;
13373 
13374  state->cursor = start;
13375  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
13376  x = row.x0;
13377 
13378  for (i=0; i < row.num_chars && x < row.x1; ++i) {
13379  float dx = nk_textedit_get_width(state, start, i, font);
13380  x += dx;
13381  if (x > goal_x)
13382  break;
13383  ++state->cursor;
13384  }
13385  nk_textedit_clamp(state);
13386 
13387  state->has_preferred_x = 1;
13388  state->preferred_x = goal_x;
13389  if (sel)
13390  state->select_end = state->cursor;
13391  }
13392  } break;
13393 
13394  case NK_KEY_UP: {
13395  struct nk_text_find find;
13396  struct nk_text_edit_row row;
13397  int i, sel = shift_mod;
13398 
13399  if (state->single_line) {
13400  /* on windows, up&down become left&right */
13401  key = NK_KEY_LEFT;
13402  goto retry;
13403  }
13404 
13405  if (sel)
13406  nk_textedit_prep_selection_at_cursor(state);
13407  else if (NK_TEXT_HAS_SELECTION(state))
13408  nk_textedit_move_to_first(state);
13409 
13410  /* compute current position of cursor point */
13411  nk_textedit_clamp(state);
13412  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13413  font, row_height);
13414 
13415  /* can only go up if there's a previous row */
13416  if (find.prev_first != find.first_char) {
13417  /* now find character position up a row */
13418  float x;
13419  float goal_x = state->has_preferred_x ? state->preferred_x : find.x;
13420 
13421  state->cursor = find.prev_first;
13422  nk_textedit_layout_row(&row, state, state->cursor, row_height, font);
13423  x = row.x0;
13424 
13425  for (i=0; i < row.num_chars && x < row.x1; ++i) {
13426  float dx = nk_textedit_get_width(state, find.prev_first, i, font);
13427  x += dx;
13428  if (x > goal_x)
13429  break;
13430  ++state->cursor;
13431  }
13432  nk_textedit_clamp(state);
13433 
13434  state->has_preferred_x = 1;
13435  state->preferred_x = goal_x;
13436  if (sel) state->select_end = state->cursor;
13437  }
13438  } break;
13439 
13440  case NK_KEY_DEL:
13441  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13442  break;
13443  if (NK_TEXT_HAS_SELECTION(state))
13445  else {
13446  int n = state->string.len;
13447  if (state->cursor < n)
13448  nk_textedit_delete(state, state->cursor, 1);
13449  }
13450  state->has_preferred_x = 0;
13451  break;
13452 
13453  case NK_KEY_BACKSPACE:
13454  if (state->mode == NK_TEXT_EDIT_MODE_VIEW)
13455  break;
13456  if (NK_TEXT_HAS_SELECTION(state))
13458  else {
13459  nk_textedit_clamp(state);
13460  if (state->cursor > 0) {
13461  nk_textedit_delete(state, state->cursor-1, 1);
13462  --state->cursor;
13463  }
13464  }
13465  state->has_preferred_x = 0;
13466  break;
13467 
13468  case NK_KEY_TEXT_START:
13469  if (shift_mod) {
13470  nk_textedit_prep_selection_at_cursor(state);
13471  state->cursor = state->select_end = 0;
13472  state->has_preferred_x = 0;
13473  } else {
13474  state->cursor = state->select_start = state->select_end = 0;
13475  state->has_preferred_x = 0;
13476  }
13477  break;
13478 
13479  case NK_KEY_TEXT_END:
13480  if (shift_mod) {
13481  nk_textedit_prep_selection_at_cursor(state);
13482  state->cursor = state->select_end = state->string.len;
13483  state->has_preferred_x = 0;
13484  } else {
13485  state->cursor = state->string.len;
13486  state->select_start = state->select_end = 0;
13487  state->has_preferred_x = 0;
13488  }
13489  break;
13490 
13491  case NK_KEY_TEXT_LINE_START: {
13492  if (shift_mod) {
13493  struct nk_text_find find;
13494  nk_textedit_clamp(state);
13495  nk_textedit_prep_selection_at_cursor(state);
13496  if (state->string.len && state->cursor == state->string.len)
13497  --state->cursor;
13498  nk_textedit_find_charpos(&find, state,state->cursor, state->single_line,
13499  font, row_height);
13500  state->cursor = state->select_end = find.first_char;
13501  state->has_preferred_x = 0;
13502  } else {
13503  struct nk_text_find find;
13504  if (state->string.len && state->cursor == state->string.len)
13505  --state->cursor;
13506  nk_textedit_clamp(state);
13507  nk_textedit_move_to_first(state);
13508  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13509  font, row_height);
13510  state->cursor = find.first_char;
13511  state->has_preferred_x = 0;
13512  }
13513  } break;
13514 
13515  case NK_KEY_TEXT_LINE_END: {
13516  if (shift_mod) {
13517  struct nk_text_find find;
13518  nk_textedit_clamp(state);
13519  nk_textedit_prep_selection_at_cursor(state);
13520  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13521  font, row_height);
13522  state->has_preferred_x = 0;
13523  state->cursor = find.first_char + find.length;
13524  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
13525  --state->cursor;
13526  state->select_end = state->cursor;
13527  } else {
13528  struct nk_text_find find;
13529  nk_textedit_clamp(state);
13530  nk_textedit_move_to_first(state);
13531  nk_textedit_find_charpos(&find, state, state->cursor, state->single_line,
13532  font, row_height);
13533 
13534  state->has_preferred_x = 0;
13535  state->cursor = find.first_char + find.length;
13536  if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n')
13537  --state->cursor;
13538  }} break;
13539  }
13540 }
13541 
13542 NK_INTERN void
13543 nk_textedit_flush_redo(struct nk_text_undo_state *state)
13544 {
13545  state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
13546  state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
13547 }
13548 
13549 NK_INTERN void
13550 nk_textedit_discard_undo(struct nk_text_undo_state *state)
13551 {
13552  /* discard the oldest entry in the undo list */
13553  if (state->undo_point > 0) {
13554  /* if the 0th undo state has characters, clean those up */
13555  if (state->undo_rec[0].char_storage >= 0) {
13556  int n = state->undo_rec[0].insert_length, i;
13557  /* delete n characters from all other records */
13558  state->undo_char_point = (short)(state->undo_char_point - n);
13559  NK_MEMCPY(state->undo_char, state->undo_char + n,
13560  (nk_size)state->undo_char_point*sizeof(nk_rune));
13561  for (i=0; i < state->undo_point; ++i) {
13562  if (state->undo_rec[i].char_storage >= 0)
13563  state->undo_rec[i].char_storage = (short)
13564  (state->undo_rec[i].char_storage - n);
13565  }
13566  }
13567  --state->undo_point;
13568  NK_MEMCPY(state->undo_rec, state->undo_rec+1,
13569  (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0])));
13570  }
13571 }
13572 
13573 NK_INTERN void
13574 nk_textedit_discard_redo(struct nk_text_undo_state *state)
13575 {
13576 /* discard the oldest entry in the redo list--it's bad if this
13577  ever happens, but because undo & redo have to store the actual
13578  characters in different cases, the redo character buffer can
13579  fill up even though the undo buffer didn't */
13580  nk_size num;
13581  int k = NK_TEXTEDIT_UNDOSTATECOUNT-1;
13582  if (state->redo_point <= k) {
13583  /* if the k'th undo state has characters, clean those up */
13584  if (state->undo_rec[k].char_storage >= 0) {
13585  int n = state->undo_rec[k].insert_length, i;
13586  /* delete n characters from all other records */
13587  state->redo_char_point = (short)(state->redo_char_point + n);
13588  num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point);
13589  NK_MEMCPY(state->undo_char + state->redo_char_point,
13590  state->undo_char + state->redo_char_point-n, num * sizeof(char));
13591  for (i = state->redo_point; i < k; ++i) {
13592  if (state->undo_rec[i].char_storage >= 0) {
13593  state->undo_rec[i].char_storage = (short)
13594  (state->undo_rec[i].char_storage + n);
13595  }
13596  }
13597  }
13598  ++state->redo_point;
13599  num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point);
13600  if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1,
13601  state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0]));
13602  }
13603 }
13604 
13606 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars)
13607 {
13608  /* any time we create a new undo record, we discard redo*/
13609  nk_textedit_flush_redo(state);
13610 
13611  /* if we have no free records, we have to make room,
13612  * by sliding the existing records down */
13613  if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
13614  nk_textedit_discard_undo(state);
13615 
13616  /* if the characters to store won't possibly fit in the buffer,
13617  * we can't undo */
13618  if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) {
13619  state->undo_point = 0;
13620  state->undo_char_point = 0;
13621  return 0;
13622  }
13623 
13624  /* if we don't have enough free characters in the buffer,
13625  * we have to make room */
13626  while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT)
13627  nk_textedit_discard_undo(state);
13628  return &state->undo_rec[state->undo_point++];
13629 }
13630 
13632 nk_textedit_createundo(struct nk_text_undo_state *state, int pos,
13633  int insert_len, int delete_len)
13634 {
13635  struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len);
13636  if (r == 0)
13637  return 0;
13638 
13639  r->where = pos;
13640  r->insert_length = (short) insert_len;
13641  r->delete_length = (short) delete_len;
13642 
13643  if (insert_len == 0) {
13644  r->char_storage = -1;
13645  return 0;
13646  } else {
13647  r->char_storage = state->undo_char_point;
13648  state->undo_char_point = (short)(state->undo_char_point + insert_len);
13649  return &state->undo_char[r->char_storage];
13650  }
13651 }
13652 
13653 NK_API void
13655 {
13656  struct nk_text_undo_state *s = &state->undo;
13657  struct nk_text_undo_record u, *r;
13658  if (s->undo_point == 0)
13659  return;
13660 
13661  /* we need to do two things: apply the undo record, and create a redo record */
13662  u = s->undo_rec[s->undo_point-1];
13663  r = &s->undo_rec[s->redo_point-1];
13664  r->char_storage = -1;
13665 
13666  r->insert_length = u.delete_length;
13667  r->delete_length = u.insert_length;
13668  r->where = u.where;
13669 
13670  if (u.delete_length)
13671  {
13672  /* if the undo record says to delete characters, then the redo record will
13673  need to re-insert the characters that get deleted, so we need to store
13674  them.
13675  there are three cases:
13676  - there's enough room to store the characters
13677  - characters stored for *redoing* don't leave room for redo
13678  - characters stored for *undoing* don't leave room for redo
13679  if the last is true, we have to bail */
13680  if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) {
13681  /* the undo records take up too much character space; there's no space
13682  * to store the redo characters */
13683  r->insert_length = 0;
13684  } else {
13685  int i;
13686  /* there's definitely room to store the characters eventually */
13687  while (s->undo_char_point + u.delete_length > s->redo_char_point) {
13688  /* there's currently not enough room, so discard a redo record */
13689  nk_textedit_discard_redo(s);
13690  /* should never happen: */
13691  if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
13692  return;
13693  }
13694 
13695  r = &s->undo_rec[s->redo_point-1];
13696  r->char_storage = (short)(s->redo_char_point - u.delete_length);
13697  s->redo_char_point = (short)(s->redo_char_point - u.delete_length);
13698 
13699  /* now save the characters */
13700  for (i=0; i < u.delete_length; ++i)
13701  s->undo_char[r->char_storage + i] =
13702  nk_str_rune_at(&state->string, u.where + i);
13703  }
13704  /* now we can carry out the deletion */
13705  nk_str_delete_runes(&state->string, u.where, u.delete_length);
13706  }
13707 
13708  /* check type of recorded action: */
13709  if (u.insert_length) {
13710  /* easy case: was a deletion, so we need to insert n characters */
13711  nk_str_insert_text_runes(&state->string, u.where,
13712  &s->undo_char[u.char_storage], u.insert_length);
13713  s->undo_char_point = (short)(s->undo_char_point - u.insert_length);
13714  }
13715  state->cursor = (short)(u.where + u.insert_length);
13716 
13717  s->undo_point--;
13718  s->redo_point--;
13719 }
13720 
13721 NK_API void
13723 {
13724  struct nk_text_undo_state *s = &state->undo;
13725  struct nk_text_undo_record *u, r;
13726  if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT)
13727  return;
13728 
13729  /* we need to do two things: apply the redo record, and create an undo record */
13730  u = &s->undo_rec[s->undo_point];
13731  r = s->undo_rec[s->redo_point];
13732 
13733  /* we KNOW there must be room for the undo record, because the redo record
13734  was derived from an undo record */
13735  u->delete_length = r.insert_length;
13736  u->insert_length = r.delete_length;
13737  u->where = r.where;
13738  u->char_storage = -1;
13739 
13740  if (r.delete_length) {
13741  /* the redo record requires us to delete characters, so the undo record
13742  needs to store the characters */
13743  if (s->undo_char_point + u->insert_length > s->redo_char_point) {
13744  u->insert_length = 0;
13745  u->delete_length = 0;
13746  } else {
13747  int i;
13748  u->char_storage = s->undo_char_point;
13749  s->undo_char_point = (short)(s->undo_char_point + u->insert_length);
13750 
13751  /* now save the characters */
13752  for (i=0; i < u->insert_length; ++i) {
13753  s->undo_char[u->char_storage + i] =
13754  nk_str_rune_at(&state->string, u->where + i);
13755  }
13756  }
13757  nk_str_delete_runes(&state->string, r.where, r.delete_length);
13758  }
13759 
13760  if (r.insert_length) {
13761  /* easy case: need to insert n characters */
13762  nk_str_insert_text_runes(&state->string, r.where,
13763  &s->undo_char[r.char_storage], r.insert_length);
13764  }
13765  state->cursor = r.where + r.insert_length;
13766 
13767  s->undo_point++;
13768  s->redo_point++;
13769 }
13770 
13771 NK_INTERN void
13772 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length)
13773 {
13774  nk_textedit_createundo(&state->undo, where, 0, length);
13775 }
13776 
13777 NK_INTERN void
13778 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length)
13779 {
13780  int i;
13781  nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0);
13782  if (p) {
13783  for (i=0; i < length; ++i)
13784  p[i] = nk_str_rune_at(&state->string, where+i);
13785  }
13786 }
13787 
13788 NK_INTERN void
13789 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where,
13790  int old_length, int new_length)
13791 {
13792  int i;
13793  nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length);
13794  if (p) {
13795  for (i=0; i < old_length; ++i)
13796  p[i] = nk_str_rune_at(&state->string, where+i);
13797  }
13798 }
13799 
13800 NK_INTERN void
13801 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type,
13803 {
13804  /* reset the state to default */
13805  state->undo.undo_point = 0;
13806  state->undo.undo_char_point = 0;
13807  state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT;
13808  state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT;
13809  state->select_end = state->select_start = 0;
13810  state->cursor = 0;
13811  state->has_preferred_x = 0;
13812  state->preferred_x = 0;
13813  state->cursor_at_end_of_line = 0;
13814  state->initialized = 1;
13815  state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE);
13816  state->mode = NK_TEXT_EDIT_MODE_VIEW;
13817  state->filter = filter;
13818  state->scrollbar = nk_vec2(0,0);
13819 }
13820 
13821 NK_API void
13822 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size)
13823 {
13824  NK_ASSERT(state);
13825  NK_ASSERT(memory);
13826  if (!state || !memory || !size) return;
13827  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
13828  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13829  nk_str_init_fixed(&state->string, memory, size);
13830 }
13831 
13832 NK_API void
13834 {
13835  NK_ASSERT(state);
13836  NK_ASSERT(alloc);
13837  if (!state || !alloc) return;
13838  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
13839  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13840  nk_str_init(&state->string, alloc, size);
13841 }
13842 
13843 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
13844 NK_API void
13845 nk_textedit_init_default(struct nk_text_edit *state)
13846 {
13847  NK_ASSERT(state);
13848  if (!state) return;
13849  NK_MEMSET(state, 0, sizeof(struct nk_text_edit));
13850  nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0);
13851  nk_str_init_default(&state->string);
13852 }
13853 #endif
13854 
13855 NK_API void
13857 {
13858  NK_ASSERT(state);
13859  state->select_start = 0;
13860  state->select_end = state->string.len;
13861 }
13862 
13863 NK_API void
13865 {
13866  NK_ASSERT(state);
13867  if (!state) return;
13868  nk_str_free(&state->string);
13869 }
13870 
13871 /* ===============================================================
13872  *
13873  * TEXT WIDGET
13874  *
13875  * ===============================================================*/
13876 #define nk_widget_state_reset(s)\
13877  if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\
13878  (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\
13879  else (*(s)) = NK_WIDGET_STATE_INACTIVE;
13880 
13881 struct nk_text {
13882  struct nk_vec2 padding;
13883  struct nk_color background;
13884  struct nk_color text;
13885 };
13886 
13887 NK_INTERN void
13888 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b,
13889  const char *string, int len, const struct nk_text *t,
13890  nk_flags a, const struct nk_user_font *f)
13891 {
13892  struct nk_rect label;
13893  float text_width;
13894 
13895  NK_ASSERT(o);
13896  NK_ASSERT(t);
13897  if (!o || !t) return;
13898 
13899  b.h = NK_MAX(b.h, 2 * t->padding.y);
13900  label.x = 0; label.w = 0;
13901  label.y = b.y + t->padding.y;
13902  label.h = NK_MIN(f->height, b.h - 2 * t->padding.y);
13903 
13904  text_width = f->width(f->userdata, f->height, (const char*)string, len);
13905  text_width += (2.0f * t->padding.x);
13906 
13907  /* align in x-axis */
13908  if (a & NK_TEXT_ALIGN_LEFT) {
13909  label.x = b.x + t->padding.x;
13910  label.w = NK_MAX(0, b.w - 2 * t->padding.x);
13911  } else if (a & NK_TEXT_ALIGN_CENTERED) {
13912  label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width);
13913  label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2);
13914  label.x = NK_MAX(b.x + t->padding.x, label.x);
13915  label.w = NK_MIN(b.x + b.w, label.x + label.w);
13916  if (label.w >= label.x) label.w -= label.x;
13917  } else if (a & NK_TEXT_ALIGN_RIGHT) {
13918  label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width));
13919  label.w = (float)text_width + 2 * t->padding.x;
13920  } else return;
13921 
13922  /* align in y-axis */
13923  if (a & NK_TEXT_ALIGN_MIDDLE) {
13924  label.y = b.y + b.h/2.0f - (float)f->height/2.0f;
13925  label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f));
13926  } else if (a & NK_TEXT_ALIGN_BOTTOM) {
13927  label.y = b.y + b.h - f->height;
13928  label.h = f->height;
13929  }
13930  nk_draw_text(o, label, (const char*)string,
13931  len, f, t->background, t->text);
13932 }
13933 
13934 NK_INTERN void
13935 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b,
13936  const char *string, int len, const struct nk_text *t,
13937  const struct nk_user_font *f)
13938 {
13939  float width;
13940  int glyphs = 0;
13941  int fitting = 0;
13942  int done = 0;
13943  struct nk_rect line;
13944  struct nk_text text;
13945  NK_INTERN nk_rune seperator[] = {' '};
13946 
13947  NK_ASSERT(o);
13948  NK_ASSERT(t);
13949  if (!o || !t) return;
13950 
13951  text.padding = nk_vec2(0,0);
13952  text.background = t->background;
13953  text.text = t->text;
13954 
13955  b.w = NK_MAX(b.w, 2 * t->padding.x);
13956  b.h = NK_MAX(b.h, 2 * t->padding.y);
13957  b.h = b.h - 2 * t->padding.y;
13958 
13959  line.x = b.x + t->padding.x;
13960  line.y = b.y + t->padding.y;
13961  line.w = b.w - 2 * t->padding.x;
13962  line.h = 2 * t->padding.y + f->height;
13963 
13964  fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
13965  while (done < len) {
13966  if (!fitting || line.y + line.h >= (b.y + b.h)) break;
13967  nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f);
13968  done += fitting;
13969  line.y += f->height + 2 * t->padding.y;
13970  fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator));
13971  }
13972 }
13973 
13974 /* ===============================================================
13975  *
13976  * BUTTON
13977  *
13978  * ===============================================================*/
13979 NK_INTERN void
13980 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type,
13981  struct nk_rect content, struct nk_color background, struct nk_color foreground,
13982  float border_width, const struct nk_user_font *font)
13983 {
13984  switch (type) {
13985  case NK_SYMBOL_X:
13986  case NK_SYMBOL_UNDERSCORE:
13987  case NK_SYMBOL_PLUS:
13988  case NK_SYMBOL_MINUS: {
13989  /* single character text symbol */
13990  const char *X = (type == NK_SYMBOL_X) ? "x":
13991  (type == NK_SYMBOL_UNDERSCORE) ? "_":
13992  (type == NK_SYMBOL_PLUS) ? "+": "-";
13993  struct nk_text text;
13994  text.padding = nk_vec2(0,0);
13995  text.background = background;
13996  text.text = foreground;
13997  nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font);
13998  } break;
14001  case NK_SYMBOL_RECT_SOLID:
14002  case NK_SYMBOL_RECT_OUTLINE: {
14003  /* simple empty/filled shapes */
14005  nk_fill_rect(out, content, 0, foreground);
14007  nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background);
14008  } else {
14009  nk_fill_circle(out, content, foreground);
14011  nk_fill_circle(out, nk_shrink_rect(content, 1), background);
14012  }
14013  } break;
14014  case NK_SYMBOL_TRIANGLE_UP:
14017  case NK_SYMBOL_TRIANGLE_RIGHT: {
14018  enum nk_heading heading;
14019  struct nk_vec2 points[3];
14020  heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT :
14023  nk_triangle_from_direction(points, content, 0, 0, heading);
14024  nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y,
14025  points[2].x, points[2].y, foreground);
14026  } break;
14027  default:
14028  case NK_SYMBOL_NONE:
14029  case NK_SYMBOL_MAX: break;
14030  }
14031 }
14032 
14033 NK_INTERN int
14035  const struct nk_input *i, enum nk_button_behavior behavior)
14036 {
14037  int ret = 0;
14038  nk_widget_state_reset(state);
14039  if (!i) return 0;
14045  ret = (behavior != NK_BUTTON_DEFAULT) ?
14047 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE
14049 #else
14051 #endif
14052  }
14053  }
14058  return ret;
14059 }
14060 
14061 NK_INTERN const struct nk_style_item*
14062 nk_draw_button(struct nk_command_buffer *out,
14063  const struct nk_rect *bounds, nk_flags state,
14064  const struct nk_style_button *style)
14065 {
14066  const struct nk_style_item *background;
14068  background = &style->hover;
14069  else if (state & NK_WIDGET_STATE_ACTIVED)
14070  background = &style->active;
14071  else background = &style->normal;
14072 
14073  if (background->type == NK_STYLE_ITEM_IMAGE) {
14074  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14075  } else {
14076  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14077  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14078  }
14079  return background;
14080 }
14081 
14082 NK_INTERN int
14083 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r,
14084  const struct nk_style_button *style, const struct nk_input *in,
14085  enum nk_button_behavior behavior, struct nk_rect *content)
14086 {
14087  struct nk_rect bounds;
14088  NK_ASSERT(style);
14089  NK_ASSERT(state);
14090  NK_ASSERT(out);
14091  if (!out || !style)
14092  return nk_false;
14093 
14094  /* calculate button content space */
14095  content->x = r.x + style->padding.x + style->border + style->rounding;
14096  content->y = r.y + style->padding.y + style->border + style->rounding;
14097  content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2);
14098  content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2);
14099 
14100  /* execute button behavior */
14101  bounds.x = r.x - style->touch_padding.x;
14102  bounds.y = r.y - style->touch_padding.y;
14103  bounds.w = r.w + 2 * style->touch_padding.x;
14104  bounds.h = r.h + 2 * style->touch_padding.y;
14105  return nk_button_behavior(state, bounds, in, behavior);
14106 }
14107 
14108 NK_INTERN void
14109 nk_draw_button_text(struct nk_command_buffer *out,
14110  const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state,
14111  const struct nk_style_button *style, const char *txt, int len,
14112  nk_flags text_alignment, const struct nk_user_font *font)
14113 {
14114  struct nk_text text;
14115  const struct nk_style_item *background;
14116  background = nk_draw_button(out, bounds, state, style);
14117 
14118  /* select correct colors/images */
14119  if (background->type == NK_STYLE_ITEM_COLOR)
14120  text.background = background->data.color;
14121  else text.background = style->text_background;
14123  text.text = style->text_hover;
14124  else if (state & NK_WIDGET_STATE_ACTIVED)
14125  text.text = style->text_active;
14126  else text.text = style->text_normal;
14127 
14128  text.padding = nk_vec2(0,0);
14129  nk_widget_text(out, *content, txt, len, &text, text_alignment, font);
14130 }
14131 
14132 NK_INTERN int
14133 nk_do_button_text(nk_flags *state,
14134  struct nk_command_buffer *out, struct nk_rect bounds,
14135  const char *string, int len, nk_flags align, enum nk_button_behavior behavior,
14136  const struct nk_style_button *style, const struct nk_input *in,
14137  const struct nk_user_font *font)
14138 {
14139  struct nk_rect content;
14140  int ret = nk_false;
14141 
14142  NK_ASSERT(state);
14143  NK_ASSERT(style);
14144  NK_ASSERT(out);
14145  NK_ASSERT(string);
14146  NK_ASSERT(font);
14147  if (!out || !style || !font || !string)
14148  return nk_false;
14149 
14150  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14151  if (style->draw_begin) style->draw_begin(out, style->userdata);
14152  nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font);
14153  if (style->draw_end) style->draw_end(out, style->userdata);
14154  return ret;
14155 }
14156 
14157 NK_INTERN void
14158 nk_draw_button_symbol(struct nk_command_buffer *out,
14159  const struct nk_rect *bounds, const struct nk_rect *content,
14160  nk_flags state, const struct nk_style_button *style,
14161  enum nk_symbol_type type, const struct nk_user_font *font)
14162 {
14163  struct nk_color sym, bg;
14164  const struct nk_style_item *background;
14165 
14166  /* select correct colors/images */
14167  background = nk_draw_button(out, bounds, state, style);
14168  if (background->type == NK_STYLE_ITEM_COLOR)
14169  bg = background->data.color;
14170  else bg = style->text_background;
14171 
14173  sym = style->text_hover;
14174  else if (state & NK_WIDGET_STATE_ACTIVED)
14175  sym = style->text_active;
14176  else sym = style->text_normal;
14177  nk_draw_symbol(out, type, *content, bg, sym, 1, font);
14178 }
14179 
14180 NK_INTERN int
14181 nk_do_button_symbol(nk_flags *state,
14182  struct nk_command_buffer *out, struct nk_rect bounds,
14183  enum nk_symbol_type symbol, enum nk_button_behavior behavior,
14184  const struct nk_style_button *style, const struct nk_input *in,
14185  const struct nk_user_font *font)
14186 {
14187  int ret;
14188  struct nk_rect content;
14189 
14190  NK_ASSERT(state);
14191  NK_ASSERT(style);
14192  NK_ASSERT(font);
14193  NK_ASSERT(out);
14194  if (!out || !style || !font || !state)
14195  return nk_false;
14196 
14197  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14198  if (style->draw_begin) style->draw_begin(out, style->userdata);
14199  nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font);
14200  if (style->draw_end) style->draw_end(out, style->userdata);
14201  return ret;
14202 }
14203 
14204 NK_INTERN void
14205 nk_draw_button_image(struct nk_command_buffer *out,
14206  const struct nk_rect *bounds, const struct nk_rect *content,
14207  nk_flags state, const struct nk_style_button *style, const struct nk_image *img)
14208 {
14209  nk_draw_button(out, bounds, state, style);
14210  nk_draw_image(out, *content, img, nk_white);
14211 }
14212 
14213 NK_INTERN int
14214 nk_do_button_image(nk_flags *state,
14215  struct nk_command_buffer *out, struct nk_rect bounds,
14216  struct nk_image img, enum nk_button_behavior b,
14217  const struct nk_style_button *style, const struct nk_input *in)
14218 {
14219  int ret;
14220  struct nk_rect content;
14221 
14222  NK_ASSERT(state);
14223  NK_ASSERT(style);
14224  NK_ASSERT(out);
14225  if (!out || !style || !state)
14226  return nk_false;
14227 
14228  ret = nk_do_button(state, out, bounds, style, in, b, &content);
14229  content.x += style->image_padding.x;
14230  content.y += style->image_padding.y;
14231  content.w -= 2 * style->image_padding.x;
14232  content.h -= 2 * style->image_padding.y;
14233 
14234  if (style->draw_begin) style->draw_begin(out, style->userdata);
14235  nk_draw_button_image(out, &bounds, &content, *state, style, &img);
14236  if (style->draw_end) style->draw_end(out, style->userdata);
14237  return ret;
14238 }
14239 
14240 NK_INTERN void
14241 nk_draw_button_text_symbol(struct nk_command_buffer *out,
14242  const struct nk_rect *bounds, const struct nk_rect *label,
14243  const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style,
14244  const char *str, int len, enum nk_symbol_type type,
14245  const struct nk_user_font *font)
14246 {
14247  struct nk_color sym;
14248  struct nk_text text;
14249  const struct nk_style_item *background;
14250 
14251  /* select correct background colors/images */
14252  background = nk_draw_button(out, bounds, state, style);
14253  if (background->type == NK_STYLE_ITEM_COLOR)
14254  text.background = background->data.color;
14255  else text.background = style->text_background;
14256 
14257  /* select correct text colors */
14258  if (state & NK_WIDGET_STATE_HOVER) {
14259  sym = style->text_hover;
14260  text.text = style->text_hover;
14261  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14262  sym = style->text_active;
14263  text.text = style->text_active;
14264  } else {
14265  sym = style->text_normal;
14266  text.text = style->text_normal;
14267  }
14268 
14269  text.padding = nk_vec2(0,0);
14270  nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font);
14271  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
14272 }
14273 
14274 NK_INTERN int
14275 nk_do_button_text_symbol(nk_flags *state,
14276  struct nk_command_buffer *out, struct nk_rect bounds,
14277  enum nk_symbol_type symbol, const char *str, int len, nk_flags align,
14278  enum nk_button_behavior behavior, const struct nk_style_button *style,
14279  const struct nk_user_font *font, const struct nk_input *in)
14280 {
14281  int ret;
14282  struct nk_rect tri = {0,0,0,0};
14283  struct nk_rect content;
14284 
14285  NK_ASSERT(style);
14286  NK_ASSERT(out);
14287  NK_ASSERT(font);
14288  if (!out || !style || !font)
14289  return nk_false;
14290 
14291  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14292  tri.y = content.y + (content.h/2) - font->height/2;
14293  tri.w = font->height; tri.h = font->height;
14295  tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w);
14296  tri.x = NK_MAX(tri.x, 0);
14297  } else tri.x = content.x + 2 * style->padding.x;
14298 
14299  /* draw button */
14300  if (style->draw_begin) style->draw_begin(out, style->userdata);
14301  nk_draw_button_text_symbol(out, &bounds, &content, &tri,
14302  *state, style, str, len, symbol, font);
14303  if (style->draw_end) style->draw_end(out, style->userdata);
14304  return ret;
14305 }
14306 
14307 NK_INTERN void
14308 nk_draw_button_text_image(struct nk_command_buffer *out,
14309  const struct nk_rect *bounds, const struct nk_rect *label,
14310  const struct nk_rect *image, nk_flags state, const struct nk_style_button *style,
14311  const char *str, int len, const struct nk_user_font *font,
14312  const struct nk_image *img)
14313 {
14314  struct nk_text text;
14315  const struct nk_style_item *background;
14316  background = nk_draw_button(out, bounds, state, style);
14317 
14318  /* select correct colors */
14319  if (background->type == NK_STYLE_ITEM_COLOR)
14320  text.background = background->data.color;
14321  else text.background = style->text_background;
14323  text.text = style->text_hover;
14324  else if (state & NK_WIDGET_STATE_ACTIVED)
14325  text.text = style->text_active;
14326  else text.text = style->text_normal;
14327 
14328  text.padding = nk_vec2(0,0);
14329  nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font);
14330  nk_draw_image(out, *image, img, nk_white);
14331 }
14332 
14333 NK_INTERN int
14334 nk_do_button_text_image(nk_flags *state,
14335  struct nk_command_buffer *out, struct nk_rect bounds,
14336  struct nk_image img, const char* str, int len, nk_flags align,
14337  enum nk_button_behavior behavior, const struct nk_style_button *style,
14338  const struct nk_user_font *font, const struct nk_input *in)
14339 {
14340  int ret;
14341  struct nk_rect icon;
14342  struct nk_rect content;
14343 
14344  NK_ASSERT(style);
14345  NK_ASSERT(state);
14346  NK_ASSERT(font);
14347  NK_ASSERT(out);
14348  if (!out || !font || !style || !str)
14349  return nk_false;
14350 
14351  ret = nk_do_button(state, out, bounds, style, in, behavior, &content);
14352  icon.y = bounds.y + style->padding.y;
14353  icon.w = icon.h = bounds.h - 2 * style->padding.y;
14354  if (align & NK_TEXT_ALIGN_LEFT) {
14355  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
14356  icon.x = NK_MAX(icon.x, 0);
14357  } else icon.x = bounds.x + 2 * style->padding.x;
14358 
14359  icon.x += style->image_padding.x;
14360  icon.y += style->image_padding.y;
14361  icon.w -= 2 * style->image_padding.x;
14362  icon.h -= 2 * style->image_padding.y;
14363 
14364  if (style->draw_begin) style->draw_begin(out, style->userdata);
14365  nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img);
14366  if (style->draw_end) style->draw_end(out, style->userdata);
14367  return ret;
14368 }
14369 
14370 /* ===============================================================
14371  *
14372  * TOGGLE
14373  *
14374  * ===============================================================*/
14375 enum nk_toggle_type {
14376  NK_TOGGLE_CHECK,
14377  NK_TOGGLE_OPTION
14378 };
14379 
14380 NK_INTERN int
14381 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select,
14382  nk_flags *state, int active)
14383 {
14384  nk_widget_state_reset(state);
14387  active = !active;
14388  }
14393  return active;
14394 }
14395 
14396 NK_INTERN void
14397 nk_draw_checkbox(struct nk_command_buffer *out,
14398  nk_flags state, const struct nk_style_toggle *style, int active,
14399  const struct nk_rect *label, const struct nk_rect *selector,
14400  const struct nk_rect *cursors, const char *string, int len,
14401  const struct nk_user_font *font)
14402 {
14403  const struct nk_style_item *background;
14404  const struct nk_style_item *cursor;
14405  struct nk_text text;
14406 
14407  /* select correct colors/images */
14408  if (state & NK_WIDGET_STATE_HOVER) {
14409  background = &style->hover;
14410  cursor = &style->cursor_hover;
14411  text.text = style->text_hover;
14412  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14413  background = &style->hover;
14414  cursor = &style->cursor_hover;
14415  text.text = style->text_active;
14416  } else {
14417  background = &style->normal;
14418  cursor = &style->cursor_normal;
14419  text.text = style->text_normal;
14420  }
14421 
14422  /* draw background and cursor */
14423  if (background->type == NK_STYLE_ITEM_COLOR) {
14424  nk_fill_rect(out, *selector, 0, style->border_color);
14425  nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color);
14426  } else nk_draw_image(out, *selector, &background->data.image, nk_white);
14427  if (active) {
14428  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14429  nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
14430  else nk_fill_rect(out, *cursors, 0, cursor->data.color);
14431  }
14432 
14433  text.padding.x = 0;
14434  text.padding.y = 0;
14435  text.background = style->text_background;
14436  nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
14437 }
14438 
14439 NK_INTERN void
14440 nk_draw_option(struct nk_command_buffer *out,
14441  nk_flags state, const struct nk_style_toggle *style, int active,
14442  const struct nk_rect *label, const struct nk_rect *selector,
14443  const struct nk_rect *cursors, const char *string, int len,
14444  const struct nk_user_font *font)
14445 {
14446  const struct nk_style_item *background;
14447  const struct nk_style_item *cursor;
14448  struct nk_text text;
14449 
14450  /* select correct colors/images */
14451  if (state & NK_WIDGET_STATE_HOVER) {
14452  background = &style->hover;
14453  cursor = &style->cursor_hover;
14454  text.text = style->text_hover;
14455  } else if (state & NK_WIDGET_STATE_ACTIVED) {
14456  background = &style->hover;
14457  cursor = &style->cursor_hover;
14458  text.text = style->text_active;
14459  } else {
14460  background = &style->normal;
14461  cursor = &style->cursor_normal;
14462  text.text = style->text_normal;
14463  }
14464 
14465  /* draw background and cursor */
14466  if (background->type == NK_STYLE_ITEM_COLOR) {
14467  nk_fill_circle(out, *selector, style->border_color);
14468  nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color);
14469  } else nk_draw_image(out, *selector, &background->data.image, nk_white);
14470  if (active) {
14471  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14472  nk_draw_image(out, *cursors, &cursor->data.image, nk_white);
14473  else nk_fill_circle(out, *cursors, cursor->data.color);
14474  }
14475 
14476  text.padding.x = 0;
14477  text.padding.y = 0;
14478  text.background = style->text_background;
14479  nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font);
14480 }
14481 
14482 NK_INTERN int
14483 nk_do_toggle(nk_flags *state,
14484  struct nk_command_buffer *out, struct nk_rect r,
14485  int *active, const char *str, int len, enum nk_toggle_type type,
14486  const struct nk_style_toggle *style, const struct nk_input *in,
14487  const struct nk_user_font *font)
14488 {
14489  int was_active;
14490  struct nk_rect bounds;
14491  struct nk_rect select;
14492  struct nk_rect cursor;
14493  struct nk_rect label;
14494 
14495  NK_ASSERT(style);
14496  NK_ASSERT(out);
14497  NK_ASSERT(font);
14498  if (!out || !style || !font || !active)
14499  return 0;
14500 
14501  r.w = NK_MAX(r.w, font->height + 2 * style->padding.x);
14502  r.h = NK_MAX(r.h, font->height + 2 * style->padding.y);
14503 
14504  /* add additional touch padding for touch screen devices */
14505  bounds.x = r.x - style->touch_padding.x;
14506  bounds.y = r.y - style->touch_padding.y;
14507  bounds.w = r.w + 2 * style->touch_padding.x;
14508  bounds.h = r.h + 2 * style->touch_padding.y;
14509 
14510  /* calculate the selector space */
14511  select.w = font->height;
14512  select.h = select.w;
14513  select.y = r.y + r.h/2.0f - select.h/2.0f;
14514  select.x = r.x;
14515 
14516  /* calculate the bounds of the cursor inside the selector */
14517  cursor.x = select.x + style->padding.x + style->border;
14518  cursor.y = select.y + style->padding.y + style->border;
14519  cursor.w = select.w - (2 * style->padding.x + 2 * style->border);
14520  cursor.h = select.h - (2 * style->padding.y + 2 * style->border);
14521 
14522  /* label behind the selector */
14523  label.x = select.x + select.w + style->spacing;
14524  label.y = select.y;
14525  label.w = NK_MAX(r.x + r.w, label.x) - label.x;
14526  label.h = select.w;
14527 
14528  /* update selector */
14529  was_active = *active;
14530  *active = nk_toggle_behavior(in, bounds, state, *active);
14531 
14532  /* draw selector */
14533  if (style->draw_begin)
14534  style->draw_begin(out, style->userdata);
14535  if (type == NK_TOGGLE_CHECK) {
14536  nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font);
14537  } else {
14538  nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font);
14539  }
14540  if (style->draw_end)
14541  style->draw_end(out, style->userdata);
14542  return (was_active != *active);
14543 }
14544 
14545 /* ===============================================================
14546  *
14547  * SELECTABLE
14548  *
14549  * ===============================================================*/
14550 NK_INTERN void
14551 nk_draw_selectable(struct nk_command_buffer *out,
14552  nk_flags state, const struct nk_style_selectable *style, int active,
14553  const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img,
14554  const char *string, int len, nk_flags align, const struct nk_user_font *font)
14555 {
14556  const struct nk_style_item *background;
14557  struct nk_text text;
14558  text.padding = style->padding;
14559 
14560  /* select correct colors/images */
14561  if (!active) {
14563  background = &style->pressed;
14564  text.text = style->text_pressed;
14565  } else if (state & NK_WIDGET_STATE_HOVER) {
14566  background = &style->hover;
14567  text.text = style->text_hover;
14568  } else {
14569  background = &style->normal;
14570  text.text = style->text_normal;
14571  }
14572  } else {
14574  background = &style->pressed_active;
14575  text.text = style->text_pressed_active;
14576  } else if (state & NK_WIDGET_STATE_HOVER) {
14577  background = &style->hover_active;
14578  text.text = style->text_hover_active;
14579  } else {
14580  background = &style->normal_active;
14581  text.text = style->text_normal_active;
14582  }
14583  }
14584 
14585 
14586  /* draw selectable background and text */
14587  if (background->type == NK_STYLE_ITEM_IMAGE) {
14588  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14589  text.background = nk_rgba(0,0,0,0);
14590  } else {
14591  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14592  text.background = background->data.color;
14593  }
14594  if (img && icon) nk_draw_image(out, *icon, img, nk_white);
14595  nk_widget_text(out, *bounds, string, len, &text, align, font);
14596 }
14597 
14598 NK_INTERN int
14599 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out,
14600  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
14601  const struct nk_style_selectable *style, const struct nk_input *in,
14602  const struct nk_user_font *font)
14603 {
14604  int old_value;
14605  struct nk_rect touch;
14606 
14607  NK_ASSERT(state);
14608  NK_ASSERT(out);
14609  NK_ASSERT(str);
14610  NK_ASSERT(len);
14611  NK_ASSERT(value);
14612  NK_ASSERT(style);
14613  NK_ASSERT(font);
14614 
14615  if (!state || !out || !str || !len || !value || !style || !font) return 0;
14616  old_value = *value;
14617 
14618  /* remove padding */
14619  touch.x = bounds.x - style->touch_padding.x;
14620  touch.y = bounds.y - style->touch_padding.y;
14621  touch.w = bounds.w + style->touch_padding.x * 2;
14622  touch.h = bounds.h + style->touch_padding.y * 2;
14623 
14624  /* update button */
14626  *value = !(*value);
14627 
14628  /* draw selectable */
14629  if (style->draw_begin) style->draw_begin(out, style->userdata);
14630  nk_draw_selectable(out, *state, style, *value, &bounds, 0,0, str, len, align, font);
14631  if (style->draw_end) style->draw_end(out, style->userdata);
14632  return old_value != *value;
14633 }
14634 
14635 NK_INTERN int
14636 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out,
14637  struct nk_rect bounds, const char *str, int len, nk_flags align, int *value,
14638  const struct nk_image *img, const struct nk_style_selectable *style,
14639  const struct nk_input *in, const struct nk_user_font *font)
14640 {
14641  int old_value;
14642  struct nk_rect touch;
14643  struct nk_rect icon;
14644 
14645  NK_ASSERT(state);
14646  NK_ASSERT(out);
14647  NK_ASSERT(str);
14648  NK_ASSERT(len);
14649  NK_ASSERT(value);
14650  NK_ASSERT(style);
14651  NK_ASSERT(font);
14652 
14653  if (!state || !out || !str || !len || !value || !style || !font) return 0;
14654  old_value = *value;
14655 
14656  /* toggle behavior */
14657  touch.x = bounds.x - style->touch_padding.x;
14658  touch.y = bounds.y - style->touch_padding.y;
14659  touch.w = bounds.w + style->touch_padding.x * 2;
14660  touch.h = bounds.h + style->touch_padding.y * 2;
14662  *value = !(*value);
14663 
14664  icon.y = bounds.y + style->padding.y;
14665  icon.w = icon.h = bounds.h - 2 * style->padding.y;
14666  if (align & NK_TEXT_ALIGN_LEFT) {
14667  icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w);
14668  icon.x = NK_MAX(icon.x, 0);
14669  } else icon.x = bounds.x + 2 * style->padding.x;
14670 
14671  icon.x += style->image_padding.x;
14672  icon.y += style->image_padding.y;
14673  icon.w -= 2 * style->image_padding.x;
14674  icon.h -= 2 * style->image_padding.y;
14675 
14676  /* draw selectable */
14677  if (style->draw_begin) style->draw_begin(out, style->userdata);
14678  nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, str, len, align, font);
14679  if (style->draw_end) style->draw_end(out, style->userdata);
14680  return old_value != *value;
14681 }
14682 
14683 
14684 /* ===============================================================
14685  *
14686  * SLIDER
14687  *
14688  * ===============================================================*/
14689 NK_INTERN float
14690 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor,
14691  struct nk_rect *visual_cursor, struct nk_input *in,
14692  struct nk_rect bounds, float slider_min, float slider_max, float slider_value,
14693  float slider_step, float slider_steps)
14694 {
14695  int left_mouse_down;
14696  int left_mouse_click_in_cursor;
14697 
14698  /* check if visual cursor is being dragged */
14699  nk_widget_state_reset(state);
14700  left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
14701  left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in,
14702  NK_BUTTON_LEFT, *visual_cursor, nk_true);
14703 
14704  if (left_mouse_down && left_mouse_click_in_cursor)
14705  {
14706  float ratio = 0;
14707  const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f);
14708  const float pxstep = bounds.w / slider_steps;
14709 
14710  /* only update value if the next slider step is reached */
14712  if (NK_ABS(d) >= pxstep) {
14713  const float steps = (float)((int)(NK_ABS(d) / pxstep));
14714  slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps);
14715  slider_value = NK_CLAMP(slider_min, slider_value, slider_max);
14716  ratio = (slider_value - slider_min)/slider_step;
14717  logical_cursor->x = bounds.x + (logical_cursor->w * ratio);
14718  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x;
14719  }
14720  }
14721 
14722  /* slider widget state */
14723  if (nk_input_is_mouse_hovering_rect(in, bounds))
14725  if (*state & NK_WIDGET_STATE_HOVER &&
14728  else if (nk_input_is_mouse_prev_hovering_rect(in, bounds))
14730  return slider_value;
14731 }
14732 
14733 NK_INTERN void
14734 nk_draw_slider(struct nk_command_buffer *out, nk_flags state,
14735  const struct nk_style_slider *style, const struct nk_rect *bounds,
14736  const struct nk_rect *visual_cursor, float min, float value, float max)
14737 {
14738  struct nk_rect fill;
14739  struct nk_rect bar;
14740  const struct nk_style_item *background;
14741 
14742  /* select correct slider images/colors */
14743  struct nk_color bar_color;
14744  const struct nk_style_item *cursor;
14745 
14746  NK_UNUSED(min);
14747  NK_UNUSED(max);
14748  NK_UNUSED(value);
14749 
14751  background = &style->active;
14752  bar_color = style->bar_active;
14753  cursor = &style->cursor_active;
14754  } else if (state & NK_WIDGET_STATE_HOVER) {
14755  background = &style->hover;
14756  bar_color = style->bar_hover;
14757  cursor = &style->cursor_hover;
14758  } else {
14759  background = &style->normal;
14760  bar_color = style->bar_normal;
14761  cursor = &style->cursor_normal;
14762  }
14763 
14764  /* calculate slider background bar */
14765  bar.x = bounds->x;
14766  bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12;
14767  bar.w = bounds->w;
14768  bar.h = bounds->h/6;
14769 
14770  /* filled background bar style */
14771  fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x;
14772  fill.x = bar.x;
14773  fill.y = bar.y;
14774  fill.h = bar.h;
14775 
14776  /* draw background */
14777  if (background->type == NK_STYLE_ITEM_IMAGE) {
14778  nk_draw_image(out, *bounds, &background->data.image, nk_white);
14779  } else {
14780  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14781  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14782  }
14783 
14784  /* draw slider bar */
14785  nk_fill_rect(out, bar, style->rounding, bar_color);
14786  nk_fill_rect(out, fill, style->rounding, style->bar_filled);
14787 
14788  /* draw cursor */
14789  if (cursor->type == NK_STYLE_ITEM_IMAGE)
14790  nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white);
14791  else nk_fill_circle(out, *visual_cursor, cursor->data.color);
14792 }
14793 
14794 NK_INTERN float
14795 nk_do_slider(nk_flags *state,
14796  struct nk_command_buffer *out, struct nk_rect bounds,
14797  float min, float val, float max, float step,
14798  const struct nk_style_slider *style, struct nk_input *in,
14799  const struct nk_user_font *font)
14800 {
14801  float slider_range;
14802  float slider_min;
14803  float slider_max;
14804  float slider_value;
14805  float slider_steps;
14806  float cursor_offset;
14807 
14808  struct nk_rect visual_cursor;
14809  struct nk_rect logical_cursor;
14810 
14811  NK_ASSERT(style);
14812  NK_ASSERT(out);
14813  if (!out || !style)
14814  return 0;
14815 
14816  /* remove padding from slider bounds */
14817  bounds.x = bounds.x + style->padding.x;
14818  bounds.y = bounds.y + style->padding.y;
14819  bounds.h = NK_MAX(bounds.h, 2*style->padding.y);
14820  bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x);
14821  bounds.w -= 2 * style->padding.x;
14822  bounds.h -= 2 * style->padding.y;
14823 
14824  /* optional buttons */
14825  if (style->show_buttons) {
14826  nk_flags ws;
14827  struct nk_rect button;
14828  button.y = bounds.y;
14829  button.w = bounds.h;
14830  button.h = bounds.h;
14831 
14832  /* decrement button */
14833  button.x = bounds.x;
14834  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT,
14835  &style->dec_button, in, font))
14836  val -= step;
14837 
14838  /* increment button */
14839  button.x = (bounds.x + bounds.w) - button.w;
14840  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT,
14841  &style->inc_button, in, font))
14842  val += step;
14843 
14844  bounds.x = bounds.x + button.w + style->spacing.x;
14845  bounds.w = bounds.w - (2*button.w + 2*style->spacing.x);
14846  }
14847 
14848  /* remove one cursor size to support visual cursor */
14849  bounds.x += style->cursor_size.x*0.5f;
14850  bounds.w -= style->cursor_size.x;
14851 
14852  /* make sure the provided values are correct */
14853  slider_max = NK_MAX(min, max);
14854  slider_min = NK_MIN(min, max);
14855  slider_value = NK_CLAMP(slider_min, val, slider_max);
14856  slider_range = slider_max - slider_min;
14857  slider_steps = slider_range / step;
14858  cursor_offset = (slider_value - slider_min) / step;
14859 
14860  /* calculate cursor
14861  Basically you have two cursors. One for visual representation and interaction
14862  and one for updating the actual cursor value. */
14863  logical_cursor.h = bounds.h;
14864  logical_cursor.w = bounds.w / slider_steps;
14865  logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset);
14866  logical_cursor.y = bounds.y;
14867 
14868  visual_cursor.h = style->cursor_size.y;
14869  visual_cursor.w = style->cursor_size.x;
14870  visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f;
14871  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
14872 
14873  slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor,
14874  in, bounds, slider_min, slider_max, slider_value, step, slider_steps);
14875  visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f;
14876 
14877  /* draw slider */
14878  if (style->draw_begin) style->draw_begin(out, style->userdata);
14879  nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max);
14880  if (style->draw_end) style->draw_end(out, style->userdata);
14881  return slider_value;
14882 }
14883 
14884 /* ===============================================================
14885  *
14886  * PROGRESSBAR
14887  *
14888  * ===============================================================*/
14890 nk_progress_behavior(nk_flags *state, const struct nk_input *in,
14891  struct nk_rect r, nk_size max, nk_size value, int modifiable)
14892 {
14893  nk_widget_state_reset(state);
14894  if (in && modifiable && nk_input_is_mouse_hovering_rect(in, r)) {
14895  int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
14896  int left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
14898 
14899  if (left_mouse_down && left_mouse_click_in_cursor) {
14900  float ratio = NK_MAX(0, (float)(in->mouse.pos.x - r.x)) / (float)r.w;
14901  value = (nk_size)NK_MAX(0,((float)max * ratio));
14903  } else *state = NK_WIDGET_STATE_HOVERED;
14904  }
14905 
14906  /* set progressbar widget state */
14911 
14912  if (!max) return value;
14913  value = NK_MIN(value, max);
14914  return value;
14915 }
14916 
14917 NK_INTERN void
14918 nk_draw_progress(struct nk_command_buffer *out, nk_flags state,
14919  const struct nk_style_progress *style, const struct nk_rect *bounds,
14920  const struct nk_rect *scursor, nk_size value, nk_size max)
14921 {
14922  const struct nk_style_item *background;
14923  const struct nk_style_item *cursor;
14924 
14925  NK_UNUSED(max);
14926  NK_UNUSED(value);
14927 
14928  /* select correct colors/images to draw */
14930  background = &style->active;
14931  cursor = &style->cursor_active;
14932  } else if (state & NK_WIDGET_STATE_HOVER){
14933  background = &style->hover;
14934  cursor = &style->cursor_hover;
14935  } else {
14936  background = &style->normal;
14937  cursor = &style->cursor_normal;
14938  }
14939 
14940  /* draw background */
14941  if (background->type == NK_STYLE_ITEM_COLOR) {
14942  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
14943  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
14944  } else nk_draw_image(out, *bounds, &background->data.image, nk_white);
14945 
14946  /* draw cursor */
14947  if (cursor->type == NK_STYLE_ITEM_COLOR) {
14948  nk_fill_rect(out, *scursor, style->rounding, cursor->data.color);
14949  nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color);
14950  } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white);
14951 }
14952 
14954 nk_do_progress(nk_flags *state,
14955  struct nk_command_buffer *out, struct nk_rect bounds,
14956  nk_size value, nk_size max, int modifiable,
14957  const struct nk_style_progress *style, const struct nk_input *in)
14958 {
14959  float prog_scale;
14960  nk_size prog_value;
14961  struct nk_rect cursor;
14962 
14963  NK_ASSERT(style);
14964  NK_ASSERT(out);
14965  if (!out || !style) return 0;
14966 
14967  /* calculate progressbar cursor */
14968  cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border);
14969  cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border);
14970  cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border));
14971  prog_scale = (float)value / (float)max;
14972  cursor.w = (bounds.w - 2) * prog_scale;
14973 
14974  /* update progressbar */
14975  prog_value = NK_MIN(value, max);
14976  prog_value = nk_progress_behavior(state, in, bounds, max, prog_value, modifiable);
14977 
14978  /* draw progressbar */
14979  if (style->draw_begin) style->draw_begin(out, style->userdata);
14980  nk_draw_progress(out, *state, style, &bounds, &cursor, value, max);
14981  if (style->draw_end) style->draw_end(out, style->userdata);
14982  return prog_value;
14983 }
14984 
14985 /* ===============================================================
14986  *
14987  * SCROLLBAR
14988  *
14989  * ===============================================================*/
14990 NK_INTERN float
14991 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in,
14992  int has_scrolling, const struct nk_rect *scroll,
14993  const struct nk_rect *cursor, const struct nk_rect *empty0,
14994  const struct nk_rect *empty1, float scroll_offset,
14995  float target, float scroll_step, enum nk_orientation o)
14996 {
14997  nk_flags ws = 0;
14998  int left_mouse_down;
14999  int left_mouse_click_in_cursor;
15000  float scroll_delta;
15001 
15002  nk_widget_state_reset(state);
15003  if (!in) return scroll_offset;
15004 
15005  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
15006  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
15007  NK_BUTTON_LEFT, *cursor, nk_true);
15008  if (nk_input_is_mouse_hovering_rect(in, *scroll))
15010 
15011  scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x;
15012  if (left_mouse_down && left_mouse_click_in_cursor) {
15013  /* update cursor by mouse dragging */
15014  float pixel, delta;
15016  if (o == NK_VERTICAL) {
15017  float cursor_y;
15018  pixel = in->mouse.delta.y;
15019  delta = (pixel / scroll->h) * target;
15020  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h);
15021  cursor_y = scroll->y + ((scroll_offset/target) * scroll->h);
15022  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f;
15023  } else {
15024  float cursor_x;
15025  pixel = in->mouse.delta.x;
15026  delta = (pixel / scroll->w) * target;
15027  scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w);
15028  cursor_x = scroll->x + ((scroll_offset/target) * scroll->w);
15029  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f;
15030  }
15031  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)||
15032  nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) {
15033  /* scroll page up by click on empty space or shortcut */
15034  if (o == NK_VERTICAL)
15035  scroll_offset = NK_MAX(0, scroll_offset - scroll->h);
15036  else scroll_offset = NK_MAX(0, scroll_offset - scroll->w);
15037  } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) ||
15038  nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) {
15039  /* scroll page down by click on empty space or shortcut */
15040  if (o == NK_VERTICAL)
15041  scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h);
15042  else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w);
15043  } else if (has_scrolling) {
15044  if ((scroll_delta < 0 || (scroll_delta > 0))) {
15045  /* update cursor by mouse scrolling */
15046  scroll_offset = scroll_offset + scroll_step * (-scroll_delta);
15047  if (o == NK_VERTICAL)
15048  scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h);
15049  else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w);
15051  /* update cursor to the beginning */
15052  if (o == NK_VERTICAL) scroll_offset = 0;
15054  /* update cursor to the end */
15055  if (o == NK_VERTICAL) scroll_offset = target - scroll->h;
15056  }
15057  }
15060  else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll))
15062  return scroll_offset;
15063 }
15064 
15065 NK_INTERN void
15066 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state,
15067  const struct nk_style_scrollbar *style, const struct nk_rect *bounds,
15068  const struct nk_rect *scroll)
15069 {
15070  const struct nk_style_item *background;
15071  const struct nk_style_item *cursor;
15072 
15073  /* select correct colors/images to draw */
15075  background = &style->active;
15076  cursor = &style->cursor_active;
15077  } else if (state & NK_WIDGET_STATE_HOVER) {
15078  background = &style->hover;
15079  cursor = &style->cursor_hover;
15080  } else {
15081  background = &style->normal;
15082  cursor = &style->cursor_normal;
15083  }
15084 
15085  /* draw background */
15086  if (background->type == NK_STYLE_ITEM_COLOR) {
15087  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
15088  nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color);
15089  } else {
15090  nk_draw_image(out, *bounds, &background->data.image, nk_white);
15091  }
15092 
15093  /* draw cursor */
15094  if (background->type == NK_STYLE_ITEM_COLOR) {
15095  nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color);
15096  nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color);
15097  } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white);
15098 }
15099 
15100 NK_INTERN float
15101 nk_do_scrollbarv(nk_flags *state,
15102  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
15103  float offset, float target, float step, float button_pixel_inc,
15104  const struct nk_style_scrollbar *style, struct nk_input *in,
15105  const struct nk_user_font *font)
15106 {
15107  struct nk_rect empty_north;
15108  struct nk_rect empty_south;
15109  struct nk_rect cursor;
15110 
15111  float scroll_step;
15112  float scroll_offset;
15113  float scroll_off;
15114  float scroll_ratio;
15115 
15116  NK_ASSERT(out);
15117  NK_ASSERT(style);
15118  NK_ASSERT(state);
15119  if (!out || !style) return 0;
15120 
15121  scroll.w = NK_MAX(scroll.w, 1);
15122  scroll.h = NK_MAX(scroll.h, 0);
15123  if (target <= scroll.h) return 0;
15124 
15125  /* optional scrollbar buttons */
15126  if (style->show_buttons) {
15127  nk_flags ws;
15128  float scroll_h;
15129  struct nk_rect button;
15130 
15131  button.x = scroll.x;
15132  button.w = scroll.w;
15133  button.h = scroll.w;
15134 
15135  scroll_h = NK_MAX(scroll.h - 2 * button.h,0);
15136  scroll_step = NK_MIN(step, button_pixel_inc);
15137 
15138  /* decrement button */
15139  button.y = scroll.y;
15140  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
15141  NK_BUTTON_REPEATER, &style->dec_button, in, font))
15142  offset = offset - scroll_step;
15143 
15144  /* increment button */
15145  button.y = scroll.y + scroll.h - button.h;
15146  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
15147  NK_BUTTON_REPEATER, &style->inc_button, in, font))
15148  offset = offset + scroll_step;
15149 
15150  scroll.y = scroll.y + button.h;
15151  scroll.h = scroll_h;
15152  }
15153 
15154  /* calculate scrollbar constants */
15155  scroll_step = NK_MIN(step, scroll.h);
15156  scroll_offset = NK_CLAMP(0, offset, target - scroll.h);
15157  scroll_ratio = scroll.h / target;
15158  scroll_off = scroll_offset / target;
15159 
15160  /* calculate scrollbar cursor bounds */
15161  cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0);
15162  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y;
15163  cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x);
15164  cursor.x = scroll.x + style->border + style->padding.x;
15165 
15166  /* calculate empty space around cursor */
15167  empty_north.x = scroll.x;
15168  empty_north.y = scroll.y;
15169  empty_north.w = scroll.w;
15170  empty_north.h = NK_MAX(cursor.y - scroll.y, 0);
15171 
15172  empty_south.x = scroll.x;
15173  empty_south.y = cursor.y + cursor.h;
15174  empty_south.w = scroll.w;
15175  empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0);
15176 
15177  /* update scrollbar */
15178  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
15179  &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL);
15180  scroll_off = scroll_offset / target;
15181  cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y;
15182 
15183  /* draw scrollbar */
15184  if (style->draw_begin) style->draw_begin(out, style->userdata);
15185  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
15186  if (style->draw_end) style->draw_end(out, style->userdata);
15187  return scroll_offset;
15188 }
15189 
15190 NK_INTERN float
15191 nk_do_scrollbarh(nk_flags *state,
15192  struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling,
15193  float offset, float target, float step, float button_pixel_inc,
15194  const struct nk_style_scrollbar *style, struct nk_input *in,
15195  const struct nk_user_font *font)
15196 {
15197  struct nk_rect cursor;
15198  struct nk_rect empty_west;
15199  struct nk_rect empty_east;
15200 
15201  float scroll_step;
15202  float scroll_offset;
15203  float scroll_off;
15204  float scroll_ratio;
15205 
15206  NK_ASSERT(out);
15207  NK_ASSERT(style);
15208  if (!out || !style) return 0;
15209 
15210  /* scrollbar background */
15211  scroll.h = NK_MAX(scroll.h, 1);
15212  scroll.w = NK_MAX(scroll.w, 2 * scroll.h);
15213  if (target <= scroll.w) return 0;
15214 
15215  /* optional scrollbar buttons */
15216  if (style->show_buttons) {
15217  nk_flags ws;
15218  float scroll_w;
15219  struct nk_rect button;
15220  button.y = scroll.y;
15221  button.w = scroll.h;
15222  button.h = scroll.h;
15223 
15224  scroll_w = scroll.w - 2 * button.w;
15225  scroll_step = NK_MIN(step, button_pixel_inc);
15226 
15227  /* decrement button */
15228  button.x = scroll.x;
15229  if (nk_do_button_symbol(&ws, out, button, style->dec_symbol,
15230  NK_BUTTON_REPEATER, &style->dec_button, in, font))
15231  offset = offset - scroll_step;
15232 
15233  /* increment button */
15234  button.x = scroll.x + scroll.w - button.w;
15235  if (nk_do_button_symbol(&ws, out, button, style->inc_symbol,
15236  NK_BUTTON_REPEATER, &style->inc_button, in, font))
15237  offset = offset + scroll_step;
15238 
15239  scroll.x = scroll.x + button.w;
15240  scroll.w = scroll_w;
15241  }
15242 
15243  /* calculate scrollbar constants */
15244  scroll_step = NK_MIN(step, scroll.w);
15245  scroll_offset = NK_CLAMP(0, offset, target - scroll.w);
15246  scroll_ratio = scroll.w / target;
15247  scroll_off = scroll_offset / target;
15248 
15249  /* calculate cursor bounds */
15250  cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x);
15251  cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x;
15252  cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y);
15253  cursor.y = scroll.y + style->border + style->padding.y;
15254 
15255  /* calculate empty space around cursor */
15256  empty_west.x = scroll.x;
15257  empty_west.y = scroll.y;
15258  empty_west.w = cursor.x - scroll.x;
15259  empty_west.h = scroll.h;
15260 
15261  empty_east.x = cursor.x + cursor.w;
15262  empty_east.y = scroll.y;
15263  empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w);
15264  empty_east.h = scroll.h;
15265 
15266  /* update scrollbar */
15267  scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor,
15268  &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL);
15269  scroll_off = scroll_offset / target;
15270  cursor.x = scroll.x + (scroll_off * scroll.w);
15271 
15272  /* draw scrollbar */
15273  if (style->draw_begin) style->draw_begin(out, style->userdata);
15274  nk_draw_scrollbar(out, *state, style, &scroll, &cursor);
15275  if (style->draw_end) style->draw_end(out, style->userdata);
15276  return scroll_offset;
15277 }
15278 
15279 /* ===============================================================
15280  *
15281  * FILTER
15282  *
15283  * ===============================================================*/
15284 NK_API int nk_filter_default(const struct nk_text_edit *box, nk_rune unicode)
15285 {(void)unicode;NK_UNUSED(box);return nk_true;}
15286 
15287 NK_API int
15288 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode)
15289 {
15290  NK_UNUSED(box);
15291  if (unicode > 128) return nk_false;
15292  else return nk_true;
15293 }
15294 
15295 NK_API int
15296 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode)
15297 {
15298  NK_UNUSED(box);
15299  if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-')
15300  return nk_false;
15301  else return nk_true;
15302 }
15303 
15304 NK_API int
15305 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode)
15306 {
15307  NK_UNUSED(box);
15308  if ((unicode < '0' || unicode > '9') && unicode != '-')
15309  return nk_false;
15310  else return nk_true;
15311 }
15312 
15313 NK_API int
15314 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode)
15315 {
15316  NK_UNUSED(box);
15317  if ((unicode < '0' || unicode > '9') &&
15318  (unicode < 'a' || unicode > 'f') &&
15319  (unicode < 'A' || unicode > 'F'))
15320  return nk_false;
15321  else return nk_true;
15322 }
15323 
15324 NK_API int
15325 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode)
15326 {
15327  NK_UNUSED(box);
15328  if (unicode < '0' || unicode > '7')
15329  return nk_false;
15330  else return nk_true;
15331 }
15332 
15333 NK_API int
15334 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode)
15335 {
15336  NK_UNUSED(box);
15337  if (unicode != '0' && unicode != '1')
15338  return nk_false;
15339  else return nk_true;
15340 }
15341 
15342 /* ===============================================================
15343  *
15344  * EDIT
15345  *
15346  * ===============================================================*/
15347 NK_INTERN void
15348 nk_edit_draw_text(struct nk_command_buffer *out,
15349  const struct nk_style_edit *style, float pos_x, float pos_y,
15350  float x_offset, const char *text, int byte_len, float row_height,
15351  const struct nk_user_font *font, struct nk_color background,
15352  struct nk_color foreground, int is_selected)
15353 {
15354  NK_ASSERT(out);
15355  NK_ASSERT(font);
15356  NK_ASSERT(style);
15357  if (!text || !byte_len || !out || !style) return;
15358 
15359  {int glyph_len = 0;
15360  nk_rune unicode = 0;
15361  int text_len = 0;
15362  float line_width = 0;
15363  float glyph_width;
15364  const char *line = text;
15365  float line_offset = 0;
15366  int line_count = 0;
15367 
15368  struct nk_text txt;
15369  txt.padding = nk_vec2(0,0);
15370  txt.background = background;
15371  txt.text = foreground;
15372 
15373  glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len);
15374  if (!glyph_len) return;
15375  while ((text_len < byte_len) && glyph_len)
15376  {
15377  if (unicode == '\n') {
15378  /* new line separator so draw previous line */
15379  struct nk_rect label;
15380  label.y = pos_y + line_offset;
15381  label.h = row_height;
15382  label.w = line_width;
15383  label.x = pos_x;
15384  if (!line_count)
15385  label.x += x_offset;
15386 
15387  if (is_selected) /* selection needs to draw different background color */
15388  nk_fill_rect(out, label, 0, background);
15389  nk_widget_text(out, label, line, (int)((text + text_len) - line),
15390  &txt, NK_TEXT_CENTERED, font);
15391 
15392  text_len++;
15393  line_count++;
15394  line_width = 0;
15395  line = text + text_len;
15396  line_offset += row_height;
15397  glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len));
15398  continue;
15399  }
15400  if (unicode == '\r') {
15401  text_len++;
15402  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
15403  continue;
15404  }
15405  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
15406  line_width += (float)glyph_width;
15407  text_len += glyph_len;
15408  glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len);
15409  continue;
15410  }
15411  if (line_width > 0) {
15412  /* draw last line */
15413  struct nk_rect label;
15414  label.y = pos_y + line_offset;
15415  label.h = row_height;
15416  label.w = line_width;
15417  label.x = pos_x;
15418  if (!line_count)
15419  label.x += x_offset;
15420 
15421  if (is_selected)
15422  nk_fill_rect(out, label, 0, background);
15423  nk_widget_text(out, label, line, (int)((text + text_len) - line),
15424  &txt, NK_TEXT_LEFT, font);
15425  }}
15426 }
15427 
15429 nk_do_edit(nk_flags *state, struct nk_command_buffer *out,
15430  struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter,
15431  struct nk_text_edit *edit, const struct nk_style_edit *style,
15432  struct nk_input *in, const struct nk_user_font *font)
15433 {
15434  struct nk_rect area;
15435  nk_flags ret = 0;
15436  float row_height;
15437  char prev_state = 0;
15438  char is_hovered = 0;
15439  char select_all = 0;
15440  char cursor_follow = 0;
15441  struct nk_rect old_clip;
15442  struct nk_rect clip;
15443 
15444  NK_ASSERT(state);
15445  NK_ASSERT(out);
15446  NK_ASSERT(style);
15447  if (!state || !out || !style)
15448  return ret;
15449 
15450  /* visible text area calculation */
15451  area.x = bounds.x + style->padding.x + style->border;
15452  area.y = bounds.y + style->padding.y + style->border;
15453  area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border);
15454  area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border);
15455  if (flags & NK_EDIT_MULTILINE)
15456  area.w = NK_MAX(0, area.w - style->scrollbar_size.x);
15457  row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h;
15458 
15459  /* calculate clipping rectangle */
15460  old_clip = out->clip;
15461  nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h);
15462 
15463  /* update edit state */
15464  prev_state = (char)edit->active;
15465  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds);
15466  if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) {
15467  edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y,
15468  bounds.x, bounds.y, bounds.w, bounds.h);
15469  }
15470 
15471  /* (de)activate text editor */
15472  if (!prev_state && edit->active) {
15473  const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ?
15475  nk_textedit_clear_state(edit, type, filter);
15478  if (flags & NK_EDIT_AUTO_SELECT)
15479  select_all = nk_true;
15481  edit->cursor = edit->string.len;
15482  in = 0;
15483  }
15484  } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW;
15485  if (flags & NK_EDIT_READ_ONLY)
15486  edit->mode = NK_TEXT_EDIT_MODE_VIEW;
15487 
15488  ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE;
15489  if (prev_state != edit->active)
15490  ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED;
15491 
15492  /* handle user input */
15493  if (edit->active && in)
15494  {
15495  int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down;
15496  const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x;
15497  const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y;
15498 
15499  /* mouse click handler */
15500  is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area);
15501  if (select_all) {
15502  nk_textedit_select_all(edit);
15503  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
15504  in->mouse.buttons[NK_BUTTON_LEFT].clicked) {
15505  nk_textedit_click(edit, mouse_x, mouse_y, font, row_height);
15506  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down &&
15507  (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) {
15508  nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height);
15509  cursor_follow = nk_true;
15510  } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked &&
15511  in->mouse.buttons[NK_BUTTON_RIGHT].down) {
15512  nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height);
15513  nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height);
15514  cursor_follow = nk_true;
15515  }
15516 
15517  {int i; /* keyboard input */
15518  int old_mode = edit->mode;
15519  for (i = 0; i < NK_KEY_MAX; ++i) {
15520  if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */
15521  if (nk_input_is_key_pressed(in, (enum nk_keys)i)) {
15522  nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height);
15523  cursor_follow = nk_true;
15524  }
15525  }
15526  if (old_mode != edit->mode) {
15527  in->keyboard.text_len = 0;
15528  }}
15529 
15530  /* text input */
15531  edit->filter = filter;
15532  if (in->keyboard.text_len) {
15533  nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len);
15534  cursor_follow = nk_true;
15535  in->keyboard.text_len = 0;
15536  }
15537 
15538  /* enter key handler */
15540  cursor_follow = nk_true;
15541  if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod)
15542  nk_textedit_text(edit, "\n", 1);
15543  else if (flags & NK_EDIT_SIG_ENTER)
15544  ret |= NK_EDIT_COMMITED;
15545  else nk_textedit_text(edit, "\n", 1);
15546  }
15547 
15548  /* cut & copy handler */
15549  {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY);
15551  if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD))
15552  {
15553  int glyph_len;
15554  nk_rune unicode;
15555  const char *text;
15556  int b = edit->select_start;
15557  int e = edit->select_end;
15558 
15559  int begin = NK_MIN(b, e);
15560  int end = NK_MAX(b, e);
15561  text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len);
15562  if (edit->clip.copy)
15563  edit->clip.copy(edit->clip.userdata, text, end - begin);
15564  if (cut && !(flags & NK_EDIT_READ_ONLY)){
15565  nk_textedit_cut(edit);
15566  cursor_follow = nk_true;
15567  }
15568  }}
15569 
15570  /* paste handler */
15571  {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE);
15572  if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) {
15573  edit->clip.paste(edit->clip.userdata, edit);
15574  cursor_follow = nk_true;
15575  }}
15576 
15577  /* tab handler */
15578  {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB);
15579  if (tab && (flags & NK_EDIT_ALLOW_TAB)) {
15580  nk_textedit_text(edit, " ", 4);
15581  cursor_follow = nk_true;
15582  }}
15583  }
15584 
15585  /* set widget state */
15586  if (edit->active)
15588  else nk_widget_state_reset(state);
15589 
15590  if (is_hovered)
15592 
15593  /* DRAW EDIT */
15594  {const char *text = nk_str_get_const(&edit->string);
15595  int len = nk_str_len_char(&edit->string);
15596 
15597  {/* select background colors/images */
15598  const struct nk_style_item *background;
15600  background = &style->active;
15601  else if (*state & NK_WIDGET_STATE_HOVER)
15602  background = &style->hover;
15603  else background = &style->normal;
15604 
15605  /* draw background frame */
15606  if (background->type == NK_STYLE_ITEM_COLOR) {
15607  nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color);
15608  nk_fill_rect(out, bounds, style->rounding, background->data.color);
15609  } else nk_draw_image(out, bounds, &background->data.image, nk_white);}
15610 
15611  area.w = NK_MAX(0, area.w - style->cursor_size);
15612  if (edit->active)
15613  {
15614  int total_lines = 1;
15615  struct nk_vec2 text_size = nk_vec2(0,0);
15616 
15617  /* text pointer positions */
15618  const char *cursor_ptr = 0;
15619  const char *select_begin_ptr = 0;
15620  const char *select_end_ptr = 0;
15621 
15622  /* 2D pixel positions */
15623  struct nk_vec2 cursor_pos = nk_vec2(0,0);
15624  struct nk_vec2 selection_offset_start = nk_vec2(0,0);
15625  struct nk_vec2 selection_offset_end = nk_vec2(0,0);
15626 
15627  int selection_begin = NK_MIN(edit->select_start, edit->select_end);
15628  int selection_end = NK_MAX(edit->select_start, edit->select_end);
15629 
15630  /* calculate total line count + total space + cursor/selection position */
15631  float line_width = 0.0f;
15632  if (text && len)
15633  {
15634  /* utf8 encoding */
15635  float glyph_width;
15636  int glyph_len = 0;
15637  nk_rune unicode = 0;
15638  int text_len = 0;
15639  int glyphs = 0;
15640  int row_begin = 0;
15641 
15642  glyph_len = nk_utf_decode(text, &unicode, len);
15643  glyph_width = font->width(font->userdata, font->height, text, glyph_len);
15644  line_width = 0;
15645 
15646  /* iterate all lines */
15647  while ((text_len < len) && glyph_len)
15648  {
15649  /* set cursor 2D position and line */
15650  if (!cursor_ptr && glyphs == edit->cursor)
15651  {
15652  int glyph_offset;
15653  struct nk_vec2 out_offset;
15654  struct nk_vec2 row_size;
15655  const char *remaining;
15656 
15657  /* calculate 2d position */
15658  cursor_pos.y = (float)(total_lines-1) * row_height;
15659  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15660  text_len-row_begin, row_height, &remaining,
15661  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15662  cursor_pos.x = row_size.x;
15663  cursor_ptr = text + text_len;
15664  }
15665 
15666  /* set start selection 2D position and line */
15667  if (!select_begin_ptr && edit->select_start != edit->select_end &&
15668  glyphs == selection_begin)
15669  {
15670  int glyph_offset;
15671  struct nk_vec2 out_offset;
15672  struct nk_vec2 row_size;
15673  const char *remaining;
15674 
15675  /* calculate 2d position */
15676  selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height;
15677  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15678  text_len-row_begin, row_height, &remaining,
15679  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15680  selection_offset_start.x = row_size.x;
15681  select_begin_ptr = text + text_len;
15682  }
15683 
15684  /* set end selection 2D position and line */
15685  if (!select_end_ptr && edit->select_start != edit->select_end &&
15686  glyphs == selection_end)
15687  {
15688  int glyph_offset;
15689  struct nk_vec2 out_offset;
15690  struct nk_vec2 row_size;
15691  const char *remaining;
15692 
15693  /* calculate 2d position */
15694  selection_offset_end.y = (float)(total_lines-1) * row_height;
15695  row_size = nk_text_calculate_text_bounds(font, text+row_begin,
15696  text_len-row_begin, row_height, &remaining,
15697  &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE);
15698  selection_offset_end.x = row_size.x;
15699  select_end_ptr = text + text_len;
15700  }
15701  if (unicode == '\n') {
15702  text_size.x = NK_MAX(text_size.x, line_width);
15703  total_lines++;
15704  line_width = 0;
15705  text_len++;
15706  glyphs++;
15707  row_begin = text_len;
15708  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
15709  glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len);
15710  continue;
15711  }
15712 
15713  glyphs++;
15714  text_len += glyph_len;
15715  line_width += (float)glyph_width;
15716 
15717  glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len);
15718  glyph_width = font->width(font->userdata, font->height,
15719  text+text_len, glyph_len);
15720  continue;
15721  }
15722  text_size.y = (float)total_lines * row_height;
15723 
15724  /* handle case when cursor is at end of text buffer */
15725  if (!cursor_ptr && edit->cursor == edit->string.len) {
15726  cursor_pos.x = line_width;
15727  cursor_pos.y = text_size.y - row_height;
15728  }
15729  }
15730  {
15731  /* scrollbar */
15732  if (cursor_follow)
15733  {
15734  /* update scrollbar to follow cursor */
15736  /* horizontal scroll */
15737  const float scroll_increment = area.w * 0.25f;
15738  if (cursor_pos.x < edit->scrollbar.x)
15739  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment);
15740  if (cursor_pos.x >= edit->scrollbar.x + area.w)
15741  edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x);
15742  } else edit->scrollbar.x = 0;
15743 
15744  if (flags & NK_EDIT_MULTILINE) {
15745  /* vertical scroll */
15746  if (cursor_pos.y < edit->scrollbar.y)
15747  edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height);
15748  if (cursor_pos.y >= edit->scrollbar.y + area.h)
15749  edit->scrollbar.y = edit->scrollbar.y + row_height;
15750  } else edit->scrollbar.y = 0;
15751  }
15752 
15753  /* scrollbar widget */
15754  if (flags & NK_EDIT_MULTILINE)
15755  {
15756  nk_flags ws;
15757  struct nk_rect scroll;
15758  float scroll_target;
15759  float scroll_offset;
15760  float scroll_step;
15761  float scroll_inc;
15762 
15763  scroll = area;
15764  scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x;
15765  scroll.w = style->scrollbar_size.x;
15766 
15767  scroll_offset = edit->scrollbar.y;
15768  scroll_step = scroll.h * 0.10f;
15769  scroll_inc = scroll.h * 0.01f;
15770  scroll_target = text_size.y;
15771  edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0,
15772  scroll_offset, scroll_target, scroll_step, scroll_inc,
15773  &style->scrollbar, in, font);
15774  }
15775  }
15776 
15777  /* draw text */
15778  {struct nk_color background_color;
15779  struct nk_color text_color;
15780  struct nk_color sel_background_color;
15781  struct nk_color sel_text_color;
15782  struct nk_color cursor_color;
15783  struct nk_color cursor_text_color;
15784  const struct nk_style_item *background;
15785  nk_push_scissor(out, clip);
15786 
15787  /* select correct colors to draw */
15788  if (*state & NK_WIDGET_STATE_ACTIVED) {
15789  background = &style->active;
15790  text_color = style->text_active;
15791  sel_text_color = style->selected_text_hover;
15792  sel_background_color = style->selected_hover;
15793  cursor_color = style->cursor_hover;
15794  cursor_text_color = style->cursor_text_hover;
15795  } else if (*state & NK_WIDGET_STATE_HOVER) {
15796  background = &style->hover;
15797  text_color = style->text_hover;
15798  sel_text_color = style->selected_text_hover;
15799  sel_background_color = style->selected_hover;
15800  cursor_text_color = style->cursor_text_hover;
15801  cursor_color = style->cursor_hover;
15802  } else {
15803  background = &style->normal;
15804  text_color = style->text_normal;
15805  sel_text_color = style->selected_text_normal;
15806  sel_background_color = style->selected_normal;
15807  cursor_color = style->cursor_normal;
15808  cursor_text_color = style->cursor_text_normal;
15809  }
15810  if (background->type == NK_STYLE_ITEM_IMAGE)
15811  background_color = nk_rgba(0,0,0,0);
15812  else background_color = background->data.color;
15813 
15814 
15815  if (edit->select_start == edit->select_end) {
15816  /* no selection so just draw the complete text */
15817  const char *begin = nk_str_get_const(&edit->string);
15818  int l = nk_str_len_char(&edit->string);
15819  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15820  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
15821  background_color, text_color, nk_false);
15822  } else {
15823  /* edit has selection so draw 1-3 text chunks */
15824  if (edit->select_start != edit->select_end && selection_begin > 0){
15825  /* draw unselected text before selection */
15826  const char *begin = nk_str_get_const(&edit->string);
15827  NK_ASSERT(select_begin_ptr);
15828  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15829  area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin),
15830  row_height, font, background_color, text_color, nk_false);
15831  }
15832  if (edit->select_start != edit->select_end) {
15833  /* draw selected text */
15834  NK_ASSERT(select_begin_ptr);
15835  if (!select_end_ptr) {
15836  const char *begin = nk_str_get_const(&edit->string);
15837  select_end_ptr = begin + nk_str_len_char(&edit->string);
15838  }
15839  nk_edit_draw_text(out, style,
15840  area.x - edit->scrollbar.x,
15841  area.y + selection_offset_start.y - edit->scrollbar.y,
15842  selection_offset_start.x,
15843  select_begin_ptr, (int)(select_end_ptr - select_begin_ptr),
15844  row_height, font, sel_background_color, sel_text_color, nk_true);
15845  }
15846  if ((edit->select_start != edit->select_end &&
15847  selection_end < edit->string.len))
15848  {
15849  /* draw unselected text after selected text */
15850  const char *begin = select_end_ptr;
15851  const char *end = nk_str_get_const(&edit->string) +
15852  nk_str_len_char(&edit->string);
15853  NK_ASSERT(select_end_ptr);
15854  nk_edit_draw_text(out, style,
15855  area.x - edit->scrollbar.x,
15856  area.y + selection_offset_end.y - edit->scrollbar.y,
15857  selection_offset_end.x,
15858  begin, (int)(end - begin), row_height, font,
15859  background_color, text_color, nk_true);
15860  }
15861  }
15862 
15863  /* cursor */
15864  if (edit->select_start == edit->select_end)
15865  {
15866  if (edit->cursor >= nk_str_len(&edit->string) ||
15867  (cursor_ptr && *cursor_ptr == '\n')) {
15868  /* draw cursor at end of line */
15869  struct nk_rect cursor;
15870  cursor.w = style->cursor_size;
15871  cursor.h = font->height;
15872  cursor.x = area.x + cursor_pos.x - edit->scrollbar.x;
15873  cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f;
15874  cursor.y -= edit->scrollbar.y;
15875  nk_fill_rect(out, cursor, 0, cursor_color);
15876  } else {
15877  /* draw cursor inside text */
15878  int glyph_len;
15879  struct nk_rect label;
15880  struct nk_text txt;
15881 
15882  nk_rune unicode;
15883  NK_ASSERT(cursor_ptr);
15884  glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4);
15885 
15886  label.x = area.x + cursor_pos.x - edit->scrollbar.x;
15887  label.y = area.y + cursor_pos.y - edit->scrollbar.y;
15888  label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len);
15889  label.h = row_height;
15890 
15891  txt.padding = nk_vec2(0,0);
15892  txt.background = cursor_color;;
15893  txt.text = cursor_text_color;
15894  nk_fill_rect(out, label, 0, cursor_color);
15895  nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font);
15896  }
15897  }}
15898  } else {
15899  /* not active so just draw text */
15900  int l = nk_str_len_char(&edit->string);
15901  const char *begin = nk_str_get_const(&edit->string);
15902 
15903  const struct nk_style_item *background;
15904  struct nk_color background_color;
15905  struct nk_color text_color;
15906  nk_push_scissor(out, clip);
15907  if (*state & NK_WIDGET_STATE_ACTIVED) {
15908  background = &style->active;
15909  text_color = style->text_active;
15910  } else if (*state & NK_WIDGET_STATE_HOVER) {
15911  background = &style->hover;
15912  text_color = style->text_hover;
15913  } else {
15914  background = &style->normal;
15915  text_color = style->text_normal;
15916  }
15917  if (background->type == NK_STYLE_ITEM_IMAGE)
15918  background_color = nk_rgba(0,0,0,0);
15919  else background_color = background->data.color;
15920  nk_edit_draw_text(out, style, area.x - edit->scrollbar.x,
15921  area.y - edit->scrollbar.y, 0, begin, l, row_height, font,
15922  background_color, text_color, nk_false);
15923  }
15924  nk_push_scissor(out, old_clip);}
15925  return ret;
15926 }
15927 
15928 /* ===============================================================
15929  *
15930  * PROPERTY
15931  *
15932  * ===============================================================*/
15933 enum nk_property_status {
15934  NK_PROPERTY_DEFAULT,
15935  NK_PROPERTY_EDIT,
15936  NK_PROPERTY_DRAG
15937 };
15938 enum nk_property_filter {
15939  NK_FILTER_INT,
15940  NK_FILTER_FLOAT
15941 };
15942 enum nk_property_kind {
15943  NK_PROPERTY_INT,
15944  NK_PROPERTY_FLOAT,
15945  NK_PROPERTY_DOUBLE
15946 };
15947 union nk_property {
15948  int i;
15949  float f;
15950  double d;
15951 };
15952 struct nk_property_variant {
15953  enum nk_property_kind kind;
15954  union nk_property value;
15955  union nk_property min_value;
15956  union nk_property max_value;
15957  union nk_property step;
15958 };
15959 
15960 NK_INTERN void
15961 nk_drag_behavior(nk_flags *state, const struct nk_input *in,
15962  struct nk_rect drag, struct nk_property_variant *variant,
15963  float inc_per_pixel)
15964 {
15965  int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down;
15966  int left_mouse_click_in_cursor = in &&
15968 
15969  nk_widget_state_reset(state);
15972 
15973  if (left_mouse_down && left_mouse_click_in_cursor) {
15974  float delta, pixels;
15975  pixels = in->mouse.delta.x;
15976  delta = pixels * inc_per_pixel;
15977  switch (variant->kind) {
15978  default: break;
15979  case NK_PROPERTY_INT:
15980  variant->value.i = variant->value.i + (int)delta;
15981  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
15982  break;
15983  case NK_PROPERTY_FLOAT:
15984  variant->value.f = variant->value.f + (float)delta;
15985  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
15986  break;
15987  case NK_PROPERTY_DOUBLE:
15988  variant->value.d = variant->value.d + (double)delta;
15989  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
15990  break;
15991  }
15993  }
15996  else if (nk_input_is_mouse_prev_hovering_rect(in, drag))
15998 }
15999 
16000 NK_INTERN void
16001 nk_property_behavior(nk_flags *ws, const struct nk_input *in,
16002  struct nk_rect property, struct nk_rect label, struct nk_rect edit,
16003  struct nk_rect empty, int *state, struct nk_property_variant *variant,
16004  float inc_per_pixel)
16005 {
16006  if (in && *state == NK_PROPERTY_DEFAULT) {
16007  if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT))
16008  *state = NK_PROPERTY_EDIT;
16010  *state = NK_PROPERTY_DRAG;
16012  *state = NK_PROPERTY_DRAG;
16013  }
16014  if (*state == NK_PROPERTY_DRAG) {
16015  nk_drag_behavior(ws, in, property, variant, inc_per_pixel);
16016  if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT;
16017  }
16018 }
16019 
16020 NK_INTERN void
16021 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style,
16022  const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state,
16023  const char *name, int len, const struct nk_user_font *font)
16024 {
16025  struct nk_text text;
16026  const struct nk_style_item *background;
16027 
16028  /* select correct background and text color */
16030  background = &style->active;
16031  text.text = style->label_active;
16032  } else if (state & NK_WIDGET_STATE_HOVER) {
16033  background = &style->hover;
16034  text.text = style->label_hover;
16035  } else {
16036  background = &style->normal;
16037  text.text = style->label_normal;
16038  }
16039 
16040  /* draw background */
16041  if (background->type == NK_STYLE_ITEM_IMAGE) {
16042  nk_draw_image(out, *bounds, &background->data.image, nk_white);
16043  text.background = nk_rgba(0,0,0,0);
16044  } else {
16045  text.background = background->data.color;
16046  nk_fill_rect(out, *bounds, style->rounding, background->data.color);
16047  nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color);
16048  }
16049 
16050  /* draw label */
16051  text.padding = nk_vec2(0,0);
16052  nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font);
16053 }
16054 
16055 NK_INTERN void
16056 nk_do_property(nk_flags *ws,
16057  struct nk_command_buffer *out, struct nk_rect property,
16058  const char *name, struct nk_property_variant *variant,
16059  float inc_per_pixel, char *buffer, int *len,
16060  int *state, int *cursor, int *select_begin, int *select_end,
16061  const struct nk_style_property *style,
16062  enum nk_property_filter filter, struct nk_input *in,
16063  const struct nk_user_font *font, struct nk_text_edit *text_edit,
16064  enum nk_button_behavior behavior)
16065 {
16066  const nk_plugin_filter filters[] = {
16069  };
16070  int active, old;
16071  int num_len, name_len;
16072  char string[NK_MAX_NUMBER_BUFFER];
16073  float size;
16074 
16075  char *dst = 0;
16076  int *length;
16077 
16078  struct nk_rect left;
16079  struct nk_rect right;
16080  struct nk_rect label;
16081  struct nk_rect edit;
16082  struct nk_rect empty;
16083 
16084  /* left decrement button */
16085  left.h = font->height/2;
16086  left.w = left.h;
16087  left.x = property.x + style->border + style->padding.x;
16088  left.y = property.y + style->border + property.h/2.0f - left.h/2;
16089 
16090  /* text label */
16091  name_len = nk_strlen(name);
16092  size = font->width(font->userdata, font->height, name, name_len);
16093  label.x = left.x + left.w + style->padding.x;
16094  label.w = (float)size + 2 * style->padding.x;
16095  label.y = property.y + style->border + style->padding.y;
16096  label.h = property.h - (2 * style->border + 2 * style->padding.y);
16097 
16098  /* right increment button */
16099  right.y = left.y;
16100  right.w = left.w;
16101  right.h = left.h;
16102  right.x = property.x + property.w - (right.w + style->padding.x);
16103 
16104  /* edit */
16105  if (*state == NK_PROPERTY_EDIT) {
16106  size = font->width(font->userdata, font->height, buffer, *len);
16107  size += style->edit.cursor_size;
16108  length = len;
16109  dst = buffer;
16110  } else {
16111  switch (variant->kind) {
16112  default: break;
16113  case NK_PROPERTY_INT:
16114  nk_itoa(string, variant->value.i);
16115  num_len = nk_strlen(string);
16116  break;
16117  case NK_PROPERTY_FLOAT:
16118  nk_dtoa(string, (double)variant->value.f);
16119  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
16120  break;
16121  case NK_PROPERTY_DOUBLE:
16122  nk_dtoa(string, variant->value.d);
16123  num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION);
16124  break;
16125  }
16126  size = font->width(font->userdata, font->height, string, num_len);
16127  dst = string;
16128  length = &num_len;
16129  }
16130 
16131  edit.w = (float)size + 2 * style->padding.x;
16132  edit.w = NK_MIN(edit.w, right.x - (label.x + label.w));
16133  edit.x = right.x - (edit.w + style->padding.x);
16134  edit.y = property.y + style->border;
16135  edit.h = property.h - (2 * style->border);
16136 
16137  /* empty left space activator */
16138  empty.w = edit.x - (label.x + label.w);
16139  empty.x = label.x + label.w;
16140  empty.y = property.y;
16141  empty.h = property.h;
16142 
16143  /* update property */
16144  old = (*state == NK_PROPERTY_EDIT);
16145  nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel);
16146 
16147  /* draw property */
16148  if (style->draw_begin) style->draw_begin(out, style->userdata);
16149  nk_draw_property(out, style, &property, &label, *ws, name, name_len, font);
16150  if (style->draw_end) style->draw_end(out, style->userdata);
16151 
16152  /* execute right button */
16153  if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) {
16154  switch (variant->kind) {
16155  default: break;
16156  case NK_PROPERTY_INT:
16157  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break;
16158  case NK_PROPERTY_FLOAT:
16159  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break;
16160  case NK_PROPERTY_DOUBLE:
16161  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break;
16162  }
16163  }
16164  /* execute left button */
16165  if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) {
16166  switch (variant->kind) {
16167  default: break;
16168  case NK_PROPERTY_INT:
16169  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break;
16170  case NK_PROPERTY_FLOAT:
16171  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break;
16172  case NK_PROPERTY_DOUBLE:
16173  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break;
16174  }
16175  }
16176  if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) {
16177  /* property has been activated so setup buffer */
16178  NK_MEMCPY(buffer, dst, (nk_size)*length);
16179  *cursor = nk_utf_len(buffer, *length);
16180  *len = *length;
16181  length = len;
16182  dst = buffer;
16183  active = 0;
16184  } else active = (*state == NK_PROPERTY_EDIT);
16185 
16186  /* execute and run text edit field */
16187  nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]);
16188  text_edit->active = (unsigned char)active;
16189  text_edit->string.len = *length;
16190  text_edit->cursor = NK_CLAMP(0, *cursor, *length);
16191  text_edit->select_start = NK_CLAMP(0,*select_begin, *length);
16192  text_edit->select_end = NK_CLAMP(0,*select_end, *length);
16193  text_edit->string.buffer.allocated = (nk_size)*length;
16195  text_edit->string.buffer.memory.ptr = dst;
16196  text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER;
16197  text_edit->mode = NK_TEXT_EDIT_MODE_INSERT;
16198  nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT,
16199  filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font);
16200 
16201  *length = text_edit->string.len;
16202  *cursor = text_edit->cursor;
16203  *select_begin = text_edit->select_start;
16204  *select_end = text_edit->select_end;
16205  if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER))
16206  text_edit->active = nk_false;
16207 
16208  if (active && !text_edit->active) {
16209  /* property is now not active so convert edit text to value*/
16210  *state = NK_PROPERTY_DEFAULT;
16211  buffer[*len] = '\0';
16212  switch (variant->kind) {
16213  default: break;
16214  case NK_PROPERTY_INT:
16215  variant->value.i = nk_strtoi(buffer, 0);
16216  variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i);
16217  break;
16218  case NK_PROPERTY_FLOAT:
16219  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
16220  variant->value.f = nk_strtof(buffer, 0);
16221  variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f);
16222  break;
16223  case NK_PROPERTY_DOUBLE:
16224  nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION);
16225  variant->value.d = nk_strtod(buffer, 0);
16226  variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d);
16227  break;
16228  }
16229  }
16230 }
16231 /* ===============================================================
16232  *
16233  * COLOR PICKER
16234  *
16235  * ===============================================================*/
16236 NK_INTERN int
16237 nk_color_picker_behavior(nk_flags *state,
16238  const struct nk_rect *bounds, const struct nk_rect *matrix,
16239  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
16240  struct nk_color *color, const struct nk_input *in)
16241 {
16242  float hsva[4];
16243  int value_changed = 0;
16244  int hsv_changed = 0;
16245 
16246  NK_ASSERT(state);
16247  NK_ASSERT(matrix);
16248  NK_ASSERT(hue_bar);
16249  NK_ASSERT(color);
16250 
16251  /* color matrix */
16252  nk_color_hsva_fv(hsva, *color);
16254  hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1));
16255  hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1));
16256  value_changed = hsv_changed = 1;
16257  }
16258 
16259  /* hue bar */
16260  if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) {
16261  hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1));
16262  value_changed = hsv_changed = 1;
16263  }
16264 
16265  /* alpha bar */
16266  if (alpha_bar) {
16267  if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) {
16268  hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1));
16269  value_changed = 1;
16270  }
16271  }
16272  nk_widget_state_reset(state);
16273  if (hsv_changed) {
16274  *color = nk_hsva_fv(hsva);
16276  }
16277  if (value_changed) {
16278  color->a = (nk_byte)(hsva[3] * 255.0f);
16280  }
16281 
16282  /* set color picker widget state */
16283  if (nk_input_is_mouse_hovering_rect(in, *bounds))
16287  else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds))
16289  return value_changed;
16290 }
16291 
16292 NK_INTERN void
16293 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix,
16294  const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar,
16295  struct nk_color color)
16296 {
16297  NK_STORAGE const struct nk_color black = {0,0,0,255};
16298  NK_STORAGE const struct nk_color white = {255, 255, 255, 255};
16299  NK_STORAGE const struct nk_color black_trans = {0,0,0,0};
16300 
16301  const float crosshair_size = 7.0f;
16302  struct nk_color temp;
16303  float hsva[4];
16304  float line_y;
16305  int i;
16306 
16307  NK_ASSERT(o);
16308  NK_ASSERT(matrix);
16309  NK_ASSERT(hue_bar);
16310 
16311  /* draw hue bar */
16312  nk_color_hsv_fv(hsva, color);
16313  for (i = 0; i < 6; ++i) {
16314  NK_GLOBAL const struct nk_color hue_colors[] = {
16315  {255, 0, 0, 255},
16316  {255,255,0,255},
16317  {0,255,0,255},
16318  {0, 255,255,255},
16319  {0,0,255,255},
16320  {255, 0, 255, 255},
16321  {255, 0, 0, 255}
16322  };
16324  nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f,
16325  hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i],
16326  hue_colors[i+1], hue_colors[i+1]);
16327  }
16328  line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f);
16329  nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2,
16330  line_y, 1, nk_rgb(255,255,255));
16331 
16332  /* draw alpha bar */
16333  if (alpha_bar) {
16334  float alpha = NK_SATURATE((float)color.a/255.0f);
16335  line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f);
16336 
16337  nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black);
16338  nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2,
16339  line_y, 1, nk_rgb(255,255,255));
16340  }
16341 
16342  /* draw color matrix */
16343  temp = nk_hsv_f(hsva[0], 1.0f, 1.0f);
16344  nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white);
16345  nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black);
16346 
16347  /* draw cross-hair */
16348  {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2];
16349  p.x = (float)(int)(matrix->x + S * matrix->w);
16350  p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h);
16351  nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white);
16352  nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white);
16353  nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white);
16354  nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);}
16355 }
16356 
16357 NK_INTERN int
16358 nk_do_color_picker(nk_flags *state,
16359  struct nk_command_buffer *out, struct nk_color *color,
16360  enum nk_color_format fmt, struct nk_rect bounds,
16361  struct nk_vec2 padding, const struct nk_input *in,
16362  const struct nk_user_font *font)
16363 {
16364  int ret = 0;
16365  struct nk_rect matrix;
16366  struct nk_rect hue_bar;
16367  struct nk_rect alpha_bar;
16368  float bar_w;
16369 
16370  NK_ASSERT(out);
16371  NK_ASSERT(color);
16372  NK_ASSERT(state);
16373  NK_ASSERT(font);
16374  if (!out || !color || !state || !font)
16375  return ret;
16376 
16377  bar_w = font->height;
16378  bounds.x += padding.x;
16379  bounds.y += padding.x;
16380  bounds.w -= 2 * padding.x;
16381  bounds.h -= 2 * padding.y;
16382 
16383  matrix.x = bounds.x;
16384  matrix.y = bounds.y;
16385  matrix.h = bounds.h;
16386  matrix.w = bounds.w - (3 * padding.x + 2 * bar_w);
16387 
16388  hue_bar.w = bar_w;
16389  hue_bar.y = bounds.y;
16390  hue_bar.h = matrix.h;
16391  hue_bar.x = matrix.x + matrix.w + padding.x;
16392 
16393  alpha_bar.x = hue_bar.x + hue_bar.w + padding.x;
16394  alpha_bar.y = bounds.y;
16395  alpha_bar.w = bar_w;
16396  alpha_bar.h = matrix.h;
16397 
16398  ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar,
16399  (fmt == NK_RGBA) ? &alpha_bar:0, color, in);
16400  nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *color);
16401  return ret;
16402 }
16403 
16404 /* ==============================================================
16405  *
16406  * STYLE
16407  *
16408  * ===============================================================*/
16410 #define NK_COLOR_MAP(NK_COLOR)\
16411  NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \
16412  NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \
16413  NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \
16414  NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \
16415  NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \
16416  NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \
16417  NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \
16418  NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \
16419  NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \
16420  NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \
16421  NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \
16422  NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \
16423  NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \
16424  NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \
16425  NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \
16426  NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \
16427  NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \
16428  NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \
16429  NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \
16430  NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \
16431  NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \
16432  NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \
16433  NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,255, 0, 0, 255) \
16434  NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \
16435  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \
16436  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,120,120,120,255) \
16437  NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,150,150,150,255) \
16438  NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255)
16439 
16440 NK_GLOBAL const struct nk_color
16441 nk_default_color_style[NK_COLOR_COUNT] = {
16442 #define NK_COLOR(a,b,c,d,e) {b,c,d,e},
16443  NK_COLOR_MAP(NK_COLOR)
16444 #undef NK_COLOR
16445 };
16446 
16447 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = {
16448 #define NK_COLOR(a,b,c,d,e) #a,
16449  NK_COLOR_MAP(NK_COLOR)
16450 #undef NK_COLOR
16451 };
16452 
16454 {return nk_color_names[c];}
16455 
16457 {struct nk_style_item i; i.type = NK_STYLE_ITEM_IMAGE; i.data.image = img; return i;}
16458 
16460 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = col; return i;}
16461 
16463 {struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = nk_rgba(0,0,0,0); return i;}
16464 
16465 NK_API void
16466 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table)
16467 {
16468  struct nk_style *style;
16469  struct nk_style_text *text;
16470  struct nk_style_button *button;
16471  struct nk_style_toggle *toggle;
16472  struct nk_style_selectable *select;
16473  struct nk_style_slider *slider;
16474  struct nk_style_progress *prog;
16475  struct nk_style_scrollbar *scroll;
16476  struct nk_style_edit *edit;
16477  struct nk_style_property *property;
16478  struct nk_style_combo *combo;
16479  struct nk_style_chart *chart;
16480  struct nk_style_tab *tab;
16481  struct nk_style_window *win;
16482 
16483  NK_ASSERT(ctx);
16484  if (!ctx) return;
16485  style = &ctx->style;
16486  table = (!table) ? nk_default_color_style: table;
16487 
16488  /* default text */
16489  text = &style->text;
16490  text->color = table[NK_COLOR_TEXT];
16491  text->padding = nk_vec2(0,0);
16492 
16493  /* default button */
16494  button = &style->button;
16499  button->border_color = table[NK_COLOR_BORDER];
16500  button->text_background = table[NK_COLOR_BUTTON];
16501  button->text_normal = table[NK_COLOR_TEXT];
16502  button->text_hover = table[NK_COLOR_TEXT];
16503  button->text_active = table[NK_COLOR_TEXT];
16504  button->padding = nk_vec2(2.0f,2.0f);
16505  button->image_padding = nk_vec2(0.0f,0.0f);
16506  button->touch_padding = nk_vec2(0.0f, 0.0f);
16507  button->userdata = nk_handle_ptr(0);
16508  button->text_alignment = NK_TEXT_CENTERED;
16509  button->border = 1.0f;
16510  button->rounding = 4.0f;
16511  button->draw_begin = 0;
16512  button->draw_end = 0;
16513 
16514  /* contextual button */
16515  button = &style->contextual_button;
16520  button->border_color = table[NK_COLOR_WINDOW];
16521  button->text_background = table[NK_COLOR_WINDOW];
16522  button->text_normal = table[NK_COLOR_TEXT];
16523  button->text_hover = table[NK_COLOR_TEXT];
16524  button->text_active = table[NK_COLOR_TEXT];
16525  button->padding = nk_vec2(2.0f,2.0f);
16526  button->touch_padding = nk_vec2(0.0f,0.0f);
16527  button->userdata = nk_handle_ptr(0);
16528  button->text_alignment = NK_TEXT_CENTERED;
16529  button->border = 0.0f;
16530  button->rounding = 0.0f;
16531  button->draw_begin = 0;
16532  button->draw_end = 0;
16533 
16534  /* menu button */
16535  button = &style->menu_button;
16540  button->border_color = table[NK_COLOR_WINDOW];
16541  button->text_background = table[NK_COLOR_WINDOW];
16542  button->text_normal = table[NK_COLOR_TEXT];
16543  button->text_hover = table[NK_COLOR_TEXT];
16544  button->text_active = table[NK_COLOR_TEXT];
16545  button->padding = nk_vec2(2.0f,2.0f);
16546  button->touch_padding = nk_vec2(0.0f,0.0f);
16547  button->userdata = nk_handle_ptr(0);
16548  button->text_alignment = NK_TEXT_CENTERED;
16549  button->border = 0.0f;
16550  button->rounding = 1.0f;
16551  button->draw_begin = 0;
16552  button->draw_end = 0;
16553 
16554  /* checkbox toggle */
16555  toggle = &style->checkbox;
16556  nk_zero_struct(*toggle);
16562  toggle->userdata = nk_handle_ptr(0);
16564  toggle->text_normal = table[NK_COLOR_TEXT];
16565  toggle->text_hover = table[NK_COLOR_TEXT];
16566  toggle->text_active = table[NK_COLOR_TEXT];
16567  toggle->padding = nk_vec2(2.0f, 2.0f);
16568  toggle->touch_padding = nk_vec2(0,0);
16569  toggle->border_color = nk_rgba(0,0,0,0);
16570  toggle->border = 0.0f;
16571  toggle->spacing = 4;
16572 
16573  /* option toggle */
16574  toggle = &style->option;
16575  nk_zero_struct(*toggle);
16581  toggle->userdata = nk_handle_ptr(0);
16583  toggle->text_normal = table[NK_COLOR_TEXT];
16584  toggle->text_hover = table[NK_COLOR_TEXT];
16585  toggle->text_active = table[NK_COLOR_TEXT];
16586  toggle->padding = nk_vec2(3.0f, 3.0f);
16587  toggle->touch_padding = nk_vec2(0,0);
16588  toggle->border_color = nk_rgba(0,0,0,0);
16589  toggle->border = 0.0f;
16590  toggle->spacing = 4;
16591 
16592  /* selectable */
16593  select = &style->selectable;
16601  select->text_normal = table[NK_COLOR_TEXT];
16602  select->text_hover = table[NK_COLOR_TEXT];
16603  select->text_pressed = table[NK_COLOR_TEXT];
16604  select->text_normal_active = table[NK_COLOR_TEXT];
16605  select->text_hover_active = table[NK_COLOR_TEXT];
16606  select->text_pressed_active = table[NK_COLOR_TEXT];
16607  select->padding = nk_vec2(2.0f,2.0f);
16608  select->touch_padding = nk_vec2(0,0);
16609  select->userdata = nk_handle_ptr(0);
16610  select->rounding = 0.0f;
16611  select->draw_begin = 0;
16612  select->draw_end = 0;
16613 
16614  /* slider */
16615  slider = &style->slider;
16616  nk_zero_struct(*slider);
16617  slider->normal = nk_style_item_hide();
16618  slider->hover = nk_style_item_hide();
16619  slider->active = nk_style_item_hide();
16620  slider->bar_normal = table[NK_COLOR_SLIDER];
16621  slider->bar_hover = table[NK_COLOR_SLIDER];
16622  slider->bar_active = table[NK_COLOR_SLIDER];
16629  slider->cursor_size = nk_vec2(16,16);
16630  slider->padding = nk_vec2(2,2);
16631  slider->spacing = nk_vec2(2,2);
16632  slider->userdata = nk_handle_ptr(0);
16633  slider->show_buttons = nk_false;
16634  slider->bar_height = 8;
16635  slider->rounding = 0;
16636  slider->draw_begin = 0;
16637  slider->draw_end = 0;
16638 
16639  /* slider buttons */
16640  button = &style->slider.inc_button;
16641  button->normal = nk_style_item_color(nk_rgb(40,40,40));
16642  button->hover = nk_style_item_color(nk_rgb(42,42,42));
16643  button->active = nk_style_item_color(nk_rgb(44,44,44));
16644  button->border_color = nk_rgb(65,65,65);
16645  button->text_background = nk_rgb(40,40,40);
16646  button->text_normal = nk_rgb(175,175,175);
16647  button->text_hover = nk_rgb(175,175,175);
16648  button->text_active = nk_rgb(175,175,175);
16649  button->padding = nk_vec2(8.0f,8.0f);
16650  button->touch_padding = nk_vec2(0.0f,0.0f);
16651  button->userdata = nk_handle_ptr(0);
16652  button->text_alignment = NK_TEXT_CENTERED;
16653  button->border = 1.0f;
16654  button->rounding = 0.0f;
16655  button->draw_begin = 0;
16656  button->draw_end = 0;
16657  style->slider.dec_button = style->slider.inc_button;
16658 
16659  /* progressbar */
16660  prog = &style->progress;
16661  nk_zero_struct(*prog);
16668  prog->border_color = nk_rgba(0,0,0,0);
16669  prog->cursor_border_color = nk_rgba(0,0,0,0);
16670  prog->userdata = nk_handle_ptr(0);
16671  prog->padding = nk_vec2(4,4);
16672  prog->rounding = 0;
16673  prog->border = 0;
16674  prog->cursor_rounding = 0;
16675  prog->cursor_border = 0;
16676  prog->draw_begin = 0;
16677  prog->draw_end = 0;
16678 
16679  /* scrollbars */
16680  scroll = &style->scrollh;
16681  nk_zero_struct(*scroll);
16690  scroll->userdata = nk_handle_ptr(0);
16693  scroll->padding = nk_vec2(0,0);
16694  scroll->show_buttons = nk_false;
16695  scroll->border = 0;
16696  scroll->rounding = 0;
16697  scroll->border_cursor = 0;
16698  scroll->rounding_cursor = 0;
16699  scroll->draw_begin = 0;
16700  scroll->draw_end = 0;
16701  style->scrollv = style->scrollh;
16702 
16703  /* scrollbars buttons */
16704  button = &style->scrollh.inc_button;
16705  button->normal = nk_style_item_color(nk_rgb(40,40,40));
16706  button->hover = nk_style_item_color(nk_rgb(42,42,42));
16707  button->active = nk_style_item_color(nk_rgb(44,44,44));
16708  button->border_color = nk_rgb(65,65,65);
16709  button->text_background = nk_rgb(40,40,40);
16710  button->text_normal = nk_rgb(175,175,175);
16711  button->text_hover = nk_rgb(175,175,175);
16712  button->text_active = nk_rgb(175,175,175);
16713  button->padding = nk_vec2(4.0f,4.0f);
16714  button->touch_padding = nk_vec2(0.0f,0.0f);
16715  button->userdata = nk_handle_ptr(0);
16716  button->text_alignment = NK_TEXT_CENTERED;
16717  button->border = 1.0f;
16718  button->rounding = 0.0f;
16719  button->draw_begin = 0;
16720  button->draw_end = 0;
16721  style->scrollh.dec_button = style->scrollh.inc_button;
16722  style->scrollv.inc_button = style->scrollh.inc_button;
16723  style->scrollv.dec_button = style->scrollh.inc_button;
16724 
16725  /* edit */
16726  edit = &style->edit;
16727  nk_zero_struct(*edit);
16732  edit->cursor_hover = table[NK_COLOR_TEXT];
16736  edit->text_normal = table[NK_COLOR_TEXT];
16737  edit->text_hover = table[NK_COLOR_TEXT];
16738  edit->text_active = table[NK_COLOR_TEXT];
16743  edit->scrollbar_size = nk_vec2(10,10);
16744  edit->scrollbar = style->scrollv;
16745  edit->padding = nk_vec2(4,4);
16746  edit->row_padding = 2;
16747  edit->cursor_size = 4;
16748  edit->border = 1;
16749  edit->rounding = 0;
16750 
16751  /* property */
16752  property = &style->property;
16753  nk_zero_struct(*property);
16754  property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16755  property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16756  property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]);
16757  property->border_color = table[NK_COLOR_BORDER];
16758  property->label_normal = table[NK_COLOR_TEXT];
16759  property->label_hover = table[NK_COLOR_TEXT];
16760  property->label_active = table[NK_COLOR_TEXT];
16761  property->sym_left = NK_SYMBOL_TRIANGLE_LEFT;
16762  property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT;
16763  property->userdata = nk_handle_ptr(0);
16764  property->padding = nk_vec2(4,4);
16765  property->border = 1;
16766  property->rounding = 10;
16767  property->draw_begin = 0;
16768  property->draw_end = 0;
16769 
16770  /* property buttons */
16771  button = &style->property.dec_button;
16776  button->border_color = nk_rgba(0,0,0,0);
16777  button->text_background = table[NK_COLOR_PROPERTY];
16778  button->text_normal = table[NK_COLOR_TEXT];
16779  button->text_hover = table[NK_COLOR_TEXT];
16780  button->text_active = table[NK_COLOR_TEXT];
16781  button->padding = nk_vec2(0.0f,0.0f);
16782  button->touch_padding = nk_vec2(0.0f,0.0f);
16783  button->userdata = nk_handle_ptr(0);
16784  button->text_alignment = NK_TEXT_CENTERED;
16785  button->border = 0.0f;
16786  button->rounding = 0.0f;
16787  button->draw_begin = 0;
16788  button->draw_end = 0;
16789  style->property.inc_button = style->property.dec_button;
16790 
16791  /* property edit */
16792  edit = &style->property.edit;
16793  nk_zero_struct(*edit);
16797  edit->border_color = nk_rgba(0,0,0,0);
16799  edit->cursor_hover = table[NK_COLOR_TEXT];
16802  edit->text_normal = table[NK_COLOR_TEXT];
16803  edit->text_hover = table[NK_COLOR_TEXT];
16804  edit->text_active = table[NK_COLOR_TEXT];
16809  edit->padding = nk_vec2(0,0);
16810  edit->cursor_size = 8;
16811  edit->border = 0;
16812  edit->rounding = 0;
16813 
16814  /* chart */
16815  chart = &style->chart;
16816  nk_zero_struct(*chart);
16820  chart->color = table[NK_COLOR_CHART_COLOR];
16821  chart->padding = nk_vec2(4,4);
16822  chart->border = 0;
16823  chart->rounding = 0;
16824 
16825  /* combo */
16826  combo = &style->combo;
16831  combo->label_normal = table[NK_COLOR_TEXT];
16832  combo->label_hover = table[NK_COLOR_TEXT];
16833  combo->label_active = table[NK_COLOR_TEXT];
16837  combo->content_padding = nk_vec2(4,4);
16838  combo->button_padding = nk_vec2(0,4);
16839  combo->spacing = nk_vec2(4,0);
16840  combo->border = 1;
16841  combo->rounding = 0;
16842 
16843  /* combo button */
16844  button = &style->combo.button;
16849  button->border_color = nk_rgba(0,0,0,0);
16850  button->text_background = table[NK_COLOR_COMBO];
16851  button->text_normal = table[NK_COLOR_TEXT];
16852  button->text_hover = table[NK_COLOR_TEXT];
16853  button->text_active = table[NK_COLOR_TEXT];
16854  button->padding = nk_vec2(2.0f,2.0f);
16855  button->touch_padding = nk_vec2(0.0f,0.0f);
16856  button->userdata = nk_handle_ptr(0);
16857  button->text_alignment = NK_TEXT_CENTERED;
16858  button->border = 0.0f;
16859  button->rounding = 0.0f;
16860  button->draw_begin = 0;
16861  button->draw_end = 0;
16862 
16863  /* tab */
16864  tab = &style->tab;
16867  tab->text = table[NK_COLOR_TEXT];
16870  tab->padding = nk_vec2(4,4);
16871  tab->spacing = nk_vec2(4,4);
16872  tab->indent = 10.0f;
16873  tab->border = 1;
16874  tab->rounding = 0;
16875 
16876  /* tab button */
16877  button = &style->tab.tab_minimize_button;
16882  button->border_color = nk_rgba(0,0,0,0);
16883  button->text_background = table[NK_COLOR_TAB_HEADER];
16884  button->text_normal = table[NK_COLOR_TEXT];
16885  button->text_hover = table[NK_COLOR_TEXT];
16886  button->text_active = table[NK_COLOR_TEXT];
16887  button->padding = nk_vec2(2.0f,2.0f);
16888  button->touch_padding = nk_vec2(0.0f,0.0f);
16889  button->userdata = nk_handle_ptr(0);
16890  button->text_alignment = NK_TEXT_CENTERED;
16891  button->border = 0.0f;
16892  button->rounding = 0.0f;
16893  button->draw_begin = 0;
16894  button->draw_end = 0;
16895  style->tab.tab_maximize_button =*button;
16896 
16897  /* node button */
16898  button = &style->tab.node_minimize_button;
16903  button->border_color = nk_rgba(0,0,0,0);
16904  button->text_background = table[NK_COLOR_TAB_HEADER];
16905  button->text_normal = table[NK_COLOR_TEXT];
16906  button->text_hover = table[NK_COLOR_TEXT];
16907  button->text_active = table[NK_COLOR_TEXT];
16908  button->padding = nk_vec2(2.0f,2.0f);
16909  button->touch_padding = nk_vec2(0.0f,0.0f);
16910  button->userdata = nk_handle_ptr(0);
16911  button->text_alignment = NK_TEXT_CENTERED;
16912  button->border = 0.0f;
16913  button->rounding = 0.0f;
16914  button->draw_begin = 0;
16915  button->draw_end = 0;
16916  style->tab.node_maximize_button =*button;
16917 
16918  /* window header */
16919  win = &style->window;
16920  win->header.align = NK_HEADER_RIGHT;
16930  win->header.label_padding = nk_vec2(4,4);
16931  win->header.padding = nk_vec2(4,4);
16932  win->header.spacing = nk_vec2(0,0);
16933 
16934  /* window header close button */
16935  button = &style->window.header.close_button;
16940  button->border_color = nk_rgba(0,0,0,0);
16941  button->text_background = table[NK_COLOR_HEADER];
16942  button->text_normal = table[NK_COLOR_TEXT];
16943  button->text_hover = table[NK_COLOR_TEXT];
16944  button->text_active = table[NK_COLOR_TEXT];
16945  button->padding = nk_vec2(0.0f,0.0f);
16946  button->touch_padding = nk_vec2(0.0f,0.0f);
16947  button->userdata = nk_handle_ptr(0);
16948  button->text_alignment = NK_TEXT_CENTERED;
16949  button->border = 0.0f;
16950  button->rounding = 0.0f;
16951  button->draw_begin = 0;
16952  button->draw_end = 0;
16953 
16954  /* window header minimize button */
16955  button = &style->window.header.minimize_button;
16960  button->border_color = nk_rgba(0,0,0,0);
16961  button->text_background = table[NK_COLOR_HEADER];
16962  button->text_normal = table[NK_COLOR_TEXT];
16963  button->text_hover = table[NK_COLOR_TEXT];
16964  button->text_active = table[NK_COLOR_TEXT];
16965  button->padding = nk_vec2(0.0f,0.0f);
16966  button->touch_padding = nk_vec2(0.0f,0.0f);
16967  button->userdata = nk_handle_ptr(0);
16968  button->text_alignment = NK_TEXT_CENTERED;
16969  button->border = 0.0f;
16970  button->rounding = 0.0f;
16971  button->draw_begin = 0;
16972  button->draw_end = 0;
16973 
16974  /* window */
16985 
16986  win->rounding = 0.0f;
16987  win->spacing = nk_vec2(4,4);
16988  win->scrollbar_size = nk_vec2(10,10);
16989  win->min_size = nk_vec2(64,64);
16990 
16991  win->combo_border = 1.0f;
16992  win->contextual_border = 1.0f;
16993  win->menu_border = 1.0f;
16994  win->group_border = 1.0f;
16995  win->tooltip_border = 1.0f;
16996  win->popup_border = 1.0f;
16997  win->border = 2.0f;
16998  win->min_row_height_padding = 8;
16999 
17000  win->padding = nk_vec2(4,4);
17001  win->group_padding = nk_vec2(4,4);
17002  win->popup_padding = nk_vec2(4,4);
17003  win->combo_padding = nk_vec2(4,4);
17004  win->contextual_padding = nk_vec2(4,4);
17005  win->menu_padding = nk_vec2(4,4);
17006  win->tooltip_padding = nk_vec2(4,4);
17007 }
17008 
17009 NK_API void
17010 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font)
17011 {
17012  struct nk_style *style;
17013  NK_ASSERT(ctx);
17014 
17015  if (!ctx) return;
17016  style = &ctx->style;
17017  style->font = font;
17018  ctx->stacks.fonts.head = 0;
17019  if (ctx->current)
17021 }
17022 
17023 NK_API int
17024 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font)
17025 {
17026  struct nk_config_stack_user_font *font_stack;
17027  struct nk_config_stack_user_font_element *element;
17028 
17029  NK_ASSERT(ctx);
17030  if (!ctx) return 0;
17031 
17032  font_stack = &ctx->stacks.fonts;
17033  NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements));
17034  if (font_stack->head >= (int)NK_LEN(font_stack->elements))
17035  return 0;
17036 
17037  element = &font_stack->elements[font_stack->head++];
17038  element->address = &ctx->style.font;
17039  element->old_value = ctx->style.font;
17040  ctx->style.font = font;
17041  return 1;
17042 }
17043 
17044 NK_API int
17046 {
17047  struct nk_config_stack_user_font *font_stack;
17048  struct nk_config_stack_user_font_element *element;
17049 
17050  NK_ASSERT(ctx);
17051  if (!ctx) return 0;
17052 
17053  font_stack = &ctx->stacks.fonts;
17054  NK_ASSERT(font_stack->head > 0);
17055  if (font_stack->head < 1)
17056  return 0;
17057 
17058  element = &font_stack->elements[--font_stack->head];
17059  *element->address = element->old_value;
17060  return 1;
17061 }
17062 
17063 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \
17064 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\
17065 {\
17066  struct nk_config_stack_##type * type_stack;\
17067  struct nk_config_stack_##type##_element *element;\
17068  NK_ASSERT(ctx);\
17069  if (!ctx) return 0;\
17070  type_stack = &ctx->stacks.stack;\
17071  NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\
17072  if (type_stack->head >= (int)NK_LEN(type_stack->elements))\
17073  return 0;\
17074  element = &type_stack->elements[type_stack->head++];\
17075  element->address = address;\
17076  element->old_value = *address;\
17077  *address = value;\
17078  return 1;\
17079 }
17080 
17081 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \
17082 nk_style_pop_##type(struct nk_context *ctx)\
17083 {\
17084  struct nk_config_stack_##type *type_stack;\
17085  struct nk_config_stack_##type##_element *element;\
17086  NK_ASSERT(ctx);\
17087  if (!ctx) return 0;\
17088  type_stack = &ctx->stacks.stack;\
17089  NK_ASSERT(type_stack->head > 0);\
17090  if (type_stack->head < 1)\
17091  return 0;\
17092  element = &type_stack->elements[--type_stack->head];\
17093  *element->address = element->old_value;\
17094  return 1;\
17095 }
17096 
17097 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items)
17098 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats)
17099 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors)
17100 NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags)
17101 NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors)
17102 
17103 NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items)
17104 NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats)
17105 NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors)
17106 NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags)
17107 NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors)
17108 
17109 NK_API int
17111 {
17112  struct nk_style *style;
17113  NK_ASSERT(ctx);
17114  if (!ctx) return 0;
17115  style = &ctx->style;
17116  if (style->cursors[c]) {
17117  style->cursor_active = style->cursors[c];
17118  return 1;
17119  }
17120  return 0;
17121 }
17122 
17123 NK_API void
17125 {
17126  ctx->style.cursor_visible = nk_true;
17127 }
17128 
17129 NK_API void
17131 {
17132  ctx->style.cursor_visible = nk_false;
17133 }
17134 
17135 NK_API void
17136 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor,
17137  const struct nk_cursor *c)
17138 {
17139  struct nk_style *style;
17140  NK_ASSERT(ctx);
17141  if (!ctx) return;
17142  style = &ctx->style;
17143  style->cursors[cursor] = c;
17144 }
17145 
17146 NK_API void
17148 {
17149  int i = 0;
17150  struct nk_style *style;
17151  NK_ASSERT(ctx);
17152  if (!ctx) return;
17153  style = &ctx->style;
17154  for (i = 0; i < NK_CURSOR_COUNT; ++i)
17155  style->cursors[i] = &cursors[i];
17156  style->cursor_visible = nk_true;
17157 }
17158 
17159 /* ===============================================================
17160  *
17161  * POOL
17162  *
17163  * ===============================================================*/
17164 NK_INTERN void
17165 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc,
17166  unsigned int capacity)
17167 {
17168  nk_zero(pool, sizeof(*pool));
17169  pool->alloc = *alloc;
17170  pool->capacity = capacity;
17171  pool->type = NK_BUFFER_DYNAMIC;
17172  pool->pages = 0;
17173 }
17174 
17175 NK_INTERN void
17176 nk_pool_free(struct nk_pool *pool)
17177 {
17178  struct nk_page *iter = pool->pages;
17179  if (!pool) return;
17180  if (pool->type == NK_BUFFER_FIXED) return;
17181  while (iter) {
17182  struct nk_page *next = iter->next;
17183  pool->alloc.free(pool->alloc.userdata, iter);
17184  iter = next;
17185  }
17186 }
17187 
17188 NK_INTERN void
17189 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size)
17190 {
17191  nk_zero(pool, sizeof(*pool));
17192  NK_ASSERT(size >= sizeof(struct nk_page));
17193  if (size < sizeof(struct nk_page)) return;
17194  pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element);
17195  pool->pages = (struct nk_page*)memory;
17196  pool->type = NK_BUFFER_FIXED;
17197  pool->size = size;
17198 }
17199 
17200 NK_INTERN struct nk_page_element*
17201 nk_pool_alloc(struct nk_pool *pool)
17202 {
17203  if (!pool->pages || pool->pages->size >= pool->capacity) {
17204  /* allocate new page */
17205  struct nk_page *page;
17206  if (pool->type == NK_BUFFER_FIXED) {
17207  if (!pool->pages) {
17208  NK_ASSERT(pool->pages);
17209  return 0;
17210  }
17211  NK_ASSERT(pool->pages->size < pool->capacity);
17212  return 0;
17213  } else {
17214  nk_size size = sizeof(struct nk_page);
17215  size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data);
17216  page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size);
17217  page->next = pool->pages;
17218  pool->pages = page;
17219  page->size = 0;
17220  }
17221  }
17222  return &pool->pages->win[pool->pages->size++];
17223 }
17224 
17225 /* ===============================================================
17226  *
17227  * CONTEXT
17228  *
17229  * ===============================================================*/
17230 NK_INTERN void* nk_create_window(struct nk_context *ctx);
17231 NK_INTERN void nk_remove_window(struct nk_context*, struct nk_window*);
17232 NK_INTERN void nk_free_window(struct nk_context *ctx, struct nk_window *win);
17233 NK_INTERN void nk_free_table(struct nk_context *ctx, struct nk_table *tbl);
17234 NK_INTERN void nk_remove_table(struct nk_window *win, struct nk_table *tbl);
17235 NK_INTERN void* nk_create_panel(struct nk_context *ctx);
17236 NK_INTERN void nk_free_panel(struct nk_context*, struct nk_panel *pan);
17237 
17238 NK_INTERN void
17239 nk_setup(struct nk_context *ctx, const struct nk_user_font *font)
17240 {
17241  NK_ASSERT(ctx);
17242  if (!ctx) return;
17243  nk_zero_struct(*ctx);
17245  ctx->seq = 1;
17246  if (font) ctx->style.font = font;
17247 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
17248  nk_draw_list_init(&ctx->draw_list);
17249 #endif
17250 }
17251 
17252 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR
17253 NK_API int
17254 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font)
17255 {
17256  struct nk_allocator alloc;
17257  alloc.userdata.ptr = 0;
17258  alloc.alloc = nk_malloc;
17259  alloc.free = nk_mfree;
17260  return nk_init(ctx, &alloc, font);
17261 }
17262 #endif
17263 
17264 NK_API int
17265 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size,
17266  const struct nk_user_font *font)
17267 {
17268  NK_ASSERT(memory);
17269  if (!memory) return 0;
17270  nk_setup(ctx, font);
17271  nk_buffer_init_fixed(&ctx->memory, memory, size);
17272  ctx->use_pool = nk_false;
17273  return 1;
17274 }
17275 
17276 NK_API int
17277 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds,
17278  struct nk_buffer *pool, const struct nk_user_font *font)
17279 {
17280  NK_ASSERT(cmds);
17281  NK_ASSERT(pool);
17282  if (!cmds || !pool) return 0;
17283 
17284  nk_setup(ctx, font);
17285  ctx->memory = *cmds;
17286  if (pool->type == NK_BUFFER_FIXED) {
17287  /* take memory from buffer and alloc fixed pool */
17288  nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size);
17289  } else {
17290  /* create dynamic pool from buffer allocator */
17291  struct nk_allocator *alloc = &pool->pool;
17292  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
17293  }
17294  ctx->use_pool = nk_true;
17295  return 1;
17296 }
17297 
17298 NK_API int
17299 nk_init(struct nk_context *ctx, struct nk_allocator *alloc,
17300  const struct nk_user_font *font)
17301 {
17302  NK_ASSERT(alloc);
17303  if (!alloc) return 0;
17304  nk_setup(ctx, font);
17305  nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE);
17306  nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY);
17307  ctx->use_pool = nk_true;
17308  return 1;
17309 }
17310 
17311 #ifdef NK_INCLUDE_COMMAND_USERDATA
17312 NK_API void
17313 nk_set_user_data(struct nk_context *ctx, nk_handle handle)
17314 {
17315  if (!ctx) return;
17316  ctx->userdata = handle;
17317  if (ctx->current)
17318  ctx->current->buffer.userdata = handle;
17319 }
17320 #endif
17321 
17322 NK_API void
17323 nk_free(struct nk_context *ctx)
17324 {
17325  NK_ASSERT(ctx);
17326  if (!ctx) return;
17327  nk_buffer_free(&ctx->memory);
17328  if (ctx->use_pool)
17329  nk_pool_free(&ctx->pool);
17330 
17331  nk_zero(&ctx->input, sizeof(ctx->input));
17332  nk_zero(&ctx->style, sizeof(ctx->style));
17333  nk_zero(&ctx->memory, sizeof(ctx->memory));
17334 
17335  ctx->seq = 0;
17336  ctx->build = 0;
17337  ctx->begin = 0;
17338  ctx->end = 0;
17339  ctx->active = 0;
17340  ctx->current = 0;
17341  ctx->freelist = 0;
17342  ctx->count = 0;
17343 }
17344 
17345 NK_API void
17346 nk_clear(struct nk_context *ctx)
17347 {
17348  struct nk_window *iter;
17349  struct nk_window *next;
17350  NK_ASSERT(ctx);
17351 
17352  if (!ctx) return;
17353  if (ctx->use_pool)
17354  nk_buffer_clear(&ctx->memory);
17355  else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT);
17356 
17357  ctx->build = 0;
17358  ctx->memory.calls = 0;
17359  ctx->last_widget_state = 0;
17360  ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
17361  NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay));
17362 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT
17363  nk_draw_list_clear(&ctx->draw_list);
17364 #endif
17365 
17366  /* garbage collector */
17367  iter = ctx->begin;
17368  while (iter) {
17369  /* make sure minimized windows do not get removed */
17370  if ((iter->flags & NK_WINDOW_MINIMIZED) &&
17371  !(iter->flags & NK_WINDOW_CLOSED)) {
17372  iter = iter->next;
17373  continue;
17374  }
17375  /* remove hotness from hidden or closed windows*/
17376  if (((iter->flags & NK_WINDOW_HIDDEN) ||
17377  (iter->flags & NK_WINDOW_CLOSED)) &&
17378  iter == ctx->active) {
17379  ctx->active = iter->prev;
17380  ctx->end = iter->prev;
17381  if (ctx->active)
17382  ctx->active->flags &= ~NK_WINDOW_ROM;
17383  }
17384 
17385  /* free unused popup windows */
17386  if (iter->popup.win && iter->popup.win->seq != ctx->seq) {
17387  nk_free_window(ctx, iter->popup.win);
17388  iter->popup.win = 0;
17389  }
17390  /* remove unused window state tables */
17391  {struct nk_table *n, *it = iter->tables;
17392  while (it) {
17393  n = it->next;
17394  if (it->seq != ctx->seq) {
17395  nk_remove_table(iter, it);
17396  nk_zero(it, sizeof(union nk_page_data));
17397  nk_free_table(ctx, it);
17398  if (it == iter->tables)
17399  iter->tables = n;
17400  }
17401  it = n;
17402  }}
17403  /* window itself is not used anymore so free */
17404  if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) {
17405  next = iter->next;
17406  nk_remove_window(ctx, iter);
17407  nk_free_window(ctx, iter);
17408  iter = next;
17409  } else iter = iter->next;
17410  }
17411  ctx->seq++;
17412 }
17413 
17414 /* ----------------------------------------------------------------
17415  *
17416  * BUFFERING
17417  *
17418  * ---------------------------------------------------------------*/
17419 NK_INTERN void
17420 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
17421 {
17422  NK_ASSERT(ctx);
17423  NK_ASSERT(buffer);
17424  if (!ctx || !buffer) return;
17425  buffer->begin = ctx->memory.allocated;
17426  buffer->end = buffer->begin;
17427  buffer->last = buffer->begin;
17428  buffer->clip = nk_null_rect;
17429 }
17430 
17431 NK_INTERN void
17432 nk_start(struct nk_context *ctx, struct nk_window *win)
17433 {
17434  NK_ASSERT(ctx);
17435  NK_ASSERT(win);
17436  nk_start_buffer(ctx, &win->buffer);
17437 }
17438 
17439 NK_INTERN void
17440 nk_start_popup(struct nk_context *ctx, struct nk_window *win)
17441 {
17442  struct nk_popup_buffer *buf;
17443  NK_ASSERT(ctx);
17444  NK_ASSERT(win);
17445  if (!ctx || !win) return;
17446 
17447  /* save buffer fill state for popup */
17448  buf = &win->popup.buf;
17449  buf->begin = win->buffer.end;
17450  buf->end = win->buffer.end;
17451  buf->parent = win->buffer.last;
17452  buf->last = buf->begin;
17453  buf->active = nk_true;
17454 }
17455 
17456 NK_INTERN void
17457 nk_finish_popup(struct nk_context *ctx, struct nk_window *win)
17458 {
17459  struct nk_popup_buffer *buf;
17460  NK_ASSERT(ctx);
17461  NK_ASSERT(win);
17462  if (!ctx || !win) return;
17463 
17464  buf = &win->popup.buf;
17465  buf->last = win->buffer.last;
17466  buf->end = win->buffer.end;
17467 }
17468 
17469 NK_INTERN void
17470 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer)
17471 {
17472  NK_ASSERT(ctx);
17473  NK_ASSERT(buffer);
17474  if (!ctx || !buffer) return;
17475  buffer->end = ctx->memory.allocated;
17476 }
17477 
17478 NK_INTERN void
17479 nk_finish(struct nk_context *ctx, struct nk_window *win)
17480 {
17481  struct nk_popup_buffer *buf;
17482  struct nk_command *parent_last;
17483  void *memory;
17484 
17485  NK_ASSERT(ctx);
17486  NK_ASSERT(win);
17487  if (!ctx || !win) return;
17488  nk_finish_buffer(ctx, &win->buffer);
17489  if (!win->popup.buf.active) return;
17490 
17491  buf = &win->popup.buf;
17492  memory = ctx->memory.memory.ptr;
17493  parent_last = nk_ptr_add(struct nk_command, memory, buf->parent);
17494  parent_last->next = buf->end;
17495 }
17496 
17497 NK_INTERN void
17498 nk_build(struct nk_context *ctx)
17499 {
17500  struct nk_window *iter = 0;
17501  struct nk_command *cmd = 0;
17502  nk_byte *buffer = 0;
17503 
17504  /* draw cursor overlay */
17505  if (!ctx->style.cursor_active)
17506  ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW];
17507  if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) {
17508  struct nk_rect mouse_bounds;
17509  const struct nk_cursor *cursor = ctx->style.cursor_active;
17510  nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF);
17511  nk_start_buffer(ctx, &ctx->overlay);
17512 
17513  mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x;
17514  mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y;
17515  mouse_bounds.w = cursor->size.x;
17516  mouse_bounds.h = cursor->size.y;
17517 
17518  nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white);
17519  nk_finish_buffer(ctx, &ctx->overlay);
17520  }
17521  /* build one big draw command list out of all window buffers */
17522  iter = ctx->begin;
17523  buffer = (nk_byte*)ctx->memory.memory.ptr;
17524  while (iter != 0) {
17525  struct nk_window *next = iter->next;
17526  if (iter->buffer.last == iter->buffer.begin || (iter->flags & NK_WINDOW_HIDDEN)||
17527  iter->seq != ctx->seq)
17528  goto cont;
17529 
17530  cmd = nk_ptr_add(struct nk_command, buffer, iter->buffer.last);
17531  while (next && ((next->buffer.last == next->buffer.begin) ||
17532  (next->flags & NK_WINDOW_HIDDEN)))
17533  next = next->next; /* skip empty command buffers */
17534 
17535  if (next) cmd->next = next->buffer.begin;
17536  cont: iter = next;
17537  }
17538  /* append all popup draw commands into lists */
17539  iter = ctx->begin;
17540  while (iter != 0) {
17541  struct nk_window *next = iter->next;
17542  struct nk_popup_buffer *buf;
17543  if (!iter->popup.buf.active)
17544  goto skip;
17545 
17546  buf = &iter->popup.buf;
17547  cmd->next = buf->begin;
17548  cmd = nk_ptr_add(struct nk_command, buffer, buf->last);
17549  buf->active = nk_false;
17550  skip: iter = next;
17551  }
17552  /* append overlay commands */
17553  if (cmd) {
17554  if (ctx->overlay.end != ctx->overlay.begin)
17555  cmd->next = ctx->overlay.begin;
17556  else cmd->next = ctx->memory.allocated;
17557  }
17558 }
17559 
17560 NK_API const struct nk_command*
17561 nk__begin(struct nk_context *ctx)
17562 {
17563  struct nk_window *iter;
17564  nk_byte *buffer;
17565  NK_ASSERT(ctx);
17566  if (!ctx) return 0;
17567  if (!ctx->count) return 0;
17568 
17569  buffer = (nk_byte*)ctx->memory.memory.ptr;
17570  if (!ctx->build) {
17571  nk_build(ctx);
17572  ctx->build = nk_true;
17573  }
17574  iter = ctx->begin;
17575  while (iter && ((iter->buffer.begin == iter->buffer.end) || (iter->flags & NK_WINDOW_HIDDEN)))
17576  iter = iter->next;
17577  if (!iter) return 0;
17578  return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin);
17579 }
17580 
17581 NK_API const struct nk_command*
17582 nk__next(struct nk_context *ctx, const struct nk_command *cmd)
17583 {
17584  nk_byte *buffer;
17585  const struct nk_command *next;
17586  NK_ASSERT(ctx);
17587  if (!ctx || !cmd || !ctx->count) return 0;
17588  if (cmd->next >= ctx->memory.allocated) return 0;
17589  buffer = (nk_byte*)ctx->memory.memory.ptr;
17590  next = nk_ptr_add_const(struct nk_command, buffer, cmd->next);
17591  return next;
17592 }
17593 
17594 /* ----------------------------------------------------------------
17595  *
17596  * PANEL
17597  *
17598  * ---------------------------------------------------------------*/
17599 static int
17600 nk_panel_has_header(nk_flags flags, const char *title)
17601 {
17602  int active = 0;
17604  active = active || (flags & NK_WINDOW_TITLE);
17605  active = active && !(flags & NK_WINDOW_HIDDEN) && title;
17606  return active;
17607 }
17608 
17609 NK_INTERN struct nk_vec2
17610 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type)
17611 {
17612  switch (type) {
17613  default:
17614  case NK_PANEL_WINDOW: return style->window.padding;
17615  case NK_PANEL_GROUP: return style->window.group_padding;
17616  case NK_PANEL_POPUP: return style->window.popup_padding;
17617  case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding;
17618  case NK_PANEL_COMBO: return style->window.combo_padding;
17619  case NK_PANEL_MENU: return style->window.menu_padding;
17620  case NK_PANEL_TOOLTIP: return style->window.menu_padding;
17621  }
17622 }
17623 
17624 NK_INTERN float
17625 nk_panel_get_border(const struct nk_style *style, nk_flags flags,
17626  enum nk_panel_type type)
17627 {
17628  if (flags & NK_WINDOW_BORDER) {
17629  switch (type) {
17630  default:
17631  case NK_PANEL_WINDOW: return style->window.border;
17632  case NK_PANEL_GROUP: return style->window.group_border;
17633  case NK_PANEL_POPUP: return style->window.popup_border;
17634  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border;
17635  case NK_PANEL_COMBO: return style->window.combo_border;
17636  case NK_PANEL_MENU: return style->window.menu_border;
17637  case NK_PANEL_TOOLTIP: return style->window.menu_border;
17638  }} else return 0;
17639 }
17640 
17641 NK_INTERN struct nk_color
17642 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type)
17643 {
17644  switch (type) {
17645  default:
17646  case NK_PANEL_WINDOW: return style->window.border_color;
17647  case NK_PANEL_GROUP: return style->window.group_border_color;
17648  case NK_PANEL_POPUP: return style->window.popup_border_color;
17649  case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color;
17650  case NK_PANEL_COMBO: return style->window.combo_border_color;
17651  case NK_PANEL_MENU: return style->window.menu_border_color;
17652  case NK_PANEL_TOOLTIP: return style->window.menu_border_color;
17653  }
17654 }
17655 
17656 NK_INTERN int
17657 nk_panel_is_sub(enum nk_panel_type type)
17658 {
17659  return (type & NK_PANEL_SET_SUB)?1:0;
17660 }
17661 
17662 NK_INTERN int
17663 nk_panel_is_nonblock(enum nk_panel_type type)
17664 {
17665  return (type & NK_PANEL_SET_NONBLOCK)?1:0;
17666 }
17667 
17668 NK_INTERN int
17669 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type)
17670 {
17671  struct nk_input *in;
17672  struct nk_window *win;
17673  struct nk_panel *layout;
17674  struct nk_command_buffer *out;
17675  const struct nk_style *style;
17676  const struct nk_user_font *font;
17677 
17678  struct nk_vec2 scrollbar_size;
17679  struct nk_vec2 panel_padding;
17680 
17681  NK_ASSERT(ctx);
17682  NK_ASSERT(ctx->current);
17683  NK_ASSERT(ctx->current->layout);
17684  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
17685  nk_zero(ctx->current->layout, sizeof(*ctx->current->layout));
17686  if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) {
17687  nk_zero(ctx->current->layout, sizeof(struct nk_panel));
17688  ctx->current->layout->type = panel_type;
17689  return 0;
17690  }
17691  /* pull state into local stack */
17692  style = &ctx->style;
17693  font = style->font;
17694  win = ctx->current;
17695  layout = win->layout;
17696  out = &win->buffer;
17697  in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input;
17698 #ifdef NK_INCLUDE_COMMAND_USERDATA
17699  win->buffer.userdata = ctx->userdata;
17700 #endif
17701  /* pull style configuration into local stack */
17702  scrollbar_size = style->window.scrollbar_size;
17703  panel_padding = nk_panel_get_padding(style, panel_type);
17704 
17705  /* window movement */
17706  if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) {
17707  int left_mouse_down;
17708  int left_mouse_click_in_cursor;
17709 
17710  /* calculate draggable window space */
17711  struct nk_rect header;
17712  header.x = win->bounds.x;
17713  header.y = win->bounds.y;
17714  header.w = win->bounds.w;
17715  if (nk_panel_has_header(win->flags, title)) {
17716  header.h = font->height + 2.0f * style->window.header.padding.y;
17717  header.h += 2.0f * style->window.header.label_padding.y;
17718  } else header.h = panel_padding.y;
17719 
17720  /* window movement by dragging */
17721  left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
17722  left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in,
17723  NK_BUTTON_LEFT, header, nk_true);
17724  if (left_mouse_down && left_mouse_click_in_cursor) {
17725  win->bounds.x = win->bounds.x + in->mouse.delta.x;
17726  win->bounds.y = win->bounds.y + in->mouse.delta.y;
17727  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x;
17728  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y;
17729  ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE];
17730  }
17731  }
17732 
17733  /* setup panel */
17734  layout->type = panel_type;
17735  layout->flags = win->flags;
17736  layout->bounds = win->bounds;
17737  layout->bounds.x += panel_padding.x;
17738  layout->bounds.w -= 2*panel_padding.x;
17739  if (win->flags & NK_WINDOW_BORDER) {
17740  layout->border = nk_panel_get_border(style, win->flags, panel_type);
17741  layout->bounds = nk_shrink_rect(layout->bounds, layout->border);
17742  } else layout->border = 0;
17743  layout->at_y = layout->bounds.y;
17744  layout->at_x = layout->bounds.x;
17745  layout->max_x = 0;
17746  layout->header_height = 0;
17747  layout->footer_height = 0;
17749  layout->row.index = 0;
17750  layout->row.columns = 0;
17751  layout->row.ratio = 0;
17752  layout->row.item_width = 0;
17753  layout->row.tree_depth = 0;
17754  layout->row.height = panel_padding.y;
17755  layout->has_scrolling = nk_true;
17756  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR))
17757  layout->bounds.w -= scrollbar_size.x;
17758  if (!nk_panel_is_nonblock(panel_type)) {
17759  layout->footer_height = 0;
17760  if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE)
17761  layout->footer_height = scrollbar_size.y;
17762  layout->bounds.h -= layout->footer_height;
17763  }
17764 
17765  /* panel header */
17766  if (nk_panel_has_header(win->flags, title))
17767  {
17768  struct nk_text text;
17769  struct nk_rect header;
17770  const struct nk_style_item *background = 0;
17771 
17772  /* calculate header bounds */
17773  header.x = win->bounds.x;
17774  header.y = win->bounds.y;
17775  header.w = win->bounds.w;
17776  header.h = font->height + 2.0f * style->window.header.padding.y;
17777  header.h += (2.0f * style->window.header.label_padding.y);
17778 
17779  /* shrink panel by header */
17780  layout->header_height = header.h;
17781  layout->bounds.y += header.h;
17782  layout->bounds.h -= header.h;
17783  layout->at_y += header.h;
17784 
17785  /* select correct header background and text color */
17786  if (ctx->active == win) {
17787  background = &style->window.header.active;
17788  text.text = style->window.header.label_active;
17789  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) {
17790  background = &style->window.header.hover;
17791  text.text = style->window.header.label_hover;
17792  } else {
17793  background = &style->window.header.normal;
17794  text.text = style->window.header.label_normal;
17795  }
17796 
17797  /* draw header background */
17798  header.h += 1.0f;
17799  if (background->type == NK_STYLE_ITEM_IMAGE) {
17800  text.background = nk_rgba(0,0,0,0);
17801  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
17802  } else {
17803  text.background = background->data.color;
17804  nk_fill_rect(out, header, 0, background->data.color);
17805  }
17806 
17807  /* window close button */
17808  {struct nk_rect button;
17809  button.y = header.y + style->window.header.padding.y;
17810  button.h = header.h - 2 * style->window.header.padding.y;
17811  button.w = button.h;
17812  if (win->flags & NK_WINDOW_CLOSABLE) {
17813  nk_flags ws = 0;
17814  if (style->window.header.align == NK_HEADER_RIGHT) {
17815  button.x = (header.w + header.x) - (button.w + style->window.header.padding.x);
17816  header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x;
17817  } else {
17818  button.x = header.x + style->window.header.padding.x;
17819  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
17820  }
17821 
17822  if (nk_do_button_symbol(&ws, &win->buffer, button,
17824  &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
17825  {
17826  layout->flags |= NK_WINDOW_HIDDEN;
17827  layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED;
17828  }
17829  }
17830 
17831  /* window minimize button */
17832  if (win->flags & NK_WINDOW_MINIMIZABLE) {
17833  nk_flags ws = 0;
17834  if (style->window.header.align == NK_HEADER_RIGHT) {
17835  button.x = (header.w + header.x) - button.w;
17836  if (!(win->flags & NK_WINDOW_CLOSABLE)) {
17837  button.x -= style->window.header.padding.x;
17838  header.w -= style->window.header.padding.x;
17839  }
17840  header.w -= button.w + style->window.header.spacing.x;
17841  } else {
17842  button.x = header.x;
17843  header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x;
17844  }
17845  if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)?
17847  NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM))
17848  layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ?
17849  layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED:
17850  layout->flags | NK_WINDOW_MINIMIZED;
17851  }}
17852 
17853  {/* window header title */
17854  int text_len = nk_strlen(title);
17855  struct nk_rect label = {0,0,0,0};
17856  float t = font->width(font->userdata, font->height, title, text_len);
17857  text.padding = nk_vec2(0,0);
17858 
17859  label.x = header.x + style->window.header.padding.x;
17860  label.x += style->window.header.label_padding.x;
17861  label.y = header.y + style->window.header.label_padding.y;
17862  label.h = font->height + 2 * style->window.header.label_padding.y;
17863  label.w = t + 2 * style->window.header.spacing.x;
17864  label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x);
17865  nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);}
17866  }
17867 
17868  /* draw window background */
17869  if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) {
17870  struct nk_rect body;
17871  body.x = win->bounds.x;
17872  body.w = win->bounds.w;
17873  body.y = (win->bounds.y + layout->header_height);
17874  body.h = (win->bounds.h - layout->header_height);
17876  nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white);
17878  }
17879 
17880  /* set clipping rectangle */
17881  {struct nk_rect clip;
17882  layout->clip = layout->bounds;
17883  nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y,
17884  layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h);
17885  nk_push_scissor(out, clip);
17886  layout->clip = clip;}
17887  return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED);
17888 }
17889 
17890 NK_INTERN void
17891 nk_panel_end(struct nk_context *ctx)
17892 {
17893  struct nk_input *in;
17894  struct nk_window *window;
17895  struct nk_panel *layout;
17896  const struct nk_style *style;
17897  struct nk_command_buffer *out;
17898 
17899  struct nk_vec2 scrollbar_size;
17900  struct nk_vec2 panel_padding;
17901 
17902  NK_ASSERT(ctx);
17903  NK_ASSERT(ctx->current);
17904  NK_ASSERT(ctx->current->layout);
17905  if (!ctx || !ctx->current || !ctx->current->layout)
17906  return;
17907 
17908  window = ctx->current;
17909  layout = window->layout;
17910  style = &ctx->style;
17911  out = &window->buffer;
17912  in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input;
17913  if (!nk_panel_is_sub(layout->type))
17914  nk_push_scissor(out, nk_null_rect);
17915 
17916  /* cache configuration data */
17917  scrollbar_size = style->window.scrollbar_size;
17918  panel_padding = nk_panel_get_padding(style, layout->type);
17919 
17920  /* update the current cursor Y-position to point over the last added widget */
17921  layout->at_y += layout->row.height;
17922 
17923  /* dynamic panels */
17924  if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED))
17925  {
17926  /* update panel height to fit dynamic growth */
17927  struct nk_rect empty_space;
17928  if (layout->at_y < (layout->bounds.y + layout->bounds.h))
17929  layout->bounds.h = layout->at_y - layout->bounds.y;
17930 
17931  /* fill top empty space */
17932  empty_space.x = window->bounds.x;
17933  empty_space.y = layout->bounds.y;
17934  empty_space.h = panel_padding.y;
17935  empty_space.w = window->bounds.w;
17936  nk_fill_rect(out, empty_space, 0, style->window.background);
17937 
17938  /* fill left empty space */
17939  empty_space.x = window->bounds.x;
17940  empty_space.y = layout->bounds.y;
17941  empty_space.w = panel_padding.x + layout->border;
17942  empty_space.h = layout->bounds.h;
17943  nk_fill_rect(out, empty_space, 0, style->window.background);
17944 
17945  /* fill right empty space */
17946  empty_space.x = layout->bounds.x + layout->bounds.w - layout->border;
17947  empty_space.y = layout->bounds.y;
17948  empty_space.w = panel_padding.x + layout->border;
17949  empty_space.h = layout->bounds.h;
17950  if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR))
17951  empty_space.w += scrollbar_size.x;
17952  nk_fill_rect(out, empty_space, 0, style->window.background);
17953 
17954  /* fill bottom empty space */
17955  if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) {
17956  empty_space.x = window->bounds.x;
17957  empty_space.y = layout->bounds.y + layout->bounds.h;
17958  empty_space.w = window->bounds.w;
17959  empty_space.h = scrollbar_size.y;
17960  nk_fill_rect(out, empty_space, 0, style->window.background);
17961  }
17962  }
17963 
17964  /* scrollbars */
17965  if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) &&
17966  !(layout->flags & NK_WINDOW_MINIMIZED) &&
17967  window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT)
17968  {
17969  struct nk_rect scroll;
17970  int scroll_has_scrolling;
17971  float scroll_target;
17972  float scroll_offset;
17973  float scroll_step;
17974  float scroll_inc;
17975 
17976  /* mouse wheel scrolling */
17977  if (nk_panel_is_sub(layout->type))
17978  {
17979  /* sub-window mouse wheel scrolling */
17980  struct nk_window *root_window = window;
17981  struct nk_panel *root_panel = window->layout;
17982  while (root_panel->parent)
17983  root_panel = root_panel->parent;
17984  while (root_window->parent)
17985  root_window = root_window->parent;
17986 
17987  /* only allow scrolling if parent window is active */
17988  scroll_has_scrolling = 0;
17989  if ((root_window == ctx->active) && layout->has_scrolling) {
17990  /* and panel is being hovered and inside clip rect*/
17991  if (nk_input_is_mouse_hovering_rect(in, layout->bounds) &&
17992  NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h,
17993  root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h))
17994  {
17995  /* deactivate all parent scrolling */
17996  root_panel = window->layout;
17997  while (root_panel->parent) {
17998  root_panel->has_scrolling = nk_false;
17999  root_panel = root_panel->parent;
18000  }
18001  root_panel->has_scrolling = nk_false;
18002  scroll_has_scrolling = nk_true;
18003  }
18004  }
18005  } else if (!nk_panel_is_sub(layout->type)) {
18006  /* window mouse wheel scrolling */
18007  scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling;
18008  if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling)
18009  window->scrolled = nk_true;
18010  else window->scrolled = nk_false;
18011  } else scroll_has_scrolling = nk_false;
18012 
18013  {
18014  /* vertical scrollbar */
18015  nk_flags state = 0;
18016  scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
18017  scroll.y = layout->bounds.y;
18018  scroll.w = scrollbar_size.x;
18019  scroll.h = layout->bounds.h;
18020 
18021  scroll_offset = (float)*layout->offset_y;
18022  scroll_step = scroll.h * 0.10f;
18023  scroll_inc = scroll.h * 0.01f;
18024  scroll_target = (float)(int)(layout->at_y - scroll.y);
18025  scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling,
18026  scroll_offset, scroll_target, scroll_step, scroll_inc,
18027  &ctx->style.scrollv, in, style->font);
18028  *layout->offset_y = (nk_uint)scroll_offset;
18029  if (in && scroll_has_scrolling)
18030  in->mouse.scroll_delta.y = 0;
18031  }
18032  {
18033  /* horizontal scrollbar */
18034  nk_flags state = 0;
18035  scroll.x = layout->bounds.x;
18036  scroll.y = layout->bounds.y + layout->bounds.h;
18037  scroll.w = layout->bounds.w;
18038  scroll.h = scrollbar_size.y;
18039 
18040  scroll_offset = (float)*layout->offset_x;
18041  scroll_target = (float)(int)(layout->max_x - scroll.x);
18042  scroll_step = layout->max_x * 0.05f;
18043  scroll_inc = layout->max_x * 0.005f;
18044  scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling,
18045  scroll_offset, scroll_target, scroll_step, scroll_inc,
18046  &ctx->style.scrollh, in, style->font);
18047  *layout->offset_x = (nk_uint)scroll_offset;
18048  }
18049  }
18050 
18051  /* hide scroll if no user input */
18052  if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) {
18053  int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0;
18054  int is_window_hovered = nk_window_is_hovered(ctx);
18055  int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
18056  if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active))
18057  window->scrollbar_hiding_timer += ctx->delta_time_seconds;
18058  else window->scrollbar_hiding_timer = 0;
18059  } else window->scrollbar_hiding_timer = 0;
18060 
18061  /* window border */
18062  if (layout->flags & NK_WINDOW_BORDER)
18063  {
18064  struct nk_color border_color = nk_panel_get_border_color(style, layout->type);
18065  const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) ?
18066  style->window.border + window->bounds.y + layout->header_height:
18067  (layout->flags & NK_WINDOW_DYNAMIC)?
18068  layout->bounds.y + layout->bounds.h + layout->footer_height:
18069  window->bounds.y + window->bounds.h;
18070 
18071  /* draw border top */
18072  nk_stroke_line(out,window->bounds.x,window->bounds.y,
18073  window->bounds.x + window->bounds.w, window->bounds.y,
18074  layout->border, border_color);
18075 
18076  /* draw bottom border */
18077  nk_stroke_line(out, window->bounds.x, padding_y,
18078  window->bounds.x + window->bounds.w, padding_y, layout->border, border_color);
18079 
18080  /* draw left border */
18081  nk_stroke_line(out, window->bounds.x + layout->border*0.5f,
18082  window->bounds.y, window->bounds.x + layout->border*0.5f,
18083  padding_y, layout->border, border_color);
18084 
18085  /* draw right border */
18086  nk_stroke_line(out, window->bounds.x + window->bounds.w - layout->border*0.5f,
18087  window->bounds.y, window->bounds.x + window->bounds.w - layout->border*0.5f,
18088  padding_y, layout->border, border_color);
18089  }
18090 
18091  /* scaler */
18092  if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED))
18093  {
18094  /* calculate scaler bounds */
18095  struct nk_rect scaler;
18096  scaler.w = scrollbar_size.x;
18097  scaler.h = scrollbar_size.y;
18098  scaler.y = layout->bounds.y + layout->bounds.h;
18099  if (layout->flags & NK_WINDOW_SCALE_LEFT)
18100  scaler.x = layout->bounds.x - panel_padding.x * 0.5f;
18101  else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x;
18102  if (layout->flags & NK_WINDOW_NO_SCROLLBAR)
18103  scaler.x -= scaler.w;
18104 
18105  /* draw scaler */
18106  {const struct nk_style_item *item = &style->window.scaler;
18107  if (item->type == NK_STYLE_ITEM_IMAGE)
18108  nk_draw_image(out, scaler, &item->data.image, nk_white);
18109  else {
18110  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
18111  nk_fill_triangle(out, scaler.x, scaler.y, scaler.x,
18112  scaler.y + scaler.h, scaler.x + scaler.w,
18113  scaler.y + scaler.h, item->data.color);
18114  } else {
18115  nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w,
18116  scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color);
18117  }
18118  }}
18119 
18120  /* do window scaling */
18121  if (!(window->flags & NK_WINDOW_ROM)) {
18122  struct nk_vec2 window_size = style->window.min_size;
18123  int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down;
18124  int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in,
18125  NK_BUTTON_LEFT, scaler, nk_true);
18126 
18127  if (left_mouse_down && left_mouse_click_in_scaler) {
18128  float delta_x = in->mouse.delta.x;
18129  if (layout->flags & NK_WINDOW_SCALE_LEFT) {
18130  delta_x = -delta_x;
18131  window->bounds.x += in->mouse.delta.x;
18132  }
18133  /* dragging in x-direction */
18134  if (window->bounds.w + delta_x >= window_size.x) {
18135  if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) {
18136  window->bounds.w = window->bounds.w + delta_x;
18137  scaler.x += in->mouse.delta.x;
18138  }
18139  }
18140  /* dragging in y-direction (only possible if static window) */
18141  if (!(layout->flags & NK_WINDOW_DYNAMIC)) {
18142  if (window_size.y < window->bounds.h + in->mouse.delta.y) {
18143  if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) {
18144  window->bounds.h = window->bounds.h + in->mouse.delta.y;
18145  scaler.y += in->mouse.delta.y;
18146  }
18147  }
18148  }
18149  ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT];
18150  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f;
18151  in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f;
18152  }
18153  }
18154  }
18155  if (!nk_panel_is_sub(layout->type)) {
18156  /* window is hidden so clear command buffer */
18157  if (layout->flags & NK_WINDOW_HIDDEN)
18158  nk_command_buffer_reset(&window->buffer);
18159  /* window is visible and not tab */
18160  else nk_finish(ctx, window);
18161  }
18162 
18163  /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */
18164  if (layout->flags & NK_WINDOW_REMOVE_ROM) {
18165  layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
18166  layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
18167  }
18168  window->flags = layout->flags;
18169 
18170  /* property garbage collector */
18171  if (window->property.active && window->property.old != window->property.seq &&
18172  window->property.active == window->property.prev) {
18173  nk_zero(&window->property, sizeof(window->property));
18174  } else {
18175  window->property.old = window->property.seq;
18176  window->property.prev = window->property.active;
18177  window->property.seq = 0;
18178  }
18179  /* edit garbage collector */
18180  if (window->edit.active && window->edit.old != window->edit.seq &&
18181  window->edit.active == window->edit.prev) {
18182  nk_zero(&window->edit, sizeof(window->edit));
18183  } else {
18184  window->edit.old = window->edit.seq;
18185  window->edit.prev = window->edit.active;
18186  window->edit.seq = 0;
18187  }
18188  /* contextual garbage collector */
18189  if (window->popup.active_con && window->popup.con_old != window->popup.con_count) {
18190  window->popup.con_count = 0;
18191  window->popup.con_old = 0;
18192  window->popup.active_con = 0;
18193  } else {
18194  window->popup.con_old = window->popup.con_count;
18195  window->popup.con_count = 0;
18196  }
18197  window->popup.combo_count = 0;
18198  /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */
18199  NK_ASSERT(!layout->row.tree_depth);
18200 }
18201 
18202 /* ----------------------------------------------------------------
18203  *
18204  * PAGE ELEMENT
18205  *
18206  * ---------------------------------------------------------------*/
18207 NK_INTERN struct nk_page_element*
18208 nk_create_page_element(struct nk_context *ctx)
18209 {
18210  struct nk_page_element *elem;
18211  if (ctx->freelist) {
18212  /* unlink page element from free list */
18213  elem = ctx->freelist;
18214  ctx->freelist = elem->next;
18215  } else if (ctx->use_pool) {
18216  /* allocate page element from memory pool */
18217  elem = nk_pool_alloc(&ctx->pool);
18218  NK_ASSERT(elem);
18219  if (!elem) return 0;
18220  } else {
18221  /* allocate new page element from back of fixed size memory buffer */
18222  NK_STORAGE const nk_size size = sizeof(struct nk_page_element);
18224  elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align);
18225  NK_ASSERT(elem);
18226  if (!elem) return 0;
18227  }
18228  nk_zero_struct(*elem);
18229  elem->next = 0;
18230  elem->prev = 0;
18231  return elem;
18232 }
18233 
18234 NK_INTERN void
18235 nk_link_page_element_into_freelist(struct nk_context *ctx,
18236  struct nk_page_element *elem)
18237 {
18238  /* link table into freelist */
18239  if (!ctx->freelist) {
18240  ctx->freelist = elem;
18241  } else {
18242  elem->next = ctx->freelist;
18243  ctx->freelist = elem;
18244  }
18245 }
18246 
18247 NK_INTERN void
18248 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem)
18249 {
18250  /* we have a pool so just add to free list */
18251  if (ctx->use_pool) {
18252  nk_link_page_element_into_freelist(ctx, elem);
18253  return;
18254  }
18255  /* if possible remove last element from back of fixed memory buffer */
18256  {void *elem_end = (void*)(elem + 1);
18257  void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size;
18258  if (elem_end == buffer_end)
18259  ctx->memory.size -= sizeof(struct nk_page_element);
18260  else nk_link_page_element_into_freelist(ctx, elem);}
18261 }
18262 
18263 /* ----------------------------------------------------------------
18264  *
18265  * PANEL
18266  *
18267  * ---------------------------------------------------------------*/
18268 NK_INTERN void*
18269 nk_create_panel(struct nk_context *ctx)
18270 {
18271  struct nk_page_element *elem;
18272  elem = nk_create_page_element(ctx);
18273  if (!elem) return 0;
18274  nk_zero_struct(*elem);
18275  return &elem->data.pan;
18276 }
18277 
18278 NK_INTERN void
18279 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan)
18280 {
18281  union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan);
18282  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18283  nk_free_page_element(ctx, pe);
18284 }
18285 
18286 /* ----------------------------------------------------------------
18287  *
18288  * TABLES
18289  *
18290  * ---------------------------------------------------------------*/
18291 NK_INTERN struct nk_table*
18292 nk_create_table(struct nk_context *ctx)
18293 {
18294  struct nk_page_element *elem;
18295  elem = nk_create_page_element(ctx);
18296  if (!elem) return 0;
18297  nk_zero_struct(*elem);
18298  return &elem->data.tbl;
18299 }
18300 
18301 NK_INTERN void
18302 nk_free_table(struct nk_context *ctx, struct nk_table *tbl)
18303 {
18304  union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl);
18305  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18306  nk_free_page_element(ctx, pe);
18307 }
18308 
18309 NK_INTERN void
18310 nk_push_table(struct nk_window *win, struct nk_table *tbl)
18311 {
18312  if (!win->tables) {
18313  win->tables = tbl;
18314  tbl->next = 0;
18315  tbl->prev = 0;
18316  tbl->size = 0;
18317  win->table_count = 1;
18318  return;
18319  }
18320  win->tables->prev = tbl;
18321  tbl->next = win->tables;
18322  tbl->prev = 0;
18323  tbl->size = 0;
18324  win->tables = tbl;
18325  win->table_count++;
18326 }
18327 
18328 NK_INTERN void
18329 nk_remove_table(struct nk_window *win, struct nk_table *tbl)
18330 {
18331  if (win->tables == tbl)
18332  win->tables = tbl->next;
18333  if (tbl->next)
18334  tbl->next->prev = tbl->prev;
18335  if (tbl->prev)
18336  tbl->prev->next = tbl->next;
18337  tbl->next = 0;
18338  tbl->prev = 0;
18339 }
18340 
18342 nk_add_value(struct nk_context *ctx, struct nk_window *win,
18344 {
18345  NK_ASSERT(ctx);
18346  NK_ASSERT(win);
18347  if (!win || !ctx) return 0;
18348  if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) {
18349  struct nk_table *tbl = nk_create_table(ctx);
18350  NK_ASSERT(tbl);
18351  if (!tbl) return 0;
18352  nk_push_table(win, tbl);
18353  }
18354  win->tables->seq = win->seq;
18355  win->tables->keys[win->tables->size] = name;
18356  win->tables->values[win->tables->size] = value;
18357  return &win->tables->values[win->tables->size++];
18358 }
18359 
18361 nk_find_value(struct nk_window *win, nk_hash name)
18362 {
18363  struct nk_table *iter = win->tables;
18364  while (iter) {
18365  unsigned int i = 0;
18366  unsigned int size = iter->size;
18367  for (i = 0; i < size; ++i) {
18368  if (iter->keys[i] == name) {
18369  iter->seq = win->seq;
18370  return &iter->values[i];
18371  }
18373  iter = iter->next;
18374  }
18375  return 0;
18376 }
18377 
18378 /* ----------------------------------------------------------------
18379  *
18380  * WINDOW
18381  *
18382  * ---------------------------------------------------------------*/
18383 NK_INTERN void*
18384 nk_create_window(struct nk_context *ctx)
18385 {
18386  struct nk_page_element *elem;
18387  elem = nk_create_page_element(ctx);
18388  if (!elem) return 0;
18389  elem->data.win.seq = ctx->seq;
18390  return &elem->data.win;
18391 }
18392 
18393 NK_INTERN void
18394 nk_free_window(struct nk_context *ctx, struct nk_window *win)
18395 {
18396  /* unlink windows from list */
18397  struct nk_table *it = win->tables;
18398  if (win->popup.win) {
18399  nk_free_window(ctx, win->popup.win);
18400  win->popup.win = 0;
18401  }
18402  win->next = 0;
18403  win->prev = 0;
18404 
18405  while (it) {
18406  /*free window state tables */
18407  struct nk_table *n = it->next;
18408  nk_remove_table(win, it);
18409  nk_free_table(ctx, it);
18410  if (it == win->tables)
18411  win->tables = n;
18412  it = n;
18413  }
18414 
18415  /* link windows into freelist */
18416  {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win);
18417  struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data);
18418  nk_free_page_element(ctx, pe);}
18419 }
18420 
18421 NK_INTERN struct nk_window*
18422 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name)
18423 {
18424  struct nk_window *iter;
18425  iter = ctx->begin;
18426  while (iter) {
18427  NK_ASSERT(iter != iter->next);
18428  if (iter->name == hash) {
18429  int max_len = nk_strlen(iter->name_string);
18430  if (!nk_stricmpn(iter->name_string, name, max_len))
18431  return iter;
18432  }
18433  iter = iter->next;
18434  }
18435  return 0;
18436 }
18437 
18438 enum nk_window_insert_location {
18439  NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */
18440  NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */
18441 };
18442 NK_INTERN void
18443 nk_insert_window(struct nk_context *ctx, struct nk_window *win,
18444  enum nk_window_insert_location loc)
18445 {
18446  const struct nk_window *iter;
18447  NK_ASSERT(ctx);
18448  NK_ASSERT(win);
18449  if (!win || !ctx) return;
18450 
18451  iter = ctx->begin;
18452  while (iter) {
18453  NK_ASSERT(iter != iter->next);
18454  NK_ASSERT(iter != win);
18455  if (iter == win) return;
18456  iter = iter->next;
18457  }
18458 
18459  if (!ctx->begin) {
18460  win->next = 0;
18461  win->prev = 0;
18462  ctx->begin = win;
18463  ctx->end = win;
18464  ctx->count = 1;
18465  return;
18466  }
18467  if (loc == NK_INSERT_BACK) {
18468  struct nk_window *end;
18469  end = ctx->end;
18470  end->flags |= NK_WINDOW_ROM;
18471  end->next = win;
18472  win->prev = ctx->end;
18473  win->next = 0;
18474  ctx->end = win;
18475  ctx->active = ctx->end;
18476  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
18477  } else {
18478  /*ctx->end->flags |= NK_WINDOW_ROM;*/
18479  ctx->begin->prev = win;
18480  win->next = ctx->begin;
18481  win->prev = 0;
18482  ctx->begin = win;
18483  ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM;
18484  }
18485  ctx->count++;
18486 }
18487 
18488 NK_INTERN void
18489 nk_remove_window(struct nk_context *ctx, struct nk_window *win)
18490 {
18491  if (win == ctx->begin || win == ctx->end) {
18492  if (win == ctx->begin) {
18493  ctx->begin = win->next;
18494  if (win->next)
18495  win->next->prev = 0;
18496  }
18497  if (win == ctx->end) {
18498  ctx->end = win->prev;
18499  if (win->prev)
18500  win->prev->next = 0;
18501  }
18502  } else {
18503  if (win->next)
18504  win->next->prev = win->prev;
18505  if (win->prev)
18506  win->prev->next = win->next;
18507  }
18508  if (win == ctx->active || !ctx->active) {
18509  ctx->active = ctx->end;
18510  if (ctx->end)
18511  ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM;
18512  }
18513  win->next = 0;
18514  win->prev = 0;
18515  ctx->count--;
18516 }
18517 
18518 NK_API int
18519 nk_begin(struct nk_context *ctx, const char *title,
18520  struct nk_rect bounds, nk_flags flags)
18521 {
18522  return nk_begin_titled(ctx, title, title, bounds, flags);
18523 }
18524 
18525 NK_API int
18526 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title,
18527  struct nk_rect bounds, nk_flags flags)
18528 {
18529  struct nk_window *win;
18530  struct nk_style *style;
18531  nk_hash title_hash;
18532  int title_len;
18533  int ret = 0;
18534 
18535  NK_ASSERT(ctx);
18536  NK_ASSERT(name);
18537  NK_ASSERT(title);
18538  NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font");
18539  NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call");
18540  if (!ctx || ctx->current || !title || !name)
18541  return 0;
18542 
18543  /* find or create window */
18544  style = &ctx->style;
18545  title_len = (int)nk_strlen(name);
18546  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18547  win = nk_find_window(ctx, title_hash, name);
18548  if (!win) {
18549  /* create new window */
18550  nk_size name_length = (nk_size)nk_strlen(name);
18551  win = (struct nk_window*)nk_create_window(ctx);
18552  NK_ASSERT(win);
18553  if (!win) return 0;
18554 
18556  nk_insert_window(ctx, win, NK_INSERT_FRONT);
18557  else nk_insert_window(ctx, win, NK_INSERT_BACK);
18558  nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON);
18559 
18560  win->flags = flags;
18561  win->bounds = bounds;
18562  win->name = title_hash;
18563  name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1);
18564  NK_MEMCPY(win->name_string, name, name_length);
18565  win->name_string[name_length] = 0;
18566  win->popup.win = 0;
18567  if (!ctx->active)
18568  ctx->active = win;
18569  } else {
18570  /* update window */
18571  win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1);
18572  win->flags |= flags;
18573  if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE)))
18574  win->bounds = bounds;
18575  /* If this assert triggers you either:
18576  *
18577  * I.) Have more than one window with the same name or
18578  * II.) You forgot to actually draw the window.
18579  * More specific you did not call `nk_clear` (nk_clear will be
18580  * automatically called for you if you are using one of the
18581  * provided demo backends). */
18582  NK_ASSERT(win->seq != ctx->seq);
18583  win->seq = ctx->seq;
18584  if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) {
18585  ctx->active = win;
18586  ctx->end = win;
18587  }
18588  }
18589  if (win->flags & NK_WINDOW_HIDDEN) {
18590  ctx->current = win;
18591  win->layout = 0;
18592  return 0;
18593  }
18594 
18595  /* window overlapping */
18596  if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT))
18597  {
18598  int inpanel, ishovered;
18599  struct nk_window *iter = win;
18600  float h = ctx->style.font->height + 2.0f * style->window.header.padding.y +
18601  (2.0f * style->window.header.label_padding.y);
18602  struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))?
18603  win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h);
18604 
18605  /* activate window if hovered and no other window is overlapping this window */
18606  nk_start(ctx, win);
18607  inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true);
18608  inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked;
18609  ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds);
18610  if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) {
18611  iter = win->next;
18612  while (iter) {
18613  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
18614  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
18615  if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18616  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
18617  (!(iter->flags & NK_WINDOW_HIDDEN)))
18618  break;
18619 
18620  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
18621  NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18622  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
18623  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
18624  break;
18625  iter = iter->next;
18626  }
18627  }
18628 
18629  /* activate window if clicked */
18630  if (iter && inpanel && (win != ctx->end)) {
18631  iter = win->next;
18632  while (iter) {
18633  /* try to find a panel with higher priority in the same position */
18634  struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))?
18635  iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h);
18636  if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y,
18637  iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) &&
18638  !(iter->flags & NK_WINDOW_HIDDEN))
18639  break;
18640  if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) &&
18641  NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h,
18642  iter->popup.win->bounds.x, iter->popup.win->bounds.y,
18643  iter->popup.win->bounds.w, iter->popup.win->bounds.h))
18644  break;
18645  iter = iter->next;
18646  }
18647  }
18648  if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) {
18649  win->flags |= (nk_flags)NK_WINDOW_ROM;
18650  iter->flags &= ~(nk_flags)NK_WINDOW_ROM;
18651  ctx->active = iter;
18652  if (!(iter->flags & NK_WINDOW_BACKGROUND)) {
18653  /* current window is active in that position so transfer to top
18654  * at the highest priority in stack */
18655  nk_remove_window(ctx, iter);
18656  nk_insert_window(ctx, iter, NK_INSERT_BACK);
18657  }
18658  } else {
18659  if (!iter && ctx->end != win) {
18660  if (!(win->flags & NK_WINDOW_BACKGROUND)) {
18661  /* current window is active in that position so transfer to top
18662  * at the highest priority in stack */
18663  nk_remove_window(ctx, win);
18664  nk_insert_window(ctx, win, NK_INSERT_BACK);
18665  }
18666  win->flags &= ~(nk_flags)NK_WINDOW_ROM;
18667  ctx->active = win;
18668  }
18669  if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND))
18670  win->flags |= NK_WINDOW_ROM;
18671  }
18672  }
18673 
18674  win->layout = (struct nk_panel*)nk_create_panel(ctx);
18675  ctx->current = win;
18676  ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW);
18677  win->layout->offset_x = &win->scrollbar.x;
18678  win->layout->offset_y = &win->scrollbar.y;
18679  return ret;
18680 }
18681 
18682 NK_API void
18683 nk_end(struct nk_context *ctx)
18684 {
18685  struct nk_panel *layout;
18686  NK_ASSERT(ctx);
18687  NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`");
18688  if (!ctx || !ctx->current)
18689  return;
18690 
18691  layout = ctx->current->layout;
18692  if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) {
18693  ctx->current = 0;
18694  return;
18695  }
18696  nk_panel_end(ctx);
18697  nk_free_panel(ctx, ctx->current->layout);
18698  ctx->current = 0;
18699 }
18700 
18701 NK_API struct nk_rect
18703 {
18704  NK_ASSERT(ctx);
18705  NK_ASSERT(ctx->current);
18706  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
18707  return ctx->current->bounds;
18708 }
18709 
18710 NK_API struct nk_vec2
18712 {
18713  NK_ASSERT(ctx);
18714  NK_ASSERT(ctx->current);
18715  if (!ctx || !ctx->current) return nk_vec2(0,0);
18716  return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y);
18717 }
18718 
18719 NK_API struct nk_vec2
18721 {
18722  NK_ASSERT(ctx);
18723  NK_ASSERT(ctx->current);
18724  if (!ctx || !ctx->current) return nk_vec2(0,0);
18725  return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h);
18726 }
18727 
18728 NK_API float
18729 nk_window_get_width(const struct nk_context *ctx)
18730 {
18731  NK_ASSERT(ctx);
18732  NK_ASSERT(ctx->current);
18733  if (!ctx || !ctx->current) return 0;
18734  return ctx->current->bounds.w;
18735 }
18736 
18737 NK_API float
18738 nk_window_get_height(const struct nk_context *ctx)
18739 {
18740  NK_ASSERT(ctx);
18741  NK_ASSERT(ctx->current);
18742  if (!ctx || !ctx->current) return 0;
18743  return ctx->current->bounds.h;
18744 }
18745 
18746 NK_API struct nk_rect
18748 {
18749  NK_ASSERT(ctx);
18750  NK_ASSERT(ctx->current);
18751  if (!ctx || !ctx->current) return nk_rect(0,0,0,0);
18752  return ctx->current->layout->clip;
18753 }
18754 
18755 NK_API struct nk_vec2
18757 {
18758  NK_ASSERT(ctx);
18759  NK_ASSERT(ctx->current);
18760  NK_ASSERT(ctx->current->layout);
18761  if (!ctx || !ctx->current) return nk_vec2(0,0);
18762  return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y);
18763 }
18764 
18765 NK_API struct nk_vec2
18767 {
18768  NK_ASSERT(ctx);
18769  NK_ASSERT(ctx->current);
18770  NK_ASSERT(ctx->current->layout);
18771  if (!ctx || !ctx->current) return nk_vec2(0,0);
18772  return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w,
18773  ctx->current->layout->clip.y + ctx->current->layout->clip.h);
18774 }
18775 
18776 NK_API struct nk_vec2
18778 {
18779  NK_ASSERT(ctx);
18780  NK_ASSERT(ctx->current);
18781  NK_ASSERT(ctx->current->layout);
18782  if (!ctx || !ctx->current) return nk_vec2(0,0);
18783  return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h);
18784 }
18785 
18786 NK_API struct nk_command_buffer*
18788 {
18789  NK_ASSERT(ctx);
18790  NK_ASSERT(ctx->current);
18791  NK_ASSERT(ctx->current->layout);
18792  if (!ctx || !ctx->current) return 0;
18793  return &ctx->current->buffer;
18794 }
18795 
18796 NK_API struct nk_panel*
18798 {
18799  NK_ASSERT(ctx);
18800  NK_ASSERT(ctx->current);
18801  if (!ctx || !ctx->current) return 0;
18802  return ctx->current->layout;
18803 }
18804 
18805 NK_API int
18806 nk_window_has_focus(const struct nk_context *ctx)
18807 {
18808  NK_ASSERT(ctx);
18809  NK_ASSERT(ctx->current);
18810  NK_ASSERT(ctx->current->layout);
18811  if (!ctx || !ctx->current) return 0;
18812  return ctx->current == ctx->active;
18813 }
18814 
18815 NK_API int
18817 {
18818  NK_ASSERT(ctx);
18819  NK_ASSERT(ctx->current);
18820  if (!ctx || !ctx->current) return 0;
18821  if(ctx->current->flags & NK_WINDOW_HIDDEN)
18822  return 0;
18823  return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds);
18824 }
18825 
18826 NK_API int
18828 {
18829  struct nk_window *iter;
18830  NK_ASSERT(ctx);
18831  if (!ctx) return 0;
18832  iter = ctx->begin;
18833  while (iter) {
18834  /* check if window is being hovered */
18835  if(!(iter->flags & NK_WINDOW_HIDDEN)) {
18836  /* check if window popup is being hovered */
18837  if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds))
18838  return 1;
18839 
18840  if (iter->flags & NK_WINDOW_MINIMIZED) {
18841  struct nk_rect header = iter->bounds;
18842  header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y;
18843  if (nk_input_is_mouse_hovering_rect(&ctx->input, header))
18844  return 1;
18845  } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) {
18846  return 1;
18847  }
18848  }
18849  iter = iter->next;
18850  }
18851  return 0;
18852 }
18853 
18854 NK_API int
18856 {
18857  int any_hovered = nk_window_is_any_hovered(ctx);
18858  int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED);
18859  return any_hovered || any_active;
18860 }
18861 
18862 NK_API int
18863 nk_window_is_collapsed(struct nk_context *ctx, const char *name)
18864 {
18865  int title_len;
18866  nk_hash title_hash;
18867  struct nk_window *win;
18868  NK_ASSERT(ctx);
18869  if (!ctx) return 0;
18870 
18871  title_len = (int)nk_strlen(name);
18872  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18873  win = nk_find_window(ctx, title_hash, name);
18874  if (!win) return 0;
18875  return win->flags & NK_WINDOW_MINIMIZED;
18876 }
18877 
18878 NK_API int
18879 nk_window_is_closed(struct nk_context *ctx, const char *name)
18880 {
18881  int title_len;
18882  nk_hash title_hash;
18883  struct nk_window *win;
18884  NK_ASSERT(ctx);
18885  if (!ctx) return 1;
18886 
18887  title_len = (int)nk_strlen(name);
18888  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18889  win = nk_find_window(ctx, title_hash, name);
18890  if (!win) return 1;
18891  return (win->flags & NK_WINDOW_CLOSED);
18892 }
18893 
18894 NK_API int
18895 nk_window_is_hidden(struct nk_context *ctx, const char *name)
18896 {
18897  int title_len;
18898  nk_hash title_hash;
18899  struct nk_window *win;
18900  NK_ASSERT(ctx);
18901  if (!ctx) return 1;
18902 
18903  title_len = (int)nk_strlen(name);
18904  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18905  win = nk_find_window(ctx, title_hash, name);
18906  if (!win) return 1;
18907  return (win->flags & NK_WINDOW_HIDDEN);
18908 }
18909 
18910 NK_API int
18911 nk_window_is_active(struct nk_context *ctx, const char *name)
18912 {
18913  int title_len;
18914  nk_hash title_hash;
18915  struct nk_window *win;
18916  NK_ASSERT(ctx);
18917  if (!ctx) return 0;
18918 
18919  title_len = (int)nk_strlen(name);
18920  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18921  win = nk_find_window(ctx, title_hash, name);
18922  if (!win) return 0;
18923  return win == ctx->active;
18924 }
18925 
18926 NK_API struct nk_window*
18927 nk_window_find(struct nk_context *ctx, const char *name)
18928 {
18929  int title_len;
18930  nk_hash title_hash;
18931  title_len = (int)nk_strlen(name);
18932  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18933  return nk_find_window(ctx, title_hash, name);
18934 }
18935 
18936 NK_API void
18937 nk_window_close(struct nk_context *ctx, const char *name)
18938 {
18939  struct nk_window *win;
18940  NK_ASSERT(ctx);
18941  if (!ctx) return;
18942  win = nk_window_find(ctx, name);
18943  if (!win) return;
18944  NK_ASSERT(ctx->current != win && "You cannot close a currently active window");
18945  if (ctx->current == win) return;
18946  win->flags |= NK_WINDOW_HIDDEN;
18947  win->flags |= NK_WINDOW_CLOSED;
18948 }
18949 
18950 NK_API void
18952  const char *name, struct nk_rect bounds)
18953 {
18954  struct nk_window *win;
18955  NK_ASSERT(ctx);
18956  if (!ctx) return;
18957  win = nk_window_find(ctx, name);
18958  if (!win) return;
18959  NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window");
18960  win->bounds = bounds;
18961 }
18962 
18963 NK_API void
18965  const char *name, struct nk_vec2 pos)
18966 {
18967  struct nk_rect bounds;
18968  bounds.x = pos.x;
18969  bounds.y = pos.y;
18970  bounds.w = ctx->current->bounds.w;
18971  bounds.h = ctx->current->bounds.h;
18972  nk_window_set_bounds(ctx, name, bounds);
18973 }
18974 
18975 NK_API void
18977  const char *name, struct nk_vec2 size)
18978 {
18979  struct nk_rect bounds;
18980  bounds.x = ctx->current->bounds.x;
18981  bounds.y = ctx->current->bounds.y;
18982  bounds.w = size.x;
18983  bounds.h = size.y;
18984  nk_window_set_bounds(ctx, name, bounds);
18985 }
18986 
18987 NK_API void
18988 nk_window_collapse(struct nk_context *ctx, const char *name,
18989  enum nk_collapse_states c)
18990 {
18991  int title_len;
18992  nk_hash title_hash;
18993  struct nk_window *win;
18994  NK_ASSERT(ctx);
18995  if (!ctx) return;
18996 
18997  title_len = (int)nk_strlen(name);
18998  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
18999  win = nk_find_window(ctx, title_hash, name);
19000  if (!win) return;
19001  if (c == NK_MINIMIZED)
19002  win->flags |= NK_WINDOW_MINIMIZED;
19003  else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED;
19004 }
19005 
19006 NK_API void
19007 nk_window_collapse_if(struct nk_context *ctx, const char *name,
19008  enum nk_collapse_states c, int cond)
19009 {
19010  NK_ASSERT(ctx);
19011  if (!ctx || !cond) return;
19013 }
19014 
19015 NK_API void
19016 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s)
19017 {
19018  int title_len;
19019  nk_hash title_hash;
19020  struct nk_window *win;
19021  NK_ASSERT(ctx);
19022  if (!ctx) return;
19023 
19024  title_len = (int)nk_strlen(name);
19025  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
19026  win = nk_find_window(ctx, title_hash, name);
19027  if (!win) return;
19028  if (s == NK_HIDDEN) {
19029  win->flags |= NK_WINDOW_HIDDEN;
19030  } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN;
19031 }
19032 
19033 NK_API void
19034 nk_window_show_if(struct nk_context *ctx, const char *name,
19035  enum nk_show_states s, int cond)
19036 {
19037  NK_ASSERT(ctx);
19038  if (!ctx || !cond) return;
19039  nk_window_show(ctx, name, s);
19040 }
19041 
19042 NK_API void
19043 nk_window_set_focus(struct nk_context *ctx, const char *name)
19044 {
19045  int title_len;
19046  nk_hash title_hash;
19047  struct nk_window *win;
19048  NK_ASSERT(ctx);
19049  if (!ctx) return;
19050 
19051  title_len = (int)nk_strlen(name);
19052  title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE);
19053  win = nk_find_window(ctx, title_hash, name);
19054  if (win && ctx->end != win) {
19055  nk_remove_window(ctx, win);
19056  nk_insert_window(ctx, win, NK_INSERT_BACK);
19057  }
19058  ctx->active = win;
19059 }
19060 
19061 /*----------------------------------------------------------------
19062  *
19063  * MENUBAR
19064  *
19065  * --------------------------------------------------------------*/
19066 NK_API void
19068 {
19069  struct nk_panel *layout;
19070  NK_ASSERT(ctx);
19071  NK_ASSERT(ctx->current);
19072  NK_ASSERT(ctx->current->layout);
19073  if (!ctx || !ctx->current || !ctx->current->layout)
19074  return;
19075 
19076  layout = ctx->current->layout;
19077  NK_ASSERT(layout->at_y == layout->bounds.y);
19078  /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin.
19079  If you want a menubar the first nuklear function after `nk_begin` has to be a
19080  `nk_menubar_begin` call. Inside the menubar you then have to allocate space for
19081  widgets (also supports multiple rows).
19082  Example:
19083  if (nk_begin(...)) {
19084  nk_menubar_begin(...);
19085  nk_layout_xxxx(...);
19086  nk_button(...);
19087  nk_layout_xxxx(...);
19088  nk_button(...);
19089  nk_menubar_end(...);
19090  }
19091  nk_end(...);
19092  */
19093  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
19094  return;
19095 
19096  layout->menu.x = layout->at_x;
19097  layout->menu.y = layout->at_y + layout->row.height;
19098  layout->menu.w = layout->bounds.w;
19099  layout->menu.offset.x = *layout->offset_x;
19100  layout->menu.offset.y = *layout->offset_y;
19101  *layout->offset_y = 0;
19102 }
19103 
19104 NK_API void
19105 nk_menubar_end(struct nk_context *ctx)
19106 {
19107  struct nk_window *win;
19108  struct nk_panel *layout;
19109  struct nk_command_buffer *out;
19110 
19111  NK_ASSERT(ctx);
19112  NK_ASSERT(ctx->current);
19113  NK_ASSERT(ctx->current->layout);
19114  if (!ctx || !ctx->current || !ctx->current->layout)
19115  return;
19116 
19117  win = ctx->current;
19118  out = &win->buffer;
19119  layout = win->layout;
19120  if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED)
19121  return;
19122 
19123  layout->menu.h = layout->at_y - layout->menu.y;
19124  layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
19125  layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height;
19126 
19127  *layout->offset_x = layout->menu.offset.x;
19128  *layout->offset_y = layout->menu.offset.y;
19129  layout->at_y = layout->bounds.y - layout->row.height;
19130 
19131  layout->clip.y = layout->bounds.y;
19132  layout->clip.h = layout->bounds.h;
19133  nk_push_scissor(out, layout->clip);
19134 }
19135 /* -------------------------------------------------------------
19136  *
19137  * LAYOUT
19138  *
19139  * --------------------------------------------------------------*/
19140 NK_API void
19142 {
19143  struct nk_window *win;
19144  struct nk_panel *layout;
19145 
19146  NK_ASSERT(ctx);
19147  NK_ASSERT(ctx->current);
19148  NK_ASSERT(ctx->current->layout);
19149  if (!ctx || !ctx->current || !ctx->current->layout)
19150  return;
19151 
19152  win = ctx->current;
19153  layout = win->layout;
19154  layout->row.min_height = height;
19155 }
19156 
19157 NK_API void
19159 {
19160  struct nk_window *win;
19161  struct nk_panel *layout;
19162 
19163  NK_ASSERT(ctx);
19164  NK_ASSERT(ctx->current);
19165  NK_ASSERT(ctx->current->layout);
19166  if (!ctx || !ctx->current || !ctx->current->layout)
19167  return;
19168 
19169  win = ctx->current;
19170  layout = win->layout;
19171  layout->row.min_height = ctx->style.font->height;
19172  layout->row.min_height += ctx->style.text.padding.y*2;
19173  layout->row.min_height += ctx->style.window.min_row_height_padding*2;
19174 }
19175 
19176 NK_INTERN float
19177 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type,
19178  float total_space, int columns)
19179 {
19180  float panel_padding;
19181  float panel_spacing;
19182  float panel_space;
19183 
19184  struct nk_vec2 spacing;
19185  struct nk_vec2 padding;
19186 
19187  spacing = style->window.spacing;
19188  padding = nk_panel_get_padding(style, type);
19189 
19190  /* calculate the usable panel space */
19191  panel_padding = 2 * padding.x;
19192  panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x;
19193  panel_space = total_space - panel_padding - panel_spacing;
19194  return panel_space;
19195 }
19196 
19197 NK_INTERN void
19198 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win,
19199  float height, int cols)
19200 {
19201  struct nk_panel *layout;
19202  const struct nk_style *style;
19203  struct nk_command_buffer *out;
19204 
19205  struct nk_vec2 item_spacing;
19206  struct nk_color color;
19207 
19208  NK_ASSERT(ctx);
19209  NK_ASSERT(ctx->current);
19210  NK_ASSERT(ctx->current->layout);
19211  if (!ctx || !ctx->current || !ctx->current->layout)
19212  return;
19213 
19214  /* prefetch some configuration data */
19215  layout = win->layout;
19216  style = &ctx->style;
19217  out = &win->buffer;
19218  color = style->window.background;
19219  item_spacing = style->window.spacing;
19220 
19221  /* if one of these triggers you forgot to add an `if` condition around either
19222  a window, group, popup, combobox or contextual menu `begin` and `end` block.
19223  Example:
19224  if (nk_begin(...) {...} nk_end(...); or
19225  if (nk_group_begin(...) { nk_group_end(...);} */
19226  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
19227  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
19228  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
19229 
19230  /* update the current row and set the current row layout */
19231  layout->row.index = 0;
19232  layout->at_y += layout->row.height;
19233  layout->row.columns = cols;
19234  if (height == 0.0f)
19235  layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y;
19236  else layout->row.height = height + item_spacing.y;
19237 
19238  layout->row.item_offset = 0;
19239  if (layout->flags & NK_WINDOW_DYNAMIC) {
19240  /* draw background for dynamic panels */
19241  struct nk_rect background;
19242  background.x = win->bounds.x;
19243  background.w = win->bounds.w;
19244  background.y = layout->at_y - 1.0f;
19245  background.h = layout->row.height + 1.0f;
19246  nk_fill_rect(out, background, 0, color);
19247  }
19248 }
19249 
19250 NK_INTERN void
19251 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt,
19252  float height, int cols, int width)
19253 {
19254  /* update the current row and set the current row layout */
19255  struct nk_window *win;
19256  NK_ASSERT(ctx);
19257  NK_ASSERT(ctx->current);
19258  NK_ASSERT(ctx->current->layout);
19259  if (!ctx || !ctx->current || !ctx->current->layout)
19260  return;
19261 
19262  win = ctx->current;
19263  nk_panel_layout(ctx, win, height, cols);
19264  if (fmt == NK_DYNAMIC)
19266  else win->layout->row.type = NK_LAYOUT_STATIC_FIXED;
19267 
19268  win->layout->row.ratio = 0;
19269  win->layout->row.filled = 0;
19270  win->layout->row.item_offset = 0;
19271  win->layout->row.item_width = (float)width;
19272 }
19273 
19274 NK_API float
19275 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width)
19276 {
19277  struct nk_window *win;
19278  NK_ASSERT(ctx);
19279  NK_ASSERT(pixel_width);
19280  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
19281  win = ctx->current;
19282  return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f);
19283 }
19284 
19285 NK_API void
19286 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
19287 {
19288  nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0);
19289 }
19290 
19291 NK_API void
19292 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
19293 {
19294  nk_row_layout(ctx, NK_STATIC, height, cols, item_width);
19295 }
19296 
19297 NK_API void
19299  float row_height, int cols)
19300 {
19301  struct nk_window *win;
19302  struct nk_panel *layout;
19303 
19304  NK_ASSERT(ctx);
19305  NK_ASSERT(ctx->current);
19306  NK_ASSERT(ctx->current->layout);
19307  if (!ctx || !ctx->current || !ctx->current->layout)
19308  return;
19309 
19310  win = ctx->current;
19311  layout = win->layout;
19312  nk_panel_layout(ctx, win, row_height, cols);
19313  if (fmt == NK_DYNAMIC)
19314  layout->row.type = NK_LAYOUT_DYNAMIC_ROW;
19315  else layout->row.type = NK_LAYOUT_STATIC_ROW;
19316 
19317  layout->row.ratio = 0;
19318  layout->row.filled = 0;
19319  layout->row.item_width = 0;
19320  layout->row.item_offset = 0;
19321  layout->row.columns = cols;
19322 }
19323 
19324 NK_API void
19325 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width)
19326 {
19327  struct nk_window *win;
19328  struct nk_panel *layout;
19329 
19330  NK_ASSERT(ctx);
19331  NK_ASSERT(ctx->current);
19332  NK_ASSERT(ctx->current->layout);
19333  if (!ctx || !ctx->current || !ctx->current->layout)
19334  return;
19335 
19336  win = ctx->current;
19337  layout = win->layout;
19338  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
19339  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
19340  return;
19341 
19342  if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) {
19343  float ratio = ratio_or_width;
19344  if ((ratio + layout->row.filled) > 1.0f) return;
19345  if (ratio > 0.0f)
19346  layout->row.item_width = NK_SATURATE(ratio);
19347  else layout->row.item_width = 1.0f - layout->row.filled;
19348  } else layout->row.item_width = ratio_or_width;
19349 }
19350 
19351 NK_API void
19353 {
19354  struct nk_window *win;
19355  struct nk_panel *layout;
19356 
19357  NK_ASSERT(ctx);
19358  NK_ASSERT(ctx->current);
19359  NK_ASSERT(ctx->current->layout);
19360  if (!ctx || !ctx->current || !ctx->current->layout)
19361  return;
19362 
19363  win = ctx->current;
19364  layout = win->layout;
19365  NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW);
19366  if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW)
19367  return;
19368  layout->row.item_width = 0;
19369  layout->row.item_offset = 0;
19370 }
19371 
19372 NK_API void
19373 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt,
19374  float height, int cols, const float *ratio)
19375 {
19376  int i;
19377  int n_undef = 0;
19378  struct nk_window *win;
19379  struct nk_panel *layout;
19380 
19381  NK_ASSERT(ctx);
19382  NK_ASSERT(ctx->current);
19383  NK_ASSERT(ctx->current->layout);
19384  if (!ctx || !ctx->current || !ctx->current->layout)
19385  return;
19386 
19387  win = ctx->current;
19388  layout = win->layout;
19389  nk_panel_layout(ctx, win, height, cols);
19390  if (fmt == NK_DYNAMIC) {
19391  /* calculate width of undefined widget ratios */
19392  float r = 0;
19393  layout->row.ratio = ratio;
19394  for (i = 0; i < cols; ++i) {
19395  if (ratio[i] < 0.0f)
19396  n_undef++;
19397  else r += ratio[i];
19398  }
19399  r = NK_SATURATE(1.0f - r);
19400  layout->row.type = NK_LAYOUT_DYNAMIC;
19401  layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0;
19402  } else {
19403  layout->row.ratio = ratio;
19404  layout->row.type = NK_LAYOUT_STATIC;
19405  layout->row.item_width = 0;
19406  layout->row.item_offset = 0;
19407  }
19408  layout->row.item_offset = 0;
19409  layout->row.filled = 0;
19410 }
19411 
19412 NK_API void
19414 {
19415  struct nk_window *win;
19416  struct nk_panel *layout;
19417 
19418  NK_ASSERT(ctx);
19419  NK_ASSERT(ctx->current);
19420  NK_ASSERT(ctx->current->layout);
19421  if (!ctx || !ctx->current || !ctx->current->layout)
19422  return;
19423 
19424  win = ctx->current;
19425  layout = win->layout;
19426  nk_panel_layout(ctx, win, height, 1);
19427  layout->row.type = NK_LAYOUT_TEMPLATE;
19428  layout->row.columns = 0;
19429  layout->row.ratio = 0;
19430  layout->row.item_width = 0;
19431  layout->row.item_height = 0;
19432  layout->row.item_offset = 0;
19433  layout->row.filled = 0;
19434  layout->row.item.x = 0;
19435  layout->row.item.y = 0;
19436  layout->row.item.w = 0;
19437  layout->row.item.h = 0;
19438 }
19439 
19440 NK_API void
19442 {
19443  struct nk_window *win;
19444  struct nk_panel *layout;
19445 
19446  NK_ASSERT(ctx);
19447  NK_ASSERT(ctx->current);
19448  NK_ASSERT(ctx->current->layout);
19449  if (!ctx || !ctx->current || !ctx->current->layout)
19450  return;
19451 
19452  win = ctx->current;
19453  layout = win->layout;
19454  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19455  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19456  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19457  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19458  layout->row.templates[layout->row.columns++] = -1.0f;
19459 }
19460 
19461 NK_API void
19462 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width)
19463 {
19464  struct nk_window *win;
19465  struct nk_panel *layout;
19466 
19467  NK_ASSERT(ctx);
19468  NK_ASSERT(ctx->current);
19469  NK_ASSERT(ctx->current->layout);
19470  if (!ctx || !ctx->current || !ctx->current->layout)
19471  return;
19472 
19473  win = ctx->current;
19474  layout = win->layout;
19475  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19476  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19477  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19478  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19479  layout->row.templates[layout->row.columns++] = -min_width;
19480 }
19481 
19482 NK_API void
19484 {
19485  struct nk_window *win;
19486  struct nk_panel *layout;
19487 
19488  NK_ASSERT(ctx);
19489  NK_ASSERT(ctx->current);
19490  NK_ASSERT(ctx->current->layout);
19491  if (!ctx || !ctx->current || !ctx->current->layout)
19492  return;
19493 
19494  win = ctx->current;
19495  layout = win->layout;
19496  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19497  NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19498  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19499  if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return;
19500  layout->row.templates[layout->row.columns++] = width;
19501 }
19502 
19503 NK_API void
19505 {
19506  struct nk_window *win;
19507  struct nk_panel *layout;
19508 
19509  int i = 0;
19510  int variable_count = 0;
19511  int min_variable_count = 0;
19512  float min_fixed_width = 0.0f;
19513  float total_fixed_width = 0.0f;
19514  float max_variable_width = 0.0f;
19515 
19516  NK_ASSERT(ctx);
19517  NK_ASSERT(ctx->current);
19518  NK_ASSERT(ctx->current->layout);
19519  if (!ctx || !ctx->current || !ctx->current->layout)
19520  return;
19521 
19522  win = ctx->current;
19523  layout = win->layout;
19524  NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE);
19525  if (layout->row.type != NK_LAYOUT_TEMPLATE) return;
19526  for (i = 0; i < layout->row.columns; ++i) {
19527  float width = layout->row.templates[i];
19528  if (width >= 0.0f) {
19529  total_fixed_width += width;
19530  min_fixed_width += width;
19531  } else if (width < -1.0f) {
19532  width = -width;
19533  total_fixed_width += width;
19534  max_variable_width = NK_MAX(max_variable_width, width);
19535  variable_count++;
19536  } else {
19537  min_variable_count++;
19538  variable_count++;
19539  }
19540  }
19541  if (variable_count) {
19542  float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
19543  layout->bounds.w, layout->row.columns);
19544  float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count;
19545  int enough_space = var_width >= max_variable_width;
19546  if (!enough_space)
19547  var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count;
19548  for (i = 0; i < layout->row.columns; ++i) {
19549  float *width = &layout->row.templates[i];
19550  *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width;
19551  }
19552  }
19553 }
19554 
19555 NK_API void
19557  float height, int widget_count)
19558 {
19559  struct nk_window *win;
19560  struct nk_panel *layout;
19561 
19562  NK_ASSERT(ctx);
19563  NK_ASSERT(ctx->current);
19564  NK_ASSERT(ctx->current->layout);
19565  if (!ctx || !ctx->current || !ctx->current->layout)
19566  return;
19567 
19568  win = ctx->current;
19569  layout = win->layout;
19570  nk_panel_layout(ctx, win, height, widget_count);
19571  if (fmt == NK_STATIC)
19572  layout->row.type = NK_LAYOUT_STATIC_FREE;
19573  else layout->row.type = NK_LAYOUT_DYNAMIC_FREE;
19574 
19575  layout->row.ratio = 0;
19576  layout->row.filled = 0;
19577  layout->row.item_width = 0;
19578  layout->row.item_offset = 0;
19579 }
19580 
19581 NK_API void
19583 {
19584  struct nk_window *win;
19585  struct nk_panel *layout;
19586 
19587  NK_ASSERT(ctx);
19588  NK_ASSERT(ctx->current);
19589  NK_ASSERT(ctx->current->layout);
19590  if (!ctx || !ctx->current || !ctx->current->layout)
19591  return;
19592 
19593  win = ctx->current;
19594  layout = win->layout;
19595  layout->row.item_width = 0;
19596  layout->row.item_height = 0;
19597  layout->row.item_offset = 0;
19598  nk_zero(&layout->row.item, sizeof(layout->row.item));
19599 }
19600 
19601 NK_API void
19602 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect)
19603 {
19604  struct nk_window *win;
19605  struct nk_panel *layout;
19606 
19607  NK_ASSERT(ctx);
19608  NK_ASSERT(ctx->current);
19609  NK_ASSERT(ctx->current->layout);
19610  if (!ctx || !ctx->current || !ctx->current->layout)
19611  return;
19612 
19613  win = ctx->current;
19614  layout = win->layout;
19615  layout->row.item = rect;
19616 }
19617 
19618 NK_API struct nk_rect
19620 {
19621  struct nk_rect ret;
19622  struct nk_window *win;
19623  struct nk_panel *layout;
19624 
19625  NK_ASSERT(ctx);
19626  NK_ASSERT(ctx->current);
19627  NK_ASSERT(ctx->current->layout);
19628  win = ctx->current;
19629  layout = win->layout;
19630 
19631  ret.x = layout->clip.x;
19632  ret.y = layout->clip.y;
19633  ret.w = layout->clip.w;
19634  ret.h = layout->row.height;
19635  return ret;
19636 }
19637 
19638 NK_API struct nk_rect
19640 {
19641  struct nk_rect ret;
19642  struct nk_window *win;
19643  struct nk_panel *layout;
19644 
19645  NK_ASSERT(ctx);
19646  NK_ASSERT(ctx->current);
19647  NK_ASSERT(ctx->current->layout);
19648  win = ctx->current;
19649  layout = win->layout;
19650 
19651  ret.x = layout->at_x;
19652  ret.y = layout->at_y;
19653  ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0);
19654  ret.h = layout->row.height;
19655  return ret;
19656 }
19657 
19658 NK_API struct nk_vec2
19659 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret)
19660 {
19661  struct nk_window *win;
19662  struct nk_panel *layout;
19663 
19664  NK_ASSERT(ctx);
19665  NK_ASSERT(ctx->current);
19666  NK_ASSERT(ctx->current->layout);
19667  win = ctx->current;
19668  layout = win->layout;
19669 
19670  ret.x += layout->at_x - (float)*layout->offset_x;
19671  ret.y += layout->at_y - (float)*layout->offset_y;
19672  return ret;
19673 }
19674 
19675 NK_API struct nk_vec2
19676 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret)
19677 {
19678  struct nk_window *win;
19679  struct nk_panel *layout;
19680 
19681  NK_ASSERT(ctx);
19682  NK_ASSERT(ctx->current);
19683  NK_ASSERT(ctx->current->layout);
19684  win = ctx->current;
19685  layout = win->layout;
19686 
19687  ret.x += -layout->at_x + (float)*layout->offset_x;
19688  ret.y += -layout->at_y + (float)*layout->offset_y;
19689  return ret;
19690 }
19691 
19692 NK_API struct nk_rect
19694 {
19695  struct nk_window *win;
19696  struct nk_panel *layout;
19697 
19698  NK_ASSERT(ctx);
19699  NK_ASSERT(ctx->current);
19700  NK_ASSERT(ctx->current->layout);
19701  win = ctx->current;
19702  layout = win->layout;
19703 
19704  ret.x += layout->at_x - (float)*layout->offset_x;
19705  ret.y += layout->at_y - (float)*layout->offset_y;
19706  return ret;
19707 }
19708 
19709 NK_API struct nk_rect
19711 {
19712  struct nk_window *win;
19713  struct nk_panel *layout;
19714 
19715  NK_ASSERT(ctx);
19716  NK_ASSERT(ctx->current);
19717  NK_ASSERT(ctx->current->layout);
19718  win = ctx->current;
19719  layout = win->layout;
19720 
19721  ret.x += -layout->at_x + (float)*layout->offset_x;
19722  ret.y += -layout->at_y + (float)*layout->offset_y;
19723  return ret;
19724 }
19725 
19726 NK_INTERN void
19727 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win)
19728 {
19729  struct nk_panel *layout = win->layout;
19730  struct nk_vec2 spacing = ctx->style.window.spacing;
19731  const float row_height = layout->row.height - spacing.y;
19732  nk_panel_layout(ctx, win, row_height, layout->row.columns);
19733 }
19734 
19735 NK_INTERN void
19736 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx,
19737  struct nk_window *win, int modify)
19738 {
19739  struct nk_panel *layout;
19740  const struct nk_style *style;
19741 
19742  struct nk_vec2 spacing;
19743  struct nk_vec2 padding;
19744 
19745  float item_offset = 0;
19746  float item_width = 0;
19747  float item_spacing = 0;
19748  float panel_space = 0;
19749 
19750  NK_ASSERT(ctx);
19751  NK_ASSERT(ctx->current);
19752  NK_ASSERT(ctx->current->layout);
19753  if (!ctx || !ctx->current || !ctx->current->layout)
19754  return;
19755 
19756  win = ctx->current;
19757  layout = win->layout;
19758  style = &ctx->style;
19759  NK_ASSERT(bounds);
19760 
19761  spacing = style->window.spacing;
19762  padding = nk_panel_get_padding(style, layout->type);
19763  panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type,
19764  layout->bounds.w, layout->row.columns);
19765 
19766  /* calculate the width of one item inside the current layout space */
19767  switch (layout->row.type) {
19768  case NK_LAYOUT_DYNAMIC_FIXED: {
19769  /* scaling fixed size widgets item width */
19770  item_width = NK_MAX(1.0f,panel_space-1.0f) / (float)layout->row.columns;
19771  item_offset = (float)layout->row.index * item_width;
19772  item_spacing = (float)layout->row.index * spacing.x;
19773  } break;
19774  case NK_LAYOUT_DYNAMIC_ROW: {
19775  /* scaling single ratio widget width */
19776  item_width = layout->row.item_width * panel_space;
19777  item_offset = layout->row.item_offset;
19778  item_spacing = 0;
19779 
19780  if (modify) {
19781  layout->row.item_offset += item_width + spacing.x;
19782  layout->row.filled += layout->row.item_width;
19783  layout->row.index = 0;
19784  }
19785  } break;
19786  case NK_LAYOUT_DYNAMIC_FREE: {
19787  /* panel width depended free widget placing */
19788  bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x);
19789  bounds->x -= (float)*layout->offset_x;
19790  bounds->y = layout->at_y + (layout->row.height * layout->row.item.y);
19791  bounds->y -= (float)*layout->offset_y;
19792  bounds->w = layout->bounds.w * layout->row.item.w;
19793  bounds->h = layout->row.height * layout->row.item.h;
19794  return;
19795  } break;
19796  case NK_LAYOUT_DYNAMIC: {
19797  /* scaling arrays of panel width ratios for every widget */
19798  float ratio;
19799  NK_ASSERT(layout->row.ratio);
19800  ratio = (layout->row.ratio[layout->row.index] < 0) ?
19801  layout->row.item_width : layout->row.ratio[layout->row.index];
19802 
19803  item_spacing = (float)layout->row.index * spacing.x;
19804  item_width = (ratio * panel_space);
19805  item_offset = layout->row.item_offset;
19806 
19807  if (modify) {
19808  layout->row.item_offset += item_width;
19809  layout->row.filled += ratio;
19810  }
19811  } break;
19812  case NK_LAYOUT_STATIC_FIXED: {
19813  /* non-scaling fixed widgets item width */
19814  item_width = layout->row.item_width;
19815  item_offset = (float)layout->row.index * item_width;
19816  item_spacing = (float)layout->row.index * spacing.x;
19817  } break;
19818  case NK_LAYOUT_STATIC_ROW: {
19819  /* scaling single ratio widget width */
19820  item_width = layout->row.item_width;
19821  item_offset = layout->row.item_offset;
19822  item_spacing = (float)layout->row.index * spacing.x;
19823  if (modify) layout->row.item_offset += item_width;
19824  } break;
19825  case NK_LAYOUT_STATIC_FREE: {
19826  /* free widget placing */
19827  bounds->x = layout->at_x + layout->row.item.x;
19828  bounds->w = layout->row.item.w;
19829  if (((bounds->x + bounds->w) > layout->max_x) && modify)
19830  layout->max_x = (bounds->x + bounds->w);
19831  bounds->x -= (float)*layout->offset_x;
19832  bounds->y = layout->at_y + layout->row.item.y;
19833  bounds->y -= (float)*layout->offset_y;
19834  bounds->h = layout->row.item.h;
19835  return;
19836  } break;
19837  case NK_LAYOUT_STATIC: {
19838  /* non-scaling array of panel pixel width for every widget */
19839  item_spacing = (float)layout->row.index * spacing.x;
19840  item_width = layout->row.ratio[layout->row.index];
19841  item_offset = layout->row.item_offset;
19842  if (modify) layout->row.item_offset += item_width;
19843  } break;
19844  case NK_LAYOUT_TEMPLATE: {
19845  /* stretchy row layout with combined dynamic/static widget width*/
19846  NK_ASSERT(layout->row.index < layout->row.columns);
19847  NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS);
19848  item_width = layout->row.templates[layout->row.index];
19849  item_offset = layout->row.item_offset;
19850  item_spacing = (float)layout->row.index * spacing.x;
19851  if (modify) layout->row.item_offset += item_width;
19852  } break;
19853  default: NK_ASSERT(0); break;
19854  };
19855 
19856  /* set the bounds of the newly allocated widget */
19857  bounds->w = item_width;
19858  bounds->h = layout->row.height - spacing.y;
19859  bounds->y = layout->at_y - (float)*layout->offset_y;
19860  bounds->x = layout->at_x + item_offset + item_spacing + padding.x;
19861  if (((bounds->x + bounds->w) > layout->max_x) && modify)
19862  layout->max_x = bounds->x + bounds->w;
19863  bounds->x -= (float)*layout->offset_x;
19864 }
19865 
19866 NK_INTERN void
19867 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx)
19868 {
19869  struct nk_window *win;
19870  struct nk_panel *layout;
19871 
19872  NK_ASSERT(ctx);
19873  NK_ASSERT(ctx->current);
19874  NK_ASSERT(ctx->current->layout);
19875  if (!ctx || !ctx->current || !ctx->current->layout)
19876  return;
19877 
19878  /* check if the end of the row has been hit and begin new row if so */
19879  win = ctx->current;
19880  layout = win->layout;
19881  if (layout->row.index >= layout->row.columns)
19882  nk_panel_alloc_row(ctx, win);
19883 
19884  /* calculate widget position and size */
19885  nk_layout_widget_space(bounds, ctx, win, nk_true);
19886  layout->row.index++;
19887 }
19888 
19889 NK_INTERN void
19890 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx)
19891 {
19892  float y;
19893  int index;
19894  struct nk_window *win;
19895  struct nk_panel *layout;
19896 
19897  NK_ASSERT(ctx);
19898  NK_ASSERT(ctx->current);
19899  NK_ASSERT(ctx->current->layout);
19900  if (!ctx || !ctx->current || !ctx->current->layout)
19901  return;
19902 
19903  win = ctx->current;
19904  layout = win->layout;
19905  y = layout->at_y;
19906  index = layout->row.index;
19907  if (layout->row.index >= layout->row.columns) {
19908  layout->at_y += layout->row.height;
19909  layout->row.index = 0;
19910  }
19911  nk_layout_widget_space(bounds, ctx, win, nk_false);
19912  layout->at_y = y;
19913  layout->row.index = index;
19914 }
19915 
19916 NK_INTERN int
19917 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type,
19918  struct nk_image *img, const char *title, enum nk_collapse_states *state)
19919 {
19920  struct nk_window *win;
19921  struct nk_panel *layout;
19922  const struct nk_style *style;
19923  struct nk_command_buffer *out;
19924  const struct nk_input *in;
19925  const struct nk_style_button *button;
19926  enum nk_symbol_type symbol;
19927  float row_height;
19928 
19929  struct nk_vec2 item_spacing;
19930  struct nk_rect header = {0,0,0,0};
19931  struct nk_rect sym = {0,0,0,0};
19932  struct nk_text text;
19933 
19934  nk_flags ws = 0;
19935  enum nk_widget_layout_states widget_state;
19936 
19937  NK_ASSERT(ctx);
19938  NK_ASSERT(ctx->current);
19939  NK_ASSERT(ctx->current->layout);
19940  if (!ctx || !ctx->current || !ctx->current->layout)
19941  return 0;
19942 
19943  /* cache some data */
19944  win = ctx->current;
19945  layout = win->layout;
19946  out = &win->buffer;
19947  style = &ctx->style;
19948  item_spacing = style->window.spacing;
19949 
19950  /* calculate header bounds and draw background */
19951  row_height = style->font->height + 2 * style->tab.padding.y;
19952  nk_layout_set_min_row_height(ctx, row_height);
19953  nk_layout_row_dynamic(ctx, row_height, 1);
19955 
19956  widget_state = nk_widget(&header, ctx);
19957  if (type == NK_TREE_TAB) {
19958  const struct nk_style_item *background = &style->tab.background;
19959  if (background->type == NK_STYLE_ITEM_IMAGE) {
19960  nk_draw_image(out, header, &background->data.image, nk_white);
19961  text.background = nk_rgba(0,0,0,0);
19962  } else {
19963  text.background = background->data.color;
19964  nk_fill_rect(out, header, 0, style->tab.border_color);
19965  nk_fill_rect(out, nk_shrink_rect(header, style->tab.border),
19966  style->tab.rounding, background->data.color);
19967  }
19968  } else text.background = style->window.background;
19969 
19970  /* update node state */
19971  in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0;
19972  in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0;
19973  if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT))
19975 
19976  /* select correct button style */
19977  if (*state == NK_MAXIMIZED) {
19978  symbol = style->tab.sym_maximize;
19979  if (type == NK_TREE_TAB)
19980  button = &style->tab.tab_maximize_button;
19981  else button = &style->tab.node_maximize_button;
19982  } else {
19983  symbol = style->tab.sym_minimize;
19984  if (type == NK_TREE_TAB)
19985  button = &style->tab.tab_minimize_button;
19986  else button = &style->tab.node_minimize_button;
19987  }
19988 
19989  {/* draw triangle button */
19990  sym.w = sym.h = style->font->height;
19991  sym.y = header.y + style->tab.padding.y;
19992  sym.x = header.x + style->tab.padding.x;
19993  nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT,
19994  button, 0, style->font);
19995 
19996  if (img) {
19997  /* draw optional image icon */
19998  sym.x = sym.x + sym.w + 4 * item_spacing.x;
19999  nk_draw_image(&win->buffer, sym, img, nk_white);
20000  sym.w = style->font->height + style->tab.spacing.x;}
20001  }
20002 
20003  {/* draw label */
20004  struct nk_rect label;
20005  header.w = NK_MAX(header.w, sym.w + item_spacing.x);
20006  label.x = sym.x + sym.w + item_spacing.x;
20007  label.y = sym.y;
20008  label.w = header.w - (sym.w + item_spacing.y + style->tab.indent);
20009  label.h = style->font->height;
20010  text.text = style->tab.text;
20011  text.padding = nk_vec2(0,0);
20012  nk_widget_text(out, label, title, nk_strlen(title), &text,
20013  NK_TEXT_LEFT, style->font);}
20014 
20015  /* increase x-axis cursor widget position pointer */
20016  if (*state == NK_MAXIMIZED) {
20017  layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent;
20018  layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent);
20019  layout->bounds.w -= (style->tab.indent + style->window.padding.x);
20020  layout->row.tree_depth++;
20021  return nk_true;
20022  } else return nk_false;
20023 }
20024 
20025 NK_INTERN int
20026 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type,
20027  struct nk_image *img, const char *title, enum nk_collapse_states initial_state,
20028  const char *hash, int len, int line)
20029 {
20030  struct nk_window *win = ctx->current;
20031  int title_len = 0;
20032  nk_hash tree_hash = 0;
20033  nk_uint *state = 0;
20034 
20035  /* retrieve tree state from internal widget state tables */
20036  if (!hash) {
20037  title_len = (int)nk_strlen(title);
20038  tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line);
20039  } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line);
20040  state = nk_find_value(win, tree_hash);
20041  if (!state) {
20042  state = nk_add_value(ctx, win, tree_hash, 0);
20043  *state = initial_state;
20044  }
20045  return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state);
20046 }
20047 
20048 NK_API int
20050  const char *title, enum nk_collapse_states *state)
20051 {return nk_tree_state_base(ctx, type, 0, title, state);}
20052 
20053 NK_API int
20055  struct nk_image img, const char *title, enum nk_collapse_states *state)
20056 {return nk_tree_state_base(ctx, type, &img, title, state);}
20057 
20058 NK_API void
20060 {
20061  struct nk_window *win = 0;
20062  struct nk_panel *layout = 0;
20063 
20064  NK_ASSERT(ctx);
20065  NK_ASSERT(ctx->current);
20066  NK_ASSERT(ctx->current->layout);
20067  if (!ctx || !ctx->current || !ctx->current->layout)
20068  return;
20069 
20070  win = ctx->current;
20071  layout = win->layout;
20072  layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x;
20073  layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x;
20074  NK_ASSERT(layout->row.tree_depth);
20075  layout->row.tree_depth--;
20076 }
20077 
20078 NK_API int
20080  const char *title, enum nk_collapse_states initial_state,
20081  const char *hash, int len, int line)
20082 {return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);}
20083 
20084 NK_API int
20086  struct nk_image img, const char *title, enum nk_collapse_states initial_state,
20087  const char *hash, int len,int seed)
20088 {return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);}
20089 
20090 NK_API void
20091 nk_tree_pop(struct nk_context *ctx)
20093 
20094 /*----------------------------------------------------------------
20095  *
20096  * WIDGETS
20097  *
20098  * --------------------------------------------------------------*/
20099 NK_API struct nk_rect
20101 {
20102  struct nk_rect bounds;
20103  NK_ASSERT(ctx);
20104  NK_ASSERT(ctx->current);
20105  if (!ctx || !ctx->current)
20106  return nk_rect(0,0,0,0);
20107  nk_layout_peek(&bounds, ctx);
20108  return bounds;
20109 }
20110 
20111 NK_API struct nk_vec2
20113 {
20114  struct nk_rect bounds;
20115  NK_ASSERT(ctx);
20116  NK_ASSERT(ctx->current);
20117  if (!ctx || !ctx->current)
20118  return nk_vec2(0,0);
20119 
20120  nk_layout_peek(&bounds, ctx);
20121  return nk_vec2(bounds.x, bounds.y);
20122 }
20123 
20124 NK_API struct nk_vec2
20125 nk_widget_size(struct nk_context *ctx)
20126 {
20127  struct nk_rect bounds;
20128  NK_ASSERT(ctx);
20129  NK_ASSERT(ctx->current);
20130  if (!ctx || !ctx->current)
20131  return nk_vec2(0,0);
20132 
20133  nk_layout_peek(&bounds, ctx);
20134  return nk_vec2(bounds.w, bounds.h);
20135 }
20136 
20137 NK_API float
20139 {
20140  struct nk_rect bounds;
20141  NK_ASSERT(ctx);
20142  NK_ASSERT(ctx->current);
20143  if (!ctx || !ctx->current)
20144  return 0;
20145 
20146  nk_layout_peek(&bounds, ctx);
20147  return bounds.w;
20148 }
20149 
20150 NK_API float
20152 {
20153  struct nk_rect bounds;
20154  NK_ASSERT(ctx);
20155  NK_ASSERT(ctx->current);
20156  if (!ctx || !ctx->current)
20157  return 0;
20158 
20159  nk_layout_peek(&bounds, ctx);
20160  return bounds.h;
20161 }
20162 
20163 NK_API int
20165 {
20166  struct nk_rect c, v;
20167  struct nk_rect bounds;
20168  NK_ASSERT(ctx);
20169  NK_ASSERT(ctx->current);
20170  if (!ctx || !ctx->current || ctx->active != ctx->current)
20171  return 0;
20172 
20173  c = ctx->current->layout->clip;
20174  c.x = (float)((int)c.x);
20175  c.y = (float)((int)c.y);
20176  c.w = (float)((int)c.w);
20177  c.h = (float)((int)c.h);
20178 
20179  nk_layout_peek(&bounds, ctx);
20180  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
20181  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
20182  return 0;
20183  return nk_input_is_mouse_hovering_rect(&ctx->input, bounds);
20184 }
20185 
20186 NK_API int
20188 {
20189  struct nk_rect c, v;
20190  struct nk_rect bounds;
20191  NK_ASSERT(ctx);
20192  NK_ASSERT(ctx->current);
20193  if (!ctx || !ctx->current || ctx->active != ctx->current)
20194  return 0;
20195 
20196  c = ctx->current->layout->clip;
20197  c.x = (float)((int)c.x);
20198  c.y = (float)((int)c.y);
20199  c.w = (float)((int)c.w);
20200  c.h = (float)((int)c.h);
20201 
20202  nk_layout_peek(&bounds, ctx);
20203  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
20204  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
20205  return 0;
20206  return nk_input_mouse_clicked(&ctx->input, btn, bounds);
20207 }
20208 
20209 NK_API int
20211 {
20212  struct nk_rect c, v;
20213  struct nk_rect bounds;
20214  NK_ASSERT(ctx);
20215  NK_ASSERT(ctx->current);
20216  if (!ctx || !ctx->current || ctx->active != ctx->current)
20217  return 0;
20218 
20219  c = ctx->current->layout->clip;
20220  c.x = (float)((int)c.x);
20221  c.y = (float)((int)c.y);
20222  c.w = (float)((int)c.w);
20223  c.h = (float)((int)c.h);
20224 
20225  nk_layout_peek(&bounds, ctx);
20226  nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h);
20227  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h))
20228  return 0;
20229  return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down);
20230 }
20231 
20233 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx)
20234 {
20235  struct nk_rect c, v;
20236  struct nk_window *win;
20237  struct nk_panel *layout;
20238  const struct nk_input *in;
20239 
20240  NK_ASSERT(ctx);
20241  NK_ASSERT(ctx->current);
20242  NK_ASSERT(ctx->current->layout);
20243  if (!ctx || !ctx->current || !ctx->current->layout)
20244  return NK_WIDGET_INVALID;
20245 
20246  /* allocate space and check if the widget needs to be updated and drawn */
20247  nk_panel_alloc_space(bounds, ctx);
20248  win = ctx->current;
20249  layout = win->layout;
20250  in = &ctx->input;
20251  c = layout->clip;
20252 
20253  /* if one of these triggers you forgot to add an `if` condition around either
20254  a window, group, popup, combobox or contextual menu `begin` and `end` block.
20255  Example:
20256  if (nk_begin(...) {...} nk_end(...); or
20257  if (nk_group_begin(...) { nk_group_end(...);} */
20258  NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED));
20259  NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN));
20260  NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED));
20261 
20262  /* need to convert to int here to remove floating point errors */
20263  bounds->x = (float)((int)bounds->x);
20264  bounds->y = (float)((int)bounds->y);
20265  bounds->w = (float)((int)bounds->w);
20266  bounds->h = (float)((int)bounds->h);
20267 
20268  c.x = (float)((int)c.x);
20269  c.y = (float)((int)c.y);
20270  c.w = (float)((int)c.w);
20271  c.h = (float)((int)c.h);
20272 
20273  nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h);
20274  if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h))
20275  return NK_WIDGET_INVALID;
20276  if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h))
20277  return NK_WIDGET_ROM;
20278  return NK_WIDGET_VALID;
20279 }
20280 
20282 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx,
20283  struct nk_vec2 item_padding)
20284 {
20285  /* update the bounds to stand without padding */
20286  struct nk_window *win;
20287  struct nk_style *style;
20288  struct nk_panel *layout;
20290  struct nk_vec2 panel_padding;
20291 
20292  NK_ASSERT(ctx);
20293  NK_ASSERT(ctx->current);
20294  NK_ASSERT(ctx->current->layout);
20295  if (!ctx || !ctx->current || !ctx->current->layout)
20296  return NK_WIDGET_INVALID;
20297 
20298  win = ctx->current;
20299  style = &ctx->style;
20300  layout = win->layout;
20301  state = nk_widget(bounds, ctx);
20302 
20303  panel_padding = nk_panel_get_padding(style, layout->type);
20304  if (layout->row.index == 1) {
20305  bounds->w += panel_padding.x;
20306  bounds->x -= panel_padding.x;
20307  } else bounds->x -= item_padding.x;
20308 
20309  if (layout->row.index == layout->row.columns)
20310  bounds->w += panel_padding.x;
20311  else bounds->w += item_padding.x;
20312  return state;
20313 }
20314 
20315 /*----------------------------------------------------------------
20316  *
20317  * MISC
20318  *
20319  * --------------------------------------------------------------*/
20320 NK_API void
20321 nk_spacing(struct nk_context *ctx, int cols)
20322 {
20323  struct nk_window *win;
20324  struct nk_panel *layout;
20325  struct nk_rect none;
20326  int i, index, rows;
20327 
20328  NK_ASSERT(ctx);
20329  NK_ASSERT(ctx->current);
20330  NK_ASSERT(ctx->current->layout);
20331  if (!ctx || !ctx->current || !ctx->current->layout)
20332  return;
20333 
20334  /* spacing over row boundaries */
20335  win = ctx->current;
20336  layout = win->layout;
20337  index = (layout->row.index + cols) % layout->row.columns;
20338  rows = (layout->row.index + cols) / layout->row.columns;
20339  if (rows) {
20340  for (i = 0; i < rows; ++i)
20341  nk_panel_alloc_row(ctx, win);
20342  cols = index;
20343  }
20344  /* non table layout need to allocate space */
20345  if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED &&
20346  layout->row.type != NK_LAYOUT_STATIC_FIXED) {
20347  for (i = 0; i < cols; ++i)
20348  nk_panel_alloc_space(&none, ctx);
20349  }
20350  layout->row.index = index;
20351 }
20352 
20353 /*----------------------------------------------------------------
20354  *
20355  * TEXT
20356  *
20357  * --------------------------------------------------------------*/
20358 NK_API void
20359 nk_text_colored(struct nk_context *ctx, const char *str, int len,
20360  nk_flags alignment, struct nk_color color)
20361 {
20362  struct nk_window *win;
20363  const struct nk_style *style;
20364 
20365  struct nk_vec2 item_padding;
20366  struct nk_rect bounds;
20367  struct nk_text text;
20368 
20369  NK_ASSERT(ctx);
20370  NK_ASSERT(ctx->current);
20371  NK_ASSERT(ctx->current->layout);
20372  if (!ctx || !ctx->current || !ctx->current->layout) return;
20373 
20374  win = ctx->current;
20375  style = &ctx->style;
20376  nk_panel_alloc_space(&bounds, ctx);
20377  item_padding = style->text.padding;
20378 
20379  text.padding.x = item_padding.x;
20380  text.padding.y = item_padding.y;
20381  text.background = style->window.background;
20382  text.text = color;
20383  nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font);
20384 }
20385 
20386 NK_API void
20387 nk_text_wrap_colored(struct nk_context *ctx, const char *str,
20388  int len, struct nk_color color)
20389 {
20390  struct nk_window *win;
20391  const struct nk_style *style;
20392 
20393  struct nk_vec2 item_padding;
20394  struct nk_rect bounds;
20395  struct nk_text text;
20396 
20397  NK_ASSERT(ctx);
20398  NK_ASSERT(ctx->current);
20399  NK_ASSERT(ctx->current->layout);
20400  if (!ctx || !ctx->current || !ctx->current->layout) return;
20401 
20402  win = ctx->current;
20403  style = &ctx->style;
20404  nk_panel_alloc_space(&bounds, ctx);
20405  item_padding = style->text.padding;
20406 
20407  text.padding.x = item_padding.x;
20408  text.padding.y = item_padding.y;
20409  text.background = style->window.background;
20410  text.text = color;
20411  nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font);
20412 }
20413 
20414 #ifdef NK_INCLUDE_STANDARD_VARARGS
20415 NK_API void
20416 nk_labelf_colored(struct nk_context *ctx, nk_flags flags,
20417  struct nk_color color, const char *fmt, ...)
20418 {
20419  char buf[256];
20420  va_list args;
20421  va_start(args, fmt);
20422  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20424  va_end(args);
20425 }
20426 
20427 NK_API void
20428 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color,
20429  const char *fmt, ...)
20430 {
20431  char buf[256];
20432  va_list args;
20433  va_start(args, fmt);
20434  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20436  va_end(args);
20437 }
20438 
20439 NK_API void
20440 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...)
20441 {
20442  char buf[256];
20443  va_list args;
20444  va_start(args, fmt);
20445  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20446  nk_label(ctx, buf, flags);
20447  va_end(args);
20448 }
20449 
20450 NK_API void
20451 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...)
20452 {
20453  char buf[256];
20454  va_list args;
20455  va_start(args, fmt);
20456  nk_strfmt(buf, NK_LEN(buf), fmt, args);
20457  nk_label_wrap(ctx, buf);
20458  va_end(args);
20459 }
20460 
20461 NK_API void
20462 nk_value_bool(struct nk_context *ctx, const char *prefix, int value)
20463 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));}
20464 
20465 NK_API void
20466 nk_value_int(struct nk_context *ctx, const char *prefix, int value)
20467 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);}
20468 
20469 NK_API void
20470 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value)
20471 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);}
20472 
20473 NK_API void
20474 nk_value_float(struct nk_context *ctx, const char *prefix, float value)
20475 {
20476  double double_value = (double)value;
20477  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value);
20478 }
20479 
20480 NK_API void
20481 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c)
20482 {nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);}
20483 
20484 NK_API void
20485 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color)
20486 {
20487  double c[4]; nk_color_dv(c, color);
20488  nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)",
20489  p, c[0], c[1], c[2], c[3]);
20490 }
20491 
20492 NK_API void
20493 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color)
20494 {
20495  char hex[16];
20497  nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex);
20498 }
20499 #endif
20500 
20501 NK_API void
20502 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment)
20503 {
20504  NK_ASSERT(ctx);
20505  if (!ctx) return;
20506  nk_text_colored(ctx, str, len, alignment, ctx->style.text.color);
20507 }
20508 
20509 NK_API void
20510 nk_text_wrap(struct nk_context *ctx, const char *str, int len)
20511 {
20512  NK_ASSERT(ctx);
20513  if (!ctx) return;
20514  nk_text_wrap_colored(ctx, str, len, ctx->style.text.color);
20515 }
20516 
20517 NK_API void
20518 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment)
20519 {nk_text(ctx, str, nk_strlen(str), alignment);}
20520 
20521 NK_API void
20522 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align,
20523  struct nk_color color)
20525 
20526 NK_API void
20527 nk_label_wrap(struct nk_context *ctx, const char *str)
20529 
20530 NK_API void
20531 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color)
20533 
20534 NK_API void
20535 nk_image(struct nk_context *ctx, struct nk_image img)
20536 {
20537  struct nk_window *win;
20538  struct nk_rect bounds;
20539 
20540  NK_ASSERT(ctx);
20541  NK_ASSERT(ctx->current);
20542  NK_ASSERT(ctx->current->layout);
20543  if (!ctx || !ctx->current || !ctx->current->layout) return;
20544 
20545  win = ctx->current;
20546  if (!nk_widget(&bounds, ctx)) return;
20547  nk_draw_image(&win->buffer, bounds, &img, nk_white);
20548 }
20549 
20550 /*----------------------------------------------------------------
20551  *
20552  * BUTTON
20553  *
20554  * --------------------------------------------------------------*/
20555 NK_API void
20557 {
20558  NK_ASSERT(ctx);
20559  if (!ctx) return;
20560  ctx->button_behavior = behavior;
20561 }
20562 
20563 NK_API int
20565 {
20566  struct nk_config_stack_button_behavior *button_stack;
20567  struct nk_config_stack_button_behavior_element *element;
20568 
20569  NK_ASSERT(ctx);
20570  if (!ctx) return 0;
20571 
20572  button_stack = &ctx->stacks.button_behaviors;
20573  NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements));
20574  if (button_stack->head >= (int)NK_LEN(button_stack->elements))
20575  return 0;
20576 
20577  element = &button_stack->elements[button_stack->head++];
20578  element->address = &ctx->button_behavior;
20579  element->old_value = ctx->button_behavior;
20580  ctx->button_behavior = behavior;
20581  return 1;
20582 }
20583 
20584 NK_API int
20586 {
20587  struct nk_config_stack_button_behavior *button_stack;
20588  struct nk_config_stack_button_behavior_element *element;
20589 
20590  NK_ASSERT(ctx);
20591  if (!ctx) return 0;
20592 
20593  button_stack = &ctx->stacks.button_behaviors;
20594  NK_ASSERT(button_stack->head > 0);
20595  if (button_stack->head < 1)
20596  return 0;
20597 
20598  element = &button_stack->elements[--button_stack->head];
20599  *element->address = element->old_value;
20600  return 1;
20601 }
20602 
20603 NK_API int
20605  const struct nk_style_button *style, const char *title, int len)
20606 {
20607  struct nk_window *win;
20608  struct nk_panel *layout;
20609  const struct nk_input *in;
20610 
20611  struct nk_rect bounds;
20613 
20614  NK_ASSERT(ctx);
20615  NK_ASSERT(style);
20616  NK_ASSERT(ctx->current);
20617  NK_ASSERT(ctx->current->layout);
20618  if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0;
20619 
20620  win = ctx->current;
20621  layout = win->layout;
20622  state = nk_widget(&bounds, ctx);
20623 
20624  if (!state) return 0;
20625  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20626  return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
20627  title, len, style->text_alignment, ctx->button_behavior,
20628  style, in, ctx->style.font);
20629 }
20630 
20631 NK_API int
20632 nk_button_text(struct nk_context *ctx, const char *title, int len)
20633 {
20634  NK_ASSERT(ctx);
20635  if (!ctx) return 0;
20636  return nk_button_text_styled(ctx, &ctx->style.button, title, len);
20637 }
20638 
20640  const struct nk_style_button *style, const char *title)
20641 {return nk_button_text_styled(ctx, style, title, nk_strlen(title));}
20642 
20643 NK_API int nk_button_label(struct nk_context *ctx, const char *title)
20644 {return nk_button_text(ctx, title, nk_strlen(title));}
20645 
20646 NK_API int
20647 nk_button_color(struct nk_context *ctx, struct nk_color color)
20648 {
20649  struct nk_window *win;
20650  struct nk_panel *layout;
20651  const struct nk_input *in;
20652  struct nk_style_button button;
20653 
20654  int ret = 0;
20655  struct nk_rect bounds;
20656  struct nk_rect content;
20658 
20659  NK_ASSERT(ctx);
20660  NK_ASSERT(ctx->current);
20661  NK_ASSERT(ctx->current->layout);
20662  if (!ctx || !ctx->current || !ctx->current->layout)
20663  return 0;
20664 
20665  win = ctx->current;
20666  layout = win->layout;
20667 
20668  state = nk_widget(&bounds, ctx);
20669  if (!state) return 0;
20670  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20671 
20672  button = ctx->style.button;
20673  button.normal = nk_style_item_color(color);
20674  button.hover = nk_style_item_color(color);
20675  button.active = nk_style_item_color(color);
20676  ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds,
20677  &button, in, ctx->button_behavior, &content);
20678  nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button);
20679  return ret;
20680 }
20681 
20682 NK_API int
20684  const struct nk_style_button *style, enum nk_symbol_type symbol)
20685 {
20686  struct nk_window *win;
20687  struct nk_panel *layout;
20688  const struct nk_input *in;
20689 
20690  struct nk_rect bounds;
20692 
20693  NK_ASSERT(ctx);
20694  NK_ASSERT(ctx->current);
20695  NK_ASSERT(ctx->current->layout);
20696  if (!ctx || !ctx->current || !ctx->current->layout)
20697  return 0;
20698 
20699  win = ctx->current;
20700  layout = win->layout;
20701  state = nk_widget(&bounds, ctx);
20702  if (!state) return 0;
20703  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20704  return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20705  symbol, ctx->button_behavior, style, in, ctx->style.font);
20706 }
20707 
20708 NK_API int
20709 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol)
20710 {
20711  NK_ASSERT(ctx);
20712  if (!ctx) return 0;
20713  return nk_button_symbol_styled(ctx, &ctx->style.button, symbol);
20714 }
20715 
20716 NK_API int
20717 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style,
20718  struct nk_image img)
20719 {
20720  struct nk_window *win;
20721  struct nk_panel *layout;
20722  const struct nk_input *in;
20723 
20724  struct nk_rect bounds;
20726 
20727  NK_ASSERT(ctx);
20728  NK_ASSERT(ctx->current);
20729  NK_ASSERT(ctx->current->layout);
20730  if (!ctx || !ctx->current || !ctx->current->layout)
20731  return 0;
20732 
20733  win = ctx->current;
20734  layout = win->layout;
20735 
20736  state = nk_widget(&bounds, ctx);
20737  if (!state) return 0;
20738  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20739  return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds,
20740  img, ctx->button_behavior, style, in);
20741 }
20742 
20743 NK_API int
20744 nk_button_image(struct nk_context *ctx, struct nk_image img)
20745 {
20746  NK_ASSERT(ctx);
20747  if (!ctx) return 0;
20748  return nk_button_image_styled(ctx, &ctx->style.button, img);
20749 }
20750 
20751 NK_API int
20753  const struct nk_style_button *style, enum nk_symbol_type symbol,
20754  const char *text, int len, nk_flags align)
20755 {
20756  struct nk_window *win;
20757  struct nk_panel *layout;
20758  const struct nk_input *in;
20759 
20760  struct nk_rect bounds;
20762 
20763  NK_ASSERT(ctx);
20764  NK_ASSERT(ctx->current);
20765  NK_ASSERT(ctx->current->layout);
20766  if (!ctx || !ctx->current || !ctx->current->layout)
20767  return 0;
20768 
20769  win = ctx->current;
20770  layout = win->layout;
20771 
20772  state = nk_widget(&bounds, ctx);
20773  if (!state) return 0;
20774  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20775  return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
20776  symbol, text, len, align, ctx->button_behavior,
20777  style, ctx->style.font, in);
20778 }
20779 
20780 NK_API int
20781 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol,
20782  const char* text, int len, nk_flags align)
20783 {
20784  NK_ASSERT(ctx);
20785  if (!ctx) return 0;
20786  return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align);
20787 }
20788 
20789 NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol,
20790  const char *label, nk_flags align)
20791 {return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);}
20792 
20794  const struct nk_style_button *style, enum nk_symbol_type symbol,
20795  const char *title, nk_flags align)
20796 {return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);}
20797 
20798 NK_API int
20800  const struct nk_style_button *style, struct nk_image img, const char *text,
20801  int len, nk_flags align)
20802 {
20803  struct nk_window *win;
20804  struct nk_panel *layout;
20805  const struct nk_input *in;
20806 
20807  struct nk_rect bounds;
20809 
20810  NK_ASSERT(ctx);
20811  NK_ASSERT(ctx->current);
20812  NK_ASSERT(ctx->current->layout);
20813  if (!ctx || !ctx->current || !ctx->current->layout)
20814  return 0;
20815 
20816  win = ctx->current;
20817  layout = win->layout;
20818 
20819  state = nk_widget(&bounds, ctx);
20820  if (!state) return 0;
20821  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20822  return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
20823  bounds, img, text, len, align, ctx->button_behavior,
20824  style, ctx->style.font, in);
20825 }
20826 
20827 NK_API int
20829  const char *text, int len, nk_flags align)
20830 {return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);}
20831 
20832 
20834  const char *label, nk_flags align)
20836 
20838  const struct nk_style_button *style, struct nk_image img,
20839  const char *label, nk_flags text_alignment)
20841 
20842 /*----------------------------------------------------------------
20843  *
20844  * SELECTABLE
20845  *
20846  * --------------------------------------------------------------*/
20847 NK_API int
20848 nk_selectable_text(struct nk_context *ctx, const char *str, int len,
20849  nk_flags align, int *value)
20850 {
20851  struct nk_window *win;
20852  struct nk_panel *layout;
20853  const struct nk_input *in;
20854  const struct nk_style *style;
20855 
20857  struct nk_rect bounds;
20858 
20859  NK_ASSERT(ctx);
20860  NK_ASSERT(value);
20861  NK_ASSERT(ctx->current);
20862  NK_ASSERT(ctx->current->layout);
20863  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20864  return 0;
20865 
20866  win = ctx->current;
20867  layout = win->layout;
20868  style = &ctx->style;
20869 
20870  state = nk_widget(&bounds, ctx);
20871  if (!state) return 0;
20872  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20873  return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds,
20874  str, len, align, value, &style->selectable, in, style->font);
20875 }
20876 
20877 NK_API int
20879  const char *str, int len, nk_flags align, int *value)
20880 {
20881  struct nk_window *win;
20882  struct nk_panel *layout;
20883  const struct nk_input *in;
20884  const struct nk_style *style;
20885 
20887  struct nk_rect bounds;
20888 
20889  NK_ASSERT(ctx);
20890  NK_ASSERT(value);
20891  NK_ASSERT(ctx->current);
20892  NK_ASSERT(ctx->current->layout);
20893  if (!ctx || !ctx->current || !ctx->current->layout || !value)
20894  return 0;
20895 
20896  win = ctx->current;
20897  layout = win->layout;
20898  style = &ctx->style;
20899 
20900  state = nk_widget(&bounds, ctx);
20901  if (!state) return 0;
20902  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20903  return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds,
20904  str, len, align, value, &img, &style->selectable, in, style->font);
20905 }
20906 
20907 NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len,
20908  nk_flags align, int value)
20909 {nk_selectable_text(ctx, str, len, align, &value);return value;}
20910 
20911 NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value)
20913 
20915  const char *str, nk_flags align, int *value)
20917 
20918 NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value)
20920 
20922  const char *str, nk_flags align, int value)
20924 
20926  const char *str, int len, nk_flags align, int value)
20928 
20929 /*----------------------------------------------------------------
20930  *
20931  * CHECKBOX
20932  *
20933  * --------------------------------------------------------------*/
20934 NK_API int
20935 nk_check_text(struct nk_context *ctx, const char *text, int len, int active)
20936 {
20937  struct nk_window *win;
20938  struct nk_panel *layout;
20939  const struct nk_input *in;
20940  const struct nk_style *style;
20941 
20942  struct nk_rect bounds;
20944 
20945  NK_ASSERT(ctx);
20946  NK_ASSERT(ctx->current);
20947  NK_ASSERT(ctx->current->layout);
20948  if (!ctx || !ctx->current || !ctx->current->layout)
20949  return active;
20950 
20951  win = ctx->current;
20952  style = &ctx->style;
20953  layout = win->layout;
20954 
20955  state = nk_widget(&bounds, ctx);
20956  if (!state) return active;
20957  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
20958  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active,
20959  text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font);
20960  return active;
20961 }
20962 
20963 NK_API unsigned int
20964 nk_check_flags_text(struct nk_context *ctx, const char *text, int len,
20965  unsigned int flags, unsigned int value)
20966 {
20967  int old_active;
20968  NK_ASSERT(ctx);
20969  NK_ASSERT(text);
20970  if (!ctx || !text) return flags;
20971  old_active = (int)((flags & value) & value);
20972  if (nk_check_text(ctx, text, len, old_active))
20973  flags |= value;
20974  else flags &= ~value;
20975  return flags;
20976 }
20977 
20978 NK_API int
20979 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active)
20980 {
20981  int old_val;
20982  NK_ASSERT(ctx);
20983  NK_ASSERT(text);
20984  NK_ASSERT(active);
20985  if (!ctx || !text || !active) return 0;
20986  old_val = *active;
20987  *active = nk_check_text(ctx, text, len, *active);
20988  return old_val != *active;
20989 }
20990 
20991 NK_API int
20992 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len,
20993  unsigned int *flags, unsigned int value)
20994 {
20995  int active;
20996  NK_ASSERT(ctx);
20997  NK_ASSERT(text);
20998  NK_ASSERT(flags);
20999  if (!ctx || !text || !flags) return 0;
21000 
21001  active = (int)((*flags & value) & value);
21002  if (nk_checkbox_text(ctx, text, len, &active)) {
21003  if (active) *flags |= value;
21004  else *flags &= ~value;
21005  return 1;
21006  }
21007  return 0;
21008 }
21009 
21010 NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active)
21011 {return nk_check_text(ctx, label, nk_strlen(label), active);}
21012 
21013 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label,
21014  unsigned int flags, unsigned int value)
21016 
21017 NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active)
21018 {return nk_checkbox_text(ctx, label, nk_strlen(label), active);}
21019 
21020 NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label,
21021  unsigned int *flags, unsigned int value)
21023 
21024 /*----------------------------------------------------------------
21025  *
21026  * OPTION
21027  *
21028  * --------------------------------------------------------------*/
21029 NK_API int
21030 nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active)
21031 {
21032  struct nk_window *win;
21033  struct nk_panel *layout;
21034  const struct nk_input *in;
21035  const struct nk_style *style;
21036 
21037  struct nk_rect bounds;
21039 
21040  NK_ASSERT(ctx);
21041  NK_ASSERT(ctx->current);
21042  NK_ASSERT(ctx->current->layout);
21043  if (!ctx || !ctx->current || !ctx->current->layout)
21044  return is_active;
21045 
21046  win = ctx->current;
21047  style = &ctx->style;
21048  layout = win->layout;
21049 
21050  state = nk_widget(&bounds, ctx);
21051  if (!state) return state;
21052  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21053  nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active,
21054  text, len, NK_TOGGLE_OPTION, &style->option, in, style->font);
21055  return is_active;
21056 }
21057 
21058 NK_API int
21059 nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active)
21060 {
21061  int old_value;
21062  NK_ASSERT(ctx);
21063  NK_ASSERT(text);
21064  NK_ASSERT(active);
21065  if (!ctx || !text || !active) return 0;
21066  old_value = *active;
21067  *active = nk_option_text(ctx, text, len, old_value);
21068  return old_value != *active;
21069 }
21070 
21071 NK_API int
21072 nk_option_label(struct nk_context *ctx, const char *label, int active)
21073 {return nk_option_text(ctx, label, nk_strlen(label), active);}
21074 
21075 NK_API int
21076 nk_radio_label(struct nk_context *ctx, const char *label, int *active)
21077 {return nk_radio_text(ctx, label, nk_strlen(label), active);}
21078 
21079 /*----------------------------------------------------------------
21080  *
21081  * SLIDER
21082  *
21083  * --------------------------------------------------------------*/
21084 NK_API int
21085 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value,
21086  float value_step)
21087 {
21088  struct nk_window *win;
21089  struct nk_panel *layout;
21090  struct nk_input *in;
21091  const struct nk_style *style;
21092 
21093  int ret = 0;
21094  float old_value;
21095  struct nk_rect bounds;
21097 
21098  NK_ASSERT(ctx);
21099  NK_ASSERT(ctx->current);
21100  NK_ASSERT(ctx->current->layout);
21101  NK_ASSERT(value);
21102  if (!ctx || !ctx->current || !ctx->current->layout || !value)
21103  return ret;
21104 
21105  win = ctx->current;
21106  style = &ctx->style;
21107  layout = win->layout;
21108 
21109  state = nk_widget(&bounds, ctx);
21110  if (!state) return ret;
21111  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21112 
21113  old_value = *value;
21114  *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value,
21115  old_value, max_value, value_step, &style->slider, in, style->font);
21116  return (old_value > *value || old_value < *value);
21117 }
21118 
21119 NK_API float
21120 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step)
21121 {
21122  nk_slider_float(ctx, min, &val, max, step); return val;
21123 }
21124 
21125 NK_API int
21126 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step)
21127 {
21128  float value = (float)val;
21129  nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
21130  return (int)value;
21131 }
21132 
21133 NK_API int
21134 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step)
21135 {
21136  int ret;
21137  float value = (float)*val;
21138  ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step);
21139  *val = (int)value;
21140  return ret;
21141 }
21142 
21143 /*----------------------------------------------------------------
21144  *
21145  * PROGRESSBAR
21146  *
21147  * --------------------------------------------------------------*/
21148 NK_API int
21149 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable)
21150 {
21151  struct nk_window *win;
21152  struct nk_panel *layout;
21153  const struct nk_style *style;
21154  const struct nk_input *in;
21155 
21156  struct nk_rect bounds;
21158  nk_size old_value;
21159 
21160  NK_ASSERT(ctx);
21161  NK_ASSERT(cur);
21162  NK_ASSERT(ctx->current);
21163  NK_ASSERT(ctx->current->layout);
21164  if (!ctx || !ctx->current || !ctx->current->layout || !cur)
21165  return 0;
21166 
21167  win = ctx->current;
21168  style = &ctx->style;
21169  layout = win->layout;
21170  state = nk_widget(&bounds, ctx);
21171  if (!state) return 0;
21172 
21173  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21174  old_value = *cur;
21175  *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds,
21176  *cur, max, is_modifyable, &style->progress, in);
21177  return (*cur != old_value);
21178 }
21179 
21180 NK_API nk_size nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable)
21181 {nk_progress(ctx, &cur, max, modifyable);return cur;}
21182 
21183 /*----------------------------------------------------------------
21184  *
21185  * EDIT
21186  *
21187  * --------------------------------------------------------------*/
21188 NK_API void
21190 {
21191  nk_hash hash;
21192  struct nk_window *win;
21193 
21194  NK_ASSERT(ctx);
21195  NK_ASSERT(ctx->current);
21196  if (!ctx || !ctx->current) return;
21197 
21198  win = ctx->current;
21199  hash = win->edit.seq;
21200  win->edit.active = nk_true;
21201  win->edit.name = hash;
21204 }
21205 
21206 NK_API void
21208 {
21209  struct nk_window *win;
21210  NK_ASSERT(ctx);
21211  NK_ASSERT(ctx->current);
21212  if (!ctx || !ctx->current) return;
21213 
21214  win = ctx->current;
21215  win->edit.active = nk_false;
21216  win->edit.name = 0;
21217 }
21218 
21221  char *memory, int *len, int max, nk_plugin_filter filter)
21222 {
21223  nk_hash hash;
21224  nk_flags state;
21225  struct nk_text_edit *edit;
21226  struct nk_window *win;
21227 
21228  NK_ASSERT(ctx);
21229  NK_ASSERT(memory);
21230  NK_ASSERT(len);
21231  if (!ctx || !memory || !len)
21232  return 0;
21233 
21235  win = ctx->current;
21236  hash = win->edit.seq;
21237  edit = &ctx->text_edit;
21238  nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)?
21240 
21241  if (win->edit.active && hash == win->edit.name) {
21242  if (flags & NK_EDIT_NO_CURSOR)
21243  edit->cursor = nk_utf_len(memory, *len);
21244  else edit->cursor = win->edit.cursor;
21245  if (!(flags & NK_EDIT_SELECTABLE)) {
21246  edit->select_start = win->edit.cursor;
21247  edit->select_end = win->edit.cursor;
21248  } else {
21249  edit->select_start = win->edit.sel_start;
21250  edit->select_end = win->edit.sel_end;
21251  }
21252  edit->mode = win->edit.mode;
21253  edit->scrollbar.x = (float)win->edit.scrollbar.x;
21254  edit->scrollbar.y = (float)win->edit.scrollbar.y;
21255  edit->active = nk_true;
21256  } else edit->active = nk_false;
21257 
21258  max = NK_MAX(1, max);
21259  *len = NK_MIN(*len, max-1);
21260  nk_str_init_fixed(&edit->string, memory, (nk_size)max);
21261  edit->string.buffer.allocated = (nk_size)*len;
21262  edit->string.len = nk_utf_len(memory, *len);
21264  *len = (int)edit->string.buffer.allocated;
21265 
21266  if (edit->active) {
21267  win->edit.cursor = edit->cursor;
21268  win->edit.sel_start = edit->select_start;
21269  win->edit.sel_end = edit->select_end;
21270  win->edit.mode = edit->mode;
21273  }
21274  return state;
21275 }
21276 
21280 {
21281  struct nk_window *win;
21282  struct nk_style *style;
21283  struct nk_input *in;
21284 
21286  struct nk_rect bounds;
21287 
21288  nk_flags ret_flags = 0;
21289  unsigned char prev_state;
21290  nk_hash hash;
21291 
21292  /* make sure correct values */
21293  NK_ASSERT(ctx);
21294  NK_ASSERT(edit);
21295  NK_ASSERT(ctx->current);
21296  NK_ASSERT(ctx->current->layout);
21297  if (!ctx || !ctx->current || !ctx->current->layout)
21298  return 0;
21299 
21300  win = ctx->current;
21301  style = &ctx->style;
21302  state = nk_widget(&bounds, ctx);
21303  if (!state) return state;
21304  in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21305 
21306  /* check if edit is currently hot item */
21307  hash = win->edit.seq++;
21308  if (win->edit.active && hash == win->edit.name) {
21309  if (flags & NK_EDIT_NO_CURSOR)
21310  edit->cursor = edit->string.len;
21311  if (!(flags & NK_EDIT_SELECTABLE)) {
21312  edit->select_start = edit->cursor;
21313  edit->select_end = edit->cursor;
21314  }
21315  if (flags & NK_EDIT_CLIPBOARD)
21316  edit->clip = ctx->clip;
21317  edit->active = win->edit.active;
21318  } else edit->active = nk_false;
21319  edit->mode = win->edit.mode;
21320 
21322  prev_state = (unsigned char)edit->active;
21323  in = (flags & NK_EDIT_READ_ONLY) ? 0: in;
21324  ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags,
21325  filter, edit, &style->edit, in, style->font);
21326 
21327  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
21328  ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT];
21329  if (edit->active && prev_state != edit->active) {
21330  /* current edit is now hot */
21331  win->edit.active = nk_true;
21332  win->edit.name = hash;
21333  } else if (prev_state && !edit->active) {
21334  /* current edit is now cold */
21335  win->edit.active = nk_false;
21336  }
21337  return ret_flags;
21338 }
21339 
21342  char *buffer, int max, nk_plugin_filter filter)
21343 {
21344  nk_flags result;
21345  int len = nk_strlen(buffer);
21347  buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0';
21348  return result;
21349 }
21350 
21351 /*----------------------------------------------------------------
21352  *
21353  * PROPERTY
21354  *
21355  * --------------------------------------------------------------*/
21356 NK_INTERN struct nk_property_variant
21357 nk_property_variant_int(int value, int min_value, int max_value, int step)
21358 {
21359  struct nk_property_variant result;
21360  result.kind = NK_PROPERTY_INT;
21361  result.value.i = value;
21362  result.min_value.i = min_value;
21363  result.max_value.i = max_value;
21364  result.step.i = step;
21365  return result;
21366 }
21367 
21368 NK_INTERN struct nk_property_variant
21369 nk_property_variant_float(float value, float min_value, float max_value, float step)
21370 {
21371  struct nk_property_variant result;
21372  result.kind = NK_PROPERTY_FLOAT;
21373  result.value.f = value;
21374  result.min_value.f = min_value;
21375  result.max_value.f = max_value;
21376  result.step.f = step;
21377  return result;
21378 }
21379 
21380 NK_INTERN struct nk_property_variant
21381 nk_property_variant_double(double value, double min_value, double max_value,
21382  double step)
21383 {
21384  struct nk_property_variant result;
21385  result.kind = NK_PROPERTY_DOUBLE;
21386  result.value.d = value;
21387  result.min_value.d = min_value;
21388  result.max_value.d = max_value;
21389  result.step.d = step;
21390  return result;
21391 }
21392 
21393 NK_INTERN void
21394 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant,
21395  float inc_per_pixel, const enum nk_property_filter filter)
21396 {
21397  struct nk_window *win;
21398  struct nk_panel *layout;
21399  struct nk_input *in;
21400  const struct nk_style *style;
21401 
21402  struct nk_rect bounds;
21404 
21405  int *state = 0;
21406  nk_hash hash = 0;
21407  char *buffer = 0;
21408  int *len = 0;
21409  int *cursor = 0;
21410  int *select_begin = 0;
21411  int *select_end = 0;
21412  int old_state;
21413 
21414  char dummy_buffer[NK_MAX_NUMBER_BUFFER];
21415  int dummy_state = NK_PROPERTY_DEFAULT;
21416  int dummy_length = 0;
21417  int dummy_cursor = 0;
21418  int dummy_select_begin = 0;
21419  int dummy_select_end = 0;
21420 
21421  NK_ASSERT(ctx);
21422  NK_ASSERT(ctx->current);
21423  NK_ASSERT(ctx->current->layout);
21424  if (!ctx || !ctx->current || !ctx->current->layout)
21425  return;
21426 
21427  win = ctx->current;
21428  layout = win->layout;
21429  style = &ctx->style;
21430  s = nk_widget(&bounds, ctx);
21431  if (!s) return;
21432 
21433  /* calculate hash from name */
21434  if (name[0] == '#') {
21435  hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++);
21436  name++; /* special number hash */
21437  } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42);
21438 
21439  /* check if property is currently hot item */
21440  if (win->property.active && hash == win->property.name) {
21441  buffer = win->property.buffer;
21442  len = &win->property.length;
21443  cursor = &win->property.cursor;
21444  state = &win->property.state;
21445  select_begin = &win->property.select_start;
21446  select_end = &win->property.select_end;
21447  } else {
21448  buffer = dummy_buffer;
21449  len = &dummy_length;
21450  cursor = &dummy_cursor;
21451  state = &dummy_state;
21452  select_begin = &dummy_select_begin;
21453  select_end = &dummy_select_end;
21454  }
21455 
21456  /* execute property widget */
21457  old_state = *state;
21458  ctx->text_edit.clip = ctx->clip;
21459  in = ((s == NK_WIDGET_ROM && !win->property.active) ||
21460  layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21461  nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name,
21462  variant, inc_per_pixel, buffer, len, state, cursor, select_begin,
21463  select_end, &style->property, filter, in, style->font, &ctx->text_edit,
21464  ctx->button_behavior);
21465 
21466  if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) {
21467  /* current property is now hot */
21468  win->property.active = 1;
21469  NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len);
21470  win->property.length = *len;
21471  win->property.cursor = *cursor;
21472  win->property.state = *state;
21473  win->property.name = hash;
21474  win->property.select_start = *select_begin;
21475  win->property.select_end = *select_end;
21476  if (*state == NK_PROPERTY_DRAG) {
21477  ctx->input.mouse.grab = nk_true;
21478  ctx->input.mouse.grabbed = nk_true;
21479  }
21480  }
21481  /* check if previously active property is now inactive */
21482  if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) {
21483  if (old_state == NK_PROPERTY_DRAG) {
21484  ctx->input.mouse.grab = nk_false;
21485  ctx->input.mouse.grabbed = nk_false;
21486  ctx->input.mouse.ungrab = nk_true;
21487  }
21488  win->property.select_start = 0;
21489  win->property.select_end = 0;
21490  win->property.active = 0;
21491  }
21492 }
21493 
21494 NK_API void
21495 nk_property_int(struct nk_context *ctx, const char *name,
21496  int min, int *val, int max, int step, float inc_per_pixel)
21497 {
21498  struct nk_property_variant variant;
21499  NK_ASSERT(ctx);
21500  NK_ASSERT(name);
21501  NK_ASSERT(val);
21502 
21503  if (!ctx || !ctx->current || !name || !val) return;
21504  variant = nk_property_variant_int(*val, min, max, step);
21505  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
21506  *val = variant.value.i;
21507 }
21508 
21509 NK_API void
21510 nk_property_float(struct nk_context *ctx, const char *name,
21511  float min, float *val, float max, float step, float inc_per_pixel)
21512 {
21513  struct nk_property_variant variant;
21514  NK_ASSERT(ctx);
21515  NK_ASSERT(name);
21516  NK_ASSERT(val);
21517 
21518  if (!ctx || !ctx->current || !name || !val) return;
21519  variant = nk_property_variant_float(*val, min, max, step);
21520  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21521  *val = variant.value.f;
21522 }
21523 
21524 NK_API void
21525 nk_property_double(struct nk_context *ctx, const char *name,
21526  double min, double *val, double max, double step, float inc_per_pixel)
21527 {
21528  struct nk_property_variant variant;
21529  NK_ASSERT(ctx);
21530  NK_ASSERT(name);
21531  NK_ASSERT(val);
21532 
21533  if (!ctx || !ctx->current || !name || !val) return;
21534  variant = nk_property_variant_double(*val, min, max, step);
21535  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21536  *val = variant.value.d;
21537 }
21538 
21539 NK_API int
21540 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val,
21541  int max, int step, float inc_per_pixel)
21542 {
21543  struct nk_property_variant variant;
21544  NK_ASSERT(ctx);
21545  NK_ASSERT(name);
21546 
21547  if (!ctx || !ctx->current || !name) return val;
21548  variant = nk_property_variant_int(val, min, max, step);
21549  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT);
21550  val = variant.value.i;
21551  return val;
21552 }
21553 
21554 NK_API float
21555 nk_propertyf(struct nk_context *ctx, const char *name, float min,
21556  float val, float max, float step, float inc_per_pixel)
21557 {
21558  struct nk_property_variant variant;
21559  NK_ASSERT(ctx);
21560  NK_ASSERT(name);
21561 
21562  if (!ctx || !ctx->current || !name) return val;
21563  variant = nk_property_variant_float(val, min, max, step);
21564  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21565  val = variant.value.f;
21566  return val;
21567 }
21568 
21569 NK_API double
21570 nk_propertyd(struct nk_context *ctx, const char *name, double min,
21571  double val, double max, double step, float inc_per_pixel)
21572 {
21573  struct nk_property_variant variant;
21574  NK_ASSERT(ctx);
21575  NK_ASSERT(name);
21576 
21577  if (!ctx || !ctx->current || !name) return val;
21578  variant = nk_property_variant_double(val, min, max, step);
21579  nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT);
21580  val = variant.value.d;
21581  return val;
21582 }
21583 
21584 /*----------------------------------------------------------------
21585  *
21586  * COLOR PICKER
21587  *
21588  * --------------------------------------------------------------*/
21589 NK_API int
21590 nk_color_pick(struct nk_context * ctx, struct nk_color *color,
21591  enum nk_color_format fmt)
21592 {
21593  struct nk_window *win;
21594  struct nk_panel *layout;
21595  const struct nk_style *config;
21596  const struct nk_input *in;
21597 
21599  struct nk_rect bounds;
21600 
21601  NK_ASSERT(ctx);
21602  NK_ASSERT(color);
21603  NK_ASSERT(ctx->current);
21604  NK_ASSERT(ctx->current->layout);
21605  if (!ctx || !ctx->current || !ctx->current->layout || !color)
21606  return 0;
21607 
21608  win = ctx->current;
21609  config = &ctx->style;
21610  layout = win->layout;
21611  state = nk_widget(&bounds, ctx);
21612  if (!state) return 0;
21613  in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
21614  return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds,
21615  nk_vec2(0,0), in, config->font);
21616 }
21617 
21618 NK_API struct nk_color
21619 nk_color_picker(struct nk_context *ctx, struct nk_color color,
21620  enum nk_color_format fmt)
21621 {
21622  nk_color_pick(ctx, &color, fmt);
21623  return color;
21624 }
21625 
21626 /* -------------------------------------------------------------
21627  *
21628  * CHART
21629  *
21630  * --------------------------------------------------------------*/
21631 NK_API int
21633  struct nk_color color, struct nk_color highlight,
21634  int count, float min_value, float max_value)
21635 {
21636  struct nk_window *win;
21637  struct nk_chart *chart;
21638  const struct nk_style *config;
21639  const struct nk_style_chart *style;
21640 
21641  const struct nk_style_item *background;
21642  struct nk_rect bounds = {0, 0, 0, 0};
21643 
21644  NK_ASSERT(ctx);
21645  NK_ASSERT(ctx->current);
21646  NK_ASSERT(ctx->current->layout);
21647 
21648  if (!ctx || !ctx->current || !ctx->current->layout) return 0;
21649  if (!nk_widget(&bounds, ctx)) {
21650  chart = &ctx->current->layout->chart;
21651  nk_zero(chart, sizeof(*chart));
21652  return 0;
21653  }
21654 
21655  win = ctx->current;
21656  config = &ctx->style;
21657  chart = &win->layout->chart;
21658  style = &config->chart;
21659 
21660  /* setup basic generic chart */
21661  nk_zero(chart, sizeof(*chart));
21662  chart->x = bounds.x + style->padding.x;
21663  chart->y = bounds.y + style->padding.y;
21664  chart->w = bounds.w - 2 * style->padding.x;
21665  chart->h = bounds.h - 2 * style->padding.y;
21666  chart->w = NK_MAX(chart->w, 2 * style->padding.x);
21667  chart->h = NK_MAX(chart->h, 2 * style->padding.y);
21668 
21669  /* add first slot into chart */
21670  {struct nk_chart_slot *slot = &chart->slots[chart->slot++];
21671  slot->type = type;
21672  slot->count = count;
21673  slot->color = color;
21674  slot->highlight = highlight;
21675  slot->min = NK_MIN(min_value, max_value);
21676  slot->max = NK_MAX(min_value, max_value);
21677  slot->range = slot->max - slot->min;}
21678 
21679  /* draw chart background */
21680  background = &style->background;
21681  if (background->type == NK_STYLE_ITEM_IMAGE) {
21682  nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white);
21683  } else {
21684  nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color);
21685  nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border),
21686  style->rounding, style->background.data.color);
21687  }
21688  return 1;
21689 }
21690 
21691 NK_API int
21692 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type,
21693  int count, float min_value, float max_value)
21694 {return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
21695 
21696 NK_API void
21698  struct nk_color color, struct nk_color highlight,
21699  int count, float min_value, float max_value)
21700 {
21701  NK_ASSERT(ctx);
21702  NK_ASSERT(ctx->current);
21703  NK_ASSERT(ctx->current->layout);
21704  NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT);
21705  if (!ctx || !ctx->current || !ctx->current->layout) return;
21706  if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return;
21707 
21708  /* add another slot into the graph */
21709  {struct nk_chart *chart = &ctx->current->layout->chart;
21710  struct nk_chart_slot *slot = &chart->slots[chart->slot++];
21711  slot->type = type;
21712  slot->count = count;
21713  slot->color = color;
21714  slot->highlight = highlight;
21715  slot->min = NK_MIN(min_value, max_value);
21716  slot->max = NK_MAX(min_value, max_value);
21717  slot->range = slot->max - slot->min;}
21718 }
21719 
21720 NK_API void
21721 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type,
21722  int count, float min_value, float max_value)
21723 {nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);}
21724 
21726 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win,
21727  struct nk_chart *g, float value, int slot)
21728 {
21729  struct nk_panel *layout = win->layout;
21730  const struct nk_input *i = &ctx->input;
21731  struct nk_command_buffer *out = &win->buffer;
21732 
21733  nk_flags ret = 0;
21734  struct nk_vec2 cur;
21735  struct nk_rect bounds;
21736  struct nk_color color;
21737  float step;
21738  float range;
21739  float ratio;
21740 
21741  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21742  step = g->w / (float)g->slots[slot].count;
21743  range = g->slots[slot].max - g->slots[slot].min;
21744  ratio = (value - g->slots[slot].min) / range;
21745 
21746  if (g->slots[slot].index == 0) {
21747  /* first data point does not have a connection */
21748  g->slots[slot].last.x = g->x;
21749  g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h;
21750 
21751  bounds.x = g->slots[slot].last.x - 2;
21752  bounds.y = g->slots[slot].last.y - 2;
21753  bounds.w = bounds.h = 4;
21754 
21755  color = g->slots[slot].color;
21756  if (!(layout->flags & NK_WINDOW_ROM) &&
21757  NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){
21758  ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0;
21759  ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down &&
21761  color = g->slots[slot].highlight;
21762  }
21763  nk_fill_rect(out, bounds, 0, color);
21764  g->slots[slot].index += 1;
21765  return ret;
21766  }
21767 
21768  /* draw a line between the last data point and the new one */
21769  color = g->slots[slot].color;
21770  cur.x = g->x + (float)(step * (float)g->slots[slot].index);
21771  cur.y = (g->y + g->h) - (ratio * (float)g->h);
21772  nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color);
21773 
21774  bounds.x = cur.x - 3;
21775  bounds.y = cur.y - 3;
21776  bounds.w = bounds.h = 6;
21777 
21778  /* user selection of current data point */
21779  if (!(layout->flags & NK_WINDOW_ROM)) {
21780  if (nk_input_is_mouse_hovering_rect(i, bounds)) {
21781  ret = NK_CHART_HOVERING;
21782  ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down &&
21784  color = g->slots[slot].highlight;
21785  }
21786  }
21787  nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color);
21788 
21789  /* save current data point position */
21790  g->slots[slot].last.x = cur.x;
21791  g->slots[slot].last.y = cur.y;
21792  g->slots[slot].index += 1;
21793  return ret;
21794 }
21795 
21797 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win,
21798  struct nk_chart *chart, float value, int slot)
21799 {
21800  struct nk_command_buffer *out = &win->buffer;
21801  const struct nk_input *in = &ctx->input;
21802  struct nk_panel *layout = win->layout;
21803 
21804  float ratio;
21805  nk_flags ret = 0;
21806  struct nk_color color;
21807  struct nk_rect item = {0,0,0,0};
21808 
21809  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21810  if (chart->slots[slot].index >= chart->slots[slot].count)
21811  return nk_false;
21812  if (chart->slots[slot].count) {
21813  float padding = (float)(chart->slots[slot].count-1);
21814  item.w = (chart->w - padding) / (float)(chart->slots[slot].count);
21815  }
21816 
21817  /* calculate bounds of current bar chart entry */
21818  color = chart->slots[slot].color;;
21819  item.h = chart->h * NK_ABS((value/chart->slots[slot].range));
21820  if (value >= 0) {
21821  ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range);
21822  item.y = (chart->y + chart->h) - chart->h * ratio;
21823  } else {
21824  ratio = (value - chart->slots[slot].max) / chart->slots[slot].range;
21825  item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h;
21826  }
21827  item.x = chart->x + ((float)chart->slots[slot].index * item.w);
21828  item.x = item.x + ((float)chart->slots[slot].index);
21829 
21830  /* user chart bar selection */
21831  if (!(layout->flags & NK_WINDOW_ROM) &&
21832  NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) {
21833  ret = NK_CHART_HOVERING;
21834  ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down &&
21835  in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0;
21836  color = chart->slots[slot].highlight;
21837  }
21838  nk_fill_rect(out, item, 0, color);
21839  chart->slots[slot].index += 1;
21840  return ret;
21841 }
21842 
21844 nk_chart_push_slot(struct nk_context *ctx, float value, int slot)
21845 {
21846  nk_flags flags;
21847  struct nk_window *win;
21848 
21849  NK_ASSERT(ctx);
21850  NK_ASSERT(ctx->current);
21851  NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT);
21852  NK_ASSERT(slot < ctx->current->layout->chart.slot);
21853  if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false;
21854  if (slot >= ctx->current->layout->chart.slot) return nk_false;
21855 
21856  win = ctx->current;
21857  if (win->layout->chart.slot < slot) return nk_false;
21858  switch (win->layout->chart.slots[slot].type) {
21859  case NK_CHART_LINES:
21860  flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break;
21861  case NK_CHART_COLUMN:
21862  flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break;
21863  default:
21864  case NK_CHART_MAX:
21865  flags = 0;
21866  }
21867  return flags;
21868 }
21869 
21871 nk_chart_push(struct nk_context *ctx, float value)
21872 {return nk_chart_push_slot(ctx, value, 0);}
21873 
21874 NK_API void
21875 nk_chart_end(struct nk_context *ctx)
21876 {
21877  struct nk_window *win;
21878  struct nk_chart *chart;
21879 
21880  NK_ASSERT(ctx);
21881  NK_ASSERT(ctx->current);
21882  if (!ctx || !ctx->current)
21883  return;
21884 
21885  win = ctx->current;
21886  chart = &win->layout->chart;
21887  NK_MEMSET(chart, 0, sizeof(*chart));
21888  return;
21889 }
21890 
21891 NK_API void
21892 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values,
21893  int count, int offset)
21894 {
21895  int i = 0;
21896  float min_value;
21897  float max_value;
21898 
21899  NK_ASSERT(ctx);
21900  NK_ASSERT(values);
21901  if (!ctx || !values || !count) return;
21902 
21903  min_value = values[offset];
21904  max_value = values[offset];
21905  for (i = 0; i < count; ++i) {
21906  min_value = NK_MIN(values[i + offset], min_value);
21907  max_value = NK_MAX(values[i + offset], max_value);
21908  }
21909 
21910  if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
21911  for (i = 0; i < count; ++i)
21912  nk_chart_push(ctx, values[i + offset]);
21913  nk_chart_end(ctx);
21914  }
21915 }
21916 
21917 NK_API void
21918 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata,
21919  float(*value_getter)(void* user, int index), int count, int offset)
21920 {
21921  int i = 0;
21922  float min_value;
21923  float max_value;
21924 
21925  NK_ASSERT(ctx);
21926  NK_ASSERT(value_getter);
21927  if (!ctx || !value_getter || !count) return;
21928 
21929  max_value = min_value = value_getter(userdata, offset);
21930  for (i = 0; i < count; ++i) {
21931  float value = value_getter(userdata, i + offset);
21932  min_value = NK_MIN(value, min_value);
21933  max_value = NK_MAX(value, max_value);
21934  }
21935 
21936  if (nk_chart_begin(ctx, type, count, min_value, max_value)) {
21937  for (i = 0; i < count; ++i)
21938  nk_chart_push(ctx, value_getter(userdata, i + offset));
21939  nk_chart_end(ctx);
21940  }
21941 }
21942 
21943 /* -------------------------------------------------------------
21944  *
21945  * GROUP
21946  *
21947  * --------------------------------------------------------------*/
21948 NK_API int
21950  nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags)
21951 {
21952  struct nk_rect bounds;
21953  struct nk_window panel;
21954  struct nk_window *win;
21955 
21956  win = ctx->current;
21957  nk_panel_alloc_space(&bounds, ctx);
21958  {const struct nk_rect *c = &win->layout->clip;
21959  if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) &&
21960  !(flags & NK_WINDOW_MOVABLE)) {
21961  return 0;
21962  }}
21963  if (win->flags & NK_WINDOW_ROM)
21964  flags |= NK_WINDOW_ROM;
21965 
21966  /* initialize a fake window to create the panel from */
21967  nk_zero(&panel, sizeof(panel));
21968  panel.bounds = bounds;
21969  panel.flags = flags;
21970  panel.scrollbar.x = *x_offset;
21971  panel.scrollbar.y = *y_offset;
21972  panel.buffer = win->buffer;
21973  panel.layout = (struct nk_panel*)nk_create_panel(ctx);
21974  ctx->current = &panel;
21975  nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP);
21976 
21977  win->buffer = panel.buffer;
21978  win->buffer.clip = panel.layout->clip;
21979  panel.layout->offset_x = x_offset;
21980  panel.layout->offset_y = y_offset;
21981  panel.layout->parent = win->layout;
21982  win->layout = panel.layout;
21983 
21984  ctx->current = win;
21985  if ((panel.layout->flags & NK_WINDOW_CLOSED) ||
21986  (panel.layout->flags & NK_WINDOW_MINIMIZED))
21987  {
21988  nk_flags f = panel.layout->flags;
21990  if (f & NK_WINDOW_CLOSED)
21991  return NK_WINDOW_CLOSED;
21992  if (f & NK_WINDOW_MINIMIZED)
21993  return NK_WINDOW_MINIMIZED;
21994  }
21995  return 1;
21996 }
21997 
21998 NK_API void
22000 {
22001  struct nk_window *win;
22002  struct nk_panel *parent;
22003  struct nk_panel *g;
22004 
22005  struct nk_rect clip;
22006  struct nk_window pan;
22007  struct nk_vec2 panel_padding;
22008 
22009  NK_ASSERT(ctx);
22010  NK_ASSERT(ctx->current);
22011  if (!ctx || !ctx->current)
22012  return;
22013 
22014  /* make sure nk_group_begin was called correctly */
22015  NK_ASSERT(ctx->current);
22016  win = ctx->current;
22017  NK_ASSERT(win->layout);
22018  g = win->layout;
22019  NK_ASSERT(g->parent);
22020  parent = g->parent;
22021 
22022  /* dummy window */
22023  nk_zero_struct(pan);
22024  panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP);
22025  pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h);
22026  pan.bounds.x = g->bounds.x - panel_padding.x;
22027  pan.bounds.w = g->bounds.w + 2 * panel_padding.x;
22028  pan.bounds.h = g->bounds.h + g->header_height + g->menu.h;
22029  if (g->flags & NK_WINDOW_BORDER) {
22030  pan.bounds.x -= g->border;
22031  pan.bounds.y -= g->border;
22032  pan.bounds.w += 2*g->border;
22033  pan.bounds.h += 2*g->border;
22034  }
22035  if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) {
22036  pan.bounds.w += ctx->style.window.scrollbar_size.x;
22037  pan.bounds.h += ctx->style.window.scrollbar_size.y;
22038  }
22039  pan.scrollbar.x = *g->offset_x;
22040  pan.scrollbar.y = *g->offset_y;
22041  pan.flags = g->flags;
22042  pan.buffer = win->buffer;
22043  pan.layout = g;
22044  pan.parent = win;
22045  ctx->current = &pan;
22046 
22047  /* make sure group has correct clipping rectangle */
22048  nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y,
22049  pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x);
22050  nk_push_scissor(&pan.buffer, clip);
22051  nk_end(ctx);
22052 
22053  win->buffer = pan.buffer;
22054  nk_push_scissor(&win->buffer, parent->clip);
22055  ctx->current = win;
22056  win->layout = parent;
22057  g->bounds = pan.bounds;
22058  return;
22059 }
22060 
22061 NK_API int
22063  struct nk_scroll *scroll, const char *title, nk_flags flags)
22064 {return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);}
22065 
22066 NK_API int
22067 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags)
22068 {
22069  int title_len;
22070  nk_hash title_hash;
22071  struct nk_window *win;
22072  nk_uint *x_offset;
22073  nk_uint *y_offset;
22074 
22075  NK_ASSERT(ctx);
22076  NK_ASSERT(title);
22077  NK_ASSERT(ctx->current);
22078  NK_ASSERT(ctx->current->layout);
22079  if (!ctx || !ctx->current || !ctx->current->layout || !title)
22080  return 0;
22081 
22082  /* find persistent group scrollbar value */
22083  win = ctx->current;
22084  title_len = (int)nk_strlen(title);
22085  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
22086  x_offset = nk_find_value(win, title_hash);
22087  if (!x_offset) {
22088  x_offset = nk_add_value(ctx, win, title_hash, 0);
22089  y_offset = nk_add_value(ctx, win, title_hash+1, 0);
22090 
22091  NK_ASSERT(x_offset);
22092  NK_ASSERT(y_offset);
22093  if (!x_offset || !y_offset) return 0;
22094  *x_offset = *y_offset = 0;
22095  } else y_offset = nk_find_value(win, title_hash+1);
22096  return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
22097 }
22098 
22099 NK_API void
22100 nk_group_end(struct nk_context *ctx)
22102 
22103 NK_API int
22104 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view,
22105  const char *title, nk_flags flags, int row_height, int row_count)
22106 {
22107  int title_len;
22108  nk_hash title_hash;
22109  nk_uint *x_offset;
22110  nk_uint *y_offset;
22111 
22112  int result;
22113  struct nk_window *win;
22114  struct nk_panel *layout;
22115  const struct nk_style *style;
22116  struct nk_vec2 item_spacing;
22117 
22118  NK_ASSERT(ctx);
22119  NK_ASSERT(view);
22120  NK_ASSERT(title);
22121  if (!ctx || !view || !title) return 0;
22122 
22123  win = ctx->current;
22124  style = &ctx->style;
22125  item_spacing = style->window.spacing;
22126  row_height += NK_MAX(0, (int)item_spacing.y);
22127 
22128  /* find persistent list view scrollbar offset */
22129  title_len = (int)nk_strlen(title);
22130  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP);
22131  x_offset = nk_find_value(win, title_hash);
22132  if (!x_offset) {
22133  x_offset = nk_add_value(ctx, win, title_hash, 0);
22134  y_offset = nk_add_value(ctx, win, title_hash+1, 0);
22135 
22136  NK_ASSERT(x_offset);
22137  NK_ASSERT(y_offset);
22138  if (!x_offset || !y_offset) return 0;
22139  *x_offset = *y_offset = 0;
22140  } else y_offset = nk_find_value(win, title_hash+1);
22141  view->scroll_value = *y_offset;
22142  view->scroll_pointer = y_offset;
22143 
22144  *y_offset = 0;
22145  result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags);
22146  win = ctx->current;
22147  layout = win->layout;
22148 
22149  view->total_height = row_height * NK_MAX(row_count,1);
22150  view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f);
22151  view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height), 0);
22152  view->end = view->begin + view->count;
22153  view->ctx = ctx;
22154  return result;
22155 }
22156 
22157 NK_API void
22158 nk_list_view_end(struct nk_list_view *view)
22159 {
22160  struct nk_context *ctx;
22161  struct nk_window *win;
22162  struct nk_panel *layout;
22163 
22164  NK_ASSERT(view);
22165  NK_ASSERT(view->ctx);
22166  NK_ASSERT(view->scroll_pointer);
22167  if (!view || !view->ctx) return;
22168 
22169  ctx = view->ctx;
22170  win = ctx->current;
22171  layout = win->layout;
22172  layout->at_y = layout->bounds.y + (float)view->total_height;
22173  *view->scroll_pointer = *view->scroll_pointer + view->scroll_value;
22174  nk_group_end(view->ctx);
22175 }
22176 
22177 /* --------------------------------------------------------------
22178  *
22179  * POPUP
22180  *
22181  * --------------------------------------------------------------*/
22182 NK_API int
22184  const char *title, nk_flags flags, struct nk_rect rect)
22185 {
22186  struct nk_window *popup;
22187  struct nk_window *win;
22188  struct nk_panel *panel;
22189 
22190  int title_len;
22191  nk_hash title_hash;
22192  nk_size allocated;
22193 
22194  NK_ASSERT(ctx);
22195  NK_ASSERT(title);
22196  NK_ASSERT(ctx->current);
22197  NK_ASSERT(ctx->current->layout);
22198  if (!ctx || !ctx->current || !ctx->current->layout)
22199  return 0;
22200 
22201  win = ctx->current;
22202  panel = win->layout;
22203  NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups");
22204  (void)panel;
22205  title_len = (int)nk_strlen(title);
22206  title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP);
22207 
22208  popup = win->popup.win;
22209  if (!popup) {
22210  popup = (struct nk_window*)nk_create_window(ctx);
22211  popup->parent = win;
22212  win->popup.win = popup;
22213  win->popup.active = 0;
22214  win->popup.type = NK_PANEL_POPUP;
22215  }
22216 
22217  /* make sure we have correct popup */
22218  if (win->popup.name != title_hash) {
22219  if (!win->popup.active) {
22220  nk_zero(popup, sizeof(*popup));
22221  win->popup.name = title_hash;
22222  win->popup.active = 1;
22223  win->popup.type = NK_PANEL_POPUP;
22224  } else return 0;
22225  }
22226 
22227  /* popup position is local to window */
22228  ctx->current = popup;
22229  rect.x += win->layout->clip.x;
22230  rect.y += win->layout->clip.y;
22231 
22232  /* setup popup data */
22233  popup->parent = win;
22234  popup->bounds = rect;
22235  popup->seq = ctx->seq;
22236  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
22237  popup->flags = flags;
22238  popup->flags |= NK_WINDOW_BORDER;
22239  if (type == NK_POPUP_DYNAMIC)
22240  popup->flags |= NK_WINDOW_DYNAMIC;
22241 
22242  popup->buffer = win->buffer;
22243  nk_start_popup(ctx, win);
22244  allocated = ctx->memory.allocated;
22245  nk_push_scissor(&popup->buffer, nk_null_rect);
22246 
22247  if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) {
22248  /* popup is running therefore invalidate parent panels */
22249  struct nk_panel *root;
22250  root = win->layout;
22251  while (root) {
22252  root->flags |= NK_WINDOW_ROM;
22253  root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM;
22254  root = root->parent;
22255  }
22256  win->popup.active = 1;
22257  popup->layout->offset_x = &popup->scrollbar.x;
22258  popup->layout->offset_y = &popup->scrollbar.y;
22259  popup->layout->parent = win->layout;
22260  return 1;
22261  } else {
22262  /* popup was closed/is invalid so cleanup */
22263  struct nk_panel *root;
22264  root = win->layout;
22265  while (root) {
22266  root->flags |= NK_WINDOW_REMOVE_ROM;
22267  root = root->parent;
22268  }
22269  win->popup.buf.active = 0;
22270  win->popup.active = 0;
22271  ctx->memory.allocated = allocated;
22272  ctx->current = win;
22273  nk_free_panel(ctx, popup->layout);
22274  popup->layout = 0;
22275  return 0;
22276  }
22277 }
22278 
22279 NK_INTERN int
22280 nk_nonblock_begin(struct nk_context *ctx,
22281  nk_flags flags, struct nk_rect body, struct nk_rect header,
22282  enum nk_panel_type panel_type)
22283 {
22284  struct nk_window *popup;
22285  struct nk_window *win;
22286  struct nk_panel *panel;
22287  int is_active = nk_true;
22288 
22289  NK_ASSERT(ctx);
22290  NK_ASSERT(ctx->current);
22291  NK_ASSERT(ctx->current->layout);
22292  if (!ctx || !ctx->current || !ctx->current->layout)
22293  return 0;
22294 
22295  /* popups cannot have popups */
22296  win = ctx->current;
22297  panel = win->layout;
22298  NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP));
22299  (void)panel;
22300  popup = win->popup.win;
22301  if (!popup) {
22302  /* create window for nonblocking popup */
22303  popup = (struct nk_window*)nk_create_window(ctx);
22304  popup->parent = win;
22305  win->popup.win = popup;
22306  win->popup.type = panel_type;
22307  nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON);
22308  } else {
22309  /* close the popup if user pressed outside or in the header */
22310  int pressed, in_body, in_header;
22311  pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
22312  in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
22313  in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header);
22314  if (pressed && (!in_body || in_header))
22315  is_active = nk_false;
22316  }
22317  win->popup.header = header;
22318 
22319  if (!is_active) {
22320  /* remove read only mode from all parent panels */
22321  struct nk_panel *root = win->layout;
22322  while (root) {
22323  root->flags |= NK_WINDOW_REMOVE_ROM;
22324  root = root->parent;
22325  }
22326  return is_active;
22327  }
22328 
22329  popup->bounds = body;
22330  popup->parent = win;
22331  popup->layout = (struct nk_panel*)nk_create_panel(ctx);
22332  popup->flags = flags;
22333  popup->flags |= NK_WINDOW_BORDER;
22334  popup->flags |= NK_WINDOW_DYNAMIC;
22335  popup->seq = ctx->seq;
22336  win->popup.active = 1;
22337  NK_ASSERT(popup->layout);
22338 
22339  nk_start_popup(ctx, win);
22340  popup->buffer = win->buffer;
22341  nk_push_scissor(&popup->buffer, nk_null_rect);
22342  ctx->current = popup;
22343 
22344  nk_panel_begin(ctx, 0, panel_type);
22345  win->buffer = popup->buffer;
22346  popup->layout->parent = win->layout;
22347  popup->layout->offset_x = &popup->scrollbar.x;
22348  popup->layout->offset_y = &popup->scrollbar.y;
22349 
22350  /* set read only mode to all parent panels */
22351  {struct nk_panel *root;
22352  root = win->layout;
22353  while (root) {
22354  root->flags |= NK_WINDOW_ROM;
22355  root = root->parent;
22356  }}
22357  return is_active;
22358 }
22359 
22360 NK_API void
22361 nk_popup_close(struct nk_context *ctx)
22362 {
22363  struct nk_window *popup;
22364  NK_ASSERT(ctx);
22365  if (!ctx || !ctx->current) return;
22366 
22367  popup = ctx->current;
22368  NK_ASSERT(popup->parent);
22369  NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP);
22370  popup->flags |= NK_WINDOW_HIDDEN;
22371 }
22372 
22373 NK_API void
22374 nk_popup_end(struct nk_context *ctx)
22375 {
22376  struct nk_window *win;
22377  struct nk_window *popup;
22378 
22379  NK_ASSERT(ctx);
22380  NK_ASSERT(ctx->current);
22381  NK_ASSERT(ctx->current->layout);
22382  if (!ctx || !ctx->current || !ctx->current->layout)
22383  return;
22384 
22385  popup = ctx->current;
22386  if (!popup->parent) return;
22387  win = popup->parent;
22388  if (popup->flags & NK_WINDOW_HIDDEN) {
22389  struct nk_panel *root;
22390  root = win->layout;
22391  while (root) {
22392  root->flags |= NK_WINDOW_REMOVE_ROM;
22393  root = root->parent;
22394  }
22395  win->popup.active = 0;
22396  }
22397  nk_push_scissor(&popup->buffer, nk_null_rect);
22398  nk_end(ctx);
22399 
22400  win->buffer = popup->buffer;
22401  nk_finish_popup(ctx, win);
22402  ctx->current = win;
22403  nk_push_scissor(&win->buffer, win->layout->clip);
22404 }
22405 /* -------------------------------------------------------------
22406  *
22407  * TOOLTIP
22408  *
22409  * -------------------------------------------------------------- */
22410 NK_API int
22411 nk_tooltip_begin(struct nk_context *ctx, float width)
22412 {
22413  struct nk_window *win;
22414  const struct nk_input *in;
22415  struct nk_rect bounds;
22416  int ret;
22417 
22418  NK_ASSERT(ctx);
22419  NK_ASSERT(ctx->current);
22420  NK_ASSERT(ctx->current->layout);
22421  if (!ctx || !ctx->current || !ctx->current->layout)
22422  return 0;
22423 
22424  /* make sure that no nonblocking popup is currently active */
22425  win = ctx->current;
22426  in = &ctx->input;
22427  if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK))
22428  return 0;
22429 
22430  bounds.w = width;
22431  bounds.h = nk_null_rect.h;
22432  bounds.x = (in->mouse.pos.x + 1) - win->layout->clip.x;
22433  bounds.y = (in->mouse.pos.y + 1) - win->layout->clip.y;
22434 
22436  "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds);
22437  if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM;
22438  win->popup.type = NK_PANEL_TOOLTIP;
22439  ctx->current->layout->type = NK_PANEL_TOOLTIP;
22440  return ret;
22441 }
22442 
22443 NK_API void
22444 nk_tooltip_end(struct nk_context *ctx)
22445 {
22446  NK_ASSERT(ctx);
22447  NK_ASSERT(ctx->current);
22448  if (!ctx || !ctx->current) return;
22449  ctx->current->seq--;
22451  nk_popup_end(ctx);
22452 }
22453 
22454 NK_API void
22455 nk_tooltip(struct nk_context *ctx, const char *text)
22456 {
22457  const struct nk_style *style;
22458  struct nk_vec2 padding;
22459 
22460  int text_len;
22461  float text_width;
22462  float text_height;
22463 
22464  NK_ASSERT(ctx);
22465  NK_ASSERT(ctx->current);
22466  NK_ASSERT(ctx->current->layout);
22467  NK_ASSERT(text);
22468  if (!ctx || !ctx->current || !ctx->current->layout || !text)
22469  return;
22470 
22471  /* fetch configuration data */
22472  style = &ctx->style;
22473  padding = style->window.padding;
22474 
22475  /* calculate size of the text and tooltip */
22476  text_len = nk_strlen(text);
22477  text_width = style->font->width(style->font->userdata,
22478  style->font->height, text, text_len);
22479  text_width += (4 * padding.x);
22480  text_height = (style->font->height + 2 * padding.y);
22481 
22482  /* execute tooltip and fill with text */
22483  if (nk_tooltip_begin(ctx, (float)text_width)) {
22484  nk_layout_row_dynamic(ctx, (float)text_height, 1);
22485  nk_text(ctx, text, text_len, NK_TEXT_LEFT);
22487  }
22488 }
22489 /* -------------------------------------------------------------
22490  *
22491  * CONTEXTUAL
22492  *
22493  * -------------------------------------------------------------- */
22494 NK_API int
22496  struct nk_rect trigger_bounds)
22497 {
22498  struct nk_window *win;
22499  struct nk_window *popup;
22500  struct nk_rect body;
22501 
22502  NK_STORAGE const struct nk_rect null_rect = {0,0,0,0};
22503  int is_clicked = 0;
22504  int is_active = 0;
22505  int is_open = 0;
22506  int ret = 0;
22507 
22508  NK_ASSERT(ctx);
22509  NK_ASSERT(ctx->current);
22510  NK_ASSERT(ctx->current->layout);
22511  if (!ctx || !ctx->current || !ctx->current->layout)
22512  return 0;
22513 
22514  win = ctx->current;
22515  ++win->popup.con_count;
22516 
22517  /* check if currently active contextual is active */
22518  popup = win->popup.win;
22519  is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL);
22520  is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds);
22521  if (win->popup.active_con && win->popup.con_count != win->popup.active_con)
22522  return 0;
22523  if ((is_clicked && is_open && !is_active) || (!is_open && !is_active && !is_clicked))
22524  return 0;
22525 
22526  /* calculate contextual position on click */
22527  win->popup.active_con = win->popup.con_count;
22528  if (is_clicked) {
22529  body.x = ctx->input.mouse.pos.x;
22530  body.y = ctx->input.mouse.pos.y;
22531  } else {
22532  body.x = popup->bounds.x;
22533  body.y = popup->bounds.y;
22534  }
22535  body.w = size.x;
22536  body.h = size.y;
22537 
22538  /* start nonblocking contextual popup */
22539  ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body,
22540  null_rect, NK_PANEL_CONTEXTUAL);
22541  if (ret) win->popup.type = NK_PANEL_CONTEXTUAL;
22542  else {
22543  win->popup.active_con = 0;
22544  if (win->popup.win)
22545  win->popup.win->flags = 0;
22546  }
22547  return ret;
22548 }
22549 
22550 NK_API int
22551 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len,
22552  nk_flags alignment)
22553 {
22554  struct nk_window *win;
22555  const struct nk_input *in;
22556  const struct nk_style *style;
22557 
22558  struct nk_rect bounds;
22560 
22561  NK_ASSERT(ctx);
22562  NK_ASSERT(ctx->current);
22563  NK_ASSERT(ctx->current->layout);
22564  if (!ctx || !ctx->current || !ctx->current->layout)
22565  return 0;
22566 
22567  win = ctx->current;
22568  style = &ctx->style;
22569  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22570  if (!state) return nk_false;
22571 
22572  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22573  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds,
22574  text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) {
22576  return nk_true;
22577  }
22578  return nk_false;
22579 }
22580 
22583 
22584 NK_API int
22586  const char *text, int len, nk_flags align)
22587 {
22588  struct nk_window *win;
22589  const struct nk_input *in;
22590  const struct nk_style *style;
22591 
22592  struct nk_rect bounds;
22594 
22595  NK_ASSERT(ctx);
22596  NK_ASSERT(ctx->current);
22597  NK_ASSERT(ctx->current->layout);
22598  if (!ctx || !ctx->current || !ctx->current->layout)
22599  return 0;
22600 
22601  win = ctx->current;
22602  style = &ctx->style;
22603  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22604  if (!state) return nk_false;
22605 
22606  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22607  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds,
22608  img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){
22610  return nk_true;
22611  }
22612  return nk_false;
22613 }
22614 
22616  const char *label, nk_flags align)
22618 
22619 NK_API int
22621  const char *text, int len, nk_flags align)
22622 {
22623  struct nk_window *win;
22624  const struct nk_input *in;
22625  const struct nk_style *style;
22626 
22627  struct nk_rect bounds;
22629 
22630  NK_ASSERT(ctx);
22631  NK_ASSERT(ctx->current);
22632  NK_ASSERT(ctx->current->layout);
22633  if (!ctx || !ctx->current || !ctx->current->layout)
22634  return 0;
22635 
22636  win = ctx->current;
22637  style = &ctx->style;
22638  state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding);
22639  if (!state) return nk_false;
22640 
22641  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
22642  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds,
22643  symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) {
22645  return nk_true;
22646  }
22647  return nk_false;
22648 }
22649 
22651  const char *text, nk_flags align)
22652 {return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);}
22653 
22654 NK_API void
22656 {
22657  NK_ASSERT(ctx);
22658  NK_ASSERT(ctx->current);
22659  NK_ASSERT(ctx->current->layout);
22660  if (!ctx || !ctx->current || !ctx->current->layout) return;
22662 }
22663 
22664 NK_API void
22666 {
22667  struct nk_window *popup;
22668  struct nk_panel *panel;
22669  NK_ASSERT(ctx);
22670  NK_ASSERT(ctx->current);
22671  if (!ctx || !ctx->current) return;
22672 
22673  popup = ctx->current;
22674  panel = popup->layout;
22675  NK_ASSERT(popup->parent);
22676  NK_ASSERT(panel->type & NK_PANEL_SET_POPUP);
22677  if (panel->flags & NK_WINDOW_DYNAMIC) {
22678  /* Close behavior
22679  This is a bit of a hack solution since we do not know before we end our popup
22680  how big it will be. We therefore do not directly know when a
22681  click outside the non-blocking popup must close it at that direct frame.
22682  Instead it will be closed in the next frame.*/
22683  struct nk_rect body = {0,0,0,0};
22684  if (panel->at_y < (panel->bounds.y + panel->bounds.h)) {
22685  struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type);
22686  body = panel->bounds;
22687  body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height);
22688  body.h = (panel->bounds.y + panel->bounds.h) - body.y;
22689  }
22690  {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT);
22691  int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body);
22692  if (pressed && in_body)
22693  popup->flags |= NK_WINDOW_HIDDEN;
22694  }
22695  }
22696  if (popup->flags & NK_WINDOW_HIDDEN)
22697  popup->seq = 0;
22698  nk_popup_end(ctx);
22699  return;
22700 }
22701 /* -------------------------------------------------------------
22702  *
22703  * COMBO
22704  *
22705  * --------------------------------------------------------------*/
22706 NK_INTERN int
22707 nk_combo_begin(struct nk_context *ctx, struct nk_window *win,
22708  struct nk_vec2 size, int is_clicked, struct nk_rect header)
22709 {
22710  struct nk_window *popup;
22711  int is_open = 0;
22712  int is_active = 0;
22713  struct nk_rect body;
22714  nk_hash hash;
22715 
22716  NK_ASSERT(ctx);
22717  NK_ASSERT(ctx->current);
22718  NK_ASSERT(ctx->current->layout);
22719  if (!ctx || !ctx->current || !ctx->current->layout)
22720  return 0;
22721 
22722  popup = win->popup.win;
22723  body.x = header.x;
22724  body.w = size.x;
22725  body.y = header.y + header.h-ctx->style.window.combo_border;
22726  body.h = size.y;
22727 
22728  hash = win->popup.combo_count++;
22729  is_open = (popup) ? nk_true:nk_false;
22730  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO);
22731  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
22732  (!is_open && !is_active && !is_clicked)) return 0;
22733  if (!nk_nonblock_begin(ctx, 0, body,
22734  (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0;
22735 
22736  win->popup.type = NK_PANEL_COMBO;
22737  win->popup.name = hash;
22738  return 1;
22739 }
22740 
22741 NK_API int
22742 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len,
22743  struct nk_vec2 size)
22744 {
22745  const struct nk_input *in;
22746  struct nk_window *win;
22747  struct nk_style *style;
22748 
22750  int is_clicked = nk_false;
22751  struct nk_rect header;
22752  const struct nk_style_item *background;
22753  struct nk_text text;
22754 
22755  NK_ASSERT(ctx);
22756  NK_ASSERT(selected);
22757  NK_ASSERT(ctx->current);
22758  NK_ASSERT(ctx->current->layout);
22759  if (!ctx || !ctx->current || !ctx->current->layout || !selected)
22760  return 0;
22761 
22762  win = ctx->current;
22763  style = &ctx->style;
22764  s = nk_widget(&header, ctx);
22765  if (s == NK_WIDGET_INVALID)
22766  return 0;
22767 
22768  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22769  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22770  is_clicked = nk_true;
22771 
22772  /* draw combo box header background and border */
22773  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22774  background = &style->combo.active;
22775  text.text = style->combo.label_active;
22776  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22777  background = &style->combo.hover;
22778  text.text = style->combo.label_hover;
22779  } else {
22780  background = &style->combo.normal;
22781  text.text = style->combo.label_normal;
22782  }
22783  if (background->type == NK_STYLE_ITEM_IMAGE) {
22784  text.background = nk_rgba(0,0,0,0);
22785  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22786  } else {
22787  text.background = background->data.color;
22788  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22789  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22790  }
22791  {
22792  /* print currently selected text item */
22793  struct nk_rect label;
22794  struct nk_rect button;
22795  struct nk_rect content;
22796 
22797  enum nk_symbol_type sym;
22798  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22799  sym = style->combo.sym_hover;
22800  else if (is_clicked)
22801  sym = style->combo.sym_active;
22802  else sym = style->combo.sym_normal;
22803 
22804  /* calculate button */
22805  button.w = header.h - 2 * style->combo.button_padding.y;
22806  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22807  button.y = header.y + style->combo.button_padding.y;
22808  button.h = button.w;
22809 
22810  content.x = button.x + style->combo.button.padding.x;
22811  content.y = button.y + style->combo.button.padding.y;
22812  content.w = button.w - 2 * style->combo.button.padding.x;
22813  content.h = button.h - 2 * style->combo.button.padding.y;
22814 
22815  /* draw selected label */
22816  text.padding = nk_vec2(0,0);
22817  label.x = header.x + style->combo.content_padding.x;
22818  label.y = header.y + style->combo.content_padding.y;
22819  label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;;
22820  label.h = header.h - 2 * style->combo.content_padding.y;
22821  nk_widget_text(&win->buffer, label, selected, len, &text,
22822  NK_TEXT_LEFT, ctx->style.font);
22823 
22824  /* draw open/close button */
22825  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22826  &ctx->style.combo.button, sym, style->font);
22827  }
22828  return nk_combo_begin(ctx, win, size, is_clicked, header);
22829 }
22830 
22831 NK_API int nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size)
22832 {return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);}
22833 
22834 NK_API int
22835 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size)
22836 {
22837  struct nk_window *win;
22838  struct nk_style *style;
22839  const struct nk_input *in;
22840 
22841  struct nk_rect header;
22842  int is_clicked = nk_false;
22844  const struct nk_style_item *background;
22845 
22846  NK_ASSERT(ctx);
22847  NK_ASSERT(ctx->current);
22848  NK_ASSERT(ctx->current->layout);
22849  if (!ctx || !ctx->current || !ctx->current->layout)
22850  return 0;
22851 
22852  win = ctx->current;
22853  style = &ctx->style;
22854  s = nk_widget(&header, ctx);
22855  if (s == NK_WIDGET_INVALID)
22856  return 0;
22857 
22858  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22859  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22860  is_clicked = nk_true;
22861 
22862  /* draw combo box header background and border */
22863  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
22864  background = &style->combo.active;
22865  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22866  background = &style->combo.hover;
22867  else background = &style->combo.normal;
22868 
22869  if (background->type == NK_STYLE_ITEM_IMAGE) {
22870  nk_draw_image(&win->buffer, header, &background->data.image,nk_white);
22871  } else {
22872  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22873  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22874  }
22875  {
22876  struct nk_rect content;
22877  struct nk_rect button;
22878  struct nk_rect bounds;
22879 
22880  enum nk_symbol_type sym;
22881  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22882  sym = style->combo.sym_hover;
22883  else if (is_clicked)
22884  sym = style->combo.sym_active;
22885  else sym = style->combo.sym_normal;
22886 
22887  /* calculate button */
22888  button.w = header.h - 2 * style->combo.button_padding.y;
22889  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
22890  button.y = header.y + style->combo.button_padding.y;
22891  button.h = button.w;
22892 
22893  content.x = button.x + style->combo.button.padding.x;
22894  content.y = button.y + style->combo.button.padding.y;
22895  content.w = button.w - 2 * style->combo.button.padding.x;
22896  content.h = button.h - 2 * style->combo.button.padding.y;
22897 
22898  /* draw color */
22899  bounds.h = header.h - 4 * style->combo.content_padding.y;
22900  bounds.y = header.y + 2 * style->combo.content_padding.y;
22901  bounds.x = header.x + 2 * style->combo.content_padding.x;
22902  bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x;
22903  nk_fill_rect(&win->buffer, bounds, 0, color);
22904 
22905  /* draw open/close button */
22906  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
22907  &ctx->style.combo.button, sym, style->font);
22908  }
22909  return nk_combo_begin(ctx, win, size, is_clicked, header);
22910 }
22911 
22912 NK_API int
22913 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size)
22914 {
22915  struct nk_window *win;
22916  struct nk_style *style;
22917  const struct nk_input *in;
22918 
22919  struct nk_rect header;
22920  int is_clicked = nk_false;
22922  const struct nk_style_item *background;
22923  struct nk_color sym_background;
22924  struct nk_color symbol_color;
22925 
22926  NK_ASSERT(ctx);
22927  NK_ASSERT(ctx->current);
22928  NK_ASSERT(ctx->current->layout);
22929  if (!ctx || !ctx->current || !ctx->current->layout)
22930  return 0;
22931 
22932  win = ctx->current;
22933  style = &ctx->style;
22934  s = nk_widget(&header, ctx);
22935  if (s == NK_WIDGET_INVALID)
22936  return 0;
22937 
22938  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
22939  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
22940  is_clicked = nk_true;
22941 
22942  /* draw combo box header background and border */
22943  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
22944  background = &style->combo.active;
22945  symbol_color = style->combo.symbol_active;
22946  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
22947  background = &style->combo.hover;
22948  symbol_color = style->combo.symbol_hover;
22949  } else {
22950  background = &style->combo.normal;
22951  symbol_color = style->combo.symbol_hover;
22952  }
22953 
22954  if (background->type == NK_STYLE_ITEM_IMAGE) {
22955  sym_background = nk_rgba(0,0,0,0);
22956  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
22957  } else {
22958  sym_background = background->data.color;
22959  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
22960  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
22961  }
22962  {
22963  struct nk_rect bounds = {0,0,0,0};
22964  struct nk_rect content;
22965  struct nk_rect button;
22966 
22967  enum nk_symbol_type sym;
22968  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
22969  sym = style->combo.sym_hover;
22970  else if (is_clicked)
22971  sym = style->combo.sym_active;
22972  else sym = style->combo.sym_normal;
22973 
22974  /* calculate button */
22975  button.w = header.h - 2 * style->combo.button_padding.y;
22976  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
22977  button.y = header.y + style->combo.button_padding.y;
22978  button.h = button.w;
22979 
22980  content.x = button.x + style->combo.button.padding.x;
22981  content.y = button.y + style->combo.button.padding.y;
22982  content.w = button.w - 2 * style->combo.button.padding.x;
22983  content.h = button.h - 2 * style->combo.button.padding.y;
22984 
22985  /* draw symbol */
22986  bounds.h = header.h - 2 * style->combo.content_padding.y;
22987  bounds.y = header.y + style->combo.content_padding.y;
22988  bounds.x = header.x + style->combo.content_padding.x;
22989  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
22990  nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color,
22991  1.0f, style->font);
22992 
22993  /* draw open/close button */
22994  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
22995  &ctx->style.combo.button, sym, style->font);
22996  }
22997  return nk_combo_begin(ctx, win, size, is_clicked, header);
22998 }
22999 
23000 NK_API int
23001 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len,
23002  enum nk_symbol_type symbol, struct nk_vec2 size)
23003 {
23004  struct nk_window *win;
23005  struct nk_style *style;
23006  struct nk_input *in;
23007 
23008  struct nk_rect header;
23009  int is_clicked = nk_false;
23011  const struct nk_style_item *background;
23012  struct nk_color symbol_color;
23013  struct nk_text text;
23014 
23015  NK_ASSERT(ctx);
23016  NK_ASSERT(ctx->current);
23017  NK_ASSERT(ctx->current->layout);
23018  if (!ctx || !ctx->current || !ctx->current->layout)
23019  return 0;
23020 
23021  win = ctx->current;
23022  style = &ctx->style;
23023  s = nk_widget(&header, ctx);
23024  if (!s) return 0;
23025 
23026  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
23027  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
23028  is_clicked = nk_true;
23029 
23030  /* draw combo box header background and border */
23031  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
23032  background = &style->combo.active;
23033  symbol_color = style->combo.symbol_active;
23034  text.text = style->combo.label_active;
23035  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
23036  background = &style->combo.hover;
23037  symbol_color = style->combo.symbol_hover;
23038  text.text = style->combo.label_hover;
23039  } else {
23040  background = &style->combo.normal;
23041  symbol_color = style->combo.symbol_normal;
23042  text.text = style->combo.label_normal;
23043  }
23044  if (background->type == NK_STYLE_ITEM_IMAGE) {
23045  text.background = nk_rgba(0,0,0,0);
23046  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23047  } else {
23048  text.background = background->data.color;
23049  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
23050  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
23051  }
23052  {
23053  struct nk_rect content;
23054  struct nk_rect button;
23055  struct nk_rect label;
23056  struct nk_rect image;
23057 
23058  enum nk_symbol_type sym;
23059  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23060  sym = style->combo.sym_hover;
23061  else if (is_clicked)
23062  sym = style->combo.sym_active;
23063  else sym = style->combo.sym_normal;
23064 
23065  /* calculate button */
23066  button.w = header.h - 2 * style->combo.button_padding.y;
23067  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
23068  button.y = header.y + style->combo.button_padding.y;
23069  button.h = button.w;
23070 
23071  content.x = button.x + style->combo.button.padding.x;
23072  content.y = button.y + style->combo.button.padding.y;
23073  content.w = button.w - 2 * style->combo.button.padding.x;
23074  content.h = button.h - 2 * style->combo.button.padding.y;
23075  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
23076  &ctx->style.combo.button, sym, style->font);
23077 
23078  /* draw symbol */
23079  image.x = header.x + style->combo.content_padding.x;
23080  image.y = header.y + style->combo.content_padding.y;
23081  image.h = header.h - 2 * style->combo.content_padding.y;
23082  image.w = image.h;
23083  nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color,
23084  1.0f, style->font);
23085 
23086  /* draw label */
23087  text.padding = nk_vec2(0,0);
23088  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
23089  label.y = header.y + style->combo.content_padding.y;
23090  label.w = (button.x - style->combo.content_padding.x) - label.x;
23091  label.h = header.h - 2 * style->combo.content_padding.y;
23092  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
23093  }
23094  return nk_combo_begin(ctx, win, size, is_clicked, header);
23095 }
23096 
23097 NK_API int
23098 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size)
23099 {
23100  struct nk_window *win;
23101  struct nk_style *style;
23102  const struct nk_input *in;
23103 
23104  struct nk_rect header;
23105  int is_clicked = nk_false;
23107  const struct nk_style_item *background;
23108 
23109  NK_ASSERT(ctx);
23110  NK_ASSERT(ctx->current);
23111  NK_ASSERT(ctx->current->layout);
23112  if (!ctx || !ctx->current || !ctx->current->layout)
23113  return 0;
23114 
23115  win = ctx->current;
23116  style = &ctx->style;
23117  s = nk_widget(&header, ctx);
23118  if (s == NK_WIDGET_INVALID)
23119  return 0;
23120 
23121  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
23122  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
23123  is_clicked = nk_true;
23124 
23125  /* draw combo box header background and border */
23126  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED)
23127  background = &style->combo.active;
23128  else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23129  background = &style->combo.hover;
23130  else background = &style->combo.normal;
23131 
23132  if (background->type == NK_STYLE_ITEM_IMAGE) {
23133  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23134  } else {
23135  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
23136  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
23137  }
23138  {
23139  struct nk_rect bounds = {0,0,0,0};
23140  struct nk_rect content;
23141  struct nk_rect button;
23142 
23143  enum nk_symbol_type sym;
23144  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23145  sym = style->combo.sym_hover;
23146  else if (is_clicked)
23147  sym = style->combo.sym_active;
23148  else sym = style->combo.sym_normal;
23149 
23150  /* calculate button */
23151  button.w = header.h - 2 * style->combo.button_padding.y;
23152  button.x = (header.x + header.w - header.h) - style->combo.button_padding.y;
23153  button.y = header.y + style->combo.button_padding.y;
23154  button.h = button.w;
23155 
23156  content.x = button.x + style->combo.button.padding.x;
23157  content.y = button.y + style->combo.button.padding.y;
23158  content.w = button.w - 2 * style->combo.button.padding.x;
23159  content.h = button.h - 2 * style->combo.button.padding.y;
23160 
23161  /* draw image */
23162  bounds.h = header.h - 2 * style->combo.content_padding.y;
23163  bounds.y = header.y + style->combo.content_padding.y;
23164  bounds.x = header.x + style->combo.content_padding.x;
23165  bounds.w = (button.x - style->combo.content_padding.y) - bounds.x;
23166  nk_draw_image(&win->buffer, bounds, &img, nk_white);
23167 
23168  /* draw open/close button */
23169  nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state,
23170  &ctx->style.combo.button, sym, style->font);
23171  }
23172  return nk_combo_begin(ctx, win, size, is_clicked, header);
23173 }
23174 
23175 NK_API int
23176 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len,
23177  struct nk_image img, struct nk_vec2 size)
23178 {
23179  struct nk_window *win;
23180  struct nk_style *style;
23181  struct nk_input *in;
23182 
23183  struct nk_rect header;
23184  int is_clicked = nk_false;
23186  const struct nk_style_item *background;
23187  struct nk_text text;
23188 
23189  NK_ASSERT(ctx);
23190  NK_ASSERT(ctx->current);
23191  NK_ASSERT(ctx->current->layout);
23192  if (!ctx || !ctx->current || !ctx->current->layout)
23193  return 0;
23194 
23195  win = ctx->current;
23196  style = &ctx->style;
23197  s = nk_widget(&header, ctx);
23198  if (!s) return 0;
23199 
23200  in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input;
23201  if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT))
23202  is_clicked = nk_true;
23203 
23204  /* draw combo box header background and border */
23205  if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) {
23206  background = &style->combo.active;
23207  text.text = style->combo.label_active;
23208  } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) {
23209  background = &style->combo.hover;
23210  text.text = style->combo.label_hover;
23211  } else {
23212  background = &style->combo.normal;
23213  text.text = style->combo.label_normal;
23214  }
23215  if (background->type == NK_STYLE_ITEM_IMAGE) {
23216  text.background = nk_rgba(0,0,0,0);
23217  nk_draw_image(&win->buffer, header, &background->data.image, nk_white);
23218  } else {
23219  text.background = background->data.color;
23220  nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color);
23221  nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color);
23222  }
23223  {
23224  struct nk_rect content;
23225  struct nk_rect button;
23226  struct nk_rect label;
23227  struct nk_rect image;
23228 
23229  enum nk_symbol_type sym;
23230  if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER)
23231  sym = style->combo.sym_hover;
23232  else if (is_clicked)
23233  sym = style->combo.sym_active;
23234  else sym = style->combo.sym_normal;
23235 
23236  /* calculate button */
23237  button.w = header.h - 2 * style->combo.button_padding.y;
23238  button.x = (header.x + header.w - header.h) - style->combo.button_padding.x;
23239  button.y = header.y + style->combo.button_padding.y;
23240  button.h = button.w;
23241 
23242  content.x = button.x + style->combo.button.padding.x;
23243  content.y = button.y + style->combo.button.padding.y;
23244  content.w = button.w - 2 * style->combo.button.padding.x;
23245  content.h = button.h - 2 * style->combo.button.padding.y;
23246  nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state,
23247  &ctx->style.combo.button, sym, style->font);
23248 
23249  /* draw image */
23250  image.x = header.x + style->combo.content_padding.x;
23251  image.y = header.y + style->combo.content_padding.y;
23252  image.h = header.h - 2 * style->combo.content_padding.y;
23253  image.w = image.h;
23254  nk_draw_image(&win->buffer, image, &img, nk_white);
23255 
23256  /* draw label */
23257  text.padding = nk_vec2(0,0);
23258  label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x;
23259  label.y = header.y + style->combo.content_padding.y;
23260  label.w = (button.x - style->combo.content_padding.x) - label.x;
23261  label.h = header.h - 2 * style->combo.content_padding.y;
23262  nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font);
23263  }
23264  return nk_combo_begin(ctx, win, size, is_clicked, header);
23265 }
23266 
23268  const char *selected, enum nk_symbol_type type, struct nk_vec2 size)
23269 {return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);}
23270 
23272  const char *selected, struct nk_image img, struct nk_vec2 size)
23273 {return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);}
23274 
23275 NK_API int nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align)
23276 {return nk_contextual_item_text(ctx, text, len, align);}
23277 
23278 NK_API int nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align)
23280 
23281 NK_API int nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text,
23282  int len, nk_flags alignment)
23283 {return nk_contextual_item_image_text(ctx, img, text, len, alignment);}
23284 
23286  const char *text, nk_flags alignment)
23287 {return nk_contextual_item_image_label(ctx, img, text, alignment);}
23288 
23290  const char *text, int len, nk_flags alignment)
23291 {return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);}
23292 
23294  const char *label, nk_flags alignment)
23295 {return nk_contextual_item_symbol_label(ctx, sym, label, alignment);}
23296 
23297 NK_API void nk_combo_end(struct nk_context *ctx)
23299 
23300 NK_API void nk_combo_close(struct nk_context *ctx)
23302 
23303 NK_API int
23304 nk_combo(struct nk_context *ctx, const char **items, int count,
23305  int selected, int item_height, struct nk_vec2 size)
23306 {
23307  int i = 0;
23308  int max_height;
23309  struct nk_vec2 item_spacing;
23310  struct nk_vec2 window_padding;
23311 
23312  NK_ASSERT(ctx);
23313  NK_ASSERT(items);
23314  NK_ASSERT(ctx->current);
23315  if (!ctx || !items ||!count)
23316  return selected;
23317 
23318  item_spacing = ctx->style.window.spacing;
23319  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23320  max_height = count * item_height + count * (int)item_spacing.y;
23321  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23322  size.y = NK_MIN(size.y, (float)max_height);
23323  if (nk_combo_begin_label(ctx, items[selected], size)) {
23324  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23325  for (i = 0; i < count; ++i) {
23326  if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT))
23327  selected = i;
23328  }
23329  nk_combo_end(ctx);
23330  }
23331  return selected;
23332 }
23333 
23334 NK_API int
23335 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator,
23336  int separator, int selected, int count, int item_height, struct nk_vec2 size)
23337 {
23338  int i;
23339  int max_height;
23340  struct nk_vec2 item_spacing;
23341  struct nk_vec2 window_padding;
23342  const char *current_item;
23343  const char *iter;
23344  int length = 0;
23345 
23346  NK_ASSERT(ctx);
23347  NK_ASSERT(items_separated_by_separator);
23348  if (!ctx || !items_separated_by_separator)
23349  return selected;
23350 
23351  /* calculate popup window */
23352  item_spacing = ctx->style.window.spacing;
23353  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23354  max_height = count * item_height + count * (int)item_spacing.y;
23355  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23356  size.y = NK_MIN(size.y, (float)max_height);
23357 
23358  /* find selected item */
23359  current_item = items_separated_by_separator;
23360  for (i = 0; i < count; ++i) {
23361  iter = current_item;
23362  while (*iter && *iter != separator) iter++;
23363  length = (int)(iter - current_item);
23364  if (i == selected) break;
23365  current_item = iter + 1;
23366  }
23367 
23368  if (nk_combo_begin_text(ctx, current_item, length, size)) {
23369  current_item = items_separated_by_separator;
23370  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23371  for (i = 0; i < count; ++i) {
23372  iter = current_item;
23373  while (*iter && *iter != separator) iter++;
23374  length = (int)(iter - current_item);
23375  if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT))
23376  selected = i;
23377  current_item = current_item + length + 1;
23378  }
23379  nk_combo_end(ctx);
23380  }
23381  return selected;
23382 }
23383 
23384 NK_API int
23385 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros,
23386  int selected, int count, int item_height, struct nk_vec2 size)
23387 {return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);}
23388 
23389 NK_API int
23390 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**),
23391  void *userdata, int selected, int count, int item_height, struct nk_vec2 size)
23392 {
23393  int i;
23394  int max_height;
23395  struct nk_vec2 item_spacing;
23396  struct nk_vec2 window_padding;
23397  const char *item;
23398 
23399  NK_ASSERT(ctx);
23400  NK_ASSERT(item_getter);
23401  if (!ctx || !item_getter)
23402  return selected;
23403 
23404  /* calculate popup window */
23405  item_spacing = ctx->style.window.spacing;
23406  window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type);
23407  max_height = count * item_height + count * (int)item_spacing.y;
23408  max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2;
23409  size.y = NK_MIN(size.y, (float)max_height);
23410 
23411  item_getter(userdata, selected, &item);
23412  if (nk_combo_begin_label(ctx, item, size)) {
23413  nk_layout_row_dynamic(ctx, (float)item_height, 1);
23414  for (i = 0; i < count; ++i) {
23415  item_getter(userdata, i, &item);
23416  if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT))
23417  selected = i;
23418  }
23419  nk_combo_end(ctx);
23420  }
23421  return selected;
23422 }
23423 
23424 NK_API void nk_combobox(struct nk_context *ctx, const char **items, int count,
23425  int *selected, int item_height, struct nk_vec2 size)
23426 {*selected = nk_combo(ctx, items, count, *selected, item_height, size);}
23427 
23428 NK_API void nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros,
23429  int *selected, int count, int item_height, struct nk_vec2 size)
23430 {*selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);}
23431 
23432 NK_API void nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator,
23433  int separator,int *selected, int count, int item_height, struct nk_vec2 size)
23434 {*selected = nk_combo_separator(ctx, items_separated_by_separator, separator,
23435  *selected, count, item_height, size);}
23436 
23438  void(*item_getter)(void* data, int id, const char **out_text),
23439  void *userdata, int *selected, int count, int item_height, struct nk_vec2 size)
23440 {*selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size);}
23441 
23442 /*
23443  * -------------------------------------------------------------
23444  *
23445  * MENU
23446  *
23447  * --------------------------------------------------------------
23448  */
23449 NK_INTERN int
23450 nk_menu_begin(struct nk_context *ctx, struct nk_window *win,
23451  const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size)
23452 {
23453  int is_open = 0;
23454  int is_active = 0;
23455  struct nk_rect body;
23456  struct nk_window *popup;
23457  nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU);
23458 
23459  NK_ASSERT(ctx);
23460  NK_ASSERT(ctx->current);
23461  NK_ASSERT(ctx->current->layout);
23462  if (!ctx || !ctx->current || !ctx->current->layout)
23463  return 0;
23464 
23465  body.x = header.x;
23466  body.w = size.x;
23467  body.y = header.y + header.h;
23468  body.h = size.y;
23469 
23470  popup = win->popup.win;
23471  is_open = popup ? nk_true : nk_false;
23472  is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU);
23473  if ((is_clicked && is_open && !is_active) || (is_open && !is_active) ||
23474  (!is_open && !is_active && !is_clicked)) return 0;
23475  if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU))
23476  return 0;
23477 
23478  win->popup.type = NK_PANEL_MENU;
23479  win->popup.name = hash;
23480  return 1;
23481 }
23482 
23483 NK_API int
23484 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len,
23485  nk_flags align, struct nk_vec2 size)
23486 {
23487  struct nk_window *win;
23488  const struct nk_input *in;
23489  struct nk_rect header;
23490  int is_clicked = nk_false;
23491  nk_flags state;
23492 
23493  NK_ASSERT(ctx);
23494  NK_ASSERT(ctx->current);
23495  NK_ASSERT(ctx->current->layout);
23496  if (!ctx || !ctx->current || !ctx->current->layout)
23497  return 0;
23498 
23499  win = ctx->current;
23500  state = nk_widget(&header, ctx);
23501  if (!state) return 0;
23502  in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23503  if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header,
23504  title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
23505  is_clicked = nk_true;
23506  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23507 }
23508 
23510  const char *text, nk_flags align, struct nk_vec2 size)
23511 {return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);}
23512 
23513 NK_API int
23514 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img,
23515  struct nk_vec2 size)
23516 {
23517  struct nk_window *win;
23518  struct nk_rect header;
23519  const struct nk_input *in;
23520  int is_clicked = nk_false;
23521  nk_flags state;
23522 
23523  NK_ASSERT(ctx);
23524  NK_ASSERT(ctx->current);
23525  NK_ASSERT(ctx->current->layout);
23526  if (!ctx || !ctx->current || !ctx->current->layout)
23527  return 0;
23528 
23529  win = ctx->current;
23530  state = nk_widget(&header, ctx);
23531  if (!state) return 0;
23532  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23533  if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header,
23534  img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in))
23535  is_clicked = nk_true;
23536  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
23537 }
23538 
23539 NK_API int
23540 nk_menu_begin_symbol(struct nk_context *ctx, const char *id,
23541  enum nk_symbol_type sym, struct nk_vec2 size)
23542 {
23543  struct nk_window *win;
23544  const struct nk_input *in;
23545  struct nk_rect header;
23546  int is_clicked = nk_false;
23547  nk_flags state;
23548 
23549  NK_ASSERT(ctx);
23550  NK_ASSERT(ctx->current);
23551  NK_ASSERT(ctx->current->layout);
23552  if (!ctx || !ctx->current || !ctx->current->layout)
23553  return 0;
23554 
23555  win = ctx->current;
23556  state = nk_widget(&header, ctx);
23557  if (!state) return 0;
23558  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23559  if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header,
23560  sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font))
23561  is_clicked = nk_true;
23562  return nk_menu_begin(ctx, win, id, is_clicked, header, size);
23563 }
23564 
23565 NK_API int
23566 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len,
23567  nk_flags align, struct nk_image img, struct nk_vec2 size)
23568 {
23569  struct nk_window *win;
23570  struct nk_rect header;
23571  const struct nk_input *in;
23572  int is_clicked = nk_false;
23573  nk_flags state;
23574 
23575  NK_ASSERT(ctx);
23576  NK_ASSERT(ctx->current);
23577  NK_ASSERT(ctx->current->layout);
23578  if (!ctx || !ctx->current || !ctx->current->layout)
23579  return 0;
23580 
23581  win = ctx->current;
23582  state = nk_widget(&header, ctx);
23583  if (!state) return 0;
23584  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23585  if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer,
23586  header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
23587  ctx->style.font, in))
23588  is_clicked = nk_true;
23589  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23590 }
23591 
23593  const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size)
23594 {return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);}
23595 
23596 NK_API int
23597 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len,
23598  nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size)
23599 {
23600  struct nk_window *win;
23601  struct nk_rect header;
23602  const struct nk_input *in;
23603  int is_clicked = nk_false;
23604  nk_flags state;
23605 
23606  NK_ASSERT(ctx);
23607  NK_ASSERT(ctx->current);
23608  NK_ASSERT(ctx->current->layout);
23609  if (!ctx || !ctx->current || !ctx->current->layout)
23610  return 0;
23611 
23612  win = ctx->current;
23613  state = nk_widget(&header, ctx);
23614  if (!state) return 0;
23615 
23616  in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input;
23617  if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer,
23618  header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button,
23619  ctx->style.font, in)) is_clicked = nk_true;
23620  return nk_menu_begin(ctx, win, title, is_clicked, header, size);
23621 }
23622 
23624  const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size )
23625 {return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);}
23626 
23627 NK_API int nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align)
23628 {return nk_contextual_item_text(ctx, title, len, align);}
23629 
23630 NK_API int nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align)
23632 
23634  const char *label, nk_flags align)
23636 
23638  const char *text, int len, nk_flags align)
23639 {return nk_contextual_item_image_text(ctx, img, text, len, align);}
23640 
23642  const char *text, int len, nk_flags align)
23643 {return nk_contextual_item_symbol_text(ctx, sym, text, len, align);}
23644 
23646  const char *label, nk_flags align)
23648 
23649 NK_API void nk_menu_close(struct nk_context *ctx)
23651 
23652 NK_API void
23653 nk_menu_end(struct nk_context *ctx)
23655 
23656 #endif /* NK_IMPLEMENTATION */
const struct nk_draw_vertex_layout_element * vertex_layout
Definition: nuklear.h:989
Definition: nuklear.h:3884
float item_width
Definition: nuklear.h:3867
NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value)
NK_API void nk_buffer_mark(struct nk_buffer *, enum nk_buffer_allocation_type type)
NK_API void nk_layout_space_push(struct nk_context *, struct nk_rect)
Definition: nuklear.h:3171
Definition: nuklear.h:467
nk_button_behavior
Definition: nuklear.h:466
struct nk_font * font
Definition: nk_common.c:40
Definition: nuklear.h:2814
float min
Definition: nuklear.h:3836
nk_handle userdata
Definition: nuklear.h:3640
unsigned short line_thickness
Definition: nuklear.h:3058
struct nk_color background
Definition: nuklear.h:3115
Definition: nuklear.h:491
nk_tree_type
Definition: nuklear.h:476
nk_size size
Definition: nuklear.h:2702
NK_API void nk_textedit_redo(struct nk_text_edit *)
NK_API int nk_menu_begin_image_label(struct nk_context *, const char *, nk_flags align, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:2018
Definition: nuklear.h:3930
unsigned short w
Definition: nuklear.h:3050
struct nk_style_button menu_button
Definition: nuklear.h:3787
NK_POINTER_TYPE nk_ptr
Definition: nuklear.h:402
void(* nk_plugin_paste)(nk_handle, struct nk_text_edit *)
Definition: nuklear.h:481
NK_API char * nk_str_get(struct nk_str *)
#define NK_CHART_MAX_SLOT
Definition: nuklear.h:3814
Definition: nuklear.h:2147
NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input *, struct nk_rect)
NK_API int nk_select_label(struct nk_context *, const char *, nk_flags align, int value)
NK_API int nk_window_is_closed(struct nk_context *, const char *)
Definition: nuklear.h:473
nk_handle userdata
Definition: nuklear.h:3516
NK_API int nk_str_append_str_runes(struct nk_str *, const nk_rune *)
enum nk_symbol_type inc_symbol
Definition: nuklear.h:3512
void *(* nk_plugin_alloc)(nk_handle, void *old, nk_size)
Definition: nuklear.h:478
float h
Definition: nuklear.h:3844
struct nk_style_item cursor_active
Definition: nuklear.h:3498
NK_API void nk_style_show_cursor(struct nk_context *)
NK_API void * nk_buffer_memory(struct nk_buffer *)
NK_API void nk_textedit_free(struct nk_text_edit *)
struct nk_style_item active
Definition: nuklear.h:3618
Definition: nuklear.h:3842
struct nk_page * next
Definition: nuklear.h:4118
static char * number(char *str, long num, int base, int size, int precision, int type)
Definition: kprintf.c:42
Definition: nuklear.h:3112
NK_API const struct nk_command * nk__begin(struct nk_context *)
struct nk_color border_color
Definition: nuklear.h:3619
Definition: nuklear.h:2684
Definition: nuklear.h:493
#define ftell
Definition: file_stream_transforms.h:54
unsigned circle_segment_count
Definition: nuklear.h:985
Definition: nuklear.h:2154
unsigned curve_segment_count
Definition: nuklear.h:987
nk_plugin_free free
Definition: nuklear.h:487
unsigned int scrolled
Definition: nuklear.h:3988
GLuint const GLchar * name
Definition: glext.h:6671
nk_keys
Definition: nuklear.h:660
NK_API void nk_text(struct nk_context *, const char *, int, nk_flags)
Definition: nuklear.h:2025
GLuint * ids
Definition: glext.h:6547
NK_API int nk_combo_begin_symbol_label(struct nk_context *, const char *selected, enum nk_symbol_type, struct nk_vec2 size)
NK_API int nk_str_len_char(struct nk_str *)
struct nk_style_item fixed_background
Definition: nuklear.h:3742
#define NK_INT16
Definition: nuklear.h:343
struct nk_color cursor_text_hover
Definition: nuklear.h:3592
enum nk_symbol_type sym_active
Definition: nuklear.h:3679
short x
Definition: nuklear.h:3041
NK_API int nk_group_scrolled_offset_begin(struct nk_context *, nk_uint *x_offset, nk_uint *y_offset, const char *, nk_flags)
const GLvoid * ptr
Definition: nx_glsym.h:242
struct nk_scroll scrollbar
Definition: nuklear.h:3979
float height
Definition: nuklear.h:3119
NK_UINT8 nk_uchar
Definition: nuklear.h:395
struct nk_color symbol_hover
Definition: nuklear.h:3672
#define NK_SIZE_TYPE
Definition: nuklear.h:374
NK_API int nk_strlen(const char *str)
Definition: nuklear.h:3740
struct nk_page_element * next
Definition: nuklear.h:4112
NK_API int nk_contextual_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
const GLint * first
Definition: glext.h:6478
struct nk_style_item hover
Definition: nuklear.h:3661
Definition: nuklear.h:3086
NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect *, struct nk_context *, struct nk_vec2)
float w
Definition: nuklear.h:457
struct nk_color menu_border_color
Definition: nuklear.h:3749
Definition: nuklear.h:2484
Definition: nuklear.h:472
int active
Definition: nuklear.h:2680
Definition: nuklear.h:2175
GLubyte * pattern
Definition: glext.h:8454
float y
Definition: nuklear.h:457
Definition: nuklear.h:2151
Definition: nuklear.h:2157
char nk_glyph[NK_UTF_SIZE]
Definition: nuklear.h:459
NK_API int nk_strfilter(const char *text, const char *regexp)
NK_API int nk_tree_push_hashed(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
NK_API void nk_image(struct nk_context *, struct nk_image)
int select_start
Definition: nuklear.h:3964
NK_API int nk_filter_ascii(const struct nk_text_edit *, nk_rune unicode)
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3478
NK_API void nk_fill_rect(struct nk_command_buffer *, struct nk_rect, float rounding, struct nk_color)
enum nk_allocation_type type
Definition: nuklear.h:2690
struct nk_vec2 touch_padding
Definition: nuklear.h:3437
NK_API int nk_checkbox_flags_label(struct nk_context *, const char *, unsigned int *flags, unsigned int value)
struct nk_vec2 padding
Definition: nuklear.h:3610
NK_API int nk_str_insert_str_runes(struct nk_str *, int pos, const nk_rune *)
float preferred_x
Definition: nuklear.h:2863
unsigned short h
Definition: nuklear.h:3043
NK_API void nk_menu_end(struct nk_context *)
short cy
Definition: nuklear.h:3065
static int align(int x, int n)
Definition: psp2.c:23
unsigned int seq
Definition: nuklear.h:4097
NK_API const char * nk_style_get_color_by_name(enum nk_style_colors)
unsigned short r
Definition: nuklear.h:3066
struct nk_style_item hover
Definition: nuklear.h:3420
NK_API struct nk_vec2 nk_vec2(float x, float y)
NK_API int nk_input_is_mouse_down(const struct nk_input *, enum nk_buttons)
NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context *)
struct nk_menu_state menu
Definition: nuklear.h:3901
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)
NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed)
nk_style_header_align
Definition: nuklear.h:3711
#define const
Definition: zconf.h:217
NK_API int nk_str_insert_text_runes(struct nk_str *, int pos, const nk_rune *, int)
struct nk_window * parent
Definition: nuklear.h:3996
NK_API char * nk_str_at_rune(struct nk_str *, int pos, nk_rune *unicode, int *len)
NK_API int nk_slider_int(struct nk_context *, int min, int *val, int max, int step)
Definition: nuklear.h:3828
GLuint GLfloat * val
Definition: glext.h:7847
set set set set set set set macro pixldst1 op
Definition: pixman-arm-neon-asm.h:54
NK_API int nk_style_pop_vec2(struct nk_context *)
NK_API int nk_button_symbol(struct nk_context *, enum nk_symbol_type)
Definition: nuklear.h:2022
Definition: nuklear.h:1844
enum nk_style_header_align align
Definition: nuklear.h:3734
NK_API void nk_label_colored_wrap(struct nk_context *, const char *, struct nk_color)
Definition: nuklear.h:4104
Definition: nuklear.h:3417
Definition: nuklear.h:2995
#define NK_INPUT_MAX
Definition: nuklear.h:257
nk_anti_aliasing
Definition: nuklear.h:969
#define nk_vec2_len_sqr(a)
Definition: nuklear.h:4195
float y
Definition: nuklear.h:455
int columns
Definition: nuklear.h:3865
Definition: nuklear.h:456
struct nk_vec2 padding
Definition: nuklear.h:3436
NK_API int nk_button_image_text(struct nk_context *, struct nk_image img, const char *, int, nk_flags alignment)
static const unsigned char tag[MAX_TESTS *3][16]
Definition: gcm.c:696
NK_API void nk_layout_row_end(struct nk_context *)
struct nk_color border_color
Definition: nuklear.h:3395
nk_uint x
Definition: nuklear.h:463
struct nk_window * next
Definition: nuklear.h:3994
#define NK_ALIGN_PTR_BACK(x, mask)
Definition: nuklear.h:4222
NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color)
struct nk_chart chart
Definition: nuklear.h:3903
NK_API int nk_selectable_label(struct nk_context *, const char *, nk_flags align, int *value)
NK_API void nk_combobox(struct nk_context *, const char **items, int count, int *selected, int item_height, struct nk_vec2 size)
nk_window_flags
Definition: nuklear.h:3916
NK_API void nk_window_set_focus(struct nk_context *, const char *name)
struct nk_config_stack_vec2 vectors
Definition: nuklear.h:4083
struct nk_color border_color
Definition: nuklear.h:3422
NK_API void nk_layout_row_template_begin(struct nk_context *, float row_height)
NK_API int nk_color_pick(struct nk_context *, struct nk_color *, enum nk_color_format)
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3577
float border
Definition: nuklear.h:3501
struct nk_allocator alloc
Definition: nuklear.h:4123
Definition: nuklear.h:1839
float y
Definition: nuklear.h:3885
NK_API int nk_utf_len(const char *, int byte_len)
nk_color_format
Definition: nuklear.h:473
unsigned active_con
Definition: nuklear.h:3942
Definition: nuklear.h:3972
Definition: nuklear.h:465
NK_API int nk_stricmp(const char *s1, const char *s2)
NK_API void nk_stroke_curve(struct nk_command_buffer *, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color)
nk_size cap
Definition: nuklear.h:4130
Definition: nuklear.h:3380
Definition: nuklear.h:452
struct nk_style_scrollbar scrollbar
Definition: nuklear.h:3586
struct nk_command header
Definition: nuklear.h:3105
Definition: nuklear.h:2972
Definition: nuklear.h:3829
Definition: nuklear.h:453
struct nk_color text_hover
Definition: nuklear.h:3460
NK_API int nk_combo_item_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags alignment)
struct nk_style_item active
Definition: nuklear.h:3421
GLboolean GLenum GLenum GLvoid * values
Definition: glext.h:6318
NK_API void nk_buffer_init_fixed(struct nk_buffer *, void *memory, nk_size size)
struct nk_row_layout row
Definition: nuklear.h:3902
struct nk_vec2 spacing
Definition: nuklear.h:3737
struct nk_panel * parent
Definition: nuklear.h:3905
short x
Definition: nuklear.h:2999
unsigned char grab
Definition: nuklear.h:3177
NK_API int nk_filter_decimal(const struct nk_text_edit *, nk_rune unicode)
GLuint buffer
Definition: glext.h:6555
Definition: nuklear.h:2007
int down
Definition: nuklear.h:3167
Definition: nuklear.h:2004
void * ptr
Definition: nuklear.h:2684
NK_API int nk_tooltip_begin(struct nk_context *, float width)
struct nk_buffer memory
Definition: nuklear.h:4137
NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context *)
struct nk_color text_normal
Definition: nuklear.h:3429
struct nk_vec2 clicked_pos
Definition: nuklear.h:3169
NK_API void nk_layout_row_template_push_dynamic(struct nk_context *)
Definition: nuklear.h:471
float height
Definition: nuklear.h:3863
Definition: nuklear.h:3934
NK_API int nk_style_push_float(struct nk_context *, float *, float)
Definition: nuklear.h:476
NK_API int nk_utf_decode(const char *, nk_rune *, int)
Definition: nuklear.h:3186
unsigned short w
Definition: nuklear.h:3000
NK_API struct nk_rect nk_recti(int x, int y, int w, int h)
nk_symbol_type
Definition: nuklear.h:489
NK_API void nk_end(struct nk_context *ctx)
NK_API int nk_tree_image_push_hashed(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len, int seed)
Definition: nuklear.h:2827
Definition: nuklear.h:469
struct nk_vec2 scrollbar
Definition: nuklear.h:2851
NK_API int nk_button_label_styled(struct nk_context *, const struct nk_style_button *, const char *title)
struct nk_color label_normal
Definition: nuklear.h:3622
NK_API int nk_str_insert_str_char(struct nk_str *, int pos, const char *)
NK_API void nk_input_key(struct nk_context *, enum nk_keys, int down)
NK_API struct nk_color nk_rgba_u32(nk_uint)
NK_API int nk_init_fixed(struct nk_context *, void *memory, nk_size size, const struct nk_user_font *)
NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
Definition: nuklear.h:2153
enum nk_symbol_type dec_symbol
Definition: nuklear.h:3572
NK_API int nk_window_is_hidden(struct nk_context *, const char *)
nk_uint * offset_x
Definition: nuklear.h:3893
float rounding
Definition: nuklear.h:3471
int sel_start
Definition: nuklear.h:3952
#define T(x)
NK_API void nk_layout_row_template_end(struct nk_context *)
struct nk_table * prev
Definition: nuklear.h:4101
NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a)
Definition: nuklear.h:2670
Definition: nuklear.h:673
struct nk_color label_hover
Definition: nuklear.h:3730
GLenum query
Definition: glext.h:8448
static int codepoint(lua_State *L)
Definition: lutf8lib.c:100
NK_API struct nk_color nk_hsva_iv(const int *hsva)
Definition: nuklear.h:2142
struct nk_style_item normal
Definition: nuklear.h:3660
return
Definition: irq.c:321
struct nk_color symbol_normal
Definition: nuklear.h:3671
struct nk_style_item pressed
Definition: nuklear.h:3451
unsigned short line_thickness
Definition: nuklear.h:2998
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)
int use_pool
Definition: nuklear.h:4163
struct nk_color text
Definition: nuklear.h:3693
Definition: nuklear.h:3876
GLenum target
Definition: glext.h:7982
Definition: nuklear.h:3166
NK_API void nk_str_delete_chars(struct nk_str *, int pos, int len)
GLuint start
Definition: glext.h:6292
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3517
nk_layout_format
Definition: nuklear.h:475
Definition: nuklear.h:1182
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:8418
Definition: nuklear.h:2731
nk_size needed
Definition: nuklear.h:2664
NK_API int nk_button_text(struct nk_context *, const char *title, int len)
NK_API int nk_filter_oct(const struct nk_text_edit *, nk_rune unicode)
unsigned int table_count
Definition: nuklear.h:3991
#define NK_SCROLLBAR_HIDING_TIMEOUT
Definition: nuklear.h:263
NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color)
Definition: nuklear.h:2956
NK_API struct nk_rect nk_rect(float x, float y, float w, float h)
float border
Definition: nuklear.h:3898
unsigned char padding1
Definition: nuklear.h:2862
unsigned con_old
Definition: nuklear.h:3941
float contextual_border
Definition: nuklear.h:3756
int use_clipping
Definition: nuklear.h:3132
struct nk_command header
Definition: nuklear.h:2987
NK_API int nk_str_insert_str_utf8(struct nk_str *, int pos, const char *)
enum nk_symbol_type sym_left
Definition: nuklear.h:3627
Definition: nuklear.h:2171
#define NK_MAX(a, b)
Definition: nuklear.h:316
Definition: nuklear.h:662
struct nk_page_element * freelist
Definition: nuklear.h:4169
void(* nk_plugin_copy)(nk_handle, const char *, int len)
Definition: nuklear.h:482
void * malloc(YYSIZE_T)
#define SEEK_END
Definition: zconf.h:440
NK_API int nk_filter_binary(const struct nk_text_edit *, nk_rune unicode)
GLfixed GLfixed x2
Definition: glsym_gl.h:1051
NK_API int nk_input_has_mouse_click(const struct nk_input *, enum nk_buttons)
NK_API int nk_str_append_str_utf8(struct nk_str *, const char *)
GLuint address
Definition: glext.h:10300
unsigned char initialized
Definition: nuklear.h:2858
NK_API int nk_button_text_styled(struct nk_context *, const struct nk_style_button *, const char *title, int len)
NK_API struct nk_rect nk_rectiv(const int *xywh)
NK_API int nk_radio_text(struct nk_context *, const char *, int, int *active)
void(* nk_command_custom_callback)(void *canvas, short x, short y, unsigned short w, unsigned short h, nk_handle callback_data)
Definition: nuklear.h:3102
Definition: libretro.h:2275
NK_API void nk_input_unicode(struct nk_context *, nk_rune)
GLdouble GLdouble GLdouble r
Definition: glext.h:6406
Definition: nuklear.h:3852
NK_API void nk_window_set_bounds(struct nk_context *, const char *name, struct nk_rect bounds)
int where
Definition: nuklear.h:2821
text_alignment
Definition: video_defines.h:103
struct nk_page * pages
Definition: nuklear.h:4126
NK_API void nk_combo_end(struct nk_context *)
short x
Definition: nuklear.h:3117
NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading)
GLsizei const GLchar ** path
Definition: glext.h:7901
NK_API int nk_group_begin(struct nk_context *, const char *title, nk_flags)
unsigned short point_count
Definition: nuklear.h:3075
NK_API void nk_layout_space_begin(struct nk_context *, enum nk_layout_format, float height, int widget_count)
float w
Definition: nuklear.h:3844
GLuint res
Definition: glext.h:10520
Definition: nuklear.h:975
#define NK_FLOAT_STACK_SIZE
Definition: nuklear.h:4037
NK_API int nk_str_len(struct nk_str *)
GLdouble GLdouble t
Definition: glext.h:6398
float border
Definition: nuklear.h:3439
nk_show_states
Definition: nuklear.h:470
struct nk_rect clip
Definition: nuklear.h:3131
Definition: nuklear.h:3924
unsigned short h
Definition: nuklear.h:3000
struct nk_style_button button
Definition: nuklear.h:3676
struct nk_color text_hover_active
Definition: nuklear.h:3465
NK_API int nk_filter_float(const struct nk_text_edit *, nk_rune unicode)
nk_popup_type
Definition: nuklear.h:474
float rounding
Definition: nuklear.h:3406
Definition: memr.c:17
NK_API int nk_combo_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
short x
Definition: nuklear.h:3096
nk_panel_type
Definition: nuklear.h:3817
enum nk_symbol_type sym_minimize
Definition: nuklear.h:3700
nk_buffer_allocation_type
Definition: nuklear.h:2673
enum nk_chart_type type
Definition: nuklear.h:3833
void(* draw_begin)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:3413
short y
Definition: nuklear.h:3096
NK_API int nk_option_label(struct nk_context *, const char *, int active)
NK_API void nk_popup_end(struct nk_context *)
static overlayled_t * cur
Definition: led_overlay.c:18
struct nk_vec2 spacing
Definition: nuklear.h:3764
GLenum GLsizei len
Definition: glext.h:7389
struct nk_vec2 min_size
Definition: nuklear.h:3766
struct nk_color combo_border_color
Definition: nuklear.h:3747
struct nk_color text_active
Definition: nuklear.h:3431
NK_API int nk_progress(struct nk_context *, nk_size *cur, nk_size max, int modifyable)
NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva)
NK_API void nk_input_scroll(struct nk_context *, struct nk_vec2 val)
struct nk_configuration_stacks stacks
Definition: nuklear.h:4141
Definition: nuklear.h:1841
unsigned capacity
Definition: nuklear.h:4128
Definition: nuklear.h:2944
float bar_height
Definition: nuklear.h:3503
GLbyte ty
Definition: glext.h:9663
NK_API struct nk_style_item nk_style_item_hide(void)
struct nk_page_element * prev
Definition: nuklear.h:4113
GLenum GLint * range
Definition: glext.h:8206
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3479
struct nk_style_button inc_button
Definition: nuklear.h:3636
Definition: nuklear.h:494
Definition: nuklear.h:2953
struct nk_color text_normal
Definition: nuklear.h:3399
NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color)
struct nk_color bar_active
Definition: nuklear.h:3492
GLenum GLsizei GLenum GLenum const GLvoid * table
Definition: glext.h:6296
struct nk_color text_pressed_active
Definition: nuklear.h:3466
Definition: nuklear.h:2176
NK_API int nk_button_image_text_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, int, nk_flags alignment)
NK_API int nk_slider_float(struct nk_context *, float min, float *val, float max, float step)
NK_API int nk_menu_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
static const float font_size
Definition: config.def.h:434
GLsizeiptr size
Definition: glext.h:6559
Definition: nuklear.h:2016
NK_API int nk_menu_begin_symbol_text(struct nk_context *, const char *, int, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
NK_API int nk_select_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int value)
nk_handle userdata
Definition: nuklear.h:3133
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3544
NK_API int nk_filter_default(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:465
GLfloat f
Definition: glext.h:8207
int sel_end
Definition: nuklear.h:3953
Definition: nuklear.h:661
NK_API void nk_input_glyph(struct nk_context *, const nk_glyph)
NK_API float nk_window_get_height(const struct nk_context *)
#define NK_UINT32
Definition: nuklear.h:359
struct nk_style_button minimize_button
Definition: nuklear.h:3723
NK_API struct nk_vec2 nk_vec2v(const float *xy)
NK_API int nk_checkbox_text(struct nk_context *, const char *, int, int *active)
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld [DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld endif[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp local skip1 beq endif SRC MASK if dst_r_bpp DST_R else add endif PF add sub src_basereg pixdeinterleave mask_basereg pixdeinterleave dst_r_basereg process_pixblock_head pixblock_size cache_preload_simple process_pixblock_tail pixinterleave dst_w_basereg irp beq endif process_pixblock_tail_head tst beq irp if pixblock_size chunk_size tst beq pixld_src SRC pixld MASK if DST_R else pixld DST_R endif if
Definition: pixman-arm-neon-asm.h:543
Definition: nuklear.h:465
NK_API int nk_menu_item_label(struct nk_context *, const char *, nk_flags alignment)
Definition: nuklear.h:4096
Definition: nuklear.h:495
GLenum GLuint id
Definition: glext.h:6233
struct nk_color group_border_color
Definition: nuklear.h:3750
Definition: nuklear.h:3390
struct nk_color cursor_border_color
Definition: nuklear.h:3532
#define NK_TEXTEDIT_UNDOSTATECOUNT
Definition: nuklear.h:2806
Definition: nuklear.h:2986
Definition: nuklear.h:2952
nk_handle callback_data
Definition: nuklear.h:3108
nk_size calls
Definition: nuklear.h:2700
NK_API int nk_combo_begin_image(struct nk_context *, struct nk_image img, struct nk_vec2 size)
struct nk_color text_active
Definition: nuklear.h:3401
Definition: nuklear.h:455
NK_API void nk_layout_row_template_push_static(struct nk_context *, float width)
struct nk_vec2 size offset
Definition: nuklear.h:462
Definition: nuklear.h:3856
Definition: nuklear.h:686
unsigned short w
Definition: nuklear.h:3015
#define NK_MIN(a, b)
Definition: nuklear.h:315
NK_API int nk_combo_begin_symbol(struct nk_context *, enum nk_symbol_type, struct nk_vec2 size)
uint32_t adler32(uint32_t adler, const uint8_t *buf, size_t len)
Definition: adler32.c:49
struct nk_popup_state popup
Definition: nuklear.h:3986
NK_API void nk_tree_state_pop(struct nk_context *)
static int cond(LexState *ls)
Definition: lparser.c:1177
NK_API void nk_stroke_rect(struct nk_command_buffer *, struct nk_rect, float rounding, float line_thickness, struct nk_color)
struct nk_color background
Definition: nuklear.h:3743
NK_API struct nk_color nk_rgba(int r, int g, int b, int a)
struct nk_vec2 scroll_delta
Definition: nuklear.h:3176
struct nk_color bar_filled
Definition: nuklear.h:3493
static int str_len(lua_State *L)
Definition: lstrlib.c:54
struct nk_style_item cursor_hover
Definition: nuklear.h:3556
struct nk_pool pool
Definition: nuklear.h:4164
Definition: nuklear.h:3918
int down
Definition: nuklear.h:3183
short x
Definition: nuklear.h:2974
NK_API void nk_text_wrap(struct nk_context *, const char *, int)
Definition: nuklear.h:1178
NK_API int nk_str_insert_text_char(struct nk_str *, int pos, const char *, int)
Definition: nuklear.h:3959
GLenum GLenum GLenum GLenum GLenum scale
Definition: glext.h:9939
struct nk_style_item active
Definition: nuklear.h:3662
NK_API void nk_label(struct nk_context *, const char *, nk_flags align)
NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input *, struct nk_rect)
Definition: nuklear.h:3375
struct nk_style_button tab_maximize_button
Definition: nuklear.h:3696
short cx
Definition: nuklear.h:3056
#define next(ls)
Definition: llex.c:32
NK_API void nk_text_colored(struct nk_context *, const char *, int, nk_flags, struct nk_color)
NK_API struct nk_image nk_image_ptr(void *)
Definition: nuklear.h:2964
struct nk_color color
Definition: nuklear.h:3650
unsigned short h
Definition: nuklear.h:3118
GLuint GLenum matrix
Definition: glext.h:10314
GLdouble s
Definition: glext.h:6390
short insert_length
Definition: nuklear.h:2822
static const struct @115 elements[]
NK_API void nk_style_load_cursor(struct nk_context *, enum nk_style_cursor, const struct nk_cursor *)
Definition: nuklear.h:3821
NK_API void nk_chart_end(struct nk_context *)
struct nk_style_button inc_button
Definition: nuklear.h:3569
Definition: nuklear.h:2005
f32 k1
Definition: gx_regdef.h:5098
Definition: nuklear.h:690
struct nk_vec2 image_padding
Definition: nuklear.h:3408
struct nk_vec2 padding
Definition: nuklear.h:3768
NK_API void nk_textedit_init_fixed(struct nk_text_edit *, void *memory, nk_size size)
struct passwd out
Definition: missing_libc_functions.c:51
NK_API struct nk_rect nk_window_get_content_region(struct nk_context *)
NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color)
struct nk_style_button tab_minimize_button
Definition: nuklear.h:3697
NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color)
struct nk_style_item normal
Definition: nuklear.h:3392
GLdouble GLdouble z
Definition: glext.h:6514
NK_API int nk_selectable_image_label(struct nk_context *, struct nk_image, const char *, nk_flags align, int *value)
enum nk_symbol_type inc_symbol
Definition: nuklear.h:3571
Definition: nuklear.h:2172
NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols)
short x
Definition: nuklear.h:3106
Definition: nuklear.h:2675
short undo_char_point
Definition: nuklear.h:2832
struct nk_vec2 scrollbar_size
Definition: nuklear.h:3765
GLsizei const GLchar *const * string
Definition: glext.h:6699
NK_API void nk_menubar_begin(struct nk_context *)
struct nk_page_element win[1]
Definition: nuklear.h:4119
struct nk_command header
Definition: nuklear.h:2979
short x
Definition: nuklear.h:3049
struct nk_color cursor_normal
Definition: nuklear.h:3589
Definition: nuklear.h:2168
nk_panel_flags
Definition: nuklear.h:1173
Definition: nuklear.h:2950
NK_API void nk_buffer_push(struct nk_buffer *, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align)
GLint GLint bottom
Definition: glext.h:8393
enum nk_anti_aliasing shape_AA
Definition: nuklear.h:984
NK_API struct nk_color nk_rgba_fv(const float *rgba)
struct nk_color tooltip_border_color
Definition: nuklear.h:3751
struct nk_scroll offset
Definition: nuklear.h:3886
short cy
Definition: nuklear.h:3056
Definition: nuklear.h:3858
#define NK_LEN(a)
Definition: nuklear.h:4183
struct nk_style_item hover
Definition: nuklear.h:3617
typedef void(__stdcall *PFN_DESTRUCTION_CALLBACK)(void *pData)
struct nk_command header
Definition: nuklear.h:3040
struct nk_color border_color
Definition: nuklear.h:3663
Definition: nuklear.h:475
Definition: nuklear.h:2010
Definition: nuklear.h:2162
unsigned short h
Definition: nuklear.h:3015
Definition: nuklear.h:972
NK_API struct nk_color nk_rgb(int r, int g, int b)
NK_API void nk_window_set_position(struct nk_context *, const char *name, struct nk_vec2 pos)
GLdouble GLdouble GLdouble GLdouble top
Definition: glext.h:11766
struct nk_command header
Definition: nuklear.h:3080
Definition: nuklear.h:2161
unsigned short w
Definition: nuklear.h:2975
#define exp(a)
Definition: math.h:32
Definition: nuklear.h:3853
Definition: nuklear.h:2842
NK_API struct nk_vec2 nk_rect_size(struct nk_rect)
Definition: nuklear.h:1873
#define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS
Definition: nuklear.h:3811
int length
Definition: nuklear.h:3120
NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color)
GLenum GLint GLint * precision
Definition: glext.h:8206
Definition: nuklear.h:503
Definition: nuklear.h:465
NK_API int nk_chart_begin_colored(struct nk_context *, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max)
NK_API int nk_widget_is_mouse_clicked(struct nk_context *, enum nk_buttons)
GLenum GLenum GLenum input
Definition: glext.h:9938
Definition: ibxm.h:9
struct nk_style_edit edit
Definition: nuklear.h:3794
unsigned short h
Definition: nuklear.h:461
Definition: nuklear.h:3712
nk_text_edit_mode
Definition: nuklear.h:2841
nk_byte g
Definition: nuklear.h:453
float rounding
Definition: nuklear.h:3683
float filled
Definition: nuklear.h:3870
NK_API struct nk_rect nk_widget_bounds(struct nk_context *)
GLuint GLuint GLfloat weight
Definition: glext.h:12626
NK_API void nk_layout_row_template_push_variable(struct nk_context *, float min_width)
struct nk_vec2 popup_padding
Definition: nuklear.h:3770
struct nk_style_button inc_button
Definition: nuklear.h:3510
GLdouble GLdouble right
Definition: glext.h:11766
Definition: nuklear.h:3372
NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color)
NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size)
nk_size begin
Definition: nuklear.h:3877
#define nk_zero_struct(s)
Definition: nuklear.h:4200
Definition: nuklear.h:2148
struct nk_color label_normal
Definition: nuklear.h:3729
NK_API int nk_contextual_item_image_label(struct nk_context *, struct nk_image, const char *, nk_flags alignment)
nk_edit_flags
Definition: nuklear.h:1999
#define NK_UINT8
Definition: nuklear.h:340
GLsizei GLsizei GLenum GLenum const GLvoid * data
Definition: glext.h:6303
#define NK_BUTTON_BEHAVIOR_STACK_SIZE
Definition: nuklear.h:4025
Definition: nuklear.h:474
unsigned short point_count
Definition: nuklear.h:3082
const GLubyte * c
Definition: glext.h:9812
short y
Definition: nuklear.h:2999
#define NK_API
Definition: nuklear.h:282
struct nk_vec2 menu_padding
Definition: nuklear.h:3773
GLboolean GLboolean GLboolean b
Definition: glext.h:6844
unsigned char cursor_at_end_of_line
Definition: nuklear.h:2857
NK_API void nk_combo_close(struct nk_context *)
Definition: nuklear.h:700
struct nk_style_item hover
Definition: nuklear.h:3718
NK_API const void * nk_buffer_memory_const(const struct nk_buffer *)
GLuint GLuint GLsizei count
Definition: glext.h:6292
Definition: nuklear.h:676
nk_plugin_filter filter
Definition: nuklear.h:2850
const float * ratio
Definition: nuklear.h:3866
float combo_border
Definition: nuklear.h:3755
float4 p3
Definition: remote.h:1
NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context *, struct nk_vec2)
struct nk_image image
Definition: nuklear.h:3376
NK_API void nk_textedit_delete_selection(struct nk_text_edit *)
#define NK_STYLE_ITEM_STACK_SIZE
Definition: nuklear.h:4033
NK_API int nk_propertyi(struct nk_context *, const char *name, int min, int val, int max, int step, float inc_per_pixel)
Definition: nuklear.h:471
float rounding
Definition: nuklear.h:3562
NK_API nk_size nk_prog(struct nk_context *, nk_size cur, nk_size max, int modifyable)
nk_handle handle
Definition: nuklear.h:461
GLuint GLuint num
Definition: glext.h:10525
NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols)
int count
Definition: nuklear.h:3837
float x
Definition: nuklear.h:457
NK_API void nk_buffer_init(struct nk_buffer *, const struct nk_allocator *, nk_size size)
unsigned char mode
Definition: nuklear.h:3955
Definition: nuklear.h:697
unsigned short line_thickness
Definition: nuklear.h:3024
struct nk_style_chart chart
Definition: nuklear.h:3795
struct nk_table * next
Definition: nuklear.h:4101
struct nk_style_scrollbar scrollv
Definition: nuklear.h:3797
struct nk_command header
Definition: nuklear.h:3064
Definition: nuklear.h:2948
Definition: nuklear.h:2008
Definition: nuklear.h:678
struct nk_style_item scaler
Definition: nuklear.h:3752
Definition: nuklear.h:2006
GLuint GLsizei const GLchar * label
Definition: glext.h:8583
struct nk_allocator pool
Definition: nuklear.h:2688
#define NK_WINDOW_MAX_NAME
Definition: nuklear.h:3912
Definition: nuklear.h:2155
NK_API void nk_list_view_end(struct nk_list_view *)
Definition: nuklear.h:1875
NK_API int nk_combo_item_label(struct nk_context *, const char *, nk_flags alignment)
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3641
NK_API const struct nk_command * nk__next(struct nk_context *, const struct nk_command *)
nk_hash name
Definition: nuklear.h:3974
struct nk_draw_null_texture null
Definition: nuklear.h:988
NK_API int nk_str_append_str_char(struct nk_str *, const char *)
Definition: nuklear.h:1866
NK_SIZE_TYPE nk_size
Definition: nuklear.h:401
GLint GLint GLsizei GLsizei GLsizei GLint GLenum GLenum const GLvoid * pixels
Definition: glext.h:6293
Definition: nuklear.h:1175
struct nk_vec2 padding
Definition: nuklear.h:3472
nk_handle userdata
Definition: nuklear.h:3412
Definition: nuklear.h:2174
Definition: nuklear.h:2951
unsigned char single_line
Definition: nuklear.h:2860
GLint GLvoid * img
Definition: glext.h:6388
Definition: nuklear.h:2158
unsigned int seq
Definition: nuklear.h:3948
NK_API int nk_filter_hex(const struct nk_text_edit *, nk_rune unicode)
NK_API int nk_combo_begin_image_text(struct nk_context *, const char *selected, int, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:2959
NK_API int nk_window_is_hovered(struct nk_context *)
struct nk_color color
Definition: nuklear.h:3386
struct nk_vec2 tooltip_padding
Definition: nuklear.h:3774
NK_API unsigned nk_check_flags_label(struct nk_context *, const char *, unsigned int flags, unsigned int value)
NK_API int nk_menu_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API int nk_check_text(struct nk_context *, const char *, int, int active)
Definition: nuklear.h:672
NK_API struct nk_vec2 nk_widget_position(struct nk_context *)
struct nk_style_item normal_active
Definition: nuklear.h:3454
struct nk_style_window_header header
Definition: nuklear.h:3741
Definition: nuklear.h:974
#define NK_PTR_TO_UINT(x)
Definition: nuklear.h:4211
struct nk_color text_normal_active
Definition: nuklear.h:3464
NK_API nk_rune nk_str_rune_at(const struct nk_str *, int pos)
struct nk_window win
Definition: nuklear.h:4107
NK_API int nk_style_push_font(struct nk_context *, const struct nk_user_font *)
struct nk_style_toggle option
Definition: nuklear.h:3788
float cursor_border
Definition: nuklear.h:3537
Definition: nuklear.h:2945
enum nk_symbol_type close_symbol
Definition: nuklear.h:3724
Definition: nuklear.h:1181
NK_API int nk_item_is_any_active(struct nk_context *)
struct nk_color cursor_text_normal
Definition: nuklear.h:3591
NK_API int nk_check_label(struct nk_context *, const char *, int active)
float border
Definition: nuklear.h:3405
float border
Definition: nuklear.h:3653
NK_API int nk_contextual_begin(struct nk_context *, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds)
Definition: nuklear.h:3857
struct nk_color label_hover
Definition: nuklear.h:3623
NK_API struct nk_color nk_hsva_fv(const float *hsva)
struct nk_color selected_normal
Definition: nuklear.h:3600
NK_API int nk_window_is_collapsed(struct nk_context *ctx, const char *name)
const struct nk_user_font * font
Definition: nuklear.h:3114
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)
GLenum const GLvoid GLbitfield GLsizei numGlyphs
Definition: glext.h:12622
NK_API int nk_style_pop_style_item(struct nk_context *)
NK_API void nk_str_remove_chars(struct nk_str *, int len)
GLint i1
Definition: nx_glsym.h:308
300 fps cap). If set to 0.0x, fastforward ratio is unlimited(no FPS cap)." ) MSG_HASH( MENU_ENUM_SUBLABEL_SLOWMOTION_RATIO, "When in slow motion, content will slow down by the factor specified/set." ) MSG_HASH( MENU_ENUM_SUBLABEL_RUN_AHEAD_ENABLED, "Run core logic one or more frames ahead then load the state back to reduce perceived input lag." ) MSG_HASH( MENU_ENUM_SUBLABEL_RUN_AHEAD_FRAMES, "The number of frames to run ahead. Causes gameplay issues such as jitter if you exceed the number of lag frames internal to the game." ) MSG_HASH( MENU_ENUM_SUBLABEL_RUN_AHEAD_SECONDARY_INSTANCE, "Use a second instance of the RetroArch core to run ahead. Prevents audio problems due to loading state." ) MSG_HASH( MENU_ENUM_SUBLABEL_RUN_AHEAD_HIDE_WARNINGS, "Hides the warning message that appears when using RunAhead and the core does not support savestates." ) MSG_HASH( MENU_ENUM_SUBLABEL_REWIND_ENABLE, "Ενεργοποίηση επιστροφής. Η επίδοση θα πέσει κατά το παιχνίδι." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_APPLY_AFTER_TOGGLE, "Apply cheat immediately after toggling." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_APPLY_AFTER_LOAD, "Auto-apply cheats when game loads." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_REPEAT_COUNT, "The number of times the cheat will be applied. Use with the other two Iteration options to affect large areas of memory." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_REPEAT_ADD_TO_ADDRESS, "After each 'Number of Iterations' the Memory Address will be increased by this number times the 'Memory Search Size'." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_REPEAT_ADD_TO_VALUE, "After each 'Number of Iterations' the Value will be increased by this amount." ) MSG_HASH( MENU_ENUM_SUBLABEL_REWIND_GRANULARITY, "When rewinding a defined number of frames, you can rewind several frames at a time, increasing the rewind speed." ) MSG_HASH( MENU_ENUM_SUBLABEL_REWIND_BUFFER_SIZE, "The amount of memory(in MB) to reserve for the rewind buffer. Increasing this will increase the amount of rewind history." ) MSG_HASH( MENU_ENUM_SUBLABEL_REWIND_BUFFER_SIZE_STEP, "Each time you increase or decrease the rewind buffer size value via this UI it will change by this amount" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_IDX, "Index position in list." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_ADDRESS_BIT_POSITION, "Address bitmask when Memory Search Size< 8-bit." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_MATCH_IDX, "Select the match to view." ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_START_OR_CONT, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_START_OR_RESTART, "Αριστερά/Δεξιά για αλλαγή μεγέθους bit" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_SEARCH_EXACT, "Αριστερά/Δεξιά για αλλαγή τιμής" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_SEARCH_LT, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_SEARCH_GT, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_SEARCH_LTE, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_SEARCH_GTE, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_SEARCH_EQ, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_SEARCH_NEQ, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_SEARCH_EQPLUS, "Αριστερά/Δεξιά για αλλαγή τιμής" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_SEARCH_EQMINUS, "Αριστερά/Δεξιά για αλλαγή τιμής" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_ADD_MATCHES, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_VIEW_MATCHES, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_CREATE_OPTION, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_DELETE_OPTION, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_ADD_NEW_TOP, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_ADD_NEW_BOTTOM, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_DELETE_ALL, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_RELOAD_CHEATS, "" ) MSG_HASH( MENU_ENUM_SUBLABEL_CHEAT_BIG_ENDIAN, "Big endian :258=0x0102,\n" "Little endian :258=0x0201" ) MSG_HASH( MENU_ENUM_SUBLABEL_LIBRETRO_LOG_LEVEL, "Sets log level for cores. If a log level issued by a core is below this value, it is ignored." ) MSG_HASH( MENU_ENUM_SUBLABEL_PERFCNT_ENABLE, "Enable performance counters for RetroArch(and cores)." ) MSG_HASH( MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_SAVE, "Automatically makes a savestate at the end of RetroArch 's runtime. RetroArch will automatically load this savestate if 'Auto Load State' is enabled." ) MSG_HASH( MENU_ENUM_SUBLABEL_SAVESTATE_AUTO_LOAD, "Automatically load the auto save state on startup." ) MSG_HASH( MENU_ENUM_SUBLABEL_SAVESTATE_THUMBNAIL_ENABLE, "Show thumbnails of save states inside the menu." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUTOSAVE_INTERVAL, "Autosaves the non-volatile Save RAM at a regular interval. This is disabled by default unless set otherwise. The interval is measured in seconds. A value of 0 disables autosave." ) MSG_HASH( MENU_ENUM_SUBLABEL_INPUT_REMAP_BINDS_ENABLE, "If enabled, overrides the input binds with the remapped binds set for the current core." ) MSG_HASH( MENU_ENUM_SUBLABEL_INPUT_AUTODETECT_ENABLE, "Enable input auto-detection. Will attempt to autoconfigure joypads, Plug-and-Play style." ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_INPUT_SWAP_OK_CANCEL, "Εναλλαγή πλήτρκων για Επιβεβαίωση/Ακύρωση. Απενεργοποιημένο είναι ο Ιαπωνικός προσανατολισμός, ενεργοποιημένος είναι ο δυτικός προσανατολισμός." ) MSG_HASH( MENU_ENUM_SUBLABEL_PAUSE_LIBRETRO, "Εάν απενεργοποιηθεί το περιεχόμενο θα συνεχίσει να τρέχει στο παρασκήνιο όταν το μενού του RetroArch είναι ανοικτό." ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_DRIVER, "Οδηγός βίντεο προς χρήση." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_DRIVER, "Οδηγός ήχου προς χρήση." ) MSG_HASH( MENU_ENUM_SUBLABEL_INPUT_DRIVER, "Οδηγός Εισόδου προς χρήση. Ανάλογα με τον οδηγό βίντεο, ίσως αλλάξει αναγκαστικά ο οδηγός εισαγωγής." ) MSG_HASH( MENU_ENUM_SUBLABEL_JOYPAD_DRIVER, "Οδηγός Joypad προς χρήση." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_DRIVER, "Οδηγός Επαναδειγματολήπτη Ήχου προς χρήση." ) MSG_HASH( MENU_ENUM_SUBLABEL_CAMERA_DRIVER, "Οδηγός Κάμερας προς χρήση." ) MSG_HASH( MENU_ENUM_SUBLABEL_LOCATION_DRIVER, "Οδηγός Τοποθεσίας προς χρήση." ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_DRIVER, "Οδηγός Μενού προς χρήση." ) MSG_HASH( MENU_ENUM_SUBLABEL_RECORD_DRIVER, "Οδηγός Εγγραφής προς χρήση." ) MSG_HASH( MENU_ENUM_SUBLABEL_MIDI_DRIVER, "Οδηγός MIDI προς χρήση." ) MSG_HASH( MENU_ENUM_SUBLABEL_WIFI_DRIVER, "Οδηγός Wi-Fi προς χρήση." ) MSG_HASH( MENU_ENUM_SUBLABEL_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE, "Filter files being shown in filebrowser by supported extensions." ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_WALLPAPER, "Select an image to set as menu wallpaper." ) MSG_HASH( MENU_ENUM_SUBLABEL_DYNAMIC_WALLPAPER, "Dynamically load a new wallpaper depending on context." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_DEVICE, "Παράκαμψη της προκαθορισμένης συσκευής ήχου που χρησιμοποιεί ο οδηγός ήχου. Αυτή η επιλογή εξαρτάται από τον οδηγό." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_DSP_PLUGIN, "Πρόσθετο ήχου DSP που επεξεργάζεται τον ήχο πριν αποσταλεί στον οδηγό." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUDIO_OUTPUT_RATE, "Audio output sample rate." ) MSG_HASH( MENU_ENUM_SUBLABEL_OVERLAY_OPACITY, "Διαφάνεια όλων των στοιχείων του επικαλλύματος." ) MSG_HASH( MENU_ENUM_SUBLABEL_OVERLAY_SCALE, "Κλίμακα όλων των στοιχείων του επικαλλύματος." ) MSG_HASH( MENU_ENUM_SUBLABEL_INPUT_OVERLAY_ENABLE, "Ενεργοποίηση του επικαλλύματος." ) MSG_HASH( MENU_ENUM_SUBLABEL_OVERLAY_PRESET, "Επιλογή ενός επικαλλύματος από τον περιηγητή αρχείων." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_IP_ADDRESS, "The address of the host to connect to." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_TCP_UDP_PORT, "The port of the host IP address. Can be either a TCP or UDP port." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_PASSWORD, "The password for connecting to the netplay host. Used only in host mode." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_PUBLIC_ANNOUNCE, "Whether to announce netplay games publicly. If unset, clients must manually connect rather than using the public lobby." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_SPECTATE_PASSWORD, "The password for connecting to the netplay host with only spectator privileges. Used only in host mode." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_START_AS_SPECTATOR, "Whether to start netplay in spectator mode." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_ALLOW_SLAVES, "Whether to allow connections in slave mode. Slave-mode clients require very little processing power on either side, but will suffer significantly from network latency." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_REQUIRE_SLAVES, "Whether to disallow connections not in slave mode. Not recommended except for very fast networks with very weak machines." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_STATELESS_MODE, "Whether to run netplay in a mode not requiring save states. If set to true, a very fast network is required, but no rewinding is performed, so there will be no netplay jitter." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_CHECK_FRAMES, "The frequency in frames with which netplay will verify that the host and client are in sync." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_NAT_TRAVERSAL, "When hosting, attempt to listen for connections from the public Internet, using UPnP or similar technologies to escape LANs." ) MSG_HASH( MENU_ENUM_SUBLABEL_STDIN_CMD_ENABLE, "Enable stdin command interface." ) MSG_HASH( MENU_ENUM_SUBLABEL_MOUSE_ENABLE, "Enable mouse controls inside the menu." ) MSG_HASH( MENU_ENUM_SUBLABEL_POINTER_ENABLE, "Enable touch controls inside the menu." ) MSG_HASH( MENU_ENUM_SUBLABEL_THUMBNAILS, "Type of thumbnail to display." ) MSG_HASH( MENU_ENUM_SUBLABEL_LEFT_THUMBNAILS, "Type of thumbnail to display at the left." ) MSG_HASH( MENU_ENUM_SUBLABEL_XMB_VERTICAL_THUMBNAILS, "Display the left thumbnail under the right one, on the right side of the screen." ) MSG_HASH( MENU_ENUM_SUBLABEL_TIMEDATE_ENABLE, "Εμφάνιση τρέχουσας ημερομηνίας ή και ώρας μέσα στο μενού." ) MSG_HASH( MENU_ENUM_SUBLABEL_BATTERY_LEVEL_ENABLE, "Εμφάνιση τρέχουσας μπαταρίας μέσα στο μενού." ) MSG_HASH( MENU_ENUM_SUBLABEL_NAVIGATION_WRAPAROUND, "Wrap-around to beginning and/or end if boundary of list is reached horizontally or vertically." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_ENABLE_HOST, "Ενεργοποιεί το netplay ως οικοδεσπότης(εξυπηρετητής)." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_ENABLE_CLIENT, "Ενεργοποιεί το netplay ως πελάτης." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_DISCONNECT, "Αποσυνδέει μία ενεργή σύνδεση Netplay." ) MSG_HASH( MENU_ENUM_SUBLABEL_SCAN_DIRECTORY, "Σαρώνει ένα ευρετήριο για συμβατά αρχεία και τα προσθέτει στην συλλογή." ) MSG_HASH( MENU_ENUM_SUBLABEL_SCAN_FILE, "Σαρώνει ένα συμβατό αρχείο και το προσθέτει στην συλλογή." ) MSG_HASH( MENU_ENUM_SUBLABEL_VIDEO_SWAP_INTERVAL, "Χρησιμοποιεί ένα προτιμώμενο διάστημα αλλαγής για το Vsync. Ορίστε αυτό ώστε να μειώσεται στο μισό τον ρυθμό ανανέωσης της οθόνης αποτελεσματικά." ) MSG_HASH( MENU_ENUM_SUBLABEL_SORT_SAVEFILES_ENABLE, "Sort save files in folders named after the core used." ) MSG_HASH( MENU_ENUM_SUBLABEL_SORT_SAVESTATES_ENABLE, "Sort save states in folders named after the core used." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_REQUEST_DEVICE_I, "Request to play with the given input device." ) MSG_HASH( MENU_ENUM_SUBLABEL_CORE_UPDATER_BUILDBOT_URL, "URL to core updater directory on the Libretro buildbot." ) MSG_HASH( MENU_ENUM_SUBLABEL_BUILDBOT_ASSETS_URL, "URL to assets updater directory on the Libretro buildbot." ) MSG_HASH( MENU_ENUM_SUBLABEL_CORE_UPDATER_AUTO_EXTRACT_ARCHIVE, "After downloading, automatically extract files contained in the downloaded archives." ) MSG_HASH( MENU_ENUM_SUBLABEL_NETPLAY_REFRESH_ROOMS, "Σάρωση για νέα δωμάτια." ) MSG_HASH( MENU_ENUM_SUBLABEL_DELETE_ENTRY, "Κατάργηση αυτής της καταχώρησης από την συλλογή." ) MSG_HASH( MENU_ENUM_SUBLABEL_INFORMATION, "View more information about the content." ) MSG_HASH( MENU_ENUM_SUBLABEL_ADD_TO_FAVORITES, "Προσθήκη καταχώρησης στα αγαπημένα." ) MSG_HASH( MENU_ENUM_SUBLABEL_ADD_TO_FAVORITES_PLAYLIST, "Προσθήκη καταχώρησης στα αγαπημένα." ) MSG_HASH( MENU_ENUM_SUBLABEL_RUN, "Έναρξη περιεχομένου." ) MSG_HASH( MENU_ENUM_SUBLABEL_MENU_FILE_BROWSER_SETTINGS, "Προσαρμογή ρυθμίσεων εξερευνητή αρχείου." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUTO_REMAPS_ENABLE, "Enable customized controls by default at startup." ) MSG_HASH( MENU_ENUM_SUBLABEL_AUTO_OVERRIDES_ENABLE, "Enable customized configuration by default at startup." ) MSG_HASH( MENU_ENUM_SUBLABEL_GAME_SPECIFIC_OPTIONS, "Enable customized core options by default at startup." ) MSG_HASH( MENU_ENUM_SUBLABEL_CORE_ENABLE, "Εμφανίζει το όνομα του τρέχων πυρήνα μέσα στο μενού." ) MSG_HASH( MENU_ENUM_SUBLABEL_DATABASE_MANAGER, "Προβολή βάσεων δεδομένων." ) MSG_HASH( MENU_ENUM_SUBLABEL_CURSOR_MANAGER, "Προβολή προηγούμενων αναζητήσεων." ) MSG_HASH( MENU_ENUM_SUBLABEL_TAKE_SCREENSHOT, "Καταγράφει μία εικόνα της οθόνης." ) MSG_HASH( MENU_ENUM_SUBLABEL_CLOSE_CONTENT, "Κλείνει το τρέχον περιεχόμενο. Οποιεσδήποτε μη αποθηκευμένες αλλαγές μπορεί να χαθούν." ) MSG_HASH( MENU_ENUM_SUBLABEL_LOAD_STATE, "Φόρτωση μίας κατάστασης από την τρέχουσα θέση." ) MSG_HASH( MENU_ENUM_SUBLABEL_SAVE_STATE, "Αποθήκευση μίας κατάστασης στην τρέχουσα θέση." ) MSG_HASH( MENU_ENUM_SUBLABEL_RESUME, "Συνέχιση εκτέλεσης του τρέχοντος περιεχομένου και έξοδος από το Γρήγορο Μενού." ) MSG_HASH( MENU_ENUM_SUBLABEL_RESUME_CONTENT, "Συνέχιση εκτέλεσης του τρέχοντος περιεχομένου και έξοδος από το Γρήγορο Μενού." ) MSG_HASH( MENU_ENUM_SUBLABEL_STATE_SLOT, "Αλλάζει την τρέχουσα επιλεγμένη θέση κατάστασης." ) MSG_HASH( MENU_ENUM_SUBLABEL_UNDO_LOAD_STATE, "Εάν μία κατάσταση φορτώθηκε, το περιεχόμενο θα επιστρέψει στην κατάσταση πριν την φόρτωση." ) MSG_HASH( MENU_ENUM_SUBLABEL_UNDO_SAVE_STATE, "Εάν μία κατάσταση αντικαταστάθηκε, το περιεχόμενο θα επιστρέψει στην προηγούμενη κατάσταση αποθήκευσης." ) MSG_HASH( MENU_ENUM_SUBLABEL_ACCOUNTS_RETRO_ACHIEVEMENTS, "Υπηρεσία RetroAchievements. Για περισσότερες πληροφορίες επισκεφθείτε το http:) MSG_HASH(MENU_ENUM_SUBLABEL_ACCOUNTS_LIST, "Διαχειρίζεται τους τρέχοντες διαμορφωμένους λογαριασμούς.") MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_META_REWIND, "Διαχειρίζεται τις ρυθμίσεις επαναφοράς.") MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_META_CHEAT_DETAILS, "Manages cheat details settings.") MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_META_CHEAT_SEARCH, "Start or continue a cheat code search.") MSG_HASH(MENU_ENUM_SUBLABEL_RESTART_CONTENT, "Επανεκκινεί το περιεχόμενο από την αρχή.") MSG_HASH(MENU_ENUM_SUBLABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CORE, "Saves an override configuration file which will apply for all content loaded with this core. Will take precedence over the main configuration.") MSG_HASH(MENU_ENUM_SUBLABEL_SAVE_CURRENT_CONFIG_OVERRIDE_CONTENT_DIR, "Saves an override configuration file which will apply for all content loaded from the same directory as the current file. Will take precedence over the main configuration.") MSG_HASH(MENU_ENUM_SUBLABEL_SAVE_CURRENT_CONFIG_OVERRIDE_GAME, "Saves an override configuration file which will apply for the current content only. Will take precedence over the main configuration.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_CHEAT_OPTIONS, "Στήσιμο κωδικών απάτης.") MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_OPTIONS, "Στήσιμο σκιάσεων για την οπτική βελτίωση της εικόνας.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_INPUT_REMAPPING_OPTIONS, "Αλλαγή χειρισμών για το τρέχον εκτελούμενο περιεχόμενο.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_OPTIONS, "Αλλαγή επιλογών για το τρέχον εκτελούμενο περιεχόμενο.") MSG_HASH(MENU_ENUM_SUBLABEL_SHOW_ADVANCED_SETTINGS, "Show advanced settings for power users (hidden by default).") MSG_HASH(MENU_ENUM_SUBLABEL_THREADED_DATA_RUNLOOP_ENABLE, "Perform tasks on a separate thread.") MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_ENTRY_REMOVE, "Επιτρέψτε στον χρήστη να καταργεί τις καταχωρήσεις από την συλλογή.") MSG_HASH(MENU_ENUM_SUBLABEL_SYSTEM_DIRECTORY, "Sets the System directory. Cores can query for this directory to load BIOSes, system-specific configs, etc.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_BROWSER_DIRECTORY, "Sets start directory for the filebrowser.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_DIR, "Usually set by developers who bundle libretro/RetroArch apps to point to assets.") MSG_HASH(MENU_ENUM_SUBLABEL_DYNAMIC_WALLPAPERS_DIRECTORY, "Directory to store wallpapers dynamically loaded by the menu depending on context.") MSG_HASH(MENU_ENUM_SUBLABEL_THUMBNAILS_DIRECTORY, "Supplementary thumbnails (boxarts/misc. images, etc.) are stored here.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_CONFIG_DIRECTORY, "Sets start directory for menu configuration browser.") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_INPUT_LATENCY_FRAMES_MIN, "The number of frames of input latency for netplay to use to hide network latency. Reduces jitter and makes netplay less CPU-intensive, at the expense of noticeable input lag.") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_INPUT_LATENCY_FRAMES_RANGE, "The range of frames of input latency that may be used to hide network latency. Reduces jitter and makes netplay less CPU-intensive, at the expense of unpredictable input lag.") MSG_HASH(MENU_ENUM_SUBLABEL_DISK_CYCLE_TRAY_STATUS, "Cycle the current disk. If the disk is inserted, it will eject the disk. If the disk has not been inserted, it will be inserted. ") MSG_HASH(MENU_ENUM_SUBLABEL_DISK_INDEX, "Change the disk index.") MSG_HASH(MENU_ENUM_SUBLABEL_DISK_OPTIONS, "Disk image management.") MSG_HASH(MENU_ENUM_SUBLABEL_DISK_IMAGE_APPEND, "Select a disk image to insert.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENUM_THROTTLE_FRAMERATE, "Makes sure the framerate is capped while inside the menu.") MSG_HASH(MENU_ENUM_SUBLABEL_VRR_RUNLOOP_ENABLE, "No deviation from core requested timing. Use for Variable Refresh Rate screens, G-Sync, FreeSync.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_LAYOUT, "Select a different layout for the XMB interface.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_THEME, "Select a different theme for the icon. Changes will take effect after you restart the program.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_SHADOWS_ENABLE, "Enable drop shadows for all icons. This will have a minor performance hit.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_COLOR_THEME, "Select a different background color gradient theme.") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_WALLPAPER_OPACITY, "Modify the opacity of the background wallpaper.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_MENU_COLOR_THEME, "Select a different background color gradient theme.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_RIBBON_ENABLE, "Select an animated background effect. Can be GPU-intensive depending on the effect. If performance is unsatisfactory, either turn this off or revert to a simpler effect.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_FONT, "Select a different main font to be used by the menu.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_FAVORITES, "Προβολή καρτέλας αγαπημένων μέσα στο μενού.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_IMAGES, "Προβολή καρτέλας εικόνων μέσα στο μενού.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_MUSIC, "Προβολή καρτέλας μουσικής μέσα στο μενού.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_VIDEO, "Προβολή καρτέλας βίντεο μέσα στο μενού.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_NETPLAY, "Προβολή καρτέλας netplay μέσα στο μενού.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_SETTINGS, "Προβολή καρτέλας ρυθμίσεων μέσα στο μενού.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_HISTORY, "Προβολή καρτέλας πρόσφατου ιστορικού μέσα στο μενού.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_ADD, "Προβολή καρτέλας εισαγωγής περιεχομένου μέσα στο μενού.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_PLAYLISTS, "Προβολή καρτέλας λίστας αναπαραγωγής μέσα στο μενού.") MSG_HASH(MENU_ENUM_SUBLABEL_RGUI_SHOW_START_SCREEN, "Προβολή οθόνης εκκίνησης στο μενού. Τίθεται αυτόματα σε αρνητικό μετά την πρώτη εκκίνηση του προγράμματος.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_HEADER_OPACITY, "Modify the opacity of the header graphic.") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_MENU_FOOTER_OPACITY, "Modify the opacity of the footer graphic.") MSG_HASH(MENU_ENUM_SUBLABEL_DPI_OVERRIDE_ENABLE, "The menu normally scales itself dynamically. If you want to set a specific scaling size instead, enable this.") MSG_HASH(MENU_ENUM_SUBLABEL_DPI_OVERRIDE_VALUE, "Set the custom scaling size here.\n" "NOTE: You have to enable 'DPI Override' for this scaling size to take effect.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_ASSETS_DIRECTORY, "Save all downloaded files to this directory.") MSG_HASH(MENU_ENUM_SUBLABEL_INPUT_REMAPPING_DIRECTORY, "Save all remapped controls to this directory.") MSG_HASH(MENU_ENUM_SUBLABEL_LIBRETRO_DIR_PATH, "Directory where the program searches for content/cores.") MSG_HASH(MENU_ENUM_SUBLABEL_LIBRETRO_INFO_PATH, "Application/core information files are stored here.") MSG_HASH(MENU_ENUM_SUBLABEL_JOYPAD_AUTOCONFIG_DIR, "If a joypad is plugged in, that joypad will be autoconfigured if a config file corresponding to it is present inside this directory.") MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_DIRECTORY, "Save all collections to this directory.") MSG_HASH(MENU_ENUM_SUBLABEL_CACHE_DIRECTORY, "If set to a directory, content which is temporarily extracted (e.g. from archives) will be extracted to this directory.") MSG_HASH(MENU_ENUM_SUBLABEL_CURSOR_DIRECTORY, "Saved queries are stored to this directory.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_DATABASE_DIRECTORY, "Databases are stored to this directory.") MSG_HASH(MENU_ENUM_SUBLABEL_ASSETS_DIRECTORY, "This location is queried by default when menu interfaces try to look for loadable assets, etc.") MSG_HASH(MENU_ENUM_SUBLABEL_SAVEFILE_DIRECTORY, "Save all save files to this directory. If not set, will try to save inside the content file's working directory.") MSG_HASH(MENU_ENUM_SUBLABEL_SAVESTATE_DIRECTORY, "Save all save states to this directory. If not set, will try to save inside the content file's working directory.") MSG_HASH(MENU_ENUM_SUBLABEL_SCREENSHOT_DIRECTORY, "Directory to dump screenshots to.") MSG_HASH(MENU_ENUM_SUBLABEL_OVERLAY_DIRECTORY, "Ορίζει ένα ευρετήριο όπου τα επικαλλύματα αποθηκεύονται για εύκολη πρόσβαση.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEAT_DATABASE_PATH, "Τα αρχεία απάτης αποθηκεύονται εδώ.") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_FILTER_DIR, "Directory where audio DSP filter files are kept.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FILTER_DIR, "Directory where CPU-based video filter files are kept.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_DIR, "Defines a directory where GPU-based video shader files are kept for easy access.") MSG_HASH(MENU_ENUM_SUBLABEL_RECORDING_OUTPUT_DIRECTORY, "Recordings will be dumped to this directory.") MSG_HASH(MENU_ENUM_SUBLABEL_RECORDING_CONFIG_DIRECTORY, "Recording configurations will be kept here.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_FONT_PATH, "Select a different font for onscreen notifications.") MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_APPLY_CHANGES, "Changes to the shader configuration will take effect immediately. Use this if you changed the amount of shader passes, filtering, FBO scale, etc.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_NUM_PASSES, "Increase or decrease the amount of shader pipeline passes. You can bind a separate shader to each pipeline pass and configure its scale and filtering.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET, "Load a shader preset. The shader pipeline will be automatically set-up.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_AS, "Save the current shader settings as a new shader preset.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_CORE, "Save the current shader settings as the default settings for this application/core.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_PARENT, "Save the current shader settings as the default settings for all files in the current content directory.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_SAVE_GAME, "Save the current shader settings as the default settings for the content.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PARAMETERS, "Modifies the current shader directly. Changes will not be saved to the preset file.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_SHADER_PRESET_PARAMETERS, "Modifies the shader preset itself currently used in the menu.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEAT_NUM_PASSES, "Increase or decrease the amount of cheats.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEAT_APPLY_CHANGES, "Cheat changes will take effect immediately.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEAT_START_SEARCH, "Start search for a new cheat. Number of bits can be changed.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEAT_CONTINUE_SEARCH, "Continue search for a new cheat.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEAT_FILE_LOAD, "Load a cheat file and replace existing cheats.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEAT_FILE_LOAD_APPEND, "Load a cheat file and append to existing cheats.") MSG_HASH(MENU_ENUM_SUBLABEL_CHEAT_FILE_SAVE_AS, "Save current cheats as a save file.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SETTINGS, "Γρήγορα πρόσβαση σε όλες τις σχετικές ρυθμίσεις παιχνιδιού.") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_INFORMATION, "View information pertaining to the application/core.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_ASPECT_RATIO, "Floating point value for video aspect ratio (width / height), used if the Aspect Ratio is set to 'Config'.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_HEIGHT, "Προτιμώμενο ύψος οπτικής γωνίας το οποίο χρησιμοποιείται εάν η Αναλογία Οθόνης είναι ορισμένη ως 'Προτιμώμενη'.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_WIDTH, "Προτιμώμενο πλάτος οπτικής γωνίας το οποίο χρησιμοποιείται εάν η Αναλογία Οθόνης είναι ορισμένη ως 'Προτιμώμενη'.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_X, "Προτιμώμενη απόκλειση οπτικής γωνίας για τον ορισμό της θέσης του άξωνα X της οπτικής γωνίας. Αυτό αγνοείται εάν έχεται ενεργοποιήσει την 'Ακέραια Κλίμακα'. Τότε θα κεντραριστεί αυτόματα.") MSG_HASH(MENU_ENUM_SUBLABEL_VIDEO_VIEWPORT_CUSTOM_Y, "Προτιμώμενη απόκλειση οπτικής γωνίας για τον ορισμό της θέσης του άξωνα Y της οπτικής γωνίας. Αυτό αγνοείται εάν έχεται ενεργοποιήσει την 'Ακέραια Κλίμακα'. Τότε θα κεντραριστεί αυτόματα.") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_USE_MITM_SERVER, "Χρήση Εξυπηρετητή Αναμετάδοσης") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_USE_MITM_SERVER, "Forward netplay connections through a man-in-the-middle server. Useful if the host is behind a firewall or has NAT/UPnP problems.") MSG_HASH(MENU_ENUM_LABEL_VALUE_NETPLAY_MITM_SERVER, "Τοποθεσία Εξυπηρετητή Αναμετάδοσης") MSG_HASH(MENU_ENUM_SUBLABEL_NETPLAY_MITM_SERVER, "Choose a specific relay server to use. Geographically closer locations tend to have lower latency.") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER, "Προσθήκη στον μίκτη") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_PLAY, "Προσθήκη στον μίκτη και αναπαραγωγή") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_COLLECTION, "Προσθήκη στον μίκτη") MSG_HASH(MENU_ENUM_LABEL_VALUE_ADD_TO_MIXER_AND_COLLECTION_AND_PLAY, "Προσθήκη στον μίκτη και αναπαραγωγή") MSG_HASH(MENU_ENUM_LABEL_VALUE_FILTER_BY_CURRENT_CORE, "Φιλτράρισμα με βάση τον τρέχων πυρήνα") MSG_HASH(MSG_AUDIO_MIXER_VOLUME, "Γενική ένταση μίκτη ήχου") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_MIXER_VOLUME, "Γενική ένταση μίκτη ήχου (σε dB). Το 0 είναι η φυσιολογική ένταση και δεν εφαρμόζεται gain.") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_VOLUME, "Επίπεδο Έντασης Μίκτη Ήχου (dB)") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_MUTE, "Σίγαση Μίκτη Ήχου") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_MIXER_MUTE, "Σίγαση/κατάργηση σίγασης μίκτη ήχου.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_ONLINE_UPDATER, "Προβολή Διαδικτυακού Ενημερωτή") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_ONLINE_UPDATER, "Εμφάνιση/απόκρυψη της επιλογής 'Διαδικτυακού Ενημερωτή'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_VIEWS_SETTINGS, "Προβολές") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_VIEWS_SETTINGS, "Προβολή ή απόκρυψη στοιχείων στην οθόνη του μενού.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_CORE_UPDATER, "Προβολή Ενημερωτή Πυρήνων") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_CORE_UPDATER, "Εμφάνιση/απόκρυψη της ικανότητας ενημέρωσης πυρήνων (και πληροφοριακών αρχείων πυρήνων).") MSG_HASH(MSG_PREPARING_FOR_CONTENT_SCAN, "Προετοιμασία για σάρωση περιεχομένου...") MSG_HASH(MENU_ENUM_LABEL_VALUE_CORE_DELETE, "Διαγραφή πυρήνα") MSG_HASH(MENU_ENUM_SUBLABEL_CORE_DELETE, "Κατάργηση αυτού του πυρήνα από τον δίσκο.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_FRAMEBUFFER_OPACITY, "Framebuffer Opacity") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_FRAMEBUFFER_OPACITY, "Modify the opacity of the framebuffer.") MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_FAVORITES, "Αγαπημένα") MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_FAVORITES, "Περιεχόμενο που έχετε προσθέσει στα 'Αγαπημένα' θα εμφανίζεται εδώ.") MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_MUSIC, "Μουσική") MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_MUSIC, "Μουσική που έχει προηγουμένως αναπαραχθεί θα εμφανίζονται εδώ.") MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_IMAGES, "Εικόνα") MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_IMAGES, "Εικόνες που έχουν προηγουμένως προβληθεί θα εμφανίζονται εδώ.") MSG_HASH(MENU_ENUM_LABEL_VALUE_GOTO_VIDEO, "Βίντεο") MSG_HASH(MENU_ENUM_SUBLABEL_GOTO_VIDEO, "Βίντεο που έχουν προηγουμένως αναπαραχθεί θα εμφανίζονται εδώ.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MATERIALUI_ICONS_ENABLE, "Εικονίδια Μενού") MSG_HASH(MENU_ENUM_SUBLABEL_MATERIALUI_ICONS_ENABLE, "Ενεργοποίηση/Απενεργοποίηση των εικονιδίων που εμφανίζονται στα αριστερά των καταχωρήσεων του μενού.") MSG_HASH(MENU_ENUM_LABEL_VALUE_XMB_MAIN_MENU_ENABLE_SETTINGS, "Ενεργοποίηση Καρτέλας Μενού") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_SETTINGS_PASSWORD, "Ορισμός Κωδικού Για Την Ενεργοποίηση Της Καρτέλας Ρυθμίσεων") MSG_HASH(MSG_INPUT_ENABLE_SETTINGS_PASSWORD, "Εισαγωγή Κωδικού") MSG_HASH(MSG_INPUT_ENABLE_SETTINGS_PASSWORD_OK, "Σωστός κωδικός.") MSG_HASH(MSG_INPUT_ENABLE_SETTINGS_PASSWORD_NOK, "Λανθασμένος κωδικός.") MSG_HASH(MENU_ENUM_SUBLABEL_XMB_MAIN_MENU_ENABLE_SETTINGS, "Ενεργοποιεί την καρτέλα Ρυθμίσεις. Χρειάζεται επανεκκίνηση για να εμφανιστεί η καρτέλα.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_SETTINGS_PASSWORD, "Supplying a password when hiding the settings tab makes it possible to later restore it from the menu, by going to the Main Menu tab, selecting Enable Settings Tab and entering the password.") MSG_HASH(MENU_ENUM_SUBLABEL_PLAYLIST_ENTRY_RENAME, "Επιτρέψτε στον χρήστη να μετονομάζει τις καταχωρήσεις στην συλλογή.") MSG_HASH(MENU_ENUM_LABEL_VALUE_PLAYLIST_ENTRY_RENAME, "Επίτρεψη μετονομασίας καταχωρήσεων") MSG_HASH(MENU_ENUM_SUBLABEL_RENAME_ENTRY, "Μετονομασία του τίτλου αυτής της καταχώρησης.") MSG_HASH(MENU_ENUM_LABEL_VALUE_RENAME_ENTRY, "Μετονομασία") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CORE, "Προβολή Φόρτωσης Πυρήνα") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_LOAD_CORE, "Εμφάνιση/απόκρυψη της επιλογής 'Φόρτωση Πυρήνα'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_LOAD_CONTENT, "Προβολή Φόρτωσης Περιεχομένου") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_LOAD_CONTENT, "Εμφάνιση/απόκρυψη της επιλογής 'Φόρτωση Περιεχομένου'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_INFORMATION, "Προβολή Πληροφοριών") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_INFORMATION, "Εμφάνιση/απόκρυψη της επιλογής 'Πληροφορίες'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_CONFIGURATIONS, "Προβολή Διαμορφώσεων") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_CONFIGURATIONS, "Εμφάνιση/απόκρυψη της επιλογής 'Διαμορφώσεις'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_HELP, "Προβολή Βοήθειας") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_HELP, "Εμφάνιση/απόκρυψη της επιλογής 'Βοήθεια'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_QUIT_RETROARCH, "Προβολή Εξόδου RetroArch") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_QUIT_RETROARCH, "Εμφάνιση/απόκρυψη της επιλογής 'Έξοδος από RetroArch'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_REBOOT, "Προβολή Επανεκκίνησης") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_REBOOT, "Εμφάνιση/απόκρυψη της επιλογής 'Επανεκκίνηση'.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_SHOW_SHUTDOWN, "Show Shutdown") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_SHOW_SHUTDOWN, "Show/hide the 'Shutdown' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_VIEWS_SETTINGS, "Γρήγορο Μενού") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_VIEWS_SETTINGS, "Show or hide elements on the Quick Menu screen.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_TAKE_SCREENSHOT, "Show Take Screenshot") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_TAKE_SCREENSHOT, "Show/hide the 'Take Screenshot' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_LOAD_STATE, "Show Save/Load State") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_LOAD_STATE, "Show/hide the options for saving/loading state.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_UNDO_SAVE_LOAD_STATE, "Show Undo Save/Load State") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_UNDO_SAVE_LOAD_STATE, "Show/hide the options for undoing save/load state.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_ADD_TO_FAVORITES, "Show Add to Favorites") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_ADD_TO_FAVORITES, "Show/hide the 'Add to Favorites' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_START_RECORDING, "Show Start Recording") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_START_RECORDING, "Show/hide the 'Start Recording' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_START_STREAMING, "Show Start Streaming") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_START_STREAMING, "Show/hide the 'Start Streaming' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_RESET_CORE_ASSOCIATION, "Show Reset Core Association") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_RESET_CORE_ASSOCIATION, "Show/hide the 'Reset Core Association' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_OPTIONS, "Show Options") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_OPTIONS, "Show/hide the 'Options' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_CONTROLS, "Show Controls") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_CONTROLS, "Show/hide the 'Controls' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_CHEATS, "Show Cheats") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_CHEATS, "Show/hide the 'Cheats' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SHADERS, "Show Shaders") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SHADERS, "Show/hide the 'Shaders' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES, "Show Save Core Overrides") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_CORE_OVERRIDES, "Show/hide the 'Save Core Overrides' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES, "Show Save Game Overrides") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_SAVE_GAME_OVERRIDES, "Show/hide the 'Save Game Overrides' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_SHOW_INFORMATION, "Show Information") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_SHOW_INFORMATION, "Show/hide the 'Information' option.") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_ENABLE, "Notification Background Enable") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_RED, "Notification Background Red Color") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_GREEN, "Notification Background Green Color") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_BLUE, "Notification Background Blue Color") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_BGCOLOR_OPACITY, "Notification Background Opacity") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_DISABLE_KIOSK_MODE, "Disable Kiosk Mode") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_DISABLE_KIOSK_MODE, "Disables kiosk mode. A restart is required for the change to take full effect.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_ENABLE_KIOSK_MODE, "Ενεργοποίηση Λειτουργίας Κιόσκι") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_ENABLE_KIOSK_MODE, "Protects the setup by hiding all configuration related settings.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_KIOSK_MODE_PASSWORD, "Set Password For Disabling Kiosk Mode") MSG_HASH(MENU_ENUM_SUBLABEL_MENU_KIOSK_MODE_PASSWORD, "Supplying a password when enabling kiosk mode makes it possible to later disable it from the menu, by going to the Main Menu, selecting Disable Kiosk Mode and entering the password.") MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD, "Εισαγωγή Κωδικού") MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD_OK, "Σωστός κωδικός.") MSG_HASH(MSG_INPUT_KIOSK_MODE_PASSWORD_NOK, "Λανθασμένος κωδικός.") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_COLOR_RED, "Notification Red Color") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_COLOR_GREEN, "Notification Green Color") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_MESSAGE_COLOR_BLUE, "Notification Blue Color") MSG_HASH(MENU_ENUM_LABEL_VALUE_FRAMECOUNT_SHOW, "Display Frame Count") MSG_HASH(MSG_CONFIG_OVERRIDE_LOADED, "Configuration override loaded.") MSG_HASH(MSG_GAME_REMAP_FILE_LOADED, "Game remap file loaded.") MSG_HASH(MSG_CORE_REMAP_FILE_LOADED, "Core remap file loaded.") MSG_HASH(MSG_RUNAHEAD_CORE_DOES_NOT_SUPPORT_SAVESTATES, "RunAhead has been disabled because this core does not support save states.") MSG_HASH(MSG_RUNAHEAD_FAILED_TO_SAVE_STATE, "Failed to save state. RunAhead has been disabled.") MSG_HASH(MSG_RUNAHEAD_FAILED_TO_LOAD_STATE, "Failed to load state. RunAhead has been disabled.") MSG_HASH(MSG_RUNAHEAD_FAILED_TO_CREATE_SECONDARY_INSTANCE, "Failed to create second instance. RunAhead will now use only one instance.") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, "Automatically add content to playlist") MSG_HASH(MENU_ENUM_SUBLABEL_AUTOMATICALLY_ADD_CONTENT_TO_PLAYLIST, "Automatically scans loaded content so they appear inside playlists.") MSG_HASH(MSG_SCANNING_OF_FILE_FINISHED, "Scanning of file finished") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_OPACITY, "Διαφάνεια Παραθύρου") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_RESAMPLER_QUALITY, "Ποιότητα Επαναδειγματολήπτη Ήχου") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_RESAMPLER_QUALITY, "Ελαττώστε αυτή την τιμή για καλύτερη επίδοση/χαμηλότερη καθυστέρηση αντί ποιότητας ήχου, αυξήστε εάν θέλετε καλύτερη ποιότητα με κόστος στην επίδοση/χαμηλότερη καθυστέρηση.") MSG_HASH(MENU_ENUM_LABEL_VALUE_SHADER_WATCH_FOR_CHANGES, "Watch shader files for changes") MSG_HASH(MENU_ENUM_SUBLABEL_SHADER_WATCH_FOR_CHANGES, "Auto-apply changes made to shader files on disk.") MSG_HASH(MENU_ENUM_LABEL_VALUE_VIDEO_WINDOW_SHOW_DECORATIONS, "Εμφάνιση Διακοσμητικών Παραθύρου") MSG_HASH(MENU_ENUM_LABEL_VALUE_STATISTICS_SHOW, "Εμφάνιση Στατιστικών") MSG_HASH(MENU_ENUM_SUBLABEL_STATISTICS_SHOW, "Εμφάνιση τεχνικών στατιστικών στην οθόνη.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_ENABLE, "Enable border filler") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BORDER_FILLER_THICKNESS_ENABLE, "Enable border filler thickness") MSG_HASH(MENU_ENUM_LABEL_VALUE_MENU_RGUI_BACKGROUND_FILLER_THICKNESS_ENABLE, "Enable background filler thickness") MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION, "Για οθόνες CRT μόνο. Προσπαθεί να χρησιμοποιήσει την ακριβή ανάλυση πυρήνα/παιχνιδιού και ρυθμού ανανέωσης.") MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION, "CRT SwitchRes") MSG_HASH(MENU_ENUM_SUBLABEL_CRT_SWITCH_RESOLUTION_SUPER, "Switch among native and ultrawide super resolutions.") MSG_HASH(MENU_ENUM_LABEL_VALUE_CRT_SWITCH_RESOLUTION_SUPER, "Σούπερ Ανάλυση CRT") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_REWIND, "Προβολή Ρυθμίσεων Επιστροφής") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_REWIND, "Εμφάνιση/απόκρυψη επιλογών Επιστροφής.") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_LATENCY, "Εμφάνιση/απόκρυψη επιλογών Καθυστέρησης.") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_LATENCY, "Προβολή Ρυθμίσεων Καθυστέρησης") MSG_HASH(MENU_ENUM_SUBLABEL_CONTENT_SHOW_OVERLAYS, "Εμφάνιση/απόκρυψη επιλογών Επικαλλυμάτων.") MSG_HASH(MENU_ENUM_LABEL_VALUE_CONTENT_SHOW_OVERLAYS, "Προβολή Ρυθμίσεων Επικαλλυμάτων") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE_MENU, "Ενεργοποίηση ήχου μενού") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_ENABLE_MENU, "Ενεργοποίηση ή απενεργοποίηση ήχου μενού.") MSG_HASH(MENU_ENUM_LABEL_VALUE_AUDIO_MIXER_SETTINGS, "Ρυθμίσεις Μίκτη") MSG_HASH(MENU_ENUM_SUBLABEL_AUDIO_MIXER_SETTINGS, "Εμφάνιση και/ή επεξεργασία ρυθμίσεων μίκτη.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_INFO, "Πληροφορίες") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_FILE, "&File") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_FILE_LOAD_CORE, "&Load Core...") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_FILE_UNLOAD_CORE, "&Unload Core") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_FILE_EXIT, "E&xit") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_EDIT, "&Edit") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_EDIT_SEARCH, "&Search") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW, "&View") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_CLOSED_DOCKS, "Closed Docks") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_SHADER_PARAMS, "Shader Parameters") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS, "&Options...") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_DOCK_POSITIONS, "Remember dock positions:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_GEOMETRY, "Remember window geometry:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SAVE_LAST_TAB, "Remember last content browser tab:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME, "Θέμα:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_SYSTEM_DEFAULT, "<System Default>") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_DARK, "Σκούρο") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_THEME_CUSTOM, "Custom...") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_TITLE, "Επιλογές") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_TOOLS, "&Tools") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP, "&Help") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_ABOUT, "Σχετικά με το RetroArch") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_HELP_DOCUMENTATION, "Εγχειρίδιο") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_LOAD_CUSTOM_CORE, "Load Custom Core...") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_LOAD_CORE, "Φόρτωση Πυρήνα΄") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_LOADING_CORE, "Φόρτωση Πυρήνα...") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_NAME, "Όνομα") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CORE_VERSION, "Έκδοση") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_TAB_PLAYLISTS, "Λίστες Αναπαραγωγής") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_TAB_FILE_BROWSER, "File Browser") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_TAB_FILE_BROWSER_TOP, "Top") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_TAB_FILE_BROWSER_UP, "Up") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_DOCK_CONTENT_BROWSER, "Content Browser") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_BOXART, "Boxart") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_SCREENSHOT, "Screenshot") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_THUMBNAIL_TITLE_SCREEN, "Title Screen") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ALL_PLAYLISTS, "All Playlists") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CORE, "Core") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CORE_INFO, "Core Info") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CORE_SELECTION_ASK, "<Ask me>") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_INFORMATION, "Information") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_WARNING, "Warning") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ERROR, "Error") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_NETWORK_ERROR, "Network Error") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_RESTART_TO_TAKE_EFFECT, "Please restart the program for the changes to take effect.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_LOG, "Log") MSG_HASH(MENU_ENUM_LABEL_VALUE_SHOW_WIMP, "Εμφάνιση Μενού Επιφάνεις Εργασίας") MSG_HASH(MENU_ENUM_SUBLABEL_SHOW_WIMP, "Opens the desktop menu if closed.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DONT_SHOW_AGAIN, "Don't show this again") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_STOP, "Στοπ") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ASSOCIATE_CORE, "Associate Core") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_HIDDEN_PLAYLISTS, "Hidden Playlists") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_HIDE, "Hide") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_HIGHLIGHT_COLOR, "Highlight color:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CHOOSE, "&Choose...") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_SELECT_COLOR, "Select Color") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_SELECT_THEME, "Select Theme") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CUSTOM_THEME, "Custom Theme") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_PATH_IS_BLANK, "File path is blank.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_IS_EMPTY, "File is empty.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_READ_OPEN_FAILED, "Could not open file for reading.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_WRITE_OPEN_FAILED, "Could not open file for writing.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_FILE_DOES_NOT_EXIST, "File does not exist.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SUGGEST_LOADED_CORE_FIRST, "Suggest loaded core first:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ZOOM, "Zoom") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_VIEW, "View") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_VIEW_TYPE_ICONS, "Icons") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_VIEW_TYPE_LIST, "List") MSG_HASH(MENU_ENUM_LABEL_VALUE_QUICK_MENU_OVERRIDE_OPTIONS, "Overrides") MSG_HASH(MENU_ENUM_SUBLABEL_QUICK_MENU_OVERRIDE_OPTIONS, "Options for overriding the global configuration.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_PLAY, "Will start playback of the audio stream. Once finished, it will remove the current audio stream from memory.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_PLAY_LOOPED, "Will start playback of the audio stream. Once finished, it will loop and play the track again from the beginning.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_PLAY_SEQUENTIAL, "Will start playback of the audio stream. Once finished, it will jump to the next audio stream in sequential order and repeat this behavior. Useful as an album playback mode.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_STOP, "This will stop playback of the audio stream, but not remove it from memory. You can start playing it again by selecting 'Play'.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_REMOVE, "This will stop playback of the audio stream and remove it entirely from memory.") MSG_HASH(MENU_ENUM_SUBLABEL_MIXER_ACTION_VOLUME, "Adjust the volume of the audio stream.") MSG_HASH(MENU_ENUM_SUBLABEL_ADD_TO_MIXER, "Add this audio track to an available audio stream slot. If no slots are currently available, it will be ignored.") MSG_HASH(MENU_ENUM_SUBLABEL_ADD_TO_MIXER_AND_PLAY, "Add this audio track to an available audio stream slot and play it. If no slots are currently available, it will be ignored.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_PLAY, "Αναπαραγωγή") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_PLAY_LOOPED, "Αναπαραγωγή (Looped)") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_PLAY_SEQUENTIAL, "Αναπαραγωγή (Sequential)") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_STOP, "Στοπ") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_REMOVE, "Κατάργηση") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIXER_ACTION_VOLUME, "Ένταση") MSG_HASH(MENU_ENUM_LABEL_VALUE_DETECT_CORE_LIST_OK_CURRENT_CORE, "Τρέχων πυρήνας") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_SEARCH_CLEAR, "Clear") MSG_HASH(MENU_ENUM_SUBLABEL_ACHIEVEMENT_PAUSE, "Pause achievements for current session (This action will enable savestates, cheats, rewind, pause, and slow-motion).") MSG_HASH(MENU_ENUM_SUBLABEL_ACHIEVEMENT_RESUME, "Resume achievements for current session (This action will disable savestates, cheats, rewind, pause, and slow-motion and reset the current game).") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_IN_MENU, "In-Menu") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME, "In-Game") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_IN_GAME_PAUSED, "In-Game (Paused)") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PLAYING, "Playing") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_STATUS_PAUSED, "Paused") MSG_HASH(MENU_ENUM_LABEL_VALUE_DISCORD_ALLOW, "Ενεργοποίηση Discord Rich Presence") MSG_HASH(MENU_ENUM_SUBLABEL_DISCORD_ALLOW, "Ενεργοποίηση ή απενεργοποίηση υποστήριξης Discord Rich Presence.\n" "ΣΗΜΕΙΩΣΗ: Δεν θα δουλέψει με την έκδοση του περιηγητή, μόνο με την τοπικά εγκατεστημένη.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIDI_INPUT, "Είσοδος") MSG_HASH(MENU_ENUM_SUBLABEL_MIDI_INPUT, "Επιλογή συσκευής εισόδου.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIDI_OUTPUT, "Έξοδος") MSG_HASH(MENU_ENUM_SUBLABEL_MIDI_OUTPUT, "Επιλογή συσκευής εξόδου.") MSG_HASH(MENU_ENUM_LABEL_VALUE_MIDI_VOLUME, "Ένταση") MSG_HASH(MENU_ENUM_SUBLABEL_MIDI_VOLUME, "Ορισμός έντασης εξόδου (%).") MSG_HASH(MENU_ENUM_LABEL_VALUE_POWER_MANAGEMENT_SETTINGS, "Διαχείριση Ενέργειας") MSG_HASH(MENU_ENUM_SUBLABEL_POWER_MANAGEMENT_SETTINGS, "Αλλαγή ρυθμίσεων διαχείρισης ενέργειας.") MSG_HASH(MENU_ENUM_LABEL_VALUE_SUSTAINED_PERFORMANCE_MODE, "Κατάσταση Συνεχούς Επίδοσης") MSG_HASH(MENU_ENUM_LABEL_VALUE_SYSTEM_INFO_MPV_SUPPORT, "Υποστήριξη mpv") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_IDX, "Index") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_MATCH_IDX, "View Match #") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_MATCH, "Match Address: %08X Mask: %02X") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_COPY_MATCH, "Create Code Match #") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_DELETE_MATCH, "Delete Match #") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_BROWSE_MEMORY, "Browse Address: %08X") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_DESC, "Πληροφορίες") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_STATE, "Ενεργοποιημένο") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_CODE, "Κωδικός") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_HANDLER, "Handler") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_MEMORY_SEARCH_SIZE, "Memory Search Size") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_TYPE, "Τύπος") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_VALUE, "Τιμή") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_ADDRESS, "Memory Address") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_ADDRESS_BIT_POSITION, "Memory Address Mask") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_RUMBLE_TYPE, "Rumble When Memory") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_RUMBLE_VALUE, "Rumble Value") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_RUMBLE_PORT, "Rumble Port") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_RUMBLE_PRIMARY_STRENGTH, "Rumble Primary Strength") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_RUMBLE_PRIMARY_DURATION, "Rumble Primary Duration (ms)") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_RUMBLE_SECONDARY_STRENGTH, "Rumble Secondary Strength") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_RUMBLE_SECONDARY_DURATION, "Rumble Secondary Duration (ms)") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_REPEAT_COUNT, "Number of Iterations") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_REPEAT_ADD_TO_VALUE, "Value Increase Each Iteration") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_REPEAT_ADD_TO_ADDRESS, "Address Increase Each Iteration") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_ADD_NEW_AFTER, "Add New Cheat After This One") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_ADD_NEW_BEFORE, "Add New Cheat Before This One") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_COPY_AFTER, "Copy This Cheat After") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_COPY_BEFORE, "Copy This Cheat Before") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_DELETE, "Delete This Cheat") MSG_HASH(MENU_ENUM_LABEL_CHEAT_HANDLER_TYPE_EMU, "Emulator") MSG_HASH(MENU_ENUM_LABEL_CHEAT_HANDLER_TYPE_RETRO, "RetroArch") MSG_HASH(MENU_ENUM_LABEL_CHEAT_TYPE_DISABLED, "<Disabled>") MSG_HASH(MENU_ENUM_LABEL_CHEAT_TYPE_SET_TO_VALUE, "Set To Value") MSG_HASH(MENU_ENUM_LABEL_CHEAT_TYPE_INCREASE_VALUE, "Increase By Value") MSG_HASH(MENU_ENUM_LABEL_CHEAT_TYPE_DECREASE_VALUE, "Decrease By Value") MSG_HASH(MENU_ENUM_LABEL_CHEAT_TYPE_RUN_NEXT_IF_EQ, "Run next cheat if value = memory") MSG_HASH(MENU_ENUM_LABEL_CHEAT_TYPE_RUN_NEXT_IF_NEQ, "Run next cheat if value != memory") MSG_HASH(MENU_ENUM_LABEL_CHEAT_TYPE_RUN_NEXT_IF_LT, "Run next cheat if value < memory") MSG_HASH(MENU_ENUM_LABEL_CHEAT_TYPE_RUN_NEXT_IF_GT, "Run next cheat if value > memory") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_DISABLED, "<Disabled>") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_CHANGES, "Changes") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_DOES_NOT_CHANGE, "Does Not Change") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_INCREASE, "Increases") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_DECREASE, "Decreases") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_EQ_VALUE, "= Rumble Value") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_NEQ_VALUE, "!= Rumble Value") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_LT_VALUE, "< Rumble Value") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_GT_VALUE, "> Rumble Value") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_INCREASE_BY_VALUE, "Increases by Rumble Value") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_TYPE_DECREASE_BY_VALUE, "Decreases by Rumble Value") MSG_HASH(MENU_ENUM_LABEL_CHEAT_MEMORY_SIZE_1, "1-bit, max value = 0x01") MSG_HASH(MENU_ENUM_LABEL_CHEAT_MEMORY_SIZE_2, "2-bit, max value = 0x03") MSG_HASH(MENU_ENUM_LABEL_CHEAT_MEMORY_SIZE_4, "4-bit, max value = 0x0F") MSG_HASH(MENU_ENUM_LABEL_CHEAT_MEMORY_SIZE_8, "8-bit, max value = 0xFF") MSG_HASH(MENU_ENUM_LABEL_CHEAT_MEMORY_SIZE_16, "16-bit, max value = 0xFFFF") MSG_HASH(MENU_ENUM_LABEL_CHEAT_MEMORY_SIZE_32, "32-bit, max value = 0xFFFFFFFF") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_0, "1") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_1, "2") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_2, "3") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_3, "4") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_4, "5") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_5, "6") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_6, "7") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_7, "8") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_8, "9") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_9, "10") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_10, "11") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_11, "12") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_12, "13") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_13, "14") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_14, "15") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_15, "16") MSG_HASH(MENU_ENUM_LABEL_RUMBLE_PORT_16, "All") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_START_OR_CONT, "Start or Continue Cheat Search") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_START_OR_RESTART, "Start or Restart Cheat Search") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_SEARCH_EXACT, "Search Memory For Values") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_SEARCH_LT, "Search Memory For Values") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_SEARCH_GT, "Search Memory For Values") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_SEARCH_EQ, "Search Memory For Values") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_SEARCH_GTE, "Search Memory For Values") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_SEARCH_LTE, "Search Memory For Values") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_SEARCH_NEQ, "Search Memory For Values") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_SEARCH_EQPLUS, "Search Memory For Values") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_SEARCH_EQMINUS, "Search Memory For Values") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_ADD_MATCHES, "Add the %u Matches to Your List") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_VIEW_MATCHES, "View the List of %u Matches") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_CREATE_OPTION, "Create Code From This Match") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_DELETE_OPTION, "Delete This Match") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_ADD_NEW_TOP, "Add New Code to Top") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_ADD_NEW_BOTTOM, "Add New Code to Bottom") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_DELETE_ALL, "Delete All Codes") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_RELOAD_CHEATS, "Reload Game-Specific Cheats") MSG_HASH(MENU_ENUM_LABEL_CHEAT_SEARCH_EXACT_VAL, "Equal to %u (%X)") MSG_HASH(MENU_ENUM_LABEL_CHEAT_SEARCH_LT_VAL, "Less Than Before") MSG_HASH(MENU_ENUM_LABEL_CHEAT_SEARCH_GT_VAL, "Greater Than Before") MSG_HASH(MENU_ENUM_LABEL_CHEAT_SEARCH_LTE_VAL, "Less Than or Equal To Before") MSG_HASH(MENU_ENUM_LABEL_CHEAT_SEARCH_GTE_VAL, "Greater Than or Equal To Before") MSG_HASH(MENU_ENUM_LABEL_CHEAT_SEARCH_EQ_VAL, "Equal to Before") MSG_HASH(MENU_ENUM_LABEL_CHEAT_SEARCH_NEQ_VAL, "Not Equal to Before") MSG_HASH(MENU_ENUM_LABEL_CHEAT_SEARCH_EQPLUS_VAL, "Equal to Before+%u (%X)") MSG_HASH(MENU_ENUM_LABEL_CHEAT_SEARCH_EQMINUS_VAL, "Equal to Before-%u (%X)") MSG_HASH(MENU_ENUM_LABEL_CHEAT_SEARCH_SETTINGS, "Start or Continue Cheat Search") MSG_HASH(MSG_CHEAT_INIT_SUCCESS, "Successfully started cheat search") MSG_HASH(MSG_CHEAT_INIT_FAIL, "Failed to start cheat search") MSG_HASH(MSG_CHEAT_SEARCH_NOT_INITIALIZED, "Searching has not been initialized/started") MSG_HASH(MSG_CHEAT_SEARCH_FOUND_MATCHES, "New match count = %u") MSG_HASH(MENU_ENUM_LABEL_VALUE_CHEAT_BIG_ENDIAN, "Big Endian") MSG_HASH(MSG_CHEAT_SEARCH_ADDED_MATCHES_SUCCESS, "Added %u matches") MSG_HASH(MSG_CHEAT_SEARCH_ADDED_MATCHES_FAIL, "Failed to add matches") MSG_HASH(MSG_CHEAT_SEARCH_ADD_MATCH_SUCCESS, "Created code from match") MSG_HASH(MSG_CHEAT_SEARCH_ADD_MATCH_FAIL, "Failed to create code") MSG_HASH(MSG_CHEAT_SEARCH_DELETE_MATCH_SUCCESS, "Deleted match") MSG_HASH(MSG_CHEAT_SEARCH_ADDED_MATCHES_TOO_MANY, "Not enough room. The total number of cheats you can have is 100.") MSG_HASH(MSG_CHEAT_ADD_TOP_SUCCESS, "New cheat added to top of list.") MSG_HASH(MSG_CHEAT_ADD_BOTTOM_SUCCESS, "New cheat added to bottom of list.") MSG_HASH(MSG_CHEAT_DELETE_ALL_INSTRUCTIONS, "Press right five times to delete all cheats.") MSG_HASH(MSG_CHEAT_DELETE_ALL_SUCCESS, "All cheats deleted.") MSG_HASH(MSG_CHEAT_ADD_BEFORE_SUCCESS, "New cheat added before this one.") MSG_HASH(MSG_CHEAT_ADD_AFTER_SUCCESS, "New cheat added after this one.") MSG_HASH(MSG_CHEAT_COPY_BEFORE_SUCCESS, "Cheat copied before this one.") MSG_HASH(MSG_CHEAT_COPY_AFTER_SUCCESS, "Cheat copied after this one.") MSG_HASH(MSG_CHEAT_DELETE_SUCCESS, "Cheat deleted.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PROGRESS, "Progress:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_LIST_MAX_COUNT, "\"All Playlists\" max list entries:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_ALL_PLAYLISTS_GRID_MAX_COUNT, "\"All Playlists\" max grid entries:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_MENU_VIEW_OPTIONS_SHOW_HIDDEN_FILES, "Εμφάνιση κρυφών αρχείων και φακέλων:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_NEW_PLAYLIST, "Νέα Λίστα Αναπαραγωγής") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ENTER_NEW_PLAYLIST_NAME, "Please enter the new playlist name:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_DELETE_PLAYLIST, "Διαγραφή Λίστας Αναπαραγωγής") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_RENAME_PLAYLIST, "Μετονομασία Λίστας Αναπαραγωγής") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_CONFIRM_DELETE_PLAYLIST, "Are you sure you want to delete the playlist \"%1\"?") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_QUESTION, "Question") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_DELETE_FILE, "Could not delete file.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_COULD_NOT_RENAME_FILE, "Could not rename file.") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_GATHERING_LIST_OF_FILES, "Gathering list of files...") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_ADDING_FILES_TO_PLAYLIST, "Adding files to playlist...") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY, "Playlist Entry") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_NAME, "Όνομα:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_PATH, "Path:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_CORE, "Πυρήνας:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_DATABASE, "Database:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_EXTENSIONS, "Extensions:") MSG_HASH(MENU_ENUM_LABEL_VALUE_QT_PLAYLIST_ENTRY_EXTENSIONS_PLACEHOLDER, "(space-separated content
Definition: msg_hash_el.h:7404
nk_uint nk_rune
Definition: nuklear.h:406
NK_API float nk_widget_height(struct nk_context *)
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3443
struct nk_vec2 prev
Definition: nuklear.h:3174
float border
Definition: nuklear.h:3606
struct nk_style_item active
Definition: nuklear.h:3551
nk_edit_events
Definition: nuklear.h:2020
NK_UINT32 nk_uint
Definition: nuklear.h:400
struct nk_config_stack_style_item style_items
Definition: nuklear.h:4081
nk_hash name
Definition: nuklear.h:3966
NK_API int nk_str_insert_at_char(struct nk_str *, int pos, const char *, int)
struct nk_vec2 touch_padding
Definition: nuklear.h:3473
struct nk_color label_active
Definition: nuklear.h:3624
float max_x
Definition: nuklear.h:3895
short y
Definition: nuklear.h:3041
NK_API void nk_textedit_init(struct nk_text_edit *, struct nk_allocator *, nk_size size)
struct nk_style_item active
Definition: nuklear.h:3486
NK_API int nk_style_pop_color(struct nk_context *)
struct nk_color border_color
Definition: nuklear.h:3585
NK_API void nk_menubar_end(struct nk_context *)
struct nk_style_item pressed_active
Definition: nuklear.h:3456
Definition: nuklear.h:2143
int cursor
Definition: nuklear.h:3963
GLenum GLuint texture
Definition: glext.h:6935
float y
Definition: nuklear.h:3844
NK_API int nk_style_push_color(struct nk_context *, struct nk_color *, struct nk_color)
nk_plugin_paste paste
Definition: nuklear.h:2816
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3543
Definition: nuklear.h:496
struct nk_style_item normal
Definition: nuklear.h:3484
unsigned short line_thickness
Definition: nuklear.h:2988
#define NK_UNUSED(x)
Definition: nuklear.h:4181
Definition: nuklear.h:3855
GLenum type
Definition: glext.h:6233
struct nk_style_item cursor_normal
Definition: nuklear.h:3496
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 abits op endm macro pixldst3 mem_operand op endm macro pixldst30 mem_operand op endm macro pixldst abits if abits elseif abits elseif abits elseif abits elseif abits pixldst0 abits else pixldst0 abits pixldst0 abits pixldst0 abits pixldst0 abits endif elseif abits else pixldst0 abits pixldst0 abits endif elseif abits else error unsupported bpp *numpix else pixst endif endm macro pixld1_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl mov asr adds SRC_WIDTH_FIXED bpl add asl else error unsupported endif endm macro pixld2_s mem_operand if mov asr add asl add asl mov asr sub UNIT_X add asl mov asr add asl add asl mov asr add UNIT_X add asl else pixld1_s mem_operand pixld1_s mem_operand endif endm macro pixld0_s mem_operand if asr adds SRC_WIDTH_FIXED bpl add asl elseif asr adds SRC_WIDTH_FIXED bpl add asl endif endm macro pixld_s_internal mem_operand if mem_operand pixld2_s mem_operand pixdeinterleave basereg elseif mem_operand elseif mem_operand elseif mem_operand elseif mem_operand pixld0_s mem_operand else pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else pixld0_s mem_operand pixld0_s mem_operand endif elseif mem_operand else error unsupported mem_operand if bpp mem_operand endif endm macro vuzp8 reg2 vuzp d d &reg2 endm macro vzip8 reg2 vzip d d &reg2 endm macro pixdeinterleave basereg basereg basereg basereg basereg endif endm macro pixinterleave basereg basereg basereg basereg basereg endif endm macro PF boost_increment endif if endif PF tst PF addne PF subne PF cmp ORIG_W if endif if endif if endif PF subge ORIG_W PF subges if endif if endif if endif endif endm macro cache_preload_simple endif if dst_r_bpp pld [DST_R, #(PREFETCH_DISTANCE_SIMPLE *dst_r_bpp/8)] endif if mask_bpp pld if[MASK, #(PREFETCH_DISTANCE_SIMPLE *mask_bpp/8)] endif endif endm macro fetch_mask_pixblock pixld mask_basereg pixblock_size MASK endm macro ensure_destination_ptr_alignment process_pixblock_tail_head if beq irp local skip1(dst_w_bpp<=(lowbit *8)) &&((lowbit *8)<(pixblock_size *dst_w_bpp)) .if lowbit< 16 tst DST_R
Definition: pixman-arm-neon-asm.h:469
float border
Definition: nuklear.h:3536
#define nk_vec2_add(a, b)
Definition: nuklear.h:4194
NK_API int nk_group_scrolled_begin(struct nk_context *, struct nk_scroll *, const char *title, nk_flags)
NK_API void nk_style_default(struct nk_context *)
short y
Definition: nuklear.h:2974
#define fclose
Definition: file_stream_transforms.h:53
NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context *, struct nk_rect)
NK_API int nk_button_image(struct nk_context *, struct nk_image img)
NK_API void nk_stroke_polygon(struct nk_command_buffer *, float *, int point_count, float line_thickness, struct nk_color)
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3518
struct nk_color text_pressed
Definition: nuklear.h:3461
unsigned short region[4]
Definition: nuklear.h:461
bool l
Definition: connect_wiiupro.c:37
struct nk_style_edit edit
Definition: nuklear.h:3635
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)
NK_API int nk_combo_item_text(struct nk_context *, const char *, int, nk_flags alignment)
float grow_factor
Definition: nuklear.h:2694
Definition: nuklear.h:3819
struct nk_vec2 label_padding
Definition: nuklear.h:3736
Definition: nuklear.h:3521
nk_uint values[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:4100
struct nk_color border_color
Definition: nuklear.h:3692
Definition: nuklear.h:2156
Definition: nuklear.h:3022
bool plus
Definition: connect_wiiupro.c:42
struct nk_vec2 group_padding
Definition: nuklear.h:3769
NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context *)
Definition: nuklear.h:460
struct nk_vec2i begin
Definition: nuklear.h:2981
NK_API void nk_input_button(struct nk_context *, enum nk_buttons, int x, int y, int down)
Definition: nuklear.h:490
NK_API int nk_select_text(struct nk_context *, const char *, int, nk_flags align, int value)
ubyte cmd
Definition: wiiuse_internal.h:319
Definition: nuklear.h:2178
int text_len
Definition: nuklear.h:3189
struct nk_table tbl
Definition: nuklear.h:4105
Definition: nuklear.h:1843
unsigned int size
Definition: nuklear.h:4117
enum nk_symbol_type sym_normal
Definition: nuklear.h:3677
Definition: nuklear.h:4122
short y
Definition: nuklear.h:3014
NK_API float nk_layout_ratio_from_pixel(struct nk_context *, float pixel_width)
NK_UINT8 nk_byte
Definition: nuklear.h:396
unsigned arc_segment_count
Definition: nuklear.h:986
nk_size allocated
Definition: nuklear.h:2696
NK_API int nk_button_symbol_text_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type, const char *, int, nk_flags alignment)
NK_API struct nk_rect nk_layout_space_bounds(struct nk_context *)
NK_API void nk_clear(struct nk_context *)
#define NK_FLAG(x)
Definition: nuklear.h:290
const void * data
Definition: libretro.h:2285
Definition: nuklear.h:3922
Definition: nuklear.h:2164
short undo_point
Definition: nuklear.h:2830
float header_height
Definition: nuklear.h:3897
nk_allocation_type
Definition: nuklear.h:2668
struct nk_style_item hover
Definition: nuklear.h:3450
short x
Definition: nuklear.h:3007
nk_size next
Definition: nuklear.h:2966
unsigned char grabbed
Definition: nuklear.h:3178
Definition: nuklear.h:3849
Definition: nuklear.h:969
NK_API int nk_button_image_label(struct nk_context *, struct nk_image img, const char *, nk_flags text_alignment)
AVFormatContext * ctx
Definition: record_ffmpeg.c:247
struct nk_color text_background
Definition: nuklear.h:3432
struct nk_color text_hover
Definition: nuklear.h:3400
unsigned short r
Definition: nuklear.h:3057
struct nk_style_item cursor_normal
Definition: nuklear.h:3425
NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color)
struct nk_rect clip
Definition: nuklear.h:3900
struct nk_image img
Definition: nuklear.h:462
Definition: nuklear.h:2146
struct nk_window * win
Definition: nuklear.h:3935
struct nk_command header
Definition: nuklear.h:3005
#define SEEK_SET
Definition: zconf.h:438
float at_x
Definition: nuklear.h:3895
struct nk_style_property property
Definition: nuklear.h:3793
Definition: nuklear.h:3917
short x
Definition: nuklear.h:456
Definition: nuklear.h:2144
enum nk_panel_row_layout_type type
Definition: nuklear.h:3861
static unsigned max_height
Definition: gx_gfx.c:278
NK_API void nk_textedit_select_all(struct nk_text_edit *)
char buffer[NK_MAX_NUMBER_BUFFER]
Definition: nuklear.h:3961
nk_size begin
Definition: nuklear.h:3134
NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score)
NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color)
std::shared_ptr< Ope > dot()
Definition: peglib.h:1603
Definition: nuklear.h:2166
static uint32_t cmd_size
Definition: ranetplayer.c:87
enum nk_anti_aliasing line_AA
Definition: nuklear.h:983
NK_API int nk_str_insert_text_utf8(struct nk_str *, int pos, const char *, int)
NK_API int nk_button_label(struct nk_context *, const char *title)
struct nk_clipboard clip
Definition: nuklear.h:2848
#define NK_ALIGN_PTR(x, mask)
Definition: nuklear.h:4220
struct nk_style_button contextual_button
Definition: nuklear.h:3786
Definition: nuklear.h:1174
struct nk_vec2 scrollbar_size
Definition: nuklear.h:3609
NK_API float nk_strtof(const char *str, const char **endptr)
NK_API struct nk_style_item nk_style_item_color(struct nk_color)
Definition: nuklear.h:3920
GLint GLint i2
Definition: nx_glsym.h:308
Definition: nuklear.h:1846
Definition: nuklear.h:2023
struct nk_style_text text
Definition: nuklear.h:3784
struct nk_config_stack_user_font fonts
Definition: nuklear.h:4086
enum nk_symbol_type maximize_symbol
Definition: nuklear.h:3726
Definition: nuklear.h:683
NK_API void nk_color_hex_rgb(char *output, struct nk_color)
NK_API int nk_widget_is_hovered(struct nk_context *)
struct nk_style_progress progress
Definition: nuklear.h:3792
Definition: nuklear.h:668
NK_API void nk_buffer_clear(struct nk_buffer *)
NK_API char * nk_str_at_char(struct nk_str *, int pos)
Definition: nuklear.h:3371
NK_API unsigned nk_check_flags_text(struct nk_context *, const char *, int, unsigned int flags, unsigned int value)
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)
struct nk_color symbol_active
Definition: nuklear.h:3673
NK_API void nk_edit_unfocus(struct nk_context *)
int end
Definition: nuklear.h:1804
unsigned int old
Definition: nuklear.h:3968
nk_size end
Definition: nuklear.h:3134
nk_handle userdata
Definition: nuklear.h:2485
nk_uint * scroll_pointer
Definition: nuklear.h:1808
struct nk_vec2 contextual_padding
Definition: nuklear.h:3772
nk_text_align
Definition: nuklear.h:1864
enum nk_symbol_type sym_maximize
Definition: nuklear.h:3701
NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context *, nk_flags, char *buffer, int max, nk_plugin_filter)
NK_API float nk_window_get_width(const struct nk_context *)
Definition: nuklear.h:2021
int show_buttons
Definition: nuklear.h:3509
NK_API int nk_str_append_text_runes(struct nk_str *, const nk_rune *, int)
const struct nk_user_font * font
Definition: nuklear.h:3778
#define NK_INT8
Definition: nuklear.h:337
NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down)
GLsizei const GLfloat * points
Definition: glext.h:9015
NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect, int down)
NK_API struct nk_color nk_rgba_iv(const int *rgba)
NK_API void nk_style_set_font(struct nk_context *, const struct nk_user_font *)
int index
Definition: nuklear.h:3839
Definition: nuklear.h:474
Definition: nuklear.h:2843
struct nk_color popup_border_color
Definition: nuklear.h:3746
NK_API int nk_image_is_subimage(const struct nk_image *img)
struct nk_style_slider slider
Definition: nuklear.h:3791
GLdouble u1
Definition: glext.h:9211
Definition: nuklear.h:2012
#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1)
Definition: nuklear.h:4188
NK_API void nk_style_from_table(struct nk_context *, const struct nk_color *)
Definition: nuklear.h:502
struct nk_panel * layout
Definition: nuklear.h:3981
Definition: nuklear.h:2669
NK_API void nk_tree_pop(struct nk_context *)
float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]
Definition: nuklear.h:3873
struct nk_vec2 cursor_size
Definition: nuklear.h:3506
struct nk_command header
Definition: nuklear.h:3095
NK_API int nk_init_custom(struct nk_context *, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *)
int active
Definition: nuklear.h:3881
Definition: nuklear.h:681
NK_API void nk_buffer_reset(struct nk_buffer *, enum nk_buffer_allocation_type type)
struct nk_style_item normal
Definition: nuklear.h:3582
NK_API int nk_checkbox_flags_text(struct nk_context *, const char *, int, unsigned int *flags, unsigned int value)
struct nk_color text_background
Definition: nuklear.h:3467
Definition: nuklear.h:2152
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3444
Definition: nuklear.h:685
struct nk_vec2 spacing
Definition: nuklear.h:3686
int total_height
Definition: nuklear.h:1806
nk_plugin_copy copy
Definition: nuklear.h:2817
Definition: nuklear.h:2943
NK_API void nk_style_hide_cursor(struct nk_context *)
nk_modify
Definition: nuklear.h:467
NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input *, enum nk_buttons, struct nk_rect)
struct nk_vec2 content_padding
Definition: nuklear.h:3684
GLfloat v0
Definition: glext.h:6701
short h
Definition: nuklear.h:458
struct nk_style_button node_maximize_button
Definition: nuklear.h:3698
NK_INT8 nk_char
Definition: nuklear.h:394
unsigned short w
Definition: nuklear.h:3008
float rounding
Definition: nuklear.h:3535
Definition: nuklear.h:3658
enum nk_panel_type type
Definition: nuklear.h:3890
struct nk_command header
Definition: nuklear.h:2973
NK_API const char * nk_str_get_const(const struct nk_str *)
NK_API struct nk_window * nk_window_find(struct nk_context *ctx, const char *name)
float b
Definition: nuklear.h:454
Definition: nuklear.h:3063
struct nk_vec2 spacing
Definition: nuklear.h:3505
Definition: nuklear.h:3926
struct nk_str string
Definition: nuklear.h:2849
NK_API void nk_menu_close(struct nk_context *)
Definition: nuklear.h:977
struct nk_style_button node_minimize_button
Definition: nuklear.h:3699
NK_API int nk_radio_label(struct nk_context *, const char *, int *active)
struct nk_color text_active
Definition: nuklear.h:3597
#define NK_POINTER_TYPE
Definition: nuklear.h:389
struct nk_style_item normal
Definition: nuklear.h:3449
static l_noret error(LoadState *S, const char *why)
Definition: lundump.c:39
struct nk_vec2i begin
Definition: nuklear.h:2989
struct nk_color border_color
Definition: nuklear.h:3745
float4 p1
Definition: notHere.h:1
short w
Definition: nuklear.h:458
GLenum GLsizei GLenum GLenum const GLvoid * image
Definition: glext.h:6305
NK_API int nk_combo_begin_text(struct nk_context *, const char *selected, int, struct nk_vec2 size)
f32 a0
Definition: gx_regdef.h:5094
NK_API void nk_fill_circle(struct nk_command_buffer *, struct nk_rect, struct nk_color)
#define NK_SATURATE(x)
Definition: nuklear.h:4182
GLfixed y1
Definition: glsym_gl.h:1051
short y
Definition: nuklear.h:3049
Definition: nuklear.h:2837
NK_API struct nk_color nk_rgb_hex(const char *rgb)
NK_API int nk_button_color(struct nk_context *, struct nk_color)
float(* nk_text_width_f)(nk_handle, float h, const char *, int len)
Definition: nuklear.h:2466
NK_API void nk_str_clear(struct nk_str *)
union nk_page_data data
Definition: nuklear.h:4111
float r
Definition: nuklear.h:454
nk_widget_states
Definition: nuklear.h:1838
struct nk_context * ctx
Definition: nuklear.h:1807
int(* nk_plugin_filter)(const struct nk_text_edit *, nk_rune unicode)
Definition: nuklear.h:480
Definition: nuklear.h:1834
struct nk_chart_slot slots[NK_CHART_MAX_SLOT]
Definition: nuklear.h:3845
float item_offset
Definition: nuklear.h:3869
nk_size size
Definition: nuklear.h:4129
static uint64_t state[MAX_PADS]
Definition: xenon360_input.c:33
#define NK_CONFIG_STACK(type, size)
Definition: nuklear.h:4057
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)
#define NK_INTERN
Definition: nuklear.h:286
struct nk_command header
Definition: nuklear.h:3023
nk_hash name
Definition: nuklear.h:3947
GLint GLint GLint GLint GLint GLint y
Definition: glext.h:6295
NK_API void nk_window_collapse(struct nk_context *, const char *name, enum nk_collapse_states state)
Definition: nuklear.h:680
NK_API void nk_window_set_size(struct nk_context *, const char *name, struct nk_vec2)
NK_API int nk_textedit_paste(struct nk_text_edit *, char const *, int len)
struct nk_vec2 padding
Definition: nuklear.h:3633
NK_API void nk_input_begin(struct nk_context *)
int tree_depth
Definition: nuklear.h:3872
Definition: nuklear.h:2017
struct nk_window * current
Definition: nuklear.h:4168
NK_API void nk_str_delete_runes(struct nk_str *, int pos, int len)
Definition: nuklear.h:670
GLenum src
Definition: glext.h:6980
NK_API struct nk_vec2 nk_vec2iv(const int *xy)
Definition: nuklear.h:2159
unsigned combo_count
Definition: nuklear.h:3940
Definition: nuklear.h:1176
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble w1
Definition: glext.h:9211
#define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)
Definition: nuklear.h:4052
NK_API int nk_style_set_cursor(struct nk_context *, enum nk_style_cursor)
Definition: nuklear.h:2160
float rounding
Definition: nuklear.h:3632
NK_API void nk_input_char(struct nk_context *, char)
union nk_style_item_data data
Definition: nuklear.h:3382
unsigned int seq
Definition: nuklear.h:3973
struct nk_command header
Definition: nuklear.h:3072
NK_API int nk_button_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags text_alignment)
GLint GLint GLint GLint GLint x
Definition: glext.h:6295
Definition: nuklear.h:1177
Definition: nuklear.h:691
GLuint in
Definition: glext.h:10523
nk_chart_event
Definition: nuklear.h:472
#define S(x)
Definition: luac.c:394
Definition: nuklear.h:2942
GLuint64EXT * result
Definition: glext.h:12211
GLdouble GLdouble GLdouble GLdouble q
Definition: glext.h:6414
int select_end
Definition: nuklear.h:3965
NK_API int nk_input_is_key_down(const struct nk_input *, enum nk_keys)
#define NK_FONT_STACK_SIZE
Definition: nuklear.h:4029
GLenum GLenum GLvoid * row
Definition: glext.h:6316
struct nk_color border_color
Definition: nuklear.h:3552
struct nk_style_item normal
Definition: nuklear.h:3616
Definition: nuklear.h:1865
NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align)
NK_API void nk_stroke_triangle(struct nk_command_buffer *, float, float, float, float, float, float, float line_thichness, struct nk_color)
Definition: nuklear.h:2960
NK_API void nk_buffer_free(struct nk_buffer *)
NK_API int nk_style_push_style_item(struct nk_context *, struct nk_style_item *, struct nk_style_item)
Definition: deflate.c:120
NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols)
dictionary args
Definition: test_shaders.py:20
Definition: nuklear.h:969
Definition: nuklear.h:1868
struct nk_vec2 padding
Definition: nuklear.h:3565
Definition: getopt.h:45
f32 a2
Definition: gx_regdef.h:5096
float rounding
Definition: nuklear.h:3705
Definition: nuklear.h:2009
struct nk_style_selectable selectable
Definition: nuklear.h:3790
NK_API void nk_str_init(struct nk_str *, const struct nk_allocator *, nk_size size)
NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx)
#define NK_CLAMP(i, v, x)
Definition: nuklear.h:317
NK_API void nk_draw_image(struct nk_command_buffer *, struct nk_rect, const struct nk_image *, struct nk_color)
NK_API int nk_menu_begin_symbol_label(struct nk_context *, const char *, nk_flags align, enum nk_symbol_type, struct nk_vec2 size)
struct nk_window * begin
Definition: nuklear.h:4165
unsigned int size
Definition: nuklear.h:4098
nk_convert_result
Definition: nuklear.h:970
struct nk_text_edit text_edit
Definition: nuklear.h:4157
NK_API void nk_label_colored(struct nk_context *, const char *, nk_flags align, struct nk_color)
int cursor_visible
Definition: nuklear.h:3782
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)
NK_API int nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags)
struct nk_color bar_hover
Definition: nuklear.h:3491
unsigned char mode
Definition: nuklear.h:2856
NK_API void nk_contextual_close(struct nk_context *)
enum nk_style_item_type type
Definition: nuklear.h:3381
NK_API int nk_window_is_any_hovered(struct nk_context *)
NK_API void nk_color_hex_rgba(char *output, struct nk_color)
struct nk_page_element * freelist
Definition: nuklear.h:4127
float rounding
Definition: nuklear.h:3654
unsigned short point_count
Definition: nuklear.h:3090
NK_API int nk_str_insert_at_rune(struct nk_str *, int pos, const char *, int)
NK_API int nk_menu_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
Definition: nuklear.h:692
struct nk_vec2 padding
Definition: nuklear.h:3539
Definition: nuklear.h:663
NK_API struct nk_color nk_hsv_fv(const float *hsv)
enum nk_button_behavior button_behavior
Definition: nuklear.h:4140
struct nk_buffer buffer
Definition: nuklear.h:2732
struct nk_vec2 delta
Definition: nuklear.h:3175
float border
Definition: nuklear.h:3682
short redo_point
Definition: nuklear.h:2831
struct config_s config
GLfloat GLfloat p
Definition: glext.h:9809
NK_API nk_handle nk_handle_id(int)
#define NK_STORAGE
Definition: nuklear.h:287
NK_API struct nk_color nk_rgb_iv(const int *rgb)
unsigned int old
Definition: nuklear.h:3949
Definition: nuklear.h:3832
set set set set set set set macro pixldst1 abits if abits op else op endif endm macro pixldst2 abits if abits op else op endif endm macro pixldst4 abits if abits op else op endif endm macro pixldst0 idx
Definition: pixman-arm-neon-asm.h:96
NK_API int nk_contextual_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
NK_API void nk_style_load_all_cursors(struct nk_context *, struct nk_cursor *)
int active
Definition: nuklear.h:3939
Definition: nuklear.h:3104
nk_flags flags
Definition: nuklear.h:3976
NK_API void nk_property_int(struct nk_context *, const char *name, int min, int *val, int max, int step, float inc_per_pixel)
NK_API nk_handle nk_handle_ptr(void *)
Definition: nuklear.h:2679
struct nk_text_undo_state undo
Definition: nuklear.h:2864
struct nk_vec2 image_padding
Definition: nuklear.h:3474
Definition: nuklear.h:671
int state
Definition: nuklear.h:3969
#define NK_ALIGNOF(t)
Definition: nuklear.h:4243
struct nk_vec2 padding
Definition: nuklear.h:3504
struct nk_style_item cursor_active
Definition: nuklear.h:3557
NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region)
float cursor_rounding
Definition: nuklear.h:3538
NK_API int nk_option_text(struct nk_context *, const char *, int, int active)
float h
Definition: nuklear.h:457
enum nk_symbol_type sym_hover
Definition: nuklear.h:3678
NK_API float nk_slide_float(struct nk_context *, float min, float val, float max, float step)
nk_size allocated
Definition: nuklear.h:2663
NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color)
struct nk_window * end
Definition: nuklear.h:4166
struct nk_style_window window
Definition: nuklear.h:3800
NK_API float nk_propertyf(struct nk_context *, const char *name, float min, float val, float max, float step, float inc_per_pixel)
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)
Definition: nuklear.h:2002
nk_size offset
Definition: nuklear.h:2681
void(* draw_end)(struct nk_command_buffer *, nk_handle userdata)
Definition: nuklear.h:3414
Definition: nuklear.h:1183
NK_API void nk_textedit_text(struct nk_text_edit *, const char *, int total_len)
Definition: nuklear.h:2676
unsigned int seq
Definition: nuklear.h:4171
struct nk_style_item normal
Definition: nuklear.h:3549
Definition: nuklear.h:1836
enum nk_command_type type
Definition: nuklear.h:2965
Definition: nuklear.h:470
struct nk_rect item
Definition: nuklear.h:3871
NK_API int nk_tree_state_push(struct nk_context *, enum nk_tree_type, const char *title, enum nk_collapse_states *state)
unsigned short line_thickness
Definition: nuklear.h:3089
short cx
Definition: nuklear.h:3065
float tooltip_border
Definition: nuklear.h:3759
struct nk_color color
Definition: nuklear.h:3834
GLfixed GLfixed GLfixed y2
Definition: glsym_gl.h:1051
static s32 hex(char ch)
Definition: debug.c:111
int index
Definition: nuklear.h:3862
NK_API int nk_strtoi(const char *str, const char **endptr)
void(* nk_plugin_free)(nk_handle, void *old)
Definition: nuklear.h:479
GLfloat GLfloat GLfloat alpha
Definition: glext.h:6290
struct nk_style_item hover
Definition: nuklear.h:3583
NK_API struct nk_color nk_rgb_bv(const nk_byte *rgb)
Definition: nuklear.h:3125
Definition: nuklear.h:2949
NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color)
#define nk_ptr_add(t, p, i)
Definition: nuklear.h:4198
NK_INT32 nk_int
Definition: nuklear.h:399
NK_API int nk_menu_begin_text(struct nk_context *, const char *title, int title_len, nk_flags align, struct nk_vec2 size)
ssize_t offset
Definition: query.c:47
float a
Definition: nuklear.h:454
struct nk_command header
Definition: nuklear.h:3048
Definition: nuklear.h:2003
NK_API int nk_input_is_key_released(const struct nk_input *, enum nk_keys)
struct nk_vec2 padding
Definition: nuklear.h:3707
float border
Definition: nuklear.h:3754
struct nk_color foreground
Definition: nuklear.h:3116
struct nk_vec2i ctrl[2]
Definition: nuklear.h:2991
GLbyte by
Definition: glext.h:9673
GLuint index
Definition: glext.h:6671
Definition: nk_menu.h:45
#define FILE
Definition: file_stream_transforms.h:35
Definition: nuklear.h:2838
NK_API nk_flags nk_edit_string(struct nk_context *, nk_flags, char *buffer, int *len, int max, nk_plugin_filter)
struct nk_style_button close_button
Definition: nuklear.h:3722
f32 a1
Definition: gx_regdef.h:5095
Definition: nuklear.h:472
nk_uint nk_hash
Definition: nuklear.h:404
NK_API void nk_str_remove_runes(struct nk_str *str, int len)
#define NK_ABS(a)
Definition: nuklear.h:4184
struct nk_style_combo combo
Definition: nuklear.h:3799
int count
Definition: nuklear.h:1804
NK_API int nk_tree_state_image_push(struct nk_context *, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state)
NK_API int nk_checkbox_label(struct nk_context *, const char *, int *active)
NK_API int nk_menu_begin_image(struct nk_context *, const char *, struct nk_image, struct nk_vec2 size)
int begin
Definition: nuklear.h:1804
Definition: nuklear.h:2954
Definition: nuklear.h:667
int slot
Definition: nuklear.h:3843
NK_API enum nk_widget_layout_states nk_widget(struct nk_rect *, const struct nk_context *)
Definition: nuklear.h:2674
Definition: nuklear.h:3827
struct nk_mouse mouse
Definition: nuklear.h:3194
Definition: nuklear.h:2946
NK_API void nk_window_show(struct nk_context *, const char *name, enum nk_show_states)
float x
Definition: nuklear.h:455
NK_API void nk_window_close(struct nk_context *ctx, const char *name)
Definition: nuklear.h:3823
NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context *)
#define NK_COLOR_STACK_SIZE
Definition: nuklear.h:4049
#define pow(x, y)
Definition: math.h:22
NK_API int nk_combo_item_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
float delta_time_seconds
Definition: nuklear.h:4142
Definition: ibxm.h:34
nk_text_alignment
Definition: nuklear.h:1872
struct nk_style_item cursor_hover
Definition: nuklear.h:3426
NK_API void nk_tooltip_end(struct nk_context *)
Definition: nuklear.h:2024
struct nk_style_item cursor_hover
Definition: nuklear.h:3497
enum nk_symbol_type minimize_symbol
Definition: nuklear.h:3725
Definition: nuklear.h:3822
Definition: nuklear.h:2150
nk_panel_row_layout_type
Definition: nuklear.h:3848
float menu_border
Definition: nuklear.h:3757
const GLdouble * v
Definition: glext.h:6391
unsigned short w
Definition: nuklear.h:3118
NK_API nk_flags nk_chart_push(struct nk_context *, float)
NK_API struct nk_color nk_rgb_fv(const float *rgb)
Definition: nuklear.h:3580
NK_API int nk_style_push_vec2(struct nk_context *, struct nk_vec2 *, struct nk_vec2)
NK_API float nk_widget_width(struct nk_context *)
Definition: nuklear.h:3039
struct nk_style_item hover
Definition: nuklear.h:3485
Definition: nuklear.h:462
struct nk_style_item normal
Definition: nuklear.h:3419
Definition: nuklear.h:475
Definition: nuklear.h:499
short y
Definition: nuklear.h:3106
NK_API int nk_button_image_label_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img, const char *, nk_flags text_alignment)
Definition: nuklear.h:2141
NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context *, struct nk_rect)
NK_API double nk_strtod(const char *str, const char **endptr)
float min_row_height_padding
Definition: nuklear.h:3761
struct nk_color label_active
Definition: nuklear.h:3668
struct nk_color border_color
Definition: nuklear.h:3487
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)
Definition: nuklear.h:1874
nk_size parent
Definition: nuklear.h:3878
Definition: nuklear.h:2149
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout)
#define NK_MAX_NUMBER_BUFFER
Definition: nuklear.h:260
Definition: nuklear.h:3889
struct nk_style_item active
Definition: nuklear.h:3719
Definition: nuklear.h:492
Definition: nuklear.h:3182
int cursor
Definition: nuklear.h:2853
Definition: nuklear.h:2145
short x
Definition: nuklear.h:3014
NK_API int nk_chart_begin(struct nk_context *, enum nk_chart_type, int num, float min, float max)
struct nk_style_item active
Definition: nuklear.h:3584
Definition: nuklear.h:2820
short y
Definition: nuklear.h:458
struct nk_style_toggle checkbox
Definition: nuklear.h:3789
const struct nk_cursor * cursors[NK_CURSOR_COUNT]
Definition: nuklear.h:3779
void free(void *)
Definition: nuklear.h:3482
struct nk_vec2 padding
Definition: nuklear.h:3655
NK_API struct nk_image nk_image_id(int)
std::string output
Definition: Config.FromFile.cpp:44
Definition: nuklear.h:3012
struct nk_style_item normal
Definition: nuklear.h:3523
Definition: nuklear.h:2947
int active
Definition: nuklear.h:3960
struct nk_command header
Definition: nuklear.h:3113
Definition: nuklear.h:458
NK_API const char * nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len)
#define NK_INBOX(px, py, x, y, w, h)
Definition: nuklear.h:4186
NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color)
u32 col
Definition: gx_regdef.h:5093
NK_API void nk_input_end(struct nk_context *)
nk_chart_type
Definition: nuklear.h:471
short x
Definition: nuklear.h:458
struct nk_style_item cursor_normal
Definition: nuklear.h:3555
nk_flags text_alignment
Definition: nuklear.h:3402
short y
Definition: nuklear.h:3007
struct nk_style_item cursor_normal
Definition: nuklear.h:3529
Definition: nuklear.h:4116
GLboolean GLboolean g
Definition: glext.h:6844
nk_panel_set
Definition: nuklear.h:3826
#define NK_BETWEEN(x, a, b)
Definition: nuklear.h:4185
Definition: nuklear.h:2955
static int digit(int c)
Definition: lstrlib.c:1180
Definition: nuklear.h:2844
#define nk_foreach(c, ctx)
Definition: nuklear.h:1011
Definition: nuklear.h:696
GLuint color
Definition: glext.h:6883
unsigned short h
Definition: nuklear.h:2975
NK_API void nk_window_collapse_if(struct nk_context *, const char *name, enum nk_collapse_states, int cond)
GLint j
Definition: nx_glsym.h:307
void * memory
Definition: nuklear.h:2660
unsigned short line_thickness
Definition: nuklear.h:3042
struct nk_color selected_text_hover
Definition: nuklear.h:3603
nk_collapse_states
Definition: nuklear.h:469
nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]
Definition: nuklear.h:2829
vu8 tail
Definition: keyboard.c:427
nk_handle userdata
Definition: nuklear.h:3575
NK_API const char * nk_str_at_char_const(const struct nk_str *, int pos)
NK_API void nk_text_wrap_colored(struct nk_context *, const char *, int, struct nk_color)
NK_API int nk_style_push_flags(struct nk_context *, nk_flags *, nk_flags)
NK_API int nk_button_symbol_text(struct nk_context *, enum nk_symbol_type, const char *, int, nk_flags alignment)
float4 p2
Definition: local.h:1
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
Definition: glext.h:6293
struct nk_color label_active
Definition: nuklear.h:3731
Definition: input_overlay.h:98
void(* nk_query_font_glyph_f)(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint)
Definition: nuklear.h:2467
struct nk_color contextual_border_color
Definition: nuklear.h:3748
NK_API void nk_layout_reset_min_row_height(struct nk_context *)
float global_alpha
Definition: nuklear.h:982
NK_API int nk_combo_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
NK_API struct nk_rect nk_get_null_rect(void)
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
Definition: glext.h:7672
struct nk_style_item active
Definition: nuklear.h:3525
NK_API int nk_menu_item_symbol_label(struct nk_context *, enum nk_symbol_type, const char *, nk_flags alignment)
int prev
Definition: nuklear.h:3950
short delete_length
Definition: nuklear.h:2823
NK_API int nk_input_mouse_clicked(const struct nk_input *, enum nk_buttons, struct nk_rect)
struct nk_command header
Definition: nuklear.h:3055
#define NK_PI
Definition: nuklear.h:4177
struct nk_style style
Definition: nuklear.h:4136
NK_API int nk_selectable_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int *value)
nk_byte r
Definition: nuklear.h:453
float g
Definition: nuklear.h:454
void * ptr
Definition: nuklear.h:460
GLint GLint GLsizei width
Definition: glext.h:6293
struct nk_style_item hover
Definition: nuklear.h:3524
Definition: nuklear.h:2167
Definition: nuklear.h:3713
NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score)
struct nk_config_stack_float floats
Definition: nuklear.h:4082
float border
Definition: nuklear.h:3561
NK_API void nk_textedit_delete(struct nk_text_edit *, int where, int len)
struct nk_vec2 touch_padding
Definition: nuklear.h:3409
struct nk_command_buffer buffer
Definition: nuklear.h:3980
nk_command_type
Definition: nuklear.h:2941
float row_padding
Definition: nuklear.h:3611
NK_API int nk_utf_encode(nk_rune, char *, int)
struct nk_color selected_text_normal
Definition: nuklear.h:3602
struct nk_color text_hover
Definition: nuklear.h:3596
#define NK_UTF_SIZE
Definition: nuklear.h:255
Definition: nuklear.h:2000
void(* draw_begin)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3576
Definition: nuklear.h:699
NK_API int nk_select_image_text(struct nk_context *, struct nk_image, const char *, int, nk_flags align, int value)
NK_API void nk_popup_close(struct nk_context *)
def sign()
Definition: build.py:201
Definition: nuklear.h:3126
struct nk_vec2 pos
Definition: nuklear.h:3173
struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]
Definition: nuklear.h:2828
struct nk_style_item normal
Definition: nuklear.h:3717
NK_API int nk_slide_int(struct nk_context *, int min, int val, int max, int step)
Definition: nuklear.h:1867
NK_API int nk_widget_has_mouse_click_down(struct nk_context *, enum nk_buttons, int down)
nk_command_clipping
Definition: nuklear.h:3124
#define NK_UTF_INVALID
Definition: nuklear.h:4178
nk_uint y
Definition: nuklear.h:463
short char_storage
Definition: nuklear.h:2824
struct nk_command header
Definition: nuklear.h:3087
Definition: ffmpeg_fft.c:36
nk_handle userdata
Definition: nuklear.h:2815
struct nk_vec2 padding
Definition: nuklear.h:3387
struct nk_rect bounds
Definition: nuklear.h:3978
Definition: nuklear.h:466
#define X(a, b)
Definition: bba.c:185
static const char * default_font
Definition: coretext.c:335
struct nk_color text_normal
Definition: nuklear.h:3459
NK_API void nk_spacing(struct nk_context *, int cols)
Definition: nuklear.h:2173
Definition: nuklear.h:3715
NK_API int nk_selectable_text(struct nk_context *, const char *, int, nk_flags align, int *value)
NK_API struct nk_color nk_hsva(int h, int s, int v, int a)
Unknown compiler Device disconnected from port File already exists Saving to backup buffer Got connection Public address Setting disk in tray You have left the game You have joined with input devices *s *s has joined as player u A netplay connection attempt failed because the peer is not running or is running an old version of RetroArch use the same version use the same version This core does not support inter architecture netplay Incorrect password A netplay client has disconnected You do not have permission to play The input devices requested are not available Netplay peer s paused Give hardware rendered cores their own private context Avoids having to assume hardware state changes inbetween frames Adjusts menu screen appearance settings Improves performance at the cost of latency and more video stuttering Use only if you cannot obtain full speed otherwise Autodetect Capabilities Connecting to port Password Username Accounts List Endpoint Achievements Scan Content Import content Ask Block Frames نظام تشغيل الصوت Audio Enable Turbo Deadzone Audio Maximum Timing Skew Audio Output Dynamic Audio Rate Control الصوت Audio Volume WASAPI Exclusive Mode WASAPI Shared Buffer Length Load Override Files Automatically Load Shader Presets Automatically Confirm Quit Scroll Up Toggle Keyboard Basic menu controls Info Scroll Up Toggle Keyboard Don t overwrite SaveRAM on loading savestate Buildbot Assets URL Allow Camera Cheat Cheat File Load Cheat File Cheat Passes Hardcore Mode Achievement Badges Locked Test Unofficial Achievements Unlocked Verbose Mode Config ملفات التكوين Collections Content Allow to remove entries Downloads Cheats Show core name Authors Core label Permissions System manufacturer Controls Options Start a Core Automatically Buildbot Cores URL Updater CPU Cursor Custom Ratio Database Selection Start directory< Default > Directory not found Disk Cycle Tray Status Disk Index Don t care Download Core DPI Override Enable أنظمة التشغيل Check for Missing Firmware Before Loading Dynamic Backgrounds Menu entry hover color False Favorites Limit Maximum Run Speed Frontend Counters Create game options file مساعدة Changing Virtual Gamepad Overlay مساعدة Scanning For Content History List Enable Horizontal Menu معلومات Analog To Digital Type Left Analog X Left analog Left Analog Y Left analog Right Analog X Right analog Right Analog Y Right analog Gun Trigger Gun Aux A Gun Aux C Gun Select Gun D pad Down Gun D pad Right Analog Stick Deadzone Bind All Bind Timeout Hide Unbound Core Input Descriptors Device Index Mouse Index Duty Cycle Keyboard Gamepad Mapping Enable B button(down)") MSG_HASH(MENU_ENUM_LABEL_VALUE_INPUT_JOYPAD_DOWN
short y
Definition: nuklear.h:3117
NK_API int nk_menu_begin_image_text(struct nk_context *, const char *, int, nk_flags align, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:3079
Definition: nuklear.h:666
Definition: nuklear.h:1802
struct nk_style_item background
Definition: nuklear.h:3691
struct nk_style_scrollbar scrollh
Definition: nuklear.h:3796
Definition: nuklear.h:2177
nk_style_colors
Definition: nuklear.h:2139
GLboolean invert
Definition: glext.h:6381
float min_height
Definition: nuklear.h:3864
Definition: nuklear.h:1869
NK_API void nk_button_set_behavior(struct nk_context *, enum nk_button_behavior)
Definition: nuklear.h:679
int select_end
Definition: nuklear.h:2855
struct nk_vec2 last
Definition: nuklear.h:3838
struct nk_color col
Definition: nuklear.h:3099
struct nk_window * prev
Definition: nuklear.h:3995
struct nk_color text_hover
Definition: nuklear.h:3430
unsigned int seq
Definition: nuklear.h:3967
NK_API struct nk_command_buffer * nk_window_get_canvas(struct nk_context *)
Definition: nuklear.h:2957
Definition: nuklear.h:669
enum nk_symbol_type dec_symbol
Definition: nuklear.h:3513
NK_API int nk_str_append_text_utf8(struct nk_str *, const char *, int)
unsigned char single_line
Definition: nuklear.h:3956
struct nk_style_button button
Definition: nuklear.h:3785
unsigned short h
Definition: nuklear.h:3107
struct nk_buffer * base
Definition: nuklear.h:3130
GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint GLdouble GLdouble w2
Definition: glext.h:9211
NK_API nk_flags nk_edit_buffer(struct nk_context *, nk_flags, struct nk_text_edit *, nk_plugin_filter)
Definition: nuklear.h:4080
struct nk_rect header
Definition: nuklear.h:3943
int active
Definition: nuklear.h:3950
Definition: nuklear.h:3385
float height
Definition: nuklear.h:2487
NK_API void nk_free(struct nk_context *)
struct nk_command header
Definition: nuklear.h:2996
NK_API void nk_property_float(struct nk_context *, const char *name, float min, float *val, float max, float step, float inc_per_pixel)
Definition: nuklear.h:2978
unsigned char has_preferred_x
Definition: nuklear.h:2859
NK_API int nk_combo_begin_image_label(struct nk_context *, const char *selected, struct nk_image, struct nk_vec2 size)
Definition: nuklear.h:2001
Definition: nuklear.h:454
NK_API void nk_plot(struct nk_context *, enum nk_chart_type, const float *values, int count, int offset)
Definition: nuklear.h:3645
NK_API const char * nk_str_at_const(const struct nk_str *, int pos, nk_rune *unicode, int *len)
NK_API void nk_layout_space_end(struct nk_context *)
Definition: nuklear.h:3054
Definition: nuklear.h:3818
float x
Definition: nuklear.h:3844
nk_buttons
Definition: nuklear.h:695
Definition: nuklear.h:484
struct nk_color text_normal
Definition: nuklear.h:3595
unsigned short line_thickness
Definition: nuklear.h:3074
static char * skip(char **buf, const char *delimiters)
Definition: civetweb.c:2018
Definition: nuklear.h:467
NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx)
NK_API struct nk_style_item nk_style_item_image(struct nk_image img)
#define NK_VALUE_PAGE_CAPACITY
Definition: nuklear.h:4093
struct nk_color selected_color
Definition: nuklear.h:3649
NK_API int nk_combo_begin_symbol_text(struct nk_context *, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size)
float indent
Definition: nuklear.h:3706
NK_INT16 nk_short
Definition: nuklear.h:397
NK_API nk_flags nk_chart_push_slot(struct nk_context *, float, int)
NK_API int nk_button_pop_behavior(struct nk_context *)
struct nk_cursor * cursor_last
Definition: nuklear.h:3781
NK_API struct nk_vec2 nk_vec2i(int x, int y)
Definition: nuklear.h:497
float border
Definition: nuklear.h:3631
GLsizei const GLfloat * value
Definition: glext.h:6709
Definition: metal_common.m:516
NK_API void nk_edit_focus(struct nk_context *, nk_flags flags)
int cursor
Definition: nuklear.h:3951
NK_API int nk_window_is_active(struct nk_context *, const char *)
struct nk_style_item hover
Definition: nuklear.h:3550
Definition: nuklear.h:2165
NK_API struct nk_color nk_hsv_iv(const int *hsv)
struct nk_color border_color
Definition: nuklear.h:3526
#define fread
Definition: file_stream_transforms.h:56
NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba)
Definition: nuklear.h:3547
NK_API int nk_init(struct nk_context *, struct nk_allocator *, const struct nk_user_font *)
nk_byte a
Definition: nuklear.h:453
struct nk_command header
Definition: nuklear.h:3032
Definition: nuklear.h:3031
struct nk_scroll scrollbar
Definition: nuklear.h:3954
nk_size needed
Definition: nuklear.h:2698
Definition: nuklear.h:461
#define NK_GLOBAL
Definition: nuklear.h:288
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)
Definition: nuklear.h:3928
float at_y
Definition: nuklear.h:3895
NK_API void nk_label_wrap(struct nk_context *, const char *)
Definition: nuklear.h:1180
unsigned short h
Definition: nuklear.h:3008
Definition: nuklear.h:4133
struct nk_style_item cursor_active
Definition: nuklear.h:3531
const GLchar * marker
Definition: glsym_es2.h:111
Definition: netplay_private.h:956
unsigned int has_scrolling
Definition: nuklear.h:3899
Definition: nuklear.h:3850
nk_edit_types
Definition: nuklear.h:2014
NK_API int nk_menu_begin_symbol(struct nk_context *, const char *, enum nk_symbol_type, struct nk_vec2 size)
float item_height
Definition: nuklear.h:3868
struct nk_style_button dec_button
Definition: nuklear.h:3511
nk_orientation
Definition: nuklear.h:468
struct nk_color border_color
Definition: nuklear.h:3648
NK_API int nk_list_view_begin(struct nk_context *, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count)
unsigned short rounding
Definition: nuklear.h:2997
struct nk_popup_buffer buf
Definition: nuklear.h:3937
NK_API int nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags)
GLsizei stride
Definition: glext.h:6488
struct nk_style_button dec_button
Definition: nuklear.h:3570
GLenum GLenum dst
Definition: glext.h:6980
Definition: nuklear.h:3447
Definition: nuklear.h:664
Definition: nuklear.h:470
#define NK_FLAGS_STACK_SIZE
Definition: nuklear.h:4045
#define fopen
Definition: file_stream_transforms.h:52
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)
Definition: nuklear.h:3004
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)
NK_API struct nk_color nk_rgba_hex(const char *rgb)
Definition: nuklear.h:457
nk_text_width_f width
Definition: nuklear.h:2489
NK_API void nk_layout_row_push(struct nk_context *, float value)
NK_API double nk_propertyd(struct nk_context *, const char *name, double min, double val, double max, double step, float inc_per_pixel)
NK_API int nk_input_is_mouse_pressed(const struct nk_input *, enum nk_buttons)
NK_API struct nk_panel * nk_window_get_panel(struct nk_context *)
NK_API int nk_textedit_cut(struct nk_text_edit *)
nk_uint * offset_y
Definition: nuklear.h:3894
Definition: nuklear.h:3854
short redo_char_point
Definition: nuklear.h:2833
#define nk_vec2_muls(a, t)
Definition: nuklear.h:4196
unsigned int clicked
Definition: nuklear.h:3184
nk_plugin_alloc alloc
Definition: nuklear.h:486
#define NK_MAX_FLOAT_PRECISION
Definition: nuklear.h:4179
Definition: nuklear.h:2163
struct nk_image img
Definition: nuklear.h:3098
Definition: nuklear.h:2015
vu8 head
Definition: keyboard.c:426
Definition: nuklear.h:4110
struct nk_color selected_hover
Definition: nuklear.h:3601
NK_API int nk_input_is_key_pressed(const struct nk_input *, enum nk_keys)
GLuint GLuint end
Definition: glext.h:6292
int select_start
Definition: nuklear.h:2854
Definition: nuklear.h:665
NK_API void nk_property_double(struct nk_context *, const char *name, double min, double *val, double max, double step, float inc_per_pixel)
Definition: nuklear.h:1835
NK_API struct nk_vec2 nk_rect_pos(struct nk_rect)
struct nk_color text_background
Definition: nuklear.h:3398
GLubyte GLubyte GLubyte GLubyte w
Definition: glext.h:6742
unsigned short rounding
Definition: nuklear.h:3006
NK_API void nk_group_scrolled_end(struct nk_context *)
nk_byte b
Definition: nuklear.h:453
#define nk_ptr_add_const(t, p, i)
Definition: nuklear.h:4199
const struct nk_cursor * cursor_active
Definition: nuklear.h:3780
nk_size last
Definition: nuklear.h:3879
Definition: nuklear.h:468
unsigned char ungrab
Definition: nuklear.h:3179
Definition: nuklear.h:468
struct nk_style_item background
Definition: nuklear.h:3647
char name_string[NK_WINDOW_MAX_NAME]
Definition: nuklear.h:3975
Definition: nuklear.h:687
Definition: nuklear.h:693
NK_API int nk_style_pop_float(struct nk_context *)
Definition: nuklear.h:689
Definition: nuklear.h:452
nk_size end
Definition: nuklear.h:3880
nk_size vertex_size
Definition: nuklear.h:990
#define NK_INT32
Definition: nuklear.h:352
nk_uint scroll_value
Definition: nuklear.h:1809
NK_API int nk_combo_begin_color(struct nk_context *, struct nk_color color, struct nk_vec2 size)
nk_heading
Definition: nuklear.h:465
struct nk_color cursor_border_color
Definition: nuklear.h:3558
int show_buttons
Definition: nuklear.h:3568
char text[NK_INPUT_MAX]
Definition: nuklear.h:3188
Definition: nuklear.h:2140
Definition: nuklear.h:500
int len
Definition: nuklear.h:2733
NK_UINT16 nk_ushort
Definition: nuklear.h:398
Definition: nuklear.h:466
NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color)
Definition: nuklear.h:682
GLfloat GLfloat GLfloat GLfloat h
Definition: glext.h:8390
NK_API void nk_input_motion(struct nk_context *, int x, int y)
float w
Definition: nuklear.h:3885
int length
Definition: nuklear.h:3962
nk_style_cursor
Definition: nuklear.h:2170
Definition: nuklear.h:3860
nk_hash name
Definition: nuklear.h:3938
struct nk_vec2 button_padding
Definition: nuklear.h:3685
float max
Definition: nuklear.h:3836
unsigned int clicked
Definition: nuklear.h:3168
nk_handle userdata
Definition: nuklear.h:485
Definition: nuklear.h:3129
struct nk_rect bounds
Definition: nuklear.h:3892
NK_API int nk_stricmpn(const char *s1, const char *s2, int n)
Definition: nuklear.h:2685
NK_API struct nk_rect nk_rectv(const float *xywh)
Definition: video4linux2.c:51
NK_API int nk_button_image_styled(struct nk_context *, const struct nk_style_button *, struct nk_image img)
Definition: nuklear.h:3820
unsigned short w
Definition: nuklear.h:3097
GLintptr offset
Definition: glext.h:6560
NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color)
NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context *, struct nk_vec2)
NK_API int nk_button_symbol_styled(struct nk_context *, const struct nk_style_button *, enum nk_symbol_type)
Definition: nuklear.h:3851
struct nk_color bar_normal
Definition: nuklear.h:3490
NK_API void nk_color_fv(float *rgba_out, struct nk_color)
#define NK_VECTOR_STACK_SIZE
Definition: nuklear.h:4041
GLint left
Definition: glext.h:8393
unsigned int count
Definition: nuklear.h:4170
unsigned char active
Definition: nuklear.h:2861
NK_API int nk_menu_item_text(struct nk_context *, const char *, int, nk_flags align)
nk_handle userdata
Definition: nuklear.h:3477
nk_style_item_type
Definition: nuklear.h:3370
nk_flags text_alignment
Definition: nuklear.h:3468
unsigned short line_thickness
Definition: nuklear.h:2980
Definition: nuklear.h:698
GLbitfield flags
Definition: glext.h:7828
NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv)
GLfloat GLfloat v1
Definition: glext.h:6702
#define NK_STATIC_ASSERT(exp)
Definition: nuklear.h:304
NK_API int nk_contextual_item_text(struct nk_context *, const char *, int, nk_flags align)
nk_flags flags
Definition: nuklear.h:3891
struct nk_color label_normal
Definition: nuklear.h:3666
static char old_mode[250]
Definition: dispserv_x11.c:37
NK_API void nk_layout_row(struct nk_context *, enum nk_layout_format, float height, int cols, const float *ratio)
NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input *, struct nk_rect)
unsigned short w
Definition: nuklear.h:3107
Definition: nuklear.h:3777
NK_API int nk_str_append_text_char(struct nk_str *, const char *, int)
NK_API int nk_input_is_mouse_released(const struct nk_input *, enum nk_buttons)
struct nk_style_item hover
Definition: nuklear.h:3393
Definition: nuklear.h:973
Definition: nuklear.h:3094
Definition: nuklear.h:2659
struct nk_clipboard clip
Definition: nuklear.h:4138
NK_API int nk_contextual_item_image_text(struct nk_context *, struct nk_image, const char *, int len, nk_flags alignment)
Definition: nuklear.h:1184
Definition: nuklear.h:971
nk_size last
Definition: nuklear.h:3134
float rounding
Definition: nuklear.h:3607
unsigned short h
Definition: nuklear.h:3050
nk_handle userdata
Definition: nuklear.h:3542
Definition: nuklear.h:473
struct nk_color cursor_hover
Definition: nuklear.h:3590
enum nk_symbol_type sym_right
Definition: nuklear.h:3628
struct nk_vec2 uv
Definition: nuklear.h:979
float h
Definition: nuklear.h:3885
struct nk_vec2 padding
Definition: nuklear.h:3735
Definition: nuklear.h:1845
Definition: nuklear.h:501
struct nk_style_item active
Definition: nuklear.h:3394
struct nk_window * active
Definition: nuklear.h:4167
Definition: nuklear.h:3689
NK_API void nk_buffer_info(struct nk_memory_status *, struct nk_buffer *)
nk_widget_layout_states
Definition: nuklear.h:1833
Definition: nuklear.h:677
Definition: nuklear.h:3071
Definition: nuklear.h:981
float group_border
Definition: nuklear.h:3758
#define NK_CONTAINER_OF(ptr, type, member)
Definition: nuklear.h:4226
NK_API int nk_style_pop_font(struct nk_context *)
nk_uint nk_flags
Definition: nuklear.h:405
NK_API void nk_contextual_end(struct nk_context *)
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)
bool down
Definition: connect_wiiupro.c:51
NK_API struct nk_color nk_hsv_f(float h, float s, float v)
float range
Definition: nuklear.h:3836
NK_API void nk_fill_polygon(struct nk_command_buffer *, float *, int point_count, struct nk_color)
Definition: nuklear.h:674
nk_size size
Definition: nuklear.h:2662
Definition: build.py:1
struct nk_vec2 padding
Definition: nuklear.h:3407
NK_API struct nk_color nk_color_picker(struct nk_context *, struct nk_color, enum nk_color_format)
Definition: nuklear.h:684
int build
Definition: nuklear.h:4162
GLenum GLuint GLenum GLsizei length
Definition: glext.h:6233
float rounding
Definition: nuklear.h:3502
static uint8_t body[]
Definition: remotepad.h:4
float x
Definition: nuklear.h:3885
GLdouble n
Definition: glext.h:8396
struct nk_edit_state edit
Definition: nuklear.h:3987
struct nk_table * tables
Definition: nuklear.h:3990
float border
Definition: nuklear.h:3704
nk_size size
Definition: nuklear.h:2684
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)
GLsizei const GLint * box
Definition: glsym_es2.h:225
float spacing
Definition: nuklear.h:3438
NK_API void nk_window_show_if(struct nk_context *, const char *name, enum nk_show_states, int cond)
struct nk_color color
Definition: nuklear.h:3377
unsigned short w
Definition: nuklear.h:461
Definition: nuklear.h:3614
Definition: nuklear.h:3047
nk_size calls
Definition: nuklear.h:2665
const GLfloat * m
Definition: glext.h:11755
Definition: nuklear.h:463
nk_handle userdata
Definition: nuklear.h:3442
NK_API nk_size nk_buffer_total(struct nk_buffer *)
NK_API void nk_group_end(struct nk_context *)
static struct _xy xy[2][12]
#define in_range(c, lo, up)
Definition: network_common.c:6
Definition: nuklear.h:3824
nk_flags text_alignment
Definition: nuklear.h:3433
struct nk_color label_hover
Definition: nuklear.h:3667
NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region)
float cursor_size
Definition: nuklear.h:3608
NK_API int nk_style_pop_flags(struct nk_context *)
float footer_height
Definition: nuklear.h:3896
NK_API nk_uint nk_color_u32(struct nk_color)
void(* draw_end)(struct nk_command_buffer *, nk_handle)
Definition: nuklear.h:3642
NK_API void nk_str_init_fixed(struct nk_str *, void *memory, nk_size size)
Definition: nuklear.h:2958
unsigned int page_count
Definition: nuklear.h:4125
Definition: nuklear.h:498
struct nk_font_atlas atlas
Definition: nk_common.c:41
NK_API struct nk_color nk_rgb_f(float r, float g, float b)
const char *const str
Definition: portlistingparse.c:18
NK_API void nk_tooltip(struct nk_context *, const char *)
struct nk_key keys[NK_KEY_MAX]
Definition: nuklear.h:3187
NK_API struct nk_vec2 nk_window_get_size(const struct nk_context *)
Definition: nuklear.h:1179
struct nk_vec2 spacing
Definition: nuklear.h:3708
struct nk_style_item cursor_hover
Definition: nuklear.h:3530
Definition: nuklear.h:476
int id
Definition: nuklear.h:460
NK_API int nk_menu_begin_label(struct nk_context *, const char *, nk_flags align, struct nk_vec2 size)
NK_API void nk_textedit_undo(struct nk_text_edit *)
unsigned int type
Definition: nuklear.h:2661
enum nk_allocation_type type
Definition: nuklear.h:4124
unsigned short w
Definition: nuklear.h:3043
NK_API void nk_color_dv(double *rgba_out, struct nk_color)
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6844
NK_API void nk_str_free(struct nk_str *)
struct nk_panel pan
Definition: nuklear.h:4106
float scrollbar_hiding_timer
Definition: nuklear.h:3982
NK_API void nk_push_scissor(struct nk_command_buffer *, struct nk_rect)
NK_API void nk_stroke_circle(struct nk_command_buffer *, struct nk_rect, float line_thickness, struct nk_color)
struct nk_config_stack_button_behavior button_behaviors
Definition: nuklear.h:4087
nk_command_custom_callback callback
Definition: nuklear.h:3109
NK_API void nk_stroke_polyline(struct nk_command_buffer *, float *points, int point_count, float line_thickness, struct nk_color col)
struct nk_command_buffer * buffer
Definition: nuklear.h:3904
struct nk_style_tab tab
Definition: nuklear.h:3798
#define fseek
Definition: file_stream_transforms.h:55
struct nk_style_button dec_button
Definition: nuklear.h:3637
short y
Definition: nuklear.h:456
Definition: nuklear.h:471
struct nk_memory memory
Definition: nuklear.h:2692
GLint GLint GLsizei GLsizei height
Definition: glext.h:6293
NK_API void nk_push_custom(struct nk_command_buffer *, struct nk_rect, nk_command_custom_callback, nk_handle usr)
nk_hash keys[NK_VALUE_PAGE_CAPACITY]
Definition: nuklear.h:4099
float popup_border
Definition: nuklear.h:3760
Definition: nuklear.h:1870
Definition: nuklear.h:3946
Definition: nuklear.h:2011
struct nk_style_item hover_active
Definition: nuklear.h:3455
nk_flags last_widget_state
Definition: nuklear.h:4139
#define NK_UINT16
Definition: nuklear.h:346
Definition: nuklear.h:3192
nk_handle texture
Definition: nuklear.h:978
NK_API void nk_layout_set_min_row_height(struct nk_context *, float height)
enum nk_panel_type type
Definition: nuklear.h:3936
struct nk_color highlight
Definition: nuklear.h:3835
#define NK_TEXTEDIT_UNDOCHARCOUNT
Definition: nuklear.h:2810
struct nk_property_state property
Definition: nuklear.h:3985
Definition: nuklear.h:2847
NK_API int nk_button_push_behavior(struct nk_context *, enum nk_button_behavior)
Definition: nuklear.h:1840
struct nk_vec2 combo_padding
Definition: nuklear.h:3771
struct nk_mouse_button buttons[NK_BUTTON_MAX]
Definition: nuklear.h:3172
struct nk_config_stack_color colors
Definition: nuklear.h:4085
NK_API struct nk_color nk_hsv(int h, int s, int v)
NK_API struct nk_image nk_subimage_ptr(void *, unsigned short w, unsigned short h, struct nk_rect sub_region)
NK_API int nk_combo_begin_label(struct nk_context *, const char *selected, struct nk_vec2 size)
NK_API int nk_window_has_focus(const struct nk_context *)
nk_text_edit_type
Definition: nuklear.h:2836
struct nk_command header
Definition: nuklear.h:3013
Definition: nuklear.h:469
NK_API struct nk_vec2 nk_widget_size(struct nk_context *)
NK_API int nk_contextual_item_label(struct nk_context *, const char *, nk_flags align)
int prev
Definition: nuklear.h:3960
float rounding_cursor
Definition: nuklear.h:3564
nk_size vertex_alignment
Definition: nuklear.h:991
#define nk_vec2_sub(a, b)
Definition: nuklear.h:4193
float border_cursor
Definition: nuklear.h:3563
set set set set set set set macro pixldst1 elem_size
Definition: pixman-arm-neon-asm.h:54
NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a)
NK_API int nk_combo(struct nk_context *, const char **items, int count, int selected, int item_height, struct nk_vec2 size)
NK_API struct nk_image nk_image_handle(nk_handle)
struct nk_keyboard keyboard
Definition: nuklear.h:3193
float rounding
Definition: nuklear.h:3763
unsigned short h
Definition: nuklear.h:3097
NK_API int nk_popup_begin(struct nk_context *, enum nk_popup_type, const char *, nk_flags, struct nk_rect bounds)
unsigned con_count
Definition: nuklear.h:3941
Definition: nuklear.h:1842