nuklear.h (1162955B)
1 /* 2 /// # Nuklear 3 /// ![](https://cloud.githubusercontent.com/assets/8057201/11761525/ae06f0ca-a0c6-11e5-819d-5610b25f6ef4.gif) 4 /// 5 /// ## Contents 6 /// 1. About section 7 /// 2. Highlights section 8 /// 3. Features section 9 /// 4. Usage section 10 /// 1. Flags section 11 /// 2. Constants section 12 /// 3. Dependencies section 13 /// 5. Example section 14 /// 6. API section 15 /// 1. Context section 16 /// 2. Input section 17 /// 3. Drawing section 18 /// 4. Window section 19 /// 5. Layouting section 20 /// 6. Groups section 21 /// 7. Tree section 22 /// 8. Properties section 23 /// 7. License section 24 /// 8. Changelog section 25 /// 9. Gallery section 26 /// 10. Credits section 27 /// 28 /// ## About 29 /// This is a minimal state immediate mode graphical user interface toolkit 30 /// written in ANSI C and licensed under public domain. It was designed as a simple 31 /// embeddable user interface for application and does not have any dependencies, 32 /// a default renderbackend or OS window and input handling but instead provides a very modular 33 /// library approach by using simple input state for input and draw 34 /// commands describing primitive shapes as output. So instead of providing a 35 /// layered library that tries to abstract over a number of platform and 36 /// render backends it only focuses on the actual UI. 37 /// 38 /// ## Highlights 39 /// - Graphical user interface toolkit 40 /// - Single header library 41 /// - Written in C89 (a.k.a. ANSI C or ISO C90) 42 /// - Small codebase (~18kLOC) 43 /// - Focus on portability, efficiency and simplicity 44 /// - No dependencies (not even the standard library if not wanted) 45 /// - Fully skinnable and customizable 46 /// - Low memory footprint with total memory control if needed or wanted 47 /// - UTF-8 support 48 /// - No global or hidden state 49 /// - Customizable library modules (you can compile and use only what you need) 50 /// - Optional font baker and vertex buffer output 51 /// - [Code available on github](https://github.com/Immediate-Mode-UI/Nuklear/) 52 /// 53 /// ## Features 54 /// - Absolutely no platform dependent code 55 /// - Memory management control ranging from/to 56 /// - Ease of use by allocating everything from standard library 57 /// - Control every byte of memory inside the library 58 /// - Font handling control ranging from/to 59 /// - Use your own font implementation for everything 60 /// - Use this libraries internal font baking and handling API 61 /// - Drawing output control ranging from/to 62 /// - Simple shapes for more high level APIs which already have drawing capabilities 63 /// - Hardware accessible anti-aliased vertex buffer output 64 /// - Customizable colors and properties ranging from/to 65 /// - Simple changes to color by filling a simple color table 66 /// - Complete control with ability to use skinning to decorate widgets 67 /// - Bendable UI library with widget ranging from/to 68 /// - Basic widgets like buttons, checkboxes, slider, ... 69 /// - Advanced widget like abstract comboboxes, contextual menus,... 70 /// - Compile time configuration to only compile what you need 71 /// - Subset which can be used if you do not want to link or use the standard library 72 /// - Can be easily modified to only update on user input instead of frame updates 73 /// 74 /// ## Usage 75 /// This library is self contained in one single header file and can be used either 76 /// in header only mode or in implementation mode. The header only mode is used 77 /// by default when included and allows including this header in other headers 78 /// and does not contain the actual implementation. <br /><br /> 79 /// 80 /// The implementation mode requires to define the preprocessor macro 81 /// NK_IMPLEMENTATION in *one* .c/.cpp file before #including this file, e.g.: 82 /// 83 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~C 84 /// #define NK_IMPLEMENTATION 85 /// #include "nuklear.h" 86 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 87 /// 88 /// Also optionally define the symbols listed in the section "OPTIONAL DEFINES" 89 /// below in header and implementation mode if you want to use additional functionality 90 /// or need more control over the library. 91 /// 92 /// !!! WARNING 93 /// Every time nuklear is included define the same compiler flags. This very important not doing so could lead to compiler errors or even worse stack corruptions. 94 /// 95 /// ### Flags 96 /// Flag | Description 97 /// --------------------------------|------------------------------------------ 98 /// NK_PRIVATE | If defined declares all functions as static, so they can only be accessed inside the file that contains the implementation 99 /// NK_INCLUDE_FIXED_TYPES | If defined it will include header `<stdint.h>` for fixed sized types otherwise nuklear tries to select the correct type. If that fails it will throw a compiler error and you have to select the correct types yourself. 100 /// NK_INCLUDE_DEFAULT_ALLOCATOR | If defined it will include header `<stdlib.h>` and provide additional functions to use this library without caring for memory allocation control and therefore ease memory management. 101 /// NK_INCLUDE_STANDARD_IO | If defined it will include header `<stdio.h>` and provide additional functions depending on file loading. 102 /// NK_INCLUDE_STANDARD_VARARGS | If defined it will include header <stdarg.h> and provide additional functions depending on file loading. 103 /// NK_INCLUDE_STANDARD_BOOL | If defined it will include header `<stdbool.h>` for nk_bool otherwise nuklear defines nk_bool as int. 104 /// NK_INCLUDE_VERTEX_BUFFER_OUTPUT | Defining this adds a vertex draw command list backend to this library, which allows you to convert queue commands into vertex draw commands. This is mainly if you need a hardware accessible format for OpenGL, DirectX, Vulkan, Metal,... 105 /// NK_INCLUDE_FONT_BAKING | Defining this adds `stb_truetype` and `stb_rect_pack` implementation to this library and provides font baking and rendering. If you already have font handling or do not want to use this font handler you don't have to define it. 106 /// NK_INCLUDE_DEFAULT_FONT | Defining this adds the default font: ProggyClean.ttf into this library which can be loaded into a font atlas and allows using this library without having a truetype font 107 /// NK_INCLUDE_COMMAND_USERDATA | Defining this adds a userdata pointer into each command. Can be useful for example if you want to provide custom shaders depending on the used widget. Can be combined with the style structures. 108 /// NK_BUTTON_TRIGGER_ON_RELEASE | Different platforms require button clicks occurring either on buttons being pressed (up to down) or released (down to up). By default this library will react on buttons being pressed, but if you define this it will only trigger if a button is released. 109 /// NK_ZERO_COMMAND_MEMORY | Defining this will zero out memory for each drawing command added to a drawing queue (inside nk_command_buffer_push). Zeroing command memory is very useful for fast checking (using memcmp) if command buffers are equal and avoid drawing frames when nothing on screen has changed since previous frame. 110 /// NK_UINT_DRAW_INDEX | Defining this will set the size of vertex index elements when using NK_VERTEX_BUFFER_OUTPUT to 32bit instead of the default of 16bit 111 /// NK_KEYSTATE_BASED_INPUT | Define this if your backend uses key state for each frame rather than key press/release events 112 /// 113 /// !!! WARNING 114 /// The following flags will pull in the standard C library: 115 /// - NK_INCLUDE_DEFAULT_ALLOCATOR 116 /// - NK_INCLUDE_STANDARD_IO 117 /// - NK_INCLUDE_STANDARD_VARARGS 118 /// 119 /// !!! WARNING 120 /// The following flags if defined need to be defined for both header and implementation: 121 /// - NK_INCLUDE_FIXED_TYPES 122 /// - NK_INCLUDE_DEFAULT_ALLOCATOR 123 /// - NK_INCLUDE_STANDARD_VARARGS 124 /// - NK_INCLUDE_STANDARD_BOOL 125 /// - NK_INCLUDE_VERTEX_BUFFER_OUTPUT 126 /// - NK_INCLUDE_FONT_BAKING 127 /// - NK_INCLUDE_DEFAULT_FONT 128 /// - NK_INCLUDE_STANDARD_VARARGS 129 /// - NK_INCLUDE_COMMAND_USERDATA 130 /// - NK_UINT_DRAW_INDEX 131 /// 132 /// ### Constants 133 /// Define | Description 134 /// --------------------------------|--------------------------------------- 135 /// NK_BUFFER_DEFAULT_INITIAL_SIZE | Initial buffer size allocated by all buffers while using the default allocator functions included by defining NK_INCLUDE_DEFAULT_ALLOCATOR. If you don't want to allocate the default 4k memory then redefine it. 136 /// NK_MAX_NUMBER_BUFFER | Maximum buffer size for the conversion buffer between float and string Under normal circumstances this should be more than sufficient. 137 /// NK_INPUT_MAX | Defines the max number of bytes which can be added as text input in one frame. Under normal circumstances this should be more than sufficient. 138 /// 139 /// !!! WARNING 140 /// The following constants if defined need to be defined for both header and implementation: 141 /// - NK_MAX_NUMBER_BUFFER 142 /// - NK_BUFFER_DEFAULT_INITIAL_SIZE 143 /// - NK_INPUT_MAX 144 /// 145 /// ### Dependencies 146 /// Function | Description 147 /// ------------|--------------------------------------------------------------- 148 /// NK_ASSERT | If you don't define this, nuklear will use <assert.h> with assert(). 149 /// NK_MEMSET | You can define this to 'memset' or your own memset implementation replacement. If not nuklear will use its own version. 150 /// NK_MEMCPY | You can define this to 'memcpy' or your own memcpy implementation replacement. If not nuklear will use its own version. 151 /// NK_INV_SQRT | You can define this to your own inverse sqrt implementation replacement. If not nuklear will use its own slow and not highly accurate version. 152 /// NK_SIN | You can define this to 'sinf' or your own sine implementation replacement. If not nuklear will use its own approximation implementation. 153 /// NK_COS | You can define this to 'cosf' or your own cosine implementation replacement. If not nuklear will use its own approximation implementation. 154 /// NK_STRTOD | You can define this to `strtod` or your own string to double conversion implementation replacement. If not defined nuklear will use its own imprecise and possibly unsafe version (does not handle nan or infinity!). 155 /// NK_DTOA | You can define this to `dtoa` or your own double to string conversion implementation replacement. If not defined nuklear will use its own imprecise and possibly unsafe version (does not handle nan or infinity!). 156 /// NK_VSNPRINTF| If you define `NK_INCLUDE_STANDARD_VARARGS` as well as `NK_INCLUDE_STANDARD_IO` and want to be safe define this to `vsnprintf` on compilers supporting later versions of C or C++. By default nuklear will check for your stdlib version in C as well as compiler version in C++. if `vsnprintf` is available it will define it to `vsnprintf` directly. If not defined and if you have older versions of C or C++ it will be defined to `vsprintf` which is unsafe. 157 /// 158 /// !!! WARNING 159 /// The following dependencies will pull in the standard C library if not redefined: 160 /// - NK_ASSERT 161 /// 162 /// !!! WARNING 163 /// The following dependencies if defined need to be defined for both header and implementation: 164 /// - NK_ASSERT 165 /// 166 /// !!! WARNING 167 /// The following dependencies if defined need to be defined only for the implementation part: 168 /// - NK_MEMSET 169 /// - NK_MEMCPY 170 /// - NK_SQRT 171 /// - NK_SIN 172 /// - NK_COS 173 /// - NK_STRTOD 174 /// - NK_DTOA 175 /// - NK_VSNPRINTF 176 /// 177 /// ## Example 178 /// 179 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 180 /// // init gui state 181 /// enum {EASY, HARD}; 182 /// static int op = EASY; 183 /// static float value = 0.6f; 184 /// static int i = 20; 185 /// struct nk_context ctx; 186 /// 187 /// nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font); 188 /// if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220), 189 /// NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) { 190 /// // fixed widget pixel width 191 /// nk_layout_row_static(&ctx, 30, 80, 1); 192 /// if (nk_button_label(&ctx, "button")) { 193 /// // event handling 194 /// } 195 /// 196 /// // fixed widget window ratio width 197 /// nk_layout_row_dynamic(&ctx, 30, 2); 198 /// if (nk_option_label(&ctx, "easy", op == EASY)) op = EASY; 199 /// if (nk_option_label(&ctx, "hard", op == HARD)) op = HARD; 200 /// 201 /// // custom widget pixel width 202 /// nk_layout_row_begin(&ctx, NK_STATIC, 30, 2); 203 /// { 204 /// nk_layout_row_push(&ctx, 50); 205 /// nk_label(&ctx, "Volume:", NK_TEXT_LEFT); 206 /// nk_layout_row_push(&ctx, 110); 207 /// nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f); 208 /// } 209 /// nk_layout_row_end(&ctx); 210 /// } 211 /// nk_end(&ctx); 212 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 213 /// 214 /// ![](https://cloud.githubusercontent.com/assets/8057201/10187981/584ecd68-675c-11e5-897c-822ef534a876.png) 215 /// 216 /// ## API 217 /// 218 */ 219 #ifndef NK_SINGLE_FILE 220 #define NK_SINGLE_FILE 221 #endif 222 223 #ifndef NK_NUKLEAR_H_ 224 #define NK_NUKLEAR_H_ 225 226 #ifdef __cplusplus 227 extern "C" { 228 #endif 229 /* 230 * ============================================================== 231 * 232 * CONSTANTS 233 * 234 * =============================================================== 235 */ 236 #define NK_UNDEFINED (-1.0f) 237 #define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */ 238 #define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/ 239 #ifndef NK_INPUT_MAX 240 #define NK_INPUT_MAX 16 241 #endif 242 #ifndef NK_MAX_NUMBER_BUFFER 243 #define NK_MAX_NUMBER_BUFFER 64 244 #endif 245 #ifndef NK_SCROLLBAR_HIDING_TIMEOUT 246 #define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f 247 #endif 248 /* 249 * ============================================================== 250 * 251 * HELPER 252 * 253 * =============================================================== 254 */ 255 #ifndef NK_API 256 #ifdef NK_PRIVATE 257 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199409L)) 258 #define NK_API static inline 259 #elif defined(__cplusplus) 260 #define NK_API static inline 261 #else 262 #define NK_API static 263 #endif 264 #else 265 #define NK_API extern 266 #endif 267 #endif 268 #ifndef NK_LIB 269 #ifdef NK_SINGLE_FILE 270 #define NK_LIB static 271 #else 272 #define NK_LIB extern 273 #endif 274 #endif 275 276 #define NK_INTERN static 277 #define NK_STORAGE static 278 #define NK_GLOBAL static 279 280 #define NK_FLAG(x) (1 << (x)) 281 #define NK_STRINGIFY(x) #x 282 #define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x) 283 #define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2 284 #define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2) 285 #define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2) 286 287 #ifdef _MSC_VER 288 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__) 289 #else 290 #define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__) 291 #endif 292 293 #ifndef NK_STATIC_ASSERT 294 #define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1] 295 #endif 296 297 #ifndef NK_FILE_LINE 298 #ifdef _MSC_VER 299 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__) 300 #else 301 #define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__) 302 #endif 303 #endif 304 305 #define NK_MIN(a,b) ((a) < (b) ? (a) : (b)) 306 #define NK_MAX(a,b) ((a) < (b) ? (b) : (a)) 307 #define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i)) 308 309 #ifdef NK_INCLUDE_STANDARD_VARARGS 310 #include <stdarg.h> 311 #if defined(_MSC_VER) && (_MSC_VER >= 1600) /* VS 2010 and above */ 312 #include <sal.h> 313 #define NK_PRINTF_FORMAT_STRING _Printf_format_string_ 314 #else 315 #define NK_PRINTF_FORMAT_STRING 316 #endif 317 #if defined(__GNUC__) 318 #define NK_PRINTF_VARARG_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, fmtargnumber+1))) 319 #define NK_PRINTF_VALIST_FUNC(fmtargnumber) __attribute__((format(__printf__, fmtargnumber, 0))) 320 #else 321 #define NK_PRINTF_VARARG_FUNC(fmtargnumber) 322 #define NK_PRINTF_VALIST_FUNC(fmtargnumber) 323 #endif 324 #endif 325 326 /* 327 * =============================================================== 328 * 329 * BASIC 330 * 331 * =============================================================== 332 */ 333 #ifdef NK_INCLUDE_FIXED_TYPES 334 #include <stdint.h> 335 #define NK_INT8 int8_t 336 #define NK_UINT8 uint8_t 337 #define NK_INT16 int16_t 338 #define NK_UINT16 uint16_t 339 #define NK_INT32 int32_t 340 #define NK_UINT32 uint32_t 341 #define NK_SIZE_TYPE uintptr_t 342 #define NK_POINTER_TYPE uintptr_t 343 #else 344 #ifndef NK_INT8 345 #define NK_INT8 signed char 346 #endif 347 #ifndef NK_UINT8 348 #define NK_UINT8 unsigned char 349 #endif 350 #ifndef NK_INT16 351 #define NK_INT16 signed short 352 #endif 353 #ifndef NK_UINT16 354 #define NK_UINT16 unsigned short 355 #endif 356 #ifndef NK_INT32 357 #if defined(_MSC_VER) 358 #define NK_INT32 __int32 359 #else 360 #define NK_INT32 signed int 361 #endif 362 #endif 363 #ifndef NK_UINT32 364 #if defined(_MSC_VER) 365 #define NK_UINT32 unsigned __int32 366 #else 367 #define NK_UINT32 unsigned int 368 #endif 369 #endif 370 #ifndef NK_SIZE_TYPE 371 #if defined(_WIN64) && defined(_MSC_VER) 372 #define NK_SIZE_TYPE unsigned __int64 373 #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) 374 #define NK_SIZE_TYPE unsigned __int32 375 #elif defined(__GNUC__) || defined(__clang__) 376 #if defined(__x86_64__) || defined(__ppc64__) || defined(__aarch64__) 377 #define NK_SIZE_TYPE unsigned long 378 #else 379 #define NK_SIZE_TYPE unsigned int 380 #endif 381 #else 382 #define NK_SIZE_TYPE unsigned long 383 #endif 384 #endif 385 #ifndef NK_POINTER_TYPE 386 #if defined(_WIN64) && defined(_MSC_VER) 387 #define NK_POINTER_TYPE unsigned __int64 388 #elif (defined(_WIN32) || defined(WIN32)) && defined(_MSC_VER) 389 #define NK_POINTER_TYPE unsigned __int32 390 #elif defined(__GNUC__) || defined(__clang__) 391 #if defined(__x86_64__) || defined(__ppc64__) || defined(__aarch64__) 392 #define NK_POINTER_TYPE unsigned long 393 #else 394 #define NK_POINTER_TYPE unsigned int 395 #endif 396 #else 397 #define NK_POINTER_TYPE unsigned long 398 #endif 399 #endif 400 #endif 401 402 #ifndef NK_BOOL 403 #ifdef NK_INCLUDE_STANDARD_BOOL 404 #include <stdbool.h> 405 #define NK_BOOL bool 406 #else 407 #define NK_BOOL int /* could be char, use int for drop-in replacement backwards compatibility */ 408 #endif 409 #endif 410 411 typedef NK_INT8 nk_char; 412 typedef NK_UINT8 nk_uchar; 413 typedef NK_UINT8 nk_byte; 414 typedef NK_INT16 nk_short; 415 typedef NK_UINT16 nk_ushort; 416 typedef NK_INT32 nk_int; 417 typedef NK_UINT32 nk_uint; 418 typedef NK_SIZE_TYPE nk_size; 419 typedef NK_POINTER_TYPE nk_ptr; 420 typedef NK_BOOL nk_bool; 421 422 typedef nk_uint nk_hash; 423 typedef nk_uint nk_flags; 424 typedef nk_uint nk_rune; 425 426 /* Make sure correct type size: 427 * This will fire with a negative subscript error if the type sizes 428 * are set incorrectly by the compiler, and compile out if not */ 429 NK_STATIC_ASSERT(sizeof(nk_short) == 2); 430 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); 431 NK_STATIC_ASSERT(sizeof(nk_uint) == 4); 432 NK_STATIC_ASSERT(sizeof(nk_int) == 4); 433 NK_STATIC_ASSERT(sizeof(nk_byte) == 1); 434 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); 435 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); 436 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); 437 NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*)); 438 #ifdef NK_INCLUDE_STANDARD_BOOL 439 NK_STATIC_ASSERT(sizeof(nk_bool) == sizeof(bool)); 440 #else 441 NK_STATIC_ASSERT(sizeof(nk_bool) >= 2); 442 #endif 443 444 /* ============================================================================ 445 * 446 * API 447 * 448 * =========================================================================== */ 449 struct nk_buffer; 450 struct nk_allocator; 451 struct nk_command_buffer; 452 struct nk_draw_command; 453 struct nk_convert_config; 454 struct nk_style_item; 455 struct nk_text_edit; 456 struct nk_draw_list; 457 struct nk_user_font; 458 struct nk_panel; 459 struct nk_context; 460 struct nk_draw_vertex_layout_element; 461 struct nk_style_button; 462 struct nk_style_toggle; 463 struct nk_style_selectable; 464 struct nk_style_slide; 465 struct nk_style_progress; 466 struct nk_style_scrollbar; 467 struct nk_style_edit; 468 struct nk_style_property; 469 struct nk_style_chart; 470 struct nk_style_combo; 471 struct nk_style_tab; 472 struct nk_style_window_header; 473 struct nk_style_window; 474 475 enum {nk_false, nk_true}; 476 struct nk_color {nk_byte r,g,b,a;}; 477 struct nk_colorf {float r,g,b,a;}; 478 struct nk_vec2 {float x,y;}; 479 struct nk_vec2i {short x, y;}; 480 struct nk_rect {float x,y,w,h;}; 481 struct nk_recti {short x,y,w,h;}; 482 typedef char nk_glyph[NK_UTF_SIZE]; 483 typedef union {void *ptr; int id;} nk_handle; 484 struct nk_image {nk_handle handle; nk_ushort w, h; nk_ushort region[4];}; 485 struct nk_nine_slice {struct nk_image img; nk_ushort l, t, r, b;}; 486 struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;}; 487 struct nk_scroll {nk_uint x, y;}; 488 489 enum nk_heading {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT}; 490 enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER}; 491 enum nk_modify {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true}; 492 enum nk_orientation {NK_VERTICAL, NK_HORIZONTAL}; 493 enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true}; 494 enum nk_show_states {NK_HIDDEN = nk_false, NK_SHOWN = nk_true}; 495 enum nk_chart_type {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX}; 496 enum nk_chart_event {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02}; 497 enum nk_color_format {NK_RGB, NK_RGBA}; 498 enum nk_popup_type {NK_POPUP_STATIC, NK_POPUP_DYNAMIC}; 499 enum nk_layout_format {NK_DYNAMIC, NK_STATIC}; 500 enum nk_tree_type {NK_TREE_NODE, NK_TREE_TAB}; 501 502 typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size); 503 typedef void (*nk_plugin_free)(nk_handle, void *old); 504 typedef nk_bool(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode); 505 typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*); 506 typedef void(*nk_plugin_copy)(nk_handle, const char*, int len); 507 508 struct nk_allocator { 509 nk_handle userdata; 510 nk_plugin_alloc alloc; 511 nk_plugin_free free; 512 }; 513 enum nk_symbol_type { 514 NK_SYMBOL_NONE, 515 NK_SYMBOL_X, 516 NK_SYMBOL_UNDERSCORE, 517 NK_SYMBOL_CIRCLE_SOLID, 518 NK_SYMBOL_CIRCLE_OUTLINE, 519 NK_SYMBOL_RECT_SOLID, 520 NK_SYMBOL_RECT_OUTLINE, 521 NK_SYMBOL_TRIANGLE_UP, 522 NK_SYMBOL_TRIANGLE_DOWN, 523 NK_SYMBOL_TRIANGLE_LEFT, 524 NK_SYMBOL_TRIANGLE_RIGHT, 525 NK_SYMBOL_PLUS, 526 NK_SYMBOL_MINUS, 527 NK_SYMBOL_MAX 528 }; 529 /* ============================================================================= 530 * 531 * CONTEXT 532 * 533 * =============================================================================*/ 534 /*/// ### Context 535 /// Contexts are the main entry point and the majestro of nuklear and contain all required state. 536 /// They are used for window, memory, input, style, stack, commands and time management and need 537 /// to be passed into all nuklear GUI specific functions. 538 /// 539 /// #### Usage 540 /// To use a context it first has to be initialized which can be achieved by calling 541 /// one of either `nk_init_default`, `nk_init_fixed`, `nk_init`, `nk_init_custom`. 542 /// Each takes in a font handle and a specific way of handling memory. Memory control 543 /// hereby ranges from standard library to just specifying a fixed sized block of memory 544 /// which nuklear has to manage itself from. 545 /// 546 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 547 /// struct nk_context ctx; 548 /// nk_init_xxx(&ctx, ...); 549 /// while (1) { 550 /// // [...] 551 /// nk_clear(&ctx); 552 /// } 553 /// nk_free(&ctx); 554 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 555 /// 556 /// #### Reference 557 /// Function | Description 558 /// --------------------|------------------------------------------------------- 559 /// __nk_init_default__ | Initializes context with standard library memory allocation (malloc,free) 560 /// __nk_init_fixed__ | Initializes context from single fixed size memory block 561 /// __nk_init__ | Initializes context with memory allocator callbacks for alloc and free 562 /// __nk_init_custom__ | Initializes context from two buffers. One for draw commands the other for window/panel/table allocations 563 /// __nk_clear__ | Called at the end of the frame to reset and prepare the context for the next frame 564 /// __nk_free__ | Shutdown and free all memory allocated inside the context 565 /// __nk_set_user_data__| Utility function to pass user data to draw command 566 */ 567 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 568 /*/// #### nk_init_default 569 /// Initializes a `nk_context` struct with a default standard library allocator. 570 /// Should be used if you don't want to be bothered with memory management in nuklear. 571 /// 572 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 573 /// nk_bool nk_init_default(struct nk_context *ctx, const struct nk_user_font *font); 574 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 575 /// 576 /// Parameter | Description 577 /// ------------|--------------------------------------------------------------- 578 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 579 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 580 /// 581 /// Returns either `false(0)` on failure or `true(1)` on success. 582 /// 583 */ 584 NK_API nk_bool nk_init_default(struct nk_context*, const struct nk_user_font*); 585 #endif 586 /*/// #### nk_init_fixed 587 /// Initializes a `nk_context` struct from single fixed size memory block 588 /// Should be used if you want complete control over nuklear's memory management. 589 /// Especially recommended for system with little memory or systems with virtual memory. 590 /// For the later case you can just allocate for example 16MB of virtual memory 591 /// and only the required amount of memory will actually be committed. 592 /// 593 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 594 /// nk_bool nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, const struct nk_user_font *font); 595 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 596 /// 597 /// !!! Warning 598 /// make sure the passed memory block is aligned correctly for `nk_draw_commands`. 599 /// 600 /// Parameter | Description 601 /// ------------|-------------------------------------------------------------- 602 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 603 /// __memory__ | Must point to a previously allocated memory block 604 /// __size__ | Must contain the total size of __memory__ 605 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 606 /// 607 /// Returns either `false(0)` on failure or `true(1)` on success. 608 */ 609 NK_API nk_bool nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*); 610 /*/// #### nk_init 611 /// Initializes a `nk_context` struct with memory allocation callbacks for nuklear to allocate 612 /// memory from. Used internally for `nk_init_default` and provides a kitchen sink allocation 613 /// interface to nuklear. Can be useful for cases like monitoring memory consumption. 614 /// 615 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 616 /// nk_bool nk_init(struct nk_context *ctx, struct nk_allocator *alloc, const struct nk_user_font *font); 617 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 618 /// 619 /// Parameter | Description 620 /// ------------|--------------------------------------------------------------- 621 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 622 /// __alloc__ | Must point to a previously allocated memory allocator 623 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 624 /// 625 /// Returns either `false(0)` on failure or `true(1)` on success. 626 */ 627 NK_API nk_bool nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*); 628 /*/// #### nk_init_custom 629 /// Initializes a `nk_context` struct from two different either fixed or growing 630 /// buffers. The first buffer is for allocating draw commands while the second buffer is 631 /// used for allocating windows, panels and state tables. 632 /// 633 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 634 /// nk_bool nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font *font); 635 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 636 /// 637 /// Parameter | Description 638 /// ------------|--------------------------------------------------------------- 639 /// __ctx__ | Must point to an either stack or heap allocated `nk_context` struct 640 /// __cmds__ | Must point to a previously initialized memory buffer either fixed or dynamic to store draw commands into 641 /// __pool__ | Must point to a previously initialized memory buffer either fixed or dynamic to store windows, panels and tables 642 /// __font__ | Must point to a previously initialized font handle for more info look at font documentation 643 /// 644 /// Returns either `false(0)` on failure or `true(1)` on success. 645 */ 646 NK_API nk_bool nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*); 647 /*/// #### nk_clear 648 /// Resets the context state at the end of the frame. This includes mostly 649 /// garbage collector tasks like removing windows or table not called and therefore 650 /// used anymore. 651 /// 652 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 653 /// void nk_clear(struct nk_context *ctx); 654 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 655 /// 656 /// Parameter | Description 657 /// ------------|----------------------------------------------------------- 658 /// __ctx__ | Must point to a previously initialized `nk_context` struct 659 */ 660 NK_API void nk_clear(struct nk_context*); 661 /*/// #### nk_free 662 /// Frees all memory allocated by nuklear. Not needed if context was 663 /// initialized with `nk_init_fixed`. 664 /// 665 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 666 /// void nk_free(struct nk_context *ctx); 667 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 668 /// 669 /// Parameter | Description 670 /// ------------|----------------------------------------------------------- 671 /// __ctx__ | Must point to a previously initialized `nk_context` struct 672 */ 673 NK_API void nk_free(struct nk_context*); 674 #ifdef NK_INCLUDE_COMMAND_USERDATA 675 /*/// #### nk_set_user_data 676 /// Sets the currently passed userdata passed down into each draw command. 677 /// 678 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 679 /// void nk_set_user_data(struct nk_context *ctx, nk_handle data); 680 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 681 /// 682 /// Parameter | Description 683 /// ------------|-------------------------------------------------------------- 684 /// __ctx__ | Must point to a previously initialized `nk_context` struct 685 /// __data__ | Handle with either pointer or index to be passed into every draw commands 686 */ 687 NK_API void nk_set_user_data(struct nk_context*, nk_handle handle); 688 #endif 689 /* ============================================================================= 690 * 691 * INPUT 692 * 693 * =============================================================================*/ 694 /*/// ### Input 695 /// The input API is responsible for holding the current input state composed of 696 /// mouse, key and text input states. 697 /// It is worth noting that no direct OS or window handling is done in nuklear. 698 /// Instead all input state has to be provided by platform specific code. This on one hand 699 /// expects more work from the user and complicates usage but on the other hand 700 /// provides simple abstraction over a big number of platforms, libraries and other 701 /// already provided functionality. 702 /// 703 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 704 /// nk_input_begin(&ctx); 705 /// while (GetEvent(&evt)) { 706 /// if (evt.type == MOUSE_MOVE) 707 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 708 /// else if (evt.type == [...]) { 709 /// // [...] 710 /// } 711 /// } nk_input_end(&ctx); 712 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 713 /// 714 /// #### Usage 715 /// Input state needs to be provided to nuklear by first calling `nk_input_begin` 716 /// which resets internal state like delta mouse position and button transitions. 717 /// After `nk_input_begin` all current input state needs to be provided. This includes 718 /// mouse motion, button and key pressed and released, text input and scrolling. 719 /// Both event- or state-based input handling are supported by this API 720 /// and should work without problems. Finally after all input state has been 721 /// mirrored `nk_input_end` needs to be called to finish input process. 722 /// 723 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 724 /// struct nk_context ctx; 725 /// nk_init_xxx(&ctx, ...); 726 /// while (1) { 727 /// Event evt; 728 /// nk_input_begin(&ctx); 729 /// while (GetEvent(&evt)) { 730 /// if (evt.type == MOUSE_MOVE) 731 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 732 /// else if (evt.type == [...]) { 733 /// // [...] 734 /// } 735 /// } 736 /// nk_input_end(&ctx); 737 /// // [...] 738 /// nk_clear(&ctx); 739 /// } nk_free(&ctx); 740 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 741 /// 742 /// #### Reference 743 /// Function | Description 744 /// --------------------|------------------------------------------------------- 745 /// __nk_input_begin__ | Begins the input mirroring process. Needs to be called before all other `nk_input_xxx` calls 746 /// __nk_input_motion__ | Mirrors mouse cursor position 747 /// __nk_input_key__ | Mirrors key state with either pressed or released 748 /// __nk_input_button__ | Mirrors mouse button state with either pressed or released 749 /// __nk_input_scroll__ | Mirrors mouse scroll values 750 /// __nk_input_char__ | Adds a single ASCII text character into an internal text buffer 751 /// __nk_input_glyph__ | Adds a single multi-byte UTF-8 character into an internal text buffer 752 /// __nk_input_unicode__| Adds a single unicode rune into an internal text buffer 753 /// __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 754 */ 755 enum nk_keys { 756 NK_KEY_NONE, 757 NK_KEY_SHIFT, 758 NK_KEY_CTRL, 759 NK_KEY_DEL, 760 NK_KEY_ENTER, 761 NK_KEY_TAB, 762 NK_KEY_BACKSPACE, 763 NK_KEY_COPY, 764 NK_KEY_CUT, 765 NK_KEY_PASTE, 766 NK_KEY_UP, 767 NK_KEY_DOWN, 768 NK_KEY_LEFT, 769 NK_KEY_RIGHT, 770 /* Shortcuts: text field */ 771 NK_KEY_TEXT_INSERT_MODE, 772 NK_KEY_TEXT_REPLACE_MODE, 773 NK_KEY_TEXT_RESET_MODE, 774 NK_KEY_TEXT_LINE_START, 775 NK_KEY_TEXT_LINE_END, 776 NK_KEY_TEXT_START, 777 NK_KEY_TEXT_END, 778 NK_KEY_TEXT_UNDO, 779 NK_KEY_TEXT_REDO, 780 NK_KEY_TEXT_SELECT_ALL, 781 NK_KEY_TEXT_WORD_LEFT, 782 NK_KEY_TEXT_WORD_RIGHT, 783 /* Shortcuts: scrollbar */ 784 NK_KEY_SCROLL_START, 785 NK_KEY_SCROLL_END, 786 NK_KEY_SCROLL_DOWN, 787 NK_KEY_SCROLL_UP, 788 NK_KEY_MAX 789 }; 790 enum nk_buttons { 791 NK_BUTTON_LEFT, 792 NK_BUTTON_MIDDLE, 793 NK_BUTTON_RIGHT, 794 NK_BUTTON_DOUBLE, 795 NK_BUTTON_MAX 796 }; 797 /*/// #### nk_input_begin 798 /// Begins the input mirroring process by resetting text, scroll 799 /// mouse, previous mouse position and movement as well as key state transitions, 800 /// 801 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 802 /// void nk_input_begin(struct nk_context*); 803 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 804 /// 805 /// Parameter | Description 806 /// ------------|----------------------------------------------------------- 807 /// __ctx__ | Must point to a previously initialized `nk_context` struct 808 */ 809 NK_API void nk_input_begin(struct nk_context*); 810 /*/// #### nk_input_motion 811 /// Mirrors current mouse position to nuklear 812 /// 813 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 814 /// void nk_input_motion(struct nk_context *ctx, int x, int y); 815 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 816 /// 817 /// Parameter | Description 818 /// ------------|----------------------------------------------------------- 819 /// __ctx__ | Must point to a previously initialized `nk_context` struct 820 /// __x__ | Must hold an integer describing the current mouse cursor x-position 821 /// __y__ | Must hold an integer describing the current mouse cursor y-position 822 */ 823 NK_API void nk_input_motion(struct nk_context*, int x, int y); 824 /*/// #### nk_input_key 825 /// Mirrors the state of a specific key to nuklear 826 /// 827 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 828 /// void nk_input_key(struct nk_context*, enum nk_keys key, nk_bool down); 829 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 830 /// 831 /// Parameter | Description 832 /// ------------|----------------------------------------------------------- 833 /// __ctx__ | Must point to a previously initialized `nk_context` struct 834 /// __key__ | Must be any value specified in enum `nk_keys` that needs to be mirrored 835 /// __down__ | Must be 0 for key is up and 1 for key is down 836 */ 837 NK_API void nk_input_key(struct nk_context*, enum nk_keys, nk_bool down); 838 /*/// #### nk_input_button 839 /// Mirrors the state of a specific mouse button to nuklear 840 /// 841 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 842 /// void nk_input_button(struct nk_context *ctx, enum nk_buttons btn, int x, int y, nk_bool down); 843 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 844 /// 845 /// Parameter | Description 846 /// ------------|----------------------------------------------------------- 847 /// __ctx__ | Must point to a previously initialized `nk_context` struct 848 /// __btn__ | Must be any value specified in enum `nk_buttons` that needs to be mirrored 849 /// __x__ | Must contain an integer describing mouse cursor x-position on click up/down 850 /// __y__ | Must contain an integer describing mouse cursor y-position on click up/down 851 /// __down__ | Must be 0 for key is up and 1 for key is down 852 */ 853 NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, nk_bool down); 854 /*/// #### nk_input_scroll 855 /// Copies the last mouse scroll value to nuklear. Is generally 856 /// a scroll value. So does not have to come from mouse and could also originate 857 /// TODO finish this sentence 858 /// 859 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 860 /// void nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val); 861 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 862 /// 863 /// Parameter | Description 864 /// ------------|----------------------------------------------------------- 865 /// __ctx__ | Must point to a previously initialized `nk_context` struct 866 /// __val__ | vector with both X- as well as Y-scroll value 867 */ 868 NK_API void nk_input_scroll(struct nk_context*, struct nk_vec2 val); 869 /*/// #### nk_input_char 870 /// Copies a single ASCII character into an internal text buffer 871 /// This is basically a helper function to quickly push ASCII characters into 872 /// nuklear. 873 /// 874 /// !!! Note 875 /// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 876 /// 877 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 878 /// void nk_input_char(struct nk_context *ctx, char c); 879 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 880 /// 881 /// Parameter | Description 882 /// ------------|----------------------------------------------------------- 883 /// __ctx__ | Must point to a previously initialized `nk_context` struct 884 /// __c__ | Must be a single ASCII character preferable one that can be printed 885 */ 886 NK_API void nk_input_char(struct nk_context*, char); 887 /*/// #### nk_input_glyph 888 /// Converts an encoded unicode rune into UTF-8 and copies the result into an 889 /// internal text buffer. 890 /// 891 /// !!! Note 892 /// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 893 /// 894 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 895 /// void nk_input_glyph(struct nk_context *ctx, const nk_glyph g); 896 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 897 /// 898 /// Parameter | Description 899 /// ------------|----------------------------------------------------------- 900 /// __ctx__ | Must point to a previously initialized `nk_context` struct 901 /// __g__ | UTF-32 unicode codepoint 902 */ 903 NK_API void nk_input_glyph(struct nk_context*, const nk_glyph); 904 /*/// #### nk_input_unicode 905 /// Converts a unicode rune into UTF-8 and copies the result 906 /// into an internal text buffer. 907 /// !!! Note 908 /// Stores up to NK_INPUT_MAX bytes between `nk_input_begin` and `nk_input_end`. 909 /// 910 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 911 /// void nk_input_unicode(struct nk_context*, nk_rune rune); 912 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 913 /// 914 /// Parameter | Description 915 /// ------------|----------------------------------------------------------- 916 /// __ctx__ | Must point to a previously initialized `nk_context` struct 917 /// __rune__ | UTF-32 unicode codepoint 918 */ 919 NK_API void nk_input_unicode(struct nk_context*, nk_rune); 920 /*/// #### nk_input_end 921 /// End the input mirroring process by resetting mouse grabbing 922 /// state to ensure the mouse cursor is not grabbed indefinitely. 923 /// 924 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 925 /// void nk_input_end(struct nk_context *ctx); 926 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 927 /// 928 /// Parameter | Description 929 /// ------------|----------------------------------------------------------- 930 /// __ctx__ | Must point to a previously initialized `nk_context` struct 931 */ 932 NK_API void nk_input_end(struct nk_context*); 933 /* ============================================================================= 934 * 935 * DRAWING 936 * 937 * =============================================================================*/ 938 /*/// ### Drawing 939 /// This library was designed to be render backend agnostic so it does 940 /// not draw anything to screen directly. Instead all drawn shapes, widgets 941 /// are made of, are buffered into memory and make up a command queue. 942 /// Each frame therefore fills the command buffer with draw commands 943 /// that then need to be executed by the user and his own render backend. 944 /// After that the command buffer needs to be cleared and a new frame can be 945 /// started. It is probably important to note that the command buffer is the main 946 /// drawing API and the optional vertex buffer API only takes this format and 947 /// converts it into a hardware accessible format. 948 /// 949 /// #### Usage 950 /// To draw all draw commands accumulated over a frame you need your own render 951 /// backend able to draw a number of 2D primitives. This includes at least 952 /// filled and stroked rectangles, circles, text, lines, triangles and scissors. 953 /// As soon as this criterion is met you can iterate over each draw command 954 /// and execute each draw command in a interpreter like fashion: 955 /// 956 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 957 /// const struct nk_command *cmd = 0; 958 /// nk_foreach(cmd, &ctx) { 959 /// switch (cmd->type) { 960 /// case NK_COMMAND_LINE: 961 /// your_draw_line_function(...) 962 /// break; 963 /// case NK_COMMAND_RECT 964 /// your_draw_rect_function(...) 965 /// break; 966 /// case //...: 967 /// //[...] 968 /// } 969 /// } 970 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 971 /// 972 /// In program flow context draw commands need to be executed after input has been 973 /// gathered and the complete UI with windows and their contained widgets have 974 /// been executed and before calling `nk_clear` which frees all previously 975 /// allocated draw commands. 976 /// 977 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 978 /// struct nk_context ctx; 979 /// nk_init_xxx(&ctx, ...); 980 /// while (1) { 981 /// Event evt; 982 /// nk_input_begin(&ctx); 983 /// while (GetEvent(&evt)) { 984 /// if (evt.type == MOUSE_MOVE) 985 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 986 /// else if (evt.type == [...]) { 987 /// [...] 988 /// } 989 /// } 990 /// nk_input_end(&ctx); 991 /// // 992 /// // [...] 993 /// // 994 /// const struct nk_command *cmd = 0; 995 /// nk_foreach(cmd, &ctx) { 996 /// switch (cmd->type) { 997 /// case NK_COMMAND_LINE: 998 /// your_draw_line_function(...) 999 /// break; 1000 /// case NK_COMMAND_RECT 1001 /// your_draw_rect_function(...) 1002 /// break; 1003 /// case ...: 1004 /// // [...] 1005 /// } 1006 /// nk_clear(&ctx); 1007 /// } 1008 /// nk_free(&ctx); 1009 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1010 /// 1011 /// You probably noticed that you have to draw all of the UI each frame which is 1012 /// quite wasteful. While the actual UI updating loop is quite fast rendering 1013 /// without actually needing it is not. So there are multiple things you could do. 1014 /// 1015 /// First is only update on input. This of course is only an option if your 1016 /// application only depends on the UI and does not require any outside calculations. 1017 /// If you actually only update on input make sure to update the UI two times each 1018 /// frame and call `nk_clear` directly after the first pass and only draw in 1019 /// the second pass. In addition it is recommended to also add additional timers 1020 /// to make sure the UI is not drawn more than a fixed number of frames per second. 1021 /// 1022 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1023 /// struct nk_context ctx; 1024 /// nk_init_xxx(&ctx, ...); 1025 /// while (1) { 1026 /// // [...wait for input ] 1027 /// // [...do two UI passes ...] 1028 /// do_ui(...) 1029 /// nk_clear(&ctx); 1030 /// do_ui(...) 1031 /// // 1032 /// // draw 1033 /// const struct nk_command *cmd = 0; 1034 /// nk_foreach(cmd, &ctx) { 1035 /// switch (cmd->type) { 1036 /// case NK_COMMAND_LINE: 1037 /// your_draw_line_function(...) 1038 /// break; 1039 /// case NK_COMMAND_RECT 1040 /// your_draw_rect_function(...) 1041 /// break; 1042 /// case ...: 1043 /// //[...] 1044 /// } 1045 /// nk_clear(&ctx); 1046 /// } 1047 /// nk_free(&ctx); 1048 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1049 /// 1050 /// The second probably more applicable trick is to only draw if anything changed. 1051 /// It is not really useful for applications with continuous draw loop but 1052 /// quite useful for desktop applications. To actually get nuklear to only 1053 /// draw on changes you first have to define `NK_ZERO_COMMAND_MEMORY` and 1054 /// allocate a memory buffer that will store each unique drawing output. 1055 /// After each frame you compare the draw command memory inside the library 1056 /// with your allocated buffer by memcmp. If memcmp detects differences 1057 /// you have to copy the command buffer into the allocated buffer 1058 /// and then draw like usual (this example uses fixed memory but you could 1059 /// use dynamically allocated memory). 1060 /// 1061 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1062 /// //[... other defines ...] 1063 /// #define NK_ZERO_COMMAND_MEMORY 1064 /// #include "nuklear.h" 1065 /// // 1066 /// // setup context 1067 /// struct nk_context ctx; 1068 /// void *last = calloc(1,64*1024); 1069 /// void *buf = calloc(1,64*1024); 1070 /// nk_init_fixed(&ctx, buf, 64*1024); 1071 /// // 1072 /// // loop 1073 /// while (1) { 1074 /// // [...input...] 1075 /// // [...ui...] 1076 /// void *cmds = nk_buffer_memory(&ctx.memory); 1077 /// if (memcmp(cmds, last, ctx.memory.allocated)) { 1078 /// memcpy(last,cmds,ctx.memory.allocated); 1079 /// const struct nk_command *cmd = 0; 1080 /// nk_foreach(cmd, &ctx) { 1081 /// switch (cmd->type) { 1082 /// case NK_COMMAND_LINE: 1083 /// your_draw_line_function(...) 1084 /// break; 1085 /// case NK_COMMAND_RECT 1086 /// your_draw_rect_function(...) 1087 /// break; 1088 /// case ...: 1089 /// // [...] 1090 /// } 1091 /// } 1092 /// } 1093 /// nk_clear(&ctx); 1094 /// } 1095 /// nk_free(&ctx); 1096 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1097 /// 1098 /// Finally while using draw commands makes sense for higher abstracted platforms like 1099 /// X11 and Win32 or drawing libraries it is often desirable to use graphics 1100 /// hardware directly. Therefore it is possible to just define 1101 /// `NK_INCLUDE_VERTEX_BUFFER_OUTPUT` which includes optional vertex output. 1102 /// To access the vertex output you first have to convert all draw commands into 1103 /// vertexes by calling `nk_convert` which takes in your preferred vertex format. 1104 /// After successfully converting all draw commands just iterate over and execute all 1105 /// vertex draw commands: 1106 /// 1107 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1108 /// // fill configuration 1109 /// struct your_vertex 1110 /// { 1111 /// float pos[2]; // important to keep it to 2 floats 1112 /// float uv[2]; 1113 /// unsigned char col[4]; 1114 /// }; 1115 /// struct nk_convert_config cfg = {}; 1116 /// static const struct nk_draw_vertex_layout_element vertex_layout[] = { 1117 /// {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, pos)}, 1118 /// {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct your_vertex, uv)}, 1119 /// {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct your_vertex, col)}, 1120 /// {NK_VERTEX_LAYOUT_END} 1121 /// }; 1122 /// cfg.shape_AA = NK_ANTI_ALIASING_ON; 1123 /// cfg.line_AA = NK_ANTI_ALIASING_ON; 1124 /// cfg.vertex_layout = vertex_layout; 1125 /// cfg.vertex_size = sizeof(struct your_vertex); 1126 /// cfg.vertex_alignment = NK_ALIGNOF(struct your_vertex); 1127 /// cfg.circle_segment_count = 22; 1128 /// cfg.curve_segment_count = 22; 1129 /// cfg.arc_segment_count = 22; 1130 /// cfg.global_alpha = 1.0f; 1131 /// cfg.tex_null = dev->tex_null; 1132 /// // 1133 /// // setup buffers and convert 1134 /// struct nk_buffer cmds, verts, idx; 1135 /// nk_buffer_init_default(&cmds); 1136 /// nk_buffer_init_default(&verts); 1137 /// nk_buffer_init_default(&idx); 1138 /// nk_convert(&ctx, &cmds, &verts, &idx, &cfg); 1139 /// // 1140 /// // draw 1141 /// nk_draw_foreach(cmd, &ctx, &cmds) { 1142 /// if (!cmd->elem_count) continue; 1143 /// //[...] 1144 /// } 1145 /// nk_buffer_free(&cms); 1146 /// nk_buffer_free(&verts); 1147 /// nk_buffer_free(&idx); 1148 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1149 /// 1150 /// #### Reference 1151 /// Function | Description 1152 /// --------------------|------------------------------------------------------- 1153 /// __nk__begin__ | Returns the first draw command in the context draw command list to be drawn 1154 /// __nk__next__ | Increments the draw command iterator to the next command inside the context draw command list 1155 /// __nk_foreach__ | Iterates over each draw command inside the context draw command list 1156 /// __nk_convert__ | Converts from the abstract draw commands list into a hardware accessible vertex format 1157 /// __nk_draw_begin__ | Returns the first vertex command in the context vertex draw list to be executed 1158 /// __nk__draw_next__ | Increments the vertex command iterator to the next command inside the context vertex command list 1159 /// __nk__draw_end__ | Returns the end of the vertex draw list 1160 /// __nk_draw_foreach__ | Iterates over each vertex draw command inside the vertex draw list 1161 */ 1162 enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON}; 1163 enum nk_convert_result { 1164 NK_CONVERT_SUCCESS = 0, 1165 NK_CONVERT_INVALID_PARAM = 1, 1166 NK_CONVERT_COMMAND_BUFFER_FULL = NK_FLAG(1), 1167 NK_CONVERT_VERTEX_BUFFER_FULL = NK_FLAG(2), 1168 NK_CONVERT_ELEMENT_BUFFER_FULL = NK_FLAG(3) 1169 }; 1170 struct nk_draw_null_texture { 1171 nk_handle texture; /* texture handle to a texture with a white pixel */ 1172 struct nk_vec2 uv; /* coordinates to a white pixel in the texture */ 1173 }; 1174 struct nk_convert_config { 1175 float global_alpha; /* global alpha value */ 1176 enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */ 1177 enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */ 1178 unsigned circle_segment_count; /* number of segments used for circles: default to 22 */ 1179 unsigned arc_segment_count; /* number of segments used for arcs: default to 22 */ 1180 unsigned curve_segment_count; /* number of segments used for curves: default to 22 */ 1181 struct nk_draw_null_texture tex_null; /* handle to texture with a white pixel for shape drawing */ 1182 const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */ 1183 nk_size vertex_size; /* sizeof one vertex for vertex packing */ 1184 nk_size vertex_alignment; /* vertex alignment: Can be obtained by NK_ALIGNOF */ 1185 }; 1186 /*/// #### nk__begin 1187 /// Returns a draw command list iterator to iterate all draw 1188 /// commands accumulated over one frame. 1189 /// 1190 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1191 /// const struct nk_command* nk__begin(struct nk_context*); 1192 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1193 /// 1194 /// Parameter | Description 1195 /// ------------|----------------------------------------------------------- 1196 /// __ctx__ | must point to an previously initialized `nk_context` struct at the end of a frame 1197 /// 1198 /// Returns draw command pointer pointing to the first command inside the draw command list 1199 */ 1200 NK_API const struct nk_command* nk__begin(struct nk_context*); 1201 /*/// #### nk__next 1202 /// Returns draw command pointer pointing to the next command inside the draw command list 1203 /// 1204 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1205 /// const struct nk_command* nk__next(struct nk_context*, const struct nk_command*); 1206 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1207 /// 1208 /// Parameter | Description 1209 /// ------------|----------------------------------------------------------- 1210 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1211 /// __cmd__ | Must point to an previously a draw command either returned by `nk__begin` or `nk__next` 1212 /// 1213 /// Returns draw command pointer pointing to the next command inside the draw command list 1214 */ 1215 NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*); 1216 /*/// #### nk_foreach 1217 /// Iterates over each draw command inside the context draw command list 1218 /// 1219 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1220 /// #define nk_foreach(c, ctx) 1221 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1222 /// 1223 /// Parameter | Description 1224 /// ------------|----------------------------------------------------------- 1225 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1226 /// __cmd__ | Command pointer initialized to NULL 1227 /// 1228 /// Iterates over each draw command inside the context draw command list 1229 */ 1230 #define nk_foreach(c, ctx) for((c) = nk__begin(ctx); (c) != 0; (c) = nk__next(ctx,c)) 1231 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 1232 /*/// #### nk_convert 1233 /// Converts all internal draw commands into vertex draw commands and fills 1234 /// three buffers with vertexes, vertex draw commands and vertex indices. The vertex format 1235 /// as well as some other configuration values have to be configured by filling out a 1236 /// `nk_convert_config` struct. 1237 /// 1238 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1239 /// nk_flags nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, 1240 /// struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*); 1241 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1242 /// 1243 /// Parameter | Description 1244 /// ------------|----------------------------------------------------------- 1245 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1246 /// __cmds__ | Must point to a previously initialized buffer to hold converted vertex draw commands 1247 /// __vertices__| Must point to a previously initialized buffer to hold all produced vertices 1248 /// __elements__| Must point to a previously initialized buffer to hold all produced vertex indices 1249 /// __config__ | Must point to a filled out `nk_config` struct to configure the conversion process 1250 /// 1251 /// Returns one of enum nk_convert_result error codes 1252 /// 1253 /// Parameter | Description 1254 /// --------------------------------|----------------------------------------------------------- 1255 /// NK_CONVERT_SUCCESS | Signals a successful draw command to vertex buffer conversion 1256 /// NK_CONVERT_INVALID_PARAM | An invalid argument was passed in the function call 1257 /// NK_CONVERT_COMMAND_BUFFER_FULL | The provided buffer for storing draw commands is full or failed to allocate more memory 1258 /// NK_CONVERT_VERTEX_BUFFER_FULL | The provided buffer for storing vertices is full or failed to allocate more memory 1259 /// NK_CONVERT_ELEMENT_BUFFER_FULL | The provided buffer for storing indices is full or failed to allocate more memory 1260 */ 1261 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*); 1262 /*/// #### nk__draw_begin 1263 /// Returns a draw vertex command buffer iterator to iterate over the vertex draw command buffer 1264 /// 1265 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1266 /// const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*); 1267 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1268 /// 1269 /// Parameter | Description 1270 /// ------------|----------------------------------------------------------- 1271 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1272 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1273 /// 1274 /// Returns vertex draw command pointer pointing to the first command inside the vertex draw command buffer 1275 */ 1276 NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*); 1277 /*/// #### nk__draw_end 1278 /// Returns the vertex draw command at the end of the vertex draw command buffer 1279 /// 1280 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1281 /// const struct nk_draw_command* nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buf); 1282 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1283 /// 1284 /// Parameter | Description 1285 /// ------------|----------------------------------------------------------- 1286 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1287 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1288 /// 1289 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer 1290 */ 1291 NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*); 1292 /*/// #### nk__draw_next 1293 /// Increments the vertex draw command buffer iterator 1294 /// 1295 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1296 /// const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*); 1297 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1298 /// 1299 /// Parameter | Description 1300 /// ------------|----------------------------------------------------------- 1301 /// __cmd__ | Must point to an previously either by `nk__draw_begin` or `nk__draw_next` returned vertex draw command 1302 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1303 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1304 /// 1305 /// Returns vertex draw command pointer pointing to the end of the last vertex draw command inside the vertex draw command buffer 1306 */ 1307 NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*); 1308 /*/// #### nk_draw_foreach 1309 /// Iterates over each vertex draw command inside a vertex draw command buffer 1310 /// 1311 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1312 /// #define nk_draw_foreach(cmd,ctx, b) 1313 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1314 /// 1315 /// Parameter | Description 1316 /// ------------|----------------------------------------------------------- 1317 /// __cmd__ | `nk_draw_command`iterator set to NULL 1318 /// __buf__ | Must point to an previously by `nk_convert` filled out vertex draw command buffer 1319 /// __ctx__ | Must point to an previously initialized `nk_context` struct at the end of a frame 1320 */ 1321 #define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx)) 1322 #endif 1323 /* ============================================================================= 1324 * 1325 * WINDOW 1326 * 1327 * ============================================================================= 1328 /// ### Window 1329 /// Windows are the main persistent state used inside nuklear and are life time 1330 /// controlled by simply "retouching" (i.e. calling) each window each frame. 1331 /// All widgets inside nuklear can only be added inside the function pair `nk_begin_xxx` 1332 /// and `nk_end`. Calling any widgets outside these two functions will result in an 1333 /// assert in debug or no state change in release mode.<br /><br /> 1334 /// 1335 /// Each window holds frame persistent state like position, size, flags, state tables, 1336 /// and some garbage collected internal persistent widget state. Each window 1337 /// is linked into a window stack list which determines the drawing and overlapping 1338 /// order. The topmost window thereby is the currently active window.<br /><br /> 1339 /// 1340 /// To change window position inside the stack occurs either automatically by 1341 /// user input by being clicked on or programmatically by calling `nk_window_focus`. 1342 /// Windows by default are visible unless explicitly being defined with flag 1343 /// `NK_WINDOW_HIDDEN`, the user clicked the close button on windows with flag 1344 /// `NK_WINDOW_CLOSABLE` or if a window was explicitly hidden by calling 1345 /// `nk_window_show`. To explicitly close and destroy a window call `nk_window_close`.<br /><br /> 1346 /// 1347 /// #### Usage 1348 /// To create and keep a window you have to call one of the two `nk_begin_xxx` 1349 /// functions to start window declarations and `nk_end` at the end. Furthermore it 1350 /// is recommended to check the return value of `nk_begin_xxx` and only process 1351 /// widgets inside the window if the value is not 0. Either way you have to call 1352 /// `nk_end` at the end of window declarations. Furthermore, do not attempt to 1353 /// nest `nk_begin_xxx` calls which will hopefully result in an assert or if not 1354 /// in a segmentation fault. 1355 /// 1356 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1357 /// if (nk_begin_xxx(...) { 1358 /// // [... widgets ...] 1359 /// } 1360 /// nk_end(ctx); 1361 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1362 /// 1363 /// In the grand concept window and widget declarations need to occur after input 1364 /// handling and before drawing to screen. Not doing so can result in higher 1365 /// latency or at worst invalid behavior. Furthermore make sure that `nk_clear` 1366 /// is called at the end of the frame. While nuklear's default platform backends 1367 /// already call `nk_clear` for you if you write your own backend not calling 1368 /// `nk_clear` can cause asserts or even worse undefined behavior. 1369 /// 1370 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1371 /// struct nk_context ctx; 1372 /// nk_init_xxx(&ctx, ...); 1373 /// while (1) { 1374 /// Event evt; 1375 /// nk_input_begin(&ctx); 1376 /// while (GetEvent(&evt)) { 1377 /// if (evt.type == MOUSE_MOVE) 1378 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 1379 /// else if (evt.type == [...]) { 1380 /// nk_input_xxx(...); 1381 /// } 1382 /// } 1383 /// nk_input_end(&ctx); 1384 /// 1385 /// if (nk_begin_xxx(...) { 1386 /// //[...] 1387 /// } 1388 /// nk_end(ctx); 1389 /// 1390 /// const struct nk_command *cmd = 0; 1391 /// nk_foreach(cmd, &ctx) { 1392 /// case NK_COMMAND_LINE: 1393 /// your_draw_line_function(...) 1394 /// break; 1395 /// case NK_COMMAND_RECT 1396 /// your_draw_rect_function(...) 1397 /// break; 1398 /// case //...: 1399 /// //[...] 1400 /// } 1401 /// nk_clear(&ctx); 1402 /// } 1403 /// nk_free(&ctx); 1404 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1405 /// 1406 /// #### Reference 1407 /// Function | Description 1408 /// ------------------------------------|---------------------------------------- 1409 /// nk_begin | Starts a new window; needs to be called every frame for every window (unless hidden) or otherwise the window gets removed 1410 /// nk_begin_titled | Extended window start with separated title and identifier to allow multiple windows with same name but not title 1411 /// nk_end | Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup 1412 // 1413 /// nk_window_find | Finds and returns the window with give name 1414 /// nk_window_get_bounds | Returns a rectangle with screen position and size of the currently processed window. 1415 /// nk_window_get_position | Returns the position of the currently processed window 1416 /// nk_window_get_size | Returns the size with width and height of the currently processed window 1417 /// nk_window_get_width | Returns the width of the currently processed window 1418 /// nk_window_get_height | Returns the height of the currently processed window 1419 /// nk_window_get_panel | Returns the underlying panel which contains all processing state of the current window 1420 /// nk_window_get_content_region | Returns the position and size of the currently visible and non-clipped space inside the currently processed window 1421 /// nk_window_get_content_region_min | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window 1422 /// nk_window_get_content_region_max | Returns the upper rectangle position of the currently visible and non-clipped space inside the currently processed window 1423 /// nk_window_get_content_region_size | Returns the size of the currently visible and non-clipped space inside the currently processed window 1424 /// nk_window_get_canvas | Returns the draw command buffer. Can be used to draw custom widgets 1425 /// nk_window_get_scroll | Gets the scroll offset of the current window 1426 /// nk_window_has_focus | Returns if the currently processed window is currently active 1427 /// nk_window_is_collapsed | Returns if the window with given name is currently minimized/collapsed 1428 /// nk_window_is_closed | Returns if the currently processed window was closed 1429 /// nk_window_is_hidden | Returns if the currently processed window was hidden 1430 /// nk_window_is_active | Same as nk_window_has_focus for some reason 1431 /// nk_window_is_hovered | Returns if the currently processed window is currently being hovered by mouse 1432 /// nk_window_is_any_hovered | Return if any window currently hovered 1433 /// nk_item_is_any_active | Returns if any window or widgets is currently hovered or active 1434 // 1435 /// nk_window_set_bounds | Updates position and size of the currently processed window 1436 /// nk_window_set_position | Updates position of the currently process window 1437 /// nk_window_set_size | Updates the size of the currently processed window 1438 /// nk_window_set_focus | Set the currently processed window as active window 1439 /// nk_window_set_scroll | Sets the scroll offset of the current window 1440 // 1441 /// nk_window_close | Closes the window with given window name which deletes the window at the end of the frame 1442 /// nk_window_collapse | Collapses the window with given window name 1443 /// nk_window_collapse_if | Collapses the window with given window name if the given condition was met 1444 /// nk_window_show | Hides a visible or reshows a hidden window 1445 /// nk_window_show_if | Hides/shows a window depending on condition 1446 */ 1447 /* 1448 /// #### nk_panel_flags 1449 /// Flag | Description 1450 /// ----------------------------|---------------------------------------- 1451 /// NK_WINDOW_BORDER | Draws a border around the window to visually separate window from the background 1452 /// NK_WINDOW_MOVABLE | The movable flag indicates that a window can be moved by user input or by dragging the window header 1453 /// NK_WINDOW_SCALABLE | The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window 1454 /// NK_WINDOW_CLOSABLE | Adds a closable icon into the header 1455 /// NK_WINDOW_MINIMIZABLE | Adds a minimize icon into the header 1456 /// NK_WINDOW_NO_SCROLLBAR | Removes the scrollbar from the window 1457 /// NK_WINDOW_TITLE | Forces a header at the top at the window showing the title 1458 /// NK_WINDOW_SCROLL_AUTO_HIDE | Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame 1459 /// NK_WINDOW_BACKGROUND | Always keep window in the background 1460 /// NK_WINDOW_SCALE_LEFT | Puts window scaler in the left-bottom corner instead right-bottom 1461 /// NK_WINDOW_NO_INPUT | Prevents window of scaling, moving or getting focus 1462 /// 1463 /// #### nk_collapse_states 1464 /// State | Description 1465 /// ----------------|----------------------------------------------------------- 1466 /// __NK_MINIMIZED__| UI section is collased and not visible until maximized 1467 /// __NK_MAXIMIZED__| UI section is extended and visible until minimized 1468 /// <br /><br /> 1469 */ 1470 enum nk_panel_flags { 1471 NK_WINDOW_BORDER = NK_FLAG(0), 1472 NK_WINDOW_MOVABLE = NK_FLAG(1), 1473 NK_WINDOW_SCALABLE = NK_FLAG(2), 1474 NK_WINDOW_CLOSABLE = NK_FLAG(3), 1475 NK_WINDOW_MINIMIZABLE = NK_FLAG(4), 1476 NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5), 1477 NK_WINDOW_TITLE = NK_FLAG(6), 1478 NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7), 1479 NK_WINDOW_BACKGROUND = NK_FLAG(8), 1480 NK_WINDOW_SCALE_LEFT = NK_FLAG(9), 1481 NK_WINDOW_NO_INPUT = NK_FLAG(10) 1482 }; 1483 /*/// #### nk_begin 1484 /// Starts a new window; needs to be called every frame for every 1485 /// window (unless hidden) or otherwise the window gets removed 1486 /// 1487 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1488 /// nk_bool nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags); 1489 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1490 /// 1491 /// Parameter | Description 1492 /// ------------|----------------------------------------------------------- 1493 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1494 /// __title__ | Window title and identifier. Needs to be persistent over frames to identify the window 1495 /// __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 1496 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different window behaviors 1497 /// 1498 /// Returns `true(1)` if the window can be filled up with widgets from this point 1499 /// until `nk_end` or `false(0)` otherwise for example if minimized 1500 */ 1501 NK_API nk_bool nk_begin(struct nk_context *ctx, const char *title, struct nk_rect bounds, nk_flags flags); 1502 /*/// #### nk_begin_titled 1503 /// Extended window start with separated title and identifier to allow multiple 1504 /// windows with same title but not name 1505 /// 1506 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1507 /// nk_bool nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags); 1508 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1509 /// 1510 /// Parameter | Description 1511 /// ------------|----------------------------------------------------------- 1512 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1513 /// __name__ | Window identifier. Needs to be persistent over frames to identify the window 1514 /// __title__ | Window title displayed inside header if flag `NK_WINDOW_TITLE` or either `NK_WINDOW_CLOSABLE` or `NK_WINDOW_MINIMIZED` was set 1515 /// __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 1516 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different window behaviors 1517 /// 1518 /// Returns `true(1)` if the window can be filled up with widgets from this point 1519 /// until `nk_end` or `false(0)` otherwise for example if minimized 1520 */ 1521 NK_API nk_bool nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, struct nk_rect bounds, nk_flags flags); 1522 /*/// #### nk_end 1523 /// Needs to be called at the end of the window building process to process scaling, scrollbars and general cleanup. 1524 /// All widget calls after this functions will result in asserts or no state changes 1525 /// 1526 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1527 /// void nk_end(struct nk_context *ctx); 1528 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1529 /// 1530 /// Parameter | Description 1531 /// ------------|----------------------------------------------------------- 1532 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1533 */ 1534 NK_API void nk_end(struct nk_context *ctx); 1535 /*/// #### nk_window_find 1536 /// Finds and returns a window from passed name 1537 /// 1538 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1539 /// struct nk_window *nk_window_find(struct nk_context *ctx, const char *name); 1540 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1541 /// 1542 /// Parameter | Description 1543 /// ------------|----------------------------------------------------------- 1544 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1545 /// __name__ | Window identifier 1546 /// 1547 /// Returns a `nk_window` struct pointing to the identified window or NULL if 1548 /// no window with the given name was found 1549 */ 1550 NK_API struct nk_window *nk_window_find(struct nk_context *ctx, const char *name); 1551 /*/// #### nk_window_get_bounds 1552 /// Returns a rectangle with screen position and size of the currently processed window 1553 /// 1554 /// !!! WARNING 1555 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1556 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1557 /// struct nk_rect nk_window_get_bounds(const struct nk_context *ctx); 1558 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1559 /// 1560 /// Parameter | Description 1561 /// ------------|----------------------------------------------------------- 1562 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1563 /// 1564 /// Returns a `nk_rect` struct with window upper left window position and size 1565 */ 1566 NK_API struct nk_rect nk_window_get_bounds(const struct nk_context *ctx); 1567 /*/// #### nk_window_get_position 1568 /// Returns the position of the currently processed window. 1569 /// 1570 /// !!! WARNING 1571 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1572 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1573 /// struct nk_vec2 nk_window_get_position(const struct nk_context *ctx); 1574 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1575 /// 1576 /// Parameter | Description 1577 /// ------------|----------------------------------------------------------- 1578 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1579 /// 1580 /// Returns a `nk_vec2` struct with window upper left position 1581 */ 1582 NK_API struct nk_vec2 nk_window_get_position(const struct nk_context *ctx); 1583 /*/// #### nk_window_get_size 1584 /// Returns the size with width and height of the currently processed window. 1585 /// 1586 /// !!! WARNING 1587 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1588 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1589 /// struct nk_vec2 nk_window_get_size(const struct nk_context *ctx); 1590 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1591 /// 1592 /// Parameter | Description 1593 /// ------------|----------------------------------------------------------- 1594 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1595 /// 1596 /// Returns a `nk_vec2` struct with window width and height 1597 */ 1598 NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*); 1599 /*/// #### nk_window_get_width 1600 /// Returns the width of the currently processed window. 1601 /// 1602 /// !!! WARNING 1603 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1604 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1605 /// float nk_window_get_width(const struct nk_context *ctx); 1606 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1607 /// 1608 /// Parameter | Description 1609 /// ------------|----------------------------------------------------------- 1610 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1611 /// 1612 /// Returns the current window width 1613 */ 1614 NK_API float nk_window_get_width(const struct nk_context*); 1615 /*/// #### nk_window_get_height 1616 /// Returns the height of the currently processed window. 1617 /// 1618 /// !!! WARNING 1619 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1620 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1621 /// float nk_window_get_height(const struct nk_context *ctx); 1622 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1623 /// 1624 /// Parameter | Description 1625 /// ------------|----------------------------------------------------------- 1626 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1627 /// 1628 /// Returns the current window height 1629 */ 1630 NK_API float nk_window_get_height(const struct nk_context*); 1631 /*/// #### nk_window_get_panel 1632 /// Returns the underlying panel which contains all processing state of the current window. 1633 /// 1634 /// !!! WARNING 1635 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1636 /// !!! WARNING 1637 /// Do not keep the returned panel pointer around, it is only valid until `nk_end` 1638 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1639 /// struct nk_panel* nk_window_get_panel(struct nk_context *ctx); 1640 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1641 /// 1642 /// Parameter | Description 1643 /// ------------|----------------------------------------------------------- 1644 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1645 /// 1646 /// Returns a pointer to window internal `nk_panel` state. 1647 */ 1648 NK_API struct nk_panel* nk_window_get_panel(struct nk_context*); 1649 /*/// #### nk_window_get_content_region 1650 /// Returns the position and size of the currently visible and non-clipped space 1651 /// inside the currently processed window. 1652 /// 1653 /// !!! WARNING 1654 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1655 /// 1656 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1657 /// struct nk_rect nk_window_get_content_region(struct nk_context *ctx); 1658 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1659 /// 1660 /// Parameter | Description 1661 /// ------------|----------------------------------------------------------- 1662 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1663 /// 1664 /// Returns `nk_rect` struct with screen position and size (no scrollbar offset) 1665 /// of the visible space inside the current window 1666 */ 1667 NK_API struct nk_rect nk_window_get_content_region(struct nk_context*); 1668 /*/// #### nk_window_get_content_region_min 1669 /// Returns the upper left position of the currently visible and non-clipped 1670 /// space inside the currently processed window. 1671 /// 1672 /// !!! WARNING 1673 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1674 /// 1675 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1676 /// struct nk_vec2 nk_window_get_content_region_min(struct nk_context *ctx); 1677 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1678 /// 1679 /// Parameter | Description 1680 /// ------------|----------------------------------------------------------- 1681 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1682 /// 1683 /// returns `nk_vec2` struct with upper left screen position (no scrollbar offset) 1684 /// of the visible space inside the current window 1685 */ 1686 NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*); 1687 /*/// #### nk_window_get_content_region_max 1688 /// Returns the lower right screen position of the currently visible and 1689 /// non-clipped space inside the currently processed window. 1690 /// 1691 /// !!! WARNING 1692 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1693 /// 1694 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1695 /// struct nk_vec2 nk_window_get_content_region_max(struct nk_context *ctx); 1696 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1697 /// 1698 /// Parameter | Description 1699 /// ------------|----------------------------------------------------------- 1700 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1701 /// 1702 /// Returns `nk_vec2` struct with lower right screen position (no scrollbar offset) 1703 /// of the visible space inside the current window 1704 */ 1705 NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*); 1706 /*/// #### nk_window_get_content_region_size 1707 /// Returns the size of the currently visible and non-clipped space inside the 1708 /// currently processed window 1709 /// 1710 /// !!! WARNING 1711 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1712 /// 1713 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1714 /// struct nk_vec2 nk_window_get_content_region_size(struct nk_context *ctx); 1715 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1716 /// 1717 /// Parameter | Description 1718 /// ------------|----------------------------------------------------------- 1719 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1720 /// 1721 /// Returns `nk_vec2` struct with size the visible space inside the current window 1722 */ 1723 NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*); 1724 /*/// #### nk_window_get_canvas 1725 /// Returns the draw command buffer. Can be used to draw custom widgets 1726 /// !!! WARNING 1727 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1728 /// !!! WARNING 1729 /// Do not keep the returned command buffer pointer around it is only valid until `nk_end` 1730 /// 1731 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1732 /// struct nk_command_buffer* nk_window_get_canvas(struct nk_context *ctx); 1733 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1734 /// 1735 /// Parameter | Description 1736 /// ------------|----------------------------------------------------------- 1737 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1738 /// 1739 /// Returns a pointer to window internal `nk_command_buffer` struct used as 1740 /// drawing canvas. Can be used to do custom drawing. 1741 */ 1742 NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*); 1743 /*/// #### nk_window_get_scroll 1744 /// Gets the scroll offset for the current window 1745 /// !!! WARNING 1746 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1747 /// 1748 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1749 /// void nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y); 1750 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1751 /// 1752 /// Parameter | Description 1753 /// -------------|----------------------------------------------------------- 1754 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1755 /// __offset_x__ | A pointer to the x offset output (or NULL to ignore) 1756 /// __offset_y__ | A pointer to the y offset output (or NULL to ignore) 1757 */ 1758 NK_API void nk_window_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y); 1759 /*/// #### nk_window_has_focus 1760 /// Returns if the currently processed window is currently active 1761 /// !!! WARNING 1762 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1763 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1764 /// nk_bool nk_window_has_focus(const struct nk_context *ctx); 1765 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1766 /// 1767 /// Parameter | Description 1768 /// ------------|----------------------------------------------------------- 1769 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1770 /// 1771 /// Returns `false(0)` if current window is not active or `true(1)` if it is 1772 */ 1773 NK_API nk_bool nk_window_has_focus(const struct nk_context*); 1774 /*/// #### nk_window_is_hovered 1775 /// Return if the current window is being hovered 1776 /// !!! WARNING 1777 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1778 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1779 /// nk_bool nk_window_is_hovered(struct nk_context *ctx); 1780 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1781 /// 1782 /// Parameter | Description 1783 /// ------------|----------------------------------------------------------- 1784 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1785 /// 1786 /// Returns `true(1)` if current window is hovered or `false(0)` otherwise 1787 */ 1788 NK_API nk_bool nk_window_is_hovered(struct nk_context*); 1789 /*/// #### nk_window_is_collapsed 1790 /// Returns if the window with given name is currently minimized/collapsed 1791 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1792 /// nk_bool nk_window_is_collapsed(struct nk_context *ctx, const char *name); 1793 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1794 /// 1795 /// Parameter | Description 1796 /// ------------|----------------------------------------------------------- 1797 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1798 /// __name__ | Identifier of window you want to check if it is collapsed 1799 /// 1800 /// Returns `true(1)` if current window is minimized and `false(0)` if window not 1801 /// found or is not minimized 1802 */ 1803 NK_API nk_bool nk_window_is_collapsed(struct nk_context *ctx, const char *name); 1804 /*/// #### nk_window_is_closed 1805 /// Returns if the window with given name was closed by calling `nk_close` 1806 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1807 /// nk_bool nk_window_is_closed(struct nk_context *ctx, const char *name); 1808 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1809 /// 1810 /// Parameter | Description 1811 /// ------------|----------------------------------------------------------- 1812 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1813 /// __name__ | Identifier of window you want to check if it is closed 1814 /// 1815 /// Returns `true(1)` if current window was closed or `false(0)` window not found or not closed 1816 */ 1817 NK_API nk_bool nk_window_is_closed(struct nk_context*, const char*); 1818 /*/// #### nk_window_is_hidden 1819 /// Returns if the window with given name is hidden 1820 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1821 /// nk_bool nk_window_is_hidden(struct nk_context *ctx, const char *name); 1822 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1823 /// 1824 /// Parameter | Description 1825 /// ------------|----------------------------------------------------------- 1826 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1827 /// __name__ | Identifier of window you want to check if it is hidden 1828 /// 1829 /// Returns `true(1)` if current window is hidden or `false(0)` window not found or visible 1830 */ 1831 NK_API nk_bool nk_window_is_hidden(struct nk_context*, const char*); 1832 /*/// #### nk_window_is_active 1833 /// Same as nk_window_has_focus for some reason 1834 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1835 /// nk_bool nk_window_is_active(struct nk_context *ctx, const char *name); 1836 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1837 /// 1838 /// Parameter | Description 1839 /// ------------|----------------------------------------------------------- 1840 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1841 /// __name__ | Identifier of window you want to check if it is active 1842 /// 1843 /// Returns `true(1)` if current window is active or `false(0)` window not found or not active 1844 */ 1845 NK_API nk_bool nk_window_is_active(struct nk_context*, const char*); 1846 /*/// #### nk_window_is_any_hovered 1847 /// Returns if the any window is being hovered 1848 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1849 /// nk_bool nk_window_is_any_hovered(struct nk_context*); 1850 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1851 /// 1852 /// Parameter | Description 1853 /// ------------|----------------------------------------------------------- 1854 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1855 /// 1856 /// Returns `true(1)` if any window is hovered or `false(0)` otherwise 1857 */ 1858 NK_API nk_bool nk_window_is_any_hovered(struct nk_context*); 1859 /*/// #### nk_item_is_any_active 1860 /// Returns if the any window is being hovered or any widget is currently active. 1861 /// Can be used to decide if input should be processed by UI or your specific input handling. 1862 /// Example could be UI and 3D camera to move inside a 3D space. 1863 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1864 /// nk_bool nk_item_is_any_active(struct nk_context*); 1865 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1866 /// 1867 /// Parameter | Description 1868 /// ------------|----------------------------------------------------------- 1869 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1870 /// 1871 /// Returns `true(1)` if any window is hovered or any item is active or `false(0)` otherwise 1872 */ 1873 NK_API nk_bool nk_item_is_any_active(struct nk_context*); 1874 /*/// #### nk_window_set_bounds 1875 /// Updates position and size of window with passed in name 1876 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1877 /// void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds); 1878 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1879 /// 1880 /// Parameter | Description 1881 /// ------------|----------------------------------------------------------- 1882 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1883 /// __name__ | Identifier of the window to modify both position and size 1884 /// __bounds__ | Must point to a `nk_rect` struct with the new position and size 1885 */ 1886 NK_API void nk_window_set_bounds(struct nk_context*, const char *name, struct nk_rect bounds); 1887 /*/// #### nk_window_set_position 1888 /// Updates position of window with passed name 1889 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1890 /// void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos); 1891 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1892 /// 1893 /// Parameter | Description 1894 /// ------------|----------------------------------------------------------- 1895 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1896 /// __name__ | Identifier of the window to modify both position 1897 /// __pos__ | Must point to a `nk_vec2` struct with the new position 1898 */ 1899 NK_API void nk_window_set_position(struct nk_context*, const char *name, struct nk_vec2 pos); 1900 /*/// #### nk_window_set_size 1901 /// Updates size of window with passed in name 1902 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1903 /// void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2); 1904 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1905 /// 1906 /// Parameter | Description 1907 /// ------------|----------------------------------------------------------- 1908 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1909 /// __name__ | Identifier of the window to modify both window size 1910 /// __size__ | Must point to a `nk_vec2` struct with new window size 1911 */ 1912 NK_API void nk_window_set_size(struct nk_context*, const char *name, struct nk_vec2); 1913 /*/// #### nk_window_set_focus 1914 /// Sets the window with given name as active 1915 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1916 /// void nk_window_set_focus(struct nk_context*, const char *name); 1917 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1918 /// 1919 /// Parameter | Description 1920 /// ------------|----------------------------------------------------------- 1921 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1922 /// __name__ | Identifier of the window to set focus on 1923 */ 1924 NK_API void nk_window_set_focus(struct nk_context*, const char *name); 1925 /*/// #### nk_window_set_scroll 1926 /// Sets the scroll offset for the current window 1927 /// !!! WARNING 1928 /// Only call this function between calls `nk_begin_xxx` and `nk_end` 1929 /// 1930 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1931 /// void nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y); 1932 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1933 /// 1934 /// Parameter | Description 1935 /// -------------|----------------------------------------------------------- 1936 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1937 /// __offset_x__ | The x offset to scroll to 1938 /// __offset_y__ | The y offset to scroll to 1939 */ 1940 NK_API void nk_window_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y); 1941 /*/// #### nk_window_close 1942 /// Closes a window and marks it for being freed at the end of the frame 1943 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1944 /// void nk_window_close(struct nk_context *ctx, const char *name); 1945 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1946 /// 1947 /// Parameter | Description 1948 /// ------------|----------------------------------------------------------- 1949 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1950 /// __name__ | Identifier of the window to close 1951 */ 1952 NK_API void nk_window_close(struct nk_context *ctx, const char *name); 1953 /*/// #### nk_window_collapse 1954 /// Updates collapse state of a window with given name 1955 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1956 /// void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state); 1957 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1958 /// 1959 /// Parameter | Description 1960 /// ------------|----------------------------------------------------------- 1961 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1962 /// __name__ | Identifier of the window to close 1963 /// __state__ | value out of nk_collapse_states section 1964 */ 1965 NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states state); 1966 /*/// #### nk_window_collapse_if 1967 /// Updates collapse state of a window with given name if given condition is met 1968 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1969 /// void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond); 1970 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1971 /// 1972 /// Parameter | Description 1973 /// ------------|----------------------------------------------------------- 1974 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1975 /// __name__ | Identifier of the window to either collapse or maximize 1976 /// __state__ | value out of nk_collapse_states section the window should be put into 1977 /// __cond__ | condition that has to be met to actually commit the collapse state change 1978 */ 1979 NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond); 1980 /*/// #### nk_window_show 1981 /// updates visibility state of a window with given name 1982 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1983 /// void nk_window_show(struct nk_context*, const char *name, enum nk_show_states); 1984 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1985 /// 1986 /// Parameter | Description 1987 /// ------------|----------------------------------------------------------- 1988 /// __ctx__ | Must point to an previously initialized `nk_context` struct 1989 /// __name__ | Identifier of the window to either collapse or maximize 1990 /// __state__ | state with either visible or hidden to modify the window with 1991 */ 1992 NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states); 1993 /*/// #### nk_window_show_if 1994 /// Updates visibility state of a window with given name if a given condition is met 1995 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 1996 /// void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond); 1997 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1998 /// 1999 /// Parameter | Description 2000 /// ------------|----------------------------------------------------------- 2001 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2002 /// __name__ | Identifier of the window to either hide or show 2003 /// __state__ | state with either visible or hidden to modify the window with 2004 /// __cond__ | condition that has to be met to actually commit the visbility state change 2005 */ 2006 NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond); 2007 /* ============================================================================= 2008 * 2009 * LAYOUT 2010 * 2011 * ============================================================================= 2012 /// ### Layouting 2013 /// Layouting in general describes placing widget inside a window with position and size. 2014 /// While in this particular implementation there are five different APIs for layouting 2015 /// each with different trade offs between control and ease of use. <br /><br /> 2016 /// 2017 /// All layouting methods in this library are based around the concept of a row. 2018 /// A row has a height the window content grows by and a number of columns and each 2019 /// layouting method specifies how each widget is placed inside the row. 2020 /// After a row has been allocated by calling a layouting functions and then 2021 /// filled with widgets will advance an internal pointer over the allocated row. <br /><br /> 2022 /// 2023 /// To actually define a layout you just call the appropriate layouting function 2024 /// and each subsequent widget call will place the widget as specified. Important 2025 /// here is that if you define more widgets then columns defined inside the layout 2026 /// functions it will allocate the next row without you having to make another layouting <br /><br /> 2027 /// call. 2028 /// 2029 /// Biggest limitation with using all these APIs outside the `nk_layout_space_xxx` API 2030 /// is that you have to define the row height for each. However the row height 2031 /// often depends on the height of the font. <br /><br /> 2032 /// 2033 /// To fix that internally nuklear uses a minimum row height that is set to the 2034 /// height plus padding of currently active font and overwrites the row height 2035 /// value if zero. <br /><br /> 2036 /// 2037 /// If you manually want to change the minimum row height then 2038 /// use nk_layout_set_min_row_height, and use nk_layout_reset_min_row_height to 2039 /// reset it back to be derived from font height. <br /><br /> 2040 /// 2041 /// Also if you change the font in nuklear it will automatically change the minimum 2042 /// row height for you and. This means if you change the font but still want 2043 /// a minimum row height smaller than the font you have to repush your value. <br /><br /> 2044 /// 2045 /// For actually more advanced UI I would even recommend using the `nk_layout_space_xxx` 2046 /// layouting method in combination with a cassowary constraint solver (there are 2047 /// some versions on github with permissive license model) to take over all control over widget 2048 /// layouting yourself. However for quick and dirty layouting using all the other layouting 2049 /// functions should be fine. 2050 /// 2051 /// #### Usage 2052 /// 1. __nk_layout_row_dynamic__<br /><br /> 2053 /// The easiest layouting function is `nk_layout_row_dynamic`. It provides each 2054 /// widgets with same horizontal space inside the row and dynamically grows 2055 /// if the owning window grows in width. So the number of columns dictates 2056 /// the size of each widget dynamically by formula: 2057 /// 2058 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2059 /// widget_width = (window_width - padding - spacing) * (1/colum_count) 2060 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2061 /// 2062 /// Just like all other layouting APIs if you define more widget than columns this 2063 /// library will allocate a new row and keep all layouting parameters previously 2064 /// defined. 2065 /// 2066 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2067 /// if (nk_begin_xxx(...) { 2068 /// // first row with height: 30 composed of two widgets 2069 /// nk_layout_row_dynamic(&ctx, 30, 2); 2070 /// nk_widget(...); 2071 /// nk_widget(...); 2072 /// // 2073 /// // second row with same parameter as defined above 2074 /// nk_widget(...); 2075 /// nk_widget(...); 2076 /// // 2077 /// // third row uses 0 for height which will use auto layouting 2078 /// nk_layout_row_dynamic(&ctx, 0, 2); 2079 /// nk_widget(...); 2080 /// nk_widget(...); 2081 /// } 2082 /// nk_end(...); 2083 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2084 /// 2085 /// 2. __nk_layout_row_static__<br /><br /> 2086 /// Another easy layouting function is `nk_layout_row_static`. It provides each 2087 /// widget with same horizontal pixel width inside the row and does not grow 2088 /// if the owning window scales smaller or bigger. 2089 /// 2090 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2091 /// if (nk_begin_xxx(...) { 2092 /// // first row with height: 30 composed of two widgets with width: 80 2093 /// nk_layout_row_static(&ctx, 30, 80, 2); 2094 /// nk_widget(...); 2095 /// nk_widget(...); 2096 /// // 2097 /// // second row with same parameter as defined above 2098 /// nk_widget(...); 2099 /// nk_widget(...); 2100 /// // 2101 /// // third row uses 0 for height which will use auto layouting 2102 /// nk_layout_row_static(&ctx, 0, 80, 2); 2103 /// nk_widget(...); 2104 /// nk_widget(...); 2105 /// } 2106 /// nk_end(...); 2107 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2108 /// 2109 /// 3. __nk_layout_row_xxx__<br /><br /> 2110 /// A little bit more advanced layouting API are functions `nk_layout_row_begin`, 2111 /// `nk_layout_row_push` and `nk_layout_row_end`. They allow to directly 2112 /// specify each column pixel or window ratio in a row. It supports either 2113 /// directly setting per column pixel width or widget window ratio but not 2114 /// both. Furthermore it is a immediate mode API so each value is directly 2115 /// pushed before calling a widget. Therefore the layout is not automatically 2116 /// repeating like the last two layouting functions. 2117 /// 2118 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2119 /// if (nk_begin_xxx(...) { 2120 /// // first row with height: 25 composed of two widgets with width 60 and 40 2121 /// nk_layout_row_begin(ctx, NK_STATIC, 25, 2); 2122 /// nk_layout_row_push(ctx, 60); 2123 /// nk_widget(...); 2124 /// nk_layout_row_push(ctx, 40); 2125 /// nk_widget(...); 2126 /// nk_layout_row_end(ctx); 2127 /// // 2128 /// // second row with height: 25 composed of two widgets with window ratio 0.25 and 0.75 2129 /// nk_layout_row_begin(ctx, NK_DYNAMIC, 25, 2); 2130 /// nk_layout_row_push(ctx, 0.25f); 2131 /// nk_widget(...); 2132 /// nk_layout_row_push(ctx, 0.75f); 2133 /// nk_widget(...); 2134 /// nk_layout_row_end(ctx); 2135 /// // 2136 /// // third row with auto generated height: composed of two widgets with window ratio 0.25 and 0.75 2137 /// nk_layout_row_begin(ctx, NK_DYNAMIC, 0, 2); 2138 /// nk_layout_row_push(ctx, 0.25f); 2139 /// nk_widget(...); 2140 /// nk_layout_row_push(ctx, 0.75f); 2141 /// nk_widget(...); 2142 /// nk_layout_row_end(ctx); 2143 /// } 2144 /// nk_end(...); 2145 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2146 /// 2147 /// 4. __nk_layout_row__<br /><br /> 2148 /// The array counterpart to API nk_layout_row_xxx is the single nk_layout_row 2149 /// functions. Instead of pushing either pixel or window ratio for every widget 2150 /// it allows to define it by array. The trade of for less control is that 2151 /// `nk_layout_row` is automatically repeating. Otherwise the behavior is the 2152 /// same. 2153 /// 2154 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2155 /// if (nk_begin_xxx(...) { 2156 /// // two rows with height: 30 composed of two widgets with width 60 and 40 2157 /// const float ratio[] = {60,40}; 2158 /// nk_layout_row(ctx, NK_STATIC, 30, 2, ratio); 2159 /// nk_widget(...); 2160 /// nk_widget(...); 2161 /// nk_widget(...); 2162 /// nk_widget(...); 2163 /// // 2164 /// // two rows with height: 30 composed of two widgets with window ratio 0.25 and 0.75 2165 /// const float ratio[] = {0.25, 0.75}; 2166 /// nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); 2167 /// nk_widget(...); 2168 /// nk_widget(...); 2169 /// nk_widget(...); 2170 /// nk_widget(...); 2171 /// // 2172 /// // two rows with auto generated height composed of two widgets with window ratio 0.25 and 0.75 2173 /// const float ratio[] = {0.25, 0.75}; 2174 /// nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratio); 2175 /// nk_widget(...); 2176 /// nk_widget(...); 2177 /// nk_widget(...); 2178 /// nk_widget(...); 2179 /// } 2180 /// nk_end(...); 2181 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2182 /// 2183 /// 5. __nk_layout_row_template_xxx__<br /><br /> 2184 /// The most complex and second most flexible API is a simplified flexbox version without 2185 /// line wrapping and weights for dynamic widgets. It is an immediate mode API but 2186 /// unlike `nk_layout_row_xxx` it has auto repeat behavior and needs to be called 2187 /// before calling the templated widgets. 2188 /// The row template layout has three different per widget size specifier. The first 2189 /// one is the `nk_layout_row_template_push_static` with fixed widget pixel width. 2190 /// They do not grow if the row grows and will always stay the same. 2191 /// The second size specifier is `nk_layout_row_template_push_variable` 2192 /// which defines a minimum widget size but it also can grow if more space is available 2193 /// not taken by other widgets. 2194 /// Finally there are dynamic widgets with `nk_layout_row_template_push_dynamic` 2195 /// which are completely flexible and unlike variable widgets can even shrink 2196 /// to zero if not enough space is provided. 2197 /// 2198 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2199 /// if (nk_begin_xxx(...) { 2200 /// // two rows with height: 30 composed of three widgets 2201 /// nk_layout_row_template_begin(ctx, 30); 2202 /// nk_layout_row_template_push_dynamic(ctx); 2203 /// nk_layout_row_template_push_variable(ctx, 80); 2204 /// nk_layout_row_template_push_static(ctx, 80); 2205 /// nk_layout_row_template_end(ctx); 2206 /// // 2207 /// // first row 2208 /// nk_widget(...); // dynamic widget can go to zero if not enough space 2209 /// nk_widget(...); // variable widget with min 80 pixel but can grow bigger if enough space 2210 /// nk_widget(...); // static widget with fixed 80 pixel width 2211 /// // 2212 /// // second row same layout 2213 /// nk_widget(...); 2214 /// nk_widget(...); 2215 /// nk_widget(...); 2216 /// } 2217 /// nk_end(...); 2218 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2219 /// 2220 /// 6. __nk_layout_space_xxx__<br /><br /> 2221 /// Finally the most flexible API directly allows you to place widgets inside the 2222 /// window. The space layout API is an immediate mode API which does not support 2223 /// row auto repeat and directly sets position and size of a widget. Position 2224 /// and size hereby can be either specified as ratio of allocated space or 2225 /// allocated space local position and pixel size. Since this API is quite 2226 /// powerful there are a number of utility functions to get the available space 2227 /// and convert between local allocated space and screen space. 2228 /// 2229 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2230 /// if (nk_begin_xxx(...) { 2231 /// // static row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) 2232 /// nk_layout_space_begin(ctx, NK_STATIC, 500, INT_MAX); 2233 /// nk_layout_space_push(ctx, nk_rect(0,0,150,200)); 2234 /// nk_widget(...); 2235 /// nk_layout_space_push(ctx, nk_rect(200,200,100,200)); 2236 /// nk_widget(...); 2237 /// nk_layout_space_end(ctx); 2238 /// // 2239 /// // dynamic row with height: 500 (you can set column count to INT_MAX if you don't want to be bothered) 2240 /// nk_layout_space_begin(ctx, NK_DYNAMIC, 500, INT_MAX); 2241 /// nk_layout_space_push(ctx, nk_rect(0.5,0.5,0.1,0.1)); 2242 /// nk_widget(...); 2243 /// nk_layout_space_push(ctx, nk_rect(0.7,0.6,0.1,0.1)); 2244 /// nk_widget(...); 2245 /// } 2246 /// nk_end(...); 2247 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2248 /// 2249 /// #### Reference 2250 /// Function | Description 2251 /// ----------------------------------------|------------------------------------ 2252 /// nk_layout_set_min_row_height | Set the currently used minimum row height to a specified value 2253 /// nk_layout_reset_min_row_height | Resets the currently used minimum row height to font height 2254 /// nk_layout_widget_bounds | Calculates current width a static layout row can fit inside a window 2255 /// nk_layout_ratio_from_pixel | Utility functions to calculate window ratio from pixel size 2256 // 2257 /// nk_layout_row_dynamic | Current layout is divided into n same sized growing columns 2258 /// nk_layout_row_static | Current layout is divided into n same fixed sized columns 2259 /// nk_layout_row_begin | Starts a new row with given height and number of columns 2260 /// nk_layout_row_push | Pushes another column with given size or window ratio 2261 /// nk_layout_row_end | Finished previously started row 2262 /// nk_layout_row | Specifies row columns in array as either window ratio or size 2263 // 2264 /// nk_layout_row_template_begin | Begins the row template declaration 2265 /// nk_layout_row_template_push_dynamic | Adds a dynamic column that dynamically grows and can go to zero if not enough space 2266 /// nk_layout_row_template_push_variable | Adds a variable column that dynamically grows but does not shrink below specified pixel width 2267 /// nk_layout_row_template_push_static | Adds a static column that does not grow and will always have the same size 2268 /// nk_layout_row_template_end | Marks the end of the row template 2269 // 2270 /// nk_layout_space_begin | Begins a new layouting space that allows to specify each widgets position and size 2271 /// nk_layout_space_push | Pushes position and size of the next widget in own coordinate space either as pixel or ratio 2272 /// nk_layout_space_end | Marks the end of the layouting space 2273 // 2274 /// nk_layout_space_bounds | Callable after nk_layout_space_begin and returns total space allocated 2275 /// nk_layout_space_to_screen | Converts vector from nk_layout_space coordinate space into screen space 2276 /// nk_layout_space_to_local | Converts vector from screen space into nk_layout_space coordinates 2277 /// nk_layout_space_rect_to_screen | Converts rectangle from nk_layout_space coordinate space into screen space 2278 /// nk_layout_space_rect_to_local | Converts rectangle from screen space into nk_layout_space coordinates 2279 */ 2280 /*/// #### nk_layout_set_min_row_height 2281 /// Sets the currently used minimum row height. 2282 /// !!! WARNING 2283 /// The passed height needs to include both your preferred row height 2284 /// as well as padding. No internal padding is added. 2285 /// 2286 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2287 /// void nk_layout_set_min_row_height(struct nk_context*, float height); 2288 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2289 /// 2290 /// Parameter | Description 2291 /// ------------|----------------------------------------------------------- 2292 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2293 /// __height__ | New minimum row height to be used for auto generating the row height 2294 */ 2295 NK_API void nk_layout_set_min_row_height(struct nk_context*, float height); 2296 /*/// #### nk_layout_reset_min_row_height 2297 /// Reset the currently used minimum row height back to `font_height + text_padding + padding` 2298 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2299 /// void nk_layout_reset_min_row_height(struct nk_context*); 2300 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2301 /// 2302 /// Parameter | Description 2303 /// ------------|----------------------------------------------------------- 2304 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2305 */ 2306 NK_API void nk_layout_reset_min_row_height(struct nk_context*); 2307 /*/// #### nk_layout_widget_bounds 2308 /// Returns the width of the next row allocate by one of the layouting functions 2309 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2310 /// struct nk_rect nk_layout_widget_bounds(struct nk_context*); 2311 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2312 /// 2313 /// Parameter | Description 2314 /// ------------|----------------------------------------------------------- 2315 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2316 /// 2317 /// Return `nk_rect` with both position and size of the next row 2318 */ 2319 NK_API struct nk_rect nk_layout_widget_bounds(struct nk_context*); 2320 /*/// #### nk_layout_ratio_from_pixel 2321 /// Utility functions to calculate window ratio from pixel size 2322 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2323 /// float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width); 2324 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2325 /// 2326 /// Parameter | Description 2327 /// ------------|----------------------------------------------------------- 2328 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2329 /// __pixel__ | Pixel_width to convert to window ratio 2330 /// 2331 /// Returns `nk_rect` with both position and size of the next row 2332 */ 2333 NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width); 2334 /*/// #### nk_layout_row_dynamic 2335 /// Sets current row layout to share horizontal space 2336 /// between @cols number of widgets evenly. Once called all subsequent widget 2337 /// calls greater than @cols will allocate a new row with same layout. 2338 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2339 /// void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols); 2340 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2341 /// 2342 /// Parameter | Description 2343 /// ------------|----------------------------------------------------------- 2344 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2345 /// __height__ | Holds height of each widget in row or zero for auto layouting 2346 /// __columns__ | Number of widget inside row 2347 */ 2348 NK_API void nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols); 2349 /*/// #### nk_layout_row_static 2350 /// Sets current row layout to fill @cols number of widgets 2351 /// in row with same @item_width horizontal size. Once called all subsequent widget 2352 /// calls greater than @cols will allocate a new row with same layout. 2353 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2354 /// void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols); 2355 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2356 /// 2357 /// Parameter | Description 2358 /// ------------|----------------------------------------------------------- 2359 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2360 /// __height__ | Holds height of each widget in row or zero for auto layouting 2361 /// __width__ | Holds pixel width of each widget in the row 2362 /// __columns__ | Number of widget inside row 2363 */ 2364 NK_API void nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols); 2365 /*/// #### nk_layout_row_begin 2366 /// Starts a new dynamic or fixed row with given height and columns. 2367 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2368 /// void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols); 2369 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2370 /// 2371 /// Parameter | Description 2372 /// ------------|----------------------------------------------------------- 2373 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2374 /// __fmt__ | either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2375 /// __height__ | holds height of each widget in row or zero for auto layouting 2376 /// __columns__ | Number of widget inside row 2377 */ 2378 NK_API void nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, float row_height, int cols); 2379 /*/// #### nk_layout_row_push 2380 /// Specifies either window ratio or width of a single column 2381 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2382 /// void nk_layout_row_push(struct nk_context*, float value); 2383 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2384 /// 2385 /// Parameter | Description 2386 /// ------------|----------------------------------------------------------- 2387 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2388 /// __value__ | either a window ratio or fixed width depending on @fmt in previous `nk_layout_row_begin` call 2389 */ 2390 NK_API void nk_layout_row_push(struct nk_context*, float value); 2391 /*/// #### nk_layout_row_end 2392 /// Finished previously started row 2393 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2394 /// void nk_layout_row_end(struct nk_context*); 2395 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2396 /// 2397 /// Parameter | Description 2398 /// ------------|----------------------------------------------------------- 2399 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2400 */ 2401 NK_API void nk_layout_row_end(struct nk_context*); 2402 /*/// #### nk_layout_row 2403 /// Specifies row columns in array as either window ratio or size 2404 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2405 /// void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio); 2406 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2407 /// 2408 /// Parameter | Description 2409 /// ------------|----------------------------------------------------------- 2410 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2411 /// __fmt__ | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2412 /// __height__ | Holds height of each widget in row or zero for auto layouting 2413 /// __columns__ | Number of widget inside row 2414 */ 2415 NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio); 2416 /*/// #### nk_layout_row_template_begin 2417 /// Begins the row template declaration 2418 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2419 /// void nk_layout_row_template_begin(struct nk_context*, float row_height); 2420 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2421 /// 2422 /// Parameter | Description 2423 /// ------------|----------------------------------------------------------- 2424 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2425 /// __height__ | Holds height of each widget in row or zero for auto layouting 2426 */ 2427 NK_API void nk_layout_row_template_begin(struct nk_context*, float row_height); 2428 /*/// #### nk_layout_row_template_push_dynamic 2429 /// Adds a dynamic column that dynamically grows and can go to zero if not enough space 2430 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2431 /// void nk_layout_row_template_push_dynamic(struct nk_context*); 2432 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2433 /// 2434 /// Parameter | Description 2435 /// ------------|----------------------------------------------------------- 2436 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2437 /// __height__ | Holds height of each widget in row or zero for auto layouting 2438 */ 2439 NK_API void nk_layout_row_template_push_dynamic(struct nk_context*); 2440 /*/// #### nk_layout_row_template_push_variable 2441 /// Adds a variable column that dynamically grows but does not shrink below specified pixel width 2442 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2443 /// void nk_layout_row_template_push_variable(struct nk_context*, float min_width); 2444 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2445 /// 2446 /// Parameter | Description 2447 /// ------------|----------------------------------------------------------- 2448 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2449 /// __width__ | Holds the minimum pixel width the next column must always be 2450 */ 2451 NK_API void nk_layout_row_template_push_variable(struct nk_context*, float min_width); 2452 /*/// #### nk_layout_row_template_push_static 2453 /// Adds a static column that does not grow and will always have the same size 2454 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2455 /// void nk_layout_row_template_push_static(struct nk_context*, float width); 2456 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2457 /// 2458 /// Parameter | Description 2459 /// ------------|----------------------------------------------------------- 2460 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2461 /// __width__ | Holds the absolute pixel width value the next column must be 2462 */ 2463 NK_API void nk_layout_row_template_push_static(struct nk_context*, float width); 2464 /*/// #### nk_layout_row_template_end 2465 /// Marks the end of the row template 2466 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2467 /// void nk_layout_row_template_end(struct nk_context*); 2468 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2469 /// 2470 /// Parameter | Description 2471 /// ------------|----------------------------------------------------------- 2472 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2473 */ 2474 NK_API void nk_layout_row_template_end(struct nk_context*); 2475 /*/// #### nk_layout_space_begin 2476 /// Begins a new layouting space that allows to specify each widgets position and size. 2477 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2478 /// void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count); 2479 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2480 /// 2481 /// Parameter | Description 2482 /// ------------|----------------------------------------------------------- 2483 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_begin_xxx` 2484 /// __fmt__ | Either `NK_DYNAMIC` for window ratio or `NK_STATIC` for fixed size columns 2485 /// __height__ | Holds height of each widget in row or zero for auto layouting 2486 /// __columns__ | Number of widgets inside row 2487 */ 2488 NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count); 2489 /*/// #### nk_layout_space_push 2490 /// Pushes position and size of the next widget in own coordinate space either as pixel or ratio 2491 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2492 /// void nk_layout_space_push(struct nk_context *ctx, struct nk_rect bounds); 2493 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2494 /// 2495 /// Parameter | Description 2496 /// ------------|----------------------------------------------------------- 2497 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2498 /// __bounds__ | Position and size in laoyut space local coordinates 2499 */ 2500 NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect bounds); 2501 /*/// #### nk_layout_space_end 2502 /// Marks the end of the layout space 2503 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2504 /// void nk_layout_space_end(struct nk_context*); 2505 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2506 /// 2507 /// Parameter | Description 2508 /// ------------|----------------------------------------------------------- 2509 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2510 */ 2511 NK_API void nk_layout_space_end(struct nk_context*); 2512 /*/// #### nk_layout_space_bounds 2513 /// Utility function to calculate total space allocated for `nk_layout_space` 2514 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2515 /// struct nk_rect nk_layout_space_bounds(struct nk_context*); 2516 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2517 /// 2518 /// Parameter | Description 2519 /// ------------|----------------------------------------------------------- 2520 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2521 /// 2522 /// Returns `nk_rect` holding the total space allocated 2523 */ 2524 NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*); 2525 /*/// #### nk_layout_space_to_screen 2526 /// Converts vector from nk_layout_space coordinate space into screen space 2527 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2528 /// struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2); 2529 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2530 /// 2531 /// Parameter | Description 2532 /// ------------|----------------------------------------------------------- 2533 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2534 /// __vec__ | Position to convert from layout space into screen coordinate space 2535 /// 2536 /// Returns transformed `nk_vec2` in screen space coordinates 2537 */ 2538 NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2); 2539 /*/// #### nk_layout_space_to_local 2540 /// Converts vector from layout space into screen space 2541 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2542 /// struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2); 2543 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2544 /// 2545 /// Parameter | Description 2546 /// ------------|----------------------------------------------------------- 2547 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2548 /// __vec__ | Position to convert from screen space into layout coordinate space 2549 /// 2550 /// Returns transformed `nk_vec2` in layout space coordinates 2551 */ 2552 NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2); 2553 /*/// #### nk_layout_space_rect_to_screen 2554 /// Converts rectangle from screen space into layout space 2555 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2556 /// struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect); 2557 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2558 /// 2559 /// Parameter | Description 2560 /// ------------|----------------------------------------------------------- 2561 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2562 /// __bounds__ | Rectangle to convert from layout space into screen space 2563 /// 2564 /// Returns transformed `nk_rect` in screen space coordinates 2565 */ 2566 NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect); 2567 /*/// #### nk_layout_space_rect_to_local 2568 /// Converts rectangle from layout space into screen space 2569 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2570 /// struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect); 2571 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2572 /// 2573 /// Parameter | Description 2574 /// ------------|----------------------------------------------------------- 2575 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2576 /// __bounds__ | Rectangle to convert from layout space into screen space 2577 /// 2578 /// Returns transformed `nk_rect` in layout space coordinates 2579 */ 2580 NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect); 2581 2582 /*/// #### nk_spacer 2583 /// Spacer is a dummy widget that consumes space as usual but doesn't draw anything 2584 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2585 /// void nk_spacer(struct nk_context* ); 2586 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2587 /// 2588 /// Parameter | Description 2589 /// ------------|----------------------------------------------------------- 2590 /// __ctx__ | Must point to an previously initialized `nk_context` struct after call `nk_layout_space_begin` 2591 /// 2592 */ 2593 NK_API void nk_spacer(struct nk_context* ); 2594 2595 2596 /* ============================================================================= 2597 * 2598 * GROUP 2599 * 2600 * ============================================================================= 2601 /// ### Groups 2602 /// Groups are basically windows inside windows. They allow to subdivide space 2603 /// in a window to layout widgets as a group. Almost all more complex widget 2604 /// layouting requirements can be solved using groups and basic layouting 2605 /// fuctionality. Groups just like windows are identified by an unique name and 2606 /// internally keep track of scrollbar offsets by default. However additional 2607 /// versions are provided to directly manage the scrollbar. 2608 /// 2609 /// #### Usage 2610 /// To create a group you have to call one of the three `nk_group_begin_xxx` 2611 /// functions to start group declarations and `nk_group_end` at the end. Furthermore it 2612 /// is required to check the return value of `nk_group_begin_xxx` and only process 2613 /// widgets inside the window if the value is not 0. 2614 /// Nesting groups is possible and even encouraged since many layouting schemes 2615 /// can only be achieved by nesting. Groups, unlike windows, need `nk_group_end` 2616 /// to be only called if the corresponding `nk_group_begin_xxx` call does not return 0: 2617 /// 2618 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2619 /// if (nk_group_begin_xxx(ctx, ...) { 2620 /// // [... widgets ...] 2621 /// nk_group_end(ctx); 2622 /// } 2623 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2624 /// 2625 /// In the grand concept groups can be called after starting a window 2626 /// with `nk_begin_xxx` and before calling `nk_end`: 2627 /// 2628 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2629 /// struct nk_context ctx; 2630 /// nk_init_xxx(&ctx, ...); 2631 /// while (1) { 2632 /// // Input 2633 /// Event evt; 2634 /// nk_input_begin(&ctx); 2635 /// while (GetEvent(&evt)) { 2636 /// if (evt.type == MOUSE_MOVE) 2637 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 2638 /// else if (evt.type == [...]) { 2639 /// nk_input_xxx(...); 2640 /// } 2641 /// } 2642 /// nk_input_end(&ctx); 2643 /// // 2644 /// // Window 2645 /// if (nk_begin_xxx(...) { 2646 /// // [...widgets...] 2647 /// nk_layout_row_dynamic(...); 2648 /// if (nk_group_begin_xxx(ctx, ...) { 2649 /// //[... widgets ...] 2650 /// nk_group_end(ctx); 2651 /// } 2652 /// } 2653 /// nk_end(ctx); 2654 /// // 2655 /// // Draw 2656 /// const struct nk_command *cmd = 0; 2657 /// nk_foreach(cmd, &ctx) { 2658 /// switch (cmd->type) { 2659 /// case NK_COMMAND_LINE: 2660 /// your_draw_line_function(...) 2661 /// break; 2662 /// case NK_COMMAND_RECT 2663 /// your_draw_rect_function(...) 2664 /// break; 2665 /// case ...: 2666 /// // [...] 2667 /// } 2668 /// nk_clear(&ctx); 2669 /// } 2670 /// nk_free(&ctx); 2671 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2672 /// #### Reference 2673 /// Function | Description 2674 /// --------------------------------|------------------------------------------- 2675 /// nk_group_begin | Start a new group with internal scrollbar handling 2676 /// nk_group_begin_titled | Start a new group with separated name and title and internal scrollbar handling 2677 /// nk_group_end | Ends a group. Should only be called if nk_group_begin returned non-zero 2678 /// nk_group_scrolled_offset_begin | Start a new group with manual separated handling of scrollbar x- and y-offset 2679 /// nk_group_scrolled_begin | Start a new group with manual scrollbar handling 2680 /// nk_group_scrolled_end | Ends a group with manual scrollbar handling. Should only be called if nk_group_begin returned non-zero 2681 /// nk_group_get_scroll | Gets the scroll offset for the given group 2682 /// nk_group_set_scroll | Sets the scroll offset for the given group 2683 */ 2684 /*/// #### nk_group_begin 2685 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size. 2686 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2687 /// nk_bool nk_group_begin(struct nk_context*, const char *title, nk_flags); 2688 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2689 /// 2690 /// Parameter | Description 2691 /// ------------|----------------------------------------------------------- 2692 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2693 /// __title__ | Must be an unique identifier for this group that is also used for the group header 2694 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different group behaviors 2695 /// 2696 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2697 */ 2698 NK_API nk_bool nk_group_begin(struct nk_context*, const char *title, nk_flags); 2699 /*/// #### nk_group_begin_titled 2700 /// Starts a new widget group. Requires a previous layouting function to specify a pos/size. 2701 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2702 /// nk_bool nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags); 2703 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2704 /// 2705 /// Parameter | Description 2706 /// ------------|----------------------------------------------------------- 2707 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2708 /// __id__ | Must be an unique identifier for this group 2709 /// __title__ | Group header title 2710 /// __flags__ | Window flags defined in the nk_panel_flags section with a number of different group behaviors 2711 /// 2712 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2713 */ 2714 NK_API nk_bool nk_group_begin_titled(struct nk_context*, const char *name, const char *title, nk_flags); 2715 /*/// #### nk_group_end 2716 /// Ends a widget group 2717 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2718 /// void nk_group_end(struct nk_context*); 2719 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2720 /// 2721 /// Parameter | Description 2722 /// ------------|----------------------------------------------------------- 2723 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2724 */ 2725 NK_API void nk_group_end(struct nk_context*); 2726 /*/// #### nk_group_scrolled_offset_begin 2727 /// starts a new widget group. requires a previous layouting function to specify 2728 /// a size. Does not keep track of scrollbar. 2729 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2730 /// nk_bool nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags); 2731 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2732 /// 2733 /// Parameter | Description 2734 /// ------------|----------------------------------------------------------- 2735 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2736 /// __x_offset__| Scrollbar x-offset to offset all widgets inside the group horizontally. 2737 /// __y_offset__| Scrollbar y-offset to offset all widgets inside the group vertically 2738 /// __title__ | Window unique group title used to both identify and display in the group header 2739 /// __flags__ | Window flags from the nk_panel_flags section 2740 /// 2741 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2742 */ 2743 NK_API nk_bool nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags); 2744 /*/// #### nk_group_scrolled_begin 2745 /// Starts a new widget group. requires a previous 2746 /// layouting function to specify a size. Does not keep track of scrollbar. 2747 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2748 /// nk_bool nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags); 2749 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2750 /// 2751 /// Parameter | Description 2752 /// ------------|----------------------------------------------------------- 2753 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2754 /// __off__ | Both x- and y- scroll offset. Allows for manual scrollbar control 2755 /// __title__ | Window unique group title used to both identify and display in the group header 2756 /// __flags__ | Window flags from nk_panel_flags section 2757 /// 2758 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2759 */ 2760 NK_API nk_bool nk_group_scrolled_begin(struct nk_context*, struct nk_scroll *off, const char *title, nk_flags); 2761 /*/// #### nk_group_scrolled_end 2762 /// Ends a widget group after calling nk_group_scrolled_offset_begin or nk_group_scrolled_begin. 2763 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2764 /// void nk_group_scrolled_end(struct nk_context*); 2765 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2766 /// 2767 /// Parameter | Description 2768 /// ------------|----------------------------------------------------------- 2769 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2770 */ 2771 NK_API void nk_group_scrolled_end(struct nk_context*); 2772 /*/// #### nk_group_get_scroll 2773 /// Gets the scroll position of the given group. 2774 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2775 /// void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset); 2776 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2777 /// 2778 /// Parameter | Description 2779 /// -------------|----------------------------------------------------------- 2780 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2781 /// __id__ | The id of the group to get the scroll position of 2782 /// __x_offset__ | A pointer to the x offset output (or NULL to ignore) 2783 /// __y_offset__ | A pointer to the y offset output (or NULL to ignore) 2784 */ 2785 NK_API void nk_group_get_scroll(struct nk_context*, const char *id, nk_uint *x_offset, nk_uint *y_offset); 2786 /*/// #### nk_group_set_scroll 2787 /// Sets the scroll position of the given group. 2788 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2789 /// void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset); 2790 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2791 /// 2792 /// Parameter | Description 2793 /// -------------|----------------------------------------------------------- 2794 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2795 /// __id__ | The id of the group to scroll 2796 /// __x_offset__ | The x offset to scroll to 2797 /// __y_offset__ | The y offset to scroll to 2798 */ 2799 NK_API void nk_group_set_scroll(struct nk_context*, const char *id, nk_uint x_offset, nk_uint y_offset); 2800 /* ============================================================================= 2801 * 2802 * TREE 2803 * 2804 * ============================================================================= 2805 /// ### Tree 2806 /// Trees represent two different concept. First the concept of a collapsible 2807 /// UI section that can be either in a hidden or visible state. They allow the UI 2808 /// user to selectively minimize the current set of visible UI to comprehend. 2809 /// The second concept are tree widgets for visual UI representation of trees.<br /><br /> 2810 /// 2811 /// Trees thereby can be nested for tree representations and multiple nested 2812 /// collapsible UI sections. All trees are started by calling of the 2813 /// `nk_tree_xxx_push_tree` functions and ended by calling one of the 2814 /// `nk_tree_xxx_pop_xxx()` functions. Each starting functions takes a title label 2815 /// and optionally an image to be displayed and the initial collapse state from 2816 /// the nk_collapse_states section.<br /><br /> 2817 /// 2818 /// The runtime state of the tree is either stored outside the library by the caller 2819 /// or inside which requires a unique ID. The unique ID can either be generated 2820 /// automatically from `__FILE__` and `__LINE__` with function `nk_tree_push`, 2821 /// by `__FILE__` and a user provided ID generated for example by loop index with 2822 /// function `nk_tree_push_id` or completely provided from outside by user with 2823 /// function `nk_tree_push_hashed`. 2824 /// 2825 /// #### Usage 2826 /// To create a tree you have to call one of the seven `nk_tree_xxx_push_xxx` 2827 /// functions to start a collapsible UI section and `nk_tree_xxx_pop` to mark the 2828 /// end. 2829 /// Each starting function will either return `false(0)` if the tree is collapsed 2830 /// or hidden and therefore does not need to be filled with content or `true(1)` 2831 /// if visible and required to be filled. 2832 /// 2833 /// !!! Note 2834 /// The tree header does not require and layouting function and instead 2835 /// calculates a auto height based on the currently used font size 2836 /// 2837 /// The tree ending functions only need to be called if the tree content is 2838 /// actually visible. So make sure the tree push function is guarded by `if` 2839 /// and the pop call is only taken if the tree is visible. 2840 /// 2841 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2842 /// if (nk_tree_push(ctx, NK_TREE_TAB, "Tree", NK_MINIMIZED)) { 2843 /// nk_layout_row_dynamic(...); 2844 /// nk_widget(...); 2845 /// nk_tree_pop(ctx); 2846 /// } 2847 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2848 /// 2849 /// #### Reference 2850 /// Function | Description 2851 /// ----------------------------|------------------------------------------- 2852 /// nk_tree_push | Start a collapsible UI section with internal state management 2853 /// nk_tree_push_id | Start a collapsible UI section with internal state management callable in a look 2854 /// nk_tree_push_hashed | Start a collapsible UI section with internal state management with full control over internal unique ID use to store state 2855 /// nk_tree_image_push | Start a collapsible UI section with image and label header 2856 /// nk_tree_image_push_id | Start a collapsible UI section with image and label header and internal state management callable in a look 2857 /// nk_tree_image_push_hashed | Start a collapsible UI section with image and label header and internal state management with full control over internal unique ID use to store state 2858 /// nk_tree_pop | Ends a collapsible UI section 2859 // 2860 /// nk_tree_state_push | Start a collapsible UI section with external state management 2861 /// nk_tree_state_image_push | Start a collapsible UI section with image and label header and external state management 2862 /// nk_tree_state_pop | Ends a collapsabale UI section 2863 /// 2864 /// #### nk_tree_type 2865 /// Flag | Description 2866 /// ----------------|---------------------------------------- 2867 /// NK_TREE_NODE | Highlighted tree header to mark a collapsible UI section 2868 /// NK_TREE_TAB | Non-highlighted tree header closer to tree representations 2869 */ 2870 /*/// #### nk_tree_push 2871 /// Starts a collapsible UI section with internal state management 2872 /// !!! WARNING 2873 /// To keep track of the runtime tree collapsible state this function uses 2874 /// defines `__FILE__` and `__LINE__` to generate a unique ID. If you want 2875 /// to call this function in a loop please use `nk_tree_push_id` or 2876 /// `nk_tree_push_hashed` instead. 2877 /// 2878 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2879 /// #define nk_tree_push(ctx, type, title, state) 2880 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2881 /// 2882 /// Parameter | Description 2883 /// ------------|----------------------------------------------------------- 2884 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2885 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2886 /// __title__ | Label printed in the tree header 2887 /// __state__ | Initial tree state value out of nk_collapse_states 2888 /// 2889 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2890 */ 2891 #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__) 2892 /*/// #### nk_tree_push_id 2893 /// Starts a collapsible UI section with internal state management callable in a look 2894 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2895 /// #define nk_tree_push_id(ctx, type, title, state, id) 2896 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2897 /// 2898 /// Parameter | Description 2899 /// ------------|----------------------------------------------------------- 2900 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2901 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2902 /// __title__ | Label printed in the tree header 2903 /// __state__ | Initial tree state value out of nk_collapse_states 2904 /// __id__ | Loop counter index if this function is called in a loop 2905 /// 2906 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2907 */ 2908 #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) 2909 /*/// #### nk_tree_push_hashed 2910 /// Start a collapsible UI section with internal state management with full 2911 /// control over internal unique ID used to store state 2912 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2913 /// nk_bool nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); 2914 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2915 /// 2916 /// Parameter | Description 2917 /// ------------|----------------------------------------------------------- 2918 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2919 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2920 /// __title__ | Label printed in the tree header 2921 /// __state__ | Initial tree state value out of nk_collapse_states 2922 /// __hash__ | Memory block or string to generate the ID from 2923 /// __len__ | Size of passed memory block or string in __hash__ 2924 /// __seed__ | Seeding value if this function is called in a loop or default to `0` 2925 /// 2926 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2927 */ 2928 NK_API nk_bool nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); 2929 /*/// #### nk_tree_image_push 2930 /// Start a collapsible UI section with image and label header 2931 /// !!! WARNING 2932 /// To keep track of the runtime tree collapsible state this function uses 2933 /// defines `__FILE__` and `__LINE__` to generate a unique ID. If you want 2934 /// to call this function in a loop please use `nk_tree_image_push_id` or 2935 /// `nk_tree_image_push_hashed` instead. 2936 /// 2937 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2938 /// #define nk_tree_image_push(ctx, type, img, title, state) 2939 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2940 // 2941 /// Parameter | Description 2942 /// ------------|----------------------------------------------------------- 2943 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2944 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2945 /// __img__ | Image to display inside the header on the left of the label 2946 /// __title__ | Label printed in the tree header 2947 /// __state__ | Initial tree state value out of nk_collapse_states 2948 /// 2949 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2950 */ 2951 #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__) 2952 /*/// #### nk_tree_image_push_id 2953 /// Start a collapsible UI section with image and label header and internal state 2954 /// management callable in a look 2955 /// 2956 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2957 /// #define nk_tree_image_push_id(ctx, type, img, title, state, id) 2958 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2959 /// 2960 /// Parameter | Description 2961 /// ------------|----------------------------------------------------------- 2962 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2963 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2964 /// __img__ | Image to display inside the header on the left of the label 2965 /// __title__ | Label printed in the tree header 2966 /// __state__ | Initial tree state value out of nk_collapse_states 2967 /// __id__ | Loop counter index if this function is called in a loop 2968 /// 2969 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2970 */ 2971 #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) 2972 /*/// #### nk_tree_image_push_hashed 2973 /// Start a collapsible UI section with internal state management with full 2974 /// control over internal unique ID used to store state 2975 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2976 /// nk_bool nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); 2977 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2978 /// 2979 /// Parameter | Description 2980 /// ------------|----------------------------------------------------------- 2981 /// __ctx__ | Must point to an previously initialized `nk_context` struct 2982 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 2983 /// __img__ | Image to display inside the header on the left of the label 2984 /// __title__ | Label printed in the tree header 2985 /// __state__ | Initial tree state value out of nk_collapse_states 2986 /// __hash__ | Memory block or string to generate the ID from 2987 /// __len__ | Size of passed memory block or string in __hash__ 2988 /// __seed__ | Seeding value if this function is called in a loop or default to `0` 2989 /// 2990 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 2991 */ 2992 NK_API nk_bool nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); 2993 /*/// #### nk_tree_pop 2994 /// Ends a collapsabale UI section 2995 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 2996 /// void nk_tree_pop(struct nk_context*); 2997 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 2998 /// 2999 /// Parameter | Description 3000 /// ------------|----------------------------------------------------------- 3001 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 3002 */ 3003 NK_API void nk_tree_pop(struct nk_context*); 3004 /*/// #### nk_tree_state_push 3005 /// Start a collapsible UI section with external state management 3006 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3007 /// nk_bool nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state); 3008 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3009 /// 3010 /// Parameter | Description 3011 /// ------------|----------------------------------------------------------- 3012 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 3013 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 3014 /// __title__ | Label printed in the tree header 3015 /// __state__ | Persistent state to update 3016 /// 3017 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 3018 */ 3019 NK_API nk_bool nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state); 3020 /*/// #### nk_tree_state_image_push 3021 /// Start a collapsible UI section with image and label header and external state management 3022 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3023 /// nk_bool nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state); 3024 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3025 /// 3026 /// Parameter | Description 3027 /// ------------|----------------------------------------------------------- 3028 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 3029 /// __img__ | Image to display inside the header on the left of the label 3030 /// __type__ | Value from the nk_tree_type section to visually mark a tree node header as either a collapseable UI section or tree node 3031 /// __title__ | Label printed in the tree header 3032 /// __state__ | Persistent state to update 3033 /// 3034 /// Returns `true(1)` if visible and fillable with widgets or `false(0)` otherwise 3035 */ 3036 NK_API nk_bool nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state); 3037 /*/// #### nk_tree_state_pop 3038 /// Ends a collapsabale UI section 3039 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3040 /// void nk_tree_state_pop(struct nk_context*); 3041 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3042 /// 3043 /// Parameter | Description 3044 /// ------------|----------------------------------------------------------- 3045 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling `nk_tree_xxx_push_xxx` 3046 */ 3047 NK_API void nk_tree_state_pop(struct nk_context*); 3048 3049 #define nk_tree_element_push(ctx, type, title, state, sel) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),__LINE__) 3050 #define nk_tree_element_push_id(ctx, type, title, state, sel, id) nk_tree_element_push_hashed(ctx, type, title, state, sel, NK_FILE_LINE,nk_strlen(NK_FILE_LINE),id) 3051 NK_API nk_bool nk_tree_element_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, nk_bool *selected, const char *hash, int len, int seed); 3052 NK_API nk_bool nk_tree_element_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, nk_bool *selected, const char *hash, int len,int seed); 3053 NK_API void nk_tree_element_pop(struct nk_context*); 3054 3055 /* ============================================================================= 3056 * 3057 * LIST VIEW 3058 * 3059 * ============================================================================= */ 3060 struct nk_list_view { 3061 /* public: */ 3062 int begin, end, count; 3063 /* private: */ 3064 int total_height; 3065 struct nk_context *ctx; 3066 nk_uint *scroll_pointer; 3067 nk_uint scroll_value; 3068 }; 3069 NK_API nk_bool nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count); 3070 NK_API void nk_list_view_end(struct nk_list_view*); 3071 /* ============================================================================= 3072 * 3073 * WIDGET 3074 * 3075 * ============================================================================= */ 3076 enum nk_widget_layout_states { 3077 NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */ 3078 NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */ 3079 NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */ 3080 }; 3081 enum nk_widget_states { 3082 NK_WIDGET_STATE_MODIFIED = NK_FLAG(1), 3083 NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */ 3084 NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */ 3085 NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */ 3086 NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */ 3087 NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */ 3088 NK_WIDGET_STATE_HOVERED = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */ 3089 NK_WIDGET_STATE_ACTIVE = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */ 3090 }; 3091 NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*); 3092 NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2); 3093 NK_API struct nk_rect nk_widget_bounds(struct nk_context*); 3094 NK_API struct nk_vec2 nk_widget_position(struct nk_context*); 3095 NK_API struct nk_vec2 nk_widget_size(struct nk_context*); 3096 NK_API float nk_widget_width(struct nk_context*); 3097 NK_API float nk_widget_height(struct nk_context*); 3098 NK_API nk_bool nk_widget_is_hovered(struct nk_context*); 3099 NK_API nk_bool nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons); 3100 NK_API nk_bool nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, nk_bool down); 3101 NK_API void nk_spacing(struct nk_context*, int cols); 3102 /* ============================================================================= 3103 * 3104 * TEXT 3105 * 3106 * ============================================================================= */ 3107 enum nk_text_align { 3108 NK_TEXT_ALIGN_LEFT = 0x01, 3109 NK_TEXT_ALIGN_CENTERED = 0x02, 3110 NK_TEXT_ALIGN_RIGHT = 0x04, 3111 NK_TEXT_ALIGN_TOP = 0x08, 3112 NK_TEXT_ALIGN_MIDDLE = 0x10, 3113 NK_TEXT_ALIGN_BOTTOM = 0x20 3114 }; 3115 enum nk_text_alignment { 3116 NK_TEXT_LEFT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT, 3117 NK_TEXT_CENTERED = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED, 3118 NK_TEXT_RIGHT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT 3119 }; 3120 NK_API void nk_text(struct nk_context*, const char*, int, nk_flags); 3121 NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color); 3122 NK_API void nk_text_wrap(struct nk_context*, const char*, int); 3123 NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color); 3124 NK_API void nk_label(struct nk_context*, const char*, nk_flags align); 3125 NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color); 3126 NK_API void nk_label_wrap(struct nk_context*, const char*); 3127 NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color); 3128 NK_API void nk_image(struct nk_context*, struct nk_image); 3129 NK_API void nk_image_color(struct nk_context*, struct nk_image, struct nk_color); 3130 #ifdef NK_INCLUDE_STANDARD_VARARGS 3131 NK_API void nk_labelf(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(3); 3132 NK_API void nk_labelf_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(4); 3133 NK_API void nk_labelf_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(2); 3134 NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*,...) NK_PRINTF_VARARG_FUNC(3); 3135 NK_API void nk_labelfv(struct nk_context*, nk_flags, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3); 3136 NK_API void nk_labelfv_colored(struct nk_context*, nk_flags, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(4); 3137 NK_API void nk_labelfv_wrap(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2); 3138 NK_API void nk_labelfv_colored_wrap(struct nk_context*, struct nk_color, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(3); 3139 NK_API void nk_value_bool(struct nk_context*, const char *prefix, int); 3140 NK_API void nk_value_int(struct nk_context*, const char *prefix, int); 3141 NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int); 3142 NK_API void nk_value_float(struct nk_context*, const char *prefix, float); 3143 NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color); 3144 NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color); 3145 NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color); 3146 #endif 3147 /* ============================================================================= 3148 * 3149 * BUTTON 3150 * 3151 * ============================================================================= */ 3152 NK_API nk_bool nk_button_text(struct nk_context*, const char *title, int len); 3153 NK_API nk_bool nk_button_label(struct nk_context*, const char *title); 3154 NK_API nk_bool nk_button_color(struct nk_context*, struct nk_color); 3155 NK_API nk_bool nk_button_symbol(struct nk_context*, enum nk_symbol_type); 3156 NK_API nk_bool nk_button_image(struct nk_context*, struct nk_image img); 3157 NK_API nk_bool nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment); 3158 NK_API nk_bool nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3159 NK_API nk_bool nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment); 3160 NK_API nk_bool nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment); 3161 NK_API nk_bool nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len); 3162 NK_API nk_bool nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title); 3163 NK_API nk_bool nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type); 3164 NK_API nk_bool nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img); 3165 NK_API nk_bool nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3166 NK_API nk_bool nk_button_symbol_label_styled(struct nk_context *ctx, const struct nk_style_button *style, enum nk_symbol_type symbol, const char *title, nk_flags align); 3167 NK_API nk_bool nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment); 3168 NK_API nk_bool nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment); 3169 NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior); 3170 NK_API nk_bool nk_button_push_behavior(struct nk_context*, enum nk_button_behavior); 3171 NK_API nk_bool nk_button_pop_behavior(struct nk_context*); 3172 /* ============================================================================= 3173 * 3174 * CHECKBOX 3175 * 3176 * ============================================================================= */ 3177 NK_API nk_bool nk_check_label(struct nk_context*, const char*, nk_bool active); 3178 NK_API nk_bool nk_check_text(struct nk_context*, const char*, int, nk_bool active); 3179 NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value); 3180 NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value); 3181 NK_API nk_bool nk_checkbox_label(struct nk_context*, const char*, nk_bool *active); 3182 NK_API nk_bool nk_checkbox_text(struct nk_context*, const char*, int, nk_bool *active); 3183 NK_API nk_bool nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value); 3184 NK_API nk_bool nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value); 3185 /* ============================================================================= 3186 * 3187 * RADIO BUTTON 3188 * 3189 * ============================================================================= */ 3190 NK_API nk_bool nk_radio_label(struct nk_context*, const char*, nk_bool *active); 3191 NK_API nk_bool nk_radio_text(struct nk_context*, const char*, int, nk_bool *active); 3192 NK_API nk_bool nk_option_label(struct nk_context*, const char*, nk_bool active); 3193 NK_API nk_bool nk_option_text(struct nk_context*, const char*, int, nk_bool active); 3194 /* ============================================================================= 3195 * 3196 * SELECTABLE 3197 * 3198 * ============================================================================= */ 3199 NK_API nk_bool nk_selectable_label(struct nk_context*, const char*, nk_flags align, nk_bool *value); 3200 NK_API nk_bool nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, nk_bool *value); 3201 NK_API nk_bool nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, nk_bool *value); 3202 NK_API nk_bool nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, nk_bool *value); 3203 NK_API nk_bool nk_selectable_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, nk_bool *value); 3204 NK_API nk_bool nk_selectable_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, nk_bool *value); 3205 3206 NK_API nk_bool nk_select_label(struct nk_context*, const char*, nk_flags align, nk_bool value); 3207 NK_API nk_bool nk_select_text(struct nk_context*, const char*, int, nk_flags align, nk_bool value); 3208 NK_API nk_bool nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, nk_bool value); 3209 NK_API nk_bool nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, nk_bool value); 3210 NK_API nk_bool nk_select_symbol_label(struct nk_context*,enum nk_symbol_type, const char*, nk_flags align, nk_bool value); 3211 NK_API nk_bool nk_select_symbol_text(struct nk_context*,enum nk_symbol_type, const char*, int, nk_flags align, nk_bool value); 3212 3213 /* ============================================================================= 3214 * 3215 * SLIDER 3216 * 3217 * ============================================================================= */ 3218 NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step); 3219 NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step); 3220 NK_API nk_bool nk_slider_float(struct nk_context*, float min, float *val, float max, float step); 3221 NK_API nk_bool nk_slider_int(struct nk_context*, int min, int *val, int max, int step); 3222 /* ============================================================================= 3223 * 3224 * PROGRESSBAR 3225 * 3226 * ============================================================================= */ 3227 NK_API nk_bool nk_progress(struct nk_context*, nk_size *cur, nk_size max, nk_bool modifyable); 3228 NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, nk_bool modifyable); 3229 3230 /* ============================================================================= 3231 * 3232 * COLOR PICKER 3233 * 3234 * ============================================================================= */ 3235 NK_API struct nk_colorf nk_color_picker(struct nk_context*, struct nk_colorf, enum nk_color_format); 3236 NK_API nk_bool nk_color_pick(struct nk_context*, struct nk_colorf*, enum nk_color_format); 3237 /* ============================================================================= 3238 * 3239 * PROPERTIES 3240 * 3241 * ============================================================================= 3242 /// ### Properties 3243 /// Properties are the main value modification widgets in Nuklear. Changing a value 3244 /// can be achieved by dragging, adding/removing incremental steps on button click 3245 /// or by directly typing a number. 3246 /// 3247 /// #### Usage 3248 /// Each property requires a unique name for identification that is also used for 3249 /// displaying a label. If you want to use the same name multiple times make sure 3250 /// add a '#' before your name. The '#' will not be shown but will generate a 3251 /// unique ID. Each property also takes in a minimum and maximum value. If you want 3252 /// to make use of the complete number range of a type just use the provided 3253 /// type limits from `limits.h`. For example `INT_MIN` and `INT_MAX` for 3254 /// `nk_property_int` and `nk_propertyi`. In additional each property takes in 3255 /// a increment value that will be added or subtracted if either the increment 3256 /// decrement button is clicked. Finally there is a value for increment per pixel 3257 /// dragged that is added or subtracted from the value. 3258 /// 3259 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3260 /// int value = 0; 3261 /// struct nk_context ctx; 3262 /// nk_init_xxx(&ctx, ...); 3263 /// while (1) { 3264 /// // Input 3265 /// Event evt; 3266 /// nk_input_begin(&ctx); 3267 /// while (GetEvent(&evt)) { 3268 /// if (evt.type == MOUSE_MOVE) 3269 /// nk_input_motion(&ctx, evt.motion.x, evt.motion.y); 3270 /// else if (evt.type == [...]) { 3271 /// nk_input_xxx(...); 3272 /// } 3273 /// } 3274 /// nk_input_end(&ctx); 3275 /// // 3276 /// // Window 3277 /// if (nk_begin_xxx(...) { 3278 /// // Property 3279 /// nk_layout_row_dynamic(...); 3280 /// nk_property_int(ctx, "ID", INT_MIN, &value, INT_MAX, 1, 1); 3281 /// } 3282 /// nk_end(ctx); 3283 /// // 3284 /// // Draw 3285 /// const struct nk_command *cmd = 0; 3286 /// nk_foreach(cmd, &ctx) { 3287 /// switch (cmd->type) { 3288 /// case NK_COMMAND_LINE: 3289 /// your_draw_line_function(...) 3290 /// break; 3291 /// case NK_COMMAND_RECT 3292 /// your_draw_rect_function(...) 3293 /// break; 3294 /// case ...: 3295 /// // [...] 3296 /// } 3297 /// nk_clear(&ctx); 3298 /// } 3299 /// nk_free(&ctx); 3300 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3301 /// 3302 /// #### Reference 3303 /// Function | Description 3304 /// --------------------|------------------------------------------- 3305 /// nk_property_int | Integer property directly modifying a passed in value 3306 /// nk_property_float | Float property directly modifying a passed in value 3307 /// nk_property_double | Double property directly modifying a passed in value 3308 /// nk_propertyi | Integer property returning the modified int value 3309 /// nk_propertyf | Float property returning the modified float value 3310 /// nk_propertyd | Double property returning the modified double value 3311 /// 3312 */ 3313 /*/// #### nk_property_int 3314 /// Integer property directly modifying a passed in value 3315 /// !!! WARNING 3316 /// To generate a unique property ID using the same label make sure to insert 3317 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3318 /// 3319 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3320 /// void nk_property_int(struct nk_context *ctx, const char *name, int min, int *val, int max, int step, float inc_per_pixel); 3321 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3322 /// 3323 /// Parameter | Description 3324 /// --------------------|----------------------------------------------------------- 3325 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3326 /// __name__ | String used both as a label as well as a unique identifier 3327 /// __min__ | Minimum value not allowed to be underflown 3328 /// __val__ | Integer pointer to be modified 3329 /// __max__ | Maximum value not allowed to be overflown 3330 /// __step__ | Increment added and subtracted on increment and decrement button 3331 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3332 */ 3333 NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel); 3334 /*/// #### nk_property_float 3335 /// Float property directly modifying a passed in value 3336 /// !!! WARNING 3337 /// To generate a unique property ID using the same label make sure to insert 3338 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3339 /// 3340 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3341 /// void nk_property_float(struct nk_context *ctx, const char *name, float min, float *val, float max, float step, float inc_per_pixel); 3342 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3343 /// 3344 /// Parameter | Description 3345 /// --------------------|----------------------------------------------------------- 3346 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3347 /// __name__ | String used both as a label as well as a unique identifier 3348 /// __min__ | Minimum value not allowed to be underflown 3349 /// __val__ | Float pointer to be modified 3350 /// __max__ | Maximum value not allowed to be overflown 3351 /// __step__ | Increment added and subtracted on increment and decrement button 3352 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3353 */ 3354 NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel); 3355 /*/// #### nk_property_double 3356 /// Double property directly modifying a passed in value 3357 /// !!! WARNING 3358 /// To generate a unique property ID using the same label make sure to insert 3359 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3360 /// 3361 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3362 /// void nk_property_double(struct nk_context *ctx, const char *name, double min, double *val, double max, double step, double inc_per_pixel); 3363 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3364 /// 3365 /// Parameter | Description 3366 /// --------------------|----------------------------------------------------------- 3367 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3368 /// __name__ | String used both as a label as well as a unique identifier 3369 /// __min__ | Minimum value not allowed to be underflown 3370 /// __val__ | Double pointer to be modified 3371 /// __max__ | Maximum value not allowed to be overflown 3372 /// __step__ | Increment added and subtracted on increment and decrement button 3373 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3374 */ 3375 NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel); 3376 /*/// #### nk_propertyi 3377 /// Integer property modifying a passed in value and returning the new value 3378 /// !!! WARNING 3379 /// To generate a unique property ID using the same label make sure to insert 3380 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3381 /// 3382 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3383 /// int nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, int max, int step, float inc_per_pixel); 3384 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3385 /// 3386 /// Parameter | Description 3387 /// --------------------|----------------------------------------------------------- 3388 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3389 /// __name__ | String used both as a label as well as a unique identifier 3390 /// __min__ | Minimum value not allowed to be underflown 3391 /// __val__ | Current integer value to be modified and returned 3392 /// __max__ | Maximum value not allowed to be overflown 3393 /// __step__ | Increment added and subtracted on increment and decrement button 3394 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3395 /// 3396 /// Returns the new modified integer value 3397 */ 3398 NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel); 3399 /*/// #### nk_propertyf 3400 /// Float property modifying a passed in value and returning the new value 3401 /// !!! WARNING 3402 /// To generate a unique property ID using the same label make sure to insert 3403 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3404 /// 3405 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3406 /// float nk_propertyf(struct nk_context *ctx, const char *name, float min, float val, float max, float step, float inc_per_pixel); 3407 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3408 /// 3409 /// Parameter | Description 3410 /// --------------------|----------------------------------------------------------- 3411 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3412 /// __name__ | String used both as a label as well as a unique identifier 3413 /// __min__ | Minimum value not allowed to be underflown 3414 /// __val__ | Current float value to be modified and returned 3415 /// __max__ | Maximum value not allowed to be overflown 3416 /// __step__ | Increment added and subtracted on increment and decrement button 3417 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3418 /// 3419 /// Returns the new modified float value 3420 */ 3421 NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel); 3422 /*/// #### nk_propertyd 3423 /// Float property modifying a passed in value and returning the new value 3424 /// !!! WARNING 3425 /// To generate a unique property ID using the same label make sure to insert 3426 /// a `#` at the beginning. It will not be shown but guarantees correct behavior. 3427 /// 3428 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~c 3429 /// float nk_propertyd(struct nk_context *ctx, const char *name, double min, double val, double max, double step, double inc_per_pixel); 3430 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 3431 /// 3432 /// Parameter | Description 3433 /// --------------------|----------------------------------------------------------- 3434 /// __ctx__ | Must point to an previously initialized `nk_context` struct after calling a layouting function 3435 /// __name__ | String used both as a label as well as a unique identifier 3436 /// __min__ | Minimum value not allowed to be underflown 3437 /// __val__ | Current double value to be modified and returned 3438 /// __max__ | Maximum value not allowed to be overflown 3439 /// __step__ | Increment added and subtracted on increment and decrement button 3440 /// __inc_per_pixel__ | Value per pixel added or subtracted on dragging 3441 /// 3442 /// Returns the new modified double value 3443 */ 3444 NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel); 3445 /* ============================================================================= 3446 * 3447 * TEXT EDIT 3448 * 3449 * ============================================================================= */ 3450 enum nk_edit_flags { 3451 NK_EDIT_DEFAULT = 0, 3452 NK_EDIT_READ_ONLY = NK_FLAG(0), 3453 NK_EDIT_AUTO_SELECT = NK_FLAG(1), 3454 NK_EDIT_SIG_ENTER = NK_FLAG(2), 3455 NK_EDIT_ALLOW_TAB = NK_FLAG(3), 3456 NK_EDIT_NO_CURSOR = NK_FLAG(4), 3457 NK_EDIT_SELECTABLE = NK_FLAG(5), 3458 NK_EDIT_CLIPBOARD = NK_FLAG(6), 3459 NK_EDIT_CTRL_ENTER_NEWLINE = NK_FLAG(7), 3460 NK_EDIT_NO_HORIZONTAL_SCROLL = NK_FLAG(8), 3461 NK_EDIT_ALWAYS_INSERT_MODE = NK_FLAG(9), 3462 NK_EDIT_MULTILINE = NK_FLAG(10), 3463 NK_EDIT_GOTO_END_ON_ACTIVATE = NK_FLAG(11) 3464 }; 3465 enum nk_edit_types { 3466 NK_EDIT_SIMPLE = NK_EDIT_ALWAYS_INSERT_MODE, 3467 NK_EDIT_FIELD = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD, 3468 NK_EDIT_BOX = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD, 3469 NK_EDIT_EDITOR = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD 3470 }; 3471 enum nk_edit_events { 3472 NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */ 3473 NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */ 3474 NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */ 3475 NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */ 3476 NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */ 3477 }; 3478 NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter); 3479 NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter); 3480 NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter); 3481 NK_API void nk_edit_focus(struct nk_context*, nk_flags flags); 3482 NK_API void nk_edit_unfocus(struct nk_context*); 3483 /* ============================================================================= 3484 * 3485 * CHART 3486 * 3487 * ============================================================================= */ 3488 NK_API nk_bool nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max); 3489 NK_API nk_bool nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max); 3490 NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value); 3491 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); 3492 NK_API nk_flags nk_chart_push(struct nk_context*, float); 3493 NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int); 3494 NK_API void nk_chart_end(struct nk_context*); 3495 NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset); 3496 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); 3497 /* ============================================================================= 3498 * 3499 * POPUP 3500 * 3501 * ============================================================================= */ 3502 NK_API nk_bool nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds); 3503 NK_API void nk_popup_close(struct nk_context*); 3504 NK_API void nk_popup_end(struct nk_context*); 3505 NK_API void nk_popup_get_scroll(struct nk_context*, nk_uint *offset_x, nk_uint *offset_y); 3506 NK_API void nk_popup_set_scroll(struct nk_context*, nk_uint offset_x, nk_uint offset_y); 3507 /* ============================================================================= 3508 * 3509 * COMBOBOX 3510 * 3511 * ============================================================================= */ 3512 NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size); 3513 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); 3514 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); 3515 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); 3516 NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size); 3517 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); 3518 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); 3519 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); 3520 /* ============================================================================= 3521 * 3522 * ABSTRACT COMBOBOX 3523 * 3524 * ============================================================================= */ 3525 NK_API nk_bool nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size); 3526 NK_API nk_bool nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size); 3527 NK_API nk_bool nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size); 3528 NK_API nk_bool nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size); 3529 NK_API nk_bool nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size); 3530 NK_API nk_bool nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size); 3531 NK_API nk_bool nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size); 3532 NK_API nk_bool nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size); 3533 NK_API nk_bool nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size); 3534 NK_API nk_bool nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment); 3535 NK_API nk_bool nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment); 3536 NK_API nk_bool nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3537 NK_API nk_bool nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment); 3538 NK_API nk_bool nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3539 NK_API nk_bool nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3540 NK_API void nk_combo_close(struct nk_context*); 3541 NK_API void nk_combo_end(struct nk_context*); 3542 /* ============================================================================= 3543 * 3544 * CONTEXTUAL 3545 * 3546 * ============================================================================= */ 3547 NK_API nk_bool nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds); 3548 NK_API nk_bool nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align); 3549 NK_API nk_bool nk_contextual_item_label(struct nk_context*, const char*, nk_flags align); 3550 NK_API nk_bool nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3551 NK_API nk_bool nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); 3552 NK_API nk_bool nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3553 NK_API nk_bool nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3554 NK_API void nk_contextual_close(struct nk_context*); 3555 NK_API void nk_contextual_end(struct nk_context*); 3556 /* ============================================================================= 3557 * 3558 * TOOLTIP 3559 * 3560 * ============================================================================= */ 3561 NK_API void nk_tooltip(struct nk_context*, const char*); 3562 #ifdef NK_INCLUDE_STANDARD_VARARGS 3563 NK_API void nk_tooltipf(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, ...) NK_PRINTF_VARARG_FUNC(2); 3564 NK_API void nk_tooltipfv(struct nk_context*, NK_PRINTF_FORMAT_STRING const char*, va_list) NK_PRINTF_VALIST_FUNC(2); 3565 #endif 3566 NK_API nk_bool nk_tooltip_begin(struct nk_context*, float width); 3567 NK_API void nk_tooltip_end(struct nk_context*); 3568 /* ============================================================================= 3569 * 3570 * MENU 3571 * 3572 * ============================================================================= */ 3573 NK_API void nk_menubar_begin(struct nk_context*); 3574 NK_API void nk_menubar_end(struct nk_context*); 3575 NK_API nk_bool nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size); 3576 NK_API nk_bool nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size); 3577 NK_API nk_bool nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size); 3578 NK_API nk_bool nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size); 3579 NK_API nk_bool nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size); 3580 NK_API nk_bool nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size); 3581 NK_API nk_bool nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size); 3582 NK_API nk_bool nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size); 3583 NK_API nk_bool nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align); 3584 NK_API nk_bool nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment); 3585 NK_API nk_bool nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); 3586 NK_API nk_bool nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); 3587 NK_API nk_bool nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); 3588 NK_API nk_bool nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); 3589 NK_API void nk_menu_close(struct nk_context*); 3590 NK_API void nk_menu_end(struct nk_context*); 3591 /* ============================================================================= 3592 * 3593 * STYLE 3594 * 3595 * ============================================================================= */ 3596 enum nk_style_colors { 3597 NK_COLOR_TEXT, 3598 NK_COLOR_WINDOW, 3599 NK_COLOR_HEADER, 3600 NK_COLOR_BORDER, 3601 NK_COLOR_BUTTON, 3602 NK_COLOR_BUTTON_HOVER, 3603 NK_COLOR_BUTTON_ACTIVE, 3604 NK_COLOR_TOGGLE, 3605 NK_COLOR_TOGGLE_HOVER, 3606 NK_COLOR_TOGGLE_CURSOR, 3607 NK_COLOR_SELECT, 3608 NK_COLOR_SELECT_ACTIVE, 3609 NK_COLOR_SLIDER, 3610 NK_COLOR_SLIDER_CURSOR, 3611 NK_COLOR_SLIDER_CURSOR_HOVER, 3612 NK_COLOR_SLIDER_CURSOR_ACTIVE, 3613 NK_COLOR_PROPERTY, 3614 NK_COLOR_EDIT, 3615 NK_COLOR_EDIT_CURSOR, 3616 NK_COLOR_COMBO, 3617 NK_COLOR_CHART, 3618 NK_COLOR_CHART_COLOR, 3619 NK_COLOR_CHART_COLOR_HIGHLIGHT, 3620 NK_COLOR_SCROLLBAR, 3621 NK_COLOR_SCROLLBAR_CURSOR, 3622 NK_COLOR_SCROLLBAR_CURSOR_HOVER, 3623 NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 3624 NK_COLOR_TAB_HEADER, 3625 NK_COLOR_COUNT 3626 }; 3627 enum nk_style_cursor { 3628 NK_CURSOR_ARROW, 3629 NK_CURSOR_TEXT, 3630 NK_CURSOR_MOVE, 3631 NK_CURSOR_RESIZE_VERTICAL, 3632 NK_CURSOR_RESIZE_HORIZONTAL, 3633 NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT, 3634 NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT, 3635 NK_CURSOR_COUNT 3636 }; 3637 NK_API void nk_style_default(struct nk_context*); 3638 NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*); 3639 NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*); 3640 NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*); 3641 NK_API const char* nk_style_get_color_by_name(enum nk_style_colors); 3642 NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*); 3643 NK_API nk_bool nk_style_set_cursor(struct nk_context*, enum nk_style_cursor); 3644 NK_API void nk_style_show_cursor(struct nk_context*); 3645 NK_API void nk_style_hide_cursor(struct nk_context*); 3646 3647 NK_API nk_bool nk_style_push_font(struct nk_context*, const struct nk_user_font*); 3648 NK_API nk_bool nk_style_push_float(struct nk_context*, float*, float); 3649 NK_API nk_bool nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2); 3650 NK_API nk_bool nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item); 3651 NK_API nk_bool nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags); 3652 NK_API nk_bool nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color); 3653 3654 NK_API nk_bool nk_style_pop_font(struct nk_context*); 3655 NK_API nk_bool nk_style_pop_float(struct nk_context*); 3656 NK_API nk_bool nk_style_pop_vec2(struct nk_context*); 3657 NK_API nk_bool nk_style_pop_style_item(struct nk_context*); 3658 NK_API nk_bool nk_style_pop_flags(struct nk_context*); 3659 NK_API nk_bool nk_style_pop_color(struct nk_context*); 3660 /* ============================================================================= 3661 * 3662 * COLOR 3663 * 3664 * ============================================================================= */ 3665 NK_API struct nk_color nk_rgb(int r, int g, int b); 3666 NK_API struct nk_color nk_rgb_iv(const int *rgb); 3667 NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb); 3668 NK_API struct nk_color nk_rgb_f(float r, float g, float b); 3669 NK_API struct nk_color nk_rgb_fv(const float *rgb); 3670 NK_API struct nk_color nk_rgb_cf(struct nk_colorf c); 3671 NK_API struct nk_color nk_rgb_hex(const char *rgb); 3672 3673 NK_API struct nk_color nk_rgba(int r, int g, int b, int a); 3674 NK_API struct nk_color nk_rgba_u32(nk_uint); 3675 NK_API struct nk_color nk_rgba_iv(const int *rgba); 3676 NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba); 3677 NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a); 3678 NK_API struct nk_color nk_rgba_fv(const float *rgba); 3679 NK_API struct nk_color nk_rgba_cf(struct nk_colorf c); 3680 NK_API struct nk_color nk_rgba_hex(const char *rgb); 3681 3682 NK_API struct nk_colorf nk_hsva_colorf(float h, float s, float v, float a); 3683 NK_API struct nk_colorf nk_hsva_colorfv(float *c); 3684 NK_API void nk_colorf_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_colorf in); 3685 NK_API void nk_colorf_hsva_fv(float *hsva, struct nk_colorf in); 3686 3687 NK_API struct nk_color nk_hsv(int h, int s, int v); 3688 NK_API struct nk_color nk_hsv_iv(const int *hsv); 3689 NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv); 3690 NK_API struct nk_color nk_hsv_f(float h, float s, float v); 3691 NK_API struct nk_color nk_hsv_fv(const float *hsv); 3692 3693 NK_API struct nk_color nk_hsva(int h, int s, int v, int a); 3694 NK_API struct nk_color nk_hsva_iv(const int *hsva); 3695 NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva); 3696 NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a); 3697 NK_API struct nk_color nk_hsva_fv(const float *hsva); 3698 3699 /* color (conversion nuklear --> user) */ 3700 NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color); 3701 NK_API void nk_color_fv(float *rgba_out, struct nk_color); 3702 NK_API struct nk_colorf nk_color_cf(struct nk_color); 3703 NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color); 3704 NK_API void nk_color_dv(double *rgba_out, struct nk_color); 3705 3706 NK_API nk_uint nk_color_u32(struct nk_color); 3707 NK_API void nk_color_hex_rgba(char *output, struct nk_color); 3708 NK_API void nk_color_hex_rgb(char *output, struct nk_color); 3709 3710 NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color); 3711 NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color); 3712 NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color); 3713 NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color); 3714 NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color); 3715 NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color); 3716 3717 NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color); 3718 NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color); 3719 NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color); 3720 NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color); 3721 NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color); 3722 NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color); 3723 /* ============================================================================= 3724 * 3725 * IMAGE 3726 * 3727 * ============================================================================= */ 3728 NK_API nk_handle nk_handle_ptr(void*); 3729 NK_API nk_handle nk_handle_id(int); 3730 NK_API struct nk_image nk_image_handle(nk_handle); 3731 NK_API struct nk_image nk_image_ptr(void*); 3732 NK_API struct nk_image nk_image_id(int); 3733 NK_API nk_bool nk_image_is_subimage(const struct nk_image* img); 3734 NK_API struct nk_image nk_subimage_ptr(void*, nk_ushort w, nk_ushort h, struct nk_rect sub_region); 3735 NK_API struct nk_image nk_subimage_id(int, nk_ushort w, nk_ushort h, struct nk_rect sub_region); 3736 NK_API struct nk_image nk_subimage_handle(nk_handle, nk_ushort w, nk_ushort h, struct nk_rect sub_region); 3737 /* ============================================================================= 3738 * 3739 * 9-SLICE 3740 * 3741 * ============================================================================= */ 3742 NK_API struct nk_nine_slice nk_nine_slice_handle(nk_handle, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b); 3743 NK_API struct nk_nine_slice nk_nine_slice_ptr(void*, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b); 3744 NK_API struct nk_nine_slice nk_nine_slice_id(int, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b); 3745 NK_API int nk_nine_slice_is_sub9slice(const struct nk_nine_slice* img); 3746 NK_API struct nk_nine_slice nk_sub9slice_ptr(void*, nk_ushort w, nk_ushort h, struct nk_rect sub_region, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b); 3747 NK_API struct nk_nine_slice nk_sub9slice_id(int, nk_ushort w, nk_ushort h, struct nk_rect sub_region, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b); 3748 NK_API struct nk_nine_slice nk_sub9slice_handle(nk_handle, nk_ushort w, nk_ushort h, struct nk_rect sub_region, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b); 3749 /* ============================================================================= 3750 * 3751 * MATH 3752 * 3753 * ============================================================================= */ 3754 NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed); 3755 NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading); 3756 3757 NK_API struct nk_vec2 nk_vec2(float x, float y); 3758 NK_API struct nk_vec2 nk_vec2i(int x, int y); 3759 NK_API struct nk_vec2 nk_vec2v(const float *xy); 3760 NK_API struct nk_vec2 nk_vec2iv(const int *xy); 3761 3762 NK_API struct nk_rect nk_get_null_rect(void); 3763 NK_API struct nk_rect nk_rect(float x, float y, float w, float h); 3764 NK_API struct nk_rect nk_recti(int x, int y, int w, int h); 3765 NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size); 3766 NK_API struct nk_rect nk_rectv(const float *xywh); 3767 NK_API struct nk_rect nk_rectiv(const int *xywh); 3768 NK_API struct nk_vec2 nk_rect_pos(struct nk_rect); 3769 NK_API struct nk_vec2 nk_rect_size(struct nk_rect); 3770 /* ============================================================================= 3771 * 3772 * STRING 3773 * 3774 * ============================================================================= */ 3775 NK_API int nk_strlen(const char *str); 3776 NK_API int nk_stricmp(const char *s1, const char *s2); 3777 NK_API int nk_stricmpn(const char *s1, const char *s2, int n); 3778 NK_API int nk_strtoi(const char *str, const char **endptr); 3779 NK_API float nk_strtof(const char *str, const char **endptr); 3780 #ifndef NK_STRTOD 3781 #define NK_STRTOD nk_strtod 3782 NK_API double nk_strtod(const char *str, const char **endptr); 3783 #endif 3784 NK_API int nk_strfilter(const char *text, const char *regexp); 3785 NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score); 3786 NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score); 3787 /* ============================================================================= 3788 * 3789 * UTF-8 3790 * 3791 * ============================================================================= */ 3792 NK_API int nk_utf_decode(const char*, nk_rune*, int); 3793 NK_API int nk_utf_encode(nk_rune, char*, int); 3794 NK_API int nk_utf_len(const char*, int byte_len); 3795 NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len); 3796 /* =============================================================== 3797 * 3798 * FONT 3799 * 3800 * ===============================================================*/ 3801 /*/// ### Font 3802 /// Font handling in this library was designed to be quite customizable and lets 3803 /// you decide what you want to use and what you want to provide. There are three 3804 /// different ways to use the font atlas. The first two will use your font 3805 /// handling scheme and only requires essential data to run nuklear. The next 3806 /// slightly more advanced features is font handling with vertex buffer output. 3807 /// Finally the most complex API wise is using nuklear's font baking API. 3808 // 3809 /// #### Using your own implementation without vertex buffer output 3810 /// 3811 /// So first up the easiest way to do font handling is by just providing a 3812 /// `nk_user_font` struct which only requires the height in pixel of the used 3813 /// font and a callback to calculate the width of a string. This way of handling 3814 /// fonts is best fitted for using the normal draw shape command API where you 3815 /// do all the text drawing yourself and the library does not require any kind 3816 /// of deeper knowledge about which font handling mechanism you use. 3817 /// IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist 3818 /// over the complete life time! I know this sucks but it is currently the only 3819 /// way to switch between fonts. 3820 /// 3821 /// ```c 3822 /// float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) 3823 /// { 3824 /// your_font_type *type = handle.ptr; 3825 /// float text_width = ...; 3826 /// return text_width; 3827 /// } 3828 /// 3829 /// struct nk_user_font font; 3830 /// font.userdata.ptr = &your_font_class_or_struct; 3831 /// font.height = your_font_height; 3832 /// font.width = your_text_width_calculation; 3833 /// 3834 /// struct nk_context ctx; 3835 /// nk_init_default(&ctx, &font); 3836 /// ``` 3837 /// #### Using your own implementation with vertex buffer output 3838 /// 3839 /// While the first approach works fine if you don't want to use the optional 3840 /// vertex buffer output it is not enough if you do. To get font handling working 3841 /// for these cases you have to provide two additional parameters inside the 3842 /// `nk_user_font`. First a texture atlas handle used to draw text as subimages 3843 /// of a bigger font atlas texture and a callback to query a character's glyph 3844 /// information (offset, size, ...). So it is still possible to provide your own 3845 /// font and use the vertex buffer output. 3846 /// 3847 /// ```c 3848 /// float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) 3849 /// { 3850 /// your_font_type *type = handle.ptr; 3851 /// float text_width = ...; 3852 /// return text_width; 3853 /// } 3854 /// void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) 3855 /// { 3856 /// your_font_type *type = handle.ptr; 3857 /// glyph.width = ...; 3858 /// glyph.height = ...; 3859 /// glyph.xadvance = ...; 3860 /// glyph.uv[0].x = ...; 3861 /// glyph.uv[0].y = ...; 3862 /// glyph.uv[1].x = ...; 3863 /// glyph.uv[1].y = ...; 3864 /// glyph.offset.x = ...; 3865 /// glyph.offset.y = ...; 3866 /// } 3867 /// 3868 /// struct nk_user_font font; 3869 /// font.userdata.ptr = &your_font_class_or_struct; 3870 /// font.height = your_font_height; 3871 /// font.width = your_text_width_calculation; 3872 /// font.query = query_your_font_glyph; 3873 /// font.texture.id = your_font_texture; 3874 /// 3875 /// struct nk_context ctx; 3876 /// nk_init_default(&ctx, &font); 3877 /// ``` 3878 /// 3879 /// #### Nuklear font baker 3880 /// 3881 /// The final approach if you do not have a font handling functionality or don't 3882 /// want to use it in this library is by using the optional font baker. 3883 /// The font baker APIs can be used to create a font plus font atlas texture 3884 /// and can be used with or without the vertex buffer output. 3885 /// 3886 /// It still uses the `nk_user_font` struct and the two different approaches 3887 /// previously stated still work. The font baker is not located inside 3888 /// `nk_context` like all other systems since it can be understood as more of 3889 /// an extension to nuklear and does not really depend on any `nk_context` state. 3890 /// 3891 /// Font baker need to be initialized first by one of the nk_font_atlas_init_xxx 3892 /// functions. If you don't care about memory just call the default version 3893 /// `nk_font_atlas_init_default` which will allocate all memory from the standard library. 3894 /// If you want to control memory allocation but you don't care if the allocated 3895 /// memory is temporary and therefore can be freed directly after the baking process 3896 /// is over or permanent you can call `nk_font_atlas_init`. 3897 /// 3898 /// After successfully initializing the font baker you can add Truetype(.ttf) fonts from 3899 /// different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`. 3900 /// functions. Adding font will permanently store each font, font config and ttf memory block(!) 3901 /// inside the font atlas and allows to reuse the font atlas. If you don't want to reuse 3902 /// the font baker by for example adding additional fonts you can call 3903 /// `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end). 3904 /// 3905 /// As soon as you added all fonts you wanted you can now start the baking process 3906 /// for every selected glyph to image by calling `nk_font_atlas_bake`. 3907 /// The baking process returns image memory, width and height which can be used to 3908 /// either create your own image object or upload it to any graphics library. 3909 /// No matter which case you finally have to call `nk_font_atlas_end` which 3910 /// will free all temporary memory including the font atlas image so make sure 3911 /// you created our texture beforehand. `nk_font_atlas_end` requires a handle 3912 /// to your font texture or object and optionally fills a `struct nk_draw_null_texture` 3913 /// which can be used for the optional vertex output. If you don't want it just 3914 /// set the argument to `NULL`. 3915 /// 3916 /// At this point you are done and if you don't want to reuse the font atlas you 3917 /// can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration 3918 /// memory. Finally if you don't use the font atlas and any of it's fonts anymore 3919 /// you need to call `nk_font_atlas_clear` to free all memory still being used. 3920 /// 3921 /// ```c 3922 /// struct nk_font_atlas atlas; 3923 /// nk_font_atlas_init_default(&atlas); 3924 /// nk_font_atlas_begin(&atlas); 3925 /// nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0); 3926 /// nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0); 3927 /// const void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32); 3928 /// nk_font_atlas_end(&atlas, nk_handle_id(texture), 0); 3929 /// 3930 /// struct nk_context ctx; 3931 /// nk_init_default(&ctx, &font->handle); 3932 /// while (1) { 3933 /// 3934 /// } 3935 /// nk_font_atlas_clear(&atlas); 3936 /// ``` 3937 /// The font baker API is probably the most complex API inside this library and 3938 /// I would suggest reading some of my examples `example/` to get a grip on how 3939 /// to use the font atlas. There are a number of details I left out. For example 3940 /// how to merge fonts, configure a font with `nk_font_config` to use other languages, 3941 /// use another texture coordinate format and a lot more: 3942 /// 3943 /// ```c 3944 /// struct nk_font_config cfg = nk_font_config(font_pixel_height); 3945 /// cfg.merge_mode = nk_false or nk_true; 3946 /// cfg.range = nk_font_korean_glyph_ranges(); 3947 /// cfg.coord_type = NK_COORD_PIXEL; 3948 /// nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg); 3949 /// ``` 3950 */ 3951 struct nk_user_font_glyph; 3952 typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len); 3953 typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height, 3954 struct nk_user_font_glyph *glyph, 3955 nk_rune codepoint, nk_rune next_codepoint); 3956 3957 #if defined(NK_INCLUDE_VERTEX_BUFFER_OUTPUT) || defined(NK_INCLUDE_SOFTWARE_FONT) 3958 struct nk_user_font_glyph { 3959 struct nk_vec2 uv[2]; 3960 /* texture coordinates */ 3961 struct nk_vec2 offset; 3962 /* offset between top left and glyph */ 3963 float width, height; 3964 /* size of the glyph */ 3965 float xadvance; 3966 /* offset to the next glyph */ 3967 }; 3968 #endif 3969 3970 struct nk_user_font { 3971 nk_handle userdata; 3972 /* user provided font handle */ 3973 float height; 3974 /* max height of the font */ 3975 nk_text_width_f width; 3976 /* font string width in pixel callback */ 3977 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 3978 nk_query_font_glyph_f query; 3979 /* font glyph callback to query drawing info */ 3980 nk_handle texture; 3981 /* texture handle to the used font atlas or texture */ 3982 #endif 3983 }; 3984 3985 #ifdef NK_INCLUDE_FONT_BAKING 3986 enum nk_font_coord_type { 3987 NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */ 3988 NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */ 3989 }; 3990 3991 struct nk_font; 3992 struct nk_baked_font { 3993 float height; 3994 /* height of the font */ 3995 float ascent, descent; 3996 /* font glyphs ascent and descent */ 3997 nk_rune glyph_offset; 3998 /* glyph array offset inside the font glyph baking output array */ 3999 nk_rune glyph_count; 4000 /* number of glyphs of this font inside the glyph baking array output */ 4001 const nk_rune *ranges; 4002 /* font codepoint ranges as pairs of (from/to) and 0 as last element */ 4003 }; 4004 4005 struct nk_font_config { 4006 struct nk_font_config *next; 4007 /* NOTE: only used internally */ 4008 void *ttf_blob; 4009 /* pointer to loaded TTF file memory block. 4010 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ 4011 nk_size ttf_size; 4012 /* size of the loaded TTF file memory block 4013 * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ 4014 4015 unsigned char ttf_data_owned_by_atlas; 4016 /* used inside font atlas: default to: 0*/ 4017 unsigned char merge_mode; 4018 /* merges this font into the last font */ 4019 unsigned char pixel_snap; 4020 /* align every character to pixel boundary (if true set oversample (1,1)) */ 4021 unsigned char oversample_v, oversample_h; 4022 /* rasterize at high quality for sub-pixel position */ 4023 unsigned char padding[3]; 4024 4025 float size; 4026 /* baked pixel height of the font */ 4027 enum nk_font_coord_type coord_type; 4028 /* texture coordinate format with either pixel or UV coordinates */ 4029 struct nk_vec2 spacing; 4030 /* extra pixel spacing between glyphs */ 4031 const nk_rune *range; 4032 /* list of unicode ranges (2 values per range, zero terminated) */ 4033 struct nk_baked_font *font; 4034 /* font to setup in the baking process: NOTE: not needed for font atlas */ 4035 nk_rune fallback_glyph; 4036 /* fallback glyph to use if a given rune is not found */ 4037 struct nk_font_config *n; 4038 struct nk_font_config *p; 4039 }; 4040 4041 struct nk_font_glyph { 4042 nk_rune codepoint; 4043 float xadvance; 4044 float x0, y0, x1, y1, w, h; 4045 float u0, v0, u1, v1; 4046 }; 4047 4048 struct nk_font { 4049 struct nk_font *next; 4050 struct nk_user_font handle; 4051 struct nk_baked_font info; 4052 float scale; 4053 struct nk_font_glyph *glyphs; 4054 const struct nk_font_glyph *fallback; 4055 nk_rune fallback_codepoint; 4056 nk_handle texture; 4057 struct nk_font_config *config; 4058 }; 4059 4060 enum nk_font_atlas_format { 4061 NK_FONT_ATLAS_ALPHA8, 4062 NK_FONT_ATLAS_RGBA32 4063 }; 4064 4065 struct nk_font_atlas { 4066 void *pixel; 4067 int tex_width; 4068 int tex_height; 4069 4070 struct nk_allocator permanent; 4071 struct nk_allocator temporary; 4072 4073 struct nk_recti custom; 4074 struct nk_cursor cursors[NK_CURSOR_COUNT]; 4075 4076 int glyph_count; 4077 struct nk_font_glyph *glyphs; 4078 struct nk_font *default_font; 4079 struct nk_font *fonts; 4080 struct nk_font_config *config; 4081 int font_num; 4082 }; 4083 4084 /* some language glyph codepoint ranges */ 4085 NK_API const nk_rune *nk_font_default_glyph_ranges(void); 4086 NK_API const nk_rune *nk_font_chinese_glyph_ranges(void); 4087 NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void); 4088 NK_API const nk_rune *nk_font_korean_glyph_ranges(void); 4089 4090 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4091 NK_API void nk_font_atlas_init_default(struct nk_font_atlas*); 4092 #endif 4093 NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*); 4094 NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient); 4095 NK_API void nk_font_atlas_begin(struct nk_font_atlas*); 4096 NK_API struct nk_font_config nk_font_config(float pixel_height); 4097 NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*); 4098 #ifdef NK_INCLUDE_DEFAULT_FONT 4099 NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*); 4100 #endif 4101 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); 4102 #ifdef NK_INCLUDE_STANDARD_IO 4103 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*); 4104 #endif 4105 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*); 4106 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); 4107 NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format); 4108 NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*); 4109 NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode); 4110 NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas); 4111 NK_API void nk_font_atlas_clear(struct nk_font_atlas*); 4112 4113 #endif 4114 4115 /* ============================================================== 4116 * 4117 * MEMORY BUFFER 4118 * 4119 * ===============================================================*/ 4120 /*/// ### Memory Buffer 4121 /// A basic (double)-buffer with linear allocation and resetting as only 4122 /// freeing policy. The buffer's main purpose is to control all memory management 4123 /// inside the GUI toolkit and still leave memory control as much as possible in 4124 /// the hand of the user while also making sure the library is easy to use if 4125 /// not as much control is needed. 4126 /// In general all memory inside this library can be provided from the user in 4127 /// three different ways. 4128 /// 4129 /// The first way and the one providing most control is by just passing a fixed 4130 /// size memory block. In this case all control lies in the hand of the user 4131 /// since he can exactly control where the memory comes from and how much memory 4132 /// the library should consume. Of course using the fixed size API removes the 4133 /// ability to automatically resize a buffer if not enough memory is provided so 4134 /// you have to take over the resizing. While being a fixed sized buffer sounds 4135 /// quite limiting, it is very effective in this library since the actual memory 4136 /// consumption is quite stable and has a fixed upper bound for a lot of cases. 4137 /// 4138 /// If you don't want to think about how much memory the library should allocate 4139 /// at all time or have a very dynamic UI with unpredictable memory consumption 4140 /// habits but still want control over memory allocation you can use the dynamic 4141 /// allocator based API. The allocator consists of two callbacks for allocating 4142 /// and freeing memory and optional userdata so you can plugin your own allocator. 4143 /// 4144 /// The final and easiest way can be used by defining 4145 /// NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory 4146 /// allocation functions malloc and free and takes over complete control over 4147 /// memory in this library. 4148 */ 4149 struct nk_memory_status { 4150 void *memory; 4151 unsigned int type; 4152 nk_size size; 4153 nk_size allocated; 4154 nk_size needed; 4155 nk_size calls; 4156 }; 4157 4158 enum nk_allocation_type { 4159 NK_BUFFER_FIXED, 4160 NK_BUFFER_DYNAMIC 4161 }; 4162 4163 enum nk_buffer_allocation_type { 4164 NK_BUFFER_FRONT, 4165 NK_BUFFER_BACK, 4166 NK_BUFFER_MAX 4167 }; 4168 4169 struct nk_buffer_marker { 4170 nk_bool active; 4171 nk_size offset; 4172 }; 4173 4174 struct nk_memory {void *ptr;nk_size size;}; 4175 struct nk_buffer { 4176 struct nk_buffer_marker marker[NK_BUFFER_MAX]; 4177 /* buffer marker to free a buffer to a certain offset */ 4178 struct nk_allocator pool; 4179 /* allocator callback for dynamic buffers */ 4180 enum nk_allocation_type type; 4181 /* memory management type */ 4182 struct nk_memory memory; 4183 /* memory and size of the current memory block */ 4184 float grow_factor; 4185 /* growing factor for dynamic memory management */ 4186 nk_size allocated; 4187 /* total amount of memory allocated */ 4188 nk_size needed; 4189 /* totally consumed memory given that enough memory is present */ 4190 nk_size calls; 4191 /* number of allocation calls */ 4192 nk_size size; 4193 /* current size of the buffer */ 4194 }; 4195 4196 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4197 NK_API void nk_buffer_init_default(struct nk_buffer*); 4198 #endif 4199 NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size); 4200 NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size); 4201 NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*); 4202 NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align); 4203 NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type); 4204 NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type); 4205 NK_API void nk_buffer_clear(struct nk_buffer*); 4206 NK_API void nk_buffer_free(struct nk_buffer*); 4207 NK_API void *nk_buffer_memory(struct nk_buffer*); 4208 NK_API const void *nk_buffer_memory_const(const struct nk_buffer*); 4209 NK_API nk_size nk_buffer_total(struct nk_buffer*); 4210 4211 /* ============================================================== 4212 * 4213 * STRING 4214 * 4215 * ===============================================================*/ 4216 /* Basic string buffer which is only used in context with the text editor 4217 * to manage and manipulate dynamic or fixed size string content. This is _NOT_ 4218 * the default string handling method. The only instance you should have any contact 4219 * with this API is if you interact with an `nk_text_edit` object inside one of the 4220 * copy and paste functions and even there only for more advanced cases. */ 4221 struct nk_str { 4222 struct nk_buffer buffer; 4223 int len; /* in codepoints/runes/glyphs */ 4224 }; 4225 4226 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4227 NK_API void nk_str_init_default(struct nk_str*); 4228 #endif 4229 NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size); 4230 NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size); 4231 NK_API void nk_str_clear(struct nk_str*); 4232 NK_API void nk_str_free(struct nk_str*); 4233 4234 NK_API int nk_str_append_text_char(struct nk_str*, const char*, int); 4235 NK_API int nk_str_append_str_char(struct nk_str*, const char*); 4236 NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int); 4237 NK_API int nk_str_append_str_utf8(struct nk_str*, const char*); 4238 NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int); 4239 NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*); 4240 4241 NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int); 4242 NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int); 4243 4244 NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int); 4245 NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*); 4246 NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int); 4247 NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*); 4248 NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int); 4249 NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*); 4250 4251 NK_API void nk_str_remove_chars(struct nk_str*, int len); 4252 NK_API void nk_str_remove_runes(struct nk_str *str, int len); 4253 NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len); 4254 NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len); 4255 4256 NK_API char *nk_str_at_char(struct nk_str*, int pos); 4257 NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len); 4258 NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos); 4259 NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos); 4260 NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len); 4261 4262 NK_API char *nk_str_get(struct nk_str*); 4263 NK_API const char *nk_str_get_const(const struct nk_str*); 4264 NK_API int nk_str_len(struct nk_str*); 4265 NK_API int nk_str_len_char(struct nk_str*); 4266 4267 /*=============================================================== 4268 * 4269 * TEXT EDITOR 4270 * 4271 * ===============================================================*/ 4272 /*/// ### Text Editor 4273 /// Editing text in this library is handled by either `nk_edit_string` or 4274 /// `nk_edit_buffer`. But like almost everything in this library there are multiple 4275 /// ways of doing it and a balance between control and ease of use with memory 4276 /// as well as functionality controlled by flags. 4277 /// 4278 /// This library generally allows three different levels of memory control: 4279 /// First of is the most basic way of just providing a simple char array with 4280 /// string length. This method is probably the easiest way of handling simple 4281 /// user text input. Main upside is complete control over memory while the biggest 4282 /// downside in comparison with the other two approaches is missing undo/redo. 4283 /// 4284 /// For UIs that require undo/redo the second way was created. It is based on 4285 /// a fixed size nk_text_edit struct, which has an internal undo/redo stack. 4286 /// This is mainly useful if you want something more like a text editor but don't want 4287 /// to have a dynamically growing buffer. 4288 /// 4289 /// The final way is using a dynamically growing nk_text_edit struct, which 4290 /// has both a default version if you don't care where memory comes from and an 4291 /// allocator version if you do. While the text editor is quite powerful for its 4292 /// complexity I would not recommend editing gigabytes of data with it. 4293 /// It is rather designed for uses cases which make sense for a GUI library not for 4294 /// an full blown text editor. 4295 */ 4296 #ifndef NK_TEXTEDIT_UNDOSTATECOUNT 4297 #define NK_TEXTEDIT_UNDOSTATECOUNT 99 4298 #endif 4299 4300 #ifndef NK_TEXTEDIT_UNDOCHARCOUNT 4301 #define NK_TEXTEDIT_UNDOCHARCOUNT 999 4302 #endif 4303 4304 struct nk_text_edit; 4305 struct nk_clipboard { 4306 nk_handle userdata; 4307 nk_plugin_paste paste; 4308 nk_plugin_copy copy; 4309 }; 4310 4311 struct nk_text_undo_record { 4312 int where; 4313 short insert_length; 4314 short delete_length; 4315 short char_storage; 4316 }; 4317 4318 struct nk_text_undo_state { 4319 struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]; 4320 nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]; 4321 short undo_point; 4322 short redo_point; 4323 short undo_char_point; 4324 short redo_char_point; 4325 }; 4326 4327 enum nk_text_edit_type { 4328 NK_TEXT_EDIT_SINGLE_LINE, 4329 NK_TEXT_EDIT_MULTI_LINE 4330 }; 4331 4332 enum nk_text_edit_mode { 4333 NK_TEXT_EDIT_MODE_VIEW, 4334 NK_TEXT_EDIT_MODE_INSERT, 4335 NK_TEXT_EDIT_MODE_REPLACE 4336 }; 4337 4338 struct nk_text_edit { 4339 struct nk_clipboard clip; 4340 struct nk_str string; 4341 nk_plugin_filter filter; 4342 struct nk_vec2 scrollbar; 4343 4344 int cursor; 4345 int select_start; 4346 int select_end; 4347 unsigned char mode; 4348 unsigned char cursor_at_end_of_line; 4349 unsigned char initialized; 4350 unsigned char has_preferred_x; 4351 unsigned char single_line; 4352 unsigned char active; 4353 unsigned char padding1; 4354 float preferred_x; 4355 struct nk_text_undo_state undo; 4356 }; 4357 4358 /* filter function */ 4359 NK_API nk_bool nk_filter_default(const struct nk_text_edit*, nk_rune unicode); 4360 NK_API nk_bool nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode); 4361 NK_API nk_bool nk_filter_float(const struct nk_text_edit*, nk_rune unicode); 4362 NK_API nk_bool nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode); 4363 NK_API nk_bool nk_filter_hex(const struct nk_text_edit*, nk_rune unicode); 4364 NK_API nk_bool nk_filter_oct(const struct nk_text_edit*, nk_rune unicode); 4365 NK_API nk_bool nk_filter_binary(const struct nk_text_edit*, nk_rune unicode); 4366 4367 /* text editor */ 4368 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 4369 NK_API void nk_textedit_init_default(struct nk_text_edit*); 4370 #endif 4371 NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size); 4372 NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size); 4373 NK_API void nk_textedit_free(struct nk_text_edit*); 4374 NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len); 4375 NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len); 4376 NK_API void nk_textedit_delete_selection(struct nk_text_edit*); 4377 NK_API void nk_textedit_select_all(struct nk_text_edit*); 4378 NK_API nk_bool nk_textedit_cut(struct nk_text_edit*); 4379 NK_API nk_bool nk_textedit_paste(struct nk_text_edit*, char const*, int len); 4380 NK_API void nk_textedit_undo(struct nk_text_edit*); 4381 NK_API void nk_textedit_redo(struct nk_text_edit*); 4382 4383 /* =============================================================== 4384 * 4385 * DRAWING 4386 * 4387 * ===============================================================*/ 4388 /*/// ### Drawing 4389 /// This library was designed to be render backend agnostic so it does 4390 /// not draw anything to screen. Instead all drawn shapes, widgets 4391 /// are made of, are buffered into memory and make up a command queue. 4392 /// Each frame therefore fills the command buffer with draw commands 4393 /// that then need to be executed by the user and his own render backend. 4394 /// After that the command buffer needs to be cleared and a new frame can be 4395 /// started. It is probably important to note that the command buffer is the main 4396 /// drawing API and the optional vertex buffer API only takes this format and 4397 /// converts it into a hardware accessible format. 4398 /// 4399 /// To use the command queue to draw your own widgets you can access the 4400 /// command buffer of each window by calling `nk_window_get_canvas` after 4401 /// previously having called `nk_begin`: 4402 /// 4403 /// ```c 4404 /// void draw_red_rectangle_widget(struct nk_context *ctx) 4405 /// { 4406 /// struct nk_command_buffer *canvas; 4407 /// struct nk_input *input = &ctx->input; 4408 /// canvas = nk_window_get_canvas(ctx); 4409 /// 4410 /// struct nk_rect space; 4411 /// enum nk_widget_layout_states state; 4412 /// state = nk_widget(&space, ctx); 4413 /// if (!state) return; 4414 /// 4415 /// if (state != NK_WIDGET_ROM) 4416 /// update_your_widget_by_user_input(...); 4417 /// nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0)); 4418 /// } 4419 /// 4420 /// if (nk_begin(...)) { 4421 /// nk_layout_row_dynamic(ctx, 25, 1); 4422 /// draw_red_rectangle_widget(ctx); 4423 /// } 4424 /// nk_end(..) 4425 /// 4426 /// ``` 4427 /// Important to know if you want to create your own widgets is the `nk_widget` 4428 /// call. It allocates space on the panel reserved for this widget to be used, 4429 /// but also returns the state of the widget space. If your widget is not seen and does 4430 /// not have to be updated it is '0' and you can just return. If it only has 4431 /// to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both 4432 /// update and draw your widget. The reason for separating is to only draw and 4433 /// update what is actually necessary which is crucial for performance. 4434 */ 4435 enum nk_command_type { 4436 NK_COMMAND_NOP, 4437 NK_COMMAND_SCISSOR, 4438 NK_COMMAND_LINE, 4439 NK_COMMAND_CURVE, 4440 NK_COMMAND_RECT, 4441 NK_COMMAND_RECT_FILLED, 4442 NK_COMMAND_RECT_MULTI_COLOR, 4443 NK_COMMAND_CIRCLE, 4444 NK_COMMAND_CIRCLE_FILLED, 4445 NK_COMMAND_ARC, 4446 NK_COMMAND_ARC_FILLED, 4447 NK_COMMAND_TRIANGLE, 4448 NK_COMMAND_TRIANGLE_FILLED, 4449 NK_COMMAND_POLYGON, 4450 NK_COMMAND_POLYGON_FILLED, 4451 NK_COMMAND_POLYLINE, 4452 NK_COMMAND_TEXT, 4453 NK_COMMAND_IMAGE, 4454 NK_COMMAND_CUSTOM 4455 }; 4456 4457 /* command base and header of every command inside the buffer */ 4458 struct nk_command { 4459 enum nk_command_type type; 4460 nk_size next; 4461 #ifdef NK_INCLUDE_COMMAND_USERDATA 4462 nk_handle userdata; 4463 #endif 4464 }; 4465 4466 struct nk_command_scissor { 4467 struct nk_command header; 4468 short x, y; 4469 unsigned short w, h; 4470 }; 4471 4472 struct nk_command_line { 4473 struct nk_command header; 4474 unsigned short line_thickness; 4475 struct nk_vec2i begin; 4476 struct nk_vec2i end; 4477 struct nk_color color; 4478 }; 4479 4480 struct nk_command_curve { 4481 struct nk_command header; 4482 unsigned short line_thickness; 4483 struct nk_vec2i begin; 4484 struct nk_vec2i end; 4485 struct nk_vec2i ctrl[2]; 4486 struct nk_color color; 4487 }; 4488 4489 struct nk_command_rect { 4490 struct nk_command header; 4491 unsigned short rounding; 4492 unsigned short line_thickness; 4493 short x, y; 4494 unsigned short w, h; 4495 struct nk_color color; 4496 }; 4497 4498 struct nk_command_rect_filled { 4499 struct nk_command header; 4500 unsigned short rounding; 4501 short x, y; 4502 unsigned short w, h; 4503 struct nk_color color; 4504 }; 4505 4506 struct nk_command_rect_multi_color { 4507 struct nk_command header; 4508 short x, y; 4509 unsigned short w, h; 4510 struct nk_color left; 4511 struct nk_color top; 4512 struct nk_color bottom; 4513 struct nk_color right; 4514 }; 4515 4516 struct nk_command_triangle { 4517 struct nk_command header; 4518 unsigned short line_thickness; 4519 struct nk_vec2i a; 4520 struct nk_vec2i b; 4521 struct nk_vec2i c; 4522 struct nk_color color; 4523 }; 4524 4525 struct nk_command_triangle_filled { 4526 struct nk_command header; 4527 struct nk_vec2i a; 4528 struct nk_vec2i b; 4529 struct nk_vec2i c; 4530 struct nk_color color; 4531 }; 4532 4533 struct nk_command_circle { 4534 struct nk_command header; 4535 short x, y; 4536 unsigned short line_thickness; 4537 unsigned short w, h; 4538 struct nk_color color; 4539 }; 4540 4541 struct nk_command_circle_filled { 4542 struct nk_command header; 4543 short x, y; 4544 unsigned short w, h; 4545 struct nk_color color; 4546 }; 4547 4548 struct nk_command_arc { 4549 struct nk_command header; 4550 short cx, cy; 4551 unsigned short r; 4552 unsigned short line_thickness; 4553 float a[2]; 4554 struct nk_color color; 4555 }; 4556 4557 struct nk_command_arc_filled { 4558 struct nk_command header; 4559 short cx, cy; 4560 unsigned short r; 4561 float a[2]; 4562 struct nk_color color; 4563 }; 4564 4565 struct nk_command_polygon { 4566 struct nk_command header; 4567 struct nk_color color; 4568 unsigned short line_thickness; 4569 unsigned short point_count; 4570 struct nk_vec2i points[1]; 4571 }; 4572 4573 struct nk_command_polygon_filled { 4574 struct nk_command header; 4575 struct nk_color color; 4576 unsigned short point_count; 4577 struct nk_vec2i points[1]; 4578 }; 4579 4580 struct nk_command_polyline { 4581 struct nk_command header; 4582 struct nk_color color; 4583 unsigned short line_thickness; 4584 unsigned short point_count; 4585 struct nk_vec2i points[1]; 4586 }; 4587 4588 struct nk_command_image { 4589 struct nk_command header; 4590 short x, y; 4591 unsigned short w, h; 4592 struct nk_image img; 4593 struct nk_color col; 4594 }; 4595 4596 typedef void (*nk_command_custom_callback)(void *canvas, short x,short y, 4597 unsigned short w, unsigned short h, nk_handle callback_data); 4598 struct nk_command_custom { 4599 struct nk_command header; 4600 short x, y; 4601 unsigned short w, h; 4602 nk_handle callback_data; 4603 nk_command_custom_callback callback; 4604 }; 4605 4606 struct nk_command_text { 4607 struct nk_command header; 4608 const struct nk_user_font *font; 4609 struct nk_color background; 4610 struct nk_color foreground; 4611 short x, y; 4612 unsigned short w, h; 4613 float height; 4614 int length; 4615 char string[1]; 4616 }; 4617 4618 enum nk_command_clipping { 4619 NK_CLIPPING_OFF = nk_false, 4620 NK_CLIPPING_ON = nk_true 4621 }; 4622 4623 struct nk_command_buffer { 4624 struct nk_buffer *base; 4625 struct nk_rect clip; 4626 int use_clipping; 4627 nk_handle userdata; 4628 nk_size begin, end, last; 4629 }; 4630 4631 /* shape outlines */ 4632 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); 4633 NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color); 4634 NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color); 4635 NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color); 4636 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); 4637 NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color); 4638 NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col); 4639 NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color); 4640 4641 /* filled shades */ 4642 NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color); 4643 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); 4644 NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color); 4645 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); 4646 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); 4647 NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color); 4648 4649 /* misc */ 4650 NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color); 4651 NK_API void nk_draw_nine_slice(struct nk_command_buffer*, struct nk_rect, const struct nk_nine_slice*, struct nk_color); 4652 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); 4653 NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect); 4654 NK_API void nk_push_custom(struct nk_command_buffer*, struct nk_rect, nk_command_custom_callback, nk_handle usr); 4655 4656 /* =============================================================== 4657 * 4658 * INPUT 4659 * 4660 * ===============================================================*/ 4661 struct nk_mouse_button { 4662 nk_bool down; 4663 unsigned int clicked; 4664 struct nk_vec2 clicked_pos; 4665 }; 4666 struct nk_mouse { 4667 struct nk_mouse_button buttons[NK_BUTTON_MAX]; 4668 struct nk_vec2 pos; 4669 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE 4670 struct nk_vec2 down_pos; 4671 #endif 4672 struct nk_vec2 prev; 4673 struct nk_vec2 delta; 4674 struct nk_vec2 scroll_delta; 4675 unsigned char grab; 4676 unsigned char grabbed; 4677 unsigned char ungrab; 4678 }; 4679 4680 struct nk_key { 4681 nk_bool down; 4682 unsigned int clicked; 4683 }; 4684 struct nk_keyboard { 4685 struct nk_key keys[NK_KEY_MAX]; 4686 char text[NK_INPUT_MAX]; 4687 int text_len; 4688 }; 4689 4690 struct nk_input { 4691 struct nk_keyboard keyboard; 4692 struct nk_mouse mouse; 4693 }; 4694 4695 NK_API nk_bool nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons); 4696 NK_API nk_bool nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); 4697 NK_API nk_bool nk_input_has_mouse_click_in_button_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); 4698 NK_API nk_bool nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, nk_bool down); 4699 NK_API nk_bool nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); 4700 NK_API nk_bool nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, nk_bool down); 4701 NK_API nk_bool nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect); 4702 NK_API nk_bool nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect); 4703 NK_API nk_bool nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect); 4704 NK_API nk_bool nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect); 4705 NK_API nk_bool nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons); 4706 NK_API nk_bool nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons); 4707 NK_API nk_bool nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons); 4708 NK_API nk_bool nk_input_is_key_pressed(const struct nk_input*, enum nk_keys); 4709 NK_API nk_bool nk_input_is_key_released(const struct nk_input*, enum nk_keys); 4710 NK_API nk_bool nk_input_is_key_down(const struct nk_input*, enum nk_keys); 4711 4712 /* =============================================================== 4713 * 4714 * DRAW LIST 4715 * 4716 * ===============================================================*/ 4717 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 4718 /* ### Draw List 4719 /// The optional vertex buffer draw list provides a 2D drawing context 4720 /// with antialiasing functionality which takes basic filled or outlined shapes 4721 /// or a path and outputs vertexes, elements and draw commands. 4722 /// The actual draw list API is not required to be used directly while using this 4723 /// library since converting the default library draw command output is done by 4724 /// just calling `nk_convert` but I decided to still make this library accessible 4725 /// since it can be useful. 4726 /// 4727 /// The draw list is based on a path buffering and polygon and polyline 4728 /// rendering API which allows a lot of ways to draw 2D content to screen. 4729 /// In fact it is probably more powerful than needed but allows even more crazy 4730 /// things than this library provides by default. 4731 */ 4732 #ifdef NK_UINT_DRAW_INDEX 4733 typedef nk_uint nk_draw_index; 4734 #else 4735 typedef nk_ushort nk_draw_index; 4736 #endif 4737 enum nk_draw_list_stroke { 4738 NK_STROKE_OPEN = nk_false, 4739 /* build up path has no connection back to the beginning */ 4740 NK_STROKE_CLOSED = nk_true 4741 /* build up path has a connection back to the beginning */ 4742 }; 4743 4744 enum nk_draw_vertex_layout_attribute { 4745 NK_VERTEX_POSITION, 4746 NK_VERTEX_COLOR, 4747 NK_VERTEX_TEXCOORD, 4748 NK_VERTEX_ATTRIBUTE_COUNT 4749 }; 4750 4751 enum nk_draw_vertex_layout_format { 4752 NK_FORMAT_SCHAR, 4753 NK_FORMAT_SSHORT, 4754 NK_FORMAT_SINT, 4755 NK_FORMAT_UCHAR, 4756 NK_FORMAT_USHORT, 4757 NK_FORMAT_UINT, 4758 NK_FORMAT_FLOAT, 4759 NK_FORMAT_DOUBLE, 4760 4761 NK_FORMAT_COLOR_BEGIN, 4762 NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN, 4763 NK_FORMAT_R16G15B16, 4764 NK_FORMAT_R32G32B32, 4765 4766 NK_FORMAT_R8G8B8A8, 4767 NK_FORMAT_B8G8R8A8, 4768 NK_FORMAT_R16G15B16A16, 4769 NK_FORMAT_R32G32B32A32, 4770 NK_FORMAT_R32G32B32A32_FLOAT, 4771 NK_FORMAT_R32G32B32A32_DOUBLE, 4772 4773 NK_FORMAT_RGB32, 4774 NK_FORMAT_RGBA32, 4775 NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32, 4776 NK_FORMAT_COUNT 4777 }; 4778 4779 #define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0 4780 struct nk_draw_vertex_layout_element { 4781 enum nk_draw_vertex_layout_attribute attribute; 4782 enum nk_draw_vertex_layout_format format; 4783 nk_size offset; 4784 }; 4785 4786 struct nk_draw_command { 4787 unsigned int elem_count; 4788 /* number of elements in the current draw batch */ 4789 struct nk_rect clip_rect; 4790 /* current screen clipping rectangle */ 4791 nk_handle texture; 4792 /* current texture to set */ 4793 #ifdef NK_INCLUDE_COMMAND_USERDATA 4794 nk_handle userdata; 4795 #endif 4796 }; 4797 4798 struct nk_draw_list { 4799 struct nk_rect clip_rect; 4800 struct nk_vec2 circle_vtx[12]; 4801 struct nk_convert_config config; 4802 4803 struct nk_buffer *buffer; 4804 struct nk_buffer *vertices; 4805 struct nk_buffer *elements; 4806 4807 unsigned int element_count; 4808 unsigned int vertex_count; 4809 unsigned int cmd_count; 4810 nk_size cmd_offset; 4811 4812 unsigned int path_count; 4813 unsigned int path_offset; 4814 4815 enum nk_anti_aliasing line_AA; 4816 enum nk_anti_aliasing shape_AA; 4817 4818 #ifdef NK_INCLUDE_COMMAND_USERDATA 4819 nk_handle userdata; 4820 #endif 4821 }; 4822 4823 /* draw list */ 4824 NK_API void nk_draw_list_init(struct nk_draw_list*); 4825 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); 4826 4827 /* drawing */ 4828 #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)) 4829 NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*); 4830 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*); 4831 NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*); 4832 4833 /* path */ 4834 NK_API void nk_draw_list_path_clear(struct nk_draw_list*); 4835 NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos); 4836 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); 4837 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); 4838 NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding); 4839 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); 4840 NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color); 4841 NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness); 4842 4843 /* stroke */ 4844 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); 4845 NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness); 4846 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); 4847 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); 4848 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); 4849 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); 4850 4851 /* fill */ 4852 NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding); 4853 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); 4854 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); 4855 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); 4856 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); 4857 4858 /* misc */ 4859 NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color); 4860 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); 4861 #ifdef NK_INCLUDE_COMMAND_USERDATA 4862 NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata); 4863 #endif 4864 4865 #endif 4866 4867 /* =============================================================== 4868 * 4869 * GUI 4870 * 4871 * ===============================================================*/ 4872 enum nk_style_item_type { 4873 NK_STYLE_ITEM_COLOR, 4874 NK_STYLE_ITEM_IMAGE, 4875 NK_STYLE_ITEM_NINE_SLICE 4876 }; 4877 4878 union nk_style_item_data { 4879 struct nk_color color; 4880 struct nk_image image; 4881 struct nk_nine_slice slice; 4882 }; 4883 4884 struct nk_style_item { 4885 enum nk_style_item_type type; 4886 union nk_style_item_data data; 4887 }; 4888 4889 struct nk_style_text { 4890 struct nk_color color; 4891 struct nk_vec2 padding; 4892 }; 4893 4894 struct nk_style_button { 4895 /* background */ 4896 struct nk_style_item normal; 4897 struct nk_style_item hover; 4898 struct nk_style_item active; 4899 struct nk_color border_color; 4900 4901 /* text */ 4902 struct nk_color text_background; 4903 struct nk_color text_normal; 4904 struct nk_color text_hover; 4905 struct nk_color text_active; 4906 nk_flags text_alignment; 4907 4908 /* properties */ 4909 float border; 4910 float rounding; 4911 struct nk_vec2 padding; 4912 struct nk_vec2 image_padding; 4913 struct nk_vec2 touch_padding; 4914 4915 /* optional user callbacks */ 4916 nk_handle userdata; 4917 void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata); 4918 void(*draw_end)(struct nk_command_buffer*, nk_handle userdata); 4919 }; 4920 4921 struct nk_style_toggle { 4922 /* background */ 4923 struct nk_style_item normal; 4924 struct nk_style_item hover; 4925 struct nk_style_item active; 4926 struct nk_color border_color; 4927 4928 /* cursor */ 4929 struct nk_style_item cursor_normal; 4930 struct nk_style_item cursor_hover; 4931 4932 /* text */ 4933 struct nk_color text_normal; 4934 struct nk_color text_hover; 4935 struct nk_color text_active; 4936 struct nk_color text_background; 4937 nk_flags text_alignment; 4938 4939 /* properties */ 4940 struct nk_vec2 padding; 4941 struct nk_vec2 touch_padding; 4942 float spacing; 4943 float border; 4944 4945 /* optional user callbacks */ 4946 nk_handle userdata; 4947 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4948 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4949 }; 4950 4951 struct nk_style_selectable { 4952 /* background (inactive) */ 4953 struct nk_style_item normal; 4954 struct nk_style_item hover; 4955 struct nk_style_item pressed; 4956 4957 /* background (active) */ 4958 struct nk_style_item normal_active; 4959 struct nk_style_item hover_active; 4960 struct nk_style_item pressed_active; 4961 4962 /* text color (inactive) */ 4963 struct nk_color text_normal; 4964 struct nk_color text_hover; 4965 struct nk_color text_pressed; 4966 4967 /* text color (active) */ 4968 struct nk_color text_normal_active; 4969 struct nk_color text_hover_active; 4970 struct nk_color text_pressed_active; 4971 struct nk_color text_background; 4972 nk_flags text_alignment; 4973 4974 /* properties */ 4975 float rounding; 4976 struct nk_vec2 padding; 4977 struct nk_vec2 touch_padding; 4978 struct nk_vec2 image_padding; 4979 4980 /* optional user callbacks */ 4981 nk_handle userdata; 4982 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 4983 void(*draw_end)(struct nk_command_buffer*, nk_handle); 4984 }; 4985 4986 struct nk_style_slider { 4987 /* background */ 4988 struct nk_style_item normal; 4989 struct nk_style_item hover; 4990 struct nk_style_item active; 4991 struct nk_color border_color; 4992 4993 /* background bar */ 4994 struct nk_color bar_normal; 4995 struct nk_color bar_hover; 4996 struct nk_color bar_active; 4997 struct nk_color bar_filled; 4998 4999 /* cursor */ 5000 struct nk_style_item cursor_normal; 5001 struct nk_style_item cursor_hover; 5002 struct nk_style_item cursor_active; 5003 5004 /* properties */ 5005 float border; 5006 float rounding; 5007 float bar_height; 5008 struct nk_vec2 padding; 5009 struct nk_vec2 spacing; 5010 struct nk_vec2 cursor_size; 5011 5012 /* optional buttons */ 5013 int show_buttons; 5014 struct nk_style_button inc_button; 5015 struct nk_style_button dec_button; 5016 enum nk_symbol_type inc_symbol; 5017 enum nk_symbol_type dec_symbol; 5018 5019 /* optional user callbacks */ 5020 nk_handle userdata; 5021 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 5022 void(*draw_end)(struct nk_command_buffer*, nk_handle); 5023 }; 5024 5025 struct nk_style_progress { 5026 /* background */ 5027 struct nk_style_item normal; 5028 struct nk_style_item hover; 5029 struct nk_style_item active; 5030 struct nk_color border_color; 5031 5032 /* cursor */ 5033 struct nk_style_item cursor_normal; 5034 struct nk_style_item cursor_hover; 5035 struct nk_style_item cursor_active; 5036 struct nk_color cursor_border_color; 5037 5038 /* properties */ 5039 float rounding; 5040 float border; 5041 float cursor_border; 5042 float cursor_rounding; 5043 struct nk_vec2 padding; 5044 5045 /* optional user callbacks */ 5046 nk_handle userdata; 5047 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 5048 void(*draw_end)(struct nk_command_buffer*, nk_handle); 5049 }; 5050 5051 struct nk_style_scrollbar { 5052 /* background */ 5053 struct nk_style_item normal; 5054 struct nk_style_item hover; 5055 struct nk_style_item active; 5056 struct nk_color border_color; 5057 5058 /* cursor */ 5059 struct nk_style_item cursor_normal; 5060 struct nk_style_item cursor_hover; 5061 struct nk_style_item cursor_active; 5062 struct nk_color cursor_border_color; 5063 5064 /* properties */ 5065 float border; 5066 float rounding; 5067 float border_cursor; 5068 float rounding_cursor; 5069 struct nk_vec2 padding; 5070 5071 /* optional buttons */ 5072 int show_buttons; 5073 struct nk_style_button inc_button; 5074 struct nk_style_button dec_button; 5075 enum nk_symbol_type inc_symbol; 5076 enum nk_symbol_type dec_symbol; 5077 5078 /* optional user callbacks */ 5079 nk_handle userdata; 5080 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 5081 void(*draw_end)(struct nk_command_buffer*, nk_handle); 5082 }; 5083 5084 struct nk_style_edit { 5085 /* background */ 5086 struct nk_style_item normal; 5087 struct nk_style_item hover; 5088 struct nk_style_item active; 5089 struct nk_color border_color; 5090 struct nk_style_scrollbar scrollbar; 5091 5092 /* cursor */ 5093 struct nk_color cursor_normal; 5094 struct nk_color cursor_hover; 5095 struct nk_color cursor_text_normal; 5096 struct nk_color cursor_text_hover; 5097 5098 /* text (unselected) */ 5099 struct nk_color text_normal; 5100 struct nk_color text_hover; 5101 struct nk_color text_active; 5102 5103 /* text (selected) */ 5104 struct nk_color selected_normal; 5105 struct nk_color selected_hover; 5106 struct nk_color selected_text_normal; 5107 struct nk_color selected_text_hover; 5108 5109 /* properties */ 5110 float border; 5111 float rounding; 5112 float cursor_size; 5113 struct nk_vec2 scrollbar_size; 5114 struct nk_vec2 padding; 5115 float row_padding; 5116 }; 5117 5118 struct nk_style_property { 5119 /* background */ 5120 struct nk_style_item normal; 5121 struct nk_style_item hover; 5122 struct nk_style_item active; 5123 struct nk_color border_color; 5124 5125 /* text */ 5126 struct nk_color label_normal; 5127 struct nk_color label_hover; 5128 struct nk_color label_active; 5129 5130 /* symbols */ 5131 enum nk_symbol_type sym_left; 5132 enum nk_symbol_type sym_right; 5133 5134 /* properties */ 5135 float border; 5136 float rounding; 5137 struct nk_vec2 padding; 5138 5139 struct nk_style_edit edit; 5140 struct nk_style_button inc_button; 5141 struct nk_style_button dec_button; 5142 5143 /* optional user callbacks */ 5144 nk_handle userdata; 5145 void(*draw_begin)(struct nk_command_buffer*, nk_handle); 5146 void(*draw_end)(struct nk_command_buffer*, nk_handle); 5147 }; 5148 5149 struct nk_style_chart { 5150 /* colors */ 5151 struct nk_style_item background; 5152 struct nk_color border_color; 5153 struct nk_color selected_color; 5154 struct nk_color color; 5155 5156 /* properties */ 5157 float border; 5158 float rounding; 5159 struct nk_vec2 padding; 5160 }; 5161 5162 struct nk_style_combo { 5163 /* background */ 5164 struct nk_style_item normal; 5165 struct nk_style_item hover; 5166 struct nk_style_item active; 5167 struct nk_color border_color; 5168 5169 /* label */ 5170 struct nk_color label_normal; 5171 struct nk_color label_hover; 5172 struct nk_color label_active; 5173 5174 /* symbol */ 5175 struct nk_color symbol_normal; 5176 struct nk_color symbol_hover; 5177 struct nk_color symbol_active; 5178 5179 /* button */ 5180 struct nk_style_button button; 5181 enum nk_symbol_type sym_normal; 5182 enum nk_symbol_type sym_hover; 5183 enum nk_symbol_type sym_active; 5184 5185 /* properties */ 5186 float border; 5187 float rounding; 5188 struct nk_vec2 content_padding; 5189 struct nk_vec2 button_padding; 5190 struct nk_vec2 spacing; 5191 }; 5192 5193 struct nk_style_tab { 5194 /* background */ 5195 struct nk_style_item background; 5196 struct nk_color border_color; 5197 struct nk_color text; 5198 5199 /* button */ 5200 struct nk_style_button tab_maximize_button; 5201 struct nk_style_button tab_minimize_button; 5202 struct nk_style_button node_maximize_button; 5203 struct nk_style_button node_minimize_button; 5204 enum nk_symbol_type sym_minimize; 5205 enum nk_symbol_type sym_maximize; 5206 5207 /* properties */ 5208 float border; 5209 float rounding; 5210 float indent; 5211 struct nk_vec2 padding; 5212 struct nk_vec2 spacing; 5213 }; 5214 5215 enum nk_style_header_align { 5216 NK_HEADER_LEFT, 5217 NK_HEADER_RIGHT 5218 }; 5219 struct nk_style_window_header { 5220 /* background */ 5221 struct nk_style_item normal; 5222 struct nk_style_item hover; 5223 struct nk_style_item active; 5224 5225 /* button */ 5226 struct nk_style_button close_button; 5227 struct nk_style_button minimize_button; 5228 enum nk_symbol_type close_symbol; 5229 enum nk_symbol_type minimize_symbol; 5230 enum nk_symbol_type maximize_symbol; 5231 5232 /* title */ 5233 struct nk_color label_normal; 5234 struct nk_color label_hover; 5235 struct nk_color label_active; 5236 5237 /* properties */ 5238 enum nk_style_header_align align; 5239 struct nk_vec2 padding; 5240 struct nk_vec2 label_padding; 5241 struct nk_vec2 spacing; 5242 }; 5243 5244 struct nk_style_window { 5245 struct nk_style_window_header header; 5246 struct nk_style_item fixed_background; 5247 struct nk_color background; 5248 5249 struct nk_color border_color; 5250 struct nk_color popup_border_color; 5251 struct nk_color combo_border_color; 5252 struct nk_color contextual_border_color; 5253 struct nk_color menu_border_color; 5254 struct nk_color group_border_color; 5255 struct nk_color tooltip_border_color; 5256 struct nk_style_item scaler; 5257 5258 float border; 5259 float combo_border; 5260 float contextual_border; 5261 float menu_border; 5262 float group_border; 5263 float tooltip_border; 5264 float popup_border; 5265 float min_row_height_padding; 5266 5267 float rounding; 5268 struct nk_vec2 spacing; 5269 struct nk_vec2 scrollbar_size; 5270 struct nk_vec2 min_size; 5271 5272 struct nk_vec2 padding; 5273 struct nk_vec2 group_padding; 5274 struct nk_vec2 popup_padding; 5275 struct nk_vec2 combo_padding; 5276 struct nk_vec2 contextual_padding; 5277 struct nk_vec2 menu_padding; 5278 struct nk_vec2 tooltip_padding; 5279 }; 5280 5281 struct nk_style { 5282 const struct nk_user_font *font; 5283 const struct nk_cursor *cursors[NK_CURSOR_COUNT]; 5284 const struct nk_cursor *cursor_active; 5285 struct nk_cursor *cursor_last; 5286 int cursor_visible; 5287 5288 struct nk_style_text text; 5289 struct nk_style_button button; 5290 struct nk_style_button contextual_button; 5291 struct nk_style_button menu_button; 5292 struct nk_style_toggle option; 5293 struct nk_style_toggle checkbox; 5294 struct nk_style_selectable selectable; 5295 struct nk_style_slider slider; 5296 struct nk_style_progress progress; 5297 struct nk_style_property property; 5298 struct nk_style_edit edit; 5299 struct nk_style_chart chart; 5300 struct nk_style_scrollbar scrollh; 5301 struct nk_style_scrollbar scrollv; 5302 struct nk_style_tab tab; 5303 struct nk_style_combo combo; 5304 struct nk_style_window window; 5305 }; 5306 5307 NK_API struct nk_style_item nk_style_item_color(struct nk_color); 5308 NK_API struct nk_style_item nk_style_item_image(struct nk_image img); 5309 NK_API struct nk_style_item nk_style_item_nine_slice(struct nk_nine_slice slice); 5310 NK_API struct nk_style_item nk_style_item_hide(void); 5311 5312 /*============================================================== 5313 * PANEL 5314 * =============================================================*/ 5315 #ifndef NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 5316 #define NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS 16 5317 #endif 5318 #ifndef NK_CHART_MAX_SLOT 5319 #define NK_CHART_MAX_SLOT 4 5320 #endif 5321 5322 enum nk_panel_type { 5323 NK_PANEL_NONE = 0, 5324 NK_PANEL_WINDOW = NK_FLAG(0), 5325 NK_PANEL_GROUP = NK_FLAG(1), 5326 NK_PANEL_POPUP = NK_FLAG(2), 5327 NK_PANEL_CONTEXTUAL = NK_FLAG(4), 5328 NK_PANEL_COMBO = NK_FLAG(5), 5329 NK_PANEL_MENU = NK_FLAG(6), 5330 NK_PANEL_TOOLTIP = NK_FLAG(7) 5331 }; 5332 enum nk_panel_set { 5333 NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP, 5334 NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP, 5335 NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP 5336 }; 5337 5338 struct nk_chart_slot { 5339 enum nk_chart_type type; 5340 struct nk_color color; 5341 struct nk_color highlight; 5342 float min, max, range; 5343 int count; 5344 struct nk_vec2 last; 5345 int index; 5346 }; 5347 5348 struct nk_chart { 5349 int slot; 5350 float x, y, w, h; 5351 struct nk_chart_slot slots[NK_CHART_MAX_SLOT]; 5352 }; 5353 5354 enum nk_panel_row_layout_type { 5355 NK_LAYOUT_DYNAMIC_FIXED = 0, 5356 NK_LAYOUT_DYNAMIC_ROW, 5357 NK_LAYOUT_DYNAMIC_FREE, 5358 NK_LAYOUT_DYNAMIC, 5359 NK_LAYOUT_STATIC_FIXED, 5360 NK_LAYOUT_STATIC_ROW, 5361 NK_LAYOUT_STATIC_FREE, 5362 NK_LAYOUT_STATIC, 5363 NK_LAYOUT_TEMPLATE, 5364 NK_LAYOUT_COUNT 5365 }; 5366 struct nk_row_layout { 5367 enum nk_panel_row_layout_type type; 5368 int index; 5369 float height; 5370 float min_height; 5371 int columns; 5372 const float *ratio; 5373 float item_width; 5374 float item_height; 5375 float item_offset; 5376 float filled; 5377 struct nk_rect item; 5378 int tree_depth; 5379 float templates[NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS]; 5380 }; 5381 5382 struct nk_popup_buffer { 5383 nk_size begin; 5384 nk_size parent; 5385 nk_size last; 5386 nk_size end; 5387 nk_bool active; 5388 }; 5389 5390 struct nk_menu_state { 5391 float x, y, w, h; 5392 struct nk_scroll offset; 5393 }; 5394 5395 struct nk_panel { 5396 enum nk_panel_type type; 5397 nk_flags flags; 5398 struct nk_rect bounds; 5399 nk_uint *offset_x; 5400 nk_uint *offset_y; 5401 float at_x, at_y, max_x; 5402 float footer_height; 5403 float header_height; 5404 float border; 5405 unsigned int has_scrolling; 5406 struct nk_rect clip; 5407 struct nk_menu_state menu; 5408 struct nk_row_layout row; 5409 struct nk_chart chart; 5410 struct nk_command_buffer *buffer; 5411 struct nk_panel *parent; 5412 }; 5413 5414 /*============================================================== 5415 * WINDOW 5416 * =============================================================*/ 5417 #ifndef NK_WINDOW_MAX_NAME 5418 #define NK_WINDOW_MAX_NAME 64 5419 #endif 5420 5421 struct nk_table; 5422 enum nk_window_flags { 5423 NK_WINDOW_PRIVATE = NK_FLAG(11), 5424 NK_WINDOW_DYNAMIC = NK_WINDOW_PRIVATE, 5425 /* special window type growing up in height while being filled to a certain maximum height */ 5426 NK_WINDOW_ROM = NK_FLAG(12), 5427 /* sets window widgets into a read only mode and does not allow input changes */ 5428 NK_WINDOW_NOT_INTERACTIVE = NK_WINDOW_ROM|NK_WINDOW_NO_INPUT, 5429 /* prevents all interaction caused by input to either window or widgets inside */ 5430 NK_WINDOW_HIDDEN = NK_FLAG(13), 5431 /* Hides window and stops any window interaction and drawing */ 5432 NK_WINDOW_CLOSED = NK_FLAG(14), 5433 /* Directly closes and frees the window at the end of the frame */ 5434 NK_WINDOW_MINIMIZED = NK_FLAG(15), 5435 /* marks the window as minimized */ 5436 NK_WINDOW_REMOVE_ROM = NK_FLAG(16) 5437 /* Removes read only mode at the end of the window */ 5438 }; 5439 5440 struct nk_popup_state { 5441 struct nk_window *win; 5442 enum nk_panel_type type; 5443 struct nk_popup_buffer buf; 5444 nk_hash name; 5445 nk_bool active; 5446 unsigned combo_count; 5447 unsigned con_count, con_old; 5448 unsigned active_con; 5449 struct nk_rect header; 5450 }; 5451 5452 struct nk_edit_state { 5453 nk_hash name; 5454 unsigned int seq; 5455 unsigned int old; 5456 int active, prev; 5457 int cursor; 5458 int sel_start; 5459 int sel_end; 5460 struct nk_scroll scrollbar; 5461 unsigned char mode; 5462 unsigned char single_line; 5463 }; 5464 5465 struct nk_property_state { 5466 int active, prev; 5467 char buffer[NK_MAX_NUMBER_BUFFER]; 5468 int length; 5469 int cursor; 5470 int select_start; 5471 int select_end; 5472 nk_hash name; 5473 unsigned int seq; 5474 unsigned int old; 5475 int state; 5476 }; 5477 5478 struct nk_window { 5479 unsigned int seq; 5480 nk_hash name; 5481 char name_string[NK_WINDOW_MAX_NAME]; 5482 nk_flags flags; 5483 5484 struct nk_rect bounds; 5485 struct nk_scroll scrollbar; 5486 struct nk_command_buffer buffer; 5487 struct nk_panel *layout; 5488 float scrollbar_hiding_timer; 5489 5490 /* persistent widget state */ 5491 struct nk_property_state property; 5492 struct nk_popup_state popup; 5493 struct nk_edit_state edit; 5494 unsigned int scrolled; 5495 5496 struct nk_table *tables; 5497 unsigned int table_count; 5498 5499 /* window list hooks */ 5500 struct nk_window *next; 5501 struct nk_window *prev; 5502 struct nk_window *parent; 5503 }; 5504 5505 /*============================================================== 5506 * STACK 5507 * =============================================================*/ 5508 /*/// ### Stack 5509 /// The style modifier stack can be used to temporarily change a 5510 /// property inside `nk_style`. For example if you want a special 5511 /// red button you can temporarily push the old button color onto a stack 5512 /// draw the button with a red color and then you just pop the old color 5513 /// back from the stack: 5514 /// 5515 /// nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0))); 5516 /// nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0))); 5517 /// nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0))); 5518 /// nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2)); 5519 /// 5520 /// nk_button(...); 5521 /// 5522 /// nk_style_pop_style_item(ctx); 5523 /// nk_style_pop_style_item(ctx); 5524 /// nk_style_pop_style_item(ctx); 5525 /// nk_style_pop_vec2(ctx); 5526 /// 5527 /// Nuklear has a stack for style_items, float properties, vector properties, 5528 /// flags, colors, fonts and for button_behavior. Each has it's own fixed size stack 5529 /// which can be changed at compile time. 5530 */ 5531 #ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE 5532 #define NK_BUTTON_BEHAVIOR_STACK_SIZE 8 5533 #endif 5534 5535 #ifndef NK_FONT_STACK_SIZE 5536 #define NK_FONT_STACK_SIZE 8 5537 #endif 5538 5539 #ifndef NK_STYLE_ITEM_STACK_SIZE 5540 #define NK_STYLE_ITEM_STACK_SIZE 16 5541 #endif 5542 5543 #ifndef NK_FLOAT_STACK_SIZE 5544 #define NK_FLOAT_STACK_SIZE 32 5545 #endif 5546 5547 #ifndef NK_VECTOR_STACK_SIZE 5548 #define NK_VECTOR_STACK_SIZE 16 5549 #endif 5550 5551 #ifndef NK_FLAGS_STACK_SIZE 5552 #define NK_FLAGS_STACK_SIZE 32 5553 #endif 5554 5555 #ifndef NK_COLOR_STACK_SIZE 5556 #define NK_COLOR_STACK_SIZE 32 5557 #endif 5558 5559 #define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\ 5560 struct nk_config_stack_##name##_element {\ 5561 prefix##_##type *address;\ 5562 prefix##_##type old_value;\ 5563 } 5564 #define NK_CONFIG_STACK(type,size)\ 5565 struct nk_config_stack_##type {\ 5566 int head;\ 5567 struct nk_config_stack_##type##_element elements[size];\ 5568 } 5569 5570 #define nk_float float 5571 NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item); 5572 NK_CONFIGURATION_STACK_TYPE(nk ,float, float); 5573 NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2); 5574 NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags); 5575 NK_CONFIGURATION_STACK_TYPE(struct nk, color, color); 5576 NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*); 5577 NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior); 5578 5579 NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE); 5580 NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE); 5581 NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE); 5582 NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE); 5583 NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE); 5584 NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE); 5585 NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE); 5586 5587 struct nk_configuration_stacks { 5588 struct nk_config_stack_style_item style_items; 5589 struct nk_config_stack_float floats; 5590 struct nk_config_stack_vec2 vectors; 5591 struct nk_config_stack_flags flags; 5592 struct nk_config_stack_color colors; 5593 struct nk_config_stack_user_font fonts; 5594 struct nk_config_stack_button_behavior button_behaviors; 5595 }; 5596 5597 /*============================================================== 5598 * CONTEXT 5599 * =============================================================*/ 5600 #define NK_VALUE_PAGE_CAPACITY \ 5601 (((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint))) / 2) 5602 5603 struct nk_table { 5604 unsigned int seq; 5605 unsigned int size; 5606 nk_hash keys[NK_VALUE_PAGE_CAPACITY]; 5607 nk_uint values[NK_VALUE_PAGE_CAPACITY]; 5608 struct nk_table *next, *prev; 5609 }; 5610 5611 union nk_page_data { 5612 struct nk_table tbl; 5613 struct nk_panel pan; 5614 struct nk_window win; 5615 }; 5616 5617 struct nk_page_element { 5618 union nk_page_data data; 5619 struct nk_page_element *next; 5620 struct nk_page_element *prev; 5621 }; 5622 5623 struct nk_page { 5624 unsigned int size; 5625 struct nk_page *next; 5626 struct nk_page_element win[1]; 5627 }; 5628 5629 struct nk_pool { 5630 struct nk_allocator alloc; 5631 enum nk_allocation_type type; 5632 unsigned int page_count; 5633 struct nk_page *pages; 5634 struct nk_page_element *freelist; 5635 unsigned capacity; 5636 nk_size size; 5637 nk_size cap; 5638 }; 5639 5640 struct nk_context { 5641 /* public: can be accessed freely */ 5642 struct nk_input input; 5643 struct nk_style style; 5644 struct nk_buffer memory; 5645 struct nk_clipboard clip; 5646 nk_flags last_widget_state; 5647 enum nk_button_behavior button_behavior; 5648 struct nk_configuration_stacks stacks; 5649 float delta_time_seconds; 5650 5651 /* private: 5652 should only be accessed if you 5653 know what you are doing */ 5654 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 5655 struct nk_draw_list draw_list; 5656 #endif 5657 #ifdef NK_INCLUDE_COMMAND_USERDATA 5658 nk_handle userdata; 5659 #endif 5660 /* text editor objects are quite big because of an internal 5661 * undo/redo stack. Therefore it does not make sense to have one for 5662 * each window for temporary use cases, so I only provide *one* instance 5663 * for all windows. This works because the content is cleared anyway */ 5664 struct nk_text_edit text_edit; 5665 /* draw buffer used for overlay drawing operation like cursor */ 5666 struct nk_command_buffer overlay; 5667 5668 /* windows */ 5669 int build; 5670 int use_pool; 5671 struct nk_pool pool; 5672 struct nk_window *begin; 5673 struct nk_window *end; 5674 struct nk_window *active; 5675 struct nk_window *current; 5676 struct nk_page_element *freelist; 5677 unsigned int count; 5678 unsigned int seq; 5679 }; 5680 5681 /* ============================================================== 5682 * MATH 5683 * =============================================================== */ 5684 #define NK_PI 3.141592654f 5685 #define NK_UTF_INVALID 0xFFFD 5686 #define NK_MAX_FLOAT_PRECISION 2 5687 5688 #define NK_UNUSED(x) ((void)(x)) 5689 #define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x))) 5690 #define NK_LEN(a) (sizeof(a)/sizeof(a)[0]) 5691 #define NK_ABS(a) (((a) < 0) ? -(a) : (a)) 5692 #define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) < (b)) 5693 #define NK_INBOX(px, py, x, y, w, h)\ 5694 (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h)) 5695 #define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \ 5696 ((x1 < (x0 + w0)) && (x0 < (x1 + w1)) && \ 5697 (y1 < (y0 + h0)) && (y0 < (y1 + h1))) 5698 #define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\ 5699 (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh)) 5700 5701 #define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y) 5702 #define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y) 5703 #define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y) 5704 #define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t)) 5705 5706 #define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i)))) 5707 #define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i)))) 5708 #define nk_zero_struct(s) nk_zero(&s, sizeof(s)) 5709 5710 /* ============================================================== 5711 * ALIGNMENT 5712 * =============================================================== */ 5713 /* Pointer to Integer type conversion for pointer alignment */ 5714 #if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/ 5715 # define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x)) 5716 # define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x)) 5717 #elif !defined(__GNUC__) /* works for compilers other than LLVM */ 5718 # define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x]) 5719 # define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0)) 5720 #elif defined(NK_USE_FIXED_TYPES) /* used if we have <stdint.h> */ 5721 # define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x)) 5722 # define NK_PTR_TO_UINT(x) ((uintptr_t)(x)) 5723 #else /* generates warning but works */ 5724 # define NK_UINT_TO_PTR(x) ((void*)(x)) 5725 # define NK_PTR_TO_UINT(x) ((nk_size)(x)) 5726 #endif 5727 5728 #define NK_ALIGN_PTR(x, mask)\ 5729 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1)))) 5730 #define NK_ALIGN_PTR_BACK(x, mask)\ 5731 (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1)))) 5732 5733 #if (defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__) 5734 #define NK_OFFSETOF(st,m) (__builtin_offsetof(st,m)) 5735 #else 5736 #define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m)) 5737 #endif 5738 5739 #ifdef __cplusplus 5740 } 5741 #endif 5742 5743 #ifdef __cplusplus 5744 template<typename T> struct nk_alignof; 5745 template<typename T, int size_diff> struct nk_helper{enum {value = size_diff};}; 5746 template<typename T> struct nk_helper<T,0>{enum {value = nk_alignof<T>::value};}; 5747 template<typename T> struct nk_alignof{struct Big {T x; char c;}; enum { 5748 diff = sizeof(Big) - sizeof(T), value = nk_helper<Big, diff>::value};}; 5749 #define NK_ALIGNOF(t) (nk_alignof<t>::value) 5750 #else 5751 #define NK_ALIGNOF(t) NK_OFFSETOF(struct {char c; t _h;}, _h) 5752 #endif 5753 5754 #define NK_CONTAINER_OF(ptr,type,member)\ 5755 (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) 5756 5757 5758 5759 #endif /* NK_NUKLEAR_H_ */ 5760 5761 #ifdef NK_IMPLEMENTATION 5762 5763 #ifndef NK_INTERNAL_H 5764 #define NK_INTERNAL_H 5765 5766 #ifndef NK_POOL_DEFAULT_CAPACITY 5767 #define NK_POOL_DEFAULT_CAPACITY 16 5768 #endif 5769 5770 #ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE 5771 #define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024) 5772 #endif 5773 5774 #ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE 5775 #define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024) 5776 #endif 5777 5778 /* standard library headers */ 5779 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 5780 #include <stdlib.h> /* malloc, free */ 5781 #endif 5782 #ifdef NK_INCLUDE_STANDARD_IO 5783 #include <stdio.h> /* fopen, fclose,... */ 5784 #endif 5785 #ifdef NK_INCLUDE_STANDARD_VARARGS 5786 #include <stdarg.h> /* valist, va_start, va_end, ... */ 5787 #endif 5788 #ifndef NK_ASSERT 5789 #include <assert.h> 5790 #define NK_ASSERT(expr) assert(expr) 5791 #endif 5792 5793 #define NK_DEFAULT (-1) 5794 5795 #ifndef NK_VSNPRINTF 5796 /* If your compiler does support `vsnprintf` I would highly recommend 5797 * defining this to vsnprintf instead since `vsprintf` is basically 5798 * unbelievable unsafe and should *NEVER* be used. But I have to support 5799 * it since C89 only provides this unsafe version. */ 5800 #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\ 5801 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ 5802 (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\ 5803 (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\ 5804 defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE) 5805 #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a) 5806 #else 5807 #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a) 5808 #endif 5809 #endif 5810 5811 #define NK_SCHAR_MIN (-127) 5812 #define NK_SCHAR_MAX 127 5813 #define NK_UCHAR_MIN 0 5814 #define NK_UCHAR_MAX 256 5815 #define NK_SSHORT_MIN (-32767) 5816 #define NK_SSHORT_MAX 32767 5817 #define NK_USHORT_MIN 0 5818 #define NK_USHORT_MAX 65535 5819 #define NK_SINT_MIN (-2147483647) 5820 #define NK_SINT_MAX 2147483647 5821 #define NK_UINT_MIN 0 5822 #define NK_UINT_MAX 4294967295u 5823 5824 /* Make sure correct type size: 5825 * This will fire with a negative subscript error if the type sizes 5826 * are set incorrectly by the compiler, and compile out if not */ 5827 NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); 5828 NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*)); 5829 NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); 5830 NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); 5831 NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); 5832 NK_STATIC_ASSERT(sizeof(nk_short) == 2); 5833 NK_STATIC_ASSERT(sizeof(nk_uint) == 4); 5834 NK_STATIC_ASSERT(sizeof(nk_int) == 4); 5835 NK_STATIC_ASSERT(sizeof(nk_byte) == 1); 5836 #ifdef NK_INCLUDE_STANDARD_BOOL 5837 NK_STATIC_ASSERT(sizeof(nk_bool) == sizeof(bool)); 5838 #else 5839 NK_STATIC_ASSERT(sizeof(nk_bool) == 4); 5840 #endif 5841 5842 NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384}; 5843 #define NK_FLOAT_PRECISION 0.00000000000001 5844 5845 NK_GLOBAL const struct nk_color nk_red = {255,0,0,255}; 5846 NK_GLOBAL const struct nk_color nk_green = {0,255,0,255}; 5847 NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255}; 5848 NK_GLOBAL const struct nk_color nk_white = {255,255,255,255}; 5849 NK_GLOBAL const struct nk_color nk_black = {0,0,0,255}; 5850 NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255}; 5851 5852 /* widget */ 5853 #define nk_widget_state_reset(s)\ 5854 if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\ 5855 (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\ 5856 else (*(s)) = NK_WIDGET_STATE_INACTIVE; 5857 5858 /* math */ 5859 #ifndef NK_INV_SQRT 5860 NK_LIB float nk_inv_sqrt(float n); 5861 #endif 5862 #ifndef NK_SIN 5863 NK_LIB float nk_sin(float x); 5864 #endif 5865 #ifndef NK_COS 5866 NK_LIB float nk_cos(float x); 5867 #endif 5868 NK_LIB nk_uint nk_round_up_pow2(nk_uint v); 5869 NK_LIB struct nk_rect nk_shrink_rect(struct nk_rect r, float amount); 5870 NK_LIB struct nk_rect nk_pad_rect(struct nk_rect r, struct nk_vec2 pad); 5871 NK_LIB void nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, float x1, float y1); 5872 NK_LIB double nk_pow(double x, int n); 5873 NK_LIB int nk_ifloord(double x); 5874 NK_LIB int nk_ifloorf(float x); 5875 NK_LIB int nk_iceilf(float x); 5876 NK_LIB int nk_log10(double n); 5877 5878 /* util */ 5879 enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE}; 5880 NK_LIB nk_bool nk_is_lower(int c); 5881 NK_LIB nk_bool nk_is_upper(int c); 5882 NK_LIB int nk_to_upper(int c); 5883 NK_LIB int nk_to_lower(int c); 5884 5885 #ifndef NK_MEMCPY 5886 NK_LIB void* nk_memcopy(void *dst, const void *src, nk_size n); 5887 #endif 5888 #ifndef NK_MEMSET 5889 NK_LIB void nk_memset(void *ptr, int c0, nk_size size); 5890 #endif 5891 NK_LIB void nk_zero(void *ptr, nk_size size); 5892 NK_LIB char *nk_itoa(char *s, long n); 5893 NK_LIB int nk_string_float_limit(char *string, int prec); 5894 #ifndef NK_DTOA 5895 NK_LIB char *nk_dtoa(char *s, double n); 5896 #endif 5897 NK_LIB int nk_text_clamp(const struct nk_user_font *font, const char *text, int text_len, float space, int *glyphs, float *text_width, nk_rune *sep_list, int sep_count); 5898 NK_LIB struct nk_vec2 nk_text_calculate_text_bounds(const struct nk_user_font *font, const char *begin, int byte_len, float row_height, const char **remaining, struct nk_vec2 *out_offset, int *glyphs, int op); 5899 #ifdef NK_INCLUDE_STANDARD_VARARGS 5900 NK_LIB int nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args); 5901 #endif 5902 #ifdef NK_INCLUDE_STANDARD_IO 5903 NK_LIB char *nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc); 5904 #endif 5905 5906 /* buffer */ 5907 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 5908 NK_LIB void* nk_malloc(nk_handle unused, void *old,nk_size size); 5909 NK_LIB void nk_mfree(nk_handle unused, void *ptr); 5910 #endif 5911 NK_LIB void* nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, enum nk_buffer_allocation_type type); 5912 NK_LIB void* nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, nk_size size, nk_size align); 5913 NK_LIB void* nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size); 5914 5915 /* draw */ 5916 NK_LIB void nk_command_buffer_init(struct nk_command_buffer *cb, struct nk_buffer *b, enum nk_command_clipping clip); 5917 NK_LIB void nk_command_buffer_reset(struct nk_command_buffer *b); 5918 NK_LIB void* nk_command_buffer_push(struct nk_command_buffer* b, enum nk_command_type t, nk_size size); 5919 NK_LIB void nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, struct nk_rect content, struct nk_color background, struct nk_color foreground, float border_width, const struct nk_user_font *font); 5920 5921 /* buffering */ 5922 NK_LIB void nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *b); 5923 NK_LIB void nk_start(struct nk_context *ctx, struct nk_window *win); 5924 NK_LIB void nk_start_popup(struct nk_context *ctx, struct nk_window *win); 5925 NK_LIB void nk_finish_popup(struct nk_context *ctx, struct nk_window*); 5926 NK_LIB void nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *b); 5927 NK_LIB void nk_finish(struct nk_context *ctx, struct nk_window *w); 5928 NK_LIB void nk_build(struct nk_context *ctx); 5929 5930 /* text editor */ 5931 NK_LIB void nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, nk_plugin_filter filter); 5932 NK_LIB void nk_textedit_click(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height); 5933 NK_LIB void nk_textedit_drag(struct nk_text_edit *state, float x, float y, const struct nk_user_font *font, float row_height); 5934 NK_LIB void nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, const struct nk_user_font *font, float row_height); 5935 5936 /* window */ 5937 enum nk_window_insert_location { 5938 NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */ 5939 NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */ 5940 }; 5941 NK_LIB void *nk_create_window(struct nk_context *ctx); 5942 NK_LIB void nk_remove_window(struct nk_context*, struct nk_window*); 5943 NK_LIB void nk_free_window(struct nk_context *ctx, struct nk_window *win); 5944 NK_LIB struct nk_window *nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name); 5945 NK_LIB void nk_insert_window(struct nk_context *ctx, struct nk_window *win, enum nk_window_insert_location loc); 5946 5947 /* pool */ 5948 NK_LIB void nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, unsigned int capacity); 5949 NK_LIB void nk_pool_free(struct nk_pool *pool); 5950 NK_LIB void nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size); 5951 NK_LIB struct nk_page_element *nk_pool_alloc(struct nk_pool *pool); 5952 5953 /* page-element */ 5954 NK_LIB struct nk_page_element* nk_create_page_element(struct nk_context *ctx); 5955 NK_LIB void nk_link_page_element_into_freelist(struct nk_context *ctx, struct nk_page_element *elem); 5956 NK_LIB void nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem); 5957 5958 /* table */ 5959 NK_LIB struct nk_table* nk_create_table(struct nk_context *ctx); 5960 NK_LIB void nk_remove_table(struct nk_window *win, struct nk_table *tbl); 5961 NK_LIB void nk_free_table(struct nk_context *ctx, struct nk_table *tbl); 5962 NK_LIB void nk_push_table(struct nk_window *win, struct nk_table *tbl); 5963 NK_LIB nk_uint *nk_add_value(struct nk_context *ctx, struct nk_window *win, nk_hash name, nk_uint value); 5964 NK_LIB nk_uint *nk_find_value(struct nk_window *win, nk_hash name); 5965 5966 /* panel */ 5967 NK_LIB void *nk_create_panel(struct nk_context *ctx); 5968 NK_LIB void nk_free_panel(struct nk_context*, struct nk_panel *pan); 5969 NK_LIB nk_bool nk_panel_has_header(nk_flags flags, const char *title); 5970 NK_LIB struct nk_vec2 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type); 5971 NK_LIB float nk_panel_get_border(const struct nk_style *style, nk_flags flags, enum nk_panel_type type); 5972 NK_LIB struct nk_color nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type); 5973 NK_LIB nk_bool nk_panel_is_sub(enum nk_panel_type type); 5974 NK_LIB nk_bool nk_panel_is_nonblock(enum nk_panel_type type); 5975 NK_LIB nk_bool nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type); 5976 NK_LIB void nk_panel_end(struct nk_context *ctx); 5977 5978 /* layout */ 5979 NK_LIB float nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, float total_space, int columns); 5980 NK_LIB void nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, float height, int cols); 5981 NK_LIB void nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, float height, int cols, int width); 5982 NK_LIB void nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win); 5983 NK_LIB void nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, struct nk_window *win, int modify); 5984 NK_LIB void nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx); 5985 NK_LIB void nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx); 5986 5987 /* popup */ 5988 NK_LIB nk_bool nk_nonblock_begin(struct nk_context *ctx, nk_flags flags, struct nk_rect body, struct nk_rect header, enum nk_panel_type panel_type); 5989 5990 /* text */ 5991 struct nk_text { 5992 struct nk_vec2 padding; 5993 struct nk_color background; 5994 struct nk_color text; 5995 }; 5996 NK_LIB void nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, nk_flags a, const struct nk_user_font *f); 5997 NK_LIB void nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, const char *string, int len, const struct nk_text *t, const struct nk_user_font *f); 5998 5999 /* button */ 6000 NK_LIB nk_bool nk_button_behavior(nk_flags *state, struct nk_rect r, const struct nk_input *i, enum nk_button_behavior behavior); 6001 NK_LIB const struct nk_style_item* nk_draw_button(struct nk_command_buffer *out, const struct nk_rect *bounds, nk_flags state, const struct nk_style_button *style); 6002 NK_LIB nk_bool nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, const struct nk_style_button *style, const struct nk_input *in, enum nk_button_behavior behavior, struct nk_rect *content); 6003 NK_LIB void nk_draw_button_text(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const char *txt, int len, nk_flags text_alignment, const struct nk_user_font *font); 6004 NK_LIB nk_bool nk_do_button_text(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *string, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font); 6005 NK_LIB void nk_draw_button_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, enum nk_symbol_type type, const struct nk_user_font *font); 6006 NK_LIB nk_bool nk_do_button_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_input *in, const struct nk_user_font *font); 6007 NK_LIB void nk_draw_button_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, const struct nk_style_button *style, const struct nk_image *img); 6008 NK_LIB nk_bool nk_do_button_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, enum nk_button_behavior b, const struct nk_style_button *style, const struct nk_input *in); 6009 NK_LIB void nk_draw_button_text_symbol(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, const char *str, int len, enum nk_symbol_type type, const struct nk_user_font *font); 6010 NK_LIB nk_bool nk_do_button_text_symbol(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, enum nk_symbol_type symbol, const char *str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in); 6011 NK_LIB void nk_draw_button_text_image(struct nk_command_buffer *out, const struct nk_rect *bounds, const struct nk_rect *label, const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, const char *str, int len, const struct nk_user_font *font, const struct nk_image *img); 6012 NK_LIB nk_bool nk_do_button_text_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, struct nk_image img, const char* str, int len, nk_flags align, enum nk_button_behavior behavior, const struct nk_style_button *style, const struct nk_user_font *font, const struct nk_input *in); 6013 6014 /* toggle */ 6015 enum nk_toggle_type { 6016 NK_TOGGLE_CHECK, 6017 NK_TOGGLE_OPTION 6018 }; 6019 NK_LIB nk_bool nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, nk_flags *state, nk_bool active); 6020 NK_LIB void nk_draw_checkbox(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, nk_bool active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font); 6021 NK_LIB void nk_draw_option(struct nk_command_buffer *out, nk_flags state, const struct nk_style_toggle *style, nk_bool active, const struct nk_rect *label, const struct nk_rect *selector, const struct nk_rect *cursors, const char *string, int len, const struct nk_user_font *font); 6022 NK_LIB nk_bool nk_do_toggle(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, nk_bool *active, const char *str, int len, enum nk_toggle_type type, const struct nk_style_toggle *style, const struct nk_input *in, const struct nk_user_font *font); 6023 6024 /* progress */ 6025 NK_LIB nk_size nk_progress_behavior(nk_flags *state, struct nk_input *in, struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, nk_bool modifiable); 6026 NK_LIB void nk_draw_progress(struct nk_command_buffer *out, nk_flags state, const struct nk_style_progress *style, const struct nk_rect *bounds, const struct nk_rect *scursor, nk_size value, nk_size max); 6027 NK_LIB nk_size nk_do_progress(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_size value, nk_size max, nk_bool modifiable, const struct nk_style_progress *style, struct nk_input *in); 6028 6029 /* slider */ 6030 NK_LIB float nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, struct nk_rect *visual_cursor, struct nk_input *in, struct nk_rect bounds, float slider_min, float slider_max, float slider_value, float slider_step, float slider_steps); 6031 NK_LIB void nk_draw_slider(struct nk_command_buffer *out, nk_flags state, const struct nk_style_slider *style, const struct nk_rect *bounds, const struct nk_rect *visual_cursor, float min, float value, float max); 6032 NK_LIB float nk_do_slider(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, float min, float val, float max, float step, const struct nk_style_slider *style, struct nk_input *in, const struct nk_user_font *font); 6033 6034 /* scrollbar */ 6035 NK_LIB float nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, int has_scrolling, const struct nk_rect *scroll, const struct nk_rect *cursor, const struct nk_rect *empty0, const struct nk_rect *empty1, float scroll_offset, float target, float scroll_step, enum nk_orientation o); 6036 NK_LIB void nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, const struct nk_style_scrollbar *style, const struct nk_rect *bounds, const struct nk_rect *scroll); 6037 NK_LIB float nk_do_scrollbarv(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font); 6038 NK_LIB float nk_do_scrollbarh(nk_flags *state, struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, float offset, float target, float step, float button_pixel_inc, const struct nk_style_scrollbar *style, struct nk_input *in, const struct nk_user_font *font); 6039 6040 /* selectable */ 6041 NK_LIB void nk_draw_selectable(struct nk_command_buffer *out, nk_flags state, const struct nk_style_selectable *style, nk_bool active, const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, const char *string, int len, nk_flags align, const struct nk_user_font *font); 6042 NK_LIB nk_bool nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font); 6043 NK_LIB nk_bool nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, const struct nk_image *img, const struct nk_style_selectable *style, const struct nk_input *in, const struct nk_user_font *font); 6044 6045 /* edit */ 6046 NK_LIB void nk_edit_draw_text(struct nk_command_buffer *out, const struct nk_style_edit *style, float pos_x, float pos_y, float x_offset, const char *text, int byte_len, float row_height, const struct nk_user_font *font, struct nk_color background, struct nk_color foreground, nk_bool is_selected); 6047 NK_LIB nk_flags nk_do_edit(nk_flags *state, struct nk_command_buffer *out, struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, struct nk_text_edit *edit, const struct nk_style_edit *style, struct nk_input *in, const struct nk_user_font *font); 6048 6049 /* color-picker */ 6050 NK_LIB nk_bool nk_color_picker_behavior(nk_flags *state, const struct nk_rect *bounds, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf *color, const struct nk_input *in); 6051 NK_LIB void nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, struct nk_colorf col); 6052 NK_LIB nk_bool nk_do_color_picker(nk_flags *state, struct nk_command_buffer *out, struct nk_colorf *col, enum nk_color_format fmt, struct nk_rect bounds, struct nk_vec2 padding, const struct nk_input *in, const struct nk_user_font *font); 6053 6054 /* property */ 6055 enum nk_property_status { 6056 NK_PROPERTY_DEFAULT, 6057 NK_PROPERTY_EDIT, 6058 NK_PROPERTY_DRAG 6059 }; 6060 enum nk_property_filter { 6061 NK_FILTER_INT, 6062 NK_FILTER_FLOAT 6063 }; 6064 enum nk_property_kind { 6065 NK_PROPERTY_INT, 6066 NK_PROPERTY_FLOAT, 6067 NK_PROPERTY_DOUBLE 6068 }; 6069 union nk_property { 6070 int i; 6071 float f; 6072 double d; 6073 }; 6074 struct nk_property_variant { 6075 enum nk_property_kind kind; 6076 union nk_property value; 6077 union nk_property min_value; 6078 union nk_property max_value; 6079 union nk_property step; 6080 }; 6081 NK_LIB struct nk_property_variant nk_property_variant_int(int value, int min_value, int max_value, int step); 6082 NK_LIB struct nk_property_variant nk_property_variant_float(float value, float min_value, float max_value, float step); 6083 NK_LIB struct nk_property_variant nk_property_variant_double(double value, double min_value, double max_value, double step); 6084 6085 NK_LIB void nk_drag_behavior(nk_flags *state, const struct nk_input *in, struct nk_rect drag, struct nk_property_variant *variant, float inc_per_pixel); 6086 NK_LIB void nk_property_behavior(nk_flags *ws, const struct nk_input *in, struct nk_rect property, struct nk_rect label, struct nk_rect edit, struct nk_rect empty, int *state, struct nk_property_variant *variant, float inc_per_pixel); 6087 NK_LIB void nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, const char *name, int len, const struct nk_user_font *font); 6088 NK_LIB void nk_do_property(nk_flags *ws, struct nk_command_buffer *out, struct nk_rect property, const char *name, struct nk_property_variant *variant, float inc_per_pixel, char *buffer, int *len, int *state, int *cursor, int *select_begin, int *select_end, const struct nk_style_property *style, enum nk_property_filter filter, struct nk_input *in, const struct nk_user_font *font, struct nk_text_edit *text_edit, enum nk_button_behavior behavior); 6089 NK_LIB void nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, float inc_per_pixel, const enum nk_property_filter filter); 6090 6091 #ifdef NK_INCLUDE_FONT_BAKING 6092 6093 #define STB_RECT_PACK_IMPLEMENTATION 6094 #define STB_TRUETYPE_IMPLEMENTATION 6095 6096 /* Allow consumer to define own STBTT_malloc/STBTT_free, and use the font atlas' allocator otherwise */ 6097 #ifndef STBTT_malloc 6098 static void* 6099 nk_stbtt_malloc(nk_size size, void *user_data) { 6100 struct nk_allocator *alloc = (struct nk_allocator *) user_data; 6101 return alloc->alloc(alloc->userdata, 0, size); 6102 } 6103 6104 static void 6105 nk_stbtt_free(void *ptr, void *user_data) { 6106 struct nk_allocator *alloc = (struct nk_allocator *) user_data; 6107 alloc->free(alloc->userdata, ptr); 6108 } 6109 6110 #define STBTT_malloc(x,u) nk_stbtt_malloc(x,u) 6111 #define STBTT_free(x,u) nk_stbtt_free(x,u) 6112 6113 #endif /* STBTT_malloc */ 6114 6115 #endif /* NK_INCLUDE_FONT_BAKING */ 6116 6117 #endif 6118 6119 6120 6121 6122 6123 /* =============================================================== 6124 * 6125 * MATH 6126 * 6127 * ===============================================================*/ 6128 /*/// ### Math 6129 /// Since nuklear is supposed to work on all systems providing floating point 6130 /// math without any dependencies I also had to implement my own math functions 6131 /// for sqrt, sin and cos. Since the actual highly accurate implementations for 6132 /// the standard library functions are quite complex and I do not need high 6133 /// precision for my use cases I use approximations. 6134 /// 6135 /// Sqrt 6136 /// ---- 6137 /// For square root nuklear uses the famous fast inverse square root: 6138 /// https://en.wikipedia.org/wiki/Fast_inverse_square_root with 6139 /// slightly tweaked magic constant. While on today's hardware it is 6140 /// probably not faster it is still fast and accurate enough for 6141 /// nuklear's use cases. IMPORTANT: this requires float format IEEE 754 6142 /// 6143 /// Sine/Cosine 6144 /// ----------- 6145 /// All constants inside both function are generated Remez's minimax 6146 /// approximations for value range 0...2*PI. The reason why I decided to 6147 /// approximate exactly that range is that nuklear only needs sine and 6148 /// cosine to generate circles which only requires that exact range. 6149 /// In addition I used Remez instead of Taylor for additional precision: 6150 /// www.lolengine.net/blog/2011/12/21/better-function-approximations. 6151 /// 6152 /// The tool I used to generate constants for both sine and cosine 6153 /// (it can actually approximate a lot more functions) can be 6154 /// found here: www.lolengine.net/wiki/oss/lolremez 6155 */ 6156 #ifndef NK_INV_SQRT 6157 #define NK_INV_SQRT nk_inv_sqrt 6158 NK_LIB float 6159 nk_inv_sqrt(float n) 6160 { 6161 float x2; 6162 const float threehalfs = 1.5f; 6163 union {nk_uint i; float f;} conv = {0}; 6164 conv.f = n; 6165 x2 = n * 0.5f; 6166 conv.i = 0x5f375A84 - (conv.i >> 1); 6167 conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f)); 6168 return conv.f; 6169 } 6170 #endif 6171 #ifndef NK_SIN 6172 #define NK_SIN nk_sin 6173 NK_LIB float 6174 nk_sin(float x) 6175 { 6176 NK_STORAGE const float a0 = +1.91059300966915117e-31f; 6177 NK_STORAGE const float a1 = +1.00086760103908896f; 6178 NK_STORAGE const float a2 = -1.21276126894734565e-2f; 6179 NK_STORAGE const float a3 = -1.38078780785773762e-1f; 6180 NK_STORAGE const float a4 = -2.67353392911981221e-2f; 6181 NK_STORAGE const float a5 = +2.08026600266304389e-2f; 6182 NK_STORAGE const float a6 = -3.03996055049204407e-3f; 6183 NK_STORAGE const float a7 = +1.38235642404333740e-4f; 6184 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7)))))); 6185 } 6186 #endif 6187 #ifndef NK_COS 6188 #define NK_COS nk_cos 6189 NK_LIB float 6190 nk_cos(float x) 6191 { 6192 /* New implementation. Also generated using lolremez. */ 6193 /* Old version significantly deviated from expected results. */ 6194 NK_STORAGE const float a0 = 9.9995999154986614e-1f; 6195 NK_STORAGE const float a1 = 1.2548995793001028e-3f; 6196 NK_STORAGE const float a2 = -5.0648546280678015e-1f; 6197 NK_STORAGE const float a3 = 1.2942246466519995e-2f; 6198 NK_STORAGE const float a4 = 2.8668384702547972e-2f; 6199 NK_STORAGE const float a5 = 7.3726485210586547e-3f; 6200 NK_STORAGE const float a6 = -3.8510875386947414e-3f; 6201 NK_STORAGE const float a7 = 4.7196604604366623e-4f; 6202 NK_STORAGE const float a8 = -1.8776444013090451e-5f; 6203 return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*(a7 + x*a8))))))); 6204 } 6205 #endif 6206 NK_LIB nk_uint 6207 nk_round_up_pow2(nk_uint v) 6208 { 6209 v--; 6210 v |= v >> 1; 6211 v |= v >> 2; 6212 v |= v >> 4; 6213 v |= v >> 8; 6214 v |= v >> 16; 6215 v++; 6216 return v; 6217 } 6218 NK_LIB double 6219 nk_pow(double x, int n) 6220 { 6221 /* check the sign of n */ 6222 double r = 1; 6223 int plus = n >= 0; 6224 n = (plus) ? n : -n; 6225 while (n > 0) { 6226 if ((n & 1) == 1) 6227 r *= x; 6228 n /= 2; 6229 x *= x; 6230 } 6231 return plus ? r : 1.0 / r; 6232 } 6233 NK_LIB int 6234 nk_ifloord(double x) 6235 { 6236 x = (double)((int)x - ((x < 0.0) ? 1 : 0)); 6237 return (int)x; 6238 } 6239 NK_LIB int 6240 nk_ifloorf(float x) 6241 { 6242 x = (float)((int)x - ((x < 0.0f) ? 1 : 0)); 6243 return (int)x; 6244 } 6245 NK_LIB int 6246 nk_iceilf(float x) 6247 { 6248 if (x >= 0) { 6249 int i = (int)x; 6250 return (x > i) ? i+1: i; 6251 } else { 6252 int t = (int)x; 6253 float r = x - (float)t; 6254 return (r > 0.0f) ? t+1: t; 6255 } 6256 } 6257 NK_LIB int 6258 nk_log10(double n) 6259 { 6260 int neg; 6261 int ret; 6262 int exp = 0; 6263 6264 neg = (n < 0) ? 1 : 0; 6265 ret = (neg) ? (int)-n : (int)n; 6266 while ((ret / 10) > 0) { 6267 ret /= 10; 6268 exp++; 6269 } 6270 if (neg) exp = -exp; 6271 return exp; 6272 } 6273 NK_API struct nk_rect 6274 nk_get_null_rect(void) 6275 { 6276 return nk_null_rect; 6277 } 6278 NK_API struct nk_rect 6279 nk_rect(float x, float y, float w, float h) 6280 { 6281 struct nk_rect r; 6282 r.x = x; r.y = y; 6283 r.w = w; r.h = h; 6284 return r; 6285 } 6286 NK_API struct nk_rect 6287 nk_recti(int x, int y, int w, int h) 6288 { 6289 struct nk_rect r; 6290 r.x = (float)x; 6291 r.y = (float)y; 6292 r.w = (float)w; 6293 r.h = (float)h; 6294 return r; 6295 } 6296 NK_API struct nk_rect 6297 nk_recta(struct nk_vec2 pos, struct nk_vec2 size) 6298 { 6299 return nk_rect(pos.x, pos.y, size.x, size.y); 6300 } 6301 NK_API struct nk_rect 6302 nk_rectv(const float *r) 6303 { 6304 return nk_rect(r[0], r[1], r[2], r[3]); 6305 } 6306 NK_API struct nk_rect 6307 nk_rectiv(const int *r) 6308 { 6309 return nk_recti(r[0], r[1], r[2], r[3]); 6310 } 6311 NK_API struct nk_vec2 6312 nk_rect_pos(struct nk_rect r) 6313 { 6314 struct nk_vec2 ret; 6315 ret.x = r.x; ret.y = r.y; 6316 return ret; 6317 } 6318 NK_API struct nk_vec2 6319 nk_rect_size(struct nk_rect r) 6320 { 6321 struct nk_vec2 ret; 6322 ret.x = r.w; ret.y = r.h; 6323 return ret; 6324 } 6325 NK_LIB struct nk_rect 6326 nk_shrink_rect(struct nk_rect r, float amount) 6327 { 6328 struct nk_rect res; 6329 r.w = NK_MAX(r.w, 2 * amount); 6330 r.h = NK_MAX(r.h, 2 * amount); 6331 res.x = r.x + amount; 6332 res.y = r.y + amount; 6333 res.w = r.w - 2 * amount; 6334 res.h = r.h - 2 * amount; 6335 return res; 6336 } 6337 NK_LIB struct nk_rect 6338 nk_pad_rect(struct nk_rect r, struct nk_vec2 pad) 6339 { 6340 r.w = NK_MAX(r.w, 2 * pad.x); 6341 r.h = NK_MAX(r.h, 2 * pad.y); 6342 r.x += pad.x; r.y += pad.y; 6343 r.w -= 2 * pad.x; 6344 r.h -= 2 * pad.y; 6345 return r; 6346 } 6347 NK_API struct nk_vec2 6348 nk_vec2(float x, float y) 6349 { 6350 struct nk_vec2 ret; 6351 ret.x = x; ret.y = y; 6352 return ret; 6353 } 6354 NK_API struct nk_vec2 6355 nk_vec2i(int x, int y) 6356 { 6357 struct nk_vec2 ret; 6358 ret.x = (float)x; 6359 ret.y = (float)y; 6360 return ret; 6361 } 6362 NK_API struct nk_vec2 6363 nk_vec2v(const float *v) 6364 { 6365 return nk_vec2(v[0], v[1]); 6366 } 6367 NK_API struct nk_vec2 6368 nk_vec2iv(const int *v) 6369 { 6370 return nk_vec2i(v[0], v[1]); 6371 } 6372 NK_LIB void 6373 nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, 6374 float x1, float y1) 6375 { 6376 NK_ASSERT(a); 6377 NK_ASSERT(clip); 6378 clip->x = NK_MAX(a->x, x0); 6379 clip->y = NK_MAX(a->y, y0); 6380 clip->w = NK_MIN(a->x + a->w, x1) - clip->x; 6381 clip->h = NK_MIN(a->y + a->h, y1) - clip->y; 6382 clip->w = NK_MAX(0, clip->w); 6383 clip->h = NK_MAX(0, clip->h); 6384 } 6385 6386 NK_API void 6387 nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, 6388 float pad_x, float pad_y, enum nk_heading direction) 6389 { 6390 float w_half, h_half; 6391 NK_ASSERT(result); 6392 6393 r.w = NK_MAX(2 * pad_x, r.w); 6394 r.h = NK_MAX(2 * pad_y, r.h); 6395 r.w = r.w - 2 * pad_x; 6396 r.h = r.h - 2 * pad_y; 6397 6398 r.x = r.x + pad_x; 6399 r.y = r.y + pad_y; 6400 6401 w_half = r.w / 2.0f; 6402 h_half = r.h / 2.0f; 6403 6404 if (direction == NK_UP) { 6405 result[0] = nk_vec2(r.x + w_half, r.y); 6406 result[1] = nk_vec2(r.x + r.w, r.y + r.h); 6407 result[2] = nk_vec2(r.x, r.y + r.h); 6408 } else if (direction == NK_RIGHT) { 6409 result[0] = nk_vec2(r.x, r.y); 6410 result[1] = nk_vec2(r.x + r.w, r.y + h_half); 6411 result[2] = nk_vec2(r.x, r.y + r.h); 6412 } else if (direction == NK_DOWN) { 6413 result[0] = nk_vec2(r.x, r.y); 6414 result[1] = nk_vec2(r.x + r.w, r.y); 6415 result[2] = nk_vec2(r.x + w_half, r.y + r.h); 6416 } else { 6417 result[0] = nk_vec2(r.x, r.y + h_half); 6418 result[1] = nk_vec2(r.x + r.w, r.y); 6419 result[2] = nk_vec2(r.x + r.w, r.y + r.h); 6420 } 6421 } 6422 6423 6424 6425 6426 6427 /* =============================================================== 6428 * 6429 * UTIL 6430 * 6431 * ===============================================================*/ 6432 NK_INTERN int nk_str_match_here(const char *regexp, const char *text); 6433 NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text); 6434 NK_LIB nk_bool nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);} 6435 NK_LIB nk_bool nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);} 6436 NK_LIB int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;} 6437 NK_LIB int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;} 6438 6439 #ifndef NK_MEMCPY 6440 #define NK_MEMCPY nk_memcopy 6441 NK_LIB void* 6442 nk_memcopy(void *dst0, const void *src0, nk_size length) 6443 { 6444 nk_ptr t; 6445 char *dst = (char*)dst0; 6446 const char *src = (const char*)src0; 6447 if (length == 0 || dst == src) 6448 goto done; 6449 6450 #define nk_word int 6451 #define nk_wsize sizeof(nk_word) 6452 #define nk_wmask (nk_wsize-1) 6453 #define NK_TLOOP(s) if (t) NK_TLOOP1(s) 6454 #define NK_TLOOP1(s) do { s; } while (--t) 6455 6456 if (dst < src) { 6457 t = (nk_ptr)src; /* only need low bits */ 6458 if ((t | (nk_ptr)dst) & nk_wmask) { 6459 if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize) 6460 t = length; 6461 else 6462 t = nk_wsize - (t & nk_wmask); 6463 length -= t; 6464 NK_TLOOP1(*dst++ = *src++); 6465 } 6466 t = length / nk_wsize; 6467 NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src; 6468 src += nk_wsize; dst += nk_wsize); 6469 t = length & nk_wmask; 6470 NK_TLOOP(*dst++ = *src++); 6471 } else { 6472 src += length; 6473 dst += length; 6474 t = (nk_ptr)src; 6475 if ((t | (nk_ptr)dst) & nk_wmask) { 6476 if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize) 6477 t = length; 6478 else 6479 t &= nk_wmask; 6480 length -= t; 6481 NK_TLOOP1(*--dst = *--src); 6482 } 6483 t = length / nk_wsize; 6484 NK_TLOOP(src -= nk_wsize; dst -= nk_wsize; 6485 *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src); 6486 t = length & nk_wmask; 6487 NK_TLOOP(*--dst = *--src); 6488 } 6489 #undef nk_word 6490 #undef nk_wsize 6491 #undef nk_wmask 6492 #undef NK_TLOOP 6493 #undef NK_TLOOP1 6494 done: 6495 return (dst0); 6496 } 6497 #endif 6498 #ifndef NK_MEMSET 6499 #define NK_MEMSET nk_memset 6500 NK_LIB void 6501 nk_memset(void *ptr, int c0, nk_size size) 6502 { 6503 #define nk_word unsigned 6504 #define nk_wsize sizeof(nk_word) 6505 #define nk_wmask (nk_wsize - 1) 6506 nk_byte *dst = (nk_byte*)ptr; 6507 unsigned c = 0; 6508 nk_size t = 0; 6509 6510 if ((c = (nk_byte)c0) != 0) { 6511 c = (c << 8) | c; /* at least 16-bits */ 6512 if (sizeof(unsigned int) > 2) 6513 c = (c << 16) | c; /* at least 32-bits*/ 6514 } 6515 6516 /* too small of a word count */ 6517 dst = (nk_byte*)ptr; 6518 if (size < 3 * nk_wsize) { 6519 while (size--) *dst++ = (nk_byte)c0; 6520 return; 6521 } 6522 6523 /* align destination */ 6524 if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) { 6525 t = nk_wsize -t; 6526 size -= t; 6527 do { 6528 *dst++ = (nk_byte)c0; 6529 } while (--t != 0); 6530 } 6531 6532 /* fill word */ 6533 t = size / nk_wsize; 6534 do { 6535 *(nk_word*)((void*)dst) = c; 6536 dst += nk_wsize; 6537 } while (--t != 0); 6538 6539 /* fill trailing bytes */ 6540 t = (size & nk_wmask); 6541 if (t != 0) { 6542 do { 6543 *dst++ = (nk_byte)c0; 6544 } while (--t != 0); 6545 } 6546 6547 #undef nk_word 6548 #undef nk_wsize 6549 #undef nk_wmask 6550 } 6551 #endif 6552 NK_LIB void 6553 nk_zero(void *ptr, nk_size size) 6554 { 6555 NK_ASSERT(ptr); 6556 NK_MEMSET(ptr, 0, size); 6557 } 6558 NK_API int 6559 nk_strlen(const char *str) 6560 { 6561 int siz = 0; 6562 NK_ASSERT(str); 6563 while (str && *str++ != '\0') siz++; 6564 return siz; 6565 } 6566 NK_API int 6567 nk_strtoi(const char *str, const char **endptr) 6568 { 6569 int neg = 1; 6570 const char *p = str; 6571 int value = 0; 6572 6573 NK_ASSERT(str); 6574 if (!str) return 0; 6575 6576 /* skip whitespace */ 6577 while (*p == ' ') p++; 6578 if (*p == '-') { 6579 neg = -1; 6580 p++; 6581 } 6582 while (*p && *p >= '0' && *p <= '9') { 6583 value = value * 10 + (int) (*p - '0'); 6584 p++; 6585 } 6586 if (endptr) 6587 *endptr = p; 6588 return neg*value; 6589 } 6590 NK_API double 6591 nk_strtod(const char *str, const char **endptr) 6592 { 6593 double m; 6594 double neg = 1.0; 6595 const char *p = str; 6596 double value = 0; 6597 double number = 0; 6598 6599 NK_ASSERT(str); 6600 if (!str) return 0; 6601 6602 /* skip whitespace */ 6603 while (*p == ' ') p++; 6604 if (*p == '-') { 6605 neg = -1.0; 6606 p++; 6607 } 6608 6609 while (*p && *p != '.' && *p != 'e') { 6610 value = value * 10.0 + (double) (*p - '0'); 6611 p++; 6612 } 6613 6614 if (*p == '.') { 6615 p++; 6616 for(m = 0.1; *p && *p != 'e'; p++ ) { 6617 value = value + (double) (*p - '0') * m; 6618 m *= 0.1; 6619 } 6620 } 6621 if (*p == 'e') { 6622 int i, pow, div; 6623 p++; 6624 if (*p == '-') { 6625 div = nk_true; 6626 p++; 6627 } else if (*p == '+') { 6628 div = nk_false; 6629 p++; 6630 } else div = nk_false; 6631 6632 for (pow = 0; *p; p++) 6633 pow = pow * 10 + (int) (*p - '0'); 6634 6635 for (m = 1.0, i = 0; i < pow; i++) 6636 m *= 10.0; 6637 6638 if (div) 6639 value /= m; 6640 else value *= m; 6641 } 6642 number = value * neg; 6643 if (endptr) 6644 *endptr = p; 6645 return number; 6646 } 6647 NK_API float 6648 nk_strtof(const char *str, const char **endptr) 6649 { 6650 float float_value; 6651 double double_value; 6652 double_value = NK_STRTOD(str, endptr); 6653 float_value = (float)double_value; 6654 return float_value; 6655 } 6656 NK_API int 6657 nk_stricmp(const char *s1, const char *s2) 6658 { 6659 nk_int c1,c2,d; 6660 do { 6661 c1 = *s1++; 6662 c2 = *s2++; 6663 d = c1 - c2; 6664 while (d) { 6665 if (c1 <= 'Z' && c1 >= 'A') { 6666 d += ('a' - 'A'); 6667 if (!d) break; 6668 } 6669 if (c2 <= 'Z' && c2 >= 'A') { 6670 d -= ('a' - 'A'); 6671 if (!d) break; 6672 } 6673 return ((d >= 0) << 1) - 1; 6674 } 6675 } while (c1); 6676 return 0; 6677 } 6678 NK_API int 6679 nk_stricmpn(const char *s1, const char *s2, int n) 6680 { 6681 int c1,c2,d; 6682 NK_ASSERT(n >= 0); 6683 do { 6684 c1 = *s1++; 6685 c2 = *s2++; 6686 if (!n--) return 0; 6687 6688 d = c1 - c2; 6689 while (d) { 6690 if (c1 <= 'Z' && c1 >= 'A') { 6691 d += ('a' - 'A'); 6692 if (!d) break; 6693 } 6694 if (c2 <= 'Z' && c2 >= 'A') { 6695 d -= ('a' - 'A'); 6696 if (!d) break; 6697 } 6698 return ((d >= 0) << 1) - 1; 6699 } 6700 } while (c1); 6701 return 0; 6702 } 6703 NK_INTERN int 6704 nk_str_match_here(const char *regexp, const char *text) 6705 { 6706 if (regexp[0] == '\0') 6707 return 1; 6708 if (regexp[1] == '*') 6709 return nk_str_match_star(regexp[0], regexp+2, text); 6710 if (regexp[0] == '$' && regexp[1] == '\0') 6711 return *text == '\0'; 6712 if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) 6713 return nk_str_match_here(regexp+1, text+1); 6714 return 0; 6715 } 6716 NK_INTERN int 6717 nk_str_match_star(int c, const char *regexp, const char *text) 6718 { 6719 do {/* a '* matches zero or more instances */ 6720 if (nk_str_match_here(regexp, text)) 6721 return 1; 6722 } while (*text != '\0' && (*text++ == c || c == '.')); 6723 return 0; 6724 } 6725 NK_API int 6726 nk_strfilter(const char *text, const char *regexp) 6727 { 6728 /* 6729 c matches any literal character c 6730 . matches any single character 6731 ^ matches the beginning of the input string 6732 $ matches the end of the input string 6733 * matches zero or more occurrences of the previous character*/ 6734 if (regexp[0] == '^') 6735 return nk_str_match_here(regexp+1, text); 6736 do { /* must look even if string is empty */ 6737 if (nk_str_match_here(regexp, text)) 6738 return 1; 6739 } while (*text++ != '\0'); 6740 return 0; 6741 } 6742 NK_API int 6743 nk_strmatch_fuzzy_text(const char *str, int str_len, 6744 const char *pattern, int *out_score) 6745 { 6746 /* Returns true if each character in pattern is found sequentially within str 6747 * if found then out_score is also set. Score value has no intrinsic meaning. 6748 * Range varies with pattern. Can only compare scores with same search pattern. */ 6749 6750 /* bonus for adjacent matches */ 6751 #define NK_ADJACENCY_BONUS 5 6752 /* bonus if match occurs after a separator */ 6753 #define NK_SEPARATOR_BONUS 10 6754 /* bonus if match is uppercase and prev is lower */ 6755 #define NK_CAMEL_BONUS 10 6756 /* penalty applied for every letter in str before the first match */ 6757 #define NK_LEADING_LETTER_PENALTY (-3) 6758 /* maximum penalty for leading letters */ 6759 #define NK_MAX_LEADING_LETTER_PENALTY (-9) 6760 /* penalty for every letter that doesn't matter */ 6761 #define NK_UNMATCHED_LETTER_PENALTY (-1) 6762 6763 /* loop variables */ 6764 int score = 0; 6765 char const * pattern_iter = pattern; 6766 int str_iter = 0; 6767 int prev_matched = nk_false; 6768 int prev_lower = nk_false; 6769 /* true so if first letter match gets separator bonus*/ 6770 int prev_separator = nk_true; 6771 6772 /* use "best" matched letter if multiple string letters match the pattern */ 6773 char const * best_letter = 0; 6774 int best_letter_score = 0; 6775 6776 /* loop over strings */ 6777 NK_ASSERT(str); 6778 NK_ASSERT(pattern); 6779 if (!str || !str_len || !pattern) return 0; 6780 while (str_iter < str_len) 6781 { 6782 const char pattern_letter = *pattern_iter; 6783 const char str_letter = str[str_iter]; 6784 6785 int next_match = *pattern_iter != '\0' && 6786 nk_to_lower(pattern_letter) == nk_to_lower(str_letter); 6787 int rematch = best_letter && nk_to_upper(*best_letter) == nk_to_upper(str_letter); 6788 6789 int advanced = next_match && best_letter; 6790 int pattern_repeat = best_letter && *pattern_iter != '\0'; 6791 pattern_repeat = pattern_repeat && 6792 nk_to_lower(*best_letter) == nk_to_lower(pattern_letter); 6793 6794 if (advanced || pattern_repeat) { 6795 score += best_letter_score; 6796 best_letter = 0; 6797 best_letter_score = 0; 6798 } 6799 6800 if (next_match || rematch) 6801 { 6802 int new_score = 0; 6803 /* Apply penalty for each letter before the first pattern match */ 6804 if (pattern_iter == pattern) { 6805 int count = (int)(&str[str_iter] - str); 6806 int penalty = NK_LEADING_LETTER_PENALTY * count; 6807 if (penalty < NK_MAX_LEADING_LETTER_PENALTY) 6808 penalty = NK_MAX_LEADING_LETTER_PENALTY; 6809 6810 score += penalty; 6811 } 6812 6813 /* apply bonus for consecutive bonuses */ 6814 if (prev_matched) 6815 new_score += NK_ADJACENCY_BONUS; 6816 6817 /* apply bonus for matches after a separator */ 6818 if (prev_separator) 6819 new_score += NK_SEPARATOR_BONUS; 6820 6821 /* apply bonus across camel case boundaries */ 6822 if (prev_lower && nk_is_upper(str_letter)) 6823 new_score += NK_CAMEL_BONUS; 6824 6825 /* update pattern iter IFF the next pattern letter was matched */ 6826 if (next_match) 6827 ++pattern_iter; 6828 6829 /* update best letter in str which may be for a "next" letter or a rematch */ 6830 if (new_score >= best_letter_score) { 6831 /* apply penalty for now skipped letter */ 6832 if (best_letter != 0) 6833 score += NK_UNMATCHED_LETTER_PENALTY; 6834 6835 best_letter = &str[str_iter]; 6836 best_letter_score = new_score; 6837 } 6838 prev_matched = nk_true; 6839 } else { 6840 score += NK_UNMATCHED_LETTER_PENALTY; 6841 prev_matched = nk_false; 6842 } 6843 6844 /* separators should be more easily defined */ 6845 prev_lower = nk_is_lower(str_letter) != 0; 6846 prev_separator = str_letter == '_' || str_letter == ' '; 6847 6848 ++str_iter; 6849 } 6850 6851 /* apply score for last match */ 6852 if (best_letter) 6853 score += best_letter_score; 6854 6855 /* did not match full pattern */ 6856 if (*pattern_iter != '\0') 6857 return nk_false; 6858 6859 if (out_score) 6860 *out_score = score; 6861 return nk_true; 6862 } 6863 NK_API int 6864 nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score) 6865 { 6866 return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score); 6867 } 6868 NK_LIB int 6869 nk_string_float_limit(char *string, int prec) 6870 { 6871 int dot = 0; 6872 char *c = string; 6873 while (*c) { 6874 if (*c == '.') { 6875 dot = 1; 6876 c++; 6877 continue; 6878 } 6879 if (dot == (prec+1)) { 6880 *c = 0; 6881 break; 6882 } 6883 if (dot > 0) dot++; 6884 c++; 6885 } 6886 return (int)(c - string); 6887 } 6888 NK_INTERN void 6889 nk_strrev_ascii(char *s) 6890 { 6891 int len = nk_strlen(s); 6892 int end = len / 2; 6893 int i = 0; 6894 char t; 6895 for (; i < end; ++i) { 6896 t = s[i]; 6897 s[i] = s[len - 1 - i]; 6898 s[len -1 - i] = t; 6899 } 6900 } 6901 NK_LIB char* 6902 nk_itoa(char *s, long n) 6903 { 6904 long i = 0; 6905 if (n == 0) { 6906 s[i++] = '0'; 6907 s[i] = 0; 6908 return s; 6909 } 6910 if (n < 0) { 6911 s[i++] = '-'; 6912 n = -n; 6913 } 6914 while (n > 0) { 6915 s[i++] = (char)('0' + (n % 10)); 6916 n /= 10; 6917 } 6918 s[i] = 0; 6919 if (s[0] == '-') 6920 ++s; 6921 6922 nk_strrev_ascii(s); 6923 return s; 6924 } 6925 #ifndef NK_DTOA 6926 #define NK_DTOA nk_dtoa 6927 NK_LIB char* 6928 nk_dtoa(char *s, double n) 6929 { 6930 int useExp = 0; 6931 int digit = 0, m = 0, m1 = 0; 6932 char *c = s; 6933 int neg = 0; 6934 6935 NK_ASSERT(s); 6936 if (!s) return 0; 6937 6938 if (n == 0.0) { 6939 s[0] = '0'; s[1] = '\0'; 6940 return s; 6941 } 6942 6943 neg = (n < 0); 6944 if (neg) n = -n; 6945 6946 /* calculate magnitude */ 6947 m = nk_log10(n); 6948 useExp = (m >= 14 || (neg && m >= 9) || m <= -9); 6949 if (neg) *(c++) = '-'; 6950 6951 /* set up for scientific notation */ 6952 if (useExp) { 6953 if (m < 0) 6954 m -= 1; 6955 n = n / (double)nk_pow(10.0, m); 6956 m1 = m; 6957 m = 0; 6958 } 6959 if (m < 1.0) { 6960 m = 0; 6961 } 6962 6963 /* convert the number */ 6964 while (n > NK_FLOAT_PRECISION || m >= 0) { 6965 double weight = nk_pow(10.0, m); 6966 if (weight > 0) { 6967 double t = (double)n / weight; 6968 digit = nk_ifloord(t); 6969 n -= ((double)digit * weight); 6970 *(c++) = (char)('0' + (char)digit); 6971 } 6972 if (m == 0 && n > 0) 6973 *(c++) = '.'; 6974 m--; 6975 } 6976 6977 if (useExp) { 6978 /* convert the exponent */ 6979 int i, j; 6980 *(c++) = 'e'; 6981 if (m1 > 0) { 6982 *(c++) = '+'; 6983 } else { 6984 *(c++) = '-'; 6985 m1 = -m1; 6986 } 6987 m = 0; 6988 while (m1 > 0) { 6989 *(c++) = (char)('0' + (char)(m1 % 10)); 6990 m1 /= 10; 6991 m++; 6992 } 6993 c -= m; 6994 for (i = 0, j = m-1; i<j; i++, j--) { 6995 /* swap without temporary */ 6996 c[i] ^= c[j]; 6997 c[j] ^= c[i]; 6998 c[i] ^= c[j]; 6999 } 7000 c += m; 7001 } 7002 *(c) = '\0'; 7003 return s; 7004 } 7005 #endif 7006 #ifdef NK_INCLUDE_STANDARD_VARARGS 7007 #ifndef NK_INCLUDE_STANDARD_IO 7008 NK_INTERN int 7009 nk_vsnprintf(char *buf, int buf_size, const char *fmt, va_list args) 7010 { 7011 enum nk_arg_type { 7012 NK_ARG_TYPE_CHAR, 7013 NK_ARG_TYPE_SHORT, 7014 NK_ARG_TYPE_DEFAULT, 7015 NK_ARG_TYPE_LONG 7016 }; 7017 enum nk_arg_flags { 7018 NK_ARG_FLAG_LEFT = 0x01, 7019 NK_ARG_FLAG_PLUS = 0x02, 7020 NK_ARG_FLAG_SPACE = 0x04, 7021 NK_ARG_FLAG_NUM = 0x10, 7022 NK_ARG_FLAG_ZERO = 0x20 7023 }; 7024 7025 char number_buffer[NK_MAX_NUMBER_BUFFER]; 7026 enum nk_arg_type arg_type = NK_ARG_TYPE_DEFAULT; 7027 int precision = NK_DEFAULT; 7028 int width = NK_DEFAULT; 7029 nk_flags flag = 0; 7030 7031 int len = 0; 7032 int result = -1; 7033 const char *iter = fmt; 7034 7035 NK_ASSERT(buf); 7036 NK_ASSERT(buf_size); 7037 if (!buf || !buf_size || !fmt) return 0; 7038 for (iter = fmt; *iter && len < buf_size; iter++) { 7039 /* copy all non-format characters */ 7040 while (*iter && (*iter != '%') && (len < buf_size)) 7041 buf[len++] = *iter++; 7042 if (!(*iter) || len >= buf_size) break; 7043 iter++; 7044 7045 /* flag arguments */ 7046 while (*iter) { 7047 if (*iter == '-') flag |= NK_ARG_FLAG_LEFT; 7048 else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS; 7049 else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE; 7050 else if (*iter == '#') flag |= NK_ARG_FLAG_NUM; 7051 else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO; 7052 else break; 7053 iter++; 7054 } 7055 7056 /* width argument */ 7057 width = NK_DEFAULT; 7058 if (*iter >= '1' && *iter <= '9') { 7059 const char *end; 7060 width = nk_strtoi(iter, &end); 7061 if (end == iter) 7062 width = -1; 7063 else iter = end; 7064 } else if (*iter == '*') { 7065 width = va_arg(args, int); 7066 iter++; 7067 } 7068 7069 /* precision argument */ 7070 precision = NK_DEFAULT; 7071 if (*iter == '.') { 7072 iter++; 7073 if (*iter == '*') { 7074 precision = va_arg(args, int); 7075 iter++; 7076 } else { 7077 const char *end; 7078 precision = nk_strtoi(iter, &end); 7079 if (end == iter) 7080 precision = -1; 7081 else iter = end; 7082 } 7083 } 7084 7085 /* length modifier */ 7086 if (*iter == 'h') { 7087 if (*(iter+1) == 'h') { 7088 arg_type = NK_ARG_TYPE_CHAR; 7089 iter++; 7090 } else arg_type = NK_ARG_TYPE_SHORT; 7091 iter++; 7092 } else if (*iter == 'l') { 7093 arg_type = NK_ARG_TYPE_LONG; 7094 iter++; 7095 } else arg_type = NK_ARG_TYPE_DEFAULT; 7096 7097 /* specifier */ 7098 if (*iter == '%') { 7099 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 7100 NK_ASSERT(precision == NK_DEFAULT); 7101 NK_ASSERT(width == NK_DEFAULT); 7102 if (len < buf_size) 7103 buf[len++] = '%'; 7104 } else if (*iter == 's') { 7105 /* string */ 7106 const char *str = va_arg(args, const char*); 7107 NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!"); 7108 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 7109 NK_ASSERT(precision == NK_DEFAULT); 7110 NK_ASSERT(width == NK_DEFAULT); 7111 if (str == buf) return -1; 7112 while (str && *str && len < buf_size) 7113 buf[len++] = *str++; 7114 } else if (*iter == 'n') { 7115 /* current length callback */ 7116 signed int *n = va_arg(args, int*); 7117 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 7118 NK_ASSERT(precision == NK_DEFAULT); 7119 NK_ASSERT(width == NK_DEFAULT); 7120 if (n) *n = len; 7121 } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') { 7122 /* signed integer */ 7123 long value = 0; 7124 const char *num_iter; 7125 int num_len, num_print, padding; 7126 int cur_precision = NK_MAX(precision, 1); 7127 int cur_width = NK_MAX(width, 0); 7128 7129 /* retrieve correct value type */ 7130 if (arg_type == NK_ARG_TYPE_CHAR) 7131 value = (signed char)va_arg(args, int); 7132 else if (arg_type == NK_ARG_TYPE_SHORT) 7133 value = (signed short)va_arg(args, int); 7134 else if (arg_type == NK_ARG_TYPE_LONG) 7135 value = va_arg(args, signed long); 7136 else if (*iter == 'c') 7137 value = (unsigned char)va_arg(args, int); 7138 else value = va_arg(args, signed int); 7139 7140 /* convert number to string */ 7141 nk_itoa(number_buffer, value); 7142 num_len = nk_strlen(number_buffer); 7143 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); 7144 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) 7145 padding = NK_MAX(padding-1, 0); 7146 7147 /* fill left padding up to a total of `width` characters */ 7148 if (!(flag & NK_ARG_FLAG_LEFT)) { 7149 while (padding-- > 0 && (len < buf_size)) { 7150 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) 7151 buf[len++] = '0'; 7152 else buf[len++] = ' '; 7153 } 7154 } 7155 7156 /* copy string value representation into buffer */ 7157 if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size) 7158 buf[len++] = '+'; 7159 else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size) 7160 buf[len++] = ' '; 7161 7162 /* fill up to precision number of digits with '0' */ 7163 num_print = NK_MAX(cur_precision, num_len); 7164 while (precision && (num_print > num_len) && (len < buf_size)) { 7165 buf[len++] = '0'; 7166 num_print--; 7167 } 7168 7169 /* copy string value representation into buffer */ 7170 num_iter = number_buffer; 7171 while (precision && *num_iter && len < buf_size) 7172 buf[len++] = *num_iter++; 7173 7174 /* fill right padding up to width characters */ 7175 if (flag & NK_ARG_FLAG_LEFT) { 7176 while ((padding-- > 0) && (len < buf_size)) 7177 buf[len++] = ' '; 7178 } 7179 } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') { 7180 /* unsigned integer */ 7181 unsigned long value = 0; 7182 int num_len = 0, num_print, padding = 0; 7183 int cur_precision = NK_MAX(precision, 1); 7184 int cur_width = NK_MAX(width, 0); 7185 unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16; 7186 7187 /* print oct/hex/dec value */ 7188 const char *upper_output_format = "0123456789ABCDEF"; 7189 const char *lower_output_format = "0123456789abcdef"; 7190 const char *output_format = (*iter == 'x') ? 7191 lower_output_format: upper_output_format; 7192 7193 /* retrieve correct value type */ 7194 if (arg_type == NK_ARG_TYPE_CHAR) 7195 value = (unsigned char)va_arg(args, int); 7196 else if (arg_type == NK_ARG_TYPE_SHORT) 7197 value = (unsigned short)va_arg(args, int); 7198 else if (arg_type == NK_ARG_TYPE_LONG) 7199 value = va_arg(args, unsigned long); 7200 else value = va_arg(args, unsigned int); 7201 7202 do { 7203 /* convert decimal number into hex/oct number */ 7204 int digit = output_format[value % base]; 7205 if (num_len < NK_MAX_NUMBER_BUFFER) 7206 number_buffer[num_len++] = (char)digit; 7207 value /= base; 7208 } while (value > 0); 7209 7210 num_print = NK_MAX(cur_precision, num_len); 7211 padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); 7212 if (flag & NK_ARG_FLAG_NUM) 7213 padding = NK_MAX(padding-1, 0); 7214 7215 /* fill left padding up to a total of `width` characters */ 7216 if (!(flag & NK_ARG_FLAG_LEFT)) { 7217 while ((padding-- > 0) && (len < buf_size)) { 7218 if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) 7219 buf[len++] = '0'; 7220 else buf[len++] = ' '; 7221 } 7222 } 7223 7224 /* fill up to precision number of digits */ 7225 if (num_print && (flag & NK_ARG_FLAG_NUM)) { 7226 if ((*iter == 'o') && (len < buf_size)) { 7227 buf[len++] = '0'; 7228 } else if ((*iter == 'x') && ((len+1) < buf_size)) { 7229 buf[len++] = '0'; 7230 buf[len++] = 'x'; 7231 } else if ((*iter == 'X') && ((len+1) < buf_size)) { 7232 buf[len++] = '0'; 7233 buf[len++] = 'X'; 7234 } 7235 } 7236 while (precision && (num_print > num_len) && (len < buf_size)) { 7237 buf[len++] = '0'; 7238 num_print--; 7239 } 7240 7241 /* reverse number direction */ 7242 while (num_len > 0) { 7243 if (precision && (len < buf_size)) 7244 buf[len++] = number_buffer[num_len-1]; 7245 num_len--; 7246 } 7247 7248 /* fill right padding up to width characters */ 7249 if (flag & NK_ARG_FLAG_LEFT) { 7250 while ((padding-- > 0) && (len < buf_size)) 7251 buf[len++] = ' '; 7252 } 7253 } else if (*iter == 'f') { 7254 /* floating point */ 7255 const char *num_iter; 7256 int cur_precision = (precision < 0) ? 6: precision; 7257 int prefix, cur_width = NK_MAX(width, 0); 7258 double value = va_arg(args, double); 7259 int num_len = 0, frac_len = 0, dot = 0; 7260 int padding = 0; 7261 7262 NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); 7263 NK_DTOA(number_buffer, value); 7264 num_len = nk_strlen(number_buffer); 7265 7266 /* calculate padding */ 7267 num_iter = number_buffer; 7268 while (*num_iter && *num_iter != '.') 7269 num_iter++; 7270 7271 prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0; 7272 padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0); 7273 if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) 7274 padding = NK_MAX(padding-1, 0); 7275 7276 /* fill left padding up to a total of `width` characters */ 7277 if (!(flag & NK_ARG_FLAG_LEFT)) { 7278 while (padding-- > 0 && (len < buf_size)) { 7279 if (flag & NK_ARG_FLAG_ZERO) 7280 buf[len++] = '0'; 7281 else buf[len++] = ' '; 7282 } 7283 } 7284 7285 /* copy string value representation into buffer */ 7286 num_iter = number_buffer; 7287 if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size)) 7288 buf[len++] = '+'; 7289 else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size)) 7290 buf[len++] = ' '; 7291 while (*num_iter) { 7292 if (dot) frac_len++; 7293 if (len < buf_size) 7294 buf[len++] = *num_iter; 7295 if (*num_iter == '.') dot = 1; 7296 if (frac_len >= cur_precision) break; 7297 num_iter++; 7298 } 7299 7300 /* fill number up to precision */ 7301 while (frac_len < cur_precision) { 7302 if (!dot && len < buf_size) { 7303 buf[len++] = '.'; 7304 dot = 1; 7305 } 7306 if (len < buf_size) 7307 buf[len++] = '0'; 7308 frac_len++; 7309 } 7310 7311 /* fill right padding up to width characters */ 7312 if (flag & NK_ARG_FLAG_LEFT) { 7313 while ((padding-- > 0) && (len < buf_size)) 7314 buf[len++] = ' '; 7315 } 7316 } else { 7317 /* Specifier not supported: g,G,e,E,p,z */ 7318 NK_ASSERT(0 && "specifier is not supported!"); 7319 return result; 7320 } 7321 } 7322 buf[(len >= buf_size)?(buf_size-1):len] = 0; 7323 result = (len >= buf_size)?-1:len; 7324 return result; 7325 } 7326 #endif 7327 NK_LIB int 7328 nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args) 7329 { 7330 int result = -1; 7331 NK_ASSERT(buf); 7332 NK_ASSERT(buf_size); 7333 if (!buf || !buf_size || !fmt) return 0; 7334 #ifdef NK_INCLUDE_STANDARD_IO 7335 result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args); 7336 result = (result >= buf_size) ? -1: result; 7337 buf[buf_size-1] = 0; 7338 #else 7339 result = nk_vsnprintf(buf, buf_size, fmt, args); 7340 #endif 7341 return result; 7342 } 7343 #endif 7344 NK_API nk_hash 7345 nk_murmur_hash(const void * key, int len, nk_hash seed) 7346 { 7347 /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/ 7348 #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r))) 7349 7350 nk_uint h1 = seed; 7351 nk_uint k1; 7352 const nk_byte *data = (const nk_byte*)key; 7353 const nk_byte *keyptr = data; 7354 nk_byte *k1ptr; 7355 const int bsize = sizeof(k1); 7356 const int nblocks = len/4; 7357 7358 const nk_uint c1 = 0xcc9e2d51; 7359 const nk_uint c2 = 0x1b873593; 7360 const nk_byte *tail; 7361 int i; 7362 7363 /* body */ 7364 if (!key) return 0; 7365 for (i = 0; i < nblocks; ++i, keyptr += bsize) { 7366 k1ptr = (nk_byte*)&k1; 7367 k1ptr[0] = keyptr[0]; 7368 k1ptr[1] = keyptr[1]; 7369 k1ptr[2] = keyptr[2]; 7370 k1ptr[3] = keyptr[3]; 7371 7372 k1 *= c1; 7373 k1 = NK_ROTL(k1,15); 7374 k1 *= c2; 7375 7376 h1 ^= k1; 7377 h1 = NK_ROTL(h1,13); 7378 h1 = h1*5+0xe6546b64; 7379 } 7380 7381 /* tail */ 7382 tail = (const nk_byte*)(data + nblocks*4); 7383 k1 = 0; 7384 switch (len & 3) { 7385 case 3: k1 ^= (nk_uint)(tail[2] << 16); /* fallthrough */ 7386 case 2: k1 ^= (nk_uint)(tail[1] << 8u); /* fallthrough */ 7387 case 1: k1 ^= tail[0]; 7388 k1 *= c1; 7389 k1 = NK_ROTL(k1,15); 7390 k1 *= c2; 7391 h1 ^= k1; 7392 break; 7393 default: break; 7394 } 7395 7396 /* finalization */ 7397 h1 ^= (nk_uint)len; 7398 /* fmix32 */ 7399 h1 ^= h1 >> 16; 7400 h1 *= 0x85ebca6b; 7401 h1 ^= h1 >> 13; 7402 h1 *= 0xc2b2ae35; 7403 h1 ^= h1 >> 16; 7404 7405 #undef NK_ROTL 7406 return h1; 7407 } 7408 #ifdef NK_INCLUDE_STANDARD_IO 7409 NK_LIB char* 7410 nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc) 7411 { 7412 char *buf; 7413 FILE *fd; 7414 long ret; 7415 7416 NK_ASSERT(path); 7417 NK_ASSERT(siz); 7418 NK_ASSERT(alloc); 7419 if (!path || !siz || !alloc) 7420 return 0; 7421 7422 fd = fopen(path, "rb"); 7423 if (!fd) return 0; 7424 fseek(fd, 0, SEEK_END); 7425 ret = ftell(fd); 7426 if (ret < 0) { 7427 fclose(fd); 7428 return 0; 7429 } 7430 *siz = (nk_size)ret; 7431 fseek(fd, 0, SEEK_SET); 7432 buf = (char*)alloc->alloc(alloc->userdata,0, *siz); 7433 NK_ASSERT(buf); 7434 if (!buf) { 7435 fclose(fd); 7436 return 0; 7437 } 7438 *siz = (nk_size)fread(buf, 1,*siz, fd); 7439 fclose(fd); 7440 return buf; 7441 } 7442 #endif 7443 NK_LIB int 7444 nk_text_clamp(const struct nk_user_font *font, const char *text, 7445 int text_len, float space, int *glyphs, float *text_width, 7446 nk_rune *sep_list, int sep_count) 7447 { 7448 int i = 0; 7449 int glyph_len = 0; 7450 float last_width = 0; 7451 nk_rune unicode = 0; 7452 float width = 0; 7453 int len = 0; 7454 int g = 0; 7455 float s; 7456 7457 int sep_len = 0; 7458 int sep_g = 0; 7459 float sep_width = 0; 7460 sep_count = NK_MAX(sep_count,0); 7461 7462 glyph_len = nk_utf_decode(text, &unicode, text_len); 7463 while (glyph_len && (width < space) && (len < text_len)) { 7464 len += glyph_len; 7465 s = font->width(font->userdata, font->height, text, len); 7466 for (i = 0; i < sep_count; ++i) { 7467 if (unicode != sep_list[i]) continue; 7468 sep_width = last_width = width; 7469 sep_g = g+1; 7470 sep_len = len; 7471 break; 7472 } 7473 if (i == sep_count){ 7474 last_width = sep_width = width; 7475 sep_g = g+1; 7476 } 7477 width = s; 7478 glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len); 7479 g++; 7480 } 7481 if (len >= text_len) { 7482 *glyphs = g; 7483 *text_width = last_width; 7484 return len; 7485 } else { 7486 *glyphs = sep_g; 7487 *text_width = sep_width; 7488 return (!sep_len) ? len: sep_len; 7489 } 7490 } 7491 NK_LIB struct nk_vec2 7492 nk_text_calculate_text_bounds(const struct nk_user_font *font, 7493 const char *begin, int byte_len, float row_height, const char **remaining, 7494 struct nk_vec2 *out_offset, int *glyphs, int op) 7495 { 7496 float line_height = row_height; 7497 struct nk_vec2 text_size = nk_vec2(0,0); 7498 float line_width = 0.0f; 7499 7500 float glyph_width; 7501 int glyph_len = 0; 7502 nk_rune unicode = 0; 7503 int text_len = 0; 7504 if (!begin || byte_len <= 0 || !font) 7505 return nk_vec2(0,row_height); 7506 7507 glyph_len = nk_utf_decode(begin, &unicode, byte_len); 7508 if (!glyph_len) return text_size; 7509 glyph_width = font->width(font->userdata, font->height, begin, glyph_len); 7510 7511 *glyphs = 0; 7512 while ((text_len < byte_len) && glyph_len) { 7513 if (unicode == '\n') { 7514 text_size.x = NK_MAX(text_size.x, line_width); 7515 text_size.y += line_height; 7516 line_width = 0; 7517 *glyphs+=1; 7518 if (op == NK_STOP_ON_NEW_LINE) 7519 break; 7520 7521 text_len++; 7522 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7523 continue; 7524 } 7525 7526 if (unicode == '\r') { 7527 text_len++; 7528 *glyphs+=1; 7529 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7530 continue; 7531 } 7532 7533 *glyphs = *glyphs + 1; 7534 text_len += glyph_len; 7535 line_width += (float)glyph_width; 7536 glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); 7537 glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len); 7538 continue; 7539 } 7540 7541 if (text_size.x < line_width) 7542 text_size.x = line_width; 7543 if (out_offset) 7544 *out_offset = nk_vec2(line_width, text_size.y + line_height); 7545 if (line_width > 0 || text_size.y == 0.0f) 7546 text_size.y += line_height; 7547 if (remaining) 7548 *remaining = begin+text_len; 7549 return text_size; 7550 } 7551 7552 7553 7554 7555 7556 /* ============================================================== 7557 * 7558 * COLOR 7559 * 7560 * ===============================================================*/ 7561 NK_INTERN int 7562 nk_parse_hex(const char *p, int length) 7563 { 7564 int i = 0; 7565 int len = 0; 7566 while (len < length) { 7567 i <<= 4; 7568 if (p[len] >= 'a' && p[len] <= 'f') 7569 i += ((p[len] - 'a') + 10); 7570 else if (p[len] >= 'A' && p[len] <= 'F') 7571 i += ((p[len] - 'A') + 10); 7572 else i += (p[len] - '0'); 7573 len++; 7574 } 7575 return i; 7576 } 7577 NK_API struct nk_color 7578 nk_rgba(int r, int g, int b, int a) 7579 { 7580 struct nk_color ret; 7581 ret.r = (nk_byte)NK_CLAMP(0, r, 255); 7582 ret.g = (nk_byte)NK_CLAMP(0, g, 255); 7583 ret.b = (nk_byte)NK_CLAMP(0, b, 255); 7584 ret.a = (nk_byte)NK_CLAMP(0, a, 255); 7585 return ret; 7586 } 7587 NK_API struct nk_color 7588 nk_rgb_hex(const char *rgb) 7589 { 7590 struct nk_color col; 7591 const char *c = rgb; 7592 if (*c == '#') c++; 7593 col.r = (nk_byte)nk_parse_hex(c, 2); 7594 col.g = (nk_byte)nk_parse_hex(c+2, 2); 7595 col.b = (nk_byte)nk_parse_hex(c+4, 2); 7596 col.a = 255; 7597 return col; 7598 } 7599 NK_API struct nk_color 7600 nk_rgba_hex(const char *rgb) 7601 { 7602 struct nk_color col; 7603 const char *c = rgb; 7604 if (*c == '#') c++; 7605 col.r = (nk_byte)nk_parse_hex(c, 2); 7606 col.g = (nk_byte)nk_parse_hex(c+2, 2); 7607 col.b = (nk_byte)nk_parse_hex(c+4, 2); 7608 col.a = (nk_byte)nk_parse_hex(c+6, 2); 7609 return col; 7610 } 7611 NK_API void 7612 nk_color_hex_rgba(char *output, struct nk_color col) 7613 { 7614 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) 7615 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); 7616 output[1] = (char)NK_TO_HEX((col.r & 0x0F)); 7617 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); 7618 output[3] = (char)NK_TO_HEX((col.g & 0x0F)); 7619 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); 7620 output[5] = (char)NK_TO_HEX((col.b & 0x0F)); 7621 output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4); 7622 output[7] = (char)NK_TO_HEX((col.a & 0x0F)); 7623 output[8] = '\0'; 7624 #undef NK_TO_HEX 7625 } 7626 NK_API void 7627 nk_color_hex_rgb(char *output, struct nk_color col) 7628 { 7629 #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) 7630 output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); 7631 output[1] = (char)NK_TO_HEX((col.r & 0x0F)); 7632 output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); 7633 output[3] = (char)NK_TO_HEX((col.g & 0x0F)); 7634 output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); 7635 output[5] = (char)NK_TO_HEX((col.b & 0x0F)); 7636 output[6] = '\0'; 7637 #undef NK_TO_HEX 7638 } 7639 NK_API struct nk_color 7640 nk_rgba_iv(const int *c) 7641 { 7642 return nk_rgba(c[0], c[1], c[2], c[3]); 7643 } 7644 NK_API struct nk_color 7645 nk_rgba_bv(const nk_byte *c) 7646 { 7647 return nk_rgba(c[0], c[1], c[2], c[3]); 7648 } 7649 NK_API struct nk_color 7650 nk_rgb(int r, int g, int b) 7651 { 7652 struct nk_color ret; 7653 ret.r = (nk_byte)NK_CLAMP(0, r, 255); 7654 ret.g = (nk_byte)NK_CLAMP(0, g, 255); 7655 ret.b = (nk_byte)NK_CLAMP(0, b, 255); 7656 ret.a = (nk_byte)255; 7657 return ret; 7658 } 7659 NK_API struct nk_color 7660 nk_rgb_iv(const int *c) 7661 { 7662 return nk_rgb(c[0], c[1], c[2]); 7663 } 7664 NK_API struct nk_color 7665 nk_rgb_bv(const nk_byte* c) 7666 { 7667 return nk_rgb(c[0], c[1], c[2]); 7668 } 7669 NK_API struct nk_color 7670 nk_rgba_u32(nk_uint in) 7671 { 7672 struct nk_color ret; 7673 ret.r = (in & 0xFF); 7674 ret.g = ((in >> 8) & 0xFF); 7675 ret.b = ((in >> 16) & 0xFF); 7676 ret.a = (nk_byte)((in >> 24) & 0xFF); 7677 return ret; 7678 } 7679 NK_API struct nk_color 7680 nk_rgba_f(float r, float g, float b, float a) 7681 { 7682 struct nk_color ret; 7683 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); 7684 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); 7685 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); 7686 ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f); 7687 return ret; 7688 } 7689 NK_API struct nk_color 7690 nk_rgba_fv(const float *c) 7691 { 7692 return nk_rgba_f(c[0], c[1], c[2], c[3]); 7693 } 7694 NK_API struct nk_color 7695 nk_rgba_cf(struct nk_colorf c) 7696 { 7697 return nk_rgba_f(c.r, c.g, c.b, c.a); 7698 } 7699 NK_API struct nk_color 7700 nk_rgb_f(float r, float g, float b) 7701 { 7702 struct nk_color ret; 7703 ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); 7704 ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); 7705 ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); 7706 ret.a = 255; 7707 return ret; 7708 } 7709 NK_API struct nk_color 7710 nk_rgb_fv(const float *c) 7711 { 7712 return nk_rgb_f(c[0], c[1], c[2]); 7713 } 7714 NK_API struct nk_color 7715 nk_rgb_cf(struct nk_colorf c) 7716 { 7717 return nk_rgb_f(c.r, c.g, c.b); 7718 } 7719 NK_API struct nk_color 7720 nk_hsv(int h, int s, int v) 7721 { 7722 return nk_hsva(h, s, v, 255); 7723 } 7724 NK_API struct nk_color 7725 nk_hsv_iv(const int *c) 7726 { 7727 return nk_hsv(c[0], c[1], c[2]); 7728 } 7729 NK_API struct nk_color 7730 nk_hsv_bv(const nk_byte *c) 7731 { 7732 return nk_hsv(c[0], c[1], c[2]); 7733 } 7734 NK_API struct nk_color 7735 nk_hsv_f(float h, float s, float v) 7736 { 7737 return nk_hsva_f(h, s, v, 1.0f); 7738 } 7739 NK_API struct nk_color 7740 nk_hsv_fv(const float *c) 7741 { 7742 return nk_hsv_f(c[0], c[1], c[2]); 7743 } 7744 NK_API struct nk_color 7745 nk_hsva(int h, int s, int v, int a) 7746 { 7747 float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f; 7748 float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f; 7749 float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f; 7750 float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f; 7751 return nk_hsva_f(hf, sf, vf, af); 7752 } 7753 NK_API struct nk_color 7754 nk_hsva_iv(const int *c) 7755 { 7756 return nk_hsva(c[0], c[1], c[2], c[3]); 7757 } 7758 NK_API struct nk_color 7759 nk_hsva_bv(const nk_byte *c) 7760 { 7761 return nk_hsva(c[0], c[1], c[2], c[3]); 7762 } 7763 NK_API struct nk_colorf 7764 nk_hsva_colorf(float h, float s, float v, float a) 7765 { 7766 int i; 7767 float p, q, t, f; 7768 struct nk_colorf out = {0,0,0,0}; 7769 if (s <= 0.0f) { 7770 out.r = v; out.g = v; out.b = v; out.a = a; 7771 return out; 7772 } 7773 h = h / (60.0f/360.0f); 7774 i = (int)h; 7775 f = h - (float)i; 7776 p = v * (1.0f - s); 7777 q = v * (1.0f - (s * f)); 7778 t = v * (1.0f - s * (1.0f - f)); 7779 7780 switch (i) { 7781 case 0: default: out.r = v; out.g = t; out.b = p; break; 7782 case 1: out.r = q; out.g = v; out.b = p; break; 7783 case 2: out.r = p; out.g = v; out.b = t; break; 7784 case 3: out.r = p; out.g = q; out.b = v; break; 7785 case 4: out.r = t; out.g = p; out.b = v; break; 7786 case 5: out.r = v; out.g = p; out.b = q; break;} 7787 out.a = a; 7788 return out; 7789 } 7790 NK_API struct nk_colorf 7791 nk_hsva_colorfv(float *c) 7792 { 7793 return nk_hsva_colorf(c[0], c[1], c[2], c[3]); 7794 } 7795 NK_API struct nk_color 7796 nk_hsva_f(float h, float s, float v, float a) 7797 { 7798 struct nk_colorf c = nk_hsva_colorf(h, s, v, a); 7799 return nk_rgba_f(c.r, c.g, c.b, c.a); 7800 } 7801 NK_API struct nk_color 7802 nk_hsva_fv(const float *c) 7803 { 7804 return nk_hsva_f(c[0], c[1], c[2], c[3]); 7805 } 7806 NK_API nk_uint 7807 nk_color_u32(struct nk_color in) 7808 { 7809 nk_uint out = (nk_uint)in.r; 7810 out |= ((nk_uint)in.g << 8); 7811 out |= ((nk_uint)in.b << 16); 7812 out |= ((nk_uint)in.a << 24); 7813 return out; 7814 } 7815 NK_API void 7816 nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in) 7817 { 7818 NK_STORAGE const float s = 1.0f/255.0f; 7819 *r = (float)in.r * s; 7820 *g = (float)in.g * s; 7821 *b = (float)in.b * s; 7822 *a = (float)in.a * s; 7823 } 7824 NK_API void 7825 nk_color_fv(float *c, struct nk_color in) 7826 { 7827 nk_color_f(&c[0], &c[1], &c[2], &c[3], in); 7828 } 7829 NK_API struct nk_colorf 7830 nk_color_cf(struct nk_color in) 7831 { 7832 struct nk_colorf o; 7833 nk_color_f(&o.r, &o.g, &o.b, &o.a, in); 7834 return o; 7835 } 7836 NK_API void 7837 nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in) 7838 { 7839 NK_STORAGE const double s = 1.0/255.0; 7840 *r = (double)in.r * s; 7841 *g = (double)in.g * s; 7842 *b = (double)in.b * s; 7843 *a = (double)in.a * s; 7844 } 7845 NK_API void 7846 nk_color_dv(double *c, struct nk_color in) 7847 { 7848 nk_color_d(&c[0], &c[1], &c[2], &c[3], in); 7849 } 7850 NK_API void 7851 nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in) 7852 { 7853 float a; 7854 nk_color_hsva_f(out_h, out_s, out_v, &a, in); 7855 } 7856 NK_API void 7857 nk_color_hsv_fv(float *out, struct nk_color in) 7858 { 7859 float a; 7860 nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in); 7861 } 7862 NK_API void 7863 nk_colorf_hsva_f(float *out_h, float *out_s, 7864 float *out_v, float *out_a, struct nk_colorf in) 7865 { 7866 float chroma; 7867 float K = 0.0f; 7868 if (in.g < in.b) { 7869 const float t = in.g; in.g = in.b; in.b = t; 7870 K = -1.f; 7871 } 7872 if (in.r < in.g) { 7873 const float t = in.r; in.r = in.g; in.g = t; 7874 K = -2.f/6.0f - K; 7875 } 7876 chroma = in.r - ((in.g < in.b) ? in.g: in.b); 7877 *out_h = NK_ABS(K + (in.g - in.b)/(6.0f * chroma + 1e-20f)); 7878 *out_s = chroma / (in.r + 1e-20f); 7879 *out_v = in.r; 7880 *out_a = in.a; 7881 7882 } 7883 NK_API void 7884 nk_colorf_hsva_fv(float *hsva, struct nk_colorf in) 7885 { 7886 nk_colorf_hsva_f(&hsva[0], &hsva[1], &hsva[2], &hsva[3], in); 7887 } 7888 NK_API void 7889 nk_color_hsva_f(float *out_h, float *out_s, 7890 float *out_v, float *out_a, struct nk_color in) 7891 { 7892 struct nk_colorf col; 7893 nk_color_f(&col.r,&col.g,&col.b,&col.a, in); 7894 nk_colorf_hsva_f(out_h, out_s, out_v, out_a, col); 7895 } 7896 NK_API void 7897 nk_color_hsva_fv(float *out, struct nk_color in) 7898 { 7899 nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in); 7900 } 7901 NK_API void 7902 nk_color_hsva_i(int *out_h, int *out_s, int *out_v, 7903 int *out_a, struct nk_color in) 7904 { 7905 float h,s,v,a; 7906 nk_color_hsva_f(&h, &s, &v, &a, in); 7907 *out_h = (nk_byte)(h * 255.0f); 7908 *out_s = (nk_byte)(s * 255.0f); 7909 *out_v = (nk_byte)(v * 255.0f); 7910 *out_a = (nk_byte)(a * 255.0f); 7911 } 7912 NK_API void 7913 nk_color_hsva_iv(int *out, struct nk_color in) 7914 { 7915 nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in); 7916 } 7917 NK_API void 7918 nk_color_hsva_bv(nk_byte *out, struct nk_color in) 7919 { 7920 int tmp[4]; 7921 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7922 out[0] = (nk_byte)tmp[0]; 7923 out[1] = (nk_byte)tmp[1]; 7924 out[2] = (nk_byte)tmp[2]; 7925 out[3] = (nk_byte)tmp[3]; 7926 } 7927 NK_API void 7928 nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in) 7929 { 7930 int tmp[4]; 7931 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7932 *h = (nk_byte)tmp[0]; 7933 *s = (nk_byte)tmp[1]; 7934 *v = (nk_byte)tmp[2]; 7935 *a = (nk_byte)tmp[3]; 7936 } 7937 NK_API void 7938 nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in) 7939 { 7940 int a; 7941 nk_color_hsva_i(out_h, out_s, out_v, &a, in); 7942 } 7943 NK_API void 7944 nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in) 7945 { 7946 int tmp[4]; 7947 nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); 7948 *out_h = (nk_byte)tmp[0]; 7949 *out_s = (nk_byte)tmp[1]; 7950 *out_v = (nk_byte)tmp[2]; 7951 } 7952 NK_API void 7953 nk_color_hsv_iv(int *out, struct nk_color in) 7954 { 7955 nk_color_hsv_i(&out[0], &out[1], &out[2], in); 7956 } 7957 NK_API void 7958 nk_color_hsv_bv(nk_byte *out, struct nk_color in) 7959 { 7960 int tmp[4]; 7961 nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in); 7962 out[0] = (nk_byte)tmp[0]; 7963 out[1] = (nk_byte)tmp[1]; 7964 out[2] = (nk_byte)tmp[2]; 7965 } 7966 7967 7968 7969 7970 7971 /* =============================================================== 7972 * 7973 * UTF-8 7974 * 7975 * ===============================================================*/ 7976 NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; 7977 NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; 7978 NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000}; 7979 NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; 7980 7981 NK_INTERN int 7982 nk_utf_validate(nk_rune *u, int i) 7983 { 7984 NK_ASSERT(u); 7985 if (!u) return 0; 7986 if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) || 7987 NK_BETWEEN(*u, 0xD800, 0xDFFF)) 7988 *u = NK_UTF_INVALID; 7989 for (i = 1; *u > nk_utfmax[i]; ++i); 7990 return i; 7991 } 7992 NK_INTERN nk_rune 7993 nk_utf_decode_byte(char c, int *i) 7994 { 7995 NK_ASSERT(i); 7996 if (!i) return 0; 7997 for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) { 7998 if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i]) 7999 return (nk_byte)(c & ~nk_utfmask[*i]); 8000 } 8001 return 0; 8002 } 8003 NK_API int 8004 nk_utf_decode(const char *c, nk_rune *u, int clen) 8005 { 8006 int i, j, len, type=0; 8007 nk_rune udecoded; 8008 8009 NK_ASSERT(c); 8010 NK_ASSERT(u); 8011 8012 if (!c || !u) return 0; 8013 if (!clen) return 0; 8014 *u = NK_UTF_INVALID; 8015 8016 udecoded = nk_utf_decode_byte(c[0], &len); 8017 if (!NK_BETWEEN(len, 1, NK_UTF_SIZE)) 8018 return 1; 8019 8020 for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { 8021 udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type); 8022 if (type != 0) 8023 return j; 8024 } 8025 if (j < len) 8026 return 0; 8027 *u = udecoded; 8028 nk_utf_validate(u, len); 8029 return len; 8030 } 8031 NK_INTERN char 8032 nk_utf_encode_byte(nk_rune u, int i) 8033 { 8034 return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i])); 8035 } 8036 NK_API int 8037 nk_utf_encode(nk_rune u, char *c, int clen) 8038 { 8039 int len, i; 8040 len = nk_utf_validate(&u, 0); 8041 if (clen < len || !len || len > NK_UTF_SIZE) 8042 return 0; 8043 8044 for (i = len - 1; i != 0; --i) { 8045 c[i] = nk_utf_encode_byte(u, 0); 8046 u >>= 6; 8047 } 8048 c[0] = nk_utf_encode_byte(u, len); 8049 return len; 8050 } 8051 NK_API int 8052 nk_utf_len(const char *str, int len) 8053 { 8054 const char *text; 8055 int glyphs = 0; 8056 int text_len; 8057 int glyph_len; 8058 int src_len = 0; 8059 nk_rune unicode; 8060 8061 NK_ASSERT(str); 8062 if (!str || !len) return 0; 8063 8064 text = str; 8065 text_len = len; 8066 glyph_len = nk_utf_decode(text, &unicode, text_len); 8067 while (glyph_len && src_len < len) { 8068 glyphs++; 8069 src_len = src_len + glyph_len; 8070 glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len); 8071 } 8072 return glyphs; 8073 } 8074 NK_API const char* 8075 nk_utf_at(const char *buffer, int length, int index, 8076 nk_rune *unicode, int *len) 8077 { 8078 int i = 0; 8079 int src_len = 0; 8080 int glyph_len = 0; 8081 const char *text; 8082 int text_len; 8083 8084 NK_ASSERT(buffer); 8085 NK_ASSERT(unicode); 8086 NK_ASSERT(len); 8087 8088 if (!buffer || !unicode || !len) return 0; 8089 if (index < 0) { 8090 *unicode = NK_UTF_INVALID; 8091 *len = 0; 8092 return 0; 8093 } 8094 8095 text = buffer; 8096 text_len = length; 8097 glyph_len = nk_utf_decode(text, unicode, text_len); 8098 while (glyph_len) { 8099 if (i == index) { 8100 *len = glyph_len; 8101 break; 8102 } 8103 8104 i++; 8105 src_len = src_len + glyph_len; 8106 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 8107 } 8108 if (i != index) return 0; 8109 return buffer + src_len; 8110 } 8111 8112 8113 8114 8115 8116 /* ============================================================== 8117 * 8118 * BUFFER 8119 * 8120 * ===============================================================*/ 8121 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 8122 NK_LIB void* 8123 nk_malloc(nk_handle unused, void *old,nk_size size) 8124 { 8125 NK_UNUSED(unused); 8126 NK_UNUSED(old); 8127 return malloc(size); 8128 } 8129 NK_LIB void 8130 nk_mfree(nk_handle unused, void *ptr) 8131 { 8132 NK_UNUSED(unused); 8133 free(ptr); 8134 } 8135 NK_API void 8136 nk_buffer_init_default(struct nk_buffer *buffer) 8137 { 8138 struct nk_allocator alloc; 8139 alloc.userdata.ptr = 0; 8140 alloc.alloc = nk_malloc; 8141 alloc.free = nk_mfree; 8142 nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE); 8143 } 8144 #endif 8145 8146 NK_API void 8147 nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a, 8148 nk_size initial_size) 8149 { 8150 NK_ASSERT(b); 8151 NK_ASSERT(a); 8152 NK_ASSERT(initial_size); 8153 if (!b || !a || !initial_size) return; 8154 8155 nk_zero(b, sizeof(*b)); 8156 b->type = NK_BUFFER_DYNAMIC; 8157 b->memory.ptr = a->alloc(a->userdata,0, initial_size); 8158 b->memory.size = initial_size; 8159 b->size = initial_size; 8160 b->grow_factor = 2.0f; 8161 b->pool = *a; 8162 } 8163 NK_API void 8164 nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size) 8165 { 8166 NK_ASSERT(b); 8167 NK_ASSERT(m); 8168 NK_ASSERT(size); 8169 if (!b || !m || !size) return; 8170 8171 nk_zero(b, sizeof(*b)); 8172 b->type = NK_BUFFER_FIXED; 8173 b->memory.ptr = m; 8174 b->memory.size = size; 8175 b->size = size; 8176 } 8177 NK_LIB void* 8178 nk_buffer_align(void *unaligned, 8179 nk_size align, nk_size *alignment, 8180 enum nk_buffer_allocation_type type) 8181 { 8182 void *memory = 0; 8183 switch (type) { 8184 default: 8185 case NK_BUFFER_MAX: 8186 case NK_BUFFER_FRONT: 8187 if (align) { 8188 memory = NK_ALIGN_PTR(unaligned, align); 8189 *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); 8190 } else { 8191 memory = unaligned; 8192 *alignment = 0; 8193 } 8194 break; 8195 case NK_BUFFER_BACK: 8196 if (align) { 8197 memory = NK_ALIGN_PTR_BACK(unaligned, align); 8198 *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory); 8199 } else { 8200 memory = unaligned; 8201 *alignment = 0; 8202 } 8203 break; 8204 } 8205 return memory; 8206 } 8207 NK_LIB void* 8208 nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size) 8209 { 8210 void *temp; 8211 nk_size buffer_size; 8212 8213 NK_ASSERT(b); 8214 NK_ASSERT(size); 8215 if (!b || !size || !b->pool.alloc || !b->pool.free) 8216 return 0; 8217 8218 buffer_size = b->memory.size; 8219 temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity); 8220 NK_ASSERT(temp); 8221 if (!temp) return 0; 8222 8223 *size = capacity; 8224 if (temp != b->memory.ptr) { 8225 NK_MEMCPY(temp, b->memory.ptr, buffer_size); 8226 b->pool.free(b->pool.userdata, b->memory.ptr); 8227 } 8228 8229 if (b->size == buffer_size) { 8230 /* no back buffer so just set correct size */ 8231 b->size = capacity; 8232 return temp; 8233 } else { 8234 /* copy back buffer to the end of the new buffer */ 8235 void *dst, *src; 8236 nk_size back_size; 8237 back_size = buffer_size - b->size; 8238 dst = nk_ptr_add(void, temp, capacity - back_size); 8239 src = nk_ptr_add(void, temp, b->size); 8240 NK_MEMCPY(dst, src, back_size); 8241 b->size = capacity - back_size; 8242 } 8243 return temp; 8244 } 8245 NK_LIB void* 8246 nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, 8247 nk_size size, nk_size align) 8248 { 8249 int full; 8250 nk_size alignment; 8251 void *unaligned; 8252 void *memory; 8253 8254 NK_ASSERT(b); 8255 NK_ASSERT(size); 8256 if (!b || !size) return 0; 8257 b->needed += size; 8258 8259 /* calculate total size with needed alignment + size */ 8260 if (type == NK_BUFFER_FRONT) 8261 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); 8262 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); 8263 memory = nk_buffer_align(unaligned, align, &alignment, type); 8264 8265 /* check if buffer has enough memory*/ 8266 if (type == NK_BUFFER_FRONT) 8267 full = ((b->allocated + size + alignment) > b->size); 8268 else full = ((b->size - NK_MIN(b->size,(size + alignment))) <= b->allocated); 8269 8270 if (full) { 8271 nk_size capacity; 8272 if (b->type != NK_BUFFER_DYNAMIC) 8273 return 0; 8274 NK_ASSERT(b->pool.alloc && b->pool.free); 8275 if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free) 8276 return 0; 8277 8278 /* buffer is full so allocate bigger buffer if dynamic */ 8279 capacity = (nk_size)((float)b->memory.size * b->grow_factor); 8280 capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size))); 8281 b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size); 8282 if (!b->memory.ptr) return 0; 8283 8284 /* align newly allocated pointer */ 8285 if (type == NK_BUFFER_FRONT) 8286 unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); 8287 else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); 8288 memory = nk_buffer_align(unaligned, align, &alignment, type); 8289 } 8290 if (type == NK_BUFFER_FRONT) 8291 b->allocated += size + alignment; 8292 else b->size -= (size + alignment); 8293 b->needed += alignment; 8294 b->calls++; 8295 return memory; 8296 } 8297 NK_API void 8298 nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type, 8299 const void *memory, nk_size size, nk_size align) 8300 { 8301 void *mem = nk_buffer_alloc(b, type, size, align); 8302 if (!mem) return; 8303 NK_MEMCPY(mem, memory, size); 8304 } 8305 NK_API void 8306 nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) 8307 { 8308 NK_ASSERT(buffer); 8309 if (!buffer) return; 8310 buffer->marker[type].active = nk_true; 8311 if (type == NK_BUFFER_BACK) 8312 buffer->marker[type].offset = buffer->size; 8313 else buffer->marker[type].offset = buffer->allocated; 8314 } 8315 NK_API void 8316 nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) 8317 { 8318 NK_ASSERT(buffer); 8319 if (!buffer) return; 8320 if (type == NK_BUFFER_BACK) { 8321 /* reset back buffer either back to marker or empty */ 8322 buffer->needed -= (buffer->memory.size - buffer->marker[type].offset); 8323 if (buffer->marker[type].active) 8324 buffer->size = buffer->marker[type].offset; 8325 else buffer->size = buffer->memory.size; 8326 buffer->marker[type].active = nk_false; 8327 } else { 8328 /* reset front buffer either back to back marker or empty */ 8329 buffer->needed -= (buffer->allocated - buffer->marker[type].offset); 8330 if (buffer->marker[type].active) 8331 buffer->allocated = buffer->marker[type].offset; 8332 else buffer->allocated = 0; 8333 buffer->marker[type].active = nk_false; 8334 } 8335 } 8336 NK_API void 8337 nk_buffer_clear(struct nk_buffer *b) 8338 { 8339 NK_ASSERT(b); 8340 if (!b) return; 8341 b->allocated = 0; 8342 b->size = b->memory.size; 8343 b->calls = 0; 8344 b->needed = 0; 8345 } 8346 NK_API void 8347 nk_buffer_free(struct nk_buffer *b) 8348 { 8349 NK_ASSERT(b); 8350 if (!b || !b->memory.ptr) return; 8351 if (b->type == NK_BUFFER_FIXED) return; 8352 if (!b->pool.free) return; 8353 NK_ASSERT(b->pool.free); 8354 b->pool.free(b->pool.userdata, b->memory.ptr); 8355 } 8356 NK_API void 8357 nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b) 8358 { 8359 NK_ASSERT(b); 8360 NK_ASSERT(s); 8361 if (!s || !b) return; 8362 s->allocated = b->allocated; 8363 s->size = b->memory.size; 8364 s->needed = b->needed; 8365 s->memory = b->memory.ptr; 8366 s->calls = b->calls; 8367 } 8368 NK_API void* 8369 nk_buffer_memory(struct nk_buffer *buffer) 8370 { 8371 NK_ASSERT(buffer); 8372 if (!buffer) return 0; 8373 return buffer->memory.ptr; 8374 } 8375 NK_API const void* 8376 nk_buffer_memory_const(const struct nk_buffer *buffer) 8377 { 8378 NK_ASSERT(buffer); 8379 if (!buffer) return 0; 8380 return buffer->memory.ptr; 8381 } 8382 NK_API nk_size 8383 nk_buffer_total(struct nk_buffer *buffer) 8384 { 8385 NK_ASSERT(buffer); 8386 if (!buffer) return 0; 8387 return buffer->memory.size; 8388 } 8389 8390 8391 8392 8393 8394 /* =============================================================== 8395 * 8396 * STRING 8397 * 8398 * ===============================================================*/ 8399 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 8400 NK_API void 8401 nk_str_init_default(struct nk_str *str) 8402 { 8403 struct nk_allocator alloc; 8404 alloc.userdata.ptr = 0; 8405 alloc.alloc = nk_malloc; 8406 alloc.free = nk_mfree; 8407 nk_buffer_init(&str->buffer, &alloc, 32); 8408 str->len = 0; 8409 } 8410 #endif 8411 8412 NK_API void 8413 nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size) 8414 { 8415 nk_buffer_init(&str->buffer, alloc, size); 8416 str->len = 0; 8417 } 8418 NK_API void 8419 nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size) 8420 { 8421 nk_buffer_init_fixed(&str->buffer, memory, size); 8422 str->len = 0; 8423 } 8424 NK_API int 8425 nk_str_append_text_char(struct nk_str *s, const char *str, int len) 8426 { 8427 char *mem; 8428 NK_ASSERT(s); 8429 NK_ASSERT(str); 8430 if (!s || !str || !len) return 0; 8431 mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); 8432 if (!mem) return 0; 8433 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); 8434 s->len += nk_utf_len(str, len); 8435 return len; 8436 } 8437 NK_API int 8438 nk_str_append_str_char(struct nk_str *s, const char *str) 8439 { 8440 return nk_str_append_text_char(s, str, nk_strlen(str)); 8441 } 8442 NK_API int 8443 nk_str_append_text_utf8(struct nk_str *str, const char *text, int len) 8444 { 8445 int i = 0; 8446 int byte_len = 0; 8447 nk_rune unicode; 8448 if (!str || !text || !len) return 0; 8449 for (i = 0; i < len; ++i) 8450 byte_len += nk_utf_decode(text+byte_len, &unicode, 4); 8451 nk_str_append_text_char(str, text, byte_len); 8452 return len; 8453 } 8454 NK_API int 8455 nk_str_append_str_utf8(struct nk_str *str, const char *text) 8456 { 8457 int byte_len = 0; 8458 int num_runes = 0; 8459 int glyph_len = 0; 8460 nk_rune unicode; 8461 if (!str || !text) return 0; 8462 8463 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); 8464 while (unicode != '\0' && glyph_len) { 8465 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); 8466 byte_len += glyph_len; 8467 num_runes++; 8468 } 8469 nk_str_append_text_char(str, text, byte_len); 8470 return num_runes; 8471 } 8472 NK_API int 8473 nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len) 8474 { 8475 int i = 0; 8476 int byte_len = 0; 8477 nk_glyph glyph; 8478 8479 NK_ASSERT(str); 8480 if (!str || !text || !len) return 0; 8481 for (i = 0; i < len; ++i) { 8482 byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE); 8483 if (!byte_len) break; 8484 nk_str_append_text_char(str, glyph, byte_len); 8485 } 8486 return len; 8487 } 8488 NK_API int 8489 nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes) 8490 { 8491 int i = 0; 8492 nk_glyph glyph; 8493 int byte_len; 8494 NK_ASSERT(str); 8495 if (!str || !runes) return 0; 8496 while (runes[i] != '\0') { 8497 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8498 nk_str_append_text_char(str, glyph, byte_len); 8499 i++; 8500 } 8501 return i; 8502 } 8503 NK_API int 8504 nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len) 8505 { 8506 int i; 8507 void *mem; 8508 char *src; 8509 char *dst; 8510 8511 int copylen; 8512 NK_ASSERT(s); 8513 NK_ASSERT(str); 8514 NK_ASSERT(len >= 0); 8515 if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0; 8516 if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) && 8517 (s->buffer.type == NK_BUFFER_FIXED)) return 0; 8518 8519 copylen = (int)s->buffer.allocated - pos; 8520 if (!copylen) { 8521 nk_str_append_text_char(s, str, len); 8522 return 1; 8523 } 8524 mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); 8525 if (!mem) return 0; 8526 8527 /* memmove */ 8528 NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0); 8529 NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0); 8530 dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1)); 8531 src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1)); 8532 for (i = 0; i < copylen; ++i) *dst-- = *src--; 8533 mem = nk_ptr_add(void, s->buffer.memory.ptr, pos); 8534 NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); 8535 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8536 return 1; 8537 } 8538 NK_API int 8539 nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len) 8540 { 8541 int glyph_len; 8542 nk_rune unicode; 8543 const char *begin; 8544 const char *buffer; 8545 8546 NK_ASSERT(str); 8547 NK_ASSERT(cstr); 8548 NK_ASSERT(len); 8549 if (!str || !cstr || !len) return 0; 8550 begin = nk_str_at_rune(str, pos, &unicode, &glyph_len); 8551 if (!str->len) 8552 return nk_str_append_text_char(str, cstr, len); 8553 buffer = nk_str_get_const(str); 8554 if (!begin) return 0; 8555 return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len); 8556 } 8557 NK_API int 8558 nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len) 8559 { 8560 return nk_str_insert_text_utf8(str, pos, text, len); 8561 } 8562 NK_API int 8563 nk_str_insert_str_char(struct nk_str *str, int pos, const char *text) 8564 { 8565 return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text)); 8566 } 8567 NK_API int 8568 nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len) 8569 { 8570 int i = 0; 8571 int byte_len = 0; 8572 nk_rune unicode; 8573 8574 NK_ASSERT(str); 8575 NK_ASSERT(text); 8576 if (!str || !text || !len) return 0; 8577 for (i = 0; i < len; ++i) 8578 byte_len += nk_utf_decode(text+byte_len, &unicode, 4); 8579 nk_str_insert_at_rune(str, pos, text, byte_len); 8580 return len; 8581 } 8582 NK_API int 8583 nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text) 8584 { 8585 int byte_len = 0; 8586 int num_runes = 0; 8587 int glyph_len = 0; 8588 nk_rune unicode; 8589 if (!str || !text) return 0; 8590 8591 glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); 8592 while (unicode != '\0' && glyph_len) { 8593 glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); 8594 byte_len += glyph_len; 8595 num_runes++; 8596 } 8597 nk_str_insert_at_rune(str, pos, text, byte_len); 8598 return num_runes; 8599 } 8600 NK_API int 8601 nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len) 8602 { 8603 int i = 0; 8604 int byte_len = 0; 8605 nk_glyph glyph; 8606 8607 NK_ASSERT(str); 8608 if (!str || !runes || !len) return 0; 8609 for (i = 0; i < len; ++i) { 8610 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8611 if (!byte_len) break; 8612 nk_str_insert_at_rune(str, pos+i, glyph, byte_len); 8613 } 8614 return len; 8615 } 8616 NK_API int 8617 nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes) 8618 { 8619 int i = 0; 8620 nk_glyph glyph; 8621 int byte_len; 8622 NK_ASSERT(str); 8623 if (!str || !runes) return 0; 8624 while (runes[i] != '\0') { 8625 byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); 8626 nk_str_insert_at_rune(str, pos+i, glyph, byte_len); 8627 i++; 8628 } 8629 return i; 8630 } 8631 NK_API void 8632 nk_str_remove_chars(struct nk_str *s, int len) 8633 { 8634 NK_ASSERT(s); 8635 NK_ASSERT(len >= 0); 8636 if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return; 8637 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); 8638 s->buffer.allocated -= (nk_size)len; 8639 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8640 } 8641 NK_API void 8642 nk_str_remove_runes(struct nk_str *str, int len) 8643 { 8644 int index; 8645 const char *begin; 8646 const char *end; 8647 nk_rune unicode; 8648 8649 NK_ASSERT(str); 8650 NK_ASSERT(len >= 0); 8651 if (!str || len < 0) return; 8652 if (len >= str->len) { 8653 str->len = 0; 8654 return; 8655 } 8656 8657 index = str->len - len; 8658 begin = nk_str_at_rune(str, index, &unicode, &len); 8659 end = (const char*)str->buffer.memory.ptr + str->buffer.allocated; 8660 nk_str_remove_chars(str, (int)(end-begin)+1); 8661 } 8662 NK_API void 8663 nk_str_delete_chars(struct nk_str *s, int pos, int len) 8664 { 8665 NK_ASSERT(s); 8666 if (!s || !len || (nk_size)pos > s->buffer.allocated || 8667 (nk_size)(pos + len) > s->buffer.allocated) return; 8668 8669 if ((nk_size)(pos + len) < s->buffer.allocated) { 8670 /* memmove */ 8671 char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos); 8672 char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len); 8673 NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len)); 8674 NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); 8675 s->buffer.allocated -= (nk_size)len; 8676 } else nk_str_remove_chars(s, len); 8677 s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); 8678 } 8679 NK_API void 8680 nk_str_delete_runes(struct nk_str *s, int pos, int len) 8681 { 8682 char *temp; 8683 nk_rune unicode; 8684 char *begin; 8685 char *end; 8686 int unused; 8687 8688 NK_ASSERT(s); 8689 NK_ASSERT(s->len >= pos + len); 8690 if (s->len < pos + len) 8691 len = NK_CLAMP(0, (s->len - pos), s->len); 8692 if (!len) return; 8693 8694 temp = (char *)s->buffer.memory.ptr; 8695 begin = nk_str_at_rune(s, pos, &unicode, &unused); 8696 if (!begin) return; 8697 s->buffer.memory.ptr = begin; 8698 end = nk_str_at_rune(s, len, &unicode, &unused); 8699 s->buffer.memory.ptr = temp; 8700 if (!end) return; 8701 nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin)); 8702 } 8703 NK_API char* 8704 nk_str_at_char(struct nk_str *s, int pos) 8705 { 8706 NK_ASSERT(s); 8707 if (!s || pos > (int)s->buffer.allocated) return 0; 8708 return nk_ptr_add(char, s->buffer.memory.ptr, pos); 8709 } 8710 NK_API char* 8711 nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len) 8712 { 8713 int i = 0; 8714 int src_len = 0; 8715 int glyph_len = 0; 8716 char *text; 8717 int text_len; 8718 8719 NK_ASSERT(str); 8720 NK_ASSERT(unicode); 8721 NK_ASSERT(len); 8722 8723 if (!str || !unicode || !len) return 0; 8724 if (pos < 0) { 8725 *unicode = 0; 8726 *len = 0; 8727 return 0; 8728 } 8729 8730 text = (char*)str->buffer.memory.ptr; 8731 text_len = (int)str->buffer.allocated; 8732 glyph_len = nk_utf_decode(text, unicode, text_len); 8733 while (glyph_len) { 8734 if (i == pos) { 8735 *len = glyph_len; 8736 break; 8737 } 8738 8739 i++; 8740 src_len = src_len + glyph_len; 8741 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 8742 } 8743 if (i != pos) return 0; 8744 return text + src_len; 8745 } 8746 NK_API const char* 8747 nk_str_at_char_const(const struct nk_str *s, int pos) 8748 { 8749 NK_ASSERT(s); 8750 if (!s || pos > (int)s->buffer.allocated) return 0; 8751 return nk_ptr_add(char, s->buffer.memory.ptr, pos); 8752 } 8753 NK_API const char* 8754 nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len) 8755 { 8756 int i = 0; 8757 int src_len = 0; 8758 int glyph_len = 0; 8759 char *text; 8760 int text_len; 8761 8762 NK_ASSERT(str); 8763 NK_ASSERT(unicode); 8764 NK_ASSERT(len); 8765 8766 if (!str || !unicode || !len) return 0; 8767 if (pos < 0) { 8768 *unicode = 0; 8769 *len = 0; 8770 return 0; 8771 } 8772 8773 text = (char*)str->buffer.memory.ptr; 8774 text_len = (int)str->buffer.allocated; 8775 glyph_len = nk_utf_decode(text, unicode, text_len); 8776 while (glyph_len) { 8777 if (i == pos) { 8778 *len = glyph_len; 8779 break; 8780 } 8781 8782 i++; 8783 src_len = src_len + glyph_len; 8784 glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); 8785 } 8786 if (i != pos) return 0; 8787 return text + src_len; 8788 } 8789 NK_API nk_rune 8790 nk_str_rune_at(const struct nk_str *str, int pos) 8791 { 8792 int len; 8793 nk_rune unicode = 0; 8794 nk_str_at_const(str, pos, &unicode, &len); 8795 return unicode; 8796 } 8797 NK_API char* 8798 nk_str_get(struct nk_str *s) 8799 { 8800 NK_ASSERT(s); 8801 if (!s || !s->len || !s->buffer.allocated) return 0; 8802 return (char*)s->buffer.memory.ptr; 8803 } 8804 NK_API const char* 8805 nk_str_get_const(const struct nk_str *s) 8806 { 8807 NK_ASSERT(s); 8808 if (!s || !s->len || !s->buffer.allocated) return 0; 8809 return (const char*)s->buffer.memory.ptr; 8810 } 8811 NK_API int 8812 nk_str_len(struct nk_str *s) 8813 { 8814 NK_ASSERT(s); 8815 if (!s || !s->len || !s->buffer.allocated) return 0; 8816 return s->len; 8817 } 8818 NK_API int 8819 nk_str_len_char(struct nk_str *s) 8820 { 8821 NK_ASSERT(s); 8822 if (!s || !s->len || !s->buffer.allocated) return 0; 8823 return (int)s->buffer.allocated; 8824 } 8825 NK_API void 8826 nk_str_clear(struct nk_str *str) 8827 { 8828 NK_ASSERT(str); 8829 nk_buffer_clear(&str->buffer); 8830 str->len = 0; 8831 } 8832 NK_API void 8833 nk_str_free(struct nk_str *str) 8834 { 8835 NK_ASSERT(str); 8836 nk_buffer_free(&str->buffer); 8837 str->len = 0; 8838 } 8839 8840 8841 8842 8843 8844 /* ============================================================== 8845 * 8846 * DRAW 8847 * 8848 * ===============================================================*/ 8849 NK_LIB void 8850 nk_command_buffer_init(struct nk_command_buffer *cb, 8851 struct nk_buffer *b, enum nk_command_clipping clip) 8852 { 8853 NK_ASSERT(cb); 8854 NK_ASSERT(b); 8855 if (!cb || !b) return; 8856 cb->base = b; 8857 cb->use_clipping = (int)clip; 8858 cb->begin = b->allocated; 8859 cb->end = b->allocated; 8860 cb->last = b->allocated; 8861 } 8862 NK_LIB void 8863 nk_command_buffer_reset(struct nk_command_buffer *b) 8864 { 8865 NK_ASSERT(b); 8866 if (!b) return; 8867 b->begin = 0; 8868 b->end = 0; 8869 b->last = 0; 8870 b->clip = nk_null_rect; 8871 #ifdef NK_INCLUDE_COMMAND_USERDATA 8872 b->userdata.ptr = 0; 8873 #endif 8874 } 8875 NK_LIB void* 8876 nk_command_buffer_push(struct nk_command_buffer* b, 8877 enum nk_command_type t, nk_size size) 8878 { 8879 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command); 8880 struct nk_command *cmd; 8881 nk_size alignment; 8882 void *unaligned; 8883 void *memory; 8884 8885 NK_ASSERT(b); 8886 NK_ASSERT(b->base); 8887 if (!b) return 0; 8888 cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align); 8889 if (!cmd) return 0; 8890 8891 /* make sure the offset to the next command is aligned */ 8892 b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr); 8893 unaligned = (nk_byte*)cmd + size; 8894 memory = NK_ALIGN_PTR(unaligned, align); 8895 alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); 8896 #ifdef NK_ZERO_COMMAND_MEMORY 8897 NK_MEMSET(cmd, 0, size + alignment); 8898 #endif 8899 8900 cmd->type = t; 8901 cmd->next = b->base->allocated + alignment; 8902 #ifdef NK_INCLUDE_COMMAND_USERDATA 8903 cmd->userdata = b->userdata; 8904 #endif 8905 b->end = cmd->next; 8906 return cmd; 8907 } 8908 NK_API void 8909 nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r) 8910 { 8911 struct nk_command_scissor *cmd; 8912 NK_ASSERT(b); 8913 if (!b) return; 8914 8915 b->clip.x = r.x; 8916 b->clip.y = r.y; 8917 b->clip.w = r.w; 8918 b->clip.h = r.h; 8919 cmd = (struct nk_command_scissor*) 8920 nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd)); 8921 8922 if (!cmd) return; 8923 cmd->x = (short)r.x; 8924 cmd->y = (short)r.y; 8925 cmd->w = (unsigned short)NK_MAX(0, r.w); 8926 cmd->h = (unsigned short)NK_MAX(0, r.h); 8927 } 8928 NK_API void 8929 nk_stroke_line(struct nk_command_buffer *b, float x0, float y0, 8930 float x1, float y1, float line_thickness, struct nk_color c) 8931 { 8932 struct nk_command_line *cmd; 8933 NK_ASSERT(b); 8934 if (!b || line_thickness <= 0) return; 8935 cmd = (struct nk_command_line*) 8936 nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd)); 8937 if (!cmd) return; 8938 cmd->line_thickness = (unsigned short)line_thickness; 8939 cmd->begin.x = (short)x0; 8940 cmd->begin.y = (short)y0; 8941 cmd->end.x = (short)x1; 8942 cmd->end.y = (short)y1; 8943 cmd->color = c; 8944 } 8945 NK_API void 8946 nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay, 8947 float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y, 8948 float bx, float by, float line_thickness, struct nk_color col) 8949 { 8950 struct nk_command_curve *cmd; 8951 NK_ASSERT(b); 8952 if (!b || col.a == 0 || line_thickness <= 0) return; 8953 8954 cmd = (struct nk_command_curve*) 8955 nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd)); 8956 if (!cmd) return; 8957 cmd->line_thickness = (unsigned short)line_thickness; 8958 cmd->begin.x = (short)ax; 8959 cmd->begin.y = (short)ay; 8960 cmd->ctrl[0].x = (short)ctrl0x; 8961 cmd->ctrl[0].y = (short)ctrl0y; 8962 cmd->ctrl[1].x = (short)ctrl1x; 8963 cmd->ctrl[1].y = (short)ctrl1y; 8964 cmd->end.x = (short)bx; 8965 cmd->end.y = (short)by; 8966 cmd->color = col; 8967 } 8968 NK_API void 8969 nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect, 8970 float rounding, float line_thickness, struct nk_color c) 8971 { 8972 struct nk_command_rect *cmd; 8973 NK_ASSERT(b); 8974 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0 || line_thickness <= 0) return; 8975 if (b->use_clipping) { 8976 const struct nk_rect *clip = &b->clip; 8977 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 8978 clip->x, clip->y, clip->w, clip->h)) return; 8979 } 8980 cmd = (struct nk_command_rect*) 8981 nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd)); 8982 if (!cmd) return; 8983 cmd->rounding = (unsigned short)rounding; 8984 cmd->line_thickness = (unsigned short)line_thickness; 8985 cmd->x = (short)rect.x; 8986 cmd->y = (short)rect.y; 8987 cmd->w = (unsigned short)NK_MAX(0, rect.w); 8988 cmd->h = (unsigned short)NK_MAX(0, rect.h); 8989 cmd->color = c; 8990 } 8991 NK_API void 8992 nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect, 8993 float rounding, struct nk_color c) 8994 { 8995 struct nk_command_rect_filled *cmd; 8996 NK_ASSERT(b); 8997 if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return; 8998 if (b->use_clipping) { 8999 const struct nk_rect *clip = &b->clip; 9000 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 9001 clip->x, clip->y, clip->w, clip->h)) return; 9002 } 9003 9004 cmd = (struct nk_command_rect_filled*) 9005 nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd)); 9006 if (!cmd) return; 9007 cmd->rounding = (unsigned short)rounding; 9008 cmd->x = (short)rect.x; 9009 cmd->y = (short)rect.y; 9010 cmd->w = (unsigned short)NK_MAX(0, rect.w); 9011 cmd->h = (unsigned short)NK_MAX(0, rect.h); 9012 cmd->color = c; 9013 } 9014 NK_API void 9015 nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect, 9016 struct nk_color left, struct nk_color top, struct nk_color right, 9017 struct nk_color bottom) 9018 { 9019 struct nk_command_rect_multi_color *cmd; 9020 NK_ASSERT(b); 9021 if (!b || rect.w == 0 || rect.h == 0) return; 9022 if (b->use_clipping) { 9023 const struct nk_rect *clip = &b->clip; 9024 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 9025 clip->x, clip->y, clip->w, clip->h)) return; 9026 } 9027 9028 cmd = (struct nk_command_rect_multi_color*) 9029 nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd)); 9030 if (!cmd) return; 9031 cmd->x = (short)rect.x; 9032 cmd->y = (short)rect.y; 9033 cmd->w = (unsigned short)NK_MAX(0, rect.w); 9034 cmd->h = (unsigned short)NK_MAX(0, rect.h); 9035 cmd->left = left; 9036 cmd->top = top; 9037 cmd->right = right; 9038 cmd->bottom = bottom; 9039 } 9040 NK_API void 9041 nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r, 9042 float line_thickness, struct nk_color c) 9043 { 9044 struct nk_command_circle *cmd; 9045 if (!b || r.w == 0 || r.h == 0 || line_thickness <= 0) return; 9046 if (b->use_clipping) { 9047 const struct nk_rect *clip = &b->clip; 9048 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) 9049 return; 9050 } 9051 9052 cmd = (struct nk_command_circle*) 9053 nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd)); 9054 if (!cmd) return; 9055 cmd->line_thickness = (unsigned short)line_thickness; 9056 cmd->x = (short)r.x; 9057 cmd->y = (short)r.y; 9058 cmd->w = (unsigned short)NK_MAX(r.w, 0); 9059 cmd->h = (unsigned short)NK_MAX(r.h, 0); 9060 cmd->color = c; 9061 } 9062 NK_API void 9063 nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c) 9064 { 9065 struct nk_command_circle_filled *cmd; 9066 NK_ASSERT(b); 9067 if (!b || c.a == 0 || r.w == 0 || r.h == 0) return; 9068 if (b->use_clipping) { 9069 const struct nk_rect *clip = &b->clip; 9070 if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) 9071 return; 9072 } 9073 9074 cmd = (struct nk_command_circle_filled*) 9075 nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd)); 9076 if (!cmd) return; 9077 cmd->x = (short)r.x; 9078 cmd->y = (short)r.y; 9079 cmd->w = (unsigned short)NK_MAX(r.w, 0); 9080 cmd->h = (unsigned short)NK_MAX(r.h, 0); 9081 cmd->color = c; 9082 } 9083 NK_API void 9084 nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius, 9085 float a_min, float a_max, float line_thickness, struct nk_color c) 9086 { 9087 struct nk_command_arc *cmd; 9088 if (!b || c.a == 0 || line_thickness <= 0) return; 9089 cmd = (struct nk_command_arc*) 9090 nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd)); 9091 if (!cmd) return; 9092 cmd->line_thickness = (unsigned short)line_thickness; 9093 cmd->cx = (short)cx; 9094 cmd->cy = (short)cy; 9095 cmd->r = (unsigned short)radius; 9096 cmd->a[0] = a_min; 9097 cmd->a[1] = a_max; 9098 cmd->color = c; 9099 } 9100 NK_API void 9101 nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius, 9102 float a_min, float a_max, struct nk_color c) 9103 { 9104 struct nk_command_arc_filled *cmd; 9105 NK_ASSERT(b); 9106 if (!b || c.a == 0) return; 9107 cmd = (struct nk_command_arc_filled*) 9108 nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd)); 9109 if (!cmd) return; 9110 cmd->cx = (short)cx; 9111 cmd->cy = (short)cy; 9112 cmd->r = (unsigned short)radius; 9113 cmd->a[0] = a_min; 9114 cmd->a[1] = a_max; 9115 cmd->color = c; 9116 } 9117 NK_API void 9118 nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, 9119 float y1, float x2, float y2, float line_thickness, struct nk_color c) 9120 { 9121 struct nk_command_triangle *cmd; 9122 NK_ASSERT(b); 9123 if (!b || c.a == 0 || line_thickness <= 0) return; 9124 if (b->use_clipping) { 9125 const struct nk_rect *clip = &b->clip; 9126 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && 9127 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && 9128 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) 9129 return; 9130 } 9131 9132 cmd = (struct nk_command_triangle*) 9133 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd)); 9134 if (!cmd) return; 9135 cmd->line_thickness = (unsigned short)line_thickness; 9136 cmd->a.x = (short)x0; 9137 cmd->a.y = (short)y0; 9138 cmd->b.x = (short)x1; 9139 cmd->b.y = (short)y1; 9140 cmd->c.x = (short)x2; 9141 cmd->c.y = (short)y2; 9142 cmd->color = c; 9143 } 9144 NK_API void 9145 nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, 9146 float y1, float x2, float y2, struct nk_color c) 9147 { 9148 struct nk_command_triangle_filled *cmd; 9149 NK_ASSERT(b); 9150 if (!b || c.a == 0) return; 9151 if (!b) return; 9152 if (b->use_clipping) { 9153 const struct nk_rect *clip = &b->clip; 9154 if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && 9155 !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && 9156 !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) 9157 return; 9158 } 9159 9160 cmd = (struct nk_command_triangle_filled*) 9161 nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd)); 9162 if (!cmd) return; 9163 cmd->a.x = (short)x0; 9164 cmd->a.y = (short)y0; 9165 cmd->b.x = (short)x1; 9166 cmd->b.y = (short)y1; 9167 cmd->c.x = (short)x2; 9168 cmd->c.y = (short)y2; 9169 cmd->color = c; 9170 } 9171 NK_API void 9172 nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count, 9173 float line_thickness, struct nk_color col) 9174 { 9175 int i; 9176 nk_size size = 0; 9177 struct nk_command_polygon *cmd; 9178 9179 NK_ASSERT(b); 9180 if (!b || col.a == 0 || line_thickness <= 0) return; 9181 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9182 cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size); 9183 if (!cmd) return; 9184 cmd->color = col; 9185 cmd->line_thickness = (unsigned short)line_thickness; 9186 cmd->point_count = (unsigned short)point_count; 9187 for (i = 0; i < point_count; ++i) { 9188 cmd->points[i].x = (short)points[i*2]; 9189 cmd->points[i].y = (short)points[i*2+1]; 9190 } 9191 } 9192 NK_API void 9193 nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count, 9194 struct nk_color col) 9195 { 9196 int i; 9197 nk_size size = 0; 9198 struct nk_command_polygon_filled *cmd; 9199 9200 NK_ASSERT(b); 9201 if (!b || col.a == 0) return; 9202 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9203 cmd = (struct nk_command_polygon_filled*) 9204 nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size); 9205 if (!cmd) return; 9206 cmd->color = col; 9207 cmd->point_count = (unsigned short)point_count; 9208 for (i = 0; i < point_count; ++i) { 9209 cmd->points[i].x = (short)points[i*2+0]; 9210 cmd->points[i].y = (short)points[i*2+1]; 9211 } 9212 } 9213 NK_API void 9214 nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count, 9215 float line_thickness, struct nk_color col) 9216 { 9217 int i; 9218 nk_size size = 0; 9219 struct nk_command_polyline *cmd; 9220 9221 NK_ASSERT(b); 9222 if (!b || col.a == 0 || line_thickness <= 0) return; 9223 size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; 9224 cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size); 9225 if (!cmd) return; 9226 cmd->color = col; 9227 cmd->point_count = (unsigned short)point_count; 9228 cmd->line_thickness = (unsigned short)line_thickness; 9229 for (i = 0; i < point_count; ++i) { 9230 cmd->points[i].x = (short)points[i*2]; 9231 cmd->points[i].y = (short)points[i*2+1]; 9232 } 9233 } 9234 NK_API void 9235 nk_draw_image(struct nk_command_buffer *b, struct nk_rect r, 9236 const struct nk_image *img, struct nk_color col) 9237 { 9238 struct nk_command_image *cmd; 9239 NK_ASSERT(b); 9240 if (!b) return; 9241 if (b->use_clipping) { 9242 const struct nk_rect *c = &b->clip; 9243 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)) 9244 return; 9245 } 9246 9247 cmd = (struct nk_command_image*) 9248 nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd)); 9249 if (!cmd) return; 9250 cmd->x = (short)r.x; 9251 cmd->y = (short)r.y; 9252 cmd->w = (unsigned short)NK_MAX(0, r.w); 9253 cmd->h = (unsigned short)NK_MAX(0, r.h); 9254 cmd->img = *img; 9255 cmd->col = col; 9256 } 9257 NK_API void 9258 nk_draw_nine_slice(struct nk_command_buffer *b, struct nk_rect r, 9259 const struct nk_nine_slice *slc, struct nk_color col) 9260 { 9261 struct nk_image img; 9262 const struct nk_image *slcimg = (const struct nk_image*)slc; 9263 nk_ushort rgnX, rgnY, rgnW, rgnH; 9264 rgnX = slcimg->region[0]; 9265 rgnY = slcimg->region[1]; 9266 rgnW = slcimg->region[2]; 9267 rgnH = slcimg->region[3]; 9268 9269 /* top-left */ 9270 img.handle = slcimg->handle; 9271 img.w = slcimg->w; 9272 img.h = slcimg->h; 9273 img.region[0] = rgnX; 9274 img.region[1] = rgnY; 9275 img.region[2] = slc->l; 9276 img.region[3] = slc->t; 9277 9278 nk_draw_image(b, 9279 nk_rect(r.x, r.y, (float)slc->l, (float)slc->t), 9280 &img, col); 9281 9282 #define IMG_RGN(x, y, w, h) img.region[0] = (nk_ushort)(x); img.region[1] = (nk_ushort)(y); img.region[2] = (nk_ushort)(w); img.region[3] = (nk_ushort)(h); 9283 9284 /* top-center */ 9285 IMG_RGN(rgnX + slc->l, rgnY, rgnW - slc->l - slc->r, slc->t); 9286 nk_draw_image(b, 9287 nk_rect(r.x + (float)slc->l, r.y, (float)(r.w - slc->l - slc->r), (float)slc->t), 9288 &img, col); 9289 9290 /* top-right */ 9291 IMG_RGN(rgnX + rgnW - slc->r, rgnY, slc->r, slc->t); 9292 nk_draw_image(b, 9293 nk_rect(r.x + r.w - (float)slc->r, r.y, (float)slc->r, (float)slc->t), 9294 &img, col); 9295 9296 /* center-left */ 9297 IMG_RGN(rgnX, rgnY + slc->t, slc->l, rgnH - slc->t - slc->b); 9298 nk_draw_image(b, 9299 nk_rect(r.x, r.y + (float)slc->t, (float)slc->l, (float)(r.h - slc->t - slc->b)), 9300 &img, col); 9301 9302 /* center */ 9303 IMG_RGN(rgnX + slc->l, rgnY + slc->t, rgnW - slc->l - slc->r, rgnH - slc->t - slc->b); 9304 nk_draw_image(b, 9305 nk_rect(r.x + (float)slc->l, r.y + (float)slc->t, (float)(r.w - slc->l - slc->r), (float)(r.h - slc->t - slc->b)), 9306 &img, col); 9307 9308 /* center-right */ 9309 IMG_RGN(rgnX + rgnW - slc->r, rgnY + slc->t, slc->r, rgnH - slc->t - slc->b); 9310 nk_draw_image(b, 9311 nk_rect(r.x + r.w - (float)slc->r, r.y + (float)slc->t, (float)slc->r, (float)(r.h - slc->t - slc->b)), 9312 &img, col); 9313 9314 /* bottom-left */ 9315 IMG_RGN(rgnX, rgnY + rgnH - slc->b, slc->l, slc->b); 9316 nk_draw_image(b, 9317 nk_rect(r.x, r.y + r.h - (float)slc->b, (float)slc->l, (float)slc->b), 9318 &img, col); 9319 9320 /* bottom-center */ 9321 IMG_RGN(rgnX + slc->l, rgnY + rgnH - slc->b, rgnW - slc->l - slc->r, slc->b); 9322 nk_draw_image(b, 9323 nk_rect(r.x + (float)slc->l, r.y + r.h - (float)slc->b, (float)(r.w - slc->l - slc->r), (float)slc->b), 9324 &img, col); 9325 9326 /* bottom-right */ 9327 IMG_RGN(rgnX + rgnW - slc->r, rgnY + rgnH - slc->b, slc->r, slc->b); 9328 nk_draw_image(b, 9329 nk_rect(r.x + r.w - (float)slc->r, r.y + r.h - (float)slc->b, (float)slc->r, (float)slc->b), 9330 &img, col); 9331 9332 #undef IMG_RGN 9333 } 9334 NK_API void 9335 nk_push_custom(struct nk_command_buffer *b, struct nk_rect r, 9336 nk_command_custom_callback cb, nk_handle usr) 9337 { 9338 struct nk_command_custom *cmd; 9339 NK_ASSERT(b); 9340 if (!b) return; 9341 if (b->use_clipping) { 9342 const struct nk_rect *c = &b->clip; 9343 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)) 9344 return; 9345 } 9346 9347 cmd = (struct nk_command_custom*) 9348 nk_command_buffer_push(b, NK_COMMAND_CUSTOM, sizeof(*cmd)); 9349 if (!cmd) return; 9350 cmd->x = (short)r.x; 9351 cmd->y = (short)r.y; 9352 cmd->w = (unsigned short)NK_MAX(0, r.w); 9353 cmd->h = (unsigned short)NK_MAX(0, r.h); 9354 cmd->callback_data = usr; 9355 cmd->callback = cb; 9356 } 9357 NK_API void 9358 nk_draw_text(struct nk_command_buffer *b, struct nk_rect r, 9359 const char *string, int length, const struct nk_user_font *font, 9360 struct nk_color bg, struct nk_color fg) 9361 { 9362 float text_width = 0; 9363 struct nk_command_text *cmd; 9364 9365 NK_ASSERT(b); 9366 NK_ASSERT(font); 9367 if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return; 9368 if (b->use_clipping) { 9369 const struct nk_rect *c = &b->clip; 9370 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)) 9371 return; 9372 } 9373 9374 /* make sure text fits inside bounds */ 9375 text_width = font->width(font->userdata, font->height, string, length); 9376 if (text_width > r.w){ 9377 int glyphs = 0; 9378 float txt_width = (float)text_width; 9379 length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0); 9380 } 9381 9382 if (!length) return; 9383 cmd = (struct nk_command_text*) 9384 nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1)); 9385 if (!cmd) return; 9386 cmd->x = (short)r.x; 9387 cmd->y = (short)r.y; 9388 cmd->w = (unsigned short)r.w; 9389 cmd->h = (unsigned short)r.h; 9390 cmd->background = bg; 9391 cmd->foreground = fg; 9392 cmd->font = font; 9393 cmd->length = length; 9394 cmd->height = font->height; 9395 NK_MEMCPY(cmd->string, string, (nk_size)length); 9396 cmd->string[length] = '\0'; 9397 } 9398 9399 9400 9401 9402 9403 /* =============================================================== 9404 * 9405 * VERTEX 9406 * 9407 * ===============================================================*/ 9408 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 9409 NK_API void 9410 nk_draw_list_init(struct nk_draw_list *list) 9411 { 9412 nk_size i = 0; 9413 NK_ASSERT(list); 9414 if (!list) return; 9415 nk_zero(list, sizeof(*list)); 9416 for (i = 0; i < NK_LEN(list->circle_vtx); ++i) { 9417 const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI; 9418 list->circle_vtx[i].x = (float)NK_COS(a); 9419 list->circle_vtx[i].y = (float)NK_SIN(a); 9420 } 9421 } 9422 NK_API void 9423 nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config, 9424 struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, 9425 enum nk_anti_aliasing line_aa, enum nk_anti_aliasing shape_aa) 9426 { 9427 NK_ASSERT(canvas); 9428 NK_ASSERT(config); 9429 NK_ASSERT(cmds); 9430 NK_ASSERT(vertices); 9431 NK_ASSERT(elements); 9432 if (!canvas || !config || !cmds || !vertices || !elements) 9433 return; 9434 9435 canvas->buffer = cmds; 9436 canvas->config = *config; 9437 canvas->elements = elements; 9438 canvas->vertices = vertices; 9439 canvas->line_AA = line_aa; 9440 canvas->shape_AA = shape_aa; 9441 canvas->clip_rect = nk_null_rect; 9442 9443 canvas->cmd_offset = 0; 9444 canvas->element_count = 0; 9445 canvas->vertex_count = 0; 9446 canvas->cmd_offset = 0; 9447 canvas->cmd_count = 0; 9448 canvas->path_count = 0; 9449 } 9450 NK_API const struct nk_draw_command* 9451 nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) 9452 { 9453 nk_byte *memory; 9454 nk_size offset; 9455 const struct nk_draw_command *cmd; 9456 9457 NK_ASSERT(buffer); 9458 if (!buffer || !buffer->size || !canvas->cmd_count) 9459 return 0; 9460 9461 memory = (nk_byte*)buffer->memory.ptr; 9462 offset = buffer->memory.size - canvas->cmd_offset; 9463 cmd = nk_ptr_add(const struct nk_draw_command, memory, offset); 9464 return cmd; 9465 } 9466 NK_API const struct nk_draw_command* 9467 nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) 9468 { 9469 nk_size size; 9470 nk_size offset; 9471 nk_byte *memory; 9472 const struct nk_draw_command *end; 9473 9474 NK_ASSERT(buffer); 9475 NK_ASSERT(canvas); 9476 if (!buffer || !canvas) 9477 return 0; 9478 9479 memory = (nk_byte*)buffer->memory.ptr; 9480 size = buffer->memory.size; 9481 offset = size - canvas->cmd_offset; 9482 end = nk_ptr_add(const struct nk_draw_command, memory, offset); 9483 end -= (canvas->cmd_count-1); 9484 return end; 9485 } 9486 NK_API const struct nk_draw_command* 9487 nk__draw_list_next(const struct nk_draw_command *cmd, 9488 const struct nk_buffer *buffer, const struct nk_draw_list *canvas) 9489 { 9490 const struct nk_draw_command *end; 9491 NK_ASSERT(buffer); 9492 NK_ASSERT(canvas); 9493 if (!cmd || !buffer || !canvas) 9494 return 0; 9495 9496 end = nk__draw_list_end(canvas, buffer); 9497 if (cmd <= end) return 0; 9498 return (cmd-1); 9499 } 9500 NK_INTERN struct nk_vec2* 9501 nk_draw_list_alloc_path(struct nk_draw_list *list, int count) 9502 { 9503 struct nk_vec2 *points; 9504 NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2); 9505 NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2); 9506 points = (struct nk_vec2*) 9507 nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT, 9508 point_size * (nk_size)count, point_align); 9509 9510 if (!points) return 0; 9511 if (!list->path_offset) { 9512 void *memory = nk_buffer_memory(list->buffer); 9513 list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory); 9514 } 9515 list->path_count += (unsigned int)count; 9516 return points; 9517 } 9518 NK_INTERN struct nk_vec2 9519 nk_draw_list_path_last(struct nk_draw_list *list) 9520 { 9521 void *memory; 9522 struct nk_vec2 *point; 9523 NK_ASSERT(list->path_count); 9524 memory = nk_buffer_memory(list->buffer); 9525 point = nk_ptr_add(struct nk_vec2, memory, list->path_offset); 9526 point += (list->path_count-1); 9527 return *point; 9528 } 9529 NK_INTERN struct nk_draw_command* 9530 nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip, 9531 nk_handle texture) 9532 { 9533 NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command); 9534 NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command); 9535 struct nk_draw_command *cmd; 9536 9537 NK_ASSERT(list); 9538 cmd = (struct nk_draw_command*) 9539 nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align); 9540 9541 if (!cmd) return 0; 9542 if (!list->cmd_count) { 9543 nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer); 9544 nk_size total = nk_buffer_total(list->buffer); 9545 memory = nk_ptr_add(nk_byte, memory, total); 9546 list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd); 9547 } 9548 9549 cmd->elem_count = 0; 9550 cmd->clip_rect = clip; 9551 cmd->texture = texture; 9552 #ifdef NK_INCLUDE_COMMAND_USERDATA 9553 cmd->userdata = list->userdata; 9554 #endif 9555 9556 list->cmd_count++; 9557 list->clip_rect = clip; 9558 return cmd; 9559 } 9560 NK_INTERN struct nk_draw_command* 9561 nk_draw_list_command_last(struct nk_draw_list *list) 9562 { 9563 void *memory; 9564 nk_size size; 9565 struct nk_draw_command *cmd; 9566 NK_ASSERT(list->cmd_count); 9567 9568 memory = nk_buffer_memory(list->buffer); 9569 size = nk_buffer_total(list->buffer); 9570 cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset); 9571 return (cmd - (list->cmd_count-1)); 9572 } 9573 NK_INTERN void 9574 nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect) 9575 { 9576 NK_ASSERT(list); 9577 if (!list) return; 9578 if (!list->cmd_count) { 9579 nk_draw_list_push_command(list, rect, list->config.tex_null.texture); 9580 } else { 9581 struct nk_draw_command *prev = nk_draw_list_command_last(list); 9582 if (prev->elem_count == 0) 9583 prev->clip_rect = rect; 9584 nk_draw_list_push_command(list, rect, prev->texture); 9585 } 9586 } 9587 NK_INTERN void 9588 nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture) 9589 { 9590 NK_ASSERT(list); 9591 if (!list) return; 9592 if (!list->cmd_count) { 9593 nk_draw_list_push_command(list, nk_null_rect, texture); 9594 } else { 9595 struct nk_draw_command *prev = nk_draw_list_command_last(list); 9596 if (prev->elem_count == 0) { 9597 prev->texture = texture; 9598 #ifdef NK_INCLUDE_COMMAND_USERDATA 9599 prev->userdata = list->userdata; 9600 #endif 9601 } else if (prev->texture.id != texture.id 9602 #ifdef NK_INCLUDE_COMMAND_USERDATA 9603 || prev->userdata.id != list->userdata.id 9604 #endif 9605 ) nk_draw_list_push_command(list, prev->clip_rect, texture); 9606 } 9607 } 9608 #ifdef NK_INCLUDE_COMMAND_USERDATA 9609 NK_API void 9610 nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata) 9611 { 9612 list->userdata = userdata; 9613 } 9614 #endif 9615 NK_INTERN void* 9616 nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count) 9617 { 9618 void *vtx; 9619 NK_ASSERT(list); 9620 if (!list) return 0; 9621 vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, 9622 list->config.vertex_size*count, list->config.vertex_alignment); 9623 if (!vtx) return 0; 9624 list->vertex_count += (unsigned int)count; 9625 9626 /* This assert triggers because your are drawing a lot of stuff and nuklear 9627 * defined `nk_draw_index` as `nk_ushort` to safe space be default. 9628 * 9629 * So you reached the maximum number of indices or rather vertexes. 9630 * To solve this issue please change typedef `nk_draw_index` to `nk_uint` 9631 * and don't forget to specify the new element size in your drawing 9632 * backend (OpenGL, DirectX, ...). For example in OpenGL for `glDrawElements` 9633 * instead of specifying `GL_UNSIGNED_SHORT` you have to define `GL_UNSIGNED_INT`. 9634 * Sorry for the inconvenience. */ 9635 if(sizeof(nk_draw_index)==2) NK_ASSERT((list->vertex_count < NK_USHORT_MAX && 9636 "To many vertices for 16-bit vertex indices. Please read comment above on how to solve this problem")); 9637 return vtx; 9638 } 9639 NK_INTERN nk_draw_index* 9640 nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count) 9641 { 9642 nk_draw_index *ids; 9643 struct nk_draw_command *cmd; 9644 NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index); 9645 NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index); 9646 NK_ASSERT(list); 9647 if (!list) return 0; 9648 9649 ids = (nk_draw_index*) 9650 nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align); 9651 if (!ids) return 0; 9652 cmd = nk_draw_list_command_last(list); 9653 list->element_count += (unsigned int)count; 9654 cmd->elem_count += (unsigned int)count; 9655 return ids; 9656 } 9657 NK_INTERN int 9658 nk_draw_vertex_layout_element_is_end_of_layout( 9659 const struct nk_draw_vertex_layout_element *element) 9660 { 9661 return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT || 9662 element->format == NK_FORMAT_COUNT); 9663 } 9664 NK_INTERN void 9665 nk_draw_vertex_color(void *attr, const float *vals, 9666 enum nk_draw_vertex_layout_format format) 9667 { 9668 /* if this triggers you tried to provide a value format for a color */ 9669 float val[4]; 9670 NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN); 9671 NK_ASSERT(format <= NK_FORMAT_COLOR_END); 9672 if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return; 9673 9674 val[0] = NK_SATURATE(vals[0]); 9675 val[1] = NK_SATURATE(vals[1]); 9676 val[2] = NK_SATURATE(vals[2]); 9677 val[3] = NK_SATURATE(vals[3]); 9678 9679 switch (format) { 9680 default: NK_ASSERT(0 && "Invalid vertex layout color format"); break; 9681 case NK_FORMAT_R8G8B8A8: 9682 case NK_FORMAT_R8G8B8: { 9683 struct nk_color col = nk_rgba_fv(val); 9684 NK_MEMCPY(attr, &col.r, sizeof(col)); 9685 } break; 9686 case NK_FORMAT_B8G8R8A8: { 9687 struct nk_color col = nk_rgba_fv(val); 9688 struct nk_color bgra = nk_rgba(col.b, col.g, col.r, col.a); 9689 NK_MEMCPY(attr, &bgra, sizeof(bgra)); 9690 } break; 9691 case NK_FORMAT_R16G15B16: { 9692 nk_ushort col[3]; 9693 col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX); 9694 col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX); 9695 col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX); 9696 NK_MEMCPY(attr, col, sizeof(col)); 9697 } break; 9698 case NK_FORMAT_R16G15B16A16: { 9699 nk_ushort col[4]; 9700 col[0] = (nk_ushort)(val[0]*(float)NK_USHORT_MAX); 9701 col[1] = (nk_ushort)(val[1]*(float)NK_USHORT_MAX); 9702 col[2] = (nk_ushort)(val[2]*(float)NK_USHORT_MAX); 9703 col[3] = (nk_ushort)(val[3]*(float)NK_USHORT_MAX); 9704 NK_MEMCPY(attr, col, sizeof(col)); 9705 } break; 9706 case NK_FORMAT_R32G32B32: { 9707 nk_uint col[3]; 9708 col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX); 9709 col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX); 9710 col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX); 9711 NK_MEMCPY(attr, col, sizeof(col)); 9712 } break; 9713 case NK_FORMAT_R32G32B32A32: { 9714 nk_uint col[4]; 9715 col[0] = (nk_uint)(val[0]*(float)NK_UINT_MAX); 9716 col[1] = (nk_uint)(val[1]*(float)NK_UINT_MAX); 9717 col[2] = (nk_uint)(val[2]*(float)NK_UINT_MAX); 9718 col[3] = (nk_uint)(val[3]*(float)NK_UINT_MAX); 9719 NK_MEMCPY(attr, col, sizeof(col)); 9720 } break; 9721 case NK_FORMAT_R32G32B32A32_FLOAT: 9722 NK_MEMCPY(attr, val, sizeof(float)*4); 9723 break; 9724 case NK_FORMAT_R32G32B32A32_DOUBLE: { 9725 double col[4]; 9726 col[0] = (double)val[0]; 9727 col[1] = (double)val[1]; 9728 col[2] = (double)val[2]; 9729 col[3] = (double)val[3]; 9730 NK_MEMCPY(attr, col, sizeof(col)); 9731 } break; 9732 case NK_FORMAT_RGB32: 9733 case NK_FORMAT_RGBA32: { 9734 struct nk_color col = nk_rgba_fv(val); 9735 nk_uint color = nk_color_u32(col); 9736 NK_MEMCPY(attr, &color, sizeof(color)); 9737 } break; } 9738 } 9739 NK_INTERN void 9740 nk_draw_vertex_element(void *dst, const float *values, int value_count, 9741 enum nk_draw_vertex_layout_format format) 9742 { 9743 int value_index; 9744 void *attribute = dst; 9745 /* if this triggers you tried to provide a color format for a value */ 9746 NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN); 9747 if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return; 9748 for (value_index = 0; value_index < value_count; ++value_index) { 9749 switch (format) { 9750 default: NK_ASSERT(0 && "invalid vertex layout format"); break; 9751 case NK_FORMAT_SCHAR: { 9752 char value = (char)NK_CLAMP((float)NK_SCHAR_MIN, values[value_index], (float)NK_SCHAR_MAX); 9753 NK_MEMCPY(attribute, &value, sizeof(value)); 9754 attribute = (void*)((char*)attribute + sizeof(char)); 9755 } break; 9756 case NK_FORMAT_SSHORT: { 9757 nk_short value = (nk_short)NK_CLAMP((float)NK_SSHORT_MIN, values[value_index], (float)NK_SSHORT_MAX); 9758 NK_MEMCPY(attribute, &value, sizeof(value)); 9759 attribute = (void*)((char*)attribute + sizeof(value)); 9760 } break; 9761 case NK_FORMAT_SINT: { 9762 nk_int value = (nk_int)NK_CLAMP((float)NK_SINT_MIN, values[value_index], (float)NK_SINT_MAX); 9763 NK_MEMCPY(attribute, &value, sizeof(value)); 9764 attribute = (void*)((char*)attribute + sizeof(nk_int)); 9765 } break; 9766 case NK_FORMAT_UCHAR: { 9767 unsigned char value = (unsigned char)NK_CLAMP((float)NK_UCHAR_MIN, values[value_index], (float)NK_UCHAR_MAX); 9768 NK_MEMCPY(attribute, &value, sizeof(value)); 9769 attribute = (void*)((char*)attribute + sizeof(unsigned char)); 9770 } break; 9771 case NK_FORMAT_USHORT: { 9772 nk_ushort value = (nk_ushort)NK_CLAMP((float)NK_USHORT_MIN, values[value_index], (float)NK_USHORT_MAX); 9773 NK_MEMCPY(attribute, &value, sizeof(value)); 9774 attribute = (void*)((char*)attribute + sizeof(value)); 9775 } break; 9776 case NK_FORMAT_UINT: { 9777 nk_uint value = (nk_uint)NK_CLAMP((float)NK_UINT_MIN, values[value_index], (float)NK_UINT_MAX); 9778 NK_MEMCPY(attribute, &value, sizeof(value)); 9779 attribute = (void*)((char*)attribute + sizeof(nk_uint)); 9780 } break; 9781 case NK_FORMAT_FLOAT: 9782 NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index])); 9783 attribute = (void*)((char*)attribute + sizeof(float)); 9784 break; 9785 case NK_FORMAT_DOUBLE: { 9786 double value = (double)values[value_index]; 9787 NK_MEMCPY(attribute, &value, sizeof(value)); 9788 attribute = (void*)((char*)attribute + sizeof(double)); 9789 } break; 9790 } 9791 } 9792 } 9793 NK_INTERN void* 9794 nk_draw_vertex(void *dst, const struct nk_convert_config *config, 9795 struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color) 9796 { 9797 void *result = (void*)((char*)dst + config->vertex_size); 9798 const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout; 9799 while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) { 9800 void *address = (void*)((char*)dst + elem_iter->offset); 9801 switch (elem_iter->attribute) { 9802 case NK_VERTEX_ATTRIBUTE_COUNT: 9803 default: NK_ASSERT(0 && "wrong element attribute"); break; 9804 case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break; 9805 case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break; 9806 case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break; 9807 } 9808 elem_iter++; 9809 } 9810 return result; 9811 } 9812 NK_API void 9813 nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points, 9814 const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed, 9815 float thickness, enum nk_anti_aliasing aliasing) 9816 { 9817 nk_size count; 9818 int thick_line; 9819 struct nk_colorf col; 9820 struct nk_colorf col_trans; 9821 NK_ASSERT(list); 9822 if (!list || points_count < 2) return; 9823 9824 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9825 count = points_count; 9826 if (!closed) count = points_count-1; 9827 thick_line = thickness > 1.0f; 9828 9829 #ifdef NK_INCLUDE_COMMAND_USERDATA 9830 nk_draw_list_push_userdata(list, list->userdata); 9831 #endif 9832 9833 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 9834 nk_color_fv(&col.r, color); 9835 col_trans = col; 9836 col_trans.a = 0; 9837 9838 if (aliasing == NK_ANTI_ALIASING_ON) { 9839 /* ANTI-ALIASED STROKE */ 9840 const float AA_SIZE = 1.0f; 9841 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); 9842 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); 9843 9844 /* allocate vertices and elements */ 9845 nk_size i1 = 0; 9846 nk_size vertex_offset; 9847 nk_size index = list->vertex_count; 9848 9849 const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12); 9850 const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3); 9851 9852 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 9853 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 9854 9855 nk_size size; 9856 struct nk_vec2 *normals, *temp; 9857 if (!vtx || !ids) return; 9858 9859 /* temporary allocate normals + points */ 9860 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); 9861 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); 9862 size = pnt_size * ((thick_line) ? 5 : 3) * points_count; 9863 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); 9864 if (!normals) return; 9865 temp = normals + points_count; 9866 9867 /* make sure vertex pointer is still correct */ 9868 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); 9869 9870 /* calculate normals */ 9871 for (i1 = 0; i1 < count; ++i1) { 9872 const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); 9873 struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]); 9874 float len; 9875 9876 /* vec2 inverted length */ 9877 len = nk_vec2_len_sqr(diff); 9878 if (len != 0.0f) 9879 len = NK_INV_SQRT(len); 9880 else len = 1.0f; 9881 9882 diff = nk_vec2_muls(diff, len); 9883 normals[i1].x = diff.y; 9884 normals[i1].y = -diff.x; 9885 } 9886 9887 if (!closed) 9888 normals[points_count-1] = normals[points_count-2]; 9889 9890 if (!thick_line) { 9891 nk_size idx1, i; 9892 if (!closed) { 9893 struct nk_vec2 d; 9894 temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE)); 9895 temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE)); 9896 d = nk_vec2_muls(normals[points_count-1], AA_SIZE); 9897 temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d); 9898 temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d); 9899 } 9900 9901 /* fill elements */ 9902 idx1 = index; 9903 for (i1 = 0; i1 < count; i1++) { 9904 struct nk_vec2 dm; 9905 float dmr2; 9906 nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); 9907 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3); 9908 9909 /* average normals */ 9910 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); 9911 dmr2 = dm.x * dm.x + dm.y* dm.y; 9912 if (dmr2 > 0.000001f) { 9913 float scale = 1.0f/dmr2; 9914 scale = NK_MIN(100.0f, scale); 9915 dm = nk_vec2_muls(dm, scale); 9916 } 9917 9918 dm = nk_vec2_muls(dm, AA_SIZE); 9919 temp[i2*2+0] = nk_vec2_add(points[i2], dm); 9920 temp[i2*2+1] = nk_vec2_sub(points[i2], dm); 9921 9922 ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0); 9923 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); 9924 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0); 9925 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); 9926 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); 9927 ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1); 9928 ids += 12; 9929 idx1 = idx2; 9930 } 9931 9932 /* fill vertices */ 9933 for (i = 0; i < points_count; ++i) { 9934 const struct nk_vec2 uv = list->config.tex_null.uv; 9935 vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col); 9936 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans); 9937 vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans); 9938 } 9939 } else { 9940 nk_size idx1, i; 9941 const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; 9942 if (!closed) { 9943 struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE); 9944 struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness); 9945 9946 temp[0] = nk_vec2_add(points[0], d1); 9947 temp[1] = nk_vec2_add(points[0], d2); 9948 temp[2] = nk_vec2_sub(points[0], d2); 9949 temp[3] = nk_vec2_sub(points[0], d1); 9950 9951 d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE); 9952 d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness); 9953 9954 temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1); 9955 temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2); 9956 temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2); 9957 temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1); 9958 } 9959 9960 /* add all elements */ 9961 idx1 = index; 9962 for (i1 = 0; i1 < count; ++i1) { 9963 struct nk_vec2 dm_out, dm_in; 9964 const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1); 9965 nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4); 9966 9967 /* average normals */ 9968 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); 9969 float dmr2 = dm.x * dm.x + dm.y* dm.y; 9970 if (dmr2 > 0.000001f) { 9971 float scale = 1.0f/dmr2; 9972 scale = NK_MIN(100.0f, scale); 9973 dm = nk_vec2_muls(dm, scale); 9974 } 9975 9976 dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE)); 9977 dm_in = nk_vec2_muls(dm, half_inner_thickness); 9978 temp[i2*4+0] = nk_vec2_add(points[i2], dm_out); 9979 temp[i2*4+1] = nk_vec2_add(points[i2], dm_in); 9980 temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in); 9981 temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out); 9982 9983 /* add indexes */ 9984 ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1); 9985 ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); 9986 ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1); 9987 ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); 9988 ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); 9989 ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1); 9990 ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2); 9991 ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3); 9992 ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2); 9993 ids += 18; 9994 idx1 = idx2; 9995 } 9996 9997 /* add vertices */ 9998 for (i = 0; i < points_count; ++i) { 9999 const struct nk_vec2 uv = list->config.tex_null.uv; 10000 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans); 10001 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col); 10002 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col); 10003 vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans); 10004 } 10005 } 10006 /* free temporary normals + points */ 10007 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); 10008 } else { 10009 /* NON ANTI-ALIASED STROKE */ 10010 nk_size i1 = 0; 10011 nk_size idx = list->vertex_count; 10012 const nk_size idx_count = count * 6; 10013 const nk_size vtx_count = count * 4; 10014 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 10015 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 10016 if (!vtx || !ids) return; 10017 10018 for (i1 = 0; i1 < count; ++i1) { 10019 float dx, dy; 10020 const struct nk_vec2 uv = list->config.tex_null.uv; 10021 const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1; 10022 const struct nk_vec2 p1 = points[i1]; 10023 const struct nk_vec2 p2 = points[i2]; 10024 struct nk_vec2 diff = nk_vec2_sub(p2, p1); 10025 float len; 10026 10027 /* vec2 inverted length */ 10028 len = nk_vec2_len_sqr(diff); 10029 if (len != 0.0f) 10030 len = NK_INV_SQRT(len); 10031 else len = 1.0f; 10032 diff = nk_vec2_muls(diff, len); 10033 10034 /* add vertices */ 10035 dx = diff.x * (thickness * 0.5f); 10036 dy = diff.y * (thickness * 0.5f); 10037 10038 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col); 10039 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col); 10040 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col); 10041 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col); 10042 10043 ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1); 10044 ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0); 10045 ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3); 10046 10047 ids += 6; 10048 idx += 4; 10049 } 10050 } 10051 } 10052 NK_API void 10053 nk_draw_list_fill_poly_convex(struct nk_draw_list *list, 10054 const struct nk_vec2 *points, const unsigned int points_count, 10055 struct nk_color color, enum nk_anti_aliasing aliasing) 10056 { 10057 struct nk_colorf col; 10058 struct nk_colorf col_trans; 10059 10060 NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); 10061 NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); 10062 NK_ASSERT(list); 10063 if (!list || points_count < 3) return; 10064 10065 #ifdef NK_INCLUDE_COMMAND_USERDATA 10066 nk_draw_list_push_userdata(list, list->userdata); 10067 #endif 10068 10069 color.a = (nk_byte)((float)color.a * list->config.global_alpha); 10070 nk_color_fv(&col.r, color); 10071 col_trans = col; 10072 col_trans.a = 0; 10073 10074 if (aliasing == NK_ANTI_ALIASING_ON) { 10075 nk_size i = 0; 10076 nk_size i0 = 0; 10077 nk_size i1 = 0; 10078 10079 const float AA_SIZE = 1.0f; 10080 nk_size vertex_offset = 0; 10081 nk_size index = list->vertex_count; 10082 10083 const nk_size idx_count = (points_count-2)*3 + points_count*6; 10084 const nk_size vtx_count = (points_count*2); 10085 10086 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 10087 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 10088 10089 nk_size size = 0; 10090 struct nk_vec2 *normals = 0; 10091 unsigned int vtx_inner_idx = (unsigned int)(index + 0); 10092 unsigned int vtx_outer_idx = (unsigned int)(index + 1); 10093 if (!vtx || !ids) return; 10094 10095 /* temporary allocate normals */ 10096 vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); 10097 nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); 10098 size = pnt_size * points_count; 10099 normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); 10100 if (!normals) return; 10101 vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); 10102 10103 /* add elements */ 10104 for (i = 2; i < points_count; i++) { 10105 ids[0] = (nk_draw_index)(vtx_inner_idx); 10106 ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1)); 10107 ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1)); 10108 ids += 3; 10109 } 10110 10111 /* compute normals */ 10112 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { 10113 struct nk_vec2 p0 = points[i0]; 10114 struct nk_vec2 p1 = points[i1]; 10115 struct nk_vec2 diff = nk_vec2_sub(p1, p0); 10116 10117 /* vec2 inverted length */ 10118 float len = nk_vec2_len_sqr(diff); 10119 if (len != 0.0f) 10120 len = NK_INV_SQRT(len); 10121 else len = 1.0f; 10122 diff = nk_vec2_muls(diff, len); 10123 10124 normals[i0].x = diff.y; 10125 normals[i0].y = -diff.x; 10126 } 10127 10128 /* add vertices + indexes */ 10129 for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { 10130 const struct nk_vec2 uv = list->config.tex_null.uv; 10131 struct nk_vec2 n0 = normals[i0]; 10132 struct nk_vec2 n1 = normals[i1]; 10133 struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f); 10134 float dmr2 = dm.x*dm.x + dm.y*dm.y; 10135 if (dmr2 > 0.000001f) { 10136 float scale = 1.0f / dmr2; 10137 scale = NK_MIN(scale, 100.0f); 10138 dm = nk_vec2_muls(dm, scale); 10139 } 10140 dm = nk_vec2_muls(dm, AA_SIZE * 0.5f); 10141 10142 /* add vertices */ 10143 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col); 10144 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans); 10145 10146 /* add indexes */ 10147 ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); 10148 ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1)); 10149 ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); 10150 ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); 10151 ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1)); 10152 ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); 10153 ids += 6; 10154 } 10155 /* free temporary normals + points */ 10156 nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); 10157 } else { 10158 nk_size i = 0; 10159 nk_size index = list->vertex_count; 10160 const nk_size idx_count = (points_count-2)*3; 10161 const nk_size vtx_count = points_count; 10162 void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); 10163 nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); 10164 10165 if (!vtx || !ids) return; 10166 for (i = 0; i < vtx_count; ++i) 10167 vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.tex_null.uv, col); 10168 for (i = 2; i < points_count; ++i) { 10169 ids[0] = (nk_draw_index)index; 10170 ids[1] = (nk_draw_index)(index+ i - 1); 10171 ids[2] = (nk_draw_index)(index+i); 10172 ids += 3; 10173 } 10174 } 10175 } 10176 NK_API void 10177 nk_draw_list_path_clear(struct nk_draw_list *list) 10178 { 10179 NK_ASSERT(list); 10180 if (!list) return; 10181 nk_buffer_reset(list->buffer, NK_BUFFER_FRONT); 10182 list->path_count = 0; 10183 list->path_offset = 0; 10184 } 10185 NK_API void 10186 nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos) 10187 { 10188 struct nk_vec2 *points = 0; 10189 struct nk_draw_command *cmd = 0; 10190 NK_ASSERT(list); 10191 if (!list) return; 10192 if (!list->cmd_count) 10193 nk_draw_list_add_clip(list, nk_null_rect); 10194 10195 cmd = nk_draw_list_command_last(list); 10196 if (cmd && cmd->texture.ptr != list->config.tex_null.texture.ptr) 10197 nk_draw_list_push_image(list, list->config.tex_null.texture); 10198 10199 points = nk_draw_list_alloc_path(list, 1); 10200 if (!points) return; 10201 points[0] = pos; 10202 } 10203 NK_API void 10204 nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center, 10205 float radius, int a_min, int a_max) 10206 { 10207 int a = 0; 10208 NK_ASSERT(list); 10209 if (!list) return; 10210 if (a_min <= a_max) { 10211 for (a = a_min; a <= a_max; a++) { 10212 const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)]; 10213 const float x = center.x + c.x * radius; 10214 const float y = center.y + c.y * radius; 10215 nk_draw_list_path_line_to(list, nk_vec2(x, y)); 10216 } 10217 } 10218 } 10219 NK_API void 10220 nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center, 10221 float radius, float a_min, float a_max, unsigned int segments) 10222 { 10223 unsigned int i = 0; 10224 NK_ASSERT(list); 10225 if (!list) return; 10226 if (radius == 0.0f) return; 10227 10228 /* This algorithm for arc drawing relies on these two trigonometric identities[1]: 10229 sin(a + b) = sin(a) * cos(b) + cos(a) * sin(b) 10230 cos(a + b) = cos(a) * cos(b) - sin(a) * sin(b) 10231 10232 Two coordinates (x, y) of a point on a circle centered on 10233 the origin can be written in polar form as: 10234 x = r * cos(a) 10235 y = r * sin(a) 10236 where r is the radius of the circle, 10237 a is the angle between (x, y) and the origin. 10238 10239 This allows us to rotate the coordinates around the 10240 origin by an angle b using the following transformation: 10241 x' = r * cos(a + b) = x * cos(b) - y * sin(b) 10242 y' = r * sin(a + b) = y * cos(b) + x * sin(b) 10243 10244 [1] https://en.wikipedia.org/wiki/List_of_trigonometric_identities#Angle_sum_and_difference_identities 10245 */ 10246 {const float d_angle = (a_max - a_min) / (float)segments; 10247 const float sin_d = (float)NK_SIN(d_angle); 10248 const float cos_d = (float)NK_COS(d_angle); 10249 10250 float cx = (float)NK_COS(a_min) * radius; 10251 float cy = (float)NK_SIN(a_min) * radius; 10252 for(i = 0; i <= segments; ++i) { 10253 float new_cx, new_cy; 10254 const float x = center.x + cx; 10255 const float y = center.y + cy; 10256 nk_draw_list_path_line_to(list, nk_vec2(x, y)); 10257 10258 new_cx = cx * cos_d - cy * sin_d; 10259 new_cy = cy * cos_d + cx * sin_d; 10260 cx = new_cx; 10261 cy = new_cy; 10262 }} 10263 } 10264 NK_API void 10265 nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a, 10266 struct nk_vec2 b, float rounding) 10267 { 10268 float r; 10269 NK_ASSERT(list); 10270 if (!list) return; 10271 r = rounding; 10272 r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x)); 10273 r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y)); 10274 10275 if (r == 0.0f) { 10276 nk_draw_list_path_line_to(list, a); 10277 nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y)); 10278 nk_draw_list_path_line_to(list, b); 10279 nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y)); 10280 } else { 10281 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9); 10282 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12); 10283 nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3); 10284 nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6); 10285 } 10286 } 10287 NK_API void 10288 nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2, 10289 struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments) 10290 { 10291 float t_step; 10292 unsigned int i_step; 10293 struct nk_vec2 p1; 10294 10295 NK_ASSERT(list); 10296 NK_ASSERT(list->path_count); 10297 if (!list || !list->path_count) return; 10298 num_segments = NK_MAX(num_segments, 1); 10299 10300 p1 = nk_draw_list_path_last(list); 10301 t_step = 1.0f/(float)num_segments; 10302 for (i_step = 1; i_step <= num_segments; ++i_step) { 10303 float t = t_step * (float)i_step; 10304 float u = 1.0f - t; 10305 float w1 = u*u*u; 10306 float w2 = 3*u*u*t; 10307 float w3 = 3*u*t*t; 10308 float w4 = t * t *t; 10309 float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; 10310 float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; 10311 nk_draw_list_path_line_to(list, nk_vec2(x,y)); 10312 } 10313 } 10314 NK_API void 10315 nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color) 10316 { 10317 struct nk_vec2 *points; 10318 NK_ASSERT(list); 10319 if (!list) return; 10320 points = (struct nk_vec2*)nk_buffer_memory(list->buffer); 10321 nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA); 10322 nk_draw_list_path_clear(list); 10323 } 10324 NK_API void 10325 nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color, 10326 enum nk_draw_list_stroke closed, float thickness) 10327 { 10328 struct nk_vec2 *points; 10329 NK_ASSERT(list); 10330 if (!list) return; 10331 points = (struct nk_vec2*)nk_buffer_memory(list->buffer); 10332 nk_draw_list_stroke_poly_line(list, points, list->path_count, color, 10333 closed, thickness, list->config.line_AA); 10334 nk_draw_list_path_clear(list); 10335 } 10336 NK_API void 10337 nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a, 10338 struct nk_vec2 b, struct nk_color col, float thickness) 10339 { 10340 NK_ASSERT(list); 10341 if (!list || !col.a) return; 10342 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10343 nk_draw_list_path_line_to(list, a); 10344 nk_draw_list_path_line_to(list, b); 10345 } else { 10346 nk_draw_list_path_line_to(list, nk_vec2_sub(a,nk_vec2(0.5f,0.5f))); 10347 nk_draw_list_path_line_to(list, nk_vec2_sub(b,nk_vec2(0.5f,0.5f))); 10348 } 10349 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); 10350 } 10351 NK_API void 10352 nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect, 10353 struct nk_color col, float rounding) 10354 { 10355 NK_ASSERT(list); 10356 if (!list || !col.a) return; 10357 10358 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10359 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y), 10360 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10361 } else { 10362 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f), 10363 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10364 } nk_draw_list_path_fill(list, col); 10365 } 10366 NK_API void 10367 nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect, 10368 struct nk_color col, float rounding, float thickness) 10369 { 10370 NK_ASSERT(list); 10371 if (!list || !col.a) return; 10372 if (list->line_AA == NK_ANTI_ALIASING_ON) { 10373 nk_draw_list_path_rect_to(list, nk_vec2(rect.x, rect.y), 10374 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10375 } else { 10376 nk_draw_list_path_rect_to(list, nk_vec2(rect.x-0.5f, rect.y-0.5f), 10377 nk_vec2(rect.x + rect.w, rect.y + rect.h), rounding); 10378 } nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10379 } 10380 NK_API void 10381 nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect, 10382 struct nk_color left, struct nk_color top, struct nk_color right, 10383 struct nk_color bottom) 10384 { 10385 void *vtx; 10386 struct nk_colorf col_left, col_top; 10387 struct nk_colorf col_right, col_bottom; 10388 nk_draw_index *idx; 10389 nk_draw_index index; 10390 10391 nk_color_fv(&col_left.r, left); 10392 nk_color_fv(&col_right.r, right); 10393 nk_color_fv(&col_top.r, top); 10394 nk_color_fv(&col_bottom.r, bottom); 10395 10396 NK_ASSERT(list); 10397 if (!list) return; 10398 10399 nk_draw_list_push_image(list, list->config.tex_null.texture); 10400 index = (nk_draw_index)list->vertex_count; 10401 vtx = nk_draw_list_alloc_vertices(list, 4); 10402 idx = nk_draw_list_alloc_elements(list, 6); 10403 if (!vtx || !idx) return; 10404 10405 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); 10406 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); 10407 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); 10408 10409 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.tex_null.uv, col_left); 10410 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.tex_null.uv, col_top); 10411 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.tex_null.uv, col_right); 10412 vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.tex_null.uv, col_bottom); 10413 } 10414 NK_API void 10415 nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a, 10416 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col) 10417 { 10418 NK_ASSERT(list); 10419 if (!list || !col.a) return; 10420 nk_draw_list_path_line_to(list, a); 10421 nk_draw_list_path_line_to(list, b); 10422 nk_draw_list_path_line_to(list, c); 10423 nk_draw_list_path_fill(list, col); 10424 } 10425 NK_API void 10426 nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a, 10427 struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness) 10428 { 10429 NK_ASSERT(list); 10430 if (!list || !col.a) return; 10431 nk_draw_list_path_line_to(list, a); 10432 nk_draw_list_path_line_to(list, b); 10433 nk_draw_list_path_line_to(list, c); 10434 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10435 } 10436 NK_API void 10437 nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center, 10438 float radius, struct nk_color col, unsigned int segs) 10439 { 10440 float a_max; 10441 NK_ASSERT(list); 10442 if (!list || !col.a) return; 10443 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; 10444 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); 10445 nk_draw_list_path_fill(list, col); 10446 } 10447 NK_API void 10448 nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center, 10449 float radius, struct nk_color col, unsigned int segs, float thickness) 10450 { 10451 float a_max; 10452 NK_ASSERT(list); 10453 if (!list || !col.a) return; 10454 a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; 10455 nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); 10456 nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); 10457 } 10458 NK_API void 10459 nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0, 10460 struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, 10461 struct nk_color col, unsigned int segments, float thickness) 10462 { 10463 NK_ASSERT(list); 10464 if (!list || !col.a) return; 10465 nk_draw_list_path_line_to(list, p0); 10466 nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments); 10467 nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); 10468 } 10469 NK_INTERN void 10470 nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a, 10471 struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc, 10472 struct nk_color color) 10473 { 10474 void *vtx; 10475 struct nk_vec2 uvb; 10476 struct nk_vec2 uvd; 10477 struct nk_vec2 b; 10478 struct nk_vec2 d; 10479 10480 struct nk_colorf col; 10481 nk_draw_index *idx; 10482 nk_draw_index index; 10483 NK_ASSERT(list); 10484 if (!list) return; 10485 10486 nk_color_fv(&col.r, color); 10487 uvb = nk_vec2(uvc.x, uva.y); 10488 uvd = nk_vec2(uva.x, uvc.y); 10489 b = nk_vec2(c.x, a.y); 10490 d = nk_vec2(a.x, c.y); 10491 10492 index = (nk_draw_index)list->vertex_count; 10493 vtx = nk_draw_list_alloc_vertices(list, 4); 10494 idx = nk_draw_list_alloc_elements(list, 6); 10495 if (!vtx || !idx) return; 10496 10497 idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); 10498 idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); 10499 idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); 10500 10501 vtx = nk_draw_vertex(vtx, &list->config, a, uva, col); 10502 vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col); 10503 vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col); 10504 vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col); 10505 } 10506 NK_API void 10507 nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture, 10508 struct nk_rect rect, struct nk_color color) 10509 { 10510 NK_ASSERT(list); 10511 if (!list) return; 10512 /* push new command with given texture */ 10513 nk_draw_list_push_image(list, texture.handle); 10514 if (nk_image_is_subimage(&texture)) { 10515 /* add region inside of the texture */ 10516 struct nk_vec2 uv[2]; 10517 uv[0].x = (float)texture.region[0]/(float)texture.w; 10518 uv[0].y = (float)texture.region[1]/(float)texture.h; 10519 uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w; 10520 uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h; 10521 nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), 10522 nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color); 10523 } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), 10524 nk_vec2(rect.x + rect.w, rect.y + rect.h), 10525 nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color); 10526 } 10527 NK_API void 10528 nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font, 10529 struct nk_rect rect, const char *text, int len, float font_height, 10530 struct nk_color fg) 10531 { 10532 float x = 0; 10533 int text_len = 0; 10534 nk_rune unicode = 0; 10535 nk_rune next = 0; 10536 int glyph_len = 0; 10537 int next_glyph_len = 0; 10538 struct nk_user_font_glyph g; 10539 10540 NK_ASSERT(list); 10541 if (!list || !len || !text) return; 10542 if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, 10543 list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return; 10544 10545 nk_draw_list_push_image(list, font->texture); 10546 x = rect.x; 10547 glyph_len = nk_utf_decode(text, &unicode, len); 10548 if (!glyph_len) return; 10549 10550 /* draw every glyph image */ 10551 fg.a = (nk_byte)((float)fg.a * list->config.global_alpha); 10552 while (text_len < len && glyph_len) { 10553 float gx, gy, gh, gw; 10554 float char_width = 0; 10555 if (unicode == NK_UTF_INVALID) break; 10556 10557 /* query currently drawn glyph information */ 10558 next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len); 10559 font->query(font->userdata, font_height, &g, unicode, 10560 (next == NK_UTF_INVALID) ? '\0' : next); 10561 10562 /* calculate and draw glyph drawing rectangle and image */ 10563 gx = x + g.offset.x; 10564 gy = rect.y + g.offset.y; 10565 gw = g.width; gh = g.height; 10566 char_width = g.xadvance; 10567 nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh), 10568 g.uv[0], g.uv[1], fg); 10569 10570 /* offset next glyph */ 10571 text_len += glyph_len; 10572 x += char_width; 10573 glyph_len = next_glyph_len; 10574 unicode = next; 10575 } 10576 } 10577 NK_API nk_flags 10578 nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, 10579 struct nk_buffer *vertices, struct nk_buffer *elements, 10580 const struct nk_convert_config *config) 10581 { 10582 nk_flags res = NK_CONVERT_SUCCESS; 10583 const struct nk_command *cmd; 10584 NK_ASSERT(ctx); 10585 NK_ASSERT(cmds); 10586 NK_ASSERT(vertices); 10587 NK_ASSERT(elements); 10588 NK_ASSERT(config); 10589 NK_ASSERT(config->vertex_layout); 10590 NK_ASSERT(config->vertex_size); 10591 if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout) 10592 return NK_CONVERT_INVALID_PARAM; 10593 10594 nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements, 10595 config->line_AA, config->shape_AA); 10596 nk_foreach(cmd, ctx) 10597 { 10598 #ifdef NK_INCLUDE_COMMAND_USERDATA 10599 ctx->draw_list.userdata = cmd->userdata; 10600 #endif 10601 switch (cmd->type) { 10602 case NK_COMMAND_NOP: break; 10603 case NK_COMMAND_SCISSOR: { 10604 const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd; 10605 nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h)); 10606 } break; 10607 case NK_COMMAND_LINE: { 10608 const struct nk_command_line *l = (const struct nk_command_line*)cmd; 10609 nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y), 10610 nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness); 10611 } break; 10612 case NK_COMMAND_CURVE: { 10613 const struct nk_command_curve *q = (const struct nk_command_curve*)cmd; 10614 nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y), 10615 nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x, 10616 q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color, 10617 config->curve_segment_count, q->line_thickness); 10618 } break; 10619 case NK_COMMAND_RECT: { 10620 const struct nk_command_rect *r = (const struct nk_command_rect*)cmd; 10621 nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10622 r->color, (float)r->rounding, r->line_thickness); 10623 } break; 10624 case NK_COMMAND_RECT_FILLED: { 10625 const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd; 10626 nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10627 r->color, (float)r->rounding); 10628 } break; 10629 case NK_COMMAND_RECT_MULTI_COLOR: { 10630 const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd; 10631 nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), 10632 r->left, r->top, r->right, r->bottom); 10633 } break; 10634 case NK_COMMAND_CIRCLE: { 10635 const struct nk_command_circle *c = (const struct nk_command_circle*)cmd; 10636 nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, 10637 (float)c->y + (float)c->h/2), (float)c->w/2, c->color, 10638 config->circle_segment_count, c->line_thickness); 10639 } break; 10640 case NK_COMMAND_CIRCLE_FILLED: { 10641 const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; 10642 nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, 10643 (float)c->y + (float)c->h/2), (float)c->w/2, c->color, 10644 config->circle_segment_count); 10645 } break; 10646 case NK_COMMAND_ARC: { 10647 const struct nk_command_arc *c = (const struct nk_command_arc*)cmd; 10648 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); 10649 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, 10650 c->a[0], c->a[1], config->arc_segment_count); 10651 nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness); 10652 } break; 10653 case NK_COMMAND_ARC_FILLED: { 10654 const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd; 10655 nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); 10656 nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, 10657 c->a[0], c->a[1], config->arc_segment_count); 10658 nk_draw_list_path_fill(&ctx->draw_list, c->color); 10659 } break; 10660 case NK_COMMAND_TRIANGLE: { 10661 const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd; 10662 nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), 10663 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color, 10664 t->line_thickness); 10665 } break; 10666 case NK_COMMAND_TRIANGLE_FILLED: { 10667 const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd; 10668 nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), 10669 nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color); 10670 } break; 10671 case NK_COMMAND_POLYGON: { 10672 int i; 10673 const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd; 10674 for (i = 0; i < p->point_count; ++i) { 10675 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10676 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10677 } 10678 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness); 10679 } break; 10680 case NK_COMMAND_POLYGON_FILLED: { 10681 int i; 10682 const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd; 10683 for (i = 0; i < p->point_count; ++i) { 10684 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10685 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10686 } 10687 nk_draw_list_path_fill(&ctx->draw_list, p->color); 10688 } break; 10689 case NK_COMMAND_POLYLINE: { 10690 int i; 10691 const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd; 10692 for (i = 0; i < p->point_count; ++i) { 10693 struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); 10694 nk_draw_list_path_line_to(&ctx->draw_list, pnt); 10695 } 10696 nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness); 10697 } break; 10698 case NK_COMMAND_TEXT: { 10699 const struct nk_command_text *t = (const struct nk_command_text*)cmd; 10700 nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h), 10701 t->string, t->length, t->height, t->foreground); 10702 } break; 10703 case NK_COMMAND_IMAGE: { 10704 const struct nk_command_image *i = (const struct nk_command_image*)cmd; 10705 nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col); 10706 } break; 10707 case NK_COMMAND_CUSTOM: { 10708 const struct nk_command_custom *c = (const struct nk_command_custom*)cmd; 10709 c->callback(&ctx->draw_list, c->x, c->y, c->w, c->h, c->callback_data); 10710 } break; 10711 default: break; 10712 } 10713 } 10714 res |= (cmds->needed > cmds->allocated + (cmds->memory.size - cmds->size)) ? NK_CONVERT_COMMAND_BUFFER_FULL: 0; 10715 res |= (vertices->needed > vertices->allocated) ? NK_CONVERT_VERTEX_BUFFER_FULL: 0; 10716 res |= (elements->needed > elements->allocated) ? NK_CONVERT_ELEMENT_BUFFER_FULL: 0; 10717 return res; 10718 } 10719 NK_API const struct nk_draw_command* 10720 nk__draw_begin(const struct nk_context *ctx, 10721 const struct nk_buffer *buffer) 10722 { 10723 return nk__draw_list_begin(&ctx->draw_list, buffer); 10724 } 10725 NK_API const struct nk_draw_command* 10726 nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer) 10727 { 10728 return nk__draw_list_end(&ctx->draw_list, buffer); 10729 } 10730 NK_API const struct nk_draw_command* 10731 nk__draw_next(const struct nk_draw_command *cmd, 10732 const struct nk_buffer *buffer, const struct nk_context *ctx) 10733 { 10734 return nk__draw_list_next(cmd, buffer, &ctx->draw_list); 10735 } 10736 #endif 10737 10738 10739 /* stb_rect_pack.h - v1.01 - public domain - rectangle packing */ 10740 /* Sean Barrett 2014 */ 10741 /* */ 10742 /* Useful for e.g. packing rectangular textures into an atlas. */ 10743 /* Does not do rotation. */ 10744 /* */ 10745 /* Before #including, */ 10746 /* */ 10747 /* #define STB_RECT_PACK_IMPLEMENTATION */ 10748 /* */ 10749 /* in the file that you want to have the implementation. */ 10750 /* */ 10751 /* Not necessarily the awesomest packing method, but better than */ 10752 /* the totally naive one in stb_truetype (which is primarily what */ 10753 /* this is meant to replace). */ 10754 /* */ 10755 /* Has only had a few tests run, may have issues. */ 10756 /* */ 10757 /* More docs to come. */ 10758 /* */ 10759 /* No memory allocations; uses qsort() and assert() from stdlib. */ 10760 /* Can override those by defining STBRP_SORT and STBRP_ASSERT. */ 10761 /* */ 10762 /* This library currently uses the Skyline Bottom-Left algorithm. */ 10763 /* */ 10764 /* Please note: better rectangle packers are welcome! Please */ 10765 /* implement them to the same API, but with a different init */ 10766 /* function. */ 10767 /* */ 10768 /* Credits */ 10769 /* */ 10770 /* Library */ 10771 /* Sean Barrett */ 10772 /* Minor features */ 10773 /* Martins Mozeiko */ 10774 /* github:IntellectualKitty */ 10775 /* */ 10776 /* Bugfixes / warning fixes */ 10777 /* Jeremy Jaussaud */ 10778 /* Fabian Giesen */ 10779 /* */ 10780 /* Version history: */ 10781 /* */ 10782 /* 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section */ 10783 /* 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles */ 10784 /* 0.99 (2019-02-07) warning fixes */ 10785 /* 0.11 (2017-03-03) return packing success/fail result */ 10786 /* 0.10 (2016-10-25) remove cast-away-const to avoid warnings */ 10787 /* 0.09 (2016-08-27) fix compiler warnings */ 10788 /* 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) */ 10789 /* 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) */ 10790 /* 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort */ 10791 /* 0.05: added STBRP_ASSERT to allow replacing assert */ 10792 /* 0.04: fixed minor bug in STBRP_LARGE_RECTS support */ 10793 /* 0.01: initial release */ 10794 /* */ 10795 /* LICENSE */ 10796 /* */ 10797 /* See end of file for license information. */ 10798 10799 /* //////////////////////////////////////////////////////////////////////////// */ 10800 /* */ 10801 /* INCLUDE SECTION */ 10802 /* */ 10803 10804 #ifndef STB_INCLUDE_STB_RECT_PACK_H 10805 #define STB_INCLUDE_STB_RECT_PACK_H 10806 10807 #define STB_RECT_PACK_VERSION 1 10808 10809 #ifdef STBRP_STATIC 10810 #define STBRP_DEF static 10811 #else 10812 #define STBRP_DEF extern 10813 #endif 10814 10815 #ifdef __cplusplus 10816 extern "C" { 10817 #endif 10818 10819 typedef struct stbrp_context stbrp_context; 10820 typedef struct stbrp_node stbrp_node; 10821 typedef struct stbrp_rect stbrp_rect; 10822 10823 typedef int stbrp_coord; 10824 10825 #define STBRP__MAXVAL 0x7fffffff 10826 /* Mostly for internal use, but this is the maximum supported coordinate value. */ 10827 10828 STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); 10829 /* Assign packed locations to rectangles. The rectangles are of type */ 10830 /* 'stbrp_rect' defined below, stored in the array 'rects', and there */ 10831 /* are 'num_rects' many of them. */ 10832 /* */ 10833 /* Rectangles which are successfully packed have the 'was_packed' flag */ 10834 /* set to a non-zero value and 'x' and 'y' store the minimum location */ 10835 /* on each axis (i.e. bottom-left in cartesian coordinates, top-left */ 10836 /* if you imagine y increasing downwards). Rectangles which do not fit */ 10837 /* have the 'was_packed' flag set to 0. */ 10838 /* */ 10839 /* You should not try to access the 'rects' array from another thread */ 10840 /* while this function is running, as the function temporarily reorders */ 10841 /* the array while it executes. */ 10842 /* */ 10843 /* To pack into another rectangle, you need to call stbrp_init_target */ 10844 /* again. To continue packing into the same rectangle, you can call */ 10845 /* this function again. Calling this multiple times with multiple rect */ 10846 /* arrays will probably produce worse packing results than calling it */ 10847 /* a single time with the full rectangle array, but the option is */ 10848 /* available. */ 10849 /* */ 10850 /* The function returns 1 if all of the rectangles were successfully */ 10851 /* packed and 0 otherwise. */ 10852 10853 struct stbrp_rect 10854 { 10855 /* reserved for your use: */ 10856 int id; 10857 10858 /* input: */ 10859 stbrp_coord w, h; 10860 10861 /* output: */ 10862 stbrp_coord x, y; 10863 int was_packed; /* non-zero if valid packing */ 10864 10865 }; /* 16 bytes, nominally */ 10866 10867 10868 STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); 10869 /* Initialize a rectangle packer to: */ 10870 /* pack a rectangle that is 'width' by 'height' in dimensions */ 10871 /* using temporary storage provided by the array 'nodes', which is 'num_nodes' long */ 10872 /* */ 10873 /* You must call this function every time you start packing into a new target. */ 10874 /* */ 10875 /* There is no "shutdown" function. The 'nodes' memory must stay valid for */ 10876 /* the following stbrp_pack_rects() call (or calls), but can be freed after */ 10877 /* the call (or calls) finish. */ 10878 /* */ 10879 /* Note: to guarantee best results, either: */ 10880 /* 1. make sure 'num_nodes' >= 'width' */ 10881 /* or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' */ 10882 /* */ 10883 /* If you don't do either of the above things, widths will be quantized to multiples */ 10884 /* of small integers to guarantee the algorithm doesn't run out of temporary storage. */ 10885 /* */ 10886 /* If you do #2, then the non-quantized algorithm will be used, but the algorithm */ 10887 /* may run out of temporary storage and be unable to pack some rectangles. */ 10888 10889 STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); 10890 /* Optionally call this function after init but before doing any packing to */ 10891 /* change the handling of the out-of-temp-memory scenario, described above. */ 10892 /* If you call init again, this will be reset to the default (false). */ 10893 10894 10895 STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); 10896 /* Optionally select which packing heuristic the library should use. Different */ 10897 /* heuristics will produce better/worse results for different data sets. */ 10898 /* If you call init again, this will be reset to the default. */ 10899 10900 enum 10901 { 10902 STBRP_HEURISTIC_Skyline_default=0, 10903 STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, 10904 STBRP_HEURISTIC_Skyline_BF_sortHeight 10905 }; 10906 10907 10908 /* //////////////////////////////////////////////////////////////////////////// */ 10909 /* */ 10910 /* the details of the following structures don't matter to you, but they must */ 10911 /* be visible so you can handle the memory allocations for them */ 10912 10913 struct stbrp_node 10914 { 10915 stbrp_coord x,y; 10916 stbrp_node *next; 10917 }; 10918 10919 struct stbrp_context 10920 { 10921 int width; 10922 int height; 10923 int align; 10924 int init_mode; 10925 int heuristic; 10926 int num_nodes; 10927 stbrp_node *active_head; 10928 stbrp_node *free_head; 10929 stbrp_node extra[2]; /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */ 10930 }; 10931 10932 #ifdef __cplusplus 10933 } 10934 #endif 10935 10936 #endif 10937 10938 /* //////////////////////////////////////////////////////////////////////////// */ 10939 /* */ 10940 /* IMPLEMENTATION SECTION */ 10941 /* */ 10942 10943 #ifdef STB_RECT_PACK_IMPLEMENTATION 10944 #ifndef STBRP_SORT 10945 #include <stdlib.h> 10946 #define STBRP_SORT qsort 10947 #endif 10948 10949 #ifndef STBRP_ASSERT 10950 #include <assert.h> 10951 #define STBRP_ASSERT assert 10952 #endif 10953 10954 #ifdef _MSC_VER 10955 #define STBRP__NOTUSED(v) (void)(v) 10956 #define STBRP__CDECL __cdecl 10957 #else 10958 #define STBRP__NOTUSED(v) (void)sizeof(v) 10959 #define STBRP__CDECL 10960 #endif 10961 10962 enum 10963 { 10964 STBRP__INIT_skyline = 1 10965 }; 10966 10967 STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) 10968 { 10969 switch (context->init_mode) { 10970 case STBRP__INIT_skyline: 10971 STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); 10972 context->heuristic = heuristic; 10973 break; 10974 default: 10975 STBRP_ASSERT(0); 10976 } 10977 } 10978 10979 STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) 10980 { 10981 if (allow_out_of_mem) 10982 /* if it's ok to run out of memory, then don't bother aligning them; */ 10983 /* this gives better packing, but may fail due to OOM (even though */ 10984 /* the rectangles easily fit). @TODO a smarter approach would be to only */ 10985 /* quantize once we've hit OOM, then we could get rid of this parameter. */ 10986 context->align = 1; 10987 else { 10988 /* if it's not ok to run out of memory, then quantize the widths */ 10989 /* so that num_nodes is always enough nodes. */ 10990 /* */ 10991 /* I.e. num_nodes * align >= width */ 10992 /* align >= width / num_nodes */ 10993 /* align = ceil(width/num_nodes) */ 10994 10995 context->align = (context->width + context->num_nodes-1) / context->num_nodes; 10996 } 10997 } 10998 10999 STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) 11000 { 11001 int i; 11002 11003 for (i=0; i < num_nodes-1; ++i) 11004 nodes[i].next = &nodes[i+1]; 11005 nodes[i].next = NULL; 11006 context->init_mode = STBRP__INIT_skyline; 11007 context->heuristic = STBRP_HEURISTIC_Skyline_default; 11008 context->free_head = &nodes[0]; 11009 context->active_head = &context->extra[0]; 11010 context->width = width; 11011 context->height = height; 11012 context->num_nodes = num_nodes; 11013 stbrp_setup_allow_out_of_mem(context, 0); 11014 11015 /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */ 11016 context->extra[0].x = 0; 11017 context->extra[0].y = 0; 11018 context->extra[0].next = &context->extra[1]; 11019 context->extra[1].x = (stbrp_coord) width; 11020 context->extra[1].y = (1<<30); 11021 context->extra[1].next = NULL; 11022 } 11023 11024 /* find minimum y position if it starts at x1 */ 11025 static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) 11026 { 11027 stbrp_node *node = first; 11028 int x1 = x0 + width; 11029 int min_y, visited_width, waste_area; 11030 11031 STBRP__NOTUSED(c); 11032 11033 STBRP_ASSERT(first->x <= x0); 11034 11035 #if 0 11036 /* skip in case we're past the node */ 11037 while (node->next->x <= x0) 11038 ++node; 11039 #else 11040 STBRP_ASSERT(node->next->x > x0); /* we ended up handling this in the caller for efficiency */ 11041 #endif 11042 11043 STBRP_ASSERT(node->x <= x0); 11044 11045 min_y = 0; 11046 waste_area = 0; 11047 visited_width = 0; 11048 while (node->x < x1) { 11049 if (node->y > min_y) { 11050 /* raise min_y higher. */ 11051 /* we've accounted for all waste up to min_y, */ 11052 /* but we'll now add more waste for everything we've visted */ 11053 waste_area += visited_width * (node->y - min_y); 11054 min_y = node->y; 11055 /* the first time through, visited_width might be reduced */ 11056 if (node->x < x0) 11057 visited_width += node->next->x - x0; 11058 else 11059 visited_width += node->next->x - node->x; 11060 } else { 11061 /* add waste area */ 11062 int under_width = node->next->x - node->x; 11063 if (under_width + visited_width > width) 11064 under_width = width - visited_width; 11065 waste_area += under_width * (min_y - node->y); 11066 visited_width += under_width; 11067 } 11068 node = node->next; 11069 } 11070 11071 *pwaste = waste_area; 11072 return min_y; 11073 } 11074 11075 typedef struct 11076 { 11077 int x,y; 11078 stbrp_node **prev_link; 11079 } stbrp__findresult; 11080 11081 static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) 11082 { 11083 int best_waste = (1<<30), best_x, best_y = (1 << 30); 11084 stbrp__findresult fr; 11085 stbrp_node **prev, *node, *tail, **best = NULL; 11086 11087 /* align to multiple of c->align */ 11088 width = (width + c->align - 1); 11089 width -= width % c->align; 11090 STBRP_ASSERT(width % c->align == 0); 11091 11092 /* if it can't possibly fit, bail immediately */ 11093 if (width > c->width || height > c->height) { 11094 fr.prev_link = NULL; 11095 fr.x = fr.y = 0; 11096 return fr; 11097 } 11098 11099 node = c->active_head; 11100 prev = &c->active_head; 11101 while (node->x + width <= c->width) { 11102 int y,waste; 11103 y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); 11104 if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { /* actually just want to test BL */ 11105 /* bottom left */ 11106 if (y < best_y) { 11107 best_y = y; 11108 best = prev; 11109 } 11110 } else { 11111 /* best-fit */ 11112 if (y + height <= c->height) { 11113 /* can only use it if it first vertically */ 11114 if (y < best_y || (y == best_y && waste < best_waste)) { 11115 best_y = y; 11116 best_waste = waste; 11117 best = prev; 11118 } 11119 } 11120 } 11121 prev = &node->next; 11122 node = node->next; 11123 } 11124 11125 best_x = (best == NULL) ? 0 : (*best)->x; 11126 11127 /* if doing best-fit (BF), we also have to try aligning right edge to each node position */ 11128 /* */ 11129 /* e.g, if fitting */ 11130 /* */ 11131 /* ____________________ */ 11132 /* |____________________| */ 11133 /* */ 11134 /* into */ 11135 /* */ 11136 /* | | */ 11137 /* | ____________| */ 11138 /* |____________| */ 11139 /* */ 11140 /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */ 11141 /* */ 11142 /* This makes BF take about 2x the time */ 11143 11144 if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { 11145 tail = c->active_head; 11146 node = c->active_head; 11147 prev = &c->active_head; 11148 /* find first node that's admissible */ 11149 while (tail->x < width) 11150 tail = tail->next; 11151 while (tail) { 11152 int xpos = tail->x - width; 11153 int y,waste; 11154 STBRP_ASSERT(xpos >= 0); 11155 /* find the left position that matches this */ 11156 while (node->next->x <= xpos) { 11157 prev = &node->next; 11158 node = node->next; 11159 } 11160 STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); 11161 y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); 11162 if (y + height <= c->height) { 11163 if (y <= best_y) { 11164 if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 11165 best_x = xpos; 11166 STBRP_ASSERT(y <= best_y); 11167 best_y = y; 11168 best_waste = waste; 11169 best = prev; 11170 } 11171 } 11172 } 11173 tail = tail->next; 11174 } 11175 } 11176 11177 fr.prev_link = best; 11178 fr.x = best_x; 11179 fr.y = best_y; 11180 return fr; 11181 } 11182 11183 static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) 11184 { 11185 /* find best position according to heuristic */ 11186 stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); 11187 stbrp_node *node, *cur; 11188 11189 /* bail if: */ 11190 /* 1. it failed */ 11191 /* 2. the best node doesn't fit (we don't always check this) */ 11192 /* 3. we're out of memory */ 11193 if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { 11194 res.prev_link = NULL; 11195 return res; 11196 } 11197 11198 /* on success, create new node */ 11199 node = context->free_head; 11200 node->x = (stbrp_coord) res.x; 11201 node->y = (stbrp_coord) (res.y + height); 11202 11203 context->free_head = node->next; 11204 11205 /* insert the new node into the right starting point, and */ 11206 /* let 'cur' point to the remaining nodes needing to be */ 11207 /* stiched back in */ 11208 11209 cur = *res.prev_link; 11210 if (cur->x < res.x) { 11211 /* preserve the existing one, so start testing with the next one */ 11212 stbrp_node *next = cur->next; 11213 cur->next = node; 11214 cur = next; 11215 } else { 11216 *res.prev_link = node; 11217 } 11218 11219 /* from here, traverse cur and free the nodes, until we get to one */ 11220 /* that shouldn't be freed */ 11221 while (cur->next && cur->next->x <= res.x + width) { 11222 stbrp_node *next = cur->next; 11223 /* move the current node to the free list */ 11224 cur->next = context->free_head; 11225 context->free_head = cur; 11226 cur = next; 11227 } 11228 11229 /* stitch the list back in */ 11230 node->next = cur; 11231 11232 if (cur->x < res.x + width) 11233 cur->x = (stbrp_coord) (res.x + width); 11234 11235 #ifdef _DEBUG 11236 cur = context->active_head; 11237 while (cur->x < context->width) { 11238 STBRP_ASSERT(cur->x < cur->next->x); 11239 cur = cur->next; 11240 } 11241 STBRP_ASSERT(cur->next == NULL); 11242 11243 { 11244 int count=0; 11245 cur = context->active_head; 11246 while (cur) { 11247 cur = cur->next; 11248 ++count; 11249 } 11250 cur = context->free_head; 11251 while (cur) { 11252 cur = cur->next; 11253 ++count; 11254 } 11255 STBRP_ASSERT(count == context->num_nodes+2); 11256 } 11257 #endif 11258 11259 return res; 11260 } 11261 11262 static int STBRP__CDECL rect_height_compare(const void *a, const void *b) 11263 { 11264 const stbrp_rect *p = (const stbrp_rect *) a; 11265 const stbrp_rect *q = (const stbrp_rect *) b; 11266 if (p->h > q->h) 11267 return -1; 11268 if (p->h < q->h) 11269 return 1; 11270 return (p->w > q->w) ? -1 : (p->w < q->w); 11271 } 11272 11273 static int STBRP__CDECL rect_original_order(const void *a, const void *b) 11274 { 11275 const stbrp_rect *p = (const stbrp_rect *) a; 11276 const stbrp_rect *q = (const stbrp_rect *) b; 11277 return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 11278 } 11279 11280 STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) 11281 { 11282 int i, all_rects_packed = 1; 11283 11284 /* we use the 'was_packed' field internally to allow sorting/unsorting */ 11285 for (i=0; i < num_rects; ++i) { 11286 rects[i].was_packed = i; 11287 } 11288 11289 /* sort according to heuristic */ 11290 STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); 11291 11292 for (i=0; i < num_rects; ++i) { 11293 if (rects[i].w == 0 || rects[i].h == 0) { 11294 rects[i].x = rects[i].y = 0; /* empty rect needs no space */ 11295 } else { 11296 stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 11297 if (fr.prev_link) { 11298 rects[i].x = (stbrp_coord) fr.x; 11299 rects[i].y = (stbrp_coord) fr.y; 11300 } else { 11301 rects[i].x = rects[i].y = STBRP__MAXVAL; 11302 } 11303 } 11304 } 11305 11306 /* unsort */ 11307 STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); 11308 11309 /* set was_packed flags and all_rects_packed status */ 11310 for (i=0; i < num_rects; ++i) { 11311 rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); 11312 if (!rects[i].was_packed) 11313 all_rects_packed = 0; 11314 } 11315 11316 /* return the all_rects_packed status */ 11317 return all_rects_packed; 11318 } 11319 #endif 11320 11321 /* 11322 ------------------------------------------------------------------------------ 11323 This software is available under 2 licenses -- choose whichever you prefer. 11324 ------------------------------------------------------------------------------ 11325 ALTERNATIVE A - MIT License 11326 Copyright (c) 2017 Sean Barrett 11327 Permission is hereby granted, free of charge, to any person obtaining a copy of 11328 this software and associated documentation files (the "Software"), to deal in 11329 the Software without restriction, including without limitation the rights to 11330 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 11331 of the Software, and to permit persons to whom the Software is furnished to do 11332 so, subject to the following conditions: 11333 The above copyright notice and this permission notice shall be included in all 11334 copies or substantial portions of the Software. 11335 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 11336 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11337 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 11338 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 11339 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 11340 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 11341 SOFTWARE. 11342 ------------------------------------------------------------------------------ 11343 ALTERNATIVE B - Public Domain (www.unlicense.org) 11344 This is free and unencumbered software released into the public domain. 11345 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 11346 software, either in source code form or as a compiled binary, for any purpose, 11347 commercial or non-commercial, and by any means. 11348 In jurisdictions that recognize copyright laws, the author or authors of this 11349 software dedicate any and all copyright interest in the software to the public 11350 domain. We make this dedication for the benefit of the public at large and to 11351 the detriment of our heirs and successors. We intend this dedication to be an 11352 overt act of relinquishment in perpetuity of all present and future rights to 11353 this software under copyright law. 11354 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 11355 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 11356 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 11357 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 11358 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 11359 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 11360 ------------------------------------------------------------------------------ 11361 */ 11362 11363 /* stb_truetype.h - v1.26 - public domain */ 11364 /* authored from 2009-2021 by Sean Barrett / RAD Game Tools */ 11365 /* */ 11366 /* ======================================================================= */ 11367 /* */ 11368 /* NO SECURITY GUARANTEE -- DO NOT USE THIS ON UNTRUSTED FONT FILES */ 11369 /* */ 11370 /* This library does no range checking of the offsets found in the file, */ 11371 /* meaning an attacker can use it to read arbitrary memory. */ 11372 /* */ 11373 /* ======================================================================= */ 11374 /* */ 11375 /* This library processes TrueType files: */ 11376 /* parse files */ 11377 /* extract glyph metrics */ 11378 /* extract glyph shapes */ 11379 /* render glyphs to one-channel bitmaps with antialiasing (box filter) */ 11380 /* render glyphs to one-channel SDF bitmaps (signed-distance field/function) */ 11381 /* */ 11382 /* Todo: */ 11383 /* non-MS cmaps */ 11384 /* crashproof on bad data */ 11385 /* hinting? (no longer patented) */ 11386 /* cleartype-style AA? */ 11387 /* optimize: use simple memory allocator for intermediates */ 11388 /* optimize: build edge-list directly from curves */ 11389 /* optimize: rasterize directly from curves? */ 11390 /* */ 11391 /* ADDITIONAL CONTRIBUTORS */ 11392 /* */ 11393 /* Mikko Mononen: compound shape support, more cmap formats */ 11394 /* Tor Andersson: kerning, subpixel rendering */ 11395 /* Dougall Johnson: OpenType / Type 2 font handling */ 11396 /* Daniel Ribeiro Maciel: basic GPOS-based kerning */ 11397 /* */ 11398 /* Misc other: */ 11399 /* Ryan Gordon */ 11400 /* Simon Glass */ 11401 /* github:IntellectualKitty */ 11402 /* Imanol Celaya */ 11403 /* Daniel Ribeiro Maciel */ 11404 /* */ 11405 /* Bug/warning reports/fixes: */ 11406 /* "Zer" on mollyrocket Fabian "ryg" Giesen github:NiLuJe */ 11407 /* Cass Everitt Martins Mozeiko github:aloucks */ 11408 /* stoiko (Haemimont Games) Cap Petschulat github:oyvindjam */ 11409 /* Brian Hook Omar Cornut github:vassvik */ 11410 /* Walter van Niftrik Ryan Griege */ 11411 /* David Gow Peter LaValle */ 11412 /* David Given Sergey Popov */ 11413 /* Ivan-Assen Ivanov Giumo X. Clanjor */ 11414 /* Anthony Pesch Higor Euripedes */ 11415 /* Johan Duparc Thomas Fields */ 11416 /* Hou Qiming Derek Vinyard */ 11417 /* Rob Loach Cort Stratton */ 11418 /* Kenney Phillis Jr. Brian Costabile */ 11419 /* Ken Voskuil (kaesve) */ 11420 /* */ 11421 /* VERSION HISTORY */ 11422 /* */ 11423 /* 1.26 (2021-08-28) fix broken rasterizer */ 11424 /* 1.25 (2021-07-11) many fixes */ 11425 /* 1.24 (2020-02-05) fix warning */ 11426 /* 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) */ 11427 /* 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined */ 11428 /* 1.21 (2019-02-25) fix warning */ 11429 /* 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() */ 11430 /* 1.19 (2018-02-11) GPOS kerning, STBTT_fmod */ 11431 /* 1.18 (2018-01-29) add missing function */ 11432 /* 1.17 (2017-07-23) make more arguments const; doc fix */ 11433 /* 1.16 (2017-07-12) SDF support */ 11434 /* 1.15 (2017-03-03) make more arguments const */ 11435 /* 1.14 (2017-01-16) num-fonts-in-TTC function */ 11436 /* 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts */ 11437 /* 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual */ 11438 /* 1.11 (2016-04-02) fix unused-variable warning */ 11439 /* 1.10 (2016-04-02) user-defined fabs(); rare memory leak; remove duplicate typedef */ 11440 /* 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use allocation userdata properly */ 11441 /* 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges */ 11442 /* 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; */ 11443 /* variant PackFontRanges to pack and render in separate phases; */ 11444 /* fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); */ 11445 /* fixed an assert() bug in the new rasterizer */ 11446 /* replace assert() with STBTT_assert() in new rasterizer */ 11447 /* */ 11448 /* Full history can be found at the end of this file. */ 11449 /* */ 11450 /* LICENSE */ 11451 /* */ 11452 /* See end of file for license information. */ 11453 /* */ 11454 /* USAGE */ 11455 /* */ 11456 /* Include this file in whatever places need to refer to it. In ONE C/C++ */ 11457 /* file, write: */ 11458 /* #define STB_TRUETYPE_IMPLEMENTATION */ 11459 /* before the #include of this file. This expands out the actual */ 11460 /* implementation into that C/C++ file. */ 11461 /* */ 11462 /* To make the implementation private to the file that generates the implementation, */ 11463 /* #define STBTT_STATIC */ 11464 /* */ 11465 /* Simple 3D API (don't ship this, but it's fine for tools and quick start) */ 11466 /* stbtt_BakeFontBitmap() -- bake a font to a bitmap for use as texture */ 11467 /* stbtt_GetBakedQuad() -- compute quad to draw for a given char */ 11468 /* */ 11469 /* Improved 3D API (more shippable): */ 11470 /* #include "stb_rect_pack.h" -- optional, but you really want it */ 11471 /* stbtt_PackBegin() */ 11472 /* stbtt_PackSetOversampling() -- for improved quality on small fonts */ 11473 /* stbtt_PackFontRanges() -- pack and renders */ 11474 /* stbtt_PackEnd() */ 11475 /* stbtt_GetPackedQuad() */ 11476 /* */ 11477 /* "Load" a font file from a memory buffer (you have to keep the buffer loaded) */ 11478 /* stbtt_InitFont() */ 11479 /* stbtt_GetFontOffsetForIndex() -- indexing for TTC font collections */ 11480 /* stbtt_GetNumberOfFonts() -- number of fonts for TTC font collections */ 11481 /* */ 11482 /* Render a unicode codepoint to a bitmap */ 11483 /* stbtt_GetCodepointBitmap() -- allocates and returns a bitmap */ 11484 /* stbtt_MakeCodepointBitmap() -- renders into bitmap you provide */ 11485 /* stbtt_GetCodepointBitmapBox() -- how big the bitmap must be */ 11486 /* */ 11487 /* Character advance/positioning */ 11488 /* stbtt_GetCodepointHMetrics() */ 11489 /* stbtt_GetFontVMetrics() */ 11490 /* stbtt_GetFontVMetricsOS2() */ 11491 /* stbtt_GetCodepointKernAdvance() */ 11492 /* */ 11493 /* Starting with version 1.06, the rasterizer was replaced with a new, */ 11494 /* faster and generally-more-precise rasterizer. The new rasterizer more */ 11495 /* accurately measures pixel coverage for anti-aliasing, except in the case */ 11496 /* where multiple shapes overlap, in which case it overestimates the AA pixel */ 11497 /* coverage. Thus, anti-aliasing of intersecting shapes may look wrong. If */ 11498 /* this turns out to be a problem, you can re-enable the old rasterizer with */ 11499 /* #define STBTT_RASTERIZER_VERSION 1 */ 11500 /* which will incur about a 15% speed hit. */ 11501 /* */ 11502 /* ADDITIONAL DOCUMENTATION */ 11503 /* */ 11504 /* Immediately after this block comment are a series of sample programs. */ 11505 /* */ 11506 /* After the sample programs is the "header file" section. This section */ 11507 /* includes documentation for each API function. */ 11508 /* */ 11509 /* Some important concepts to understand to use this library: */ 11510 /* */ 11511 /* Codepoint */ 11512 /* Characters are defined by unicode codepoints, e.g. 65 is */ 11513 /* uppercase A, 231 is lowercase c with a cedilla, 0x7e30 is */ 11514 /* the hiragana for "ma". */ 11515 /* */ 11516 /* Glyph */ 11517 /* A visual character shape (every codepoint is rendered as */ 11518 /* some glyph) */ 11519 /* */ 11520 /* Glyph index */ 11521 /* A font-specific integer ID representing a glyph */ 11522 /* */ 11523 /* Baseline */ 11524 /* Glyph shapes are defined relative to a baseline, which is the */ 11525 /* bottom of uppercase characters. Characters extend both above */ 11526 /* and below the baseline. */ 11527 /* */ 11528 /* Current Point */ 11529 /* As you draw text to the screen, you keep track of a "current point" */ 11530 /* which is the origin of each character. The current point's vertical */ 11531 /* position is the baseline. Even "baked fonts" use this model. */ 11532 /* */ 11533 /* Vertical Font Metrics */ 11534 /* The vertical qualities of the font, used to vertically position */ 11535 /* and space the characters. See docs for stbtt_GetFontVMetrics. */ 11536 /* */ 11537 /* Font Size in Pixels or Points */ 11538 /* The preferred interface for specifying font sizes in stb_truetype */ 11539 /* is to specify how tall the font's vertical extent should be in pixels. */ 11540 /* If that sounds good enough, skip the next paragraph. */ 11541 /* */ 11542 /* Most font APIs instead use "points", which are a common typographic */ 11543 /* measurement for describing font size, defined as 72 points per inch. */ 11544 /* stb_truetype provides a point API for compatibility. However, true */ 11545 /* "per inch" conventions don't make much sense on computer displays */ 11546 /* since different monitors have different number of pixels per */ 11547 /* inch. For example, Windows traditionally uses a convention that */ 11548 /* there are 96 pixels per inch, thus making 'inch' measurements have */ 11549 /* nothing to do with inches, and thus effectively defining a point to */ 11550 /* be 1.333 pixels. Additionally, the TrueType font data provides */ 11551 /* an explicit scale factor to scale a given font's glyphs to points, */ 11552 /* but the author has observed that this scale factor is often wrong */ 11553 /* for non-commercial fonts, thus making fonts scaled in points */ 11554 /* according to the TrueType spec incoherently sized in practice. */ 11555 /* */ 11556 /* DETAILED USAGE: */ 11557 /* */ 11558 /* Scale: */ 11559 /* Select how high you want the font to be, in points or pixels. */ 11560 /* Call ScaleForPixelHeight or ScaleForMappingEmToPixels to compute */ 11561 /* a scale factor SF that will be used by all other functions. */ 11562 /* */ 11563 /* Baseline: */ 11564 /* You need to select a y-coordinate that is the baseline of where */ 11565 /* your text will appear. Call GetFontBoundingBox to get the baseline-relative */ 11566 /* bounding box for all characters. SF*-y0 will be the distance in pixels */ 11567 /* that the worst-case character could extend above the baseline, so if */ 11568 /* you want the top edge of characters to appear at the top of the */ 11569 /* screen where y=0, then you would set the baseline to SF*-y0. */ 11570 /* */ 11571 /* Current point: */ 11572 /* Set the current point where the first character will appear. The */ 11573 /* first character could extend left of the current point; this is font */ 11574 /* dependent. You can either choose a current point that is the leftmost */ 11575 /* point and hope, or add some padding, or check the bounding box or */ 11576 /* left-side-bearing of the first character to be displayed and set */ 11577 /* the current point based on that. */ 11578 /* */ 11579 /* Displaying a character: */ 11580 /* Compute the bounding box of the character. It will contain signed values */ 11581 /* relative to <current_point, baseline>. I.e. if it returns x0,y0,x1,y1, */ 11582 /* then the character should be displayed in the rectangle from */ 11583 /* <current_point+SF*x0, baseline+SF*y0> to <current_point+SF*x1,baseline+SF*y1). */ 11584 /* */ 11585 /* Advancing for the next character: */ 11586 /* Call GlyphHMetrics, and compute 'current_point += SF * advance'. */ 11587 /* */ 11588 /* */ 11589 /* ADVANCED USAGE */ 11590 /* */ 11591 /* Quality: */ 11592 /* */ 11593 /* - Use the functions with Subpixel at the end to allow your characters */ 11594 /* to have subpixel positioning. Since the font is anti-aliased, not */ 11595 /* hinted, this is very import for quality. (This is not possible with */ 11596 /* baked fonts.) */ 11597 /* */ 11598 /* - Kerning is now supported, and if you're supporting subpixel rendering */ 11599 /* then kerning is worth using to give your text a polished look. */ 11600 /* */ 11601 /* Performance: */ 11602 /* */ 11603 /* - Convert Unicode codepoints to glyph indexes and operate on the glyphs; */ 11604 /* if you don't do this, stb_truetype is forced to do the conversion on */ 11605 /* every call. */ 11606 /* */ 11607 /* - There are a lot of memory allocations. We should modify it to take */ 11608 /* a temp buffer and allocate from the temp buffer (without freeing), */ 11609 /* should help performance a lot. */ 11610 /* */ 11611 /* NOTES */ 11612 /* */ 11613 /* The system uses the raw data found in the .ttf file without changing it */ 11614 /* and without building auxiliary data structures. This is a bit inefficient */ 11615 /* on little-endian systems (the data is big-endian), but assuming you're */ 11616 /* caching the bitmaps or glyph shapes this shouldn't be a big deal. */ 11617 /* */ 11618 /* It appears to be very hard to programmatically determine what font a */ 11619 /* given file is in a general way. I provide an API for this, but I don't */ 11620 /* recommend it. */ 11621 /* */ 11622 /* */ 11623 /* PERFORMANCE MEASUREMENTS FOR 1.06: */ 11624 /* */ 11625 /* 32-bit 64-bit */ 11626 /* Previous release: 8.83 s 7.68 s */ 11627 /* Pool allocations: 7.72 s 6.34 s */ 11628 /* Inline sort : 6.54 s 5.65 s */ 11629 /* New rasterizer : 5.63 s 5.00 s */ 11630 11631 /* //////////////////////////////////////////////////////////////////////////// */ 11632 /* //////////////////////////////////////////////////////////////////////////// */ 11633 /* // */ 11634 /* // SAMPLE PROGRAMS */ 11635 /* // */ 11636 /* */ 11637 /* Incomplete text-in-3d-api example, which draws quads properly aligned to be lossless. */ 11638 /* See "tests/truetype_demo_win32.c" for a complete version. */ 11639 #if 0 11640 #define STB_TRUETYPE_IMPLEMENTATION /* force following include to generate implementation */ 11641 #include "stb_truetype.h" 11642 11643 unsigned char ttf_buffer[1<<20]; 11644 unsigned char temp_bitmap[512*512]; 11645 11646 stbtt_bakedchar cdata[96]; /* ASCII 32..126 is 95 glyphs */ 11647 GLuint ftex; 11648 11649 void my_stbtt_initfont(void) 11650 { 11651 fread(ttf_buffer, 1, 1<<20, fopen("c:/windows/fonts/times.ttf", "rb")); 11652 stbtt_BakeFontBitmap(ttf_buffer,0, 32.0, temp_bitmap,512,512, 32,96, cdata); /* no guarantee this fits! */ 11653 /* can free ttf_buffer at this point */ 11654 glGenTextures(1, &ftex); 11655 glBindTexture(GL_TEXTURE_2D, ftex); 11656 glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, 512,512, 0, GL_ALPHA, GL_UNSIGNED_BYTE, temp_bitmap); 11657 /* can free temp_bitmap at this point */ 11658 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); 11659 } 11660 11661 void my_stbtt_print(float x, float y, char *text) 11662 { 11663 /* assume orthographic projection with units = screen pixels, origin at top left */ 11664 glEnable(GL_BLEND); 11665 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 11666 glEnable(GL_TEXTURE_2D); 11667 glBindTexture(GL_TEXTURE_2D, ftex); 11668 glBegin(GL_QUADS); 11669 while (*text) { 11670 if (*text >= 32 && *text < 128) { 11671 stbtt_aligned_quad q; 11672 stbtt_GetBakedQuad(cdata, 512,512, *text-32, &x,&y,&q,1);/* 1=opengl & d3d10+,0=d3d9 */ 11673 glTexCoord2f(q.s0,q.t0); glVertex2f(q.x0,q.y0); 11674 glTexCoord2f(q.s1,q.t0); glVertex2f(q.x1,q.y0); 11675 glTexCoord2f(q.s1,q.t1); glVertex2f(q.x1,q.y1); 11676 glTexCoord2f(q.s0,q.t1); glVertex2f(q.x0,q.y1); 11677 } 11678 ++text; 11679 } 11680 glEnd(); 11681 } 11682 #endif 11683 /* */ 11684 /* */ 11685 /* //////////////////////////////////////////////////////////////////////////// */ 11686 /* */ 11687 /* Complete program (this compiles): get a single bitmap, print as ASCII art */ 11688 /* */ 11689 #if 0 11690 #include <stdio.h> 11691 #define STB_TRUETYPE_IMPLEMENTATION /* force following include to generate implementation */ 11692 #include "stb_truetype.h" 11693 11694 char ttf_buffer[1<<25]; 11695 11696 int main(int argc, char **argv) 11697 { 11698 stbtt_fontinfo font; 11699 unsigned char *bitmap; 11700 int w,h,i,j,c = (argc > 1 ? atoi(argv[1]) : 'a'), s = (argc > 2 ? atoi(argv[2]) : 20); 11701 11702 fread(ttf_buffer, 1, 1<<25, fopen(argc > 3 ? argv[3] : "c:/windows/fonts/arialbd.ttf", "rb")); 11703 11704 stbtt_InitFont(&font, ttf_buffer, stbtt_GetFontOffsetForIndex(ttf_buffer,0)); 11705 bitmap = stbtt_GetCodepointBitmap(&font, 0,stbtt_ScaleForPixelHeight(&font, s), c, &w, &h, 0,0); 11706 11707 for (j=0; j < h; ++j) { 11708 for (i=0; i < w; ++i) 11709 putchar(" .:ioVM@"[bitmap[j*w+i]>>5]); 11710 putchar('\n'); 11711 } 11712 return 0; 11713 } 11714 #endif 11715 /* */ 11716 /* Output: */ 11717 /* */ 11718 /* .ii. */ 11719 /* @@@@@@. */ 11720 /* V@Mio@@o */ 11721 /* :i. V@V */ 11722 /* :oM@@M */ 11723 /* :@@@MM@M */ 11724 /* @@o o@M */ 11725 /* :@@. M@M */ 11726 /* @@@o@@@@ */ 11727 /* :M@@V:@@. */ 11728 /* */ 11729 /* //////////////////////////////////////////////////////////////////////////// */ 11730 /* */ 11731 /* Complete program: print "Hello World!" banner, with bugs */ 11732 /* */ 11733 #if 0 11734 char buffer[24<<20]; 11735 unsigned char screen[20][79]; 11736 11737 int main(int arg, char **argv) 11738 { 11739 stbtt_fontinfo font; 11740 int i,j,ascent,baseline,ch=0; 11741 float scale, xpos=2; /* leave a little padding in case the character extends left */ 11742 char *text = "Heljo World!"; /* intentionally misspelled to show 'lj' brokenness */ 11743 11744 fread(buffer, 1, 1000000, fopen("c:/windows/fonts/arialbd.ttf", "rb")); 11745 stbtt_InitFont(&font, buffer, 0); 11746 11747 scale = stbtt_ScaleForPixelHeight(&font, 15); 11748 stbtt_GetFontVMetrics(&font, &ascent,0,0); 11749 baseline = (int) (ascent*scale); 11750 11751 while (text[ch]) { 11752 int advance,lsb,x0,y0,x1,y1; 11753 float x_shift = xpos - (float) floor(xpos); 11754 stbtt_GetCodepointHMetrics(&font, text[ch], &advance, &lsb); 11755 stbtt_GetCodepointBitmapBoxSubpixel(&font, text[ch], scale,scale,x_shift,0, &x0,&y0,&x1,&y1); 11756 stbtt_MakeCodepointBitmapSubpixel(&font, &screen[baseline + y0][(int) xpos + x0], x1-x0,y1-y0, 79, scale,scale,x_shift,0, text[ch]); 11757 /* note that this stomps the old data, so where character boxes overlap (e.g. 'lj') it's wrong */ 11758 /* because this API is really for baking character bitmaps into textures. if you want to render */ 11759 /* a sequence of characters, you really need to render each bitmap to a temp buffer, then */ 11760 /* "alpha blend" that into the working buffer */ 11761 xpos += (advance * scale); 11762 if (text[ch+1]) 11763 xpos += scale*stbtt_GetCodepointKernAdvance(&font, text[ch],text[ch+1]); 11764 ++ch; 11765 } 11766 11767 for (j=0; j < 20; ++j) { 11768 for (i=0; i < 78; ++i) 11769 putchar(" .:ioVM@"[screen[j][i]>>5]); 11770 putchar('\n'); 11771 } 11772 11773 return 0; 11774 } 11775 #endif 11776 11777 11778 /* //////////////////////////////////////////////////////////////////////////// */ 11779 /* //////////////////////////////////////////////////////////////////////////// */ 11780 /* // */ 11781 /* // INTEGRATION WITH YOUR CODEBASE */ 11782 /* // */ 11783 /* // The following sections allow you to supply alternate definitions */ 11784 /* // of C library functions used by stb_truetype, e.g. if you don't */ 11785 /* // link with the C runtime library. */ 11786 11787 #ifdef STB_TRUETYPE_IMPLEMENTATION 11788 /* #define your own (u)stbtt_int8/16/32 before including to override this */ 11789 #ifndef stbtt_uint8 11790 typedef unsigned char stbtt_uint8; 11791 typedef signed char stbtt_int8; 11792 typedef unsigned short stbtt_uint16; 11793 typedef signed short stbtt_int16; 11794 typedef unsigned int stbtt_uint32; 11795 typedef signed int stbtt_int32; 11796 #endif 11797 11798 typedef char stbtt__check_size32[sizeof(stbtt_int32)==4 ? 1 : -1]; 11799 typedef char stbtt__check_size16[sizeof(stbtt_int16)==2 ? 1 : -1]; 11800 11801 /* e.g. #define your own STBTT_ifloor/STBTT_iceil() to avoid math.h */ 11802 #ifndef STBTT_ifloor 11803 #include <math.h> 11804 #define STBTT_ifloor(x) ((int) floor(x)) 11805 #define STBTT_iceil(x) ((int) ceil(x)) 11806 #endif 11807 11808 #ifndef STBTT_sqrt 11809 #include <math.h> 11810 #define STBTT_sqrt(x) sqrt(x) 11811 #define STBTT_pow(x,y) pow(x,y) 11812 #endif 11813 11814 #ifndef STBTT_fmod 11815 #include <math.h> 11816 #define STBTT_fmod(x,y) fmod(x,y) 11817 #endif 11818 11819 #ifndef STBTT_cos 11820 #include <math.h> 11821 #define STBTT_cos(x) cos(x) 11822 #define STBTT_acos(x) acos(x) 11823 #endif 11824 11825 #ifndef STBTT_fabs 11826 #include <math.h> 11827 #define STBTT_fabs(x) fabs(x) 11828 #endif 11829 11830 /* #define your own functions "STBTT_malloc" / "STBTT_free" to avoid malloc.h */ 11831 #ifndef STBTT_malloc 11832 #include <stdlib.h> 11833 #define STBTT_malloc(x,u) ((void)(u),malloc(x)) 11834 #define STBTT_free(x,u) ((void)(u),free(x)) 11835 #endif 11836 11837 #ifndef STBTT_assert 11838 #include <assert.h> 11839 #define STBTT_assert(x) assert(x) 11840 #endif 11841 11842 #ifndef STBTT_strlen 11843 #include <string.h> 11844 #define STBTT_strlen(x) strlen(x) 11845 #endif 11846 11847 #ifndef STBTT_memcpy 11848 #include <string.h> 11849 #define STBTT_memcpy memcpy 11850 #define STBTT_memset memset 11851 #endif 11852 #endif 11853 11854 /* ///////////////////////////////////////////////////////////////////////////// */ 11855 /* ///////////////////////////////////////////////////////////////////////////// */ 11856 /* // */ 11857 /* // INTERFACE */ 11858 /* // */ 11859 /* // */ 11860 11861 #ifndef __STB_INCLUDE_STB_TRUETYPE_H__ 11862 #define __STB_INCLUDE_STB_TRUETYPE_H__ 11863 11864 #ifdef STBTT_STATIC 11865 #define STBTT_DEF static 11866 #else 11867 #define STBTT_DEF extern 11868 #endif 11869 11870 #ifdef __cplusplus 11871 extern "C" { 11872 #endif 11873 11874 /* private structure */ 11875 typedef struct 11876 { 11877 unsigned char *data; 11878 int cursor; 11879 int size; 11880 } stbtt__buf; 11881 11882 /* //////////////////////////////////////////////////////////////////////////// */ 11883 /* */ 11884 /* TEXTURE BAKING API */ 11885 /* */ 11886 /* If you use this API, you only have to call two functions ever. */ 11887 /* */ 11888 11889 typedef struct 11890 { 11891 unsigned short x0,y0,x1,y1; /* coordinates of bbox in bitmap */ 11892 float xoff,yoff,xadvance; 11893 } stbtt_bakedchar; 11894 11895 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, /* font location (use offset=0 for plain .ttf) */ 11896 float pixel_height, /* height of font in pixels */ 11897 unsigned char *pixels, int pw, int ph, /* bitmap to be filled in */ 11898 int first_char, int num_chars, /* characters to bake */ 11899 stbtt_bakedchar *chardata); /* you allocate this, it's num_chars long */ 11900 /* if return is positive, the first unused row of the bitmap */ 11901 /* if return is negative, returns the negative of the number of characters that fit */ 11902 /* if return is 0, no characters fit and no rows were used */ 11903 /* This uses a very crappy packing. */ 11904 11905 typedef struct 11906 { 11907 float x0,y0,s0,t0; /* top-left */ 11908 float x1,y1,s1,t1; /* bottom-right */ 11909 } stbtt_aligned_quad; 11910 11911 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, /* same data as above */ 11912 int char_index, /* character to display */ 11913 float *xpos, float *ypos, /* pointers to current position in screen pixel space */ 11914 stbtt_aligned_quad *q, /* output: quad to draw */ 11915 int opengl_fillrule); /* true if opengl fill rule; false if DX9 or earlier */ 11916 /* Call GetBakedQuad with char_index = 'character - first_char', and it */ 11917 /* creates the quad you need to draw and advances the current position. */ 11918 /* */ 11919 /* The coordinate system used assumes y increases downwards. */ 11920 /* */ 11921 /* Characters will extend both above and below the current position; */ 11922 /* see discussion of "BASELINE" above. */ 11923 /* */ 11924 /* It's inefficient; you might want to c&p it and optimize it. */ 11925 11926 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap); 11927 /* Query the font vertical metrics without having to create a font first. */ 11928 11929 11930 /* //////////////////////////////////////////////////////////////////////////// */ 11931 /* */ 11932 /* NEW TEXTURE BAKING API */ 11933 /* */ 11934 /* This provides options for packing multiple fonts into one atlas, not */ 11935 /* perfectly but better than nothing. */ 11936 11937 typedef struct 11938 { 11939 unsigned short x0,y0,x1,y1; /* coordinates of bbox in bitmap */ 11940 float xoff,yoff,xadvance; 11941 float xoff2,yoff2; 11942 } stbtt_packedchar; 11943 11944 typedef struct stbtt_pack_context stbtt_pack_context; 11945 typedef struct stbtt_fontinfo stbtt_fontinfo; 11946 #ifndef STB_RECT_PACK_VERSION 11947 typedef struct stbrp_rect stbrp_rect; 11948 #endif 11949 11950 STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int width, int height, int stride_in_bytes, int padding, void *alloc_context); 11951 /* Initializes a packing context stored in the passed-in stbtt_pack_context. */ 11952 /* Future calls using this context will pack characters into the bitmap passed */ 11953 /* in here: a 1-channel bitmap that is width * height. stride_in_bytes is */ 11954 /* the distance from one row to the next (or 0 to mean they are packed tightly */ 11955 /* together). "padding" is the amount of padding to leave between each */ 11956 /* character (normally you want '1' for bitmaps you'll use as textures with */ 11957 /* bilinear filtering). */ 11958 /* */ 11959 /* Returns 0 on failure, 1 on success. */ 11960 11961 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc); 11962 /* Cleans up the packing context and frees all memory. */ 11963 11964 #define STBTT_POINT_SIZE(x) (-(x)) 11965 11966 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, 11967 int first_unicode_char_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range); 11968 /* Creates character bitmaps from the font_index'th font found in fontdata (use */ 11969 /* font_index=0 if you don't know what that is). It creates num_chars_in_range */ 11970 /* bitmaps for characters with unicode values starting at first_unicode_char_in_range */ 11971 /* and increasing. Data for how to render them is stored in chardata_for_range; */ 11972 /* pass these to stbtt_GetPackedQuad to get back renderable quads. */ 11973 /* */ 11974 /* font_size is the full height of the character from ascender to descender, */ 11975 /* as computed by stbtt_ScaleForPixelHeight. To use a point size as computed */ 11976 /* by stbtt_ScaleForMappingEmToPixels, wrap the point size in STBTT_POINT_SIZE() */ 11977 /* and pass that result as 'font_size': */ 11978 /* ..., 20 , ... // font max minus min y is 20 pixels tall */ 11979 /* ..., STBTT_POINT_SIZE(20), ... // 'M' is 20 pixels tall */ 11980 11981 typedef struct 11982 { 11983 float font_size; 11984 int first_unicode_codepoint_in_range; /* if non-zero, then the chars are continuous, and this is the first codepoint */ 11985 int *array_of_unicode_codepoints; /* if non-zero, then this is an array of unicode codepoints */ 11986 int num_chars; 11987 stbtt_packedchar *chardata_for_range; /* output */ 11988 unsigned char h_oversample, v_oversample; /* don't set these, they're used internally */ 11989 } stbtt_pack_range; 11990 11991 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges); 11992 /* Creates character bitmaps from multiple ranges of characters stored in */ 11993 /* ranges. This will usually create a better-packed bitmap than multiple */ 11994 /* calls to stbtt_PackFontRange. Note that you can call this multiple */ 11995 /* times within a single PackBegin/PackEnd. */ 11996 11997 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample); 11998 /* Oversampling a font increases the quality by allowing higher-quality subpixel */ 11999 /* positioning, and is especially valuable at smaller text sizes. */ 12000 /* */ 12001 /* This function sets the amount of oversampling for all following calls to */ 12002 /* stbtt_PackFontRange(s) or stbtt_PackFontRangesGatherRects for a given */ 12003 /* pack context. The default (no oversampling) is achieved by h_oversample=1 */ 12004 /* and v_oversample=1. The total number of pixels required is */ 12005 /* h_oversample*v_oversample larger than the default; for example, 2x2 */ 12006 /* oversampling requires 4x the storage of 1x1. For best results, render */ 12007 /* oversampled textures with bilinear filtering. Look at the readme in */ 12008 /* stb/tests/oversample for information about oversampled fonts */ 12009 /* */ 12010 /* To use with PackFontRangesGather etc., you must set it before calls */ 12011 /* call to PackFontRangesGatherRects. */ 12012 12013 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip); 12014 /* If skip != 0, this tells stb_truetype to skip any codepoints for which */ 12015 /* there is no corresponding glyph. If skip=0, which is the default, then */ 12016 /* codepoints without a glyph recived the font's "missing character" glyph, */ 12017 /* typically an empty box by convention. */ 12018 12019 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, /* same data as above */ 12020 int char_index, /* character to display */ 12021 float *xpos, float *ypos, /* pointers to current position in screen pixel space */ 12022 stbtt_aligned_quad *q, /* output: quad to draw */ 12023 int align_to_integer); 12024 12025 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); 12026 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects); 12027 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects); 12028 /* Calling these functions in sequence is roughly equivalent to calling */ 12029 /* stbtt_PackFontRanges(). If you more control over the packing of multiple */ 12030 /* fonts, or if you want to pack custom data into a font texture, take a look */ 12031 /* at the source to of stbtt_PackFontRanges() and create a custom version */ 12032 /* using these functions, e.g. call GatherRects multiple times, */ 12033 /* building up a single array of rects, then call PackRects once, */ 12034 /* then call RenderIntoRects repeatedly. This may result in a */ 12035 /* better packing than calling PackFontRanges multiple times */ 12036 /* (or it may not). */ 12037 12038 /* this is an opaque structure that you shouldn't mess with which holds */ 12039 /* all the context needed from PackBegin to PackEnd. */ 12040 struct stbtt_pack_context { 12041 void *user_allocator_context; 12042 void *pack_info; 12043 int width; 12044 int height; 12045 int stride_in_bytes; 12046 int padding; 12047 int skip_missing; 12048 unsigned int h_oversample, v_oversample; 12049 unsigned char *pixels; 12050 void *nodes; 12051 }; 12052 12053 /* //////////////////////////////////////////////////////////////////////////// */ 12054 /* */ 12055 /* FONT LOADING */ 12056 /* */ 12057 /* */ 12058 12059 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data); 12060 /* This function will determine the number of fonts in a font file. TrueType */ 12061 /* collection (.ttc) files may contain multiple fonts, while TrueType font */ 12062 /* (.ttf) files only contain one font. The number of fonts can be used for */ 12063 /* indexing with the previous function where the index is between zero and one */ 12064 /* less than the total fonts. If an error occurs, -1 is returned. */ 12065 12066 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index); 12067 /* Each .ttf/.ttc file may have more than one font. Each font has a sequential */ 12068 /* index number starting from 0. Call this function to get the font offset for */ 12069 /* a given index; it returns -1 if the index is out of range. A regular .ttf */ 12070 /* file will only define one font and it always be at offset 0, so it will */ 12071 /* return '0' for index 0, and -1 for all other indices. */ 12072 12073 /* The following structure is defined publicly so you can declare one on */ 12074 /* the stack or as a global or etc, but you should treat it as opaque. */ 12075 struct stbtt_fontinfo 12076 { 12077 void * userdata; 12078 unsigned char * data; /* pointer to .ttf file */ 12079 int fontstart; /* offset of start of font */ 12080 12081 int numGlyphs; /* number of glyphs, needed for range checking */ 12082 12083 int loca,head,glyf,hhea,hmtx,kern,gpos,svg; /* table locations as offset from start of .ttf */ 12084 int index_map; /* a cmap mapping for our chosen character encoding */ 12085 int indexToLocFormat; /* format needed to map from glyph index to glyph */ 12086 12087 stbtt__buf cff; /* cff font data */ 12088 stbtt__buf charstrings; /* the charstring index */ 12089 stbtt__buf gsubrs; /* global charstring subroutines index */ 12090 stbtt__buf subrs; /* private charstring subroutines index */ 12091 stbtt__buf fontdicts; /* array of font dicts */ 12092 stbtt__buf fdselect; /* map from glyph to fontdict */ 12093 }; 12094 12095 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset); 12096 /* Given an offset into the file that defines a font, this function builds */ 12097 /* the necessary cached info for the rest of the system. You must allocate */ 12098 /* the stbtt_fontinfo yourself, and stbtt_InitFont will fill it out. You don't */ 12099 /* need to do anything special to free it, because the contents are pure */ 12100 /* value data with no additional data structures. Returns 0 on failure. */ 12101 12102 12103 /* //////////////////////////////////////////////////////////////////////////// */ 12104 /* */ 12105 /* CHARACTER TO GLYPH-INDEX CONVERSIOn */ 12106 12107 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint); 12108 /* If you're going to perform multiple operations on the same character */ 12109 /* and you want a speed-up, call this function with the character you're */ 12110 /* going to process, then use glyph-based functions instead of the */ 12111 /* codepoint-based functions. */ 12112 /* Returns 0 if the character codepoint is not defined in the font. */ 12113 12114 12115 /* //////////////////////////////////////////////////////////////////////////// */ 12116 /* */ 12117 /* CHARACTER PROPERTIES */ 12118 /* */ 12119 12120 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float pixels); 12121 /* computes a scale factor to produce a font whose "height" is 'pixels' tall. */ 12122 /* Height is measured as the distance from the highest ascender to the lowest */ 12123 /* descender; in other words, it's equivalent to calling stbtt_GetFontVMetrics */ 12124 /* and computing: */ 12125 /* scale = pixels / (ascent - descent) */ 12126 /* so if you prefer to measure height by the ascent only, use a similar calculation. */ 12127 12128 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels); 12129 /* computes a scale factor to produce a font whose EM size is mapped to */ 12130 /* 'pixels' tall. This is probably what traditional APIs compute, but */ 12131 /* I'm not positive. */ 12132 12133 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap); 12134 /* ascent is the coordinate above the baseline the font extends; descent */ 12135 /* is the coordinate below the baseline the font extends (i.e. it is typically negative) */ 12136 /* lineGap is the spacing between one row's descent and the next row's ascent... */ 12137 /* so you should advance the vertical position by "*ascent - *descent + *lineGap" */ 12138 /* these are expressed in unscaled coordinates, so you must multiply by */ 12139 /* the scale factor for a given size */ 12140 12141 STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap); 12142 /* analogous to GetFontVMetrics, but returns the "typographic" values from the OS/2 */ 12143 /* table (specific to MS/Windows TTF files). */ 12144 /* */ 12145 /* Returns 1 on success (table present), 0 on failure. */ 12146 12147 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1); 12148 /* the bounding box around all possible characters */ 12149 12150 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing); 12151 /* leftSideBearing is the offset from the current horizontal position to the left edge of the character */ 12152 /* advanceWidth is the offset from the current horizontal position to the next horizontal position */ 12153 /* these are expressed in unscaled coordinates */ 12154 12155 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2); 12156 /* an additional amount to add to the 'advance' value between ch1 and ch2 */ 12157 12158 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1); 12159 /* Gets the bounding box of the visible part of the glyph, in unscaled coordinates */ 12160 12161 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing); 12162 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2); 12163 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); 12164 /* as above, but takes one or more glyph indices for greater efficiency */ 12165 12166 typedef struct stbtt_kerningentry 12167 { 12168 int glyph1; /* use stbtt_FindGlyphIndex */ 12169 int glyph2; 12170 int advance; 12171 } stbtt_kerningentry; 12172 12173 STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info); 12174 STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length); 12175 /* Retrieves a complete list of all of the kerning pairs provided by the font */ 12176 /* stbtt_GetKerningTable never writes more than table_length entries and returns how many entries it did write. */ 12177 /* The table will be sorted by (a.glyph1 == b.glyph1)?(a.glyph2 < b.glyph2):(a.glyph1 < b.glyph1) */ 12178 12179 /* //////////////////////////////////////////////////////////////////////////// */ 12180 /* */ 12181 /* GLYPH SHAPES (you probably don't need these, but they have to go before */ 12182 /* the bitmaps for C declaration-order reasons) */ 12183 /* */ 12184 12185 #ifndef STBTT_vmove /* you can predefine these to use different values (but why?) */ 12186 enum { 12187 STBTT_vmove=1, 12188 STBTT_vline, 12189 STBTT_vcurve, 12190 STBTT_vcubic 12191 }; 12192 #endif 12193 12194 #ifndef stbtt_vertex /* you can predefine this to use different values */ 12195 /* (we share this with other code at RAD) */ 12196 #define stbtt_vertex_type short /* can't use stbtt_int16 because that's not visible in the header file */ 12197 typedef struct 12198 { 12199 stbtt_vertex_type x,y,cx,cy,cx1,cy1; 12200 unsigned char type,padding; 12201 } stbtt_vertex; 12202 #endif 12203 12204 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index); 12205 /* returns non-zero if nothing is drawn for this glyph */ 12206 12207 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices); 12208 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **vertices); 12209 /* returns # of vertices and fills *vertices with the pointer to them */ 12210 /* these are expressed in "unscaled" coordinates */ 12211 /* */ 12212 /* The shape is a series of contours. Each one starts with */ 12213 /* a STBTT_moveto, then consists of a series of mixed */ 12214 /* STBTT_lineto and STBTT_curveto segments. A lineto */ 12215 /* draws a line from previous endpoint to its x,y; a curveto */ 12216 /* draws a quadratic bezier from previous endpoint to */ 12217 /* its x,y, using cx,cy as the bezier control point. */ 12218 12219 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *vertices); 12220 /* frees the data allocated above */ 12221 12222 STBTT_DEF unsigned char *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl); 12223 STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg); 12224 STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg); 12225 /* fills svg with the character's SVG data. */ 12226 /* returns data size or 0 if SVG not found. */ 12227 12228 /* //////////////////////////////////////////////////////////////////////////// */ 12229 /* */ 12230 /* BITMAP RENDERING */ 12231 /* */ 12232 12233 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata); 12234 /* frees the bitmap allocated below */ 12235 12236 STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff); 12237 /* allocates a large-enough single-channel 8bpp bitmap and renders the */ 12238 /* specified character/glyph at the specified scale into it, with */ 12239 /* antialiasing. 0 is no coverage (transparent), 255 is fully covered (opaque). */ 12240 /* *width & *height are filled out with the width & height of the bitmap, */ 12241 /* which is stored left-to-right, top-to-bottom. */ 12242 /* */ 12243 /* xoff/yoff are the offset it pixel space from the glyph origin to the top-left of the bitmap */ 12244 12245 STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff); 12246 /* the same as stbtt_GetCodepoitnBitmap, but you can specify a subpixel */ 12247 /* shift for the character */ 12248 12249 STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint); 12250 /* the same as stbtt_GetCodepointBitmap, but you pass in storage for the bitmap */ 12251 /* in the form of 'output', with row spacing of 'out_stride' bytes. the bitmap */ 12252 /* is clipped to out_w/out_h bytes. Call stbtt_GetCodepointBitmapBox to get the */ 12253 /* width and height and positioning info for it first. */ 12254 12255 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint); 12256 /* same as stbtt_MakeCodepointBitmap, but you can specify a subpixel */ 12257 /* shift for the character */ 12258 12259 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint); 12260 /* same as stbtt_MakeCodepointBitmapSubpixel, but prefiltering */ 12261 /* is performed (see stbtt_PackSetOversampling) */ 12262 12263 STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); 12264 /* get the bbox of the bitmap centered around the glyph origin; so the */ 12265 /* bitmap width is ix1-ix0, height is iy1-iy0, and location to place */ 12266 /* the bitmap top left is (leftSideBearing*scale,iy0). */ 12267 /* (Note that the bitmap uses y-increases-down, but the shape uses */ 12268 /* y-increases-up, so CodepointBitmapBox and CodepointBox are inverted.) */ 12269 12270 STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); 12271 /* same as stbtt_GetCodepointBitmapBox, but you can specify a subpixel */ 12272 /* shift for the character */ 12273 12274 /* the following functions are equivalent to the above functions, but operate */ 12275 /* on glyph indices instead of Unicode codepoints (for efficiency) */ 12276 STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff); 12277 STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff); 12278 STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph); 12279 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph); 12280 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int glyph); 12281 STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1); 12282 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1); 12283 12284 12285 /* @TODO: don't expose this structure */ 12286 typedef struct 12287 { 12288 int w,h,stride; 12289 unsigned char *pixels; 12290 } stbtt__bitmap; 12291 12292 /* rasterize a shape with quadratic beziers into a bitmap */ 12293 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, /* 1-channel bitmap to draw into */ 12294 float flatness_in_pixels, /* allowable error of curve in pixels */ 12295 stbtt_vertex *vertices, /* array of vertices defining shape */ 12296 int num_verts, /* number of vertices in above array */ 12297 float scale_x, float scale_y, /* scale applied to input vertices */ 12298 float shift_x, float shift_y, /* translation applied to input vertices */ 12299 int x_off, int y_off, /* another translation applied to input */ 12300 int invert, /* if non-zero, vertically flip shape */ 12301 void *userdata); /* context for to STBTT_MALLOC */ 12302 12303 /* //////////////////////////////////////////////////////////////////////////// */ 12304 /* */ 12305 /* Signed Distance Function (or Field) rendering */ 12306 12307 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata); 12308 /* frees the SDF bitmap allocated below */ 12309 12310 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); 12311 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff); 12312 /* These functions compute a discretized SDF field for a single character, suitable for storing */ 12313 /* in a single-channel texture, sampling with bilinear filtering, and testing against */ 12314 /* larger than some threshold to produce scalable fonts. */ 12315 /* info -- the font */ 12316 /* scale -- controls the size of the resulting SDF bitmap, same as it would be creating a regular bitmap */ 12317 /* glyph/codepoint -- the character to generate the SDF for */ 12318 /* padding -- extra "pixels" around the character which are filled with the distance to the character (not 0), */ 12319 /* which allows effects like bit outlines */ 12320 /* onedge_value -- value 0-255 to test the SDF against to reconstruct the character (i.e. the isocontour of the character) */ 12321 /* pixel_dist_scale -- what value the SDF should increase by when moving one SDF "pixel" away from the edge (on the 0..255 scale) */ 12322 /* if positive, > onedge_value is inside; if negative, < onedge_value is inside */ 12323 /* width,height -- output height & width of the SDF bitmap (including padding) */ 12324 /* xoff,yoff -- output origin of the character */ 12325 /* return value -- a 2D array of bytes 0..255, width*height in size */ 12326 /* */ 12327 /* pixel_dist_scale & onedge_value are a scale & bias that allows you to make */ 12328 /* optimal use of the limited 0..255 for your application, trading off precision */ 12329 /* and special effects. SDF values outside the range 0..255 are clamped to 0..255. */ 12330 /* */ 12331 /* Example: */ 12332 /* scale = stbtt_ScaleForPixelHeight(22) */ 12333 /* padding = 5 */ 12334 /* onedge_value = 180 */ 12335 /* pixel_dist_scale = 180/5.0 = 36.0 */ 12336 /* */ 12337 /* This will create an SDF bitmap in which the character is about 22 pixels */ 12338 /* high but the whole bitmap is about 22+5+5=32 pixels high. To produce a filled */ 12339 /* shape, sample the SDF at each pixel and fill the pixel if the SDF value */ 12340 /* is greater than or equal to 180/255. (You'll actually want to antialias, */ 12341 /* which is beyond the scope of this example.) Additionally, you can compute */ 12342 /* offset outlines (e.g. to stroke the character border inside & outside, */ 12343 /* or only outside). For example, to fill outside the character up to 3 SDF */ 12344 /* pixels, you would compare against (180-36.0*3)/255 = 72/255. The above */ 12345 /* choice of variables maps a range from 5 pixels outside the shape to */ 12346 /* 2 pixels inside the shape to 0..255; this is intended primarily for apply */ 12347 /* outside effects only (the interior range is needed to allow proper */ 12348 /* antialiasing of the font at *smaller* sizes) */ 12349 /* */ 12350 /* The function computes the SDF analytically at each SDF pixel, not by e.g. */ 12351 /* building a higher-res bitmap and approximating it. In theory the quality */ 12352 /* should be as high as possible for an SDF of this size & representation, but */ 12353 /* unclear if this is true in practice (perhaps building a higher-res bitmap */ 12354 /* and computing from that can allow drop-out prevention). */ 12355 /* */ 12356 /* The algorithm has not been optimized at all, so expect it to be slow */ 12357 /* if computing lots of characters or very large sizes. */ 12358 12359 12360 12361 /* //////////////////////////////////////////////////////////////////////////// */ 12362 /* */ 12363 /* Finding the right font... */ 12364 /* */ 12365 /* You should really just solve this offline, keep your own tables */ 12366 /* of what font is what, and don't try to get it out of the .ttf file. */ 12367 /* That's because getting it out of the .ttf file is really hard, because */ 12368 /* the names in the file can appear in many possible encodings, in many */ 12369 /* possible languages, and e.g. if you need a case-insensitive comparison, */ 12370 /* the details of that depend on the encoding & language in a complex way */ 12371 /* (actually underspecified in truetype, but also gigantic). */ 12372 /* */ 12373 /* But you can use the provided functions in two possible ways: */ 12374 /* stbtt_FindMatchingFont() will use *case-sensitive* comparisons on */ 12375 /* unicode-encoded names to try to find the font you want; */ 12376 /* you can run this before calling stbtt_InitFont() */ 12377 /* */ 12378 /* stbtt_GetFontNameString() lets you get any of the various strings */ 12379 /* from the file yourself and do your own comparisons on them. */ 12380 /* You have to have called stbtt_InitFont() first. */ 12381 12382 12383 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags); 12384 /* returns the offset (not index) of the font that matches, or -1 if none */ 12385 /* if you use STBTT_MACSTYLE_DONTCARE, use a font name like "Arial Bold". */ 12386 /* if you use any other flag, use a font name like "Arial"; this checks */ 12387 /* the 'macStyle' header field; i don't know if fonts set this consistently */ 12388 #define STBTT_MACSTYLE_DONTCARE 0 12389 #define STBTT_MACSTYLE_BOLD 1 12390 #define STBTT_MACSTYLE_ITALIC 2 12391 #define STBTT_MACSTYLE_UNDERSCORE 4 12392 #define STBTT_MACSTYLE_NONE 8 /* <= not same as 0, this makes us check the bitfield is 0 */ 12393 12394 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2); 12395 /* returns 1/0 whether the first string interpreted as utf8 is identical to */ 12396 /* the second string interpreted as big-endian utf16... useful for strings from next func */ 12397 12398 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID); 12399 /* returns the string (which may be big-endian double byte, e.g. for unicode) */ 12400 /* and puts the length in bytes in *length. */ 12401 /* */ 12402 /* some of the values for the IDs are below; for more see the truetype spec: */ 12403 /* http://developer.apple.com/textfonts/TTRefMan/RM06/Chap6name.html */ 12404 /* http://www.microsoft.com/typography/otspec/name.htm */ 12405 12406 enum { /* platformID */ 12407 STBTT_PLATFORM_ID_UNICODE =0, 12408 STBTT_PLATFORM_ID_MAC =1, 12409 STBTT_PLATFORM_ID_ISO =2, 12410 STBTT_PLATFORM_ID_MICROSOFT =3 12411 }; 12412 12413 enum { /* encodingID for STBTT_PLATFORM_ID_UNICODE */ 12414 STBTT_UNICODE_EID_UNICODE_1_0 =0, 12415 STBTT_UNICODE_EID_UNICODE_1_1 =1, 12416 STBTT_UNICODE_EID_ISO_10646 =2, 12417 STBTT_UNICODE_EID_UNICODE_2_0_BMP=3, 12418 STBTT_UNICODE_EID_UNICODE_2_0_FULL=4 12419 }; 12420 12421 enum { /* encodingID for STBTT_PLATFORM_ID_MICROSOFT */ 12422 STBTT_MS_EID_SYMBOL =0, 12423 STBTT_MS_EID_UNICODE_BMP =1, 12424 STBTT_MS_EID_SHIFTJIS =2, 12425 STBTT_MS_EID_UNICODE_FULL =10 12426 }; 12427 12428 enum { /* encodingID for STBTT_PLATFORM_ID_MAC; same as Script Manager codes */ 12429 STBTT_MAC_EID_ROMAN =0, STBTT_MAC_EID_ARABIC =4, 12430 STBTT_MAC_EID_JAPANESE =1, STBTT_MAC_EID_HEBREW =5, 12431 STBTT_MAC_EID_CHINESE_TRAD =2, STBTT_MAC_EID_GREEK =6, 12432 STBTT_MAC_EID_KOREAN =3, STBTT_MAC_EID_RUSSIAN =7 12433 }; 12434 12435 enum { /* languageID for STBTT_PLATFORM_ID_MICROSOFT; same as LCID... */ 12436 /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */ 12437 STBTT_MS_LANG_ENGLISH =0x0409, STBTT_MS_LANG_ITALIAN =0x0410, 12438 STBTT_MS_LANG_CHINESE =0x0804, STBTT_MS_LANG_JAPANESE =0x0411, 12439 STBTT_MS_LANG_DUTCH =0x0413, STBTT_MS_LANG_KOREAN =0x0412, 12440 STBTT_MS_LANG_FRENCH =0x040c, STBTT_MS_LANG_RUSSIAN =0x0419, 12441 STBTT_MS_LANG_GERMAN =0x0407, STBTT_MS_LANG_SPANISH =0x0409, 12442 STBTT_MS_LANG_HEBREW =0x040d, STBTT_MS_LANG_SWEDISH =0x041D 12443 }; 12444 12445 enum { /* languageID for STBTT_PLATFORM_ID_MAC */ 12446 STBTT_MAC_LANG_ENGLISH =0 , STBTT_MAC_LANG_JAPANESE =11, 12447 STBTT_MAC_LANG_ARABIC =12, STBTT_MAC_LANG_KOREAN =23, 12448 STBTT_MAC_LANG_DUTCH =4 , STBTT_MAC_LANG_RUSSIAN =32, 12449 STBTT_MAC_LANG_FRENCH =1 , STBTT_MAC_LANG_SPANISH =6 , 12450 STBTT_MAC_LANG_GERMAN =2 , STBTT_MAC_LANG_SWEDISH =5 , 12451 STBTT_MAC_LANG_HEBREW =10, STBTT_MAC_LANG_CHINESE_SIMPLIFIED =33, 12452 STBTT_MAC_LANG_ITALIAN =3 , STBTT_MAC_LANG_CHINESE_TRAD =19 12453 }; 12454 12455 #ifdef __cplusplus 12456 } 12457 #endif 12458 12459 #endif /* __STB_INCLUDE_STB_TRUETYPE_H__ */ 12460 12461 /* ///////////////////////////////////////////////////////////////////////////// */ 12462 /* ///////////////////////////////////////////////////////////////////////////// */ 12463 /* // */ 12464 /* // IMPLEMENTATION */ 12465 /* // */ 12466 /* // */ 12467 12468 #ifdef STB_TRUETYPE_IMPLEMENTATION 12469 12470 #ifndef STBTT_MAX_OVERSAMPLE 12471 #define STBTT_MAX_OVERSAMPLE 8 12472 #endif 12473 12474 #if STBTT_MAX_OVERSAMPLE > 255 12475 #error "STBTT_MAX_OVERSAMPLE cannot be > 255" 12476 #endif 12477 12478 typedef int stbtt__test_oversample_pow2[(STBTT_MAX_OVERSAMPLE & (STBTT_MAX_OVERSAMPLE-1)) == 0 ? 1 : -1]; 12479 12480 #ifndef STBTT_RASTERIZER_VERSION 12481 #define STBTT_RASTERIZER_VERSION 2 12482 #endif 12483 12484 #ifdef _MSC_VER 12485 #define STBTT__NOTUSED(v) (void)(v) 12486 #else 12487 #define STBTT__NOTUSED(v) (void)sizeof(v) 12488 #endif 12489 12490 /* //////////////////////////////////////////////////////////////////////// */ 12491 /* */ 12492 /* stbtt__buf helpers to parse data from file */ 12493 /* */ 12494 12495 static stbtt_uint8 stbtt__buf_get8(stbtt__buf *b) 12496 { 12497 if (b->cursor >= b->size) 12498 return 0; 12499 return b->data[b->cursor++]; 12500 } 12501 12502 static stbtt_uint8 stbtt__buf_peek8(stbtt__buf *b) 12503 { 12504 if (b->cursor >= b->size) 12505 return 0; 12506 return b->data[b->cursor]; 12507 } 12508 12509 static void stbtt__buf_seek(stbtt__buf *b, int o) 12510 { 12511 STBTT_assert(!(o > b->size || o < 0)); 12512 b->cursor = (o > b->size || o < 0) ? b->size : o; 12513 } 12514 12515 static void stbtt__buf_skip(stbtt__buf *b, int o) 12516 { 12517 stbtt__buf_seek(b, b->cursor + o); 12518 } 12519 12520 static stbtt_uint32 stbtt__buf_get(stbtt__buf *b, int n) 12521 { 12522 stbtt_uint32 v = 0; 12523 int i; 12524 STBTT_assert(n >= 1 && n <= 4); 12525 for (i = 0; i < n; i++) 12526 v = (v << 8) | stbtt__buf_get8(b); 12527 return v; 12528 } 12529 12530 static stbtt__buf stbtt__new_buf(const void *p, size_t size) 12531 { 12532 stbtt__buf r; 12533 STBTT_assert(size < 0x40000000); 12534 r.data = (stbtt_uint8*) p; 12535 r.size = (int) size; 12536 r.cursor = 0; 12537 return r; 12538 } 12539 12540 #define stbtt__buf_get16(b) stbtt__buf_get((b), 2) 12541 #define stbtt__buf_get32(b) stbtt__buf_get((b), 4) 12542 12543 static stbtt__buf stbtt__buf_range(const stbtt__buf *b, int o, int s) 12544 { 12545 stbtt__buf r = stbtt__new_buf(NULL, 0); 12546 if (o < 0 || s < 0 || o > b->size || s > b->size - o) return r; 12547 r.data = b->data + o; 12548 r.size = s; 12549 return r; 12550 } 12551 12552 static stbtt__buf stbtt__cff_get_index(stbtt__buf *b) 12553 { 12554 int count, start, offsize; 12555 start = b->cursor; 12556 count = stbtt__buf_get16(b); 12557 if (count) { 12558 offsize = stbtt__buf_get8(b); 12559 STBTT_assert(offsize >= 1 && offsize <= 4); 12560 stbtt__buf_skip(b, offsize * count); 12561 stbtt__buf_skip(b, stbtt__buf_get(b, offsize) - 1); 12562 } 12563 return stbtt__buf_range(b, start, b->cursor - start); 12564 } 12565 12566 static stbtt_uint32 stbtt__cff_int(stbtt__buf *b) 12567 { 12568 int b0 = stbtt__buf_get8(b); 12569 if (b0 >= 32 && b0 <= 246) return b0 - 139; 12570 else if (b0 >= 247 && b0 <= 250) return (b0 - 247)*256 + stbtt__buf_get8(b) + 108; 12571 else if (b0 >= 251 && b0 <= 254) return -(b0 - 251)*256 - stbtt__buf_get8(b) - 108; 12572 else if (b0 == 28) return stbtt__buf_get16(b); 12573 else if (b0 == 29) return stbtt__buf_get32(b); 12574 STBTT_assert(0); 12575 return 0; 12576 } 12577 12578 static void stbtt__cff_skip_operand(stbtt__buf *b) { 12579 int v, b0 = stbtt__buf_peek8(b); 12580 STBTT_assert(b0 >= 28); 12581 if (b0 == 30) { 12582 stbtt__buf_skip(b, 1); 12583 while (b->cursor < b->size) { 12584 v = stbtt__buf_get8(b); 12585 if ((v & 0xF) == 0xF || (v >> 4) == 0xF) 12586 break; 12587 } 12588 } else { 12589 stbtt__cff_int(b); 12590 } 12591 } 12592 12593 static stbtt__buf stbtt__dict_get(stbtt__buf *b, int key) 12594 { 12595 stbtt__buf_seek(b, 0); 12596 while (b->cursor < b->size) { 12597 int start = b->cursor, end, op; 12598 while (stbtt__buf_peek8(b) >= 28) 12599 stbtt__cff_skip_operand(b); 12600 end = b->cursor; 12601 op = stbtt__buf_get8(b); 12602 if (op == 12) op = stbtt__buf_get8(b) | 0x100; 12603 if (op == key) return stbtt__buf_range(b, start, end-start); 12604 } 12605 return stbtt__buf_range(b, 0, 0); 12606 } 12607 12608 static void stbtt__dict_get_ints(stbtt__buf *b, int key, int outcount, stbtt_uint32 *out) 12609 { 12610 int i; 12611 stbtt__buf operands = stbtt__dict_get(b, key); 12612 for (i = 0; i < outcount && operands.cursor < operands.size; i++) 12613 out[i] = stbtt__cff_int(&operands); 12614 } 12615 12616 static int stbtt__cff_index_count(stbtt__buf *b) 12617 { 12618 stbtt__buf_seek(b, 0); 12619 return stbtt__buf_get16(b); 12620 } 12621 12622 static stbtt__buf stbtt__cff_index_get(stbtt__buf b, int i) 12623 { 12624 int count, offsize, start, end; 12625 stbtt__buf_seek(&b, 0); 12626 count = stbtt__buf_get16(&b); 12627 offsize = stbtt__buf_get8(&b); 12628 STBTT_assert(i >= 0 && i < count); 12629 STBTT_assert(offsize >= 1 && offsize <= 4); 12630 stbtt__buf_skip(&b, i*offsize); 12631 start = stbtt__buf_get(&b, offsize); 12632 end = stbtt__buf_get(&b, offsize); 12633 return stbtt__buf_range(&b, 2+(count+1)*offsize+start, end - start); 12634 } 12635 12636 /* //////////////////////////////////////////////////////////////////////// */ 12637 /* */ 12638 /* accessors to parse data from file */ 12639 /* */ 12640 12641 /* on platforms that don't allow misaligned reads, if we want to allow */ 12642 /* truetype fonts that aren't padded to alignment, define ALLOW_UNALIGNED_TRUETYPE */ 12643 12644 #define ttBYTE(p) (* (stbtt_uint8 *) (p)) 12645 #define ttCHAR(p) (* (stbtt_int8 *) (p)) 12646 #define ttFixed(p) ttLONG(p) 12647 12648 static stbtt_uint16 ttUSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } 12649 static stbtt_int16 ttSHORT(stbtt_uint8 *p) { return p[0]*256 + p[1]; } 12650 static stbtt_uint32 ttULONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } 12651 static stbtt_int32 ttLONG(stbtt_uint8 *p) { return (p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]; } 12652 12653 #define stbtt_tag4(p,c0,c1,c2,c3) ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) 12654 #define stbtt_tag(p,str) stbtt_tag4(p,str[0],str[1],str[2],str[3]) 12655 12656 static int stbtt__isfont(stbtt_uint8 *font) 12657 { 12658 /* check the version number */ 12659 if (stbtt_tag4(font, '1',0,0,0)) return 1; /* TrueType 1 */ 12660 if (stbtt_tag(font, "typ1")) return 1; /* TrueType with type 1 font -- we don't support this! */ 12661 if (stbtt_tag(font, "OTTO")) return 1; /* OpenType with CFF */ 12662 if (stbtt_tag4(font, 0,1,0,0)) return 1; /* OpenType 1.0 */ 12663 if (stbtt_tag(font, "true")) return 1; /* Apple specification for TrueType fonts */ 12664 return 0; 12665 } 12666 12667 /* @OPTIMIZE: binary search */ 12668 static stbtt_uint32 stbtt__find_table(stbtt_uint8 *data, stbtt_uint32 fontstart, const char *tag) 12669 { 12670 stbtt_int32 num_tables = ttUSHORT(data+fontstart+4); 12671 stbtt_uint32 tabledir = fontstart + 12; 12672 stbtt_int32 i; 12673 for (i=0; i < num_tables; ++i) { 12674 stbtt_uint32 loc = tabledir + 16*i; 12675 if (stbtt_tag(data+loc+0, tag)) 12676 return ttULONG(data+loc+8); 12677 } 12678 return 0; 12679 } 12680 12681 static int stbtt_GetFontOffsetForIndex_internal(unsigned char *font_collection, int index) 12682 { 12683 /* if it's just a font, there's only one valid index */ 12684 if (stbtt__isfont(font_collection)) 12685 return index == 0 ? 0 : -1; 12686 12687 /* check if it's a TTC */ 12688 if (stbtt_tag(font_collection, "ttcf")) { 12689 /* version 1? */ 12690 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { 12691 stbtt_int32 n = ttLONG(font_collection+8); 12692 if (index >= n) 12693 return -1; 12694 return ttULONG(font_collection+12+index*4); 12695 } 12696 } 12697 return -1; 12698 } 12699 12700 static int stbtt_GetNumberOfFonts_internal(unsigned char *font_collection) 12701 { 12702 /* if it's just a font, there's only one valid font */ 12703 if (stbtt__isfont(font_collection)) 12704 return 1; 12705 12706 /* check if it's a TTC */ 12707 if (stbtt_tag(font_collection, "ttcf")) { 12708 /* version 1? */ 12709 if (ttULONG(font_collection+4) == 0x00010000 || ttULONG(font_collection+4) == 0x00020000) { 12710 return ttLONG(font_collection+8); 12711 } 12712 } 12713 return 0; 12714 } 12715 12716 static stbtt__buf stbtt__get_subrs(stbtt__buf cff, stbtt__buf fontdict) 12717 { 12718 stbtt_uint32 subrsoff = 0, private_loc[2] = { 0, 0 }; 12719 stbtt__buf pdict; 12720 stbtt__dict_get_ints(&fontdict, 18, 2, private_loc); 12721 if (!private_loc[1] || !private_loc[0]) return stbtt__new_buf(NULL, 0); 12722 pdict = stbtt__buf_range(&cff, private_loc[1], private_loc[0]); 12723 stbtt__dict_get_ints(&pdict, 19, 1, &subrsoff); 12724 if (!subrsoff) return stbtt__new_buf(NULL, 0); 12725 stbtt__buf_seek(&cff, private_loc[1]+subrsoff); 12726 return stbtt__cff_get_index(&cff); 12727 } 12728 12729 /* since most people won't use this, find this table the first time it's needed */ 12730 static int stbtt__get_svg(stbtt_fontinfo *info) 12731 { 12732 stbtt_uint32 t; 12733 if (info->svg < 0) { 12734 t = stbtt__find_table(info->data, info->fontstart, "SVG "); 12735 if (t) { 12736 stbtt_uint32 offset = ttULONG(info->data + t + 2); 12737 info->svg = t + offset; 12738 } else { 12739 info->svg = 0; 12740 } 12741 } 12742 return info->svg; 12743 } 12744 12745 static int stbtt_InitFont_internal(stbtt_fontinfo *info, unsigned char *data, int fontstart) 12746 { 12747 stbtt_uint32 cmap, t; 12748 stbtt_int32 i,numTables; 12749 12750 info->data = data; 12751 info->fontstart = fontstart; 12752 info->cff = stbtt__new_buf(NULL, 0); 12753 12754 cmap = stbtt__find_table(data, fontstart, "cmap"); /* required */ 12755 info->loca = stbtt__find_table(data, fontstart, "loca"); /* required */ 12756 info->head = stbtt__find_table(data, fontstart, "head"); /* required */ 12757 info->glyf = stbtt__find_table(data, fontstart, "glyf"); /* required */ 12758 info->hhea = stbtt__find_table(data, fontstart, "hhea"); /* required */ 12759 info->hmtx = stbtt__find_table(data, fontstart, "hmtx"); /* required */ 12760 info->kern = stbtt__find_table(data, fontstart, "kern"); /* not required */ 12761 info->gpos = stbtt__find_table(data, fontstart, "GPOS"); /* not required */ 12762 12763 if (!cmap || !info->head || !info->hhea || !info->hmtx) 12764 return 0; 12765 if (info->glyf) { 12766 /* required for truetype */ 12767 if (!info->loca) return 0; 12768 } else { 12769 /* initialization for CFF / Type2 fonts (OTF) */ 12770 stbtt__buf b, topdict, topdictidx; 12771 stbtt_uint32 cstype = 2, charstrings = 0, fdarrayoff = 0, fdselectoff = 0; 12772 stbtt_uint32 cff; 12773 12774 cff = stbtt__find_table(data, fontstart, "CFF "); 12775 if (!cff) return 0; 12776 12777 info->fontdicts = stbtt__new_buf(NULL, 0); 12778 info->fdselect = stbtt__new_buf(NULL, 0); 12779 12780 /* @TODO this should use size from table (not 512MB) */ 12781 info->cff = stbtt__new_buf(data+cff, 512*1024*1024); 12782 b = info->cff; 12783 12784 /* read the header */ 12785 stbtt__buf_skip(&b, 2); 12786 stbtt__buf_seek(&b, stbtt__buf_get8(&b)); /* hdrsize */ 12787 12788 /* @TODO the name INDEX could list multiple fonts, */ 12789 /* but we just use the first one. */ 12790 stbtt__cff_get_index(&b); /* name INDEX */ 12791 topdictidx = stbtt__cff_get_index(&b); 12792 topdict = stbtt__cff_index_get(topdictidx, 0); 12793 stbtt__cff_get_index(&b); /* string INDEX */ 12794 info->gsubrs = stbtt__cff_get_index(&b); 12795 12796 stbtt__dict_get_ints(&topdict, 17, 1, &charstrings); 12797 stbtt__dict_get_ints(&topdict, 0x100 | 6, 1, &cstype); 12798 stbtt__dict_get_ints(&topdict, 0x100 | 36, 1, &fdarrayoff); 12799 stbtt__dict_get_ints(&topdict, 0x100 | 37, 1, &fdselectoff); 12800 info->subrs = stbtt__get_subrs(b, topdict); 12801 12802 /* we only support Type 2 charstrings */ 12803 if (cstype != 2) return 0; 12804 if (charstrings == 0) return 0; 12805 12806 if (fdarrayoff) { 12807 /* looks like a CID font */ 12808 if (!fdselectoff) return 0; 12809 stbtt__buf_seek(&b, fdarrayoff); 12810 info->fontdicts = stbtt__cff_get_index(&b); 12811 info->fdselect = stbtt__buf_range(&b, fdselectoff, b.size-fdselectoff); 12812 } 12813 12814 stbtt__buf_seek(&b, charstrings); 12815 info->charstrings = stbtt__cff_get_index(&b); 12816 } 12817 12818 t = stbtt__find_table(data, fontstart, "maxp"); 12819 if (t) 12820 info->numGlyphs = ttUSHORT(data+t+4); 12821 else 12822 info->numGlyphs = 0xffff; 12823 12824 info->svg = -1; 12825 12826 /* find a cmap encoding table we understand *now* to avoid searching */ 12827 /* later. (todo: could make this installable) */ 12828 /* the same regardless of glyph. */ 12829 numTables = ttUSHORT(data + cmap + 2); 12830 info->index_map = 0; 12831 for (i=0; i < numTables; ++i) { 12832 stbtt_uint32 encoding_record = cmap + 4 + 8 * i; 12833 /* find an encoding we understand: */ 12834 switch(ttUSHORT(data+encoding_record)) { 12835 case STBTT_PLATFORM_ID_MICROSOFT: 12836 switch (ttUSHORT(data+encoding_record+2)) { 12837 case STBTT_MS_EID_UNICODE_BMP: 12838 case STBTT_MS_EID_UNICODE_FULL: 12839 /* MS/Unicode */ 12840 info->index_map = cmap + ttULONG(data+encoding_record+4); 12841 break; 12842 } 12843 break; 12844 case STBTT_PLATFORM_ID_UNICODE: 12845 /* Mac/iOS has these */ 12846 /* all the encodingIDs are unicode, so we don't bother to check it */ 12847 info->index_map = cmap + ttULONG(data+encoding_record+4); 12848 break; 12849 } 12850 } 12851 if (info->index_map == 0) 12852 return 0; 12853 12854 info->indexToLocFormat = ttUSHORT(data+info->head + 50); 12855 return 1; 12856 } 12857 12858 STBTT_DEF int stbtt_FindGlyphIndex(const stbtt_fontinfo *info, int unicode_codepoint) 12859 { 12860 stbtt_uint8 *data = info->data; 12861 stbtt_uint32 index_map = info->index_map; 12862 12863 stbtt_uint16 format = ttUSHORT(data + index_map + 0); 12864 if (format == 0) { /* apple byte encoding */ 12865 stbtt_int32 bytes = ttUSHORT(data + index_map + 2); 12866 if (unicode_codepoint < bytes-6) 12867 return ttBYTE(data + index_map + 6 + unicode_codepoint); 12868 return 0; 12869 } else if (format == 6) { 12870 stbtt_uint32 first = ttUSHORT(data + index_map + 6); 12871 stbtt_uint32 count = ttUSHORT(data + index_map + 8); 12872 if ((stbtt_uint32) unicode_codepoint >= first && (stbtt_uint32) unicode_codepoint < first+count) 12873 return ttUSHORT(data + index_map + 10 + (unicode_codepoint - first)*2); 12874 return 0; 12875 } else if (format == 2) { 12876 STBTT_assert(0); /* @TODO: high-byte mapping for japanese/chinese/korean */ 12877 return 0; 12878 } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */ 12879 stbtt_uint16 segcount = ttUSHORT(data+index_map+6) >> 1; 12880 stbtt_uint16 searchRange = ttUSHORT(data+index_map+8) >> 1; 12881 stbtt_uint16 entrySelector = ttUSHORT(data+index_map+10); 12882 stbtt_uint16 rangeShift = ttUSHORT(data+index_map+12) >> 1; 12883 12884 /* do a binary search of the segments */ 12885 stbtt_uint32 endCount = index_map + 14; 12886 stbtt_uint32 search = endCount; 12887 12888 if (unicode_codepoint > 0xffff) 12889 return 0; 12890 12891 /* they lie from endCount .. endCount + segCount */ 12892 /* but searchRange is the nearest power of two, so... */ 12893 if (unicode_codepoint >= ttUSHORT(data + search + rangeShift*2)) 12894 search += rangeShift*2; 12895 12896 /* now decrement to bias correctly to find smallest */ 12897 search -= 2; 12898 while (entrySelector) { 12899 stbtt_uint16 end; 12900 searchRange >>= 1; 12901 end = ttUSHORT(data + search + searchRange*2); 12902 if (unicode_codepoint > end) 12903 search += searchRange*2; 12904 --entrySelector; 12905 } 12906 search += 2; 12907 12908 { 12909 stbtt_uint16 offset, start, last; 12910 stbtt_uint16 item = (stbtt_uint16) ((search - endCount) >> 1); 12911 12912 start = ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); 12913 last = ttUSHORT(data + endCount + 2*item); 12914 if (unicode_codepoint < start || unicode_codepoint > last) 12915 return 0; 12916 12917 offset = ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); 12918 if (offset == 0) 12919 return (stbtt_uint16) (unicode_codepoint + ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); 12920 12921 return ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); 12922 } 12923 } else if (format == 12 || format == 13) { 12924 stbtt_uint32 ngroups = ttULONG(data+index_map+12); 12925 stbtt_int32 low,high; 12926 low = 0; high = (stbtt_int32)ngroups; 12927 /* Binary search the right group. */ 12928 while (low < high) { 12929 stbtt_int32 mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */ 12930 stbtt_uint32 start_char = ttULONG(data+index_map+16+mid*12); 12931 stbtt_uint32 end_char = ttULONG(data+index_map+16+mid*12+4); 12932 if ((stbtt_uint32) unicode_codepoint < start_char) 12933 high = mid; 12934 else if ((stbtt_uint32) unicode_codepoint > end_char) 12935 low = mid+1; 12936 else { 12937 stbtt_uint32 start_glyph = ttULONG(data+index_map+16+mid*12+8); 12938 if (format == 12) 12939 return start_glyph + unicode_codepoint-start_char; 12940 else /* format == 13 */ 12941 return start_glyph; 12942 } 12943 } 12944 return 0; /* not found */ 12945 } 12946 /* @TODO */ 12947 STBTT_assert(0); 12948 return 0; 12949 } 12950 12951 STBTT_DEF int stbtt_GetCodepointShape(const stbtt_fontinfo *info, int unicode_codepoint, stbtt_vertex **vertices) 12952 { 12953 return stbtt_GetGlyphShape(info, stbtt_FindGlyphIndex(info, unicode_codepoint), vertices); 12954 } 12955 12956 static void stbtt_setvertex(stbtt_vertex *v, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy) 12957 { 12958 v->type = type; 12959 v->x = (stbtt_int16) x; 12960 v->y = (stbtt_int16) y; 12961 v->cx = (stbtt_int16) cx; 12962 v->cy = (stbtt_int16) cy; 12963 } 12964 12965 static int stbtt__GetGlyfOffset(const stbtt_fontinfo *info, int glyph_index) 12966 { 12967 int g1,g2; 12968 12969 STBTT_assert(!info->cff.size); 12970 12971 if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */ 12972 if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */ 12973 12974 if (info->indexToLocFormat == 0) { 12975 g1 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; 12976 g2 = info->glyf + ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; 12977 } else { 12978 g1 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4); 12979 g2 = info->glyf + ttULONG (info->data + info->loca + glyph_index * 4 + 4); 12980 } 12981 12982 return g1==g2 ? -1 : g1; /* if length is 0, return -1 */ 12983 } 12984 12985 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1); 12986 12987 STBTT_DEF int stbtt_GetGlyphBox(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) 12988 { 12989 if (info->cff.size) { 12990 stbtt__GetGlyphInfoT2(info, glyph_index, x0, y0, x1, y1); 12991 } else { 12992 int g = stbtt__GetGlyfOffset(info, glyph_index); 12993 if (g < 0) return 0; 12994 12995 if (x0) *x0 = ttSHORT(info->data + g + 2); 12996 if (y0) *y0 = ttSHORT(info->data + g + 4); 12997 if (x1) *x1 = ttSHORT(info->data + g + 6); 12998 if (y1) *y1 = ttSHORT(info->data + g + 8); 12999 } 13000 return 1; 13001 } 13002 13003 STBTT_DEF int stbtt_GetCodepointBox(const stbtt_fontinfo *info, int codepoint, int *x0, int *y0, int *x1, int *y1) 13004 { 13005 return stbtt_GetGlyphBox(info, stbtt_FindGlyphIndex(info,codepoint), x0,y0,x1,y1); 13006 } 13007 13008 STBTT_DEF int stbtt_IsGlyphEmpty(const stbtt_fontinfo *info, int glyph_index) 13009 { 13010 stbtt_int16 numberOfContours; 13011 int g; 13012 if (info->cff.size) 13013 return stbtt__GetGlyphInfoT2(info, glyph_index, NULL, NULL, NULL, NULL) == 0; 13014 g = stbtt__GetGlyfOffset(info, glyph_index); 13015 if (g < 0) return 1; 13016 numberOfContours = ttSHORT(info->data + g); 13017 return numberOfContours == 0; 13018 } 13019 13020 static int stbtt__close_shape(stbtt_vertex *vertices, int num_vertices, int was_off, int start_off, 13021 stbtt_int32 sx, stbtt_int32 sy, stbtt_int32 scx, stbtt_int32 scy, stbtt_int32 cx, stbtt_int32 cy) 13022 { 13023 if (start_off) { 13024 if (was_off) 13025 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); 13026 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, sx,sy,scx,scy); 13027 } else { 13028 if (was_off) 13029 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve,sx,sy,cx,cy); 13030 else 13031 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline,sx,sy,0,0); 13032 } 13033 return num_vertices; 13034 } 13035 13036 static int stbtt__GetGlyphShapeTT(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) 13037 { 13038 stbtt_int16 numberOfContours; 13039 stbtt_uint8 *endPtsOfContours; 13040 stbtt_uint8 *data = info->data; 13041 stbtt_vertex *vertices=0; 13042 int num_vertices=0; 13043 int g = stbtt__GetGlyfOffset(info, glyph_index); 13044 13045 *pvertices = NULL; 13046 13047 if (g < 0) return 0; 13048 13049 numberOfContours = ttSHORT(data + g); 13050 13051 if (numberOfContours > 0) { 13052 stbtt_uint8 flags=0,flagcount; 13053 stbtt_int32 ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; 13054 stbtt_int32 x,y,cx,cy,sx,sy, scx,scy; 13055 stbtt_uint8 *points; 13056 endPtsOfContours = (data + g + 10); 13057 ins = ttUSHORT(data + g + 10 + numberOfContours * 2); 13058 points = data + g + 10 + numberOfContours * 2 + 2 + ins; 13059 13060 n = 1+ttUSHORT(endPtsOfContours + numberOfContours*2-2); 13061 13062 m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */ 13063 vertices = (stbtt_vertex *) STBTT_malloc(m * sizeof(vertices[0]), info->userdata); 13064 if (vertices == 0) 13065 return 0; 13066 13067 next_move = 0; 13068 flagcount=0; 13069 13070 /* in first pass, we load uninterpreted data into the allocated array */ 13071 /* above, shifted to the end of the array so we won't overwrite it when */ 13072 /* we create our final data starting from the front */ 13073 13074 off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */ 13075 13076 /* first load flags */ 13077 13078 for (i=0; i < n; ++i) { 13079 if (flagcount == 0) { 13080 flags = *points++; 13081 if (flags & 8) 13082 flagcount = *points++; 13083 } else 13084 --flagcount; 13085 vertices[off+i].type = flags; 13086 } 13087 13088 /* now load x coordinates */ 13089 x=0; 13090 for (i=0; i < n; ++i) { 13091 flags = vertices[off+i].type; 13092 if (flags & 2) { 13093 stbtt_int16 dx = *points++; 13094 x += (flags & 16) ? dx : -dx; /* ??? */ 13095 } else { 13096 if (!(flags & 16)) { 13097 x = x + (stbtt_int16) (points[0]*256 + points[1]); 13098 points += 2; 13099 } 13100 } 13101 vertices[off+i].x = (stbtt_int16) x; 13102 } 13103 13104 /* now load y coordinates */ 13105 y=0; 13106 for (i=0; i < n; ++i) { 13107 flags = vertices[off+i].type; 13108 if (flags & 4) { 13109 stbtt_int16 dy = *points++; 13110 y += (flags & 32) ? dy : -dy; /* ??? */ 13111 } else { 13112 if (!(flags & 32)) { 13113 y = y + (stbtt_int16) (points[0]*256 + points[1]); 13114 points += 2; 13115 } 13116 } 13117 vertices[off+i].y = (stbtt_int16) y; 13118 } 13119 13120 /* now convert them to our format */ 13121 num_vertices=0; 13122 sx = sy = cx = cy = scx = scy = 0; 13123 for (i=0; i < n; ++i) { 13124 flags = vertices[off+i].type; 13125 x = (stbtt_int16) vertices[off+i].x; 13126 y = (stbtt_int16) vertices[off+i].y; 13127 13128 if (next_move == i) { 13129 if (i != 0) 13130 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 13131 13132 /* now start the new one */ 13133 start_off = !(flags & 1); 13134 if (start_off) { 13135 /* if we start off with an off-curve point, then when we need to find a point on the curve */ 13136 /* where we can start, and we need to save some state for when we wraparound. */ 13137 scx = x; 13138 scy = y; 13139 if (!(vertices[off+i+1].type & 1)) { 13140 /* next point is also a curve point, so interpolate an on-point curve */ 13141 sx = (x + (stbtt_int32) vertices[off+i+1].x) >> 1; 13142 sy = (y + (stbtt_int32) vertices[off+i+1].y) >> 1; 13143 } else { 13144 /* otherwise just use the next point as our start point */ 13145 sx = (stbtt_int32) vertices[off+i+1].x; 13146 sy = (stbtt_int32) vertices[off+i+1].y; 13147 ++i; /* we're using point i+1 as the starting point, so skip it */ 13148 } 13149 } else { 13150 sx = x; 13151 sy = y; 13152 } 13153 stbtt_setvertex(&vertices[num_vertices++], STBTT_vmove,sx,sy,0,0); 13154 was_off = 0; 13155 next_move = 1 + ttUSHORT(endPtsOfContours+j*2); 13156 ++j; 13157 } else { 13158 if (!(flags & 1)) { /* if it's a curve */ 13159 if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */ 13160 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); 13161 cx = x; 13162 cy = y; 13163 was_off = 1; 13164 } else { 13165 if (was_off) 13166 stbtt_setvertex(&vertices[num_vertices++], STBTT_vcurve, x,y, cx, cy); 13167 else 13168 stbtt_setvertex(&vertices[num_vertices++], STBTT_vline, x,y,0,0); 13169 was_off = 0; 13170 } 13171 } 13172 } 13173 num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); 13174 } else if (numberOfContours < 0) { 13175 /* Compound shapes. */ 13176 int more = 1; 13177 stbtt_uint8 *comp = data + g + 10; 13178 num_vertices = 0; 13179 vertices = 0; 13180 while (more) { 13181 stbtt_uint16 flags, gidx; 13182 int comp_num_verts = 0, i; 13183 stbtt_vertex *comp_verts = 0, *tmp = 0; 13184 float mtx[6] = {1,0,0,1,0,0}, m, n; 13185 13186 flags = ttSHORT(comp); comp+=2; 13187 gidx = ttSHORT(comp); comp+=2; 13188 13189 if (flags & 2) { /* XY values */ 13190 if (flags & 1) { /* shorts */ 13191 mtx[4] = ttSHORT(comp); comp+=2; 13192 mtx[5] = ttSHORT(comp); comp+=2; 13193 } else { 13194 mtx[4] = ttCHAR(comp); comp+=1; 13195 mtx[5] = ttCHAR(comp); comp+=1; 13196 } 13197 } 13198 else { 13199 /* @TODO handle matching point */ 13200 STBTT_assert(0); 13201 } 13202 if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */ 13203 mtx[0] = mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; 13204 mtx[1] = mtx[2] = 0; 13205 } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */ 13206 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; 13207 mtx[1] = mtx[2] = 0; 13208 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; 13209 } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */ 13210 mtx[0] = ttSHORT(comp)/16384.0f; comp+=2; 13211 mtx[1] = ttSHORT(comp)/16384.0f; comp+=2; 13212 mtx[2] = ttSHORT(comp)/16384.0f; comp+=2; 13213 mtx[3] = ttSHORT(comp)/16384.0f; comp+=2; 13214 } 13215 13216 /* Find transformation scales. */ 13217 m = (float) STBTT_sqrt(mtx[0]*mtx[0] + mtx[1]*mtx[1]); 13218 n = (float) STBTT_sqrt(mtx[2]*mtx[2] + mtx[3]*mtx[3]); 13219 13220 /* Get indexed glyph. */ 13221 comp_num_verts = stbtt_GetGlyphShape(info, gidx, &comp_verts); 13222 if (comp_num_verts > 0) { 13223 /* Transform vertices. */ 13224 for (i = 0; i < comp_num_verts; ++i) { 13225 stbtt_vertex* v = &comp_verts[i]; 13226 stbtt_vertex_type x,y; 13227 x=v->x; y=v->y; 13228 v->x = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 13229 v->y = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 13230 x=v->cx; y=v->cy; 13231 v->cx = (stbtt_vertex_type)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); 13232 v->cy = (stbtt_vertex_type)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); 13233 } 13234 /* Append vertices. */ 13235 tmp = (stbtt_vertex*)STBTT_malloc((num_vertices+comp_num_verts)*sizeof(stbtt_vertex), info->userdata); 13236 if (!tmp) { 13237 if (vertices) STBTT_free(vertices, info->userdata); 13238 if (comp_verts) STBTT_free(comp_verts, info->userdata); 13239 return 0; 13240 } 13241 if (num_vertices > 0 && vertices) STBTT_memcpy(tmp, vertices, num_vertices*sizeof(stbtt_vertex)); 13242 STBTT_memcpy(tmp+num_vertices, comp_verts, comp_num_verts*sizeof(stbtt_vertex)); 13243 if (vertices) STBTT_free(vertices, info->userdata); 13244 vertices = tmp; 13245 STBTT_free(comp_verts, info->userdata); 13246 num_vertices += comp_num_verts; 13247 } 13248 /* More components ? */ 13249 more = flags & (1<<5); 13250 } 13251 } else { 13252 /* numberOfCounters == 0, do nothing */ 13253 } 13254 13255 *pvertices = vertices; 13256 return num_vertices; 13257 } 13258 13259 typedef struct 13260 { 13261 int bounds; 13262 int started; 13263 float first_x, first_y; 13264 float x, y; 13265 stbtt_int32 min_x, max_x, min_y, max_y; 13266 13267 stbtt_vertex *pvertices; 13268 int num_vertices; 13269 } stbtt__csctx; 13270 13271 #define STBTT__CSCTX_INIT(bounds) {bounds,0, 0,0, 0,0, 0,0,0,0, NULL, 0} 13272 13273 static void stbtt__track_vertex(stbtt__csctx *c, stbtt_int32 x, stbtt_int32 y) 13274 { 13275 if (x > c->max_x || !c->started) c->max_x = x; 13276 if (y > c->max_y || !c->started) c->max_y = y; 13277 if (x < c->min_x || !c->started) c->min_x = x; 13278 if (y < c->min_y || !c->started) c->min_y = y; 13279 c->started = 1; 13280 } 13281 13282 static void stbtt__csctx_v(stbtt__csctx *c, stbtt_uint8 type, stbtt_int32 x, stbtt_int32 y, stbtt_int32 cx, stbtt_int32 cy, stbtt_int32 cx1, stbtt_int32 cy1) 13283 { 13284 if (c->bounds) { 13285 stbtt__track_vertex(c, x, y); 13286 if (type == STBTT_vcubic) { 13287 stbtt__track_vertex(c, cx, cy); 13288 stbtt__track_vertex(c, cx1, cy1); 13289 } 13290 } else { 13291 stbtt_setvertex(&c->pvertices[c->num_vertices], type, x, y, cx, cy); 13292 c->pvertices[c->num_vertices].cx1 = (stbtt_int16) cx1; 13293 c->pvertices[c->num_vertices].cy1 = (stbtt_int16) cy1; 13294 } 13295 c->num_vertices++; 13296 } 13297 13298 static void stbtt__csctx_close_shape(stbtt__csctx *ctx) 13299 { 13300 if (ctx->first_x != ctx->x || ctx->first_y != ctx->y) 13301 stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->first_x, (int)ctx->first_y, 0, 0, 0, 0); 13302 } 13303 13304 static void stbtt__csctx_rmove_to(stbtt__csctx *ctx, float dx, float dy) 13305 { 13306 stbtt__csctx_close_shape(ctx); 13307 ctx->first_x = ctx->x = ctx->x + dx; 13308 ctx->first_y = ctx->y = ctx->y + dy; 13309 stbtt__csctx_v(ctx, STBTT_vmove, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); 13310 } 13311 13312 static void stbtt__csctx_rline_to(stbtt__csctx *ctx, float dx, float dy) 13313 { 13314 ctx->x += dx; 13315 ctx->y += dy; 13316 stbtt__csctx_v(ctx, STBTT_vline, (int)ctx->x, (int)ctx->y, 0, 0, 0, 0); 13317 } 13318 13319 static void stbtt__csctx_rccurve_to(stbtt__csctx *ctx, float dx1, float dy1, float dx2, float dy2, float dx3, float dy3) 13320 { 13321 float cx1 = ctx->x + dx1; 13322 float cy1 = ctx->y + dy1; 13323 float cx2 = cx1 + dx2; 13324 float cy2 = cy1 + dy2; 13325 ctx->x = cx2 + dx3; 13326 ctx->y = cy2 + dy3; 13327 stbtt__csctx_v(ctx, STBTT_vcubic, (int)ctx->x, (int)ctx->y, (int)cx1, (int)cy1, (int)cx2, (int)cy2); 13328 } 13329 13330 static stbtt__buf stbtt__get_subr(stbtt__buf idx, int n) 13331 { 13332 int count = stbtt__cff_index_count(&idx); 13333 int bias = 107; 13334 if (count >= 33900) 13335 bias = 32768; 13336 else if (count >= 1240) 13337 bias = 1131; 13338 n += bias; 13339 if (n < 0 || n >= count) 13340 return stbtt__new_buf(NULL, 0); 13341 return stbtt__cff_index_get(idx, n); 13342 } 13343 13344 static stbtt__buf stbtt__cid_get_glyph_subrs(const stbtt_fontinfo *info, int glyph_index) 13345 { 13346 stbtt__buf fdselect = info->fdselect; 13347 int nranges, start, end, v, fmt, fdselector = -1, i; 13348 13349 stbtt__buf_seek(&fdselect, 0); 13350 fmt = stbtt__buf_get8(&fdselect); 13351 if (fmt == 0) { 13352 /* untested */ 13353 stbtt__buf_skip(&fdselect, glyph_index); 13354 fdselector = stbtt__buf_get8(&fdselect); 13355 } else if (fmt == 3) { 13356 nranges = stbtt__buf_get16(&fdselect); 13357 start = stbtt__buf_get16(&fdselect); 13358 for (i = 0; i < nranges; i++) { 13359 v = stbtt__buf_get8(&fdselect); 13360 end = stbtt__buf_get16(&fdselect); 13361 if (glyph_index >= start && glyph_index < end) { 13362 fdselector = v; 13363 break; 13364 } 13365 start = end; 13366 } 13367 } 13368 if (fdselector == -1) stbtt__new_buf(NULL, 0); 13369 return stbtt__get_subrs(info->cff, stbtt__cff_index_get(info->fontdicts, fdselector)); 13370 } 13371 13372 static int stbtt__run_charstring(const stbtt_fontinfo *info, int glyph_index, stbtt__csctx *c) 13373 { 13374 int in_header = 1, maskbits = 0, subr_stack_height = 0, sp = 0, v, i, b0; 13375 int has_subrs = 0, clear_stack; 13376 float s[48]; 13377 stbtt__buf subr_stack[10], subrs = info->subrs, b; 13378 float f; 13379 13380 #define STBTT__CSERR(s) (0) 13381 13382 /* this currently ignores the initial width value, which isn't needed if we have hmtx */ 13383 b = stbtt__cff_index_get(info->charstrings, glyph_index); 13384 while (b.cursor < b.size) { 13385 i = 0; 13386 clear_stack = 1; 13387 b0 = stbtt__buf_get8(&b); 13388 switch (b0) { 13389 /* @TODO implement hinting */ 13390 case 0x13: /* hintmask */ 13391 case 0x14: /* cntrmask */ 13392 if (in_header) 13393 maskbits += (sp / 2); /* implicit "vstem" */ 13394 in_header = 0; 13395 stbtt__buf_skip(&b, (maskbits + 7) / 8); 13396 break; 13397 13398 case 0x01: /* hstem */ 13399 case 0x03: /* vstem */ 13400 case 0x12: /* hstemhm */ 13401 case 0x17: /* vstemhm */ 13402 maskbits += (sp / 2); 13403 break; 13404 13405 case 0x15: /* rmoveto */ 13406 in_header = 0; 13407 if (sp < 2) return STBTT__CSERR("rmoveto stack"); 13408 stbtt__csctx_rmove_to(c, s[sp-2], s[sp-1]); 13409 break; 13410 case 0x04: /* vmoveto */ 13411 in_header = 0; 13412 if (sp < 1) return STBTT__CSERR("vmoveto stack"); 13413 stbtt__csctx_rmove_to(c, 0, s[sp-1]); 13414 break; 13415 case 0x16: /* hmoveto */ 13416 in_header = 0; 13417 if (sp < 1) return STBTT__CSERR("hmoveto stack"); 13418 stbtt__csctx_rmove_to(c, s[sp-1], 0); 13419 break; 13420 13421 case 0x05: /* rlineto */ 13422 if (sp < 2) return STBTT__CSERR("rlineto stack"); 13423 for (; i + 1 < sp; i += 2) 13424 stbtt__csctx_rline_to(c, s[i], s[i+1]); 13425 break; 13426 13427 /* hlineto/vlineto and vhcurveto/hvcurveto alternate horizontal and vertical */ 13428 /* starting from a different place. */ 13429 13430 case 0x07: /* vlineto */ 13431 if (sp < 1) return STBTT__CSERR("vlineto stack"); 13432 goto vlineto; 13433 case 0x06: /* hlineto */ 13434 if (sp < 1) return STBTT__CSERR("hlineto stack"); 13435 for (;;) { 13436 if (i >= sp) break; 13437 stbtt__csctx_rline_to(c, s[i], 0); 13438 i++; 13439 vlineto: 13440 if (i >= sp) break; 13441 stbtt__csctx_rline_to(c, 0, s[i]); 13442 i++; 13443 } 13444 break; 13445 13446 case 0x1F: /* hvcurveto */ 13447 if (sp < 4) return STBTT__CSERR("hvcurveto stack"); 13448 goto hvcurveto; 13449 case 0x1E: /* vhcurveto */ 13450 if (sp < 4) return STBTT__CSERR("vhcurveto stack"); 13451 for (;;) { 13452 if (i + 3 >= sp) break; 13453 stbtt__csctx_rccurve_to(c, 0, s[i], s[i+1], s[i+2], s[i+3], (sp - i == 5) ? s[i + 4] : 0.0f); 13454 i += 4; 13455 hvcurveto: 13456 if (i + 3 >= sp) break; 13457 stbtt__csctx_rccurve_to(c, s[i], 0, s[i+1], s[i+2], (sp - i == 5) ? s[i+4] : 0.0f, s[i+3]); 13458 i += 4; 13459 } 13460 break; 13461 13462 case 0x08: /* rrcurveto */ 13463 if (sp < 6) return STBTT__CSERR("rcurveline stack"); 13464 for (; i + 5 < sp; i += 6) 13465 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); 13466 break; 13467 13468 case 0x18: /* rcurveline */ 13469 if (sp < 8) return STBTT__CSERR("rcurveline stack"); 13470 for (; i + 5 < sp - 2; i += 6) 13471 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); 13472 if (i + 1 >= sp) return STBTT__CSERR("rcurveline stack"); 13473 stbtt__csctx_rline_to(c, s[i], s[i+1]); 13474 break; 13475 13476 case 0x19: /* rlinecurve */ 13477 if (sp < 8) return STBTT__CSERR("rlinecurve stack"); 13478 for (; i + 1 < sp - 6; i += 2) 13479 stbtt__csctx_rline_to(c, s[i], s[i+1]); 13480 if (i + 5 >= sp) return STBTT__CSERR("rlinecurve stack"); 13481 stbtt__csctx_rccurve_to(c, s[i], s[i+1], s[i+2], s[i+3], s[i+4], s[i+5]); 13482 break; 13483 13484 case 0x1A: /* vvcurveto */ 13485 case 0x1B: /* hhcurveto */ 13486 if (sp < 4) return STBTT__CSERR("(vv|hh)curveto stack"); 13487 f = 0.0; 13488 if (sp & 1) { f = s[i]; i++; } 13489 for (; i + 3 < sp; i += 4) { 13490 if (b0 == 0x1B) 13491 stbtt__csctx_rccurve_to(c, s[i], f, s[i+1], s[i+2], s[i+3], 0.0); 13492 else 13493 stbtt__csctx_rccurve_to(c, f, s[i], s[i+1], s[i+2], 0.0, s[i+3]); 13494 f = 0.0; 13495 } 13496 break; 13497 13498 case 0x0A: /* callsubr */ 13499 if (!has_subrs) { 13500 if (info->fdselect.size) 13501 subrs = stbtt__cid_get_glyph_subrs(info, glyph_index); 13502 has_subrs = 1; 13503 } 13504 /* FALLTHROUGH */ 13505 case 0x1D: /* callgsubr */ 13506 if (sp < 1) return STBTT__CSERR("call(g|)subr stack"); 13507 v = (int) s[--sp]; 13508 if (subr_stack_height >= 10) return STBTT__CSERR("recursion limit"); 13509 subr_stack[subr_stack_height++] = b; 13510 b = stbtt__get_subr(b0 == 0x0A ? subrs : info->gsubrs, v); 13511 if (b.size == 0) return STBTT__CSERR("subr not found"); 13512 b.cursor = 0; 13513 clear_stack = 0; 13514 break; 13515 13516 case 0x0B: /* return */ 13517 if (subr_stack_height <= 0) return STBTT__CSERR("return outside subr"); 13518 b = subr_stack[--subr_stack_height]; 13519 clear_stack = 0; 13520 break; 13521 13522 case 0x0E: /* endchar */ 13523 stbtt__csctx_close_shape(c); 13524 return 1; 13525 13526 case 0x0C: { /* two-byte escape */ 13527 float dx1, dx2, dx3, dx4, dx5, dx6, dy1, dy2, dy3, dy4, dy5, dy6; 13528 float dx, dy; 13529 int b1 = stbtt__buf_get8(&b); 13530 switch (b1) { 13531 /* @TODO These "flex" implementations ignore the flex-depth and resolution, */ 13532 /* and always draw beziers. */ 13533 case 0x22: /* hflex */ 13534 if (sp < 7) return STBTT__CSERR("hflex stack"); 13535 dx1 = s[0]; 13536 dx2 = s[1]; 13537 dy2 = s[2]; 13538 dx3 = s[3]; 13539 dx4 = s[4]; 13540 dx5 = s[5]; 13541 dx6 = s[6]; 13542 stbtt__csctx_rccurve_to(c, dx1, 0, dx2, dy2, dx3, 0); 13543 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, -dy2, dx6, 0); 13544 break; 13545 13546 case 0x23: /* flex */ 13547 if (sp < 13) return STBTT__CSERR("flex stack"); 13548 dx1 = s[0]; 13549 dy1 = s[1]; 13550 dx2 = s[2]; 13551 dy2 = s[3]; 13552 dx3 = s[4]; 13553 dy3 = s[5]; 13554 dx4 = s[6]; 13555 dy4 = s[7]; 13556 dx5 = s[8]; 13557 dy5 = s[9]; 13558 dx6 = s[10]; 13559 dy6 = s[11]; 13560 /* fd is s[12] */ 13561 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); 13562 stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); 13563 break; 13564 13565 case 0x24: /* hflex1 */ 13566 if (sp < 9) return STBTT__CSERR("hflex1 stack"); 13567 dx1 = s[0]; 13568 dy1 = s[1]; 13569 dx2 = s[2]; 13570 dy2 = s[3]; 13571 dx3 = s[4]; 13572 dx4 = s[5]; 13573 dx5 = s[6]; 13574 dy5 = s[7]; 13575 dx6 = s[8]; 13576 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, 0); 13577 stbtt__csctx_rccurve_to(c, dx4, 0, dx5, dy5, dx6, -(dy1+dy2+dy5)); 13578 break; 13579 13580 case 0x25: /* flex1 */ 13581 if (sp < 11) return STBTT__CSERR("flex1 stack"); 13582 dx1 = s[0]; 13583 dy1 = s[1]; 13584 dx2 = s[2]; 13585 dy2 = s[3]; 13586 dx3 = s[4]; 13587 dy3 = s[5]; 13588 dx4 = s[6]; 13589 dy4 = s[7]; 13590 dx5 = s[8]; 13591 dy5 = s[9]; 13592 dx6 = dy6 = s[10]; 13593 dx = dx1+dx2+dx3+dx4+dx5; 13594 dy = dy1+dy2+dy3+dy4+dy5; 13595 if (STBTT_fabs(dx) > STBTT_fabs(dy)) 13596 dy6 = -dy; 13597 else 13598 dx6 = -dx; 13599 stbtt__csctx_rccurve_to(c, dx1, dy1, dx2, dy2, dx3, dy3); 13600 stbtt__csctx_rccurve_to(c, dx4, dy4, dx5, dy5, dx6, dy6); 13601 break; 13602 13603 default: 13604 return STBTT__CSERR("unimplemented"); 13605 } 13606 } break; 13607 13608 default: 13609 if (b0 != 255 && b0 != 28 && b0 < 32) 13610 return STBTT__CSERR("reserved operator"); 13611 13612 /* push immediate */ 13613 if (b0 == 255) { 13614 f = (float)(stbtt_int32)stbtt__buf_get32(&b) / 0x10000; 13615 } else { 13616 stbtt__buf_skip(&b, -1); 13617 f = (float)(stbtt_int16)stbtt__cff_int(&b); 13618 } 13619 if (sp >= 48) return STBTT__CSERR("push stack overflow"); 13620 s[sp++] = f; 13621 clear_stack = 0; 13622 break; 13623 } 13624 if (clear_stack) sp = 0; 13625 } 13626 return STBTT__CSERR("no endchar"); 13627 13628 #undef STBTT__CSERR 13629 } 13630 13631 static int stbtt__GetGlyphShapeT2(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) 13632 { 13633 /* runs the charstring twice, once to count and once to output (to avoid realloc) */ 13634 stbtt__csctx count_ctx = STBTT__CSCTX_INIT(1); 13635 stbtt__csctx output_ctx = STBTT__CSCTX_INIT(0); 13636 if (stbtt__run_charstring(info, glyph_index, &count_ctx)) { 13637 *pvertices = (stbtt_vertex*)STBTT_malloc(count_ctx.num_vertices*sizeof(stbtt_vertex), info->userdata); 13638 output_ctx.pvertices = *pvertices; 13639 if (stbtt__run_charstring(info, glyph_index, &output_ctx)) { 13640 STBTT_assert(output_ctx.num_vertices == count_ctx.num_vertices); 13641 return output_ctx.num_vertices; 13642 } 13643 } 13644 *pvertices = NULL; 13645 return 0; 13646 } 13647 13648 static int stbtt__GetGlyphInfoT2(const stbtt_fontinfo *info, int glyph_index, int *x0, int *y0, int *x1, int *y1) 13649 { 13650 stbtt__csctx c = STBTT__CSCTX_INIT(1); 13651 int r = stbtt__run_charstring(info, glyph_index, &c); 13652 if (x0) *x0 = r ? c.min_x : 0; 13653 if (y0) *y0 = r ? c.min_y : 0; 13654 if (x1) *x1 = r ? c.max_x : 0; 13655 if (y1) *y1 = r ? c.max_y : 0; 13656 return r ? c.num_vertices : 0; 13657 } 13658 13659 STBTT_DEF int stbtt_GetGlyphShape(const stbtt_fontinfo *info, int glyph_index, stbtt_vertex **pvertices) 13660 { 13661 if (!info->cff.size) 13662 return stbtt__GetGlyphShapeTT(info, glyph_index, pvertices); 13663 else 13664 return stbtt__GetGlyphShapeT2(info, glyph_index, pvertices); 13665 } 13666 13667 STBTT_DEF void stbtt_GetGlyphHMetrics(const stbtt_fontinfo *info, int glyph_index, int *advanceWidth, int *leftSideBearing) 13668 { 13669 stbtt_uint16 numOfLongHorMetrics = ttUSHORT(info->data+info->hhea + 34); 13670 if (glyph_index < numOfLongHorMetrics) { 13671 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*glyph_index); 13672 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); 13673 } else { 13674 if (advanceWidth) *advanceWidth = ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); 13675 if (leftSideBearing) *leftSideBearing = ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); 13676 } 13677 } 13678 13679 STBTT_DEF int stbtt_GetKerningTableLength(const stbtt_fontinfo *info) 13680 { 13681 stbtt_uint8 *data = info->data + info->kern; 13682 13683 /* we only look at the first table. it must be 'horizontal' and format 0. */ 13684 if (!info->kern) 13685 return 0; 13686 if (ttUSHORT(data+2) < 1) /* number of tables, need at least 1 */ 13687 return 0; 13688 if (ttUSHORT(data+8) != 1) /* horizontal flag must be set in format */ 13689 return 0; 13690 13691 return ttUSHORT(data+10); 13692 } 13693 13694 STBTT_DEF int stbtt_GetKerningTable(const stbtt_fontinfo *info, stbtt_kerningentry* table, int table_length) 13695 { 13696 stbtt_uint8 *data = info->data + info->kern; 13697 int k, length; 13698 13699 /* we only look at the first table. it must be 'horizontal' and format 0. */ 13700 if (!info->kern) 13701 return 0; 13702 if (ttUSHORT(data+2) < 1) /* number of tables, need at least 1 */ 13703 return 0; 13704 if (ttUSHORT(data+8) != 1) /* horizontal flag must be set in format */ 13705 return 0; 13706 13707 length = ttUSHORT(data+10); 13708 if (table_length < length) 13709 length = table_length; 13710 13711 for (k = 0; k < length; k++) 13712 { 13713 table[k].glyph1 = ttUSHORT(data+18+(k*6)); 13714 table[k].glyph2 = ttUSHORT(data+20+(k*6)); 13715 table[k].advance = ttSHORT(data+22+(k*6)); 13716 } 13717 13718 return length; 13719 } 13720 13721 static int stbtt__GetGlyphKernInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) 13722 { 13723 stbtt_uint8 *data = info->data + info->kern; 13724 stbtt_uint32 needle, straw; 13725 int l, r, m; 13726 13727 /* we only look at the first table. it must be 'horizontal' and format 0. */ 13728 if (!info->kern) 13729 return 0; 13730 if (ttUSHORT(data+2) < 1) /* number of tables, need at least 1 */ 13731 return 0; 13732 if (ttUSHORT(data+8) != 1) /* horizontal flag must be set in format */ 13733 return 0; 13734 13735 l = 0; 13736 r = ttUSHORT(data+10) - 1; 13737 needle = glyph1 << 16 | glyph2; 13738 while (l <= r) { 13739 m = (l + r) >> 1; 13740 straw = ttULONG(data+18+(m*6)); /* note: unaligned read */ 13741 if (needle < straw) 13742 r = m - 1; 13743 else if (needle > straw) 13744 l = m + 1; 13745 else 13746 return ttSHORT(data+22+(m*6)); 13747 } 13748 return 0; 13749 } 13750 13751 static stbtt_int32 stbtt__GetCoverageIndex(stbtt_uint8 *coverageTable, int glyph) 13752 { 13753 stbtt_uint16 coverageFormat = ttUSHORT(coverageTable); 13754 switch (coverageFormat) { 13755 case 1: { 13756 stbtt_uint16 glyphCount = ttUSHORT(coverageTable + 2); 13757 13758 /* Binary search. */ 13759 stbtt_int32 l=0, r=glyphCount-1, m; 13760 int straw, needle=glyph; 13761 while (l <= r) { 13762 stbtt_uint8 *glyphArray = coverageTable + 4; 13763 stbtt_uint16 glyphID; 13764 m = (l + r) >> 1; 13765 glyphID = ttUSHORT(glyphArray + 2 * m); 13766 straw = glyphID; 13767 if (needle < straw) 13768 r = m - 1; 13769 else if (needle > straw) 13770 l = m + 1; 13771 else { 13772 return m; 13773 } 13774 } 13775 break; 13776 } 13777 13778 case 2: { 13779 stbtt_uint16 rangeCount = ttUSHORT(coverageTable + 2); 13780 stbtt_uint8 *rangeArray = coverageTable + 4; 13781 13782 /* Binary search. */ 13783 stbtt_int32 l=0, r=rangeCount-1, m; 13784 int strawStart, strawEnd, needle=glyph; 13785 while (l <= r) { 13786 stbtt_uint8 *rangeRecord; 13787 m = (l + r) >> 1; 13788 rangeRecord = rangeArray + 6 * m; 13789 strawStart = ttUSHORT(rangeRecord); 13790 strawEnd = ttUSHORT(rangeRecord + 2); 13791 if (needle < strawStart) 13792 r = m - 1; 13793 else if (needle > strawEnd) 13794 l = m + 1; 13795 else { 13796 stbtt_uint16 startCoverageIndex = ttUSHORT(rangeRecord + 4); 13797 return startCoverageIndex + glyph - strawStart; 13798 } 13799 } 13800 break; 13801 } 13802 13803 default: return -1; /* unsupported */ 13804 } 13805 13806 return -1; 13807 } 13808 13809 static stbtt_int32 stbtt__GetGlyphClass(stbtt_uint8 *classDefTable, int glyph) 13810 { 13811 stbtt_uint16 classDefFormat = ttUSHORT(classDefTable); 13812 switch (classDefFormat) 13813 { 13814 case 1: { 13815 stbtt_uint16 startGlyphID = ttUSHORT(classDefTable + 2); 13816 stbtt_uint16 glyphCount = ttUSHORT(classDefTable + 4); 13817 stbtt_uint8 *classDef1ValueArray = classDefTable + 6; 13818 13819 if (glyph >= startGlyphID && glyph < startGlyphID + glyphCount) 13820 return (stbtt_int32)ttUSHORT(classDef1ValueArray + 2 * (glyph - startGlyphID)); 13821 break; 13822 } 13823 13824 case 2: { 13825 stbtt_uint16 classRangeCount = ttUSHORT(classDefTable + 2); 13826 stbtt_uint8 *classRangeRecords = classDefTable + 4; 13827 13828 /* Binary search. */ 13829 stbtt_int32 l=0, r=classRangeCount-1, m; 13830 int strawStart, strawEnd, needle=glyph; 13831 while (l <= r) { 13832 stbtt_uint8 *classRangeRecord; 13833 m = (l + r) >> 1; 13834 classRangeRecord = classRangeRecords + 6 * m; 13835 strawStart = ttUSHORT(classRangeRecord); 13836 strawEnd = ttUSHORT(classRangeRecord + 2); 13837 if (needle < strawStart) 13838 r = m - 1; 13839 else if (needle > strawEnd) 13840 l = m + 1; 13841 else 13842 return (stbtt_int32)ttUSHORT(classRangeRecord + 4); 13843 } 13844 break; 13845 } 13846 13847 default: 13848 return -1; /* Unsupported definition type, return an error. */ 13849 } 13850 13851 /* "All glyphs not assigned to a class fall into class 0". (OpenType spec) */ 13852 return 0; 13853 } 13854 13855 /* Define to STBTT_assert(x) if you want to break on unimplemented formats. */ 13856 #define STBTT_GPOS_TODO_assert(x) 13857 13858 static stbtt_int32 stbtt__GetGlyphGPOSInfoAdvance(const stbtt_fontinfo *info, int glyph1, int glyph2) 13859 { 13860 stbtt_uint16 lookupListOffset; 13861 stbtt_uint8 *lookupList; 13862 stbtt_uint16 lookupCount; 13863 stbtt_uint8 *data; 13864 stbtt_int32 i, sti; 13865 13866 if (!info->gpos) return 0; 13867 13868 data = info->data + info->gpos; 13869 13870 if (ttUSHORT(data+0) != 1) return 0; /* Major version 1 */ 13871 if (ttUSHORT(data+2) != 0) return 0; /* Minor version 0 */ 13872 13873 lookupListOffset = ttUSHORT(data+8); 13874 lookupList = data + lookupListOffset; 13875 lookupCount = ttUSHORT(lookupList); 13876 13877 for (i=0; i<lookupCount; ++i) { 13878 stbtt_uint16 lookupOffset = ttUSHORT(lookupList + 2 + 2 * i); 13879 stbtt_uint8 *lookupTable = lookupList + lookupOffset; 13880 13881 stbtt_uint16 lookupType = ttUSHORT(lookupTable); 13882 stbtt_uint16 subTableCount = ttUSHORT(lookupTable + 4); 13883 stbtt_uint8 *subTableOffsets = lookupTable + 6; 13884 if (lookupType != 2) /* Pair Adjustment Positioning Subtable */ 13885 continue; 13886 13887 for (sti=0; sti<subTableCount; sti++) { 13888 stbtt_uint16 subtableOffset = ttUSHORT(subTableOffsets + 2 * sti); 13889 stbtt_uint8 *table = lookupTable + subtableOffset; 13890 stbtt_uint16 posFormat = ttUSHORT(table); 13891 stbtt_uint16 coverageOffset = ttUSHORT(table + 2); 13892 stbtt_int32 coverageIndex = stbtt__GetCoverageIndex(table + coverageOffset, glyph1); 13893 if (coverageIndex == -1) continue; 13894 13895 switch (posFormat) { 13896 case 1: { 13897 stbtt_int32 l, r, m; 13898 int straw, needle; 13899 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); 13900 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); 13901 if (valueFormat1 == 4 && valueFormat2 == 0) { /* Support more formats? */ 13902 stbtt_int32 valueRecordPairSizeInBytes = 2; 13903 stbtt_uint16 pairSetCount = ttUSHORT(table + 8); 13904 stbtt_uint16 pairPosOffset = ttUSHORT(table + 10 + 2 * coverageIndex); 13905 stbtt_uint8 *pairValueTable = table + pairPosOffset; 13906 stbtt_uint16 pairValueCount = ttUSHORT(pairValueTable); 13907 stbtt_uint8 *pairValueArray = pairValueTable + 2; 13908 13909 if (coverageIndex >= pairSetCount) return 0; 13910 13911 needle=glyph2; 13912 r=pairValueCount-1; 13913 l=0; 13914 13915 /* Binary search. */ 13916 while (l <= r) { 13917 stbtt_uint16 secondGlyph; 13918 stbtt_uint8 *pairValue; 13919 m = (l + r) >> 1; 13920 pairValue = pairValueArray + (2 + valueRecordPairSizeInBytes) * m; 13921 secondGlyph = ttUSHORT(pairValue); 13922 straw = secondGlyph; 13923 if (needle < straw) 13924 r = m - 1; 13925 else if (needle > straw) 13926 l = m + 1; 13927 else { 13928 stbtt_int16 xAdvance = ttSHORT(pairValue + 2); 13929 return xAdvance; 13930 } 13931 } 13932 } else 13933 return 0; 13934 break; 13935 } 13936 13937 case 2: { 13938 stbtt_uint16 valueFormat1 = ttUSHORT(table + 4); 13939 stbtt_uint16 valueFormat2 = ttUSHORT(table + 6); 13940 if (valueFormat1 == 4 && valueFormat2 == 0) { /* Support more formats? */ 13941 stbtt_uint16 classDef1Offset = ttUSHORT(table + 8); 13942 stbtt_uint16 classDef2Offset = ttUSHORT(table + 10); 13943 int glyph1class = stbtt__GetGlyphClass(table + classDef1Offset, glyph1); 13944 int glyph2class = stbtt__GetGlyphClass(table + classDef2Offset, glyph2); 13945 13946 stbtt_uint16 class1Count = ttUSHORT(table + 12); 13947 stbtt_uint16 class2Count = ttUSHORT(table + 14); 13948 stbtt_uint8 *class1Records, *class2Records; 13949 stbtt_int16 xAdvance; 13950 13951 if (glyph1class < 0 || glyph1class >= class1Count) return 0; /* malformed */ 13952 if (glyph2class < 0 || glyph2class >= class2Count) return 0; /* malformed */ 13953 13954 class1Records = table + 16; 13955 class2Records = class1Records + 2 * (glyph1class * class2Count); 13956 xAdvance = ttSHORT(class2Records + 2 * glyph2class); 13957 return xAdvance; 13958 } else 13959 return 0; 13960 break; 13961 } 13962 13963 default: 13964 return 0; /* Unsupported position format */ 13965 } 13966 } 13967 } 13968 13969 return 0; 13970 } 13971 13972 STBTT_DEF int stbtt_GetGlyphKernAdvance(const stbtt_fontinfo *info, int g1, int g2) 13973 { 13974 int xAdvance = 0; 13975 13976 if (info->gpos) 13977 xAdvance += stbtt__GetGlyphGPOSInfoAdvance(info, g1, g2); 13978 else if (info->kern) 13979 xAdvance += stbtt__GetGlyphKernInfoAdvance(info, g1, g2); 13980 13981 return xAdvance; 13982 } 13983 13984 STBTT_DEF int stbtt_GetCodepointKernAdvance(const stbtt_fontinfo *info, int ch1, int ch2) 13985 { 13986 if (!info->kern && !info->gpos) /* if no kerning table, don't waste time looking up both codepoint->glyphs */ 13987 return 0; 13988 return stbtt_GetGlyphKernAdvance(info, stbtt_FindGlyphIndex(info,ch1), stbtt_FindGlyphIndex(info,ch2)); 13989 } 13990 13991 STBTT_DEF void stbtt_GetCodepointHMetrics(const stbtt_fontinfo *info, int codepoint, int *advanceWidth, int *leftSideBearing) 13992 { 13993 stbtt_GetGlyphHMetrics(info, stbtt_FindGlyphIndex(info,codepoint), advanceWidth, leftSideBearing); 13994 } 13995 13996 STBTT_DEF void stbtt_GetFontVMetrics(const stbtt_fontinfo *info, int *ascent, int *descent, int *lineGap) 13997 { 13998 if (ascent ) *ascent = ttSHORT(info->data+info->hhea + 4); 13999 if (descent) *descent = ttSHORT(info->data+info->hhea + 6); 14000 if (lineGap) *lineGap = ttSHORT(info->data+info->hhea + 8); 14001 } 14002 14003 STBTT_DEF int stbtt_GetFontVMetricsOS2(const stbtt_fontinfo *info, int *typoAscent, int *typoDescent, int *typoLineGap) 14004 { 14005 int tab = stbtt__find_table(info->data, info->fontstart, "OS/2"); 14006 if (!tab) 14007 return 0; 14008 if (typoAscent ) *typoAscent = ttSHORT(info->data+tab + 68); 14009 if (typoDescent) *typoDescent = ttSHORT(info->data+tab + 70); 14010 if (typoLineGap) *typoLineGap = ttSHORT(info->data+tab + 72); 14011 return 1; 14012 } 14013 14014 STBTT_DEF void stbtt_GetFontBoundingBox(const stbtt_fontinfo *info, int *x0, int *y0, int *x1, int *y1) 14015 { 14016 *x0 = ttSHORT(info->data + info->head + 36); 14017 *y0 = ttSHORT(info->data + info->head + 38); 14018 *x1 = ttSHORT(info->data + info->head + 40); 14019 *y1 = ttSHORT(info->data + info->head + 42); 14020 } 14021 14022 STBTT_DEF float stbtt_ScaleForPixelHeight(const stbtt_fontinfo *info, float height) 14023 { 14024 int fheight = ttSHORT(info->data + info->hhea + 4) - ttSHORT(info->data + info->hhea + 6); 14025 return (float) height / fheight; 14026 } 14027 14028 STBTT_DEF float stbtt_ScaleForMappingEmToPixels(const stbtt_fontinfo *info, float pixels) 14029 { 14030 int unitsPerEm = ttUSHORT(info->data + info->head + 18); 14031 return pixels / unitsPerEm; 14032 } 14033 14034 STBTT_DEF void stbtt_FreeShape(const stbtt_fontinfo *info, stbtt_vertex *v) 14035 { 14036 STBTT_free(v, info->userdata); 14037 } 14038 14039 STBTT_DEF stbtt_uint8 *stbtt_FindSVGDoc(const stbtt_fontinfo *info, int gl) 14040 { 14041 int i; 14042 stbtt_uint8 *data = info->data; 14043 stbtt_uint8 *svg_doc_list = data + stbtt__get_svg((stbtt_fontinfo *) info); 14044 14045 int numEntries = ttUSHORT(svg_doc_list); 14046 stbtt_uint8 *svg_docs = svg_doc_list + 2; 14047 14048 for(i=0; i<numEntries; i++) { 14049 stbtt_uint8 *svg_doc = svg_docs + (12 * i); 14050 if ((gl >= ttUSHORT(svg_doc)) && (gl <= ttUSHORT(svg_doc + 2))) 14051 return svg_doc; 14052 } 14053 return 0; 14054 } 14055 14056 STBTT_DEF int stbtt_GetGlyphSVG(const stbtt_fontinfo *info, int gl, const char **svg) 14057 { 14058 stbtt_uint8 *data = info->data; 14059 stbtt_uint8 *svg_doc; 14060 14061 if (info->svg == 0) 14062 return 0; 14063 14064 svg_doc = stbtt_FindSVGDoc(info, gl); 14065 if (svg_doc != NULL) { 14066 *svg = (char *) data + info->svg + ttULONG(svg_doc + 4); 14067 return ttULONG(svg_doc + 8); 14068 } else { 14069 return 0; 14070 } 14071 } 14072 14073 STBTT_DEF int stbtt_GetCodepointSVG(const stbtt_fontinfo *info, int unicode_codepoint, const char **svg) 14074 { 14075 return stbtt_GetGlyphSVG(info, stbtt_FindGlyphIndex(info, unicode_codepoint), svg); 14076 } 14077 14078 /* //////////////////////////////////////////////////////////////////////////// */ 14079 /* */ 14080 /* antialiasing software rasterizer */ 14081 /* */ 14082 14083 STBTT_DEF void stbtt_GetGlyphBitmapBoxSubpixel(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y,float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) 14084 { 14085 int x0=0,y0=0,x1,y1; /* =0 suppresses compiler warning */ 14086 if (!stbtt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { 14087 /* e.g. space character */ 14088 if (ix0) *ix0 = 0; 14089 if (iy0) *iy0 = 0; 14090 if (ix1) *ix1 = 0; 14091 if (iy1) *iy1 = 0; 14092 } else { 14093 /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */ 14094 if (ix0) *ix0 = STBTT_ifloor( x0 * scale_x + shift_x); 14095 if (iy0) *iy0 = STBTT_ifloor(-y1 * scale_y + shift_y); 14096 if (ix1) *ix1 = STBTT_iceil ( x1 * scale_x + shift_x); 14097 if (iy1) *iy1 = STBTT_iceil (-y0 * scale_y + shift_y); 14098 } 14099 } 14100 14101 STBTT_DEF void stbtt_GetGlyphBitmapBox(const stbtt_fontinfo *font, int glyph, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) 14102 { 14103 stbtt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); 14104 } 14105 14106 STBTT_DEF void stbtt_GetCodepointBitmapBoxSubpixel(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, float shift_x, float shift_y, int *ix0, int *iy0, int *ix1, int *iy1) 14107 { 14108 stbtt_GetGlyphBitmapBoxSubpixel(font, stbtt_FindGlyphIndex(font,codepoint), scale_x, scale_y,shift_x,shift_y, ix0,iy0,ix1,iy1); 14109 } 14110 14111 STBTT_DEF void stbtt_GetCodepointBitmapBox(const stbtt_fontinfo *font, int codepoint, float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) 14112 { 14113 stbtt_GetCodepointBitmapBoxSubpixel(font, codepoint, scale_x, scale_y,0.0f,0.0f, ix0,iy0,ix1,iy1); 14114 } 14115 14116 /* //////////////////////////////////////////////////////////////////////////// */ 14117 /* */ 14118 /* Rasterizer */ 14119 14120 typedef struct stbtt__hheap_chunk 14121 { 14122 struct stbtt__hheap_chunk *next; 14123 } stbtt__hheap_chunk; 14124 14125 typedef struct stbtt__hheap 14126 { 14127 struct stbtt__hheap_chunk *head; 14128 void *first_free; 14129 int num_remaining_in_head_chunk; 14130 } stbtt__hheap; 14131 14132 static void *stbtt__hheap_alloc(stbtt__hheap *hh, size_t size, void *userdata) 14133 { 14134 if (hh->first_free) { 14135 void *p = hh->first_free; 14136 hh->first_free = * (void **) p; 14137 return p; 14138 } else { 14139 if (hh->num_remaining_in_head_chunk == 0) { 14140 int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); 14141 stbtt__hheap_chunk *c = (stbtt__hheap_chunk *) STBTT_malloc(sizeof(stbtt__hheap_chunk) + size * count, userdata); 14142 if (c == NULL) 14143 return NULL; 14144 c->next = hh->head; 14145 hh->head = c; 14146 hh->num_remaining_in_head_chunk = count; 14147 } 14148 --hh->num_remaining_in_head_chunk; 14149 return (char *) (hh->head) + sizeof(stbtt__hheap_chunk) + size * hh->num_remaining_in_head_chunk; 14150 } 14151 } 14152 14153 static void stbtt__hheap_free(stbtt__hheap *hh, void *p) 14154 { 14155 *(void **) p = hh->first_free; 14156 hh->first_free = p; 14157 } 14158 14159 static void stbtt__hheap_cleanup(stbtt__hheap *hh, void *userdata) 14160 { 14161 stbtt__hheap_chunk *c = hh->head; 14162 while (c) { 14163 stbtt__hheap_chunk *n = c->next; 14164 STBTT_free(c, userdata); 14165 c = n; 14166 } 14167 } 14168 14169 typedef struct stbtt__edge { 14170 float x0,y0, x1,y1; 14171 int invert; 14172 } stbtt__edge; 14173 14174 14175 typedef struct stbtt__active_edge 14176 { 14177 struct stbtt__active_edge *next; 14178 #if STBTT_RASTERIZER_VERSION==1 14179 int x,dx; 14180 float ey; 14181 int direction; 14182 #elif STBTT_RASTERIZER_VERSION==2 14183 float fx,fdx,fdy; 14184 float direction; 14185 float sy; 14186 float ey; 14187 #else 14188 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 14189 #endif 14190 } stbtt__active_edge; 14191 14192 #if STBTT_RASTERIZER_VERSION == 1 14193 #define STBTT_FIXSHIFT 10 14194 #define STBTT_FIX (1 << STBTT_FIXSHIFT) 14195 #define STBTT_FIXMASK (STBTT_FIX-1) 14196 14197 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) 14198 { 14199 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); 14200 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); 14201 STBTT_assert(z != NULL); 14202 if (!z) return z; 14203 14204 /* round dx down to avoid overshooting */ 14205 if (dxdy < 0) 14206 z->dx = -STBTT_ifloor(STBTT_FIX * -dxdy); 14207 else 14208 z->dx = STBTT_ifloor(STBTT_FIX * dxdy); 14209 14210 z->x = STBTT_ifloor(STBTT_FIX * e->x0 + z->dx * (start_point - e->y0)); /* use z->dx so when we offset later it's by the same amount */ 14211 z->x -= off_x * STBTT_FIX; 14212 14213 z->ey = e->y1; 14214 z->next = 0; 14215 z->direction = e->invert ? 1 : -1; 14216 return z; 14217 } 14218 #elif STBTT_RASTERIZER_VERSION == 2 14219 static stbtt__active_edge *stbtt__new_active(stbtt__hheap *hh, stbtt__edge *e, int off_x, float start_point, void *userdata) 14220 { 14221 stbtt__active_edge *z = (stbtt__active_edge *) stbtt__hheap_alloc(hh, sizeof(*z), userdata); 14222 float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); 14223 STBTT_assert(z != NULL); 14224 /* STBTT_assert(e->y0 <= start_point); */ 14225 if (!z) return z; 14226 z->fdx = dxdy; 14227 z->fdy = dxdy != 0.0f ? (1.0f/dxdy) : 0.0f; 14228 z->fx = e->x0 + dxdy * (start_point - e->y0); 14229 z->fx -= off_x; 14230 z->direction = e->invert ? 1.0f : -1.0f; 14231 z->sy = e->y0; 14232 z->ey = e->y1; 14233 z->next = 0; 14234 return z; 14235 } 14236 #else 14237 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 14238 #endif 14239 14240 #if STBTT_RASTERIZER_VERSION == 1 14241 /* note: this routine clips fills that extend off the edges... ideally this */ 14242 /* wouldn't happen, but it could happen if the truetype glyph bounding boxes */ 14243 /* are wrong, or if the user supplies a too-small bitmap */ 14244 static void stbtt__fill_active_edges(unsigned char *scanline, int len, stbtt__active_edge *e, int max_weight) 14245 { 14246 /* non-zero winding fill */ 14247 int x0=0, w=0; 14248 14249 while (e) { 14250 if (w == 0) { 14251 /* if we're currently at zero, we need to record the edge start point */ 14252 x0 = e->x; w += e->direction; 14253 } else { 14254 int x1 = e->x; w += e->direction; 14255 /* if we went to zero, we need to draw */ 14256 if (w == 0) { 14257 int i = x0 >> STBTT_FIXSHIFT; 14258 int j = x1 >> STBTT_FIXSHIFT; 14259 14260 if (i < len && j >= 0) { 14261 if (i == j) { 14262 /* x0,x1 are the same pixel, so compute combined coverage */ 14263 scanline[i] = scanline[i] + (stbtt_uint8) ((x1 - x0) * max_weight >> STBTT_FIXSHIFT); 14264 } else { 14265 if (i >= 0) /* add antialiasing for x0 */ 14266 scanline[i] = scanline[i] + (stbtt_uint8) (((STBTT_FIX - (x0 & STBTT_FIXMASK)) * max_weight) >> STBTT_FIXSHIFT); 14267 else 14268 i = -1; /* clip */ 14269 14270 if (j < len) /* add antialiasing for x1 */ 14271 scanline[j] = scanline[j] + (stbtt_uint8) (((x1 & STBTT_FIXMASK) * max_weight) >> STBTT_FIXSHIFT); 14272 else 14273 j = len; /* clip */ 14274 14275 for (++i; i < j; ++i) /* fill pixels between x0 and x1 */ 14276 scanline[i] = scanline[i] + (stbtt_uint8) max_weight; 14277 } 14278 } 14279 } 14280 } 14281 14282 e = e->next; 14283 } 14284 } 14285 14286 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) 14287 { 14288 stbtt__hheap hh = { 0, 0, 0 }; 14289 stbtt__active_edge *active = NULL; 14290 int y,j=0; 14291 int max_weight = (255 / vsubsample); /* weight per vertical scanline */ 14292 int s; /* vertical subsample index */ 14293 unsigned char scanline_data[512], *scanline; 14294 14295 if (result->w > 512) 14296 scanline = (unsigned char *) STBTT_malloc(result->w, userdata); 14297 else 14298 scanline = scanline_data; 14299 14300 y = off_y * vsubsample; 14301 e[n].y0 = (off_y + result->h) * (float) vsubsample + 1; 14302 14303 while (j < result->h) { 14304 STBTT_memset(scanline, 0, result->w); 14305 for (s=0; s < vsubsample; ++s) { 14306 /* find center of pixel for this scanline */ 14307 float scan_y = y + 0.5f; 14308 stbtt__active_edge **step = &active; 14309 14310 /* update all active edges; */ 14311 /* remove all active edges that terminate before the center of this scanline */ 14312 while (*step) { 14313 stbtt__active_edge * z = *step; 14314 if (z->ey <= scan_y) { 14315 *step = z->next; /* delete from list */ 14316 STBTT_assert(z->direction); 14317 z->direction = 0; 14318 stbtt__hheap_free(&hh, z); 14319 } else { 14320 z->x += z->dx; /* advance to position for current scanline */ 14321 step = &((*step)->next); /* advance through list */ 14322 } 14323 } 14324 14325 /* resort the list if needed */ 14326 for(;;) { 14327 int changed=0; 14328 step = &active; 14329 while (*step && (*step)->next) { 14330 if ((*step)->x > (*step)->next->x) { 14331 stbtt__active_edge *t = *step; 14332 stbtt__active_edge *q = t->next; 14333 14334 t->next = q->next; 14335 q->next = t; 14336 *step = q; 14337 changed = 1; 14338 } 14339 step = &(*step)->next; 14340 } 14341 if (!changed) break; 14342 } 14343 14344 /* insert all edges that start before the center of this scanline -- omit ones that also end on this scanline */ 14345 while (e->y0 <= scan_y) { 14346 if (e->y1 > scan_y) { 14347 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y, userdata); 14348 if (z != NULL) { 14349 /* find insertion point */ 14350 if (active == NULL) 14351 active = z; 14352 else if (z->x < active->x) { 14353 /* insert at front */ 14354 z->next = active; 14355 active = z; 14356 } else { 14357 /* find thing to insert AFTER */ 14358 stbtt__active_edge *p = active; 14359 while (p->next && p->next->x < z->x) 14360 p = p->next; 14361 /* at this point, p->next->x is NOT < z->x */ 14362 z->next = p->next; 14363 p->next = z; 14364 } 14365 } 14366 } 14367 ++e; 14368 } 14369 14370 /* now process all active edges in XOR fashion */ 14371 if (active) 14372 stbtt__fill_active_edges(scanline, result->w, active, max_weight); 14373 14374 ++y; 14375 } 14376 STBTT_memcpy(result->pixels + j * result->stride, scanline, result->w); 14377 ++j; 14378 } 14379 14380 stbtt__hheap_cleanup(&hh, userdata); 14381 14382 if (scanline != scanline_data) 14383 STBTT_free(scanline, userdata); 14384 } 14385 14386 #elif STBTT_RASTERIZER_VERSION == 2 14387 14388 /* the edge passed in here does not cross the vertical line at x or the vertical line at x+1 */ 14389 /* (i.e. it has already been clipped to those) */ 14390 static void stbtt__handle_clipped_edge(float *scanline, int x, stbtt__active_edge *e, float x0, float y0, float x1, float y1) 14391 { 14392 if (y0 == y1) return; 14393 STBTT_assert(y0 < y1); 14394 STBTT_assert(e->sy <= e->ey); 14395 if (y0 > e->ey) return; 14396 if (y1 < e->sy) return; 14397 if (y0 < e->sy) { 14398 x0 += (x1-x0) * (e->sy - y0) / (y1-y0); 14399 y0 = e->sy; 14400 } 14401 if (y1 > e->ey) { 14402 x1 += (x1-x0) * (e->ey - y1) / (y1-y0); 14403 y1 = e->ey; 14404 } 14405 14406 if (x0 == x) 14407 STBTT_assert(x1 <= x+1); 14408 else if (x0 == x+1) 14409 STBTT_assert(x1 >= x); 14410 else if (x0 <= x) 14411 STBTT_assert(x1 <= x); 14412 else if (x0 >= x+1) 14413 STBTT_assert(x1 >= x+1); 14414 else 14415 STBTT_assert(x1 >= x && x1 <= x+1); 14416 14417 if (x0 <= x && x1 <= x) 14418 scanline[x] += e->direction * (y1-y0); 14419 else if (x0 >= x+1 && x1 >= x+1) 14420 ; 14421 else { 14422 STBTT_assert(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); 14423 scanline[x] += e->direction * (y1-y0) * (1-((x0-x)+(x1-x))/2); /* coverage = 1 - average x position */ 14424 } 14425 } 14426 14427 static float stbtt__sized_trapezoid_area(float height, float top_width, float bottom_width) 14428 { 14429 STBTT_assert(top_width >= 0); 14430 STBTT_assert(bottom_width >= 0); 14431 return (top_width + bottom_width) / 2.0f * height; 14432 } 14433 14434 static float stbtt__position_trapezoid_area(float height, float tx0, float tx1, float bx0, float bx1) 14435 { 14436 return stbtt__sized_trapezoid_area(height, tx1 - tx0, bx1 - bx0); 14437 } 14438 14439 static float stbtt__sized_triangle_area(float height, float width) 14440 { 14441 return height * width / 2; 14442 } 14443 14444 static void stbtt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, stbtt__active_edge *e, float y_top) 14445 { 14446 float y_bottom = y_top+1; 14447 14448 while (e) { 14449 /* brute force every pixel */ 14450 14451 /* compute intersection points with top & bottom */ 14452 STBTT_assert(e->ey >= y_top); 14453 14454 if (e->fdx == 0) { 14455 float x0 = e->fx; 14456 if (x0 < len) { 14457 if (x0 >= 0) { 14458 stbtt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); 14459 stbtt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); 14460 } else { 14461 stbtt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); 14462 } 14463 } 14464 } else { 14465 float x0 = e->fx; 14466 float dx = e->fdx; 14467 float xb = x0 + dx; 14468 float x_top, x_bottom; 14469 float sy0,sy1; 14470 float dy = e->fdy; 14471 STBTT_assert(e->sy <= y_bottom && e->ey >= y_top); 14472 14473 /* compute endpoints of line segment clipped to this scanline (if the */ 14474 /* line segment starts on this scanline. x0 is the intersection of the */ 14475 /* line with y_top, but that may be off the line segment. */ 14476 if (e->sy > y_top) { 14477 x_top = x0 + dx * (e->sy - y_top); 14478 sy0 = e->sy; 14479 } else { 14480 x_top = x0; 14481 sy0 = y_top; 14482 } 14483 if (e->ey < y_bottom) { 14484 x_bottom = x0 + dx * (e->ey - y_top); 14485 sy1 = e->ey; 14486 } else { 14487 x_bottom = xb; 14488 sy1 = y_bottom; 14489 } 14490 14491 if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) { 14492 /* from here on, we don't have to range check x values */ 14493 14494 if ((int) x_top == (int) x_bottom) { 14495 float height; 14496 /* simple case, only spans one pixel */ 14497 int x = (int) x_top; 14498 height = (sy1 - sy0) * e->direction; 14499 STBTT_assert(x >= 0 && x < len); 14500 scanline[x] += stbtt__position_trapezoid_area(height, x_top, x+1.0f, x_bottom, x+1.0f); 14501 scanline_fill[x] += height; /* everything right of this pixel is filled */ 14502 } else { 14503 int x,x1,x2; 14504 float y_crossing, y_final, step, sign, area; 14505 /* covers 2+ pixels */ 14506 if (x_top > x_bottom) { 14507 /* flip scanline vertically; signed area is the same */ 14508 float t; 14509 sy0 = y_bottom - (sy0 - y_top); 14510 sy1 = y_bottom - (sy1 - y_top); 14511 t = sy0, sy0 = sy1, sy1 = t; 14512 t = x_bottom, x_bottom = x_top, x_top = t; 14513 dx = -dx; 14514 dy = -dy; 14515 t = x0, x0 = xb, xb = t; 14516 } 14517 STBTT_assert(dy >= 0); 14518 STBTT_assert(dx >= 0); 14519 14520 x1 = (int) x_top; 14521 x2 = (int) x_bottom; 14522 /* compute intersection with y axis at x1+1 */ 14523 y_crossing = y_top + dy * (x1+1 - x0); 14524 14525 /* compute intersection with y axis at x2 */ 14526 y_final = y_top + dy * (x2 - x0); 14527 14528 /* x1 x_top x2 x_bottom */ 14529 /* y_top +------|-----+------------+------------+--------|---+------------+ */ 14530 /* | | | | | | */ 14531 /* | | | | | | */ 14532 /* sy0 | Txxxxx|............|............|............|............| */ 14533 /* y_crossing | *xxxxx.......|............|............|............| */ 14534 /* | | xxxxx..|............|............|............| */ 14535 /* | | /- xx*xxxx........|............|............| */ 14536 /* | | dy < | xxxxxx..|............|............| */ 14537 /* y_final | | \- | xx*xxx.........|............| */ 14538 /* sy1 | | | | xxxxxB...|............| */ 14539 /* | | | | | | */ 14540 /* | | | | | | */ 14541 /* y_bottom +------------+------------+------------+------------+------------+ */ 14542 /* */ 14543 /* goal is to measure the area covered by '.' in each pixel */ 14544 14545 /* if x2 is right at the right edge of x1, y_crossing can blow up, github #1057 */ 14546 /* @TODO: maybe test against sy1 rather than y_bottom? */ 14547 if (y_crossing > y_bottom) 14548 y_crossing = y_bottom; 14549 14550 sign = e->direction; 14551 14552 /* area of the rectangle covered from sy0..y_crossing */ 14553 area = sign * (y_crossing-sy0); 14554 14555 /* area of the triangle (x_top,sy0), (x1+1,sy0), (x1+1,y_crossing) */ 14556 scanline[x1] += stbtt__sized_triangle_area(area, x1+1 - x_top); 14557 14558 /* check if final y_crossing is blown up; no test case for this */ 14559 if (y_final > y_bottom) { 14560 y_final = y_bottom; 14561 dy = (y_final - y_crossing ) / (x2 - (x1+1)); /* if denom=0, y_final = y_crossing, so y_final <= y_bottom */ 14562 } 14563 14564 /* in second pixel, area covered by line segment found in first pixel */ 14565 /* is always a rectangle 1 wide * the height of that line segment; this */ 14566 /* is exactly what the variable 'area' stores. it also gets a contribution */ 14567 /* from the line segment within it. the THIRD pixel will get the first */ 14568 /* pixel's rectangle contribution, the second pixel's rectangle contribution, */ 14569 /* and its own contribution. the 'own contribution' is the same in every pixel except */ 14570 /* the leftmost and rightmost, a trapezoid that slides down in each pixel. */ 14571 /* the second pixel's contribution to the third pixel will be the */ 14572 /* rectangle 1 wide times the height change in the second pixel, which is dy. */ 14573 14574 step = sign * dy * 1; /* dy is dy/dx, change in y for every 1 change in x, */ 14575 /* which multiplied by 1-pixel-width is how much pixel area changes for each step in x */ 14576 /* so the area advances by 'step' every time */ 14577 14578 for (x = x1+1; x < x2; ++x) { 14579 scanline[x] += area + step/2; /* area of trapezoid is 1*step/2 */ 14580 area += step; 14581 } 14582 STBTT_assert(STBTT_fabs(area) <= 1.01f); /* accumulated error from area += step unless we round step down */ 14583 STBTT_assert(sy1 > y_final-0.01f); 14584 14585 /* area covered in the last pixel is the rectangle from all the pixels to the left, */ 14586 /* plus the trapezoid filled by the line segment in this pixel all the way to the right edge */ 14587 scanline[x2] += area + sign * stbtt__position_trapezoid_area(sy1-y_final, (float) x2, x2+1.0f, x_bottom, x2+1.0f); 14588 14589 /* the rest of the line is filled based on the total height of the line segment in this pixel */ 14590 scanline_fill[x2] += sign * (sy1-sy0); 14591 } 14592 } else { 14593 /* if edge goes outside of box we're drawing, we require */ 14594 /* clipping logic. since this does not match the intended use */ 14595 /* of this library, we use a different, very slow brute */ 14596 /* force implementation */ 14597 /* note though that this does happen some of the time because */ 14598 /* x_top and x_bottom can be extrapolated at the top & bottom of */ 14599 /* the shape and actually lie outside the bounding box */ 14600 int x; 14601 for (x=0; x < len; ++x) { 14602 /* cases: */ 14603 /* */ 14604 /* there can be up to two intersections with the pixel. any intersection */ 14605 /* with left or right edges can be handled by splitting into two (or three) */ 14606 /* regions. intersections with top & bottom do not necessitate case-wise logic. */ 14607 /* */ 14608 /* the old way of doing this found the intersections with the left & right edges, */ 14609 /* then used some simple logic to produce up to three segments in sorted order */ 14610 /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */ 14611 /* across the x border, then the corresponding y position might not be distinct */ 14612 /* from the other y segment, and it might ignored as an empty segment. to avoid */ 14613 /* that, we need to explicitly produce segments based on x positions. */ 14614 14615 /* rename variables to clearly-defined pairs */ 14616 float y0 = y_top; 14617 float x1 = (float) (x); 14618 float x2 = (float) (x+1); 14619 float x3 = xb; 14620 float y3 = y_bottom; 14621 14622 /* x = e->x + e->dx * (y-y_top) */ 14623 /* (y-y_top) = (x - e->x) / e->dx */ 14624 /* y = (x - e->x) / e->dx + y_top */ 14625 float y1 = (x - x0) / dx + y_top; 14626 float y2 = (x+1 - x0) / dx + y_top; 14627 14628 if (x0 < x1 && x3 > x2) { /* three segments descending down-right */ 14629 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); 14630 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x2,y2); 14631 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 14632 } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */ 14633 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); 14634 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x1,y1); 14635 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); 14636 } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */ 14637 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); 14638 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); 14639 } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */ 14640 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x1,y1); 14641 stbtt__handle_clipped_edge(scanline,x,e, x1,y1, x3,y3); 14642 } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */ 14643 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); 14644 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 14645 } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */ 14646 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x2,y2); 14647 stbtt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); 14648 } else { /* one segment */ 14649 stbtt__handle_clipped_edge(scanline,x,e, x0,y0, x3,y3); 14650 } 14651 } 14652 } 14653 } 14654 e = e->next; 14655 } 14656 } 14657 14658 /* directly AA rasterize edges w/o supersampling */ 14659 static void stbtt__rasterize_sorted_edges(stbtt__bitmap *result, stbtt__edge *e, int n, int vsubsample, int off_x, int off_y, void *userdata) 14660 { 14661 stbtt__hheap hh = { 0, 0, 0 }; 14662 stbtt__active_edge *active = NULL; 14663 int y,j=0, i; 14664 float scanline_data[129], *scanline, *scanline2; 14665 14666 STBTT__NOTUSED(vsubsample); 14667 14668 if (result->w > 64) 14669 scanline = (float *) STBTT_malloc((result->w*2+1) * sizeof(float), userdata); 14670 else 14671 scanline = scanline_data; 14672 14673 scanline2 = scanline + result->w; 14674 14675 y = off_y; 14676 e[n].y0 = (float) (off_y + result->h) + 1; 14677 14678 while (j < result->h) { 14679 /* find center of pixel for this scanline */ 14680 float scan_y_top = y + 0.0f; 14681 float scan_y_bottom = y + 1.0f; 14682 stbtt__active_edge **step = &active; 14683 14684 STBTT_memset(scanline , 0, result->w*sizeof(scanline[0])); 14685 STBTT_memset(scanline2, 0, (result->w+1)*sizeof(scanline[0])); 14686 14687 /* update all active edges; */ 14688 /* remove all active edges that terminate before the top of this scanline */ 14689 while (*step) { 14690 stbtt__active_edge * z = *step; 14691 if (z->ey <= scan_y_top) { 14692 *step = z->next; /* delete from list */ 14693 STBTT_assert(z->direction); 14694 z->direction = 0; 14695 stbtt__hheap_free(&hh, z); 14696 } else { 14697 step = &((*step)->next); /* advance through list */ 14698 } 14699 } 14700 14701 /* insert all edges that start before the bottom of this scanline */ 14702 while (e->y0 <= scan_y_bottom) { 14703 if (e->y0 != e->y1) { 14704 stbtt__active_edge *z = stbtt__new_active(&hh, e, off_x, scan_y_top, userdata); 14705 if (z != NULL) { 14706 if (j == 0 && off_y != 0) { 14707 if (z->ey < scan_y_top) { 14708 /* this can happen due to subpixel positioning and some kind of fp rounding error i think */ 14709 z->ey = scan_y_top; 14710 } 14711 } 14712 STBTT_assert(z->ey >= scan_y_top); /* if we get really unlucky a tiny bit of an edge can be out of bounds */ 14713 /* insert at front */ 14714 z->next = active; 14715 active = z; 14716 } 14717 } 14718 ++e; 14719 } 14720 14721 /* now process all active edges */ 14722 if (active) 14723 stbtt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); 14724 14725 { 14726 float sum = 0; 14727 for (i=0; i < result->w; ++i) { 14728 float k; 14729 int m; 14730 sum += scanline2[i]; 14731 k = scanline[i] + sum; 14732 k = (float) STBTT_fabs(k)*255 + 0.5f; 14733 m = (int) k; 14734 if (m > 255) m = 255; 14735 result->pixels[j*result->stride + i] = (unsigned char) m; 14736 } 14737 } 14738 /* advance all the edges */ 14739 step = &active; 14740 while (*step) { 14741 stbtt__active_edge *z = *step; 14742 z->fx += z->fdx; /* advance to position for current scanline */ 14743 step = &((*step)->next); /* advance through list */ 14744 } 14745 14746 ++y; 14747 ++j; 14748 } 14749 14750 stbtt__hheap_cleanup(&hh, userdata); 14751 14752 if (scanline != scanline_data) 14753 STBTT_free(scanline, userdata); 14754 } 14755 #else 14756 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 14757 #endif 14758 14759 #define STBTT__COMPARE(a,b) ((a)->y0 < (b)->y0) 14760 14761 static void stbtt__sort_edges_ins_sort(stbtt__edge *p, int n) 14762 { 14763 int i,j; 14764 for (i=1; i < n; ++i) { 14765 stbtt__edge t = p[i], *a = &t; 14766 j = i; 14767 while (j > 0) { 14768 stbtt__edge *b = &p[j-1]; 14769 int c = STBTT__COMPARE(a,b); 14770 if (!c) break; 14771 p[j] = p[j-1]; 14772 --j; 14773 } 14774 if (i != j) 14775 p[j] = t; 14776 } 14777 } 14778 14779 static void stbtt__sort_edges_quicksort(stbtt__edge *p, int n) 14780 { 14781 /* threshold for transitioning to insertion sort */ 14782 while (n > 12) { 14783 stbtt__edge t; 14784 int c01,c12,c,m,i,j; 14785 14786 /* compute median of three */ 14787 m = n >> 1; 14788 c01 = STBTT__COMPARE(&p[0],&p[m]); 14789 c12 = STBTT__COMPARE(&p[m],&p[n-1]); 14790 /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ 14791 if (c01 != c12) { 14792 /* otherwise, we'll need to swap something else to middle */ 14793 int z; 14794 c = STBTT__COMPARE(&p[0],&p[n-1]); 14795 /* 0>mid && mid<n: 0>n => n; 0<n => 0 */ 14796 /* 0<mid && mid>n: 0>n => 0; 0<n => n */ 14797 z = (c == c12) ? 0 : n-1; 14798 t = p[z]; 14799 p[z] = p[m]; 14800 p[m] = t; 14801 } 14802 /* now p[m] is the median-of-three */ 14803 /* swap it to the beginning so it won't move around */ 14804 t = p[0]; 14805 p[0] = p[m]; 14806 p[m] = t; 14807 14808 /* partition loop */ 14809 i=1; 14810 j=n-1; 14811 for(;;) { 14812 /* handling of equality is crucial here */ 14813 /* for sentinels & efficiency with duplicates */ 14814 for (;;++i) { 14815 if (!STBTT__COMPARE(&p[i], &p[0])) break; 14816 } 14817 for (;;--j) { 14818 if (!STBTT__COMPARE(&p[0], &p[j])) break; 14819 } 14820 /* make sure we haven't crossed */ 14821 if (i >= j) break; 14822 t = p[i]; 14823 p[i] = p[j]; 14824 p[j] = t; 14825 14826 ++i; 14827 --j; 14828 } 14829 /* recurse on smaller side, iterate on larger */ 14830 if (j < (n-i)) { 14831 stbtt__sort_edges_quicksort(p,j); 14832 p = p+i; 14833 n = n-i; 14834 } else { 14835 stbtt__sort_edges_quicksort(p+i, n-i); 14836 n = j; 14837 } 14838 } 14839 } 14840 14841 static void stbtt__sort_edges(stbtt__edge *p, int n) 14842 { 14843 stbtt__sort_edges_quicksort(p, n); 14844 stbtt__sort_edges_ins_sort(p, n); 14845 } 14846 14847 typedef struct 14848 { 14849 float x,y; 14850 } stbtt__point; 14851 14852 static void stbtt__rasterize(stbtt__bitmap *result, stbtt__point *pts, int *wcount, int windings, float scale_x, float scale_y, float shift_x, float shift_y, int off_x, int off_y, int invert, void *userdata) 14853 { 14854 float y_scale_inv = invert ? -scale_y : scale_y; 14855 stbtt__edge *e; 14856 int n,i,j,k,m; 14857 #if STBTT_RASTERIZER_VERSION == 1 14858 int vsubsample = result->h < 8 ? 15 : 5; 14859 #elif STBTT_RASTERIZER_VERSION == 2 14860 int vsubsample = 1; 14861 #else 14862 #error "Unrecognized value of STBTT_RASTERIZER_VERSION" 14863 #endif 14864 /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */ 14865 14866 /* now we have to blow out the windings into explicit edge lists */ 14867 n = 0; 14868 for (i=0; i < windings; ++i) 14869 n += wcount[i]; 14870 14871 e = (stbtt__edge *) STBTT_malloc(sizeof(*e) * (n+1), userdata); /* add an extra one as a sentinel */ 14872 if (e == 0) return; 14873 n = 0; 14874 14875 m=0; 14876 for (i=0; i < windings; ++i) { 14877 stbtt__point *p = pts + m; 14878 m += wcount[i]; 14879 j = wcount[i]-1; 14880 for (k=0; k < wcount[i]; j=k++) { 14881 int a=k,b=j; 14882 /* skip the edge if horizontal */ 14883 if (p[j].y == p[k].y) 14884 continue; 14885 /* add edge from j to k to the list */ 14886 e[n].invert = 0; 14887 if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { 14888 e[n].invert = 1; 14889 a=j,b=k; 14890 } 14891 e[n].x0 = p[a].x * scale_x + shift_x; 14892 e[n].y0 = (p[a].y * y_scale_inv + shift_y) * vsubsample; 14893 e[n].x1 = p[b].x * scale_x + shift_x; 14894 e[n].y1 = (p[b].y * y_scale_inv + shift_y) * vsubsample; 14895 ++n; 14896 } 14897 } 14898 14899 /* now sort the edges by their highest point (should snap to integer, and then by x) */ 14900 /* STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); */ 14901 stbtt__sort_edges(e, n); 14902 14903 /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */ 14904 stbtt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, userdata); 14905 14906 STBTT_free(e, userdata); 14907 } 14908 14909 static void stbtt__add_point(stbtt__point *points, int n, float x, float y) 14910 { 14911 if (!points) return; /* during first pass, it's unallocated */ 14912 points[n].x = x; 14913 points[n].y = y; 14914 } 14915 14916 /* tessellate until threshold p is happy... @TODO warped to compensate for non-linear stretching */ 14917 static int stbtt__tesselate_curve(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float objspace_flatness_squared, int n) 14918 { 14919 /* midpoint */ 14920 float mx = (x0 + 2*x1 + x2)/4; 14921 float my = (y0 + 2*y1 + y2)/4; 14922 /* versus directly drawn line */ 14923 float dx = (x0+x2)/2 - mx; 14924 float dy = (y0+y2)/2 - my; 14925 if (n > 16) /* 65536 segments on one curve better be enough! */ 14926 return 1; 14927 if (dx*dx+dy*dy > objspace_flatness_squared) { /* half-pixel error allowed... need to be smaller if AA */ 14928 stbtt__tesselate_curve(points, num_points, x0,y0, (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); 14929 stbtt__tesselate_curve(points, num_points, mx,my, (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); 14930 } else { 14931 stbtt__add_point(points, *num_points,x2,y2); 14932 *num_points = *num_points+1; 14933 } 14934 return 1; 14935 } 14936 14937 static void stbtt__tesselate_cubic(stbtt__point *points, int *num_points, float x0, float y0, float x1, float y1, float x2, float y2, float x3, float y3, float objspace_flatness_squared, int n) 14938 { 14939 /* @TODO this "flatness" calculation is just made-up nonsense that seems to work well enough */ 14940 float dx0 = x1-x0; 14941 float dy0 = y1-y0; 14942 float dx1 = x2-x1; 14943 float dy1 = y2-y1; 14944 float dx2 = x3-x2; 14945 float dy2 = y3-y2; 14946 float dx = x3-x0; 14947 float dy = y3-y0; 14948 float longlen = (float) (STBTT_sqrt(dx0*dx0+dy0*dy0)+STBTT_sqrt(dx1*dx1+dy1*dy1)+STBTT_sqrt(dx2*dx2+dy2*dy2)); 14949 float shortlen = (float) STBTT_sqrt(dx*dx+dy*dy); 14950 float flatness_squared = longlen*longlen-shortlen*shortlen; 14951 14952 if (n > 16) /* 65536 segments on one curve better be enough! */ 14953 return; 14954 14955 if (flatness_squared > objspace_flatness_squared) { 14956 float x01 = (x0+x1)/2; 14957 float y01 = (y0+y1)/2; 14958 float x12 = (x1+x2)/2; 14959 float y12 = (y1+y2)/2; 14960 float x23 = (x2+x3)/2; 14961 float y23 = (y2+y3)/2; 14962 14963 float xa = (x01+x12)/2; 14964 float ya = (y01+y12)/2; 14965 float xb = (x12+x23)/2; 14966 float yb = (y12+y23)/2; 14967 14968 float mx = (xa+xb)/2; 14969 float my = (ya+yb)/2; 14970 14971 stbtt__tesselate_cubic(points, num_points, x0,y0, x01,y01, xa,ya, mx,my, objspace_flatness_squared,n+1); 14972 stbtt__tesselate_cubic(points, num_points, mx,my, xb,yb, x23,y23, x3,y3, objspace_flatness_squared,n+1); 14973 } else { 14974 stbtt__add_point(points, *num_points,x3,y3); 14975 *num_points = *num_points+1; 14976 } 14977 } 14978 14979 /* returns number of contours */ 14980 static stbtt__point *stbtt_FlattenCurves(stbtt_vertex *vertices, int num_verts, float objspace_flatness, int **contour_lengths, int *num_contours, void *userdata) 14981 { 14982 stbtt__point *points=0; 14983 int num_points=0; 14984 14985 float objspace_flatness_squared = objspace_flatness * objspace_flatness; 14986 int i,n=0,start=0, pass; 14987 14988 /* count how many "moves" there are to get the contour count */ 14989 for (i=0; i < num_verts; ++i) 14990 if (vertices[i].type == STBTT_vmove) 14991 ++n; 14992 14993 *num_contours = n; 14994 if (n == 0) return 0; 14995 14996 *contour_lengths = (int *) STBTT_malloc(sizeof(**contour_lengths) * n, userdata); 14997 14998 if (*contour_lengths == 0) { 14999 *num_contours = 0; 15000 return 0; 15001 } 15002 15003 /* make two passes through the points so we don't need to realloc */ 15004 for (pass=0; pass < 2; ++pass) { 15005 float x=0,y=0; 15006 if (pass == 1) { 15007 points = (stbtt__point *) STBTT_malloc(num_points * sizeof(points[0]), userdata); 15008 if (points == NULL) goto error; 15009 } 15010 num_points = 0; 15011 n= -1; 15012 for (i=0; i < num_verts; ++i) { 15013 switch (vertices[i].type) { 15014 case STBTT_vmove: 15015 /* start the next contour */ 15016 if (n >= 0) 15017 (*contour_lengths)[n] = num_points - start; 15018 ++n; 15019 start = num_points; 15020 15021 x = vertices[i].x, y = vertices[i].y; 15022 stbtt__add_point(points, num_points++, x,y); 15023 break; 15024 case STBTT_vline: 15025 x = vertices[i].x, y = vertices[i].y; 15026 stbtt__add_point(points, num_points++, x, y); 15027 break; 15028 case STBTT_vcurve: 15029 stbtt__tesselate_curve(points, &num_points, x,y, 15030 vertices[i].cx, vertices[i].cy, 15031 vertices[i].x, vertices[i].y, 15032 objspace_flatness_squared, 0); 15033 x = vertices[i].x, y = vertices[i].y; 15034 break; 15035 case STBTT_vcubic: 15036 stbtt__tesselate_cubic(points, &num_points, x,y, 15037 vertices[i].cx, vertices[i].cy, 15038 vertices[i].cx1, vertices[i].cy1, 15039 vertices[i].x, vertices[i].y, 15040 objspace_flatness_squared, 0); 15041 x = vertices[i].x, y = vertices[i].y; 15042 break; 15043 } 15044 } 15045 (*contour_lengths)[n] = num_points - start; 15046 } 15047 15048 return points; 15049 error: 15050 STBTT_free(points, userdata); 15051 STBTT_free(*contour_lengths, userdata); 15052 *contour_lengths = 0; 15053 *num_contours = 0; 15054 return NULL; 15055 } 15056 15057 STBTT_DEF void stbtt_Rasterize(stbtt__bitmap *result, float flatness_in_pixels, stbtt_vertex *vertices, int num_verts, float scale_x, float scale_y, float shift_x, float shift_y, int x_off, int y_off, int invert, void *userdata) 15058 { 15059 float scale = scale_x > scale_y ? scale_y : scale_x; 15060 int winding_count = 0; 15061 int *winding_lengths = NULL; 15062 stbtt__point *windings = stbtt_FlattenCurves(vertices, num_verts, flatness_in_pixels / scale, &winding_lengths, &winding_count, userdata); 15063 if (windings) { 15064 stbtt__rasterize(result, windings, winding_lengths, winding_count, scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, userdata); 15065 STBTT_free(winding_lengths, userdata); 15066 STBTT_free(windings, userdata); 15067 } 15068 } 15069 15070 STBTT_DEF void stbtt_FreeBitmap(unsigned char *bitmap, void *userdata) 15071 { 15072 STBTT_free(bitmap, userdata); 15073 } 15074 15075 STBTT_DEF unsigned char *stbtt_GetGlyphBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int glyph, int *width, int *height, int *xoff, int *yoff) 15076 { 15077 int ix0,iy0,ix1,iy1; 15078 stbtt__bitmap gbm; 15079 stbtt_vertex *vertices; 15080 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); 15081 15082 if (scale_x == 0) scale_x = scale_y; 15083 if (scale_y == 0) { 15084 if (scale_x == 0) { 15085 STBTT_free(vertices, info->userdata); 15086 return NULL; 15087 } 15088 scale_y = scale_x; 15089 } 15090 15091 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,&ix1,&iy1); 15092 15093 /* now we get the size */ 15094 gbm.w = (ix1 - ix0); 15095 gbm.h = (iy1 - iy0); 15096 gbm.pixels = NULL; /* in case we error */ 15097 15098 if (width ) *width = gbm.w; 15099 if (height) *height = gbm.h; 15100 if (xoff ) *xoff = ix0; 15101 if (yoff ) *yoff = iy0; 15102 15103 if (gbm.w && gbm.h) { 15104 gbm.pixels = (unsigned char *) STBTT_malloc(gbm.w * gbm.h, info->userdata); 15105 if (gbm.pixels) { 15106 gbm.stride = gbm.w; 15107 15108 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0, iy0, 1, info->userdata); 15109 } 15110 } 15111 STBTT_free(vertices, info->userdata); 15112 return gbm.pixels; 15113 } 15114 15115 STBTT_DEF unsigned char *stbtt_GetGlyphBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int glyph, int *width, int *height, int *xoff, int *yoff) 15116 { 15117 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y, 0.0f, 0.0f, glyph, width, height, xoff, yoff); 15118 } 15119 15120 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int glyph) 15121 { 15122 int ix0,iy0; 15123 stbtt_vertex *vertices; 15124 int num_verts = stbtt_GetGlyphShape(info, glyph, &vertices); 15125 stbtt__bitmap gbm; 15126 15127 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, shift_y, &ix0,&iy0,0,0); 15128 gbm.pixels = output; 15129 gbm.w = out_w; 15130 gbm.h = out_h; 15131 gbm.stride = out_stride; 15132 15133 if (gbm.w && gbm.h) 15134 stbtt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, shift_x, shift_y, ix0,iy0, 1, info->userdata); 15135 15136 STBTT_free(vertices, info->userdata); 15137 } 15138 15139 STBTT_DEF void stbtt_MakeGlyphBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int glyph) 15140 { 15141 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, glyph); 15142 } 15143 15144 STBTT_DEF unsigned char *stbtt_GetCodepointBitmapSubpixel(const stbtt_fontinfo *info, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint, int *width, int *height, int *xoff, int *yoff) 15145 { 15146 return stbtt_GetGlyphBitmapSubpixel(info, scale_x, scale_y,shift_x,shift_y, stbtt_FindGlyphIndex(info,codepoint), width,height,xoff,yoff); 15147 } 15148 15149 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int oversample_x, int oversample_y, float *sub_x, float *sub_y, int codepoint) 15150 { 15151 stbtt_MakeGlyphBitmapSubpixelPrefilter(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, oversample_x, oversample_y, sub_x, sub_y, stbtt_FindGlyphIndex(info,codepoint)); 15152 } 15153 15154 STBTT_DEF void stbtt_MakeCodepointBitmapSubpixel(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int codepoint) 15155 { 15156 stbtt_MakeGlyphBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, shift_x, shift_y, stbtt_FindGlyphIndex(info,codepoint)); 15157 } 15158 15159 STBTT_DEF unsigned char *stbtt_GetCodepointBitmap(const stbtt_fontinfo *info, float scale_x, float scale_y, int codepoint, int *width, int *height, int *xoff, int *yoff) 15160 { 15161 return stbtt_GetCodepointBitmapSubpixel(info, scale_x, scale_y, 0.0f,0.0f, codepoint, width,height,xoff,yoff); 15162 } 15163 15164 STBTT_DEF void stbtt_MakeCodepointBitmap(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, int codepoint) 15165 { 15166 stbtt_MakeCodepointBitmapSubpixel(info, output, out_w, out_h, out_stride, scale_x, scale_y, 0.0f,0.0f, codepoint); 15167 } 15168 15169 /* //////////////////////////////////////////////////////////////////////////// */ 15170 /* */ 15171 /* bitmap baking */ 15172 /* */ 15173 /* This is SUPER-CRAPPY packing to keep source code small */ 15174 15175 static int stbtt_BakeFontBitmap_internal(unsigned char *data, int offset, /* font location (use offset=0 for plain .ttf) */ 15176 float pixel_height, /* height of font in pixels */ 15177 unsigned char *pixels, int pw, int ph, /* bitmap to be filled in */ 15178 int first_char, int num_chars, /* characters to bake */ 15179 stbtt_bakedchar *chardata) 15180 { 15181 float scale; 15182 int x,y,bottom_y, i; 15183 stbtt_fontinfo f; 15184 f.userdata = NULL; 15185 if (!stbtt_InitFont(&f, data, offset)) 15186 return -1; 15187 STBTT_memset(pixels, 0, pw*ph); /* background of 0 around pixels */ 15188 x=y=1; 15189 bottom_y = 1; 15190 15191 scale = stbtt_ScaleForPixelHeight(&f, pixel_height); 15192 15193 for (i=0; i < num_chars; ++i) { 15194 int advance, lsb, x0,y0,x1,y1,gw,gh; 15195 int g = stbtt_FindGlyphIndex(&f, first_char + i); 15196 stbtt_GetGlyphHMetrics(&f, g, &advance, &lsb); 15197 stbtt_GetGlyphBitmapBox(&f, g, scale,scale, &x0,&y0,&x1,&y1); 15198 gw = x1-x0; 15199 gh = y1-y0; 15200 if (x + gw + 1 >= pw) 15201 y = bottom_y, x = 1; /* advance to next row */ 15202 if (y + gh + 1 >= ph) /* check if it fits vertically AFTER potentially moving to next row */ 15203 return -i; 15204 STBTT_assert(x+gw < pw); 15205 STBTT_assert(y+gh < ph); 15206 stbtt_MakeGlyphBitmap(&f, pixels+x+y*pw, gw,gh,pw, scale,scale, g); 15207 chardata[i].x0 = (stbtt_int16) x; 15208 chardata[i].y0 = (stbtt_int16) y; 15209 chardata[i].x1 = (stbtt_int16) (x + gw); 15210 chardata[i].y1 = (stbtt_int16) (y + gh); 15211 chardata[i].xadvance = scale * advance; 15212 chardata[i].xoff = (float) x0; 15213 chardata[i].yoff = (float) y0; 15214 x = x + gw + 1; 15215 if (y+gh+1 > bottom_y) 15216 bottom_y = y+gh+1; 15217 } 15218 return bottom_y; 15219 } 15220 15221 STBTT_DEF void stbtt_GetBakedQuad(const stbtt_bakedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int opengl_fillrule) 15222 { 15223 float d3d_bias = opengl_fillrule ? 0 : -0.5f; 15224 float ipw = 1.0f / pw, iph = 1.0f / ph; 15225 const stbtt_bakedchar *b = chardata + char_index; 15226 int round_x = STBTT_ifloor((*xpos + b->xoff) + 0.5f); 15227 int round_y = STBTT_ifloor((*ypos + b->yoff) + 0.5f); 15228 15229 q->x0 = round_x + d3d_bias; 15230 q->y0 = round_y + d3d_bias; 15231 q->x1 = round_x + b->x1 - b->x0 + d3d_bias; 15232 q->y1 = round_y + b->y1 - b->y0 + d3d_bias; 15233 15234 q->s0 = b->x0 * ipw; 15235 q->t0 = b->y0 * iph; 15236 q->s1 = b->x1 * ipw; 15237 q->t1 = b->y1 * iph; 15238 15239 *xpos += b->xadvance; 15240 } 15241 15242 /* //////////////////////////////////////////////////////////////////////////// */ 15243 /* */ 15244 /* rectangle packing replacement routines if you don't have stb_rect_pack.h */ 15245 /* */ 15246 15247 #ifndef STB_RECT_PACK_VERSION 15248 15249 typedef int stbrp_coord; 15250 15251 /* ////////////////////////////////////////////////////////////////////////////////// */ 15252 /* // */ 15253 /* // */ 15254 /* COMPILER WARNING ?!?!? // */ 15255 /* // */ 15256 /* // */ 15257 /* if you get a compile warning due to these symbols being defined more than // */ 15258 /* once, move #include "stb_rect_pack.h" before #include "stb_truetype.h" // */ 15259 /* // */ 15260 /* ////////////////////////////////////////////////////////////////////////////////// */ 15261 15262 typedef struct 15263 { 15264 int width,height; 15265 int x,y,bottom_y; 15266 } stbrp_context; 15267 15268 typedef struct 15269 { 15270 unsigned char x; 15271 } stbrp_node; 15272 15273 struct stbrp_rect 15274 { 15275 stbrp_coord x,y; 15276 int id,w,h,was_packed; 15277 }; 15278 15279 static void stbrp_init_target(stbrp_context *con, int pw, int ph, stbrp_node *nodes, int num_nodes) 15280 { 15281 con->width = pw; 15282 con->height = ph; 15283 con->x = 0; 15284 con->y = 0; 15285 con->bottom_y = 0; 15286 STBTT__NOTUSED(nodes); 15287 STBTT__NOTUSED(num_nodes); 15288 } 15289 15290 static void stbrp_pack_rects(stbrp_context *con, stbrp_rect *rects, int num_rects) 15291 { 15292 int i; 15293 for (i=0; i < num_rects; ++i) { 15294 if (con->x + rects[i].w > con->width) { 15295 con->x = 0; 15296 con->y = con->bottom_y; 15297 } 15298 if (con->y + rects[i].h > con->height) 15299 break; 15300 rects[i].x = con->x; 15301 rects[i].y = con->y; 15302 rects[i].was_packed = 1; 15303 con->x += rects[i].w; 15304 if (con->y + rects[i].h > con->bottom_y) 15305 con->bottom_y = con->y + rects[i].h; 15306 } 15307 for ( ; i < num_rects; ++i) 15308 rects[i].was_packed = 0; 15309 } 15310 #endif 15311 15312 /* //////////////////////////////////////////////////////////////////////////// */ 15313 /* */ 15314 /* bitmap baking */ 15315 /* */ 15316 /* This is SUPER-AWESOME (tm Ryan Gordon) packing using stb_rect_pack.h. If */ 15317 /* stb_rect_pack.h isn't available, it uses the BakeFontBitmap strategy. */ 15318 15319 STBTT_DEF int stbtt_PackBegin(stbtt_pack_context *spc, unsigned char *pixels, int pw, int ph, int stride_in_bytes, int padding, void *alloc_context) 15320 { 15321 stbrp_context *context = (stbrp_context *) STBTT_malloc(sizeof(*context) ,alloc_context); 15322 int num_nodes = pw - padding; 15323 stbrp_node *nodes = (stbrp_node *) STBTT_malloc(sizeof(*nodes ) * num_nodes,alloc_context); 15324 15325 if (context == NULL || nodes == NULL) { 15326 if (context != NULL) STBTT_free(context, alloc_context); 15327 if (nodes != NULL) STBTT_free(nodes , alloc_context); 15328 return 0; 15329 } 15330 15331 spc->user_allocator_context = alloc_context; 15332 spc->width = pw; 15333 spc->height = ph; 15334 spc->pixels = pixels; 15335 spc->pack_info = context; 15336 spc->nodes = nodes; 15337 spc->padding = padding; 15338 spc->stride_in_bytes = stride_in_bytes != 0 ? stride_in_bytes : pw; 15339 spc->h_oversample = 1; 15340 spc->v_oversample = 1; 15341 spc->skip_missing = 0; 15342 15343 stbrp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); 15344 15345 if (pixels) 15346 STBTT_memset(pixels, 0, pw*ph); /* background of 0 around pixels */ 15347 15348 return 1; 15349 } 15350 15351 STBTT_DEF void stbtt_PackEnd (stbtt_pack_context *spc) 15352 { 15353 STBTT_free(spc->nodes , spc->user_allocator_context); 15354 STBTT_free(spc->pack_info, spc->user_allocator_context); 15355 } 15356 15357 STBTT_DEF void stbtt_PackSetOversampling(stbtt_pack_context *spc, unsigned int h_oversample, unsigned int v_oversample) 15358 { 15359 STBTT_assert(h_oversample <= STBTT_MAX_OVERSAMPLE); 15360 STBTT_assert(v_oversample <= STBTT_MAX_OVERSAMPLE); 15361 if (h_oversample <= STBTT_MAX_OVERSAMPLE) 15362 spc->h_oversample = h_oversample; 15363 if (v_oversample <= STBTT_MAX_OVERSAMPLE) 15364 spc->v_oversample = v_oversample; 15365 } 15366 15367 STBTT_DEF void stbtt_PackSetSkipMissingCodepoints(stbtt_pack_context *spc, int skip) 15368 { 15369 spc->skip_missing = skip; 15370 } 15371 15372 #define STBTT__OVER_MASK (STBTT_MAX_OVERSAMPLE-1) 15373 15374 static void stbtt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) 15375 { 15376 unsigned char buffer[STBTT_MAX_OVERSAMPLE]; 15377 int safe_w = w - kernel_width; 15378 int j; 15379 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); /* suppress bogus warning from VS2013 -analyze */ 15380 for (j=0; j < h; ++j) { 15381 int i; 15382 unsigned int total; 15383 STBTT_memset(buffer, 0, kernel_width); 15384 15385 total = 0; 15386 15387 /* make kernel_width a constant in common cases so compiler can optimize out the divide */ 15388 switch (kernel_width) { 15389 case 2: 15390 for (i=0; i <= safe_w; ++i) { 15391 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 15392 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 15393 pixels[i] = (unsigned char) (total / 2); 15394 } 15395 break; 15396 case 3: 15397 for (i=0; i <= safe_w; ++i) { 15398 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 15399 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 15400 pixels[i] = (unsigned char) (total / 3); 15401 } 15402 break; 15403 case 4: 15404 for (i=0; i <= safe_w; ++i) { 15405 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 15406 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 15407 pixels[i] = (unsigned char) (total / 4); 15408 } 15409 break; 15410 case 5: 15411 for (i=0; i <= safe_w; ++i) { 15412 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 15413 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 15414 pixels[i] = (unsigned char) (total / 5); 15415 } 15416 break; 15417 default: 15418 for (i=0; i <= safe_w; ++i) { 15419 total += pixels[i] - buffer[i & STBTT__OVER_MASK]; 15420 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i]; 15421 pixels[i] = (unsigned char) (total / kernel_width); 15422 } 15423 break; 15424 } 15425 15426 for (; i < w; ++i) { 15427 STBTT_assert(pixels[i] == 0); 15428 total -= buffer[i & STBTT__OVER_MASK]; 15429 pixels[i] = (unsigned char) (total / kernel_width); 15430 } 15431 15432 pixels += stride_in_bytes; 15433 } 15434 } 15435 15436 static void stbtt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, unsigned int kernel_width) 15437 { 15438 unsigned char buffer[STBTT_MAX_OVERSAMPLE]; 15439 int safe_h = h - kernel_width; 15440 int j; 15441 STBTT_memset(buffer, 0, STBTT_MAX_OVERSAMPLE); /* suppress bogus warning from VS2013 -analyze */ 15442 for (j=0; j < w; ++j) { 15443 int i; 15444 unsigned int total; 15445 STBTT_memset(buffer, 0, kernel_width); 15446 15447 total = 0; 15448 15449 /* make kernel_width a constant in common cases so compiler can optimize out the divide */ 15450 switch (kernel_width) { 15451 case 2: 15452 for (i=0; i <= safe_h; ++i) { 15453 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 15454 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 15455 pixels[i*stride_in_bytes] = (unsigned char) (total / 2); 15456 } 15457 break; 15458 case 3: 15459 for (i=0; i <= safe_h; ++i) { 15460 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 15461 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 15462 pixels[i*stride_in_bytes] = (unsigned char) (total / 3); 15463 } 15464 break; 15465 case 4: 15466 for (i=0; i <= safe_h; ++i) { 15467 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 15468 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 15469 pixels[i*stride_in_bytes] = (unsigned char) (total / 4); 15470 } 15471 break; 15472 case 5: 15473 for (i=0; i <= safe_h; ++i) { 15474 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 15475 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 15476 pixels[i*stride_in_bytes] = (unsigned char) (total / 5); 15477 } 15478 break; 15479 default: 15480 for (i=0; i <= safe_h; ++i) { 15481 total += pixels[i*stride_in_bytes] - buffer[i & STBTT__OVER_MASK]; 15482 buffer[(i+kernel_width) & STBTT__OVER_MASK] = pixels[i*stride_in_bytes]; 15483 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); 15484 } 15485 break; 15486 } 15487 15488 for (; i < h; ++i) { 15489 STBTT_assert(pixels[i*stride_in_bytes] == 0); 15490 total -= buffer[i & STBTT__OVER_MASK]; 15491 pixels[i*stride_in_bytes] = (unsigned char) (total / kernel_width); 15492 } 15493 15494 pixels += 1; 15495 } 15496 } 15497 15498 static float stbtt__oversample_shift(int oversample) 15499 { 15500 if (!oversample) 15501 return 0.0f; 15502 15503 /* The prefilter is a box filter of width "oversample", */ 15504 /* which shifts phase by (oversample - 1)/2 pixels in */ 15505 /* oversampled space. We want to shift in the opposite */ 15506 /* direction to counter this. */ 15507 return (float)-(oversample - 1) / (2.0f * (float)oversample); 15508 } 15509 15510 /* rects array must be big enough to accommodate all characters in the given ranges */ 15511 STBTT_DEF int stbtt_PackFontRangesGatherRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) 15512 { 15513 int i,j,k; 15514 int missing_glyph_added = 0; 15515 15516 k=0; 15517 for (i=0; i < num_ranges; ++i) { 15518 float fh = ranges[i].font_size; 15519 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); 15520 ranges[i].h_oversample = (unsigned char) spc->h_oversample; 15521 ranges[i].v_oversample = (unsigned char) spc->v_oversample; 15522 for (j=0; j < ranges[i].num_chars; ++j) { 15523 int x0,y0,x1,y1; 15524 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; 15525 int glyph = stbtt_FindGlyphIndex(info, codepoint); 15526 if (glyph == 0 && (spc->skip_missing || missing_glyph_added)) { 15527 rects[k].w = rects[k].h = 0; 15528 } else { 15529 stbtt_GetGlyphBitmapBoxSubpixel(info,glyph, 15530 scale * spc->h_oversample, 15531 scale * spc->v_oversample, 15532 0,0, 15533 &x0,&y0,&x1,&y1); 15534 rects[k].w = (stbrp_coord) (x1-x0 + spc->padding + spc->h_oversample-1); 15535 rects[k].h = (stbrp_coord) (y1-y0 + spc->padding + spc->v_oversample-1); 15536 if (glyph == 0) 15537 missing_glyph_added = 1; 15538 } 15539 ++k; 15540 } 15541 } 15542 15543 return k; 15544 } 15545 15546 STBTT_DEF void stbtt_MakeGlyphBitmapSubpixelPrefilter(const stbtt_fontinfo *info, unsigned char *output, int out_w, int out_h, int out_stride, float scale_x, float scale_y, float shift_x, float shift_y, int prefilter_x, int prefilter_y, float *sub_x, float *sub_y, int glyph) 15547 { 15548 stbtt_MakeGlyphBitmapSubpixel(info, 15549 output, 15550 out_w - (prefilter_x - 1), 15551 out_h - (prefilter_y - 1), 15552 out_stride, 15553 scale_x, 15554 scale_y, 15555 shift_x, 15556 shift_y, 15557 glyph); 15558 15559 if (prefilter_x > 1) 15560 stbtt__h_prefilter(output, out_w, out_h, out_stride, prefilter_x); 15561 15562 if (prefilter_y > 1) 15563 stbtt__v_prefilter(output, out_w, out_h, out_stride, prefilter_y); 15564 15565 *sub_x = stbtt__oversample_shift(prefilter_x); 15566 *sub_y = stbtt__oversample_shift(prefilter_y); 15567 } 15568 15569 /* rects array must be big enough to accommodate all characters in the given ranges */ 15570 STBTT_DEF int stbtt_PackFontRangesRenderIntoRects(stbtt_pack_context *spc, const stbtt_fontinfo *info, stbtt_pack_range *ranges, int num_ranges, stbrp_rect *rects) 15571 { 15572 int i,j,k, missing_glyph = -1, return_value = 1; 15573 15574 /* save current values */ 15575 int old_h_over = spc->h_oversample; 15576 int old_v_over = spc->v_oversample; 15577 15578 k = 0; 15579 for (i=0; i < num_ranges; ++i) { 15580 float fh = ranges[i].font_size; 15581 float scale = fh > 0 ? stbtt_ScaleForPixelHeight(info, fh) : stbtt_ScaleForMappingEmToPixels(info, -fh); 15582 float recip_h,recip_v,sub_x,sub_y; 15583 spc->h_oversample = ranges[i].h_oversample; 15584 spc->v_oversample = ranges[i].v_oversample; 15585 recip_h = 1.0f / spc->h_oversample; 15586 recip_v = 1.0f / spc->v_oversample; 15587 sub_x = stbtt__oversample_shift(spc->h_oversample); 15588 sub_y = stbtt__oversample_shift(spc->v_oversample); 15589 for (j=0; j < ranges[i].num_chars; ++j) { 15590 stbrp_rect *r = &rects[k]; 15591 if (r->was_packed && r->w != 0 && r->h != 0) { 15592 stbtt_packedchar *bc = &ranges[i].chardata_for_range[j]; 15593 int advance, lsb, x0,y0,x1,y1; 15594 int codepoint = ranges[i].array_of_unicode_codepoints == NULL ? ranges[i].first_unicode_codepoint_in_range + j : ranges[i].array_of_unicode_codepoints[j]; 15595 int glyph = stbtt_FindGlyphIndex(info, codepoint); 15596 stbrp_coord pad = (stbrp_coord) spc->padding; 15597 15598 /* pad on left and top */ 15599 r->x += pad; 15600 r->y += pad; 15601 r->w -= pad; 15602 r->h -= pad; 15603 stbtt_GetGlyphHMetrics(info, glyph, &advance, &lsb); 15604 stbtt_GetGlyphBitmapBox(info, glyph, 15605 scale * spc->h_oversample, 15606 scale * spc->v_oversample, 15607 &x0,&y0,&x1,&y1); 15608 stbtt_MakeGlyphBitmapSubpixel(info, 15609 spc->pixels + r->x + r->y*spc->stride_in_bytes, 15610 r->w - spc->h_oversample+1, 15611 r->h - spc->v_oversample+1, 15612 spc->stride_in_bytes, 15613 scale * spc->h_oversample, 15614 scale * spc->v_oversample, 15615 0,0, 15616 glyph); 15617 15618 if (spc->h_oversample > 1) 15619 stbtt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 15620 r->w, r->h, spc->stride_in_bytes, 15621 spc->h_oversample); 15622 15623 if (spc->v_oversample > 1) 15624 stbtt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, 15625 r->w, r->h, spc->stride_in_bytes, 15626 spc->v_oversample); 15627 15628 bc->x0 = (stbtt_int16) r->x; 15629 bc->y0 = (stbtt_int16) r->y; 15630 bc->x1 = (stbtt_int16) (r->x + r->w); 15631 bc->y1 = (stbtt_int16) (r->y + r->h); 15632 bc->xadvance = scale * advance; 15633 bc->xoff = (float) x0 * recip_h + sub_x; 15634 bc->yoff = (float) y0 * recip_v + sub_y; 15635 bc->xoff2 = (x0 + r->w) * recip_h + sub_x; 15636 bc->yoff2 = (y0 + r->h) * recip_v + sub_y; 15637 15638 if (glyph == 0) 15639 missing_glyph = j; 15640 } else if (spc->skip_missing) { 15641 return_value = 0; 15642 } else if (r->was_packed && r->w == 0 && r->h == 0 && missing_glyph >= 0) { 15643 ranges[i].chardata_for_range[j] = ranges[i].chardata_for_range[missing_glyph]; 15644 } else { 15645 return_value = 0; /* if any fail, report failure */ 15646 } 15647 15648 ++k; 15649 } 15650 } 15651 15652 /* restore original values */ 15653 spc->h_oversample = old_h_over; 15654 spc->v_oversample = old_v_over; 15655 15656 return return_value; 15657 } 15658 15659 STBTT_DEF void stbtt_PackFontRangesPackRects(stbtt_pack_context *spc, stbrp_rect *rects, int num_rects) 15660 { 15661 stbrp_pack_rects((stbrp_context *) spc->pack_info, rects, num_rects); 15662 } 15663 15664 STBTT_DEF int stbtt_PackFontRanges(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, stbtt_pack_range *ranges, int num_ranges) 15665 { 15666 stbtt_fontinfo info; 15667 int i,j,n, return_value = 1; 15668 /* stbrp_context *context = (stbrp_context *) spc->pack_info; */ 15669 stbrp_rect *rects; 15670 15671 /* flag all characters as NOT packed */ 15672 for (i=0; i < num_ranges; ++i) 15673 for (j=0; j < ranges[i].num_chars; ++j) 15674 ranges[i].chardata_for_range[j].x0 = 15675 ranges[i].chardata_for_range[j].y0 = 15676 ranges[i].chardata_for_range[j].x1 = 15677 ranges[i].chardata_for_range[j].y1 = 0; 15678 15679 n = 0; 15680 for (i=0; i < num_ranges; ++i) 15681 n += ranges[i].num_chars; 15682 15683 rects = (stbrp_rect *) STBTT_malloc(sizeof(*rects) * n, spc->user_allocator_context); 15684 if (rects == NULL) 15685 return 0; 15686 15687 info.userdata = spc->user_allocator_context; 15688 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata,font_index)); 15689 15690 n = stbtt_PackFontRangesGatherRects(spc, &info, ranges, num_ranges, rects); 15691 15692 stbtt_PackFontRangesPackRects(spc, rects, n); 15693 15694 return_value = stbtt_PackFontRangesRenderIntoRects(spc, &info, ranges, num_ranges, rects); 15695 15696 STBTT_free(rects, spc->user_allocator_context); 15697 return return_value; 15698 } 15699 15700 STBTT_DEF int stbtt_PackFontRange(stbtt_pack_context *spc, const unsigned char *fontdata, int font_index, float font_size, 15701 int first_unicode_codepoint_in_range, int num_chars_in_range, stbtt_packedchar *chardata_for_range) 15702 { 15703 stbtt_pack_range range; 15704 range.first_unicode_codepoint_in_range = first_unicode_codepoint_in_range; 15705 range.array_of_unicode_codepoints = NULL; 15706 range.num_chars = num_chars_in_range; 15707 range.chardata_for_range = chardata_for_range; 15708 range.font_size = font_size; 15709 return stbtt_PackFontRanges(spc, fontdata, font_index, &range, 1); 15710 } 15711 15712 STBTT_DEF void stbtt_GetScaledFontVMetrics(const unsigned char *fontdata, int index, float size, float *ascent, float *descent, float *lineGap) 15713 { 15714 int i_ascent, i_descent, i_lineGap; 15715 float scale; 15716 stbtt_fontinfo info; 15717 stbtt_InitFont(&info, fontdata, stbtt_GetFontOffsetForIndex(fontdata, index)); 15718 scale = size > 0 ? stbtt_ScaleForPixelHeight(&info, size) : stbtt_ScaleForMappingEmToPixels(&info, -size); 15719 stbtt_GetFontVMetrics(&info, &i_ascent, &i_descent, &i_lineGap); 15720 *ascent = (float) i_ascent * scale; 15721 *descent = (float) i_descent * scale; 15722 *lineGap = (float) i_lineGap * scale; 15723 } 15724 15725 STBTT_DEF void stbtt_GetPackedQuad(const stbtt_packedchar *chardata, int pw, int ph, int char_index, float *xpos, float *ypos, stbtt_aligned_quad *q, int align_to_integer) 15726 { 15727 float ipw = 1.0f / pw, iph = 1.0f / ph; 15728 const stbtt_packedchar *b = chardata + char_index; 15729 15730 if (align_to_integer) { 15731 float x = (float) STBTT_ifloor((*xpos + b->xoff) + 0.5f); 15732 float y = (float) STBTT_ifloor((*ypos + b->yoff) + 0.5f); 15733 q->x0 = x; 15734 q->y0 = y; 15735 q->x1 = x + b->xoff2 - b->xoff; 15736 q->y1 = y + b->yoff2 - b->yoff; 15737 } else { 15738 q->x0 = *xpos + b->xoff; 15739 q->y0 = *ypos + b->yoff; 15740 q->x1 = *xpos + b->xoff2; 15741 q->y1 = *ypos + b->yoff2; 15742 } 15743 15744 q->s0 = b->x0 * ipw; 15745 q->t0 = b->y0 * iph; 15746 q->s1 = b->x1 * ipw; 15747 q->t1 = b->y1 * iph; 15748 15749 *xpos += b->xadvance; 15750 } 15751 15752 /* //////////////////////////////////////////////////////////////////////////// */ 15753 /* */ 15754 /* sdf computation */ 15755 /* */ 15756 15757 #define STBTT_min(a,b) ((a) < (b) ? (a) : (b)) 15758 #define STBTT_max(a,b) ((a) < (b) ? (b) : (a)) 15759 15760 static int stbtt__ray_intersect_bezier(float orig[2], float ray[2], float q0[2], float q1[2], float q2[2], float hits[2][2]) 15761 { 15762 float q0perp = q0[1]*ray[0] - q0[0]*ray[1]; 15763 float q1perp = q1[1]*ray[0] - q1[0]*ray[1]; 15764 float q2perp = q2[1]*ray[0] - q2[0]*ray[1]; 15765 float roperp = orig[1]*ray[0] - orig[0]*ray[1]; 15766 15767 float a = q0perp - 2*q1perp + q2perp; 15768 float b = q1perp - q0perp; 15769 float c = q0perp - roperp; 15770 15771 float s0 = 0., s1 = 0.; 15772 int num_s = 0; 15773 15774 if (a != 0.0) { 15775 float discr = b*b - a*c; 15776 if (discr > 0.0) { 15777 float rcpna = -1 / a; 15778 float d = (float) STBTT_sqrt(discr); 15779 s0 = (b+d) * rcpna; 15780 s1 = (b-d) * rcpna; 15781 if (s0 >= 0.0 && s0 <= 1.0) 15782 num_s = 1; 15783 if (d > 0.0 && s1 >= 0.0 && s1 <= 1.0) { 15784 if (num_s == 0) s0 = s1; 15785 ++num_s; 15786 } 15787 } 15788 } else { 15789 /* 2*b*s + c = 0 */ 15790 /* s = -c / (2*b) */ 15791 s0 = c / (-2 * b); 15792 if (s0 >= 0.0 && s0 <= 1.0) 15793 num_s = 1; 15794 } 15795 15796 if (num_s == 0) 15797 return 0; 15798 else { 15799 float rcp_len2 = 1 / (ray[0]*ray[0] + ray[1]*ray[1]); 15800 float rayn_x = ray[0] * rcp_len2, rayn_y = ray[1] * rcp_len2; 15801 15802 float q0d = q0[0]*rayn_x + q0[1]*rayn_y; 15803 float q1d = q1[0]*rayn_x + q1[1]*rayn_y; 15804 float q2d = q2[0]*rayn_x + q2[1]*rayn_y; 15805 float rod = orig[0]*rayn_x + orig[1]*rayn_y; 15806 15807 float q10d = q1d - q0d; 15808 float q20d = q2d - q0d; 15809 float q0rd = q0d - rod; 15810 15811 hits[0][0] = q0rd + s0*(2.0f - 2.0f*s0)*q10d + s0*s0*q20d; 15812 hits[0][1] = a*s0+b; 15813 15814 if (num_s > 1) { 15815 hits[1][0] = q0rd + s1*(2.0f - 2.0f*s1)*q10d + s1*s1*q20d; 15816 hits[1][1] = a*s1+b; 15817 return 2; 15818 } else { 15819 return 1; 15820 } 15821 } 15822 } 15823 15824 static int equal(float *a, float *b) 15825 { 15826 return (a[0] == b[0] && a[1] == b[1]); 15827 } 15828 15829 static int stbtt__compute_crossings_x(float x, float y, int nverts, stbtt_vertex *verts) 15830 { 15831 int i; 15832 float orig[2], ray[2] = { 1, 0 }; 15833 float y_frac; 15834 int winding = 0; 15835 15836 /* make sure y never passes through a vertex of the shape */ 15837 y_frac = (float) STBTT_fmod(y, 1.0f); 15838 if (y_frac < 0.01f) 15839 y += 0.01f; 15840 else if (y_frac > 0.99f) 15841 y -= 0.01f; 15842 15843 orig[0] = x; 15844 orig[1] = y; 15845 15846 /* test a ray from (-infinity,y) to (x,y) */ 15847 for (i=0; i < nverts; ++i) { 15848 if (verts[i].type == STBTT_vline) { 15849 int x0 = (int) verts[i-1].x, y0 = (int) verts[i-1].y; 15850 int x1 = (int) verts[i ].x, y1 = (int) verts[i ].y; 15851 if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { 15852 float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; 15853 if (x_inter < x) 15854 winding += (y0 < y1) ? 1 : -1; 15855 } 15856 } 15857 if (verts[i].type == STBTT_vcurve) { 15858 int x0 = (int) verts[i-1].x , y0 = (int) verts[i-1].y ; 15859 int x1 = (int) verts[i ].cx, y1 = (int) verts[i ].cy; 15860 int x2 = (int) verts[i ].x , y2 = (int) verts[i ].y ; 15861 int ax = STBTT_min(x0,STBTT_min(x1,x2)), ay = STBTT_min(y0,STBTT_min(y1,y2)); 15862 int by = STBTT_max(y0,STBTT_max(y1,y2)); 15863 if (y > ay && y < by && x > ax) { 15864 float q0[2],q1[2],q2[2]; 15865 float hits[2][2]; 15866 q0[0] = (float)x0; 15867 q0[1] = (float)y0; 15868 q1[0] = (float)x1; 15869 q1[1] = (float)y1; 15870 q2[0] = (float)x2; 15871 q2[1] = (float)y2; 15872 if (equal(q0,q1) || equal(q1,q2)) { 15873 x0 = (int)verts[i-1].x; 15874 y0 = (int)verts[i-1].y; 15875 x1 = (int)verts[i ].x; 15876 y1 = (int)verts[i ].y; 15877 if (y > STBTT_min(y0,y1) && y < STBTT_max(y0,y1) && x > STBTT_min(x0,x1)) { 15878 float x_inter = (y - y0) / (y1 - y0) * (x1-x0) + x0; 15879 if (x_inter < x) 15880 winding += (y0 < y1) ? 1 : -1; 15881 } 15882 } else { 15883 int num_hits = stbtt__ray_intersect_bezier(orig, ray, q0, q1, q2, hits); 15884 if (num_hits >= 1) 15885 if (hits[0][0] < 0) 15886 winding += (hits[0][1] < 0 ? -1 : 1); 15887 if (num_hits >= 2) 15888 if (hits[1][0] < 0) 15889 winding += (hits[1][1] < 0 ? -1 : 1); 15890 } 15891 } 15892 } 15893 } 15894 return winding; 15895 } 15896 15897 static float stbtt__cuberoot( float x ) 15898 { 15899 if (x<0) 15900 return -(float) STBTT_pow(-x,1.0f/3.0f); 15901 else 15902 return (float) STBTT_pow( x,1.0f/3.0f); 15903 } 15904 15905 /* x^3 + a*x^2 + b*x + c = 0 */ 15906 static int stbtt__solve_cubic(float a, float b, float c, float* r) 15907 { 15908 float s = -a / 3; 15909 float p = b - a*a / 3; 15910 float q = a * (2*a*a - 9*b) / 27 + c; 15911 float p3 = p*p*p; 15912 float d = q*q + 4*p3 / 27; 15913 if (d >= 0) { 15914 float z = (float) STBTT_sqrt(d); 15915 float u = (-q + z) / 2; 15916 float v = (-q - z) / 2; 15917 u = stbtt__cuberoot(u); 15918 v = stbtt__cuberoot(v); 15919 r[0] = s + u + v; 15920 return 1; 15921 } else { 15922 float u = (float) STBTT_sqrt(-p/3); 15923 float v = (float) STBTT_acos(-STBTT_sqrt(-27/p3) * q / 2) / 3; /* p3 must be negative, since d is negative */ 15924 float m = (float) STBTT_cos(v); 15925 float n = (float) STBTT_cos(v-3.141592/2)*1.732050808f; 15926 r[0] = s + u * 2 * m; 15927 r[1] = s - u * (m + n); 15928 r[2] = s - u * (m - n); 15929 15930 /* STBTT_assert( STBTT_fabs(((r[0]+a)*r[0]+b)*r[0]+c) < 0.05f); // these asserts may not be safe at all scales, though they're in bezier t parameter units so maybe? */ 15931 /* STBTT_assert( STBTT_fabs(((r[1]+a)*r[1]+b)*r[1]+c) < 0.05f); */ 15932 /* STBTT_assert( STBTT_fabs(((r[2]+a)*r[2]+b)*r[2]+c) < 0.05f); */ 15933 return 3; 15934 } 15935 } 15936 15937 STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float scale, int glyph, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) 15938 { 15939 float scale_x = scale, scale_y = scale; 15940 int ix0,iy0,ix1,iy1; 15941 int w,h; 15942 unsigned char *data; 15943 15944 if (scale == 0) return NULL; 15945 15946 stbtt_GetGlyphBitmapBoxSubpixel(info, glyph, scale, scale, 0.0f,0.0f, &ix0,&iy0,&ix1,&iy1); 15947 15948 /* if empty, return NULL */ 15949 if (ix0 == ix1 || iy0 == iy1) 15950 return NULL; 15951 15952 ix0 -= padding; 15953 iy0 -= padding; 15954 ix1 += padding; 15955 iy1 += padding; 15956 15957 w = (ix1 - ix0); 15958 h = (iy1 - iy0); 15959 15960 if (width ) *width = w; 15961 if (height) *height = h; 15962 if (xoff ) *xoff = ix0; 15963 if (yoff ) *yoff = iy0; 15964 15965 /* invert for y-downwards bitmaps */ 15966 scale_y = -scale_y; 15967 15968 { 15969 int x,y,i,j; 15970 float *precompute; 15971 stbtt_vertex *verts; 15972 int num_verts = stbtt_GetGlyphShape(info, glyph, &verts); 15973 data = (unsigned char *) STBTT_malloc(w * h, info->userdata); 15974 precompute = (float *) STBTT_malloc(num_verts * sizeof(float), info->userdata); 15975 15976 for (i=0,j=num_verts-1; i < num_verts; j=i++) { 15977 if (verts[i].type == STBTT_vline) { 15978 float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; 15979 float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y; 15980 float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0)); 15981 precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist; 15982 } else if (verts[i].type == STBTT_vcurve) { 15983 float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y; 15984 float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y; 15985 float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y; 15986 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; 15987 float len2 = bx*bx + by*by; 15988 if (len2 != 0.0f) 15989 precompute[i] = 1.0f / (bx*bx + by*by); 15990 else 15991 precompute[i] = 0.0f; 15992 } else 15993 precompute[i] = 0.0f; 15994 } 15995 15996 for (y=iy0; y < iy1; ++y) { 15997 for (x=ix0; x < ix1; ++x) { 15998 float val; 15999 float min_dist = 999999.0f; 16000 float sx = (float) x + 0.5f; 16001 float sy = (float) y + 0.5f; 16002 float x_gspace = (sx / scale_x); 16003 float y_gspace = (sy / scale_y); 16004 16005 int winding = stbtt__compute_crossings_x(x_gspace, y_gspace, num_verts, verts); /* @OPTIMIZE: this could just be a rasterization, but needs to be line vs. non-tesselated curves so a new path */ 16006 16007 for (i=0; i < num_verts; ++i) { 16008 float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y; 16009 16010 if (verts[i].type == STBTT_vline && precompute[i] != 0.0f) { 16011 float x1 = verts[i-1].x*scale_x, y1 = verts[i-1].y*scale_y; 16012 16013 float dist,dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); 16014 if (dist2 < min_dist*min_dist) 16015 min_dist = (float) STBTT_sqrt(dist2); 16016 16017 /* coarse culling against bbox */ 16018 /* if (sx > STBTT_min(x0,x1)-min_dist && sx < STBTT_max(x0,x1)+min_dist && */ 16019 /* sy > STBTT_min(y0,y1)-min_dist && sy < STBTT_max(y0,y1)+min_dist) */ 16020 dist = (float) STBTT_fabs((x1-x0)*(y0-sy) - (y1-y0)*(x0-sx)) * precompute[i]; 16021 STBTT_assert(i != 0); 16022 if (dist < min_dist) { 16023 /* check position along line */ 16024 /* x' = x0 + t*(x1-x0), y' = y0 + t*(y1-y0) */ 16025 /* minimize (x'-sx)*(x'-sx)+(y'-sy)*(y'-sy) */ 16026 float dx = x1-x0, dy = y1-y0; 16027 float px = x0-sx, py = y0-sy; 16028 /* minimize (px+t*dx)^2 + (py+t*dy)^2 = px*px + 2*px*dx*t + t^2*dx*dx + py*py + 2*py*dy*t + t^2*dy*dy */ 16029 /* derivative: 2*px*dx + 2*py*dy + (2*dx*dx+2*dy*dy)*t, set to 0 and solve */ 16030 float t = -(px*dx + py*dy) / (dx*dx + dy*dy); 16031 if (t >= 0.0f && t <= 1.0f) 16032 min_dist = dist; 16033 } 16034 } else if (verts[i].type == STBTT_vcurve) { 16035 float x2 = verts[i-1].x *scale_x, y2 = verts[i-1].y *scale_y; 16036 float x1 = verts[i ].cx*scale_x, y1 = verts[i ].cy*scale_y; 16037 float box_x0 = STBTT_min(STBTT_min(x0,x1),x2); 16038 float box_y0 = STBTT_min(STBTT_min(y0,y1),y2); 16039 float box_x1 = STBTT_max(STBTT_max(x0,x1),x2); 16040 float box_y1 = STBTT_max(STBTT_max(y0,y1),y2); 16041 /* coarse culling against bbox to avoid computing cubic unnecessarily */ 16042 if (sx > box_x0-min_dist && sx < box_x1+min_dist && sy > box_y0-min_dist && sy < box_y1+min_dist) { 16043 int num=0; 16044 float ax = x1-x0, ay = y1-y0; 16045 float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2; 16046 float mx = x0 - sx, my = y0 - sy; 16047 float res[3] = {0.f,0.f,0.f}; 16048 float px,py,t,it,dist2; 16049 float a_inv = precompute[i]; 16050 if (a_inv == 0.0) { /* if a_inv is 0, it's 2nd degree so use quadratic formula */ 16051 float a = 3*(ax*bx + ay*by); 16052 float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by); 16053 float c = mx*ax+my*ay; 16054 if (a == 0.0) { /* if a is 0, it's linear */ 16055 if (b != 0.0) { 16056 res[num++] = -c/b; 16057 } 16058 } else { 16059 float discriminant = b*b - 4*a*c; 16060 if (discriminant < 0) 16061 num = 0; 16062 else { 16063 float root = (float) STBTT_sqrt(discriminant); 16064 res[0] = (-b - root)/(2*a); 16065 res[1] = (-b + root)/(2*a); 16066 num = 2; /* don't bother distinguishing 1-solution case, as code below will still work */ 16067 } 16068 } 16069 } else { 16070 float b = 3*(ax*bx + ay*by) * a_inv; /* could precompute this as it doesn't depend on sample point */ 16071 float c = (2*(ax*ax + ay*ay) + (mx*bx+my*by)) * a_inv; 16072 float d = (mx*ax+my*ay) * a_inv; 16073 num = stbtt__solve_cubic(b, c, d, res); 16074 } 16075 dist2 = (x0-sx)*(x0-sx) + (y0-sy)*(y0-sy); 16076 if (dist2 < min_dist*min_dist) 16077 min_dist = (float) STBTT_sqrt(dist2); 16078 16079 if (num >= 1 && res[0] >= 0.0f && res[0] <= 1.0f) { 16080 t = res[0], it = 1.0f - t; 16081 px = it*it*x0 + 2*t*it*x1 + t*t*x2; 16082 py = it*it*y0 + 2*t*it*y1 + t*t*y2; 16083 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); 16084 if (dist2 < min_dist * min_dist) 16085 min_dist = (float) STBTT_sqrt(dist2); 16086 } 16087 if (num >= 2 && res[1] >= 0.0f && res[1] <= 1.0f) { 16088 t = res[1], it = 1.0f - t; 16089 px = it*it*x0 + 2*t*it*x1 + t*t*x2; 16090 py = it*it*y0 + 2*t*it*y1 + t*t*y2; 16091 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); 16092 if (dist2 < min_dist * min_dist) 16093 min_dist = (float) STBTT_sqrt(dist2); 16094 } 16095 if (num >= 3 && res[2] >= 0.0f && res[2] <= 1.0f) { 16096 t = res[2], it = 1.0f - t; 16097 px = it*it*x0 + 2*t*it*x1 + t*t*x2; 16098 py = it*it*y0 + 2*t*it*y1 + t*t*y2; 16099 dist2 = (px-sx)*(px-sx) + (py-sy)*(py-sy); 16100 if (dist2 < min_dist * min_dist) 16101 min_dist = (float) STBTT_sqrt(dist2); 16102 } 16103 } 16104 } 16105 } 16106 if (winding == 0) 16107 min_dist = -min_dist; /* if outside the shape, value is negative */ 16108 val = onedge_value + pixel_dist_scale * min_dist; 16109 if (val < 0) 16110 val = 0; 16111 else if (val > 255) 16112 val = 255; 16113 data[(y-iy0)*w+(x-ix0)] = (unsigned char) val; 16114 } 16115 } 16116 STBTT_free(precompute, info->userdata); 16117 STBTT_free(verts, info->userdata); 16118 } 16119 return data; 16120 } 16121 16122 STBTT_DEF unsigned char * stbtt_GetCodepointSDF(const stbtt_fontinfo *info, float scale, int codepoint, int padding, unsigned char onedge_value, float pixel_dist_scale, int *width, int *height, int *xoff, int *yoff) 16123 { 16124 return stbtt_GetGlyphSDF(info, scale, stbtt_FindGlyphIndex(info, codepoint), padding, onedge_value, pixel_dist_scale, width, height, xoff, yoff); 16125 } 16126 16127 STBTT_DEF void stbtt_FreeSDF(unsigned char *bitmap, void *userdata) 16128 { 16129 STBTT_free(bitmap, userdata); 16130 } 16131 16132 /* //////////////////////////////////////////////////////////////////////////// */ 16133 /* */ 16134 /* font name matching -- recommended not to use this */ 16135 /* */ 16136 16137 /* check if a utf8 string contains a prefix which is the utf16 string; if so return length of matching utf8 string */ 16138 static stbtt_int32 stbtt__CompareUTF8toUTF16_bigendian_prefix(stbtt_uint8 *s1, stbtt_int32 len1, stbtt_uint8 *s2, stbtt_int32 len2) 16139 { 16140 stbtt_int32 i=0; 16141 16142 /* convert utf16 to utf8 and compare the results while converting */ 16143 while (len2) { 16144 stbtt_uint16 ch = s2[0]*256 + s2[1]; 16145 if (ch < 0x80) { 16146 if (i >= len1) return -1; 16147 if (s1[i++] != ch) return -1; 16148 } else if (ch < 0x800) { 16149 if (i+1 >= len1) return -1; 16150 if (s1[i++] != 0xc0 + (ch >> 6)) return -1; 16151 if (s1[i++] != 0x80 + (ch & 0x3f)) return -1; 16152 } else if (ch >= 0xd800 && ch < 0xdc00) { 16153 stbtt_uint32 c; 16154 stbtt_uint16 ch2 = s2[2]*256 + s2[3]; 16155 if (i+3 >= len1) return -1; 16156 c = ((ch - 0xd800) << 10) + (ch2 - 0xdc00) + 0x10000; 16157 if (s1[i++] != 0xf0 + (c >> 18)) return -1; 16158 if (s1[i++] != 0x80 + ((c >> 12) & 0x3f)) return -1; 16159 if (s1[i++] != 0x80 + ((c >> 6) & 0x3f)) return -1; 16160 if (s1[i++] != 0x80 + ((c ) & 0x3f)) return -1; 16161 s2 += 2; /* plus another 2 below */ 16162 len2 -= 2; 16163 } else if (ch >= 0xdc00 && ch < 0xe000) { 16164 return -1; 16165 } else { 16166 if (i+2 >= len1) return -1; 16167 if (s1[i++] != 0xe0 + (ch >> 12)) return -1; 16168 if (s1[i++] != 0x80 + ((ch >> 6) & 0x3f)) return -1; 16169 if (s1[i++] != 0x80 + ((ch ) & 0x3f)) return -1; 16170 } 16171 s2 += 2; 16172 len2 -= 2; 16173 } 16174 return i; 16175 } 16176 16177 static int stbtt_CompareUTF8toUTF16_bigendian_internal(char *s1, int len1, char *s2, int len2) 16178 { 16179 return len1 == stbtt__CompareUTF8toUTF16_bigendian_prefix((stbtt_uint8*) s1, len1, (stbtt_uint8*) s2, len2); 16180 } 16181 16182 /* returns results in whatever encoding you request... but note that 2-byte encodings */ 16183 /* will be BIG-ENDIAN... use stbtt_CompareUTF8toUTF16_bigendian() to compare */ 16184 STBTT_DEF const char *stbtt_GetFontNameString(const stbtt_fontinfo *font, int *length, int platformID, int encodingID, int languageID, int nameID) 16185 { 16186 stbtt_int32 i,count,stringOffset; 16187 stbtt_uint8 *fc = font->data; 16188 stbtt_uint32 offset = font->fontstart; 16189 stbtt_uint32 nm = stbtt__find_table(fc, offset, "name"); 16190 if (!nm) return NULL; 16191 16192 count = ttUSHORT(fc+nm+2); 16193 stringOffset = nm + ttUSHORT(fc+nm+4); 16194 for (i=0; i < count; ++i) { 16195 stbtt_uint32 loc = nm + 6 + 12 * i; 16196 if (platformID == ttUSHORT(fc+loc+0) && encodingID == ttUSHORT(fc+loc+2) 16197 && languageID == ttUSHORT(fc+loc+4) && nameID == ttUSHORT(fc+loc+6)) { 16198 *length = ttUSHORT(fc+loc+8); 16199 return (const char *) (fc+stringOffset+ttUSHORT(fc+loc+10)); 16200 } 16201 } 16202 return NULL; 16203 } 16204 16205 static int stbtt__matchpair(stbtt_uint8 *fc, stbtt_uint32 nm, stbtt_uint8 *name, stbtt_int32 nlen, stbtt_int32 target_id, stbtt_int32 next_id) 16206 { 16207 stbtt_int32 i; 16208 stbtt_int32 count = ttUSHORT(fc+nm+2); 16209 stbtt_int32 stringOffset = nm + ttUSHORT(fc+nm+4); 16210 16211 for (i=0; i < count; ++i) { 16212 stbtt_uint32 loc = nm + 6 + 12 * i; 16213 stbtt_int32 id = ttUSHORT(fc+loc+6); 16214 if (id == target_id) { 16215 /* find the encoding */ 16216 stbtt_int32 platform = ttUSHORT(fc+loc+0), encoding = ttUSHORT(fc+loc+2), language = ttUSHORT(fc+loc+4); 16217 16218 /* is this a Unicode encoding? */ 16219 if (platform == 0 || (platform == 3 && encoding == 1) || (platform == 3 && encoding == 10)) { 16220 stbtt_int32 slen = ttUSHORT(fc+loc+8); 16221 stbtt_int32 off = ttUSHORT(fc+loc+10); 16222 16223 /* check if there's a prefix match */ 16224 stbtt_int32 matchlen = stbtt__CompareUTF8toUTF16_bigendian_prefix(name, nlen, fc+stringOffset+off,slen); 16225 if (matchlen >= 0) { 16226 /* check for target_id+1 immediately following, with same encoding & language */ 16227 if (i+1 < count && ttUSHORT(fc+loc+12+6) == next_id && ttUSHORT(fc+loc+12) == platform && ttUSHORT(fc+loc+12+2) == encoding && ttUSHORT(fc+loc+12+4) == language) { 16228 slen = ttUSHORT(fc+loc+12+8); 16229 off = ttUSHORT(fc+loc+12+10); 16230 if (slen == 0) { 16231 if (matchlen == nlen) 16232 return 1; 16233 } else if (matchlen < nlen && name[matchlen] == ' ') { 16234 ++matchlen; 16235 if (stbtt_CompareUTF8toUTF16_bigendian_internal((char*) (name+matchlen), nlen-matchlen, (char*)(fc+stringOffset+off),slen)) 16236 return 1; 16237 } 16238 } else { 16239 /* if nothing immediately following */ 16240 if (matchlen == nlen) 16241 return 1; 16242 } 16243 } 16244 } 16245 16246 /* @TODO handle other encodings */ 16247 } 16248 } 16249 return 0; 16250 } 16251 16252 static int stbtt__matches(stbtt_uint8 *fc, stbtt_uint32 offset, stbtt_uint8 *name, stbtt_int32 flags) 16253 { 16254 stbtt_int32 nlen = (stbtt_int32) STBTT_strlen((char *) name); 16255 stbtt_uint32 nm,hd; 16256 if (!stbtt__isfont(fc+offset)) return 0; 16257 16258 /* check italics/bold/underline flags in macStyle... */ 16259 if (flags) { 16260 hd = stbtt__find_table(fc, offset, "head"); 16261 if ((ttUSHORT(fc+hd+44) & 7) != (flags & 7)) return 0; 16262 } 16263 16264 nm = stbtt__find_table(fc, offset, "name"); 16265 if (!nm) return 0; 16266 16267 if (flags) { 16268 /* if we checked the macStyle flags, then just check the family and ignore the subfamily */ 16269 if (stbtt__matchpair(fc, nm, name, nlen, 16, -1)) return 1; 16270 if (stbtt__matchpair(fc, nm, name, nlen, 1, -1)) return 1; 16271 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; 16272 } else { 16273 if (stbtt__matchpair(fc, nm, name, nlen, 16, 17)) return 1; 16274 if (stbtt__matchpair(fc, nm, name, nlen, 1, 2)) return 1; 16275 if (stbtt__matchpair(fc, nm, name, nlen, 3, -1)) return 1; 16276 } 16277 16278 return 0; 16279 } 16280 16281 static int stbtt_FindMatchingFont_internal(unsigned char *font_collection, char *name_utf8, stbtt_int32 flags) 16282 { 16283 stbtt_int32 i; 16284 for (i=0;;++i) { 16285 stbtt_int32 off = stbtt_GetFontOffsetForIndex(font_collection, i); 16286 if (off < 0) return off; 16287 if (stbtt__matches((stbtt_uint8 *) font_collection, off, (stbtt_uint8*) name_utf8, flags)) 16288 return off; 16289 } 16290 } 16291 16292 #if defined(__GNUC__) || defined(__clang__) 16293 #pragma GCC diagnostic push 16294 #pragma GCC diagnostic ignored "-Wcast-qual" 16295 #endif 16296 16297 STBTT_DEF int stbtt_BakeFontBitmap(const unsigned char *data, int offset, 16298 float pixel_height, unsigned char *pixels, int pw, int ph, 16299 int first_char, int num_chars, stbtt_bakedchar *chardata) 16300 { 16301 return stbtt_BakeFontBitmap_internal((unsigned char *) data, offset, pixel_height, pixels, pw, ph, first_char, num_chars, chardata); 16302 } 16303 16304 STBTT_DEF int stbtt_GetFontOffsetForIndex(const unsigned char *data, int index) 16305 { 16306 return stbtt_GetFontOffsetForIndex_internal((unsigned char *) data, index); 16307 } 16308 16309 STBTT_DEF int stbtt_GetNumberOfFonts(const unsigned char *data) 16310 { 16311 return stbtt_GetNumberOfFonts_internal((unsigned char *) data); 16312 } 16313 16314 STBTT_DEF int stbtt_InitFont(stbtt_fontinfo *info, const unsigned char *data, int offset) 16315 { 16316 return stbtt_InitFont_internal(info, (unsigned char *) data, offset); 16317 } 16318 16319 STBTT_DEF int stbtt_FindMatchingFont(const unsigned char *fontdata, const char *name, int flags) 16320 { 16321 return stbtt_FindMatchingFont_internal((unsigned char *) fontdata, (char *) name, flags); 16322 } 16323 16324 STBTT_DEF int stbtt_CompareUTF8toUTF16_bigendian(const char *s1, int len1, const char *s2, int len2) 16325 { 16326 return stbtt_CompareUTF8toUTF16_bigendian_internal((char *) s1, len1, (char *) s2, len2); 16327 } 16328 16329 #if defined(__GNUC__) || defined(__clang__) 16330 #pragma GCC diagnostic pop 16331 #endif 16332 16333 #endif /* STB_TRUETYPE_IMPLEMENTATION */ 16334 16335 16336 /* FULL VERSION HISTORY */ 16337 /* */ 16338 /* 1.25 (2021-07-11) many fixes */ 16339 /* 1.24 (2020-02-05) fix warning */ 16340 /* 1.23 (2020-02-02) query SVG data for glyphs; query whole kerning table (but only kern not GPOS) */ 16341 /* 1.22 (2019-08-11) minimize missing-glyph duplication; fix kerning if both 'GPOS' and 'kern' are defined */ 16342 /* 1.21 (2019-02-25) fix warning */ 16343 /* 1.20 (2019-02-07) PackFontRange skips missing codepoints; GetScaleFontVMetrics() */ 16344 /* 1.19 (2018-02-11) OpenType GPOS kerning (horizontal only), STBTT_fmod */ 16345 /* 1.18 (2018-01-29) add missing function */ 16346 /* 1.17 (2017-07-23) make more arguments const; doc fix */ 16347 /* 1.16 (2017-07-12) SDF support */ 16348 /* 1.15 (2017-03-03) make more arguments const */ 16349 /* 1.14 (2017-01-16) num-fonts-in-TTC function */ 16350 /* 1.13 (2017-01-02) support OpenType fonts, certain Apple fonts */ 16351 /* 1.12 (2016-10-25) suppress warnings about casting away const with -Wcast-qual */ 16352 /* 1.11 (2016-04-02) fix unused-variable warning */ 16353 /* 1.10 (2016-04-02) allow user-defined fabs() replacement */ 16354 /* fix memory leak if fontsize=0.0 */ 16355 /* fix warning from duplicate typedef */ 16356 /* 1.09 (2016-01-16) warning fix; avoid crash on outofmem; use alloc userdata for PackFontRanges */ 16357 /* 1.08 (2015-09-13) document stbtt_Rasterize(); fixes for vertical & horizontal edges */ 16358 /* 1.07 (2015-08-01) allow PackFontRanges to accept arrays of sparse codepoints; */ 16359 /* allow PackFontRanges to pack and render in separate phases; */ 16360 /* fix stbtt_GetFontOFfsetForIndex (never worked for non-0 input?); */ 16361 /* fixed an assert() bug in the new rasterizer */ 16362 /* replace assert() with STBTT_assert() in new rasterizer */ 16363 /* 1.06 (2015-07-14) performance improvements (~35% faster on x86 and x64 on test machine) */ 16364 /* also more precise AA rasterizer, except if shapes overlap */ 16365 /* remove need for STBTT_sort */ 16366 /* 1.05 (2015-04-15) fix misplaced definitions for STBTT_STATIC */ 16367 /* 1.04 (2015-04-15) typo in example */ 16368 /* 1.03 (2015-04-12) STBTT_STATIC, fix memory leak in new packing, various fixes */ 16369 /* 1.02 (2014-12-10) fix various warnings & compile issues w/ stb_rect_pack, C++ */ 16370 /* 1.01 (2014-12-08) fix subpixel position when oversampling to exactly match */ 16371 /* non-oversampled; STBTT_POINT_SIZE for packed case only */ 16372 /* 1.00 (2014-12-06) add new PackBegin etc. API, w/ support for oversampling */ 16373 /* 0.99 (2014-09-18) fix multiple bugs with subpixel rendering (ryg) */ 16374 /* 0.9 (2014-08-07) support certain mac/iOS fonts without an MS platformID */ 16375 /* 0.8b (2014-07-07) fix a warning */ 16376 /* 0.8 (2014-05-25) fix a few more warnings */ 16377 /* 0.7 (2013-09-25) bugfix: subpixel glyph bug fixed in 0.5 had come back */ 16378 /* 0.6c (2012-07-24) improve documentation */ 16379 /* 0.6b (2012-07-20) fix a few more warnings */ 16380 /* 0.6 (2012-07-17) fix warnings; added stbtt_ScaleForMappingEmToPixels, */ 16381 /* stbtt_GetFontBoundingBox, stbtt_IsGlyphEmpty */ 16382 /* 0.5 (2011-12-09) bugfixes: */ 16383 /* subpixel glyph renderer computed wrong bounding box */ 16384 /* first vertex of shape can be off-curve (FreeSans) */ 16385 /* 0.4b (2011-12-03) fixed an error in the font baking example */ 16386 /* 0.4 (2011-12-01) kerning, subpixel rendering (tor) */ 16387 /* bugfixes for: */ 16388 /* codepoint-to-glyph conversion using table fmt=12 */ 16389 /* codepoint-to-glyph conversion using table fmt=4 */ 16390 /* stbtt_GetBakedQuad with non-square texture (Zer) */ 16391 /* updated Hello World! sample to use kerning and subpixel */ 16392 /* fixed some warnings */ 16393 /* 0.3 (2009-06-24) cmap fmt=12, compound shapes (MM) */ 16394 /* userdata, malloc-from-userdata, non-zero fill (stb) */ 16395 /* 0.2 (2009-03-11) Fix unsigned/signed char warnings */ 16396 /* 0.1 (2009-03-09) First public release */ 16397 /* */ 16398 16399 /* 16400 ------------------------------------------------------------------------------ 16401 This software is available under 2 licenses -- choose whichever you prefer. 16402 ------------------------------------------------------------------------------ 16403 ALTERNATIVE A - MIT License 16404 Copyright (c) 2017 Sean Barrett 16405 Permission is hereby granted, free of charge, to any person obtaining a copy of 16406 this software and associated documentation files (the "Software"), to deal in 16407 the Software without restriction, including without limitation the rights to 16408 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 16409 of the Software, and to permit persons to whom the Software is furnished to do 16410 so, subject to the following conditions: 16411 The above copyright notice and this permission notice shall be included in all 16412 copies or substantial portions of the Software. 16413 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16414 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16415 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16416 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 16417 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16418 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 16419 SOFTWARE. 16420 ------------------------------------------------------------------------------ 16421 ALTERNATIVE B - Public Domain (www.unlicense.org) 16422 This is free and unencumbered software released into the public domain. 16423 Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 16424 software, either in source code form or as a compiled binary, for any purpose, 16425 commercial or non-commercial, and by any means. 16426 In jurisdictions that recognize copyright laws, the author or authors of this 16427 software dedicate any and all copyright interest in the software to the public 16428 domain. We make this dedication for the benefit of the public at large and to 16429 the detriment of our heirs and successors. We intend this dedication to be an 16430 overt act of relinquishment in perpetuity of all present and future rights to 16431 this software under copyright law. 16432 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16433 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16434 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16435 AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 16436 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 16437 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 16438 ------------------------------------------------------------------------------ 16439 */ 16440 16441 16442 16443 16444 #ifdef NK_INCLUDE_FONT_BAKING 16445 /* ------------------------------------------------------------- 16446 * 16447 * RECT PACK 16448 * 16449 * --------------------------------------------------------------*/ 16450 16451 16452 16453 /* 16454 * ============================================================== 16455 * 16456 * TRUETYPE 16457 * 16458 * =============================================================== 16459 */ 16460 #define STBTT_MAX_OVERSAMPLE 8 16461 16462 16463 /* ------------------------------------------------------------- 16464 * 16465 * FONT BAKING 16466 * 16467 * --------------------------------------------------------------*/ 16468 struct nk_font_bake_data { 16469 struct stbtt_fontinfo info; 16470 struct stbrp_rect *rects; 16471 stbtt_pack_range *ranges; 16472 nk_rune range_count; 16473 }; 16474 16475 struct nk_font_baker { 16476 struct nk_allocator alloc; 16477 struct stbtt_pack_context spc; 16478 struct nk_font_bake_data *build; 16479 stbtt_packedchar *packed_chars; 16480 struct stbrp_rect *rects; 16481 stbtt_pack_range *ranges; 16482 }; 16483 16484 NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct stbrp_rect); 16485 NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(stbtt_pack_range); 16486 NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(stbtt_packedchar); 16487 NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data); 16488 NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker); 16489 16490 NK_INTERN int 16491 nk_range_count(const nk_rune *range) 16492 { 16493 const nk_rune *iter = range; 16494 NK_ASSERT(range); 16495 if (!range) return 0; 16496 while (*(iter++) != 0); 16497 return (iter == range) ? 0 : (int)((iter - range)/2); 16498 } 16499 NK_INTERN int 16500 nk_range_glyph_count(const nk_rune *range, int count) 16501 { 16502 int i = 0; 16503 int total_glyphs = 0; 16504 for (i = 0; i < count; ++i) { 16505 int diff; 16506 nk_rune f = range[(i*2)+0]; 16507 nk_rune t = range[(i*2)+1]; 16508 NK_ASSERT(t >= f); 16509 diff = (int)((t - f) + 1); 16510 total_glyphs += diff; 16511 } 16512 return total_glyphs; 16513 } 16514 NK_API const nk_rune* 16515 nk_font_default_glyph_ranges(void) 16516 { 16517 NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0}; 16518 return ranges; 16519 } 16520 NK_API const nk_rune* 16521 nk_font_chinese_glyph_ranges(void) 16522 { 16523 NK_STORAGE const nk_rune ranges[] = { 16524 0x0020, 0x00FF, 16525 0x3000, 0x30FF, 16526 0x31F0, 0x31FF, 16527 0xFF00, 0xFFEF, 16528 0x4E00, 0x9FAF, 16529 0 16530 }; 16531 return ranges; 16532 } 16533 NK_API const nk_rune* 16534 nk_font_cyrillic_glyph_ranges(void) 16535 { 16536 NK_STORAGE const nk_rune ranges[] = { 16537 0x0020, 0x00FF, 16538 0x0400, 0x052F, 16539 0x2DE0, 0x2DFF, 16540 0xA640, 0xA69F, 16541 0 16542 }; 16543 return ranges; 16544 } 16545 NK_API const nk_rune* 16546 nk_font_korean_glyph_ranges(void) 16547 { 16548 NK_STORAGE const nk_rune ranges[] = { 16549 0x0020, 0x00FF, 16550 0x3131, 0x3163, 16551 0xAC00, 0xD79D, 16552 0 16553 }; 16554 return ranges; 16555 } 16556 NK_INTERN void 16557 nk_font_baker_memory(nk_size *temp, int *glyph_count, 16558 struct nk_font_config *config_list, int count) 16559 { 16560 int range_count = 0; 16561 int total_range_count = 0; 16562 struct nk_font_config *iter, *i; 16563 16564 NK_ASSERT(config_list); 16565 NK_ASSERT(glyph_count); 16566 if (!config_list) { 16567 *temp = 0; 16568 *glyph_count = 0; 16569 return; 16570 } 16571 *glyph_count = 0; 16572 for (iter = config_list; iter; iter = iter->next) { 16573 i = iter; 16574 do {if (!i->range) iter->range = nk_font_default_glyph_ranges(); 16575 range_count = nk_range_count(i->range); 16576 total_range_count += range_count; 16577 *glyph_count += nk_range_glyph_count(i->range, range_count); 16578 } while ((i = i->n) != iter); 16579 } 16580 *temp = (nk_size)*glyph_count * sizeof(struct stbrp_rect); 16581 *temp += (nk_size)total_range_count * sizeof(stbtt_pack_range); 16582 *temp += (nk_size)*glyph_count * sizeof(stbtt_packedchar); 16583 *temp += (nk_size)count * sizeof(struct nk_font_bake_data); 16584 *temp += sizeof(struct nk_font_baker); 16585 *temp += nk_rect_align + nk_range_align + nk_char_align; 16586 *temp += nk_build_align + nk_baker_align; 16587 } 16588 NK_INTERN struct nk_font_baker* 16589 nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc) 16590 { 16591 struct nk_font_baker *baker; 16592 if (!memory) return 0; 16593 /* setup baker inside a memory block */ 16594 baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align); 16595 baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align); 16596 baker->packed_chars = (stbtt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align); 16597 baker->rects = (struct stbrp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align); 16598 baker->ranges = (stbtt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align); 16599 baker->alloc = *alloc; 16600 return baker; 16601 } 16602 NK_INTERN int 16603 nk_font_bake_pack(struct nk_font_baker *baker, 16604 nk_size *image_memory, int *width, int *height, struct nk_recti *custom, 16605 const struct nk_font_config *config_list, int count, 16606 struct nk_allocator *alloc) 16607 { 16608 NK_STORAGE const nk_size max_height = 1024 * 32; 16609 const struct nk_font_config *config_iter, *it; 16610 int total_glyph_count = 0; 16611 int total_range_count = 0; 16612 int range_count = 0; 16613 int i = 0; 16614 16615 NK_ASSERT(image_memory); 16616 NK_ASSERT(width); 16617 NK_ASSERT(height); 16618 NK_ASSERT(config_list); 16619 NK_ASSERT(count); 16620 NK_ASSERT(alloc); 16621 16622 if (!image_memory || !width || !height || !config_list || !count) return nk_false; 16623 for (config_iter = config_list; config_iter; config_iter = config_iter->next) { 16624 it = config_iter; 16625 do {range_count = nk_range_count(it->range); 16626 total_range_count += range_count; 16627 total_glyph_count += nk_range_glyph_count(it->range, range_count); 16628 } while ((it = it->n) != config_iter); 16629 } 16630 /* setup font baker from temporary memory */ 16631 for (config_iter = config_list; config_iter; config_iter = config_iter->next) { 16632 it = config_iter; 16633 do { 16634 struct stbtt_fontinfo *font_info = &baker->build[i++].info; 16635 font_info->userdata = alloc; 16636 16637 if (!stbtt_InitFont(font_info, (const unsigned char*)it->ttf_blob, stbtt_GetFontOffsetForIndex((const unsigned char*)it->ttf_blob, 0))) 16638 return nk_false; 16639 } while ((it = it->n) != config_iter); 16640 } 16641 *height = 0; 16642 *width = (total_glyph_count > 1000) ? 1024 : 512; 16643 stbtt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc); 16644 { 16645 int input_i = 0; 16646 int range_n = 0; 16647 int rect_n = 0; 16648 int char_n = 0; 16649 16650 if (custom) { 16651 /* pack custom user data first so it will be in the upper left corner*/ 16652 struct stbrp_rect custom_space; 16653 nk_zero(&custom_space, sizeof(custom_space)); 16654 custom_space.w = (stbrp_coord)(custom->w); 16655 custom_space.h = (stbrp_coord)(custom->h); 16656 16657 stbtt_PackSetOversampling(&baker->spc, 1, 1); 16658 stbrp_pack_rects((struct stbrp_context*)baker->spc.pack_info, &custom_space, 1); 16659 *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h)); 16660 16661 custom->x = (short)custom_space.x; 16662 custom->y = (short)custom_space.y; 16663 custom->w = (short)custom_space.w; 16664 custom->h = (short)custom_space.h; 16665 } 16666 16667 /* first font pass: pack all glyphs */ 16668 for (input_i = 0, config_iter = config_list; input_i < count && config_iter; 16669 config_iter = config_iter->next) { 16670 it = config_iter; 16671 do {int n = 0; 16672 int glyph_count; 16673 const nk_rune *in_range; 16674 const struct nk_font_config *cfg = it; 16675 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 16676 16677 /* count glyphs + ranges in current font */ 16678 glyph_count = 0; range_count = 0; 16679 for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) { 16680 glyph_count += (int)(in_range[1] - in_range[0]) + 1; 16681 range_count++; 16682 } 16683 16684 /* setup ranges */ 16685 tmp->ranges = baker->ranges + range_n; 16686 tmp->range_count = (nk_rune)range_count; 16687 range_n += range_count; 16688 for (i = 0; i < range_count; ++i) { 16689 in_range = &cfg->range[i * 2]; 16690 tmp->ranges[i].font_size = cfg->size; 16691 tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0]; 16692 tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1; 16693 tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n; 16694 char_n += tmp->ranges[i].num_chars; 16695 } 16696 16697 /* pack */ 16698 tmp->rects = baker->rects + rect_n; 16699 rect_n += glyph_count; 16700 stbtt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); 16701 n = stbtt_PackFontRangesGatherRects(&baker->spc, &tmp->info, 16702 tmp->ranges, (int)tmp->range_count, tmp->rects); 16703 stbrp_pack_rects((struct stbrp_context*)baker->spc.pack_info, tmp->rects, (int)n); 16704 16705 /* texture height */ 16706 for (i = 0; i < n; ++i) { 16707 if (tmp->rects[i].was_packed) 16708 *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h); 16709 } 16710 } while ((it = it->n) != config_iter); 16711 } 16712 NK_ASSERT(rect_n == total_glyph_count); 16713 NK_ASSERT(char_n == total_glyph_count); 16714 NK_ASSERT(range_n == total_range_count); 16715 } 16716 *height = (int)nk_round_up_pow2((nk_uint)*height); 16717 *image_memory = (nk_size)(*width) * (nk_size)(*height); 16718 return nk_true; 16719 } 16720 NK_INTERN void 16721 nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height, 16722 struct nk_font_glyph *glyphs, int glyphs_count, 16723 const struct nk_font_config *config_list, int font_count) 16724 { 16725 int input_i = 0; 16726 nk_rune glyph_n = 0; 16727 const struct nk_font_config *config_iter; 16728 const struct nk_font_config *it; 16729 16730 NK_ASSERT(image_memory); 16731 NK_ASSERT(width); 16732 NK_ASSERT(height); 16733 NK_ASSERT(config_list); 16734 NK_ASSERT(baker); 16735 NK_ASSERT(font_count); 16736 NK_ASSERT(glyphs_count); 16737 if (!image_memory || !width || !height || !config_list || 16738 !font_count || !glyphs || !glyphs_count) 16739 return; 16740 16741 /* second font pass: render glyphs */ 16742 nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height)); 16743 baker->spc.pixels = (unsigned char*)image_memory; 16744 baker->spc.height = (int)height; 16745 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; 16746 config_iter = config_iter->next) { 16747 it = config_iter; 16748 do {const struct nk_font_config *cfg = it; 16749 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 16750 stbtt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); 16751 stbtt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges, (int)tmp->range_count, tmp->rects); 16752 } while ((it = it->n) != config_iter); 16753 } stbtt_PackEnd(&baker->spc); 16754 16755 /* third pass: setup font and glyphs */ 16756 for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; 16757 config_iter = config_iter->next) { 16758 it = config_iter; 16759 do {nk_size i = 0; 16760 int char_idx = 0; 16761 nk_rune glyph_count = 0; 16762 const struct nk_font_config *cfg = it; 16763 struct nk_font_bake_data *tmp = &baker->build[input_i++]; 16764 struct nk_baked_font *dst_font = cfg->font; 16765 16766 float font_scale = stbtt_ScaleForPixelHeight(&tmp->info, cfg->size); 16767 int unscaled_ascent, unscaled_descent, unscaled_line_gap; 16768 stbtt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent, 16769 &unscaled_line_gap); 16770 16771 /* fill baked font */ 16772 if (!cfg->merge_mode) { 16773 dst_font->ranges = cfg->range; 16774 dst_font->height = cfg->size; 16775 dst_font->ascent = ((float)unscaled_ascent * font_scale); 16776 dst_font->descent = ((float)unscaled_descent * font_scale); 16777 dst_font->glyph_offset = glyph_n; 16778 /* 16779 Need to zero this, or it will carry over from a previous 16780 bake, and cause a segfault when accessing glyphs[]. 16781 */ 16782 dst_font->glyph_count = 0; 16783 } 16784 16785 /* fill own baked font glyph array */ 16786 for (i = 0; i < tmp->range_count; ++i) { 16787 stbtt_pack_range *range = &tmp->ranges[i]; 16788 for (char_idx = 0; char_idx < range->num_chars; char_idx++) 16789 { 16790 nk_rune codepoint = 0; 16791 float dummy_x = 0, dummy_y = 0; 16792 stbtt_aligned_quad q; 16793 struct nk_font_glyph *glyph; 16794 16795 /* query glyph bounds from stb_truetype */ 16796 const stbtt_packedchar *pc = &range->chardata_for_range[char_idx]; 16797 codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx); 16798 stbtt_GetPackedQuad(range->chardata_for_range, (int)width, 16799 (int)height, char_idx, &dummy_x, &dummy_y, &q, 0); 16800 16801 /* fill own glyph type with data */ 16802 glyph = &glyphs[dst_font->glyph_offset + dst_font->glyph_count + (unsigned int)glyph_count]; 16803 glyph->codepoint = codepoint; 16804 glyph->x0 = q.x0; glyph->y0 = q.y0; 16805 glyph->x1 = q.x1; glyph->y1 = q.y1; 16806 glyph->y0 += (dst_font->ascent + 0.5f); 16807 glyph->y1 += (dst_font->ascent + 0.5f); 16808 glyph->w = glyph->x1 - glyph->x0 + 0.5f; 16809 glyph->h = glyph->y1 - glyph->y0; 16810 16811 if (cfg->coord_type == NK_COORD_PIXEL) { 16812 glyph->u0 = q.s0 * (float)width; 16813 glyph->v0 = q.t0 * (float)height; 16814 glyph->u1 = q.s1 * (float)width; 16815 glyph->v1 = q.t1 * (float)height; 16816 } else { 16817 glyph->u0 = q.s0; 16818 glyph->v0 = q.t0; 16819 glyph->u1 = q.s1; 16820 glyph->v1 = q.t1; 16821 } 16822 glyph->xadvance = (pc->xadvance + cfg->spacing.x); 16823 if (cfg->pixel_snap) 16824 glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f); 16825 glyph_count++; 16826 } 16827 } 16828 dst_font->glyph_count += glyph_count; 16829 glyph_n += glyph_count; 16830 } while ((it = it->n) != config_iter); 16831 } 16832 } 16833 NK_INTERN void 16834 nk_font_bake_custom_data(void *img_memory, int img_width, int img_height, 16835 struct nk_recti img_dst, const char *texture_data_mask, int tex_width, 16836 int tex_height, char white, char black) 16837 { 16838 nk_byte *pixels; 16839 int y = 0; 16840 int x = 0; 16841 int n = 0; 16842 16843 NK_ASSERT(img_memory); 16844 NK_ASSERT(img_width); 16845 NK_ASSERT(img_height); 16846 NK_ASSERT(texture_data_mask); 16847 NK_UNUSED(tex_height); 16848 if (!img_memory || !img_width || !img_height || !texture_data_mask) 16849 return; 16850 16851 pixels = (nk_byte*)img_memory; 16852 for (y = 0, n = 0; y < tex_height; ++y) { 16853 for (x = 0; x < tex_width; ++x, ++n) { 16854 const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width); 16855 const int off1 = off0 + 1 + tex_width; 16856 pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00; 16857 pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00; 16858 } 16859 } 16860 } 16861 NK_INTERN void 16862 nk_font_bake_convert(void *out_memory, int img_width, int img_height, 16863 const void *in_memory) 16864 { 16865 int n = 0; 16866 nk_rune *dst; 16867 const nk_byte *src; 16868 16869 NK_ASSERT(out_memory); 16870 NK_ASSERT(in_memory); 16871 NK_ASSERT(img_width); 16872 NK_ASSERT(img_height); 16873 if (!out_memory || !in_memory || !img_height || !img_width) return; 16874 16875 dst = (nk_rune*)out_memory; 16876 src = (const nk_byte*)in_memory; 16877 for (n = (int)(img_width * img_height); n > 0; n--) 16878 *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF; 16879 } 16880 16881 /* ------------------------------------------------------------- 16882 * 16883 * FONT 16884 * 16885 * --------------------------------------------------------------*/ 16886 NK_INTERN float 16887 nk_font_text_width(nk_handle handle, float height, const char *text, int len) 16888 { 16889 nk_rune unicode; 16890 int text_len = 0; 16891 float text_width = 0; 16892 int glyph_len = 0; 16893 float scale = 0; 16894 16895 struct nk_font *font = (struct nk_font*)handle.ptr; 16896 NK_ASSERT(font); 16897 NK_ASSERT(font->glyphs); 16898 if (!font || !text || !len) 16899 return 0; 16900 16901 scale = height/font->info.height; 16902 glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len); 16903 if (!glyph_len) return 0; 16904 while (text_len <= (int)len && glyph_len) { 16905 const struct nk_font_glyph *g; 16906 if (unicode == NK_UTF_INVALID) break; 16907 16908 /* query currently drawn glyph information */ 16909 g = nk_font_find_glyph(font, unicode); 16910 text_width += g->xadvance * scale; 16911 16912 /* offset next glyph */ 16913 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len); 16914 text_len += glyph_len; 16915 } 16916 return text_width; 16917 } 16918 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 16919 NK_INTERN void 16920 nk_font_query_font_glyph(nk_handle handle, float height, 16921 struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) 16922 { 16923 float scale; 16924 const struct nk_font_glyph *g; 16925 struct nk_font *font; 16926 16927 NK_ASSERT(glyph); 16928 NK_UNUSED(next_codepoint); 16929 16930 font = (struct nk_font*)handle.ptr; 16931 NK_ASSERT(font); 16932 NK_ASSERT(font->glyphs); 16933 if (!font || !glyph) 16934 return; 16935 16936 scale = height/font->info.height; 16937 g = nk_font_find_glyph(font, codepoint); 16938 glyph->width = (g->x1 - g->x0) * scale; 16939 glyph->height = (g->y1 - g->y0) * scale; 16940 glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale); 16941 glyph->xadvance = (g->xadvance * scale); 16942 glyph->uv[0] = nk_vec2(g->u0, g->v0); 16943 glyph->uv[1] = nk_vec2(g->u1, g->v1); 16944 } 16945 #endif 16946 NK_API const struct nk_font_glyph* 16947 nk_font_find_glyph(struct nk_font *font, nk_rune unicode) 16948 { 16949 int i = 0; 16950 int count; 16951 int total_glyphs = 0; 16952 const struct nk_font_glyph *glyph = 0; 16953 const struct nk_font_config *iter = 0; 16954 16955 NK_ASSERT(font); 16956 NK_ASSERT(font->glyphs); 16957 NK_ASSERT(font->info.ranges); 16958 if (!font || !font->glyphs) return 0; 16959 16960 glyph = font->fallback; 16961 iter = font->config; 16962 do {count = nk_range_count(iter->range); 16963 for (i = 0; i < count; ++i) { 16964 nk_rune f = iter->range[(i*2)+0]; 16965 nk_rune t = iter->range[(i*2)+1]; 16966 int diff = (int)((t - f) + 1); 16967 if (unicode >= f && unicode <= t) 16968 return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))]; 16969 total_glyphs += diff; 16970 } 16971 } while ((iter = iter->n) != font->config); 16972 return glyph; 16973 } 16974 NK_INTERN void 16975 nk_font_init(struct nk_font *font, float pixel_height, 16976 nk_rune fallback_codepoint, struct nk_font_glyph *glyphs, 16977 const struct nk_baked_font *baked_font, nk_handle atlas) 16978 { 16979 struct nk_baked_font baked; 16980 NK_ASSERT(font); 16981 NK_ASSERT(glyphs); 16982 NK_ASSERT(baked_font); 16983 if (!font || !glyphs || !baked_font) 16984 return; 16985 16986 baked = *baked_font; 16987 font->fallback = 0; 16988 font->info = baked; 16989 font->scale = (float)pixel_height / (float)font->info.height; 16990 font->glyphs = &glyphs[baked_font->glyph_offset]; 16991 font->texture = atlas; 16992 font->fallback_codepoint = fallback_codepoint; 16993 font->fallback = nk_font_find_glyph(font, fallback_codepoint); 16994 16995 font->handle.height = font->info.height * font->scale; 16996 font->handle.width = nk_font_text_width; 16997 font->handle.userdata.ptr = font; 16998 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 16999 font->handle.query = nk_font_query_font_glyph; 17000 font->handle.texture = font->texture; 17001 #endif 17002 } 17003 17004 /* --------------------------------------------------------------------------- 17005 * 17006 * DEFAULT FONT 17007 * 17008 * ProggyClean.ttf 17009 * Copyright (c) 2004, 2005 Tristan Grimmer 17010 * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) 17011 * Download and more information at http://upperbounds.net 17012 *-----------------------------------------------------------------------------*/ 17013 #ifdef __clang__ 17014 #pragma clang diagnostic push 17015 #pragma clang diagnostic ignored "-Woverlength-strings" 17016 #elif defined(__GNUC__) || defined(__GNUG__) 17017 #pragma GCC diagnostic push 17018 #pragma GCC diagnostic ignored "-Woverlength-strings" 17019 #endif 17020 17021 #ifdef NK_INCLUDE_DEFAULT_FONT 17022 17023 NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] = 17024 "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" 17025 "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#" 17026 "`8ND>Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1<q-UE31#^-V'8IRUo7Qf./L>=Ke$$'5F%)]0^#0X@U.a<r:QLtFsLcL6##lOj)#.Y5<-R&KgLwqJfLgN&;Q?gI^#DY2uL" 17027 "i@^rMl9t=cWq6##weg>$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;-<nLENhvx>-VsM.M0rJfLH2eTM`*oJMHRC`N" 17028 "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+`�j@'DbG&#^$PG.Ll+DNa<XCMKEV*N)LN/N" 17029 "*b=%Q6pia-Xg8I$<MR&,VdJe$<(7G;Ckl'&hF;;$<_=X(b.RS%%)###MPBuuE1V:v&cXm#(&cV]`k9OhLMbn%s$G2,B$BfD3X*sp5#l,$R#]x_X1xKX%b5U*[r5iMfUo9U`N99hG)" 17030 "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" 17031 "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." 17032 "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" 17033 "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(,)" 17034 "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#" 17035 "'/###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" 17036 "_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" 17037 "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/" 17038 "/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" 17039 "%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&#" 17040 "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)(" 17041 "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" 17042 "o;#2:;%d	v68C5g?ntX0X)pT`;%pB3q7mgGN)3%(P8nTd5L7GeA-GL@+%J3u2:(Yf>et`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO" 17043 "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^-" 17044 "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-" 17045 "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" 17046 "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%" 17047 "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]" 17048 "%(?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" 17049 "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:" 17050 "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(" 17051 "$/V,;(kXZejWO`<[5?\?ewY(*9=%wDc;,u<'9t3W-(H1th3+G]ucQ]kLs7df($/*JL]@*t7Bu_G3_7mp7<iaQjO@.kLg;x3B0lqp7Hf,^Ze7-##@/c58Mo(3;knp0%)A7?-W+eI'o8)b<" 17052 "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'?" 17053 "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/;" 17054 ")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" 17055 "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(" 17056 "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" 17057 "bIu)'Z,*[>br5fX^:FPAWr-m2KgL<LUN098kTF&#lvo58=/vjDo;.;)Ka*hLR#/k=rKbxuV`>Q_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q" 17058 "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<-" 17059 "V8J'(1)G][68hW$5'q[GC&5j`TE?m'esFGNRM)j,ffZ?-qx8;->g4t*:CIP/[Qap7/9'#(1sao7w-.qNUdkJ)tCF&#B^;xGvn2r9FEPFFFcL@.iFNkTve$m%#QvQS8U@)2Z+3K:AKM5i" 17060 "sZ88+dKQ)W6>J%CL<KE>`.d*(B`-n8D9oK<Up]c$X$(,)M8Zt7/[rdkqTgl-0cuGMv'?>-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P	r+$%CE=68>K8r0=dSC%%(@p7" 17061 ".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@@" 17062 "$&)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*" 17063 "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" 17064 "@-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&#" 17065 "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#" 17066 "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" 17067 "d=j.LQf./Ll33+(;q3L-w=8dX$#WF&uIJ@-bfI>%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoFDoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8" 17068 "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&#" 17069 "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" 17070 ":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+" 17071 "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*" 17072 "$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" 17073 ":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" 17074 "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" 17075 "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" 17076 "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" 17077 ":^#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@&]>" 17078 "_>@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%" 17079 "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;" 17080 "^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:" 17081 "+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%" 17082 "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-" 17083 "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*" 17084 "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" 17085 "8kD2)2fU/M#$e.)T4,_=8hLim[&);?UkK'-x?'(:siIfL<$pFM`i<?%W(mGDHM%>iWP,##P`%/L<eXi:@Z9C.7o=@(pXdAO/NLQ8lPl+HPOQa8wD8=^GlPa8TKI1CjhsCTSLJM'/Wl>-" 17086 "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`" 17087 "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]%/" 17088 "+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" 17089 "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" 17090 "?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" 17091 "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" 17092 ">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'>" 17093 "[%$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" 17094 "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#" 17095 "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$" 17096 "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,)" 17097 "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" 17098 "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" 17099 "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" 17100 "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(#" 17101 ";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&>" 17102 "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#" 17103 "d<F&#*;G##.GY##2Sl##6`($#:l:$#>xL$#B.`$#F:r$#JF.%#NR@%#R_R%#Vke%#Zww%#_-4^Rh%Sflr-k'MS.o?.5/sWel/wpEM0%3'/1)K^f1-d>G21&v(35>V`39V7A4=onx4" 17104 "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#" 17105 "/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-#" 17106 "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#" 17107 "TmD<#%JSMFove:CTBEXI:<eh2g)B,3h2^G3i;#d3jD>)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP" 17108 "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp" 17109 "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#"; 17110 17111 #endif /* NK_INCLUDE_DEFAULT_FONT */ 17112 17113 #define NK_CURSOR_DATA_W 90 17114 #define NK_CURSOR_DATA_H 27 17115 NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] = 17116 { 17117 "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" 17118 "..- -X.....X- X.X - X.X -X.....X - X.....X" 17119 "--- -XXX.XXX- X...X - X...X -X....X - X....X" 17120 "X - X.X - X.....X - X.....X -X...X - X...X" 17121 "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" 17122 "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" 17123 "X..X - X.X - X.X - X.X -XX X.X - X.X XX" 17124 "X...X - X.X - X.X - XX X.X XX - X.X - X.X " 17125 "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X " 17126 "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X " 17127 "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " 17128 "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " 17129 "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " 17130 "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " 17131 "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " 17132 "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " 17133 "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " 17134 "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" 17135 "X.X X..X - -X.......X- X.......X - XX XX - " 17136 "XX X..X - - X.....X - X.....X - X.X X.X - " 17137 " X..X - X...X - X...X - X..X X..X - " 17138 " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " 17139 "------------ - X - X -X.....................X- " 17140 " ----------------------------------- X...XXXXXXXXXXXXX...X - " 17141 " - X..X X..X - " 17142 " - X.X X.X - " 17143 " - XX XX - " 17144 }; 17145 17146 #ifdef __clang__ 17147 #pragma clang diagnostic pop 17148 #elif defined(__GNUC__) || defined(__GNUG__) 17149 #pragma GCC diagnostic pop 17150 #endif 17151 17152 NK_GLOBAL unsigned char *nk__barrier; 17153 NK_GLOBAL unsigned char *nk__barrier2; 17154 NK_GLOBAL unsigned char *nk__barrier3; 17155 NK_GLOBAL unsigned char *nk__barrier4; 17156 NK_GLOBAL unsigned char *nk__dout; 17157 17158 NK_INTERN unsigned int 17159 nk_decompress_length(unsigned char *input) 17160 { 17161 return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]); 17162 } 17163 NK_INTERN void 17164 nk__match(unsigned char *data, unsigned int length) 17165 { 17166 /* INVERSE of memmove... write each byte before copying the next...*/ 17167 NK_ASSERT (nk__dout + length <= nk__barrier); 17168 if (nk__dout + length > nk__barrier) { nk__dout += length; return; } 17169 if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; } 17170 while (length--) *nk__dout++ = *data++; 17171 } 17172 NK_INTERN void 17173 nk__lit(unsigned char *data, unsigned int length) 17174 { 17175 NK_ASSERT (nk__dout + length <= nk__barrier); 17176 if (nk__dout + length > nk__barrier) { nk__dout += length; return; } 17177 if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; } 17178 NK_MEMCPY(nk__dout, data, length); 17179 nk__dout += length; 17180 } 17181 NK_INTERN unsigned char* 17182 nk_decompress_token(unsigned char *i) 17183 { 17184 #define nk__in2(x) ((i[x] << 8) + i[(x)+1]) 17185 #define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1)) 17186 #define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1)) 17187 17188 if (*i >= 0x20) { /* use fewer if's for cases that expand small */ 17189 if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2; 17190 else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3; 17191 else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1); 17192 } else { /* more ifs for cases that expand large, since overhead is amortized */ 17193 if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4; 17194 else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5; 17195 else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1); 17196 else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1); 17197 else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5; 17198 else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6; 17199 } 17200 return i; 17201 } 17202 NK_INTERN unsigned int 17203 nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen) 17204 { 17205 const unsigned long ADLER_MOD = 65521; 17206 unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; 17207 unsigned long blocklen, i; 17208 17209 blocklen = buflen % 5552; 17210 while (buflen) { 17211 for (i=0; i + 7 < blocklen; i += 8) { 17212 s1 += buffer[0]; s2 += s1; 17213 s1 += buffer[1]; s2 += s1; 17214 s1 += buffer[2]; s2 += s1; 17215 s1 += buffer[3]; s2 += s1; 17216 s1 += buffer[4]; s2 += s1; 17217 s1 += buffer[5]; s2 += s1; 17218 s1 += buffer[6]; s2 += s1; 17219 s1 += buffer[7]; s2 += s1; 17220 buffer += 8; 17221 } 17222 for (; i < blocklen; ++i) { 17223 s1 += *buffer++; s2 += s1; 17224 } 17225 17226 s1 %= ADLER_MOD; s2 %= ADLER_MOD; 17227 buflen -= (unsigned int)blocklen; 17228 blocklen = 5552; 17229 } 17230 return (unsigned int)(s2 << 16) + (unsigned int)s1; 17231 } 17232 NK_INTERN unsigned int 17233 nk_decompress(unsigned char *output, unsigned char *i, unsigned int length) 17234 { 17235 unsigned int olen; 17236 if (nk__in4(0) != 0x57bC0000) return 0; 17237 if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */ 17238 olen = nk_decompress_length(i); 17239 nk__barrier2 = i; 17240 nk__barrier3 = i+length; 17241 nk__barrier = output + olen; 17242 nk__barrier4 = output; 17243 i += 16; 17244 17245 nk__dout = output; 17246 for (;;) { 17247 unsigned char *old_i = i; 17248 i = nk_decompress_token(i); 17249 if (i == old_i) { 17250 if (*i == 0x05 && i[1] == 0xfa) { 17251 NK_ASSERT(nk__dout == output + olen); 17252 if (nk__dout != output + olen) return 0; 17253 if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2)) 17254 return 0; 17255 return olen; 17256 } else { 17257 NK_ASSERT(0); /* NOTREACHED */ 17258 return 0; 17259 } 17260 } 17261 NK_ASSERT(nk__dout <= output + olen); 17262 if (nk__dout > output + olen) 17263 return 0; 17264 } 17265 } 17266 NK_INTERN unsigned int 17267 nk_decode_85_byte(char c) 17268 { 17269 return (unsigned int)((c >= '\\') ? c-36 : c-35); 17270 } 17271 NK_INTERN void 17272 nk_decode_85(unsigned char* dst, const unsigned char* src) 17273 { 17274 while (*src) 17275 { 17276 unsigned int tmp = 17277 nk_decode_85_byte((char)src[0]) + 17278 85 * (nk_decode_85_byte((char)src[1]) + 17279 85 * (nk_decode_85_byte((char)src[2]) + 17280 85 * (nk_decode_85_byte((char)src[3]) + 17281 85 * nk_decode_85_byte((char)src[4])))); 17282 17283 /* we can't assume little-endianess. */ 17284 dst[0] = (unsigned char)((tmp >> 0) & 0xFF); 17285 dst[1] = (unsigned char)((tmp >> 8) & 0xFF); 17286 dst[2] = (unsigned char)((tmp >> 16) & 0xFF); 17287 dst[3] = (unsigned char)((tmp >> 24) & 0xFF); 17288 17289 src += 5; 17290 dst += 4; 17291 } 17292 } 17293 17294 /* ------------------------------------------------------------- 17295 * 17296 * FONT ATLAS 17297 * 17298 * --------------------------------------------------------------*/ 17299 NK_API struct nk_font_config 17300 nk_font_config(float pixel_height) 17301 { 17302 struct nk_font_config cfg; 17303 nk_zero_struct(cfg); 17304 cfg.ttf_blob = 0; 17305 cfg.ttf_size = 0; 17306 cfg.ttf_data_owned_by_atlas = 0; 17307 cfg.size = pixel_height; 17308 cfg.oversample_h = 3; 17309 cfg.oversample_v = 1; 17310 cfg.pixel_snap = 0; 17311 cfg.coord_type = NK_COORD_UV; 17312 cfg.spacing = nk_vec2(0,0); 17313 cfg.range = nk_font_default_glyph_ranges(); 17314 cfg.merge_mode = 0; 17315 cfg.fallback_glyph = '?'; 17316 cfg.font = 0; 17317 cfg.n = 0; 17318 return cfg; 17319 } 17320 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 17321 NK_API void 17322 nk_font_atlas_init_default(struct nk_font_atlas *atlas) 17323 { 17324 NK_ASSERT(atlas); 17325 if (!atlas) return; 17326 nk_zero_struct(*atlas); 17327 atlas->temporary.userdata.ptr = 0; 17328 atlas->temporary.alloc = nk_malloc; 17329 atlas->temporary.free = nk_mfree; 17330 atlas->permanent.userdata.ptr = 0; 17331 atlas->permanent.alloc = nk_malloc; 17332 atlas->permanent.free = nk_mfree; 17333 } 17334 #endif 17335 NK_API void 17336 nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc) 17337 { 17338 NK_ASSERT(atlas); 17339 NK_ASSERT(alloc); 17340 if (!atlas || !alloc) return; 17341 nk_zero_struct(*atlas); 17342 atlas->permanent = *alloc; 17343 atlas->temporary = *alloc; 17344 } 17345 NK_API void 17346 nk_font_atlas_init_custom(struct nk_font_atlas *atlas, 17347 struct nk_allocator *permanent, struct nk_allocator *temporary) 17348 { 17349 NK_ASSERT(atlas); 17350 NK_ASSERT(permanent); 17351 NK_ASSERT(temporary); 17352 if (!atlas || !permanent || !temporary) return; 17353 nk_zero_struct(*atlas); 17354 atlas->permanent = *permanent; 17355 atlas->temporary = *temporary; 17356 } 17357 NK_API void 17358 nk_font_atlas_begin(struct nk_font_atlas *atlas) 17359 { 17360 NK_ASSERT(atlas); 17361 NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free); 17362 NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free); 17363 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free || 17364 !atlas->temporary.alloc || !atlas->temporary.free) return; 17365 if (atlas->glyphs) { 17366 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 17367 atlas->glyphs = 0; 17368 } 17369 if (atlas->pixel) { 17370 atlas->permanent.free(atlas->permanent.userdata, atlas->pixel); 17371 atlas->pixel = 0; 17372 } 17373 } 17374 NK_API struct nk_font* 17375 nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config) 17376 { 17377 struct nk_font *font = 0; 17378 struct nk_font_config *cfg; 17379 17380 NK_ASSERT(atlas); 17381 NK_ASSERT(atlas->permanent.alloc); 17382 NK_ASSERT(atlas->permanent.free); 17383 NK_ASSERT(atlas->temporary.alloc); 17384 NK_ASSERT(atlas->temporary.free); 17385 17386 NK_ASSERT(config); 17387 NK_ASSERT(config->ttf_blob); 17388 NK_ASSERT(config->ttf_size); 17389 NK_ASSERT(config->size > 0.0f); 17390 17391 if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f|| 17392 !atlas->permanent.alloc || !atlas->permanent.free || 17393 !atlas->temporary.alloc || !atlas->temporary.free) 17394 return 0; 17395 17396 /* allocate font config */ 17397 cfg = (struct nk_font_config*) 17398 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config)); 17399 NK_MEMCPY(cfg, config, sizeof(*config)); 17400 cfg->n = cfg; 17401 cfg->p = cfg; 17402 17403 if (!config->merge_mode) { 17404 /* insert font config into list */ 17405 if (!atlas->config) { 17406 atlas->config = cfg; 17407 cfg->next = 0; 17408 } else { 17409 struct nk_font_config *i = atlas->config; 17410 while (i->next) i = i->next; 17411 i->next = cfg; 17412 cfg->next = 0; 17413 } 17414 /* allocate new font */ 17415 font = (struct nk_font*) 17416 atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font)); 17417 NK_ASSERT(font); 17418 nk_zero(font, sizeof(*font)); 17419 if (!font) return 0; 17420 font->config = cfg; 17421 17422 /* insert font into list */ 17423 if (!atlas->fonts) { 17424 atlas->fonts = font; 17425 font->next = 0; 17426 } else { 17427 struct nk_font *i = atlas->fonts; 17428 while (i->next) i = i->next; 17429 i->next = font; 17430 font->next = 0; 17431 } 17432 cfg->font = &font->info; 17433 } else { 17434 /* extend previously added font */ 17435 struct nk_font *f = 0; 17436 struct nk_font_config *c = 0; 17437 NK_ASSERT(atlas->font_num); 17438 f = atlas->fonts; 17439 c = f->config; 17440 cfg->font = &f->info; 17441 17442 cfg->n = c; 17443 cfg->p = c->p; 17444 c->p->n = cfg; 17445 c->p = cfg; 17446 } 17447 /* create own copy of .TTF font blob */ 17448 if (!config->ttf_data_owned_by_atlas) { 17449 cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size); 17450 NK_ASSERT(cfg->ttf_blob); 17451 if (!cfg->ttf_blob) { 17452 atlas->font_num++; 17453 return 0; 17454 } 17455 NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size); 17456 cfg->ttf_data_owned_by_atlas = 1; 17457 } 17458 atlas->font_num++; 17459 return font; 17460 } 17461 NK_API struct nk_font* 17462 nk_font_atlas_add_from_memory(struct nk_font_atlas *atlas, void *memory, 17463 nk_size size, float height, const struct nk_font_config *config) 17464 { 17465 struct nk_font_config cfg; 17466 NK_ASSERT(memory); 17467 NK_ASSERT(size); 17468 17469 NK_ASSERT(atlas); 17470 NK_ASSERT(atlas->temporary.alloc); 17471 NK_ASSERT(atlas->temporary.free); 17472 NK_ASSERT(atlas->permanent.alloc); 17473 NK_ASSERT(atlas->permanent.free); 17474 if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size || 17475 !atlas->permanent.alloc || !atlas->permanent.free) 17476 return 0; 17477 17478 cfg = (config) ? *config: nk_font_config(height); 17479 cfg.ttf_blob = memory; 17480 cfg.ttf_size = size; 17481 cfg.size = height; 17482 cfg.ttf_data_owned_by_atlas = 0; 17483 return nk_font_atlas_add(atlas, &cfg); 17484 } 17485 #ifdef NK_INCLUDE_STANDARD_IO 17486 NK_API struct nk_font* 17487 nk_font_atlas_add_from_file(struct nk_font_atlas *atlas, const char *file_path, 17488 float height, const struct nk_font_config *config) 17489 { 17490 nk_size size; 17491 char *memory; 17492 struct nk_font_config cfg; 17493 17494 NK_ASSERT(atlas); 17495 NK_ASSERT(atlas->temporary.alloc); 17496 NK_ASSERT(atlas->temporary.free); 17497 NK_ASSERT(atlas->permanent.alloc); 17498 NK_ASSERT(atlas->permanent.free); 17499 17500 if (!atlas || !file_path) return 0; 17501 memory = nk_file_load(file_path, &size, &atlas->permanent); 17502 if (!memory) return 0; 17503 17504 cfg = (config) ? *config: nk_font_config(height); 17505 cfg.ttf_blob = memory; 17506 cfg.ttf_size = size; 17507 cfg.size = height; 17508 cfg.ttf_data_owned_by_atlas = 1; 17509 return nk_font_atlas_add(atlas, &cfg); 17510 } 17511 #endif 17512 NK_API struct nk_font* 17513 nk_font_atlas_add_compressed(struct nk_font_atlas *atlas, 17514 void *compressed_data, nk_size compressed_size, float height, 17515 const struct nk_font_config *config) 17516 { 17517 unsigned int decompressed_size; 17518 void *decompressed_data; 17519 struct nk_font_config cfg; 17520 17521 NK_ASSERT(atlas); 17522 NK_ASSERT(atlas->temporary.alloc); 17523 NK_ASSERT(atlas->temporary.free); 17524 NK_ASSERT(atlas->permanent.alloc); 17525 NK_ASSERT(atlas->permanent.free); 17526 17527 NK_ASSERT(compressed_data); 17528 NK_ASSERT(compressed_size); 17529 if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free || 17530 !atlas->permanent.alloc || !atlas->permanent.free) 17531 return 0; 17532 17533 decompressed_size = nk_decompress_length((unsigned char*)compressed_data); 17534 decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size); 17535 NK_ASSERT(decompressed_data); 17536 if (!decompressed_data) return 0; 17537 nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data, 17538 (unsigned int)compressed_size); 17539 17540 cfg = (config) ? *config: nk_font_config(height); 17541 cfg.ttf_blob = decompressed_data; 17542 cfg.ttf_size = decompressed_size; 17543 cfg.size = height; 17544 cfg.ttf_data_owned_by_atlas = 1; 17545 return nk_font_atlas_add(atlas, &cfg); 17546 } 17547 NK_API struct nk_font* 17548 nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas, 17549 const char *data_base85, float height, const struct nk_font_config *config) 17550 { 17551 int compressed_size; 17552 void *compressed_data; 17553 struct nk_font *font; 17554 17555 NK_ASSERT(atlas); 17556 NK_ASSERT(atlas->temporary.alloc); 17557 NK_ASSERT(atlas->temporary.free); 17558 NK_ASSERT(atlas->permanent.alloc); 17559 NK_ASSERT(atlas->permanent.free); 17560 17561 NK_ASSERT(data_base85); 17562 if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free || 17563 !atlas->permanent.alloc || !atlas->permanent.free) 17564 return 0; 17565 17566 compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4; 17567 compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size); 17568 NK_ASSERT(compressed_data); 17569 if (!compressed_data) return 0; 17570 nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85); 17571 font = nk_font_atlas_add_compressed(atlas, compressed_data, 17572 (nk_size)compressed_size, height, config); 17573 atlas->temporary.free(atlas->temporary.userdata, compressed_data); 17574 return font; 17575 } 17576 17577 #ifdef NK_INCLUDE_DEFAULT_FONT 17578 NK_API struct nk_font* 17579 nk_font_atlas_add_default(struct nk_font_atlas *atlas, 17580 float pixel_height, const struct nk_font_config *config) 17581 { 17582 NK_ASSERT(atlas); 17583 NK_ASSERT(atlas->temporary.alloc); 17584 NK_ASSERT(atlas->temporary.free); 17585 NK_ASSERT(atlas->permanent.alloc); 17586 NK_ASSERT(atlas->permanent.free); 17587 return nk_font_atlas_add_compressed_base85(atlas, 17588 nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config); 17589 } 17590 #endif 17591 NK_API const void* 17592 nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height, 17593 enum nk_font_atlas_format fmt) 17594 { 17595 int i = 0; 17596 void *tmp = 0; 17597 nk_size tmp_size, img_size; 17598 struct nk_font *font_iter; 17599 struct nk_font_baker *baker; 17600 17601 NK_ASSERT(atlas); 17602 NK_ASSERT(atlas->temporary.alloc); 17603 NK_ASSERT(atlas->temporary.free); 17604 NK_ASSERT(atlas->permanent.alloc); 17605 NK_ASSERT(atlas->permanent.free); 17606 17607 NK_ASSERT(width); 17608 NK_ASSERT(height); 17609 if (!atlas || !width || !height || 17610 !atlas->temporary.alloc || !atlas->temporary.free || 17611 !atlas->permanent.alloc || !atlas->permanent.free) 17612 return 0; 17613 17614 #ifdef NK_INCLUDE_DEFAULT_FONT 17615 /* no font added so just use default font */ 17616 if (!atlas->font_num) 17617 atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0); 17618 #endif 17619 NK_ASSERT(atlas->font_num); 17620 if (!atlas->font_num) return 0; 17621 17622 /* allocate temporary baker memory required for the baking process */ 17623 nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num); 17624 tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size); 17625 NK_ASSERT(tmp); 17626 if (!tmp) goto failed; 17627 NK_MEMSET(tmp,0,tmp_size); 17628 17629 /* allocate glyph memory for all fonts */ 17630 baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary); 17631 atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc( 17632 atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count); 17633 NK_ASSERT(atlas->glyphs); 17634 if (!atlas->glyphs) 17635 goto failed; 17636 17637 /* pack all glyphs into a tight fit space */ 17638 atlas->custom.w = (NK_CURSOR_DATA_W*2)+1; 17639 atlas->custom.h = NK_CURSOR_DATA_H + 1; 17640 if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom, 17641 atlas->config, atlas->font_num, &atlas->temporary)) 17642 goto failed; 17643 17644 /* allocate memory for the baked image font atlas */ 17645 atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size); 17646 NK_ASSERT(atlas->pixel); 17647 if (!atlas->pixel) 17648 goto failed; 17649 17650 /* bake glyphs and custom white pixel into image */ 17651 nk_font_bake(baker, atlas->pixel, *width, *height, 17652 atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num); 17653 nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom, 17654 nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X'); 17655 17656 if (fmt == NK_FONT_ATLAS_RGBA32) { 17657 /* convert alpha8 image into rgba32 image */ 17658 void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0, 17659 (nk_size)(*width * *height * 4)); 17660 NK_ASSERT(img_rgba); 17661 if (!img_rgba) goto failed; 17662 nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel); 17663 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 17664 atlas->pixel = img_rgba; 17665 } 17666 atlas->tex_width = *width; 17667 atlas->tex_height = *height; 17668 17669 /* initialize each font */ 17670 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { 17671 struct nk_font *font = font_iter; 17672 struct nk_font_config *config = font->config; 17673 nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs, 17674 config->font, nk_handle_ptr(0)); 17675 } 17676 17677 /* initialize each cursor */ 17678 {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = { 17679 /* Pos Size Offset */ 17680 {{ 0, 3}, {12,19}, { 0, 0}}, 17681 {{13, 0}, { 7,16}, { 4, 8}}, 17682 {{31, 0}, {23,23}, {11,11}}, 17683 {{21, 0}, { 9, 23}, { 5,11}}, 17684 {{55,18}, {23, 9}, {11, 5}}, 17685 {{73, 0}, {17,17}, { 9, 9}}, 17686 {{55, 0}, {17,17}, { 9, 9}} 17687 }; 17688 for (i = 0; i < NK_CURSOR_COUNT; ++i) { 17689 struct nk_cursor *cursor = &atlas->cursors[i]; 17690 cursor->img.w = (unsigned short)*width; 17691 cursor->img.h = (unsigned short)*height; 17692 cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x); 17693 cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y); 17694 cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x; 17695 cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y; 17696 cursor->size = nk_cursor_data[i][1]; 17697 cursor->offset = nk_cursor_data[i][2]; 17698 }} 17699 /* free temporary memory */ 17700 atlas->temporary.free(atlas->temporary.userdata, tmp); 17701 return atlas->pixel; 17702 17703 failed: 17704 /* error so cleanup all memory */ 17705 if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp); 17706 if (atlas->glyphs) { 17707 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 17708 atlas->glyphs = 0; 17709 } 17710 if (atlas->pixel) { 17711 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 17712 atlas->pixel = 0; 17713 } 17714 return 0; 17715 } 17716 NK_API void 17717 nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture, 17718 struct nk_draw_null_texture *tex_null) 17719 { 17720 int i = 0; 17721 struct nk_font *font_iter; 17722 NK_ASSERT(atlas); 17723 if (!atlas) { 17724 if (!tex_null) return; 17725 tex_null->texture = texture; 17726 tex_null->uv = nk_vec2(0.5f,0.5f); 17727 } 17728 if (tex_null) { 17729 tex_null->texture = texture; 17730 tex_null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width; 17731 tex_null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height; 17732 } 17733 for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { 17734 font_iter->texture = texture; 17735 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 17736 font_iter->handle.texture = texture; 17737 #endif 17738 } 17739 for (i = 0; i < NK_CURSOR_COUNT; ++i) 17740 atlas->cursors[i].img.handle = texture; 17741 17742 atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); 17743 atlas->pixel = 0; 17744 atlas->tex_width = 0; 17745 atlas->tex_height = 0; 17746 atlas->custom.x = 0; 17747 atlas->custom.y = 0; 17748 atlas->custom.w = 0; 17749 atlas->custom.h = 0; 17750 } 17751 NK_API void 17752 nk_font_atlas_cleanup(struct nk_font_atlas *atlas) 17753 { 17754 NK_ASSERT(atlas); 17755 NK_ASSERT(atlas->temporary.alloc); 17756 NK_ASSERT(atlas->temporary.free); 17757 NK_ASSERT(atlas->permanent.alloc); 17758 NK_ASSERT(atlas->permanent.free); 17759 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; 17760 if (atlas->config) { 17761 struct nk_font_config *iter; 17762 for (iter = atlas->config; iter; iter = iter->next) { 17763 struct nk_font_config *i; 17764 for (i = iter->n; i != iter; i = i->n) { 17765 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob); 17766 i->ttf_blob = 0; 17767 } 17768 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob); 17769 iter->ttf_blob = 0; 17770 } 17771 } 17772 } 17773 NK_API void 17774 nk_font_atlas_clear(struct nk_font_atlas *atlas) 17775 { 17776 NK_ASSERT(atlas); 17777 NK_ASSERT(atlas->temporary.alloc); 17778 NK_ASSERT(atlas->temporary.free); 17779 NK_ASSERT(atlas->permanent.alloc); 17780 NK_ASSERT(atlas->permanent.free); 17781 if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; 17782 17783 if (atlas->config) { 17784 struct nk_font_config *iter, *next; 17785 for (iter = atlas->config; iter; iter = next) { 17786 struct nk_font_config *i, *n; 17787 for (i = iter->n; i != iter; i = n) { 17788 n = i->n; 17789 if (i->ttf_blob) 17790 atlas->permanent.free(atlas->permanent.userdata, i->ttf_blob); 17791 atlas->permanent.free(atlas->permanent.userdata, i); 17792 } 17793 next = iter->next; 17794 if (i->ttf_blob) 17795 atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob); 17796 atlas->permanent.free(atlas->permanent.userdata, iter); 17797 } 17798 atlas->config = 0; 17799 } 17800 if (atlas->fonts) { 17801 struct nk_font *iter, *next; 17802 for (iter = atlas->fonts; iter; iter = next) { 17803 next = iter->next; 17804 atlas->permanent.free(atlas->permanent.userdata, iter); 17805 } 17806 atlas->fonts = 0; 17807 } 17808 if (atlas->glyphs) 17809 atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); 17810 nk_zero_struct(*atlas); 17811 } 17812 #endif 17813 17814 17815 17816 17817 17818 /* =============================================================== 17819 * 17820 * INPUT 17821 * 17822 * ===============================================================*/ 17823 NK_API void 17824 nk_input_begin(struct nk_context *ctx) 17825 { 17826 int i; 17827 struct nk_input *in; 17828 NK_ASSERT(ctx); 17829 if (!ctx) return; 17830 in = &ctx->input; 17831 for (i = 0; i < NK_BUTTON_MAX; ++i) 17832 in->mouse.buttons[i].clicked = 0; 17833 17834 in->keyboard.text_len = 0; 17835 in->mouse.scroll_delta = nk_vec2(0,0); 17836 in->mouse.prev.x = in->mouse.pos.x; 17837 in->mouse.prev.y = in->mouse.pos.y; 17838 in->mouse.delta.x = 0; 17839 in->mouse.delta.y = 0; 17840 for (i = 0; i < NK_KEY_MAX; i++) 17841 in->keyboard.keys[i].clicked = 0; 17842 } 17843 NK_API void 17844 nk_input_end(struct nk_context *ctx) 17845 { 17846 struct nk_input *in; 17847 NK_ASSERT(ctx); 17848 if (!ctx) return; 17849 in = &ctx->input; 17850 if (in->mouse.grab) 17851 in->mouse.grab = 0; 17852 if (in->mouse.ungrab) { 17853 in->mouse.grabbed = 0; 17854 in->mouse.ungrab = 0; 17855 in->mouse.grab = 0; 17856 } 17857 } 17858 NK_API void 17859 nk_input_motion(struct nk_context *ctx, int x, int y) 17860 { 17861 struct nk_input *in; 17862 NK_ASSERT(ctx); 17863 if (!ctx) return; 17864 in = &ctx->input; 17865 in->mouse.pos.x = (float)x; 17866 in->mouse.pos.y = (float)y; 17867 in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x; 17868 in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y; 17869 } 17870 NK_API void 17871 nk_input_key(struct nk_context *ctx, enum nk_keys key, nk_bool down) 17872 { 17873 struct nk_input *in; 17874 NK_ASSERT(ctx); 17875 if (!ctx) return; 17876 in = &ctx->input; 17877 #ifdef NK_KEYSTATE_BASED_INPUT 17878 if (in->keyboard.keys[key].down != down) 17879 in->keyboard.keys[key].clicked++; 17880 #else 17881 in->keyboard.keys[key].clicked++; 17882 #endif 17883 in->keyboard.keys[key].down = down; 17884 } 17885 NK_API void 17886 nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, nk_bool down) 17887 { 17888 struct nk_mouse_button *btn; 17889 struct nk_input *in; 17890 NK_ASSERT(ctx); 17891 if (!ctx) return; 17892 in = &ctx->input; 17893 if (in->mouse.buttons[id].down == down) return; 17894 17895 btn = &in->mouse.buttons[id]; 17896 btn->clicked_pos.x = (float)x; 17897 btn->clicked_pos.y = (float)y; 17898 btn->down = down; 17899 btn->clicked++; 17900 17901 /* Fix Click-Drag for touch events. */ 17902 in->mouse.delta.x = 0; 17903 in->mouse.delta.y = 0; 17904 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE 17905 if (down == 1 && id == NK_BUTTON_LEFT) 17906 { 17907 in->mouse.down_pos.x = btn->clicked_pos.x; 17908 in->mouse.down_pos.y = btn->clicked_pos.y; 17909 } 17910 #endif 17911 } 17912 NK_API void 17913 nk_input_scroll(struct nk_context *ctx, struct nk_vec2 val) 17914 { 17915 NK_ASSERT(ctx); 17916 if (!ctx) return; 17917 ctx->input.mouse.scroll_delta.x += val.x; 17918 ctx->input.mouse.scroll_delta.y += val.y; 17919 } 17920 NK_API void 17921 nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph) 17922 { 17923 int len = 0; 17924 nk_rune unicode; 17925 struct nk_input *in; 17926 17927 NK_ASSERT(ctx); 17928 if (!ctx) return; 17929 in = &ctx->input; 17930 17931 len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE); 17932 if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) { 17933 nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len], 17934 NK_INPUT_MAX - in->keyboard.text_len); 17935 in->keyboard.text_len += len; 17936 } 17937 } 17938 NK_API void 17939 nk_input_char(struct nk_context *ctx, char c) 17940 { 17941 nk_glyph glyph; 17942 NK_ASSERT(ctx); 17943 if (!ctx) return; 17944 glyph[0] = c; 17945 nk_input_glyph(ctx, glyph); 17946 } 17947 NK_API void 17948 nk_input_unicode(struct nk_context *ctx, nk_rune unicode) 17949 { 17950 nk_glyph rune; 17951 NK_ASSERT(ctx); 17952 if (!ctx) return; 17953 nk_utf_encode(unicode, rune, NK_UTF_SIZE); 17954 nk_input_glyph(ctx, rune); 17955 } 17956 NK_API nk_bool 17957 nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id) 17958 { 17959 const struct nk_mouse_button *btn; 17960 if (!i) return nk_false; 17961 btn = &i->mouse.buttons[id]; 17962 return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false; 17963 } 17964 NK_API nk_bool 17965 nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, 17966 struct nk_rect b) 17967 { 17968 const struct nk_mouse_button *btn; 17969 if (!i) return nk_false; 17970 btn = &i->mouse.buttons[id]; 17971 if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h)) 17972 return nk_false; 17973 return nk_true; 17974 } 17975 NK_API nk_bool 17976 nk_input_has_mouse_click_in_button_rect(const struct nk_input *i, enum nk_buttons id, 17977 struct nk_rect b) 17978 { 17979 const struct nk_mouse_button *btn; 17980 if (!i) return nk_false; 17981 btn = &i->mouse.buttons[id]; 17982 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE 17983 if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h) 17984 || !NK_INBOX(i->mouse.down_pos.x,i->mouse.down_pos.y,b.x,b.y,b.w,b.h)) 17985 #else 17986 if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h)) 17987 #endif 17988 return nk_false; 17989 return nk_true; 17990 } 17991 NK_API nk_bool 17992 nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, 17993 struct nk_rect b, nk_bool down) 17994 { 17995 const struct nk_mouse_button *btn; 17996 if (!i) return nk_false; 17997 btn = &i->mouse.buttons[id]; 17998 return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down); 17999 } 18000 NK_API nk_bool 18001 nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, 18002 struct nk_rect b) 18003 { 18004 const struct nk_mouse_button *btn; 18005 if (!i) return nk_false; 18006 btn = &i->mouse.buttons[id]; 18007 return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) && 18008 btn->clicked) ? nk_true : nk_false; 18009 } 18010 NK_API nk_bool 18011 nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, 18012 struct nk_rect b, nk_bool down) 18013 { 18014 const struct nk_mouse_button *btn; 18015 if (!i) return nk_false; 18016 btn = &i->mouse.buttons[id]; 18017 return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) && 18018 btn->clicked) ? nk_true : nk_false; 18019 } 18020 NK_API nk_bool 18021 nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b) 18022 { 18023 int i, down = 0; 18024 for (i = 0; i < NK_BUTTON_MAX; ++i) 18025 down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b); 18026 return down; 18027 } 18028 NK_API nk_bool 18029 nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect) 18030 { 18031 if (!i) return nk_false; 18032 return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h); 18033 } 18034 NK_API nk_bool 18035 nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect) 18036 { 18037 if (!i) return nk_false; 18038 return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h); 18039 } 18040 NK_API nk_bool 18041 nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect) 18042 { 18043 if (!i) return nk_false; 18044 if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false; 18045 return nk_input_is_mouse_click_in_rect(i, id, rect); 18046 } 18047 NK_API nk_bool 18048 nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id) 18049 { 18050 if (!i) return nk_false; 18051 return i->mouse.buttons[id].down; 18052 } 18053 NK_API nk_bool 18054 nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id) 18055 { 18056 const struct nk_mouse_button *b; 18057 if (!i) return nk_false; 18058 b = &i->mouse.buttons[id]; 18059 if (b->down && b->clicked) 18060 return nk_true; 18061 return nk_false; 18062 } 18063 NK_API nk_bool 18064 nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id) 18065 { 18066 if (!i) return nk_false; 18067 return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked); 18068 } 18069 NK_API nk_bool 18070 nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key) 18071 { 18072 const struct nk_key *k; 18073 if (!i) return nk_false; 18074 k = &i->keyboard.keys[key]; 18075 if ((k->down && k->clicked) || (!k->down && k->clicked >= 2)) 18076 return nk_true; 18077 return nk_false; 18078 } 18079 NK_API nk_bool 18080 nk_input_is_key_released(const struct nk_input *i, enum nk_keys key) 18081 { 18082 const struct nk_key *k; 18083 if (!i) return nk_false; 18084 k = &i->keyboard.keys[key]; 18085 if ((!k->down && k->clicked) || (k->down && k->clicked >= 2)) 18086 return nk_true; 18087 return nk_false; 18088 } 18089 NK_API nk_bool 18090 nk_input_is_key_down(const struct nk_input *i, enum nk_keys key) 18091 { 18092 const struct nk_key *k; 18093 if (!i) return nk_false; 18094 k = &i->keyboard.keys[key]; 18095 if (k->down) return nk_true; 18096 return nk_false; 18097 } 18098 18099 18100 18101 18102 18103 /* =============================================================== 18104 * 18105 * STYLE 18106 * 18107 * ===============================================================*/ 18108 NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);} 18109 #define NK_COLOR_MAP(NK_COLOR)\ 18110 NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \ 18111 NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \ 18112 NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \ 18113 NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \ 18114 NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \ 18115 NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \ 18116 NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \ 18117 NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \ 18118 NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \ 18119 NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \ 18120 NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \ 18121 NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \ 18122 NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \ 18123 NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \ 18124 NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \ 18125 NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \ 18126 NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \ 18127 NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \ 18128 NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \ 18129 NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \ 18130 NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \ 18131 NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \ 18132 NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT, 255, 0, 0, 255) \ 18133 NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \ 18134 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \ 18135 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER, 120,120,120,255) \ 18136 NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, 150,150,150,255) \ 18137 NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) 18138 18139 NK_GLOBAL const struct nk_color 18140 nk_default_color_style[NK_COLOR_COUNT] = { 18141 #define NK_COLOR(a,b,c,d,e) {b,c,d,e}, 18142 NK_COLOR_MAP(NK_COLOR) 18143 #undef NK_COLOR 18144 }; 18145 NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = { 18146 #define NK_COLOR(a,b,c,d,e) #a, 18147 NK_COLOR_MAP(NK_COLOR) 18148 #undef NK_COLOR 18149 }; 18150 18151 NK_API const char* 18152 nk_style_get_color_by_name(enum nk_style_colors c) 18153 { 18154 return nk_color_names[c]; 18155 } 18156 NK_API struct nk_style_item 18157 nk_style_item_color(struct nk_color col) 18158 { 18159 struct nk_style_item i; 18160 i.type = NK_STYLE_ITEM_COLOR; 18161 i.data.color = col; 18162 return i; 18163 } 18164 NK_API struct nk_style_item 18165 nk_style_item_image(struct nk_image img) 18166 { 18167 struct nk_style_item i; 18168 i.type = NK_STYLE_ITEM_IMAGE; 18169 i.data.image = img; 18170 return i; 18171 } 18172 NK_API struct nk_style_item 18173 nk_style_item_nine_slice(struct nk_nine_slice slice) 18174 { 18175 struct nk_style_item i; 18176 i.type = NK_STYLE_ITEM_NINE_SLICE; 18177 i.data.slice = slice; 18178 return i; 18179 } 18180 NK_API struct nk_style_item 18181 nk_style_item_hide(void) 18182 { 18183 struct nk_style_item i; 18184 i.type = NK_STYLE_ITEM_COLOR; 18185 i.data.color = nk_rgba(0,0,0,0); 18186 return i; 18187 } 18188 NK_API void 18189 nk_style_from_table(struct nk_context *ctx, const struct nk_color *table) 18190 { 18191 struct nk_style *style; 18192 struct nk_style_text *text; 18193 struct nk_style_button *button; 18194 struct nk_style_toggle *toggle; 18195 struct nk_style_selectable *select; 18196 struct nk_style_slider *slider; 18197 struct nk_style_progress *prog; 18198 struct nk_style_scrollbar *scroll; 18199 struct nk_style_edit *edit; 18200 struct nk_style_property *property; 18201 struct nk_style_combo *combo; 18202 struct nk_style_chart *chart; 18203 struct nk_style_tab *tab; 18204 struct nk_style_window *win; 18205 18206 NK_ASSERT(ctx); 18207 if (!ctx) return; 18208 style = &ctx->style; 18209 table = (!table) ? nk_default_color_style: table; 18210 18211 /* default text */ 18212 text = &style->text; 18213 text->color = table[NK_COLOR_TEXT]; 18214 text->padding = nk_vec2(0,0); 18215 18216 /* default button */ 18217 button = &style->button; 18218 nk_zero_struct(*button); 18219 button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]); 18220 button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); 18221 button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); 18222 button->border_color = table[NK_COLOR_BORDER]; 18223 button->text_background = table[NK_COLOR_BUTTON]; 18224 button->text_normal = table[NK_COLOR_TEXT]; 18225 button->text_hover = table[NK_COLOR_TEXT]; 18226 button->text_active = table[NK_COLOR_TEXT]; 18227 button->padding = nk_vec2(2.0f,2.0f); 18228 button->image_padding = nk_vec2(0.0f,0.0f); 18229 button->touch_padding = nk_vec2(0.0f, 0.0f); 18230 button->userdata = nk_handle_ptr(0); 18231 button->text_alignment = NK_TEXT_CENTERED; 18232 button->border = 1.0f; 18233 button->rounding = 4.0f; 18234 button->draw_begin = 0; 18235 button->draw_end = 0; 18236 18237 /* contextual button */ 18238 button = &style->contextual_button; 18239 nk_zero_struct(*button); 18240 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 18241 button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); 18242 button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); 18243 button->border_color = table[NK_COLOR_WINDOW]; 18244 button->text_background = table[NK_COLOR_WINDOW]; 18245 button->text_normal = table[NK_COLOR_TEXT]; 18246 button->text_hover = table[NK_COLOR_TEXT]; 18247 button->text_active = table[NK_COLOR_TEXT]; 18248 button->padding = nk_vec2(2.0f,2.0f); 18249 button->touch_padding = nk_vec2(0.0f,0.0f); 18250 button->userdata = nk_handle_ptr(0); 18251 button->text_alignment = NK_TEXT_CENTERED; 18252 button->border = 0.0f; 18253 button->rounding = 0.0f; 18254 button->draw_begin = 0; 18255 button->draw_end = 0; 18256 18257 /* menu button */ 18258 button = &style->menu_button; 18259 nk_zero_struct(*button); 18260 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 18261 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); 18262 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); 18263 button->border_color = table[NK_COLOR_WINDOW]; 18264 button->text_background = table[NK_COLOR_WINDOW]; 18265 button->text_normal = table[NK_COLOR_TEXT]; 18266 button->text_hover = table[NK_COLOR_TEXT]; 18267 button->text_active = table[NK_COLOR_TEXT]; 18268 button->padding = nk_vec2(2.0f,2.0f); 18269 button->touch_padding = nk_vec2(0.0f,0.0f); 18270 button->userdata = nk_handle_ptr(0); 18271 button->text_alignment = NK_TEXT_CENTERED; 18272 button->border = 0.0f; 18273 button->rounding = 1.0f; 18274 button->draw_begin = 0; 18275 button->draw_end = 0; 18276 18277 /* checkbox toggle */ 18278 toggle = &style->checkbox; 18279 nk_zero_struct(*toggle); 18280 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); 18281 toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 18282 toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 18283 toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 18284 toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 18285 toggle->userdata = nk_handle_ptr(0); 18286 toggle->text_background = table[NK_COLOR_WINDOW]; 18287 toggle->text_normal = table[NK_COLOR_TEXT]; 18288 toggle->text_hover = table[NK_COLOR_TEXT]; 18289 toggle->text_active = table[NK_COLOR_TEXT]; 18290 toggle->padding = nk_vec2(2.0f, 2.0f); 18291 toggle->touch_padding = nk_vec2(0,0); 18292 toggle->border_color = nk_rgba(0,0,0,0); 18293 toggle->border = 0.0f; 18294 toggle->spacing = 4; 18295 18296 /* option toggle */ 18297 toggle = &style->option; 18298 nk_zero_struct(*toggle); 18299 toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); 18300 toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 18301 toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); 18302 toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 18303 toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); 18304 toggle->userdata = nk_handle_ptr(0); 18305 toggle->text_background = table[NK_COLOR_WINDOW]; 18306 toggle->text_normal = table[NK_COLOR_TEXT]; 18307 toggle->text_hover = table[NK_COLOR_TEXT]; 18308 toggle->text_active = table[NK_COLOR_TEXT]; 18309 toggle->padding = nk_vec2(3.0f, 3.0f); 18310 toggle->touch_padding = nk_vec2(0,0); 18311 toggle->border_color = nk_rgba(0,0,0,0); 18312 toggle->border = 0.0f; 18313 toggle->spacing = 4; 18314 18315 /* selectable */ 18316 select = &style->selectable; 18317 nk_zero_struct(*select); 18318 select->normal = nk_style_item_color(table[NK_COLOR_SELECT]); 18319 select->hover = nk_style_item_color(table[NK_COLOR_SELECT]); 18320 select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]); 18321 select->normal_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 18322 select->hover_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 18323 select->pressed_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); 18324 select->text_normal = table[NK_COLOR_TEXT]; 18325 select->text_hover = table[NK_COLOR_TEXT]; 18326 select->text_pressed = table[NK_COLOR_TEXT]; 18327 select->text_normal_active = table[NK_COLOR_TEXT]; 18328 select->text_hover_active = table[NK_COLOR_TEXT]; 18329 select->text_pressed_active = table[NK_COLOR_TEXT]; 18330 select->padding = nk_vec2(2.0f,2.0f); 18331 select->image_padding = nk_vec2(2.0f,2.0f); 18332 select->touch_padding = nk_vec2(0,0); 18333 select->userdata = nk_handle_ptr(0); 18334 select->rounding = 0.0f; 18335 select->draw_begin = 0; 18336 select->draw_end = 0; 18337 18338 /* slider */ 18339 slider = &style->slider; 18340 nk_zero_struct(*slider); 18341 slider->normal = nk_style_item_hide(); 18342 slider->hover = nk_style_item_hide(); 18343 slider->active = nk_style_item_hide(); 18344 slider->bar_normal = table[NK_COLOR_SLIDER]; 18345 slider->bar_hover = table[NK_COLOR_SLIDER]; 18346 slider->bar_active = table[NK_COLOR_SLIDER]; 18347 slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR]; 18348 slider->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); 18349 slider->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); 18350 slider->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); 18351 slider->inc_symbol = NK_SYMBOL_TRIANGLE_RIGHT; 18352 slider->dec_symbol = NK_SYMBOL_TRIANGLE_LEFT; 18353 slider->cursor_size = nk_vec2(16,16); 18354 slider->padding = nk_vec2(2,2); 18355 slider->spacing = nk_vec2(2,2); 18356 slider->userdata = nk_handle_ptr(0); 18357 slider->show_buttons = nk_false; 18358 slider->bar_height = 8; 18359 slider->rounding = 0; 18360 slider->draw_begin = 0; 18361 slider->draw_end = 0; 18362 18363 /* slider buttons */ 18364 button = &style->slider.inc_button; 18365 button->normal = nk_style_item_color(nk_rgb(40,40,40)); 18366 button->hover = nk_style_item_color(nk_rgb(42,42,42)); 18367 button->active = nk_style_item_color(nk_rgb(44,44,44)); 18368 button->border_color = nk_rgb(65,65,65); 18369 button->text_background = nk_rgb(40,40,40); 18370 button->text_normal = nk_rgb(175,175,175); 18371 button->text_hover = nk_rgb(175,175,175); 18372 button->text_active = nk_rgb(175,175,175); 18373 button->padding = nk_vec2(8.0f,8.0f); 18374 button->touch_padding = nk_vec2(0.0f,0.0f); 18375 button->userdata = nk_handle_ptr(0); 18376 button->text_alignment = NK_TEXT_CENTERED; 18377 button->border = 1.0f; 18378 button->rounding = 0.0f; 18379 button->draw_begin = 0; 18380 button->draw_end = 0; 18381 style->slider.dec_button = style->slider.inc_button; 18382 18383 /* progressbar */ 18384 prog = &style->progress; 18385 nk_zero_struct(*prog); 18386 prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]); 18387 prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]); 18388 prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]); 18389 prog->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); 18390 prog->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); 18391 prog->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); 18392 prog->border_color = nk_rgba(0,0,0,0); 18393 prog->cursor_border_color = nk_rgba(0,0,0,0); 18394 prog->userdata = nk_handle_ptr(0); 18395 prog->padding = nk_vec2(4,4); 18396 prog->rounding = 0; 18397 prog->border = 0; 18398 prog->cursor_rounding = 0; 18399 prog->cursor_border = 0; 18400 prog->draw_begin = 0; 18401 prog->draw_end = 0; 18402 18403 /* scrollbars */ 18404 scroll = &style->scrollh; 18405 nk_zero_struct(*scroll); 18406 scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 18407 scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 18408 scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); 18409 scroll->cursor_normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]); 18410 scroll->cursor_hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]); 18411 scroll->cursor_active = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]); 18412 scroll->dec_symbol = NK_SYMBOL_CIRCLE_SOLID; 18413 scroll->inc_symbol = NK_SYMBOL_CIRCLE_SOLID; 18414 scroll->userdata = nk_handle_ptr(0); 18415 scroll->border_color = table[NK_COLOR_SCROLLBAR]; 18416 scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR]; 18417 scroll->padding = nk_vec2(0,0); 18418 scroll->show_buttons = nk_false; 18419 scroll->border = 0; 18420 scroll->rounding = 0; 18421 scroll->border_cursor = 0; 18422 scroll->rounding_cursor = 0; 18423 scroll->draw_begin = 0; 18424 scroll->draw_end = 0; 18425 style->scrollv = style->scrollh; 18426 18427 /* scrollbars buttons */ 18428 button = &style->scrollh.inc_button; 18429 button->normal = nk_style_item_color(nk_rgb(40,40,40)); 18430 button->hover = nk_style_item_color(nk_rgb(42,42,42)); 18431 button->active = nk_style_item_color(nk_rgb(44,44,44)); 18432 button->border_color = nk_rgb(65,65,65); 18433 button->text_background = nk_rgb(40,40,40); 18434 button->text_normal = nk_rgb(175,175,175); 18435 button->text_hover = nk_rgb(175,175,175); 18436 button->text_active = nk_rgb(175,175,175); 18437 button->padding = nk_vec2(4.0f,4.0f); 18438 button->touch_padding = nk_vec2(0.0f,0.0f); 18439 button->userdata = nk_handle_ptr(0); 18440 button->text_alignment = NK_TEXT_CENTERED; 18441 button->border = 1.0f; 18442 button->rounding = 0.0f; 18443 button->draw_begin = 0; 18444 button->draw_end = 0; 18445 style->scrollh.dec_button = style->scrollh.inc_button; 18446 style->scrollv.inc_button = style->scrollh.inc_button; 18447 style->scrollv.dec_button = style->scrollh.inc_button; 18448 18449 /* edit */ 18450 edit = &style->edit; 18451 nk_zero_struct(*edit); 18452 edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]); 18453 edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]); 18454 edit->active = nk_style_item_color(table[NK_COLOR_EDIT]); 18455 edit->cursor_normal = table[NK_COLOR_TEXT]; 18456 edit->cursor_hover = table[NK_COLOR_TEXT]; 18457 edit->cursor_text_normal= table[NK_COLOR_EDIT]; 18458 edit->cursor_text_hover = table[NK_COLOR_EDIT]; 18459 edit->border_color = table[NK_COLOR_BORDER]; 18460 edit->text_normal = table[NK_COLOR_TEXT]; 18461 edit->text_hover = table[NK_COLOR_TEXT]; 18462 edit->text_active = table[NK_COLOR_TEXT]; 18463 edit->selected_normal = table[NK_COLOR_TEXT]; 18464 edit->selected_hover = table[NK_COLOR_TEXT]; 18465 edit->selected_text_normal = table[NK_COLOR_EDIT]; 18466 edit->selected_text_hover = table[NK_COLOR_EDIT]; 18467 edit->scrollbar_size = nk_vec2(10,10); 18468 edit->scrollbar = style->scrollv; 18469 edit->padding = nk_vec2(4,4); 18470 edit->row_padding = 2; 18471 edit->cursor_size = 4; 18472 edit->border = 1; 18473 edit->rounding = 0; 18474 18475 /* property */ 18476 property = &style->property; 18477 nk_zero_struct(*property); 18478 property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 18479 property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 18480 property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 18481 property->border_color = table[NK_COLOR_BORDER]; 18482 property->label_normal = table[NK_COLOR_TEXT]; 18483 property->label_hover = table[NK_COLOR_TEXT]; 18484 property->label_active = table[NK_COLOR_TEXT]; 18485 property->sym_left = NK_SYMBOL_TRIANGLE_LEFT; 18486 property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT; 18487 property->userdata = nk_handle_ptr(0); 18488 property->padding = nk_vec2(4,4); 18489 property->border = 1; 18490 property->rounding = 10; 18491 property->draw_begin = 0; 18492 property->draw_end = 0; 18493 18494 /* property buttons */ 18495 button = &style->property.dec_button; 18496 nk_zero_struct(*button); 18497 button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 18498 button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 18499 button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 18500 button->border_color = nk_rgba(0,0,0,0); 18501 button->text_background = table[NK_COLOR_PROPERTY]; 18502 button->text_normal = table[NK_COLOR_TEXT]; 18503 button->text_hover = table[NK_COLOR_TEXT]; 18504 button->text_active = table[NK_COLOR_TEXT]; 18505 button->padding = nk_vec2(0.0f,0.0f); 18506 button->touch_padding = nk_vec2(0.0f,0.0f); 18507 button->userdata = nk_handle_ptr(0); 18508 button->text_alignment = NK_TEXT_CENTERED; 18509 button->border = 0.0f; 18510 button->rounding = 0.0f; 18511 button->draw_begin = 0; 18512 button->draw_end = 0; 18513 style->property.inc_button = style->property.dec_button; 18514 18515 /* property edit */ 18516 edit = &style->property.edit; 18517 nk_zero_struct(*edit); 18518 edit->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); 18519 edit->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); 18520 edit->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); 18521 edit->border_color = nk_rgba(0,0,0,0); 18522 edit->cursor_normal = table[NK_COLOR_TEXT]; 18523 edit->cursor_hover = table[NK_COLOR_TEXT]; 18524 edit->cursor_text_normal= table[NK_COLOR_EDIT]; 18525 edit->cursor_text_hover = table[NK_COLOR_EDIT]; 18526 edit->text_normal = table[NK_COLOR_TEXT]; 18527 edit->text_hover = table[NK_COLOR_TEXT]; 18528 edit->text_active = table[NK_COLOR_TEXT]; 18529 edit->selected_normal = table[NK_COLOR_TEXT]; 18530 edit->selected_hover = table[NK_COLOR_TEXT]; 18531 edit->selected_text_normal = table[NK_COLOR_EDIT]; 18532 edit->selected_text_hover = table[NK_COLOR_EDIT]; 18533 edit->padding = nk_vec2(0,0); 18534 edit->cursor_size = 8; 18535 edit->border = 0; 18536 edit->rounding = 0; 18537 18538 /* chart */ 18539 chart = &style->chart; 18540 nk_zero_struct(*chart); 18541 chart->background = nk_style_item_color(table[NK_COLOR_CHART]); 18542 chart->border_color = table[NK_COLOR_BORDER]; 18543 chart->selected_color = table[NK_COLOR_CHART_COLOR_HIGHLIGHT]; 18544 chart->color = table[NK_COLOR_CHART_COLOR]; 18545 chart->padding = nk_vec2(4,4); 18546 chart->border = 0; 18547 chart->rounding = 0; 18548 18549 /* combo */ 18550 combo = &style->combo; 18551 combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]); 18552 combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]); 18553 combo->active = nk_style_item_color(table[NK_COLOR_COMBO]); 18554 combo->border_color = table[NK_COLOR_BORDER]; 18555 combo->label_normal = table[NK_COLOR_TEXT]; 18556 combo->label_hover = table[NK_COLOR_TEXT]; 18557 combo->label_active = table[NK_COLOR_TEXT]; 18558 combo->sym_normal = NK_SYMBOL_TRIANGLE_DOWN; 18559 combo->sym_hover = NK_SYMBOL_TRIANGLE_DOWN; 18560 combo->sym_active = NK_SYMBOL_TRIANGLE_DOWN; 18561 combo->content_padding = nk_vec2(4,4); 18562 combo->button_padding = nk_vec2(0,4); 18563 combo->spacing = nk_vec2(4,0); 18564 combo->border = 1; 18565 combo->rounding = 0; 18566 18567 /* combo button */ 18568 button = &style->combo.button; 18569 nk_zero_struct(*button); 18570 button->normal = nk_style_item_color(table[NK_COLOR_COMBO]); 18571 button->hover = nk_style_item_color(table[NK_COLOR_COMBO]); 18572 button->active = nk_style_item_color(table[NK_COLOR_COMBO]); 18573 button->border_color = nk_rgba(0,0,0,0); 18574 button->text_background = table[NK_COLOR_COMBO]; 18575 button->text_normal = table[NK_COLOR_TEXT]; 18576 button->text_hover = table[NK_COLOR_TEXT]; 18577 button->text_active = table[NK_COLOR_TEXT]; 18578 button->padding = nk_vec2(2.0f,2.0f); 18579 button->touch_padding = nk_vec2(0.0f,0.0f); 18580 button->userdata = nk_handle_ptr(0); 18581 button->text_alignment = NK_TEXT_CENTERED; 18582 button->border = 0.0f; 18583 button->rounding = 0.0f; 18584 button->draw_begin = 0; 18585 button->draw_end = 0; 18586 18587 /* tab */ 18588 tab = &style->tab; 18589 tab->background = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 18590 tab->border_color = table[NK_COLOR_BORDER]; 18591 tab->text = table[NK_COLOR_TEXT]; 18592 tab->sym_minimize = NK_SYMBOL_TRIANGLE_RIGHT; 18593 tab->sym_maximize = NK_SYMBOL_TRIANGLE_DOWN; 18594 tab->padding = nk_vec2(4,4); 18595 tab->spacing = nk_vec2(4,4); 18596 tab->indent = 10.0f; 18597 tab->border = 1; 18598 tab->rounding = 0; 18599 18600 /* tab button */ 18601 button = &style->tab.tab_minimize_button; 18602 nk_zero_struct(*button); 18603 button->normal = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 18604 button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 18605 button->active = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); 18606 button->border_color = nk_rgba(0,0,0,0); 18607 button->text_background = table[NK_COLOR_TAB_HEADER]; 18608 button->text_normal = table[NK_COLOR_TEXT]; 18609 button->text_hover = table[NK_COLOR_TEXT]; 18610 button->text_active = table[NK_COLOR_TEXT]; 18611 button->padding = nk_vec2(2.0f,2.0f); 18612 button->touch_padding = nk_vec2(0.0f,0.0f); 18613 button->userdata = nk_handle_ptr(0); 18614 button->text_alignment = NK_TEXT_CENTERED; 18615 button->border = 0.0f; 18616 button->rounding = 0.0f; 18617 button->draw_begin = 0; 18618 button->draw_end = 0; 18619 style->tab.tab_maximize_button =*button; 18620 18621 /* node button */ 18622 button = &style->tab.node_minimize_button; 18623 nk_zero_struct(*button); 18624 button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); 18625 button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); 18626 button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); 18627 button->border_color = nk_rgba(0,0,0,0); 18628 button->text_background = table[NK_COLOR_TAB_HEADER]; 18629 button->text_normal = table[NK_COLOR_TEXT]; 18630 button->text_hover = table[NK_COLOR_TEXT]; 18631 button->text_active = table[NK_COLOR_TEXT]; 18632 button->padding = nk_vec2(2.0f,2.0f); 18633 button->touch_padding = nk_vec2(0.0f,0.0f); 18634 button->userdata = nk_handle_ptr(0); 18635 button->text_alignment = NK_TEXT_CENTERED; 18636 button->border = 0.0f; 18637 button->rounding = 0.0f; 18638 button->draw_begin = 0; 18639 button->draw_end = 0; 18640 style->tab.node_maximize_button =*button; 18641 18642 /* window header */ 18643 win = &style->window; 18644 win->header.align = NK_HEADER_RIGHT; 18645 win->header.close_symbol = NK_SYMBOL_X; 18646 win->header.minimize_symbol = NK_SYMBOL_MINUS; 18647 win->header.maximize_symbol = NK_SYMBOL_PLUS; 18648 win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]); 18649 win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]); 18650 win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]); 18651 win->header.label_normal = table[NK_COLOR_TEXT]; 18652 win->header.label_hover = table[NK_COLOR_TEXT]; 18653 win->header.label_active = table[NK_COLOR_TEXT]; 18654 win->header.label_padding = nk_vec2(4,4); 18655 win->header.padding = nk_vec2(4,4); 18656 win->header.spacing = nk_vec2(0,0); 18657 18658 /* window header close button */ 18659 button = &style->window.header.close_button; 18660 nk_zero_struct(*button); 18661 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); 18662 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); 18663 button->active = nk_style_item_color(table[NK_COLOR_HEADER]); 18664 button->border_color = nk_rgba(0,0,0,0); 18665 button->text_background = table[NK_COLOR_HEADER]; 18666 button->text_normal = table[NK_COLOR_TEXT]; 18667 button->text_hover = table[NK_COLOR_TEXT]; 18668 button->text_active = table[NK_COLOR_TEXT]; 18669 button->padding = nk_vec2(0.0f,0.0f); 18670 button->touch_padding = nk_vec2(0.0f,0.0f); 18671 button->userdata = nk_handle_ptr(0); 18672 button->text_alignment = NK_TEXT_CENTERED; 18673 button->border = 0.0f; 18674 button->rounding = 0.0f; 18675 button->draw_begin = 0; 18676 button->draw_end = 0; 18677 18678 /* window header minimize button */ 18679 button = &style->window.header.minimize_button; 18680 nk_zero_struct(*button); 18681 button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); 18682 button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); 18683 button->active = nk_style_item_color(table[NK_COLOR_HEADER]); 18684 button->border_color = nk_rgba(0,0,0,0); 18685 button->text_background = table[NK_COLOR_HEADER]; 18686 button->text_normal = table[NK_COLOR_TEXT]; 18687 button->text_hover = table[NK_COLOR_TEXT]; 18688 button->text_active = table[NK_COLOR_TEXT]; 18689 button->padding = nk_vec2(0.0f,0.0f); 18690 button->touch_padding = nk_vec2(0.0f,0.0f); 18691 button->userdata = nk_handle_ptr(0); 18692 button->text_alignment = NK_TEXT_CENTERED; 18693 button->border = 0.0f; 18694 button->rounding = 0.0f; 18695 button->draw_begin = 0; 18696 button->draw_end = 0; 18697 18698 /* window */ 18699 win->background = table[NK_COLOR_WINDOW]; 18700 win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]); 18701 win->border_color = table[NK_COLOR_BORDER]; 18702 win->popup_border_color = table[NK_COLOR_BORDER]; 18703 win->combo_border_color = table[NK_COLOR_BORDER]; 18704 win->contextual_border_color = table[NK_COLOR_BORDER]; 18705 win->menu_border_color = table[NK_COLOR_BORDER]; 18706 win->group_border_color = table[NK_COLOR_BORDER]; 18707 win->tooltip_border_color = table[NK_COLOR_BORDER]; 18708 win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]); 18709 18710 win->rounding = 0.0f; 18711 win->spacing = nk_vec2(4,4); 18712 win->scrollbar_size = nk_vec2(10,10); 18713 win->min_size = nk_vec2(64,64); 18714 18715 win->combo_border = 1.0f; 18716 win->contextual_border = 1.0f; 18717 win->menu_border = 1.0f; 18718 win->group_border = 1.0f; 18719 win->tooltip_border = 1.0f; 18720 win->popup_border = 1.0f; 18721 win->border = 2.0f; 18722 win->min_row_height_padding = 8; 18723 18724 win->padding = nk_vec2(4,4); 18725 win->group_padding = nk_vec2(4,4); 18726 win->popup_padding = nk_vec2(4,4); 18727 win->combo_padding = nk_vec2(4,4); 18728 win->contextual_padding = nk_vec2(4,4); 18729 win->menu_padding = nk_vec2(4,4); 18730 win->tooltip_padding = nk_vec2(4,4); 18731 } 18732 NK_API void 18733 nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font) 18734 { 18735 struct nk_style *style; 18736 NK_ASSERT(ctx); 18737 18738 if (!ctx) return; 18739 style = &ctx->style; 18740 style->font = font; 18741 ctx->stacks.fonts.head = 0; 18742 if (ctx->current) 18743 nk_layout_reset_min_row_height(ctx); 18744 } 18745 NK_API nk_bool 18746 nk_style_push_font(struct nk_context *ctx, const struct nk_user_font *font) 18747 { 18748 struct nk_config_stack_user_font *font_stack; 18749 struct nk_config_stack_user_font_element *element; 18750 18751 NK_ASSERT(ctx); 18752 if (!ctx) return 0; 18753 18754 font_stack = &ctx->stacks.fonts; 18755 NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements)); 18756 if (font_stack->head >= (int)NK_LEN(font_stack->elements)) 18757 return 0; 18758 18759 element = &font_stack->elements[font_stack->head++]; 18760 element->address = &ctx->style.font; 18761 element->old_value = ctx->style.font; 18762 ctx->style.font = font; 18763 return 1; 18764 } 18765 NK_API nk_bool 18766 nk_style_pop_font(struct nk_context *ctx) 18767 { 18768 struct nk_config_stack_user_font *font_stack; 18769 struct nk_config_stack_user_font_element *element; 18770 18771 NK_ASSERT(ctx); 18772 if (!ctx) return 0; 18773 18774 font_stack = &ctx->stacks.fonts; 18775 NK_ASSERT(font_stack->head > 0); 18776 if (font_stack->head < 1) 18777 return 0; 18778 18779 element = &font_stack->elements[--font_stack->head]; 18780 *element->address = element->old_value; 18781 return 1; 18782 } 18783 #define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \ 18784 nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\ 18785 {\ 18786 struct nk_config_stack_##type * type_stack;\ 18787 struct nk_config_stack_##type##_element *element;\ 18788 NK_ASSERT(ctx);\ 18789 if (!ctx) return 0;\ 18790 type_stack = &ctx->stacks.stack;\ 18791 NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\ 18792 if (type_stack->head >= (int)NK_LEN(type_stack->elements))\ 18793 return 0;\ 18794 element = &type_stack->elements[type_stack->head++];\ 18795 element->address = address;\ 18796 element->old_value = *address;\ 18797 *address = value;\ 18798 return 1;\ 18799 } 18800 #define NK_STYLE_POP_IMPLEMENATION(type, stack) \ 18801 nk_style_pop_##type(struct nk_context *ctx)\ 18802 {\ 18803 struct nk_config_stack_##type *type_stack;\ 18804 struct nk_config_stack_##type##_element *element;\ 18805 NK_ASSERT(ctx);\ 18806 if (!ctx) return 0;\ 18807 type_stack = &ctx->stacks.stack;\ 18808 NK_ASSERT(type_stack->head > 0);\ 18809 if (type_stack->head < 1)\ 18810 return 0;\ 18811 element = &type_stack->elements[--type_stack->head];\ 18812 *element->address = element->old_value;\ 18813 return 1;\ 18814 } 18815 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items) 18816 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats) 18817 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors) 18818 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags) 18819 NK_API nk_bool NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors) 18820 18821 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(style_item, style_items) 18822 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(float,floats) 18823 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(vec2, vectors) 18824 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(flags,flags) 18825 NK_API nk_bool NK_STYLE_POP_IMPLEMENATION(color,colors) 18826 18827 NK_API nk_bool 18828 nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c) 18829 { 18830 struct nk_style *style; 18831 NK_ASSERT(ctx); 18832 if (!ctx) return 0; 18833 style = &ctx->style; 18834 if (style->cursors[c]) { 18835 style->cursor_active = style->cursors[c]; 18836 return 1; 18837 } 18838 return 0; 18839 } 18840 NK_API void 18841 nk_style_show_cursor(struct nk_context *ctx) 18842 { 18843 ctx->style.cursor_visible = nk_true; 18844 } 18845 NK_API void 18846 nk_style_hide_cursor(struct nk_context *ctx) 18847 { 18848 ctx->style.cursor_visible = nk_false; 18849 } 18850 NK_API void 18851 nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor, 18852 const struct nk_cursor *c) 18853 { 18854 struct nk_style *style; 18855 NK_ASSERT(ctx); 18856 if (!ctx) return; 18857 style = &ctx->style; 18858 style->cursors[cursor] = c; 18859 } 18860 NK_API void 18861 nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors) 18862 { 18863 int i = 0; 18864 struct nk_style *style; 18865 NK_ASSERT(ctx); 18866 if (!ctx) return; 18867 style = &ctx->style; 18868 for (i = 0; i < NK_CURSOR_COUNT; ++i) 18869 style->cursors[i] = &cursors[i]; 18870 style->cursor_visible = nk_true; 18871 } 18872 18873 18874 18875 18876 18877 /* ============================================================== 18878 * 18879 * CONTEXT 18880 * 18881 * ===============================================================*/ 18882 NK_INTERN void 18883 nk_setup(struct nk_context *ctx, const struct nk_user_font *font) 18884 { 18885 NK_ASSERT(ctx); 18886 if (!ctx) return; 18887 nk_zero_struct(*ctx); 18888 nk_style_default(ctx); 18889 ctx->seq = 1; 18890 if (font) ctx->style.font = font; 18891 #ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT 18892 nk_draw_list_init(&ctx->draw_list); 18893 #endif 18894 } 18895 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 18896 NK_API nk_bool 18897 nk_init_default(struct nk_context *ctx, const struct nk_user_font *font) 18898 { 18899 struct nk_allocator alloc; 18900 alloc.userdata.ptr = 0; 18901 alloc.alloc = nk_malloc; 18902 alloc.free = nk_mfree; 18903 return nk_init(ctx, &alloc, font); 18904 } 18905 #endif 18906 NK_API nk_bool 18907 nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, 18908 const struct nk_user_font *font) 18909 { 18910 NK_ASSERT(memory); 18911 if (!memory) return 0; 18912 nk_setup(ctx, font); 18913 nk_buffer_init_fixed(&ctx->memory, memory, size); 18914 ctx->use_pool = nk_false; 18915 return 1; 18916 } 18917 NK_API nk_bool 18918 nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, 18919 struct nk_buffer *pool, const struct nk_user_font *font) 18920 { 18921 NK_ASSERT(cmds); 18922 NK_ASSERT(pool); 18923 if (!cmds || !pool) return 0; 18924 18925 nk_setup(ctx, font); 18926 ctx->memory = *cmds; 18927 if (pool->type == NK_BUFFER_FIXED) { 18928 /* take memory from buffer and alloc fixed pool */ 18929 nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size); 18930 } else { 18931 /* create dynamic pool from buffer allocator */ 18932 struct nk_allocator *alloc = &pool->pool; 18933 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); 18934 } 18935 ctx->use_pool = nk_true; 18936 return 1; 18937 } 18938 NK_API nk_bool 18939 nk_init(struct nk_context *ctx, struct nk_allocator *alloc, 18940 const struct nk_user_font *font) 18941 { 18942 NK_ASSERT(alloc); 18943 if (!alloc) return 0; 18944 nk_setup(ctx, font); 18945 nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE); 18946 nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); 18947 ctx->use_pool = nk_true; 18948 return 1; 18949 } 18950 #ifdef NK_INCLUDE_COMMAND_USERDATA 18951 NK_API void 18952 nk_set_user_data(struct nk_context *ctx, nk_handle handle) 18953 { 18954 if (!ctx) return; 18955 ctx->userdata = handle; 18956 if (ctx->current) 18957 ctx->current->buffer.userdata = handle; 18958 } 18959 #endif 18960 NK_API void 18961 nk_free(struct nk_context *ctx) 18962 { 18963 NK_ASSERT(ctx); 18964 if (!ctx) return; 18965 nk_buffer_free(&ctx->memory); 18966 if (ctx->use_pool) 18967 nk_pool_free(&ctx->pool); 18968 18969 nk_zero(&ctx->input, sizeof(ctx->input)); 18970 nk_zero(&ctx->style, sizeof(ctx->style)); 18971 nk_zero(&ctx->memory, sizeof(ctx->memory)); 18972 18973 ctx->seq = 0; 18974 ctx->build = 0; 18975 ctx->begin = 0; 18976 ctx->end = 0; 18977 ctx->active = 0; 18978 ctx->current = 0; 18979 ctx->freelist = 0; 18980 ctx->count = 0; 18981 } 18982 NK_API void 18983 nk_clear(struct nk_context *ctx) 18984 { 18985 struct nk_window *iter; 18986 struct nk_window *next; 18987 NK_ASSERT(ctx); 18988 18989 if (!ctx) return; 18990 if (ctx->use_pool) 18991 nk_buffer_clear(&ctx->memory); 18992 else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); 18993 18994 ctx->build = 0; 18995 ctx->memory.calls = 0; 18996 ctx->last_widget_state = 0; 18997 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; 18998 NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); 18999 19000 /* garbage collector */ 19001 iter = ctx->begin; 19002 while (iter) { 19003 /* make sure valid minimized windows do not get removed */ 19004 if ((iter->flags & NK_WINDOW_MINIMIZED) && 19005 !(iter->flags & NK_WINDOW_CLOSED) && 19006 iter->seq == ctx->seq) { 19007 iter = iter->next; 19008 continue; 19009 } 19010 /* remove hotness from hidden or closed windows*/ 19011 if (((iter->flags & NK_WINDOW_HIDDEN) || 19012 (iter->flags & NK_WINDOW_CLOSED)) && 19013 iter == ctx->active) { 19014 ctx->active = iter->prev; 19015 ctx->end = iter->prev; 19016 if (!ctx->end) 19017 ctx->begin = 0; 19018 if (ctx->active) 19019 ctx->active->flags &= ~(unsigned)NK_WINDOW_ROM; 19020 } 19021 /* free unused popup windows */ 19022 if (iter->popup.win && iter->popup.win->seq != ctx->seq) { 19023 nk_free_window(ctx, iter->popup.win); 19024 iter->popup.win = 0; 19025 } 19026 /* remove unused window state tables */ 19027 {struct nk_table *n, *it = iter->tables; 19028 while (it) { 19029 n = it->next; 19030 if (it->seq != ctx->seq) { 19031 nk_remove_table(iter, it); 19032 nk_zero(it, sizeof(union nk_page_data)); 19033 nk_free_table(ctx, it); 19034 if (it == iter->tables) 19035 iter->tables = n; 19036 } it = n; 19037 }} 19038 /* window itself is not used anymore so free */ 19039 if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) { 19040 next = iter->next; 19041 nk_remove_window(ctx, iter); 19042 nk_free_window(ctx, iter); 19043 iter = next; 19044 } else iter = iter->next; 19045 } 19046 ctx->seq++; 19047 } 19048 NK_LIB void 19049 nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) 19050 { 19051 NK_ASSERT(ctx); 19052 NK_ASSERT(buffer); 19053 if (!ctx || !buffer) return; 19054 buffer->begin = ctx->memory.allocated; 19055 buffer->end = buffer->begin; 19056 buffer->last = buffer->begin; 19057 buffer->clip = nk_null_rect; 19058 } 19059 NK_LIB void 19060 nk_start(struct nk_context *ctx, struct nk_window *win) 19061 { 19062 NK_ASSERT(ctx); 19063 NK_ASSERT(win); 19064 nk_start_buffer(ctx, &win->buffer); 19065 } 19066 NK_LIB void 19067 nk_start_popup(struct nk_context *ctx, struct nk_window *win) 19068 { 19069 struct nk_popup_buffer *buf; 19070 NK_ASSERT(ctx); 19071 NK_ASSERT(win); 19072 if (!ctx || !win) return; 19073 19074 /* save buffer fill state for popup */ 19075 buf = &win->popup.buf; 19076 buf->begin = win->buffer.end; 19077 buf->end = win->buffer.end; 19078 buf->parent = win->buffer.last; 19079 buf->last = buf->begin; 19080 buf->active = nk_true; 19081 } 19082 NK_LIB void 19083 nk_finish_popup(struct nk_context *ctx, struct nk_window *win) 19084 { 19085 struct nk_popup_buffer *buf; 19086 NK_ASSERT(ctx); 19087 NK_ASSERT(win); 19088 if (!ctx || !win) return; 19089 19090 buf = &win->popup.buf; 19091 buf->last = win->buffer.last; 19092 buf->end = win->buffer.end; 19093 } 19094 NK_LIB void 19095 nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) 19096 { 19097 NK_ASSERT(ctx); 19098 NK_ASSERT(buffer); 19099 if (!ctx || !buffer) return; 19100 buffer->end = ctx->memory.allocated; 19101 } 19102 NK_LIB void 19103 nk_finish(struct nk_context *ctx, struct nk_window *win) 19104 { 19105 struct nk_popup_buffer *buf; 19106 struct nk_command *parent_last; 19107 void *memory; 19108 19109 NK_ASSERT(ctx); 19110 NK_ASSERT(win); 19111 if (!ctx || !win) return; 19112 nk_finish_buffer(ctx, &win->buffer); 19113 if (!win->popup.buf.active) return; 19114 19115 buf = &win->popup.buf; 19116 memory = ctx->memory.memory.ptr; 19117 parent_last = nk_ptr_add(struct nk_command, memory, buf->parent); 19118 parent_last->next = buf->end; 19119 } 19120 NK_LIB void 19121 nk_build(struct nk_context *ctx) 19122 { 19123 struct nk_window *it = 0; 19124 struct nk_command *cmd = 0; 19125 nk_byte *buffer = 0; 19126 19127 /* draw cursor overlay */ 19128 if (!ctx->style.cursor_active) 19129 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; 19130 if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) { 19131 struct nk_rect mouse_bounds; 19132 const struct nk_cursor *cursor = ctx->style.cursor_active; 19133 nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF); 19134 nk_start_buffer(ctx, &ctx->overlay); 19135 19136 mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x; 19137 mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y; 19138 mouse_bounds.w = cursor->size.x; 19139 mouse_bounds.h = cursor->size.y; 19140 19141 nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white); 19142 nk_finish_buffer(ctx, &ctx->overlay); 19143 } 19144 /* build one big draw command list out of all window buffers */ 19145 it = ctx->begin; 19146 buffer = (nk_byte*)ctx->memory.memory.ptr; 19147 while (it != 0) { 19148 struct nk_window *next = it->next; 19149 if (it->buffer.last == it->buffer.begin || (it->flags & NK_WINDOW_HIDDEN)|| 19150 it->seq != ctx->seq) 19151 goto cont; 19152 19153 cmd = nk_ptr_add(struct nk_command, buffer, it->buffer.last); 19154 while (next && ((next->buffer.last == next->buffer.begin) || 19155 (next->flags & NK_WINDOW_HIDDEN) || next->seq != ctx->seq)) 19156 next = next->next; /* skip empty command buffers */ 19157 19158 if (next) cmd->next = next->buffer.begin; 19159 cont: it = next; 19160 } 19161 /* append all popup draw commands into lists */ 19162 it = ctx->begin; 19163 while (it != 0) { 19164 struct nk_window *next = it->next; 19165 struct nk_popup_buffer *buf; 19166 if (!it->popup.buf.active) 19167 goto skip; 19168 19169 buf = &it->popup.buf; 19170 cmd->next = buf->begin; 19171 cmd = nk_ptr_add(struct nk_command, buffer, buf->last); 19172 buf->active = nk_false; 19173 skip: it = next; 19174 } 19175 if (cmd) { 19176 /* append overlay commands */ 19177 if (ctx->overlay.end != ctx->overlay.begin) 19178 cmd->next = ctx->overlay.begin; 19179 else cmd->next = ctx->memory.allocated; 19180 } 19181 } 19182 NK_API const struct nk_command* 19183 nk__begin(struct nk_context *ctx) 19184 { 19185 struct nk_window *iter; 19186 nk_byte *buffer; 19187 NK_ASSERT(ctx); 19188 if (!ctx) return 0; 19189 if (!ctx->count) return 0; 19190 19191 buffer = (nk_byte*)ctx->memory.memory.ptr; 19192 if (!ctx->build) { 19193 nk_build(ctx); 19194 ctx->build = nk_true; 19195 } 19196 iter = ctx->begin; 19197 while (iter && ((iter->buffer.begin == iter->buffer.end) || 19198 (iter->flags & NK_WINDOW_HIDDEN) || iter->seq != ctx->seq)) 19199 iter = iter->next; 19200 if (!iter) return 0; 19201 return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin); 19202 } 19203 19204 NK_API const struct nk_command* 19205 nk__next(struct nk_context *ctx, const struct nk_command *cmd) 19206 { 19207 nk_byte *buffer; 19208 const struct nk_command *next; 19209 NK_ASSERT(ctx); 19210 if (!ctx || !cmd || !ctx->count) return 0; 19211 if (cmd->next >= ctx->memory.allocated) return 0; 19212 buffer = (nk_byte*)ctx->memory.memory.ptr; 19213 next = nk_ptr_add_const(struct nk_command, buffer, cmd->next); 19214 return next; 19215 } 19216 19217 19218 19219 19220 19221 19222 /* =============================================================== 19223 * 19224 * POOL 19225 * 19226 * ===============================================================*/ 19227 NK_LIB void 19228 nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, 19229 unsigned int capacity) 19230 { 19231 NK_ASSERT(capacity >= 1); 19232 nk_zero(pool, sizeof(*pool)); 19233 pool->alloc = *alloc; 19234 pool->capacity = capacity; 19235 pool->type = NK_BUFFER_DYNAMIC; 19236 pool->pages = 0; 19237 } 19238 NK_LIB void 19239 nk_pool_free(struct nk_pool *pool) 19240 { 19241 struct nk_page *iter; 19242 if (!pool) return; 19243 iter = pool->pages; 19244 if (pool->type == NK_BUFFER_FIXED) return; 19245 while (iter) { 19246 struct nk_page *next = iter->next; 19247 pool->alloc.free(pool->alloc.userdata, iter); 19248 iter = next; 19249 } 19250 } 19251 NK_LIB void 19252 nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size) 19253 { 19254 nk_zero(pool, sizeof(*pool)); 19255 NK_ASSERT(size >= sizeof(struct nk_page)); 19256 if (size < sizeof(struct nk_page)) return; 19257 /* first nk_page_element is embedded in nk_page, additional elements follow in adjacent space */ 19258 pool->capacity = (unsigned)(1 + (size - sizeof(struct nk_page)) / sizeof(struct nk_page_element)); 19259 pool->pages = (struct nk_page*)memory; 19260 pool->type = NK_BUFFER_FIXED; 19261 pool->size = size; 19262 } 19263 NK_LIB struct nk_page_element* 19264 nk_pool_alloc(struct nk_pool *pool) 19265 { 19266 if (!pool->pages || pool->pages->size >= pool->capacity) { 19267 /* allocate new page */ 19268 struct nk_page *page; 19269 if (pool->type == NK_BUFFER_FIXED) { 19270 NK_ASSERT(pool->pages); 19271 if (!pool->pages) return 0; 19272 NK_ASSERT(pool->pages->size < pool->capacity); 19273 return 0; 19274 } else { 19275 nk_size size = sizeof(struct nk_page); 19276 size += (pool->capacity - 1) * sizeof(struct nk_page_element); 19277 page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size); 19278 page->next = pool->pages; 19279 pool->pages = page; 19280 page->size = 0; 19281 } 19282 } return &pool->pages->win[pool->pages->size++]; 19283 } 19284 19285 19286 19287 19288 19289 /* =============================================================== 19290 * 19291 * PAGE ELEMENT 19292 * 19293 * ===============================================================*/ 19294 NK_LIB struct nk_page_element* 19295 nk_create_page_element(struct nk_context *ctx) 19296 { 19297 struct nk_page_element *elem; 19298 if (ctx->freelist) { 19299 /* unlink page element from free list */ 19300 elem = ctx->freelist; 19301 ctx->freelist = elem->next; 19302 } else if (ctx->use_pool) { 19303 /* allocate page element from memory pool */ 19304 elem = nk_pool_alloc(&ctx->pool); 19305 NK_ASSERT(elem); 19306 if (!elem) return 0; 19307 } else { 19308 /* allocate new page element from back of fixed size memory buffer */ 19309 NK_STORAGE const nk_size size = sizeof(struct nk_page_element); 19310 NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element); 19311 elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align); 19312 NK_ASSERT(elem); 19313 if (!elem) return 0; 19314 } 19315 nk_zero_struct(*elem); 19316 elem->next = 0; 19317 elem->prev = 0; 19318 return elem; 19319 } 19320 NK_LIB void 19321 nk_link_page_element_into_freelist(struct nk_context *ctx, 19322 struct nk_page_element *elem) 19323 { 19324 /* link table into freelist */ 19325 if (!ctx->freelist) { 19326 ctx->freelist = elem; 19327 } else { 19328 elem->next = ctx->freelist; 19329 ctx->freelist = elem; 19330 } 19331 } 19332 NK_LIB void 19333 nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem) 19334 { 19335 /* we have a pool so just add to free list */ 19336 if (ctx->use_pool) { 19337 nk_link_page_element_into_freelist(ctx, elem); 19338 return; 19339 } 19340 /* if possible remove last element from back of fixed memory buffer */ 19341 {void *elem_end = (void*)(elem + 1); 19342 void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size; 19343 if (elem_end == buffer_end) 19344 ctx->memory.size -= sizeof(struct nk_page_element); 19345 else nk_link_page_element_into_freelist(ctx, elem);} 19346 } 19347 19348 19349 19350 19351 19352 /* =============================================================== 19353 * 19354 * TABLE 19355 * 19356 * ===============================================================*/ 19357 NK_LIB struct nk_table* 19358 nk_create_table(struct nk_context *ctx) 19359 { 19360 struct nk_page_element *elem; 19361 elem = nk_create_page_element(ctx); 19362 if (!elem) return 0; 19363 nk_zero_struct(*elem); 19364 return &elem->data.tbl; 19365 } 19366 NK_LIB void 19367 nk_free_table(struct nk_context *ctx, struct nk_table *tbl) 19368 { 19369 union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl); 19370 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 19371 nk_free_page_element(ctx, pe); 19372 } 19373 NK_LIB void 19374 nk_push_table(struct nk_window *win, struct nk_table *tbl) 19375 { 19376 if (!win->tables) { 19377 win->tables = tbl; 19378 tbl->next = 0; 19379 tbl->prev = 0; 19380 tbl->size = 0; 19381 win->table_count = 1; 19382 return; 19383 } 19384 win->tables->prev = tbl; 19385 tbl->next = win->tables; 19386 tbl->prev = 0; 19387 tbl->size = 0; 19388 win->tables = tbl; 19389 win->table_count++; 19390 } 19391 NK_LIB void 19392 nk_remove_table(struct nk_window *win, struct nk_table *tbl) 19393 { 19394 if (win->tables == tbl) 19395 win->tables = tbl->next; 19396 if (tbl->next) 19397 tbl->next->prev = tbl->prev; 19398 if (tbl->prev) 19399 tbl->prev->next = tbl->next; 19400 tbl->next = 0; 19401 tbl->prev = 0; 19402 } 19403 NK_LIB nk_uint* 19404 nk_add_value(struct nk_context *ctx, struct nk_window *win, 19405 nk_hash name, nk_uint value) 19406 { 19407 NK_ASSERT(ctx); 19408 NK_ASSERT(win); 19409 if (!win || !ctx) return 0; 19410 if (!win->tables || win->tables->size >= NK_VALUE_PAGE_CAPACITY) { 19411 struct nk_table *tbl = nk_create_table(ctx); 19412 NK_ASSERT(tbl); 19413 if (!tbl) return 0; 19414 nk_push_table(win, tbl); 19415 } 19416 win->tables->seq = win->seq; 19417 win->tables->keys[win->tables->size] = name; 19418 win->tables->values[win->tables->size] = value; 19419 return &win->tables->values[win->tables->size++]; 19420 } 19421 NK_LIB nk_uint* 19422 nk_find_value(struct nk_window *win, nk_hash name) 19423 { 19424 struct nk_table *iter = win->tables; 19425 while (iter) { 19426 unsigned int i = 0; 19427 unsigned int size = iter->size; 19428 for (i = 0; i < size; ++i) { 19429 if (iter->keys[i] == name) { 19430 iter->seq = win->seq; 19431 return &iter->values[i]; 19432 } 19433 } size = NK_VALUE_PAGE_CAPACITY; 19434 iter = iter->next; 19435 } 19436 return 0; 19437 } 19438 19439 19440 19441 19442 19443 /* =============================================================== 19444 * 19445 * PANEL 19446 * 19447 * ===============================================================*/ 19448 NK_LIB void* 19449 nk_create_panel(struct nk_context *ctx) 19450 { 19451 struct nk_page_element *elem; 19452 elem = nk_create_page_element(ctx); 19453 if (!elem) return 0; 19454 nk_zero_struct(*elem); 19455 return &elem->data.pan; 19456 } 19457 NK_LIB void 19458 nk_free_panel(struct nk_context *ctx, struct nk_panel *pan) 19459 { 19460 union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan); 19461 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 19462 nk_free_page_element(ctx, pe); 19463 } 19464 NK_LIB nk_bool 19465 nk_panel_has_header(nk_flags flags, const char *title) 19466 { 19467 nk_bool active = 0; 19468 active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE)); 19469 active = active || (flags & NK_WINDOW_TITLE); 19470 active = active && !(flags & NK_WINDOW_HIDDEN) && title; 19471 return active; 19472 } 19473 NK_LIB struct nk_vec2 19474 nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type) 19475 { 19476 switch (type) { 19477 default: 19478 case NK_PANEL_WINDOW: return style->window.padding; 19479 case NK_PANEL_GROUP: return style->window.group_padding; 19480 case NK_PANEL_POPUP: return style->window.popup_padding; 19481 case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding; 19482 case NK_PANEL_COMBO: return style->window.combo_padding; 19483 case NK_PANEL_MENU: return style->window.menu_padding; 19484 case NK_PANEL_TOOLTIP: return style->window.menu_padding;} 19485 } 19486 NK_LIB float 19487 nk_panel_get_border(const struct nk_style *style, nk_flags flags, 19488 enum nk_panel_type type) 19489 { 19490 if (flags & NK_WINDOW_BORDER) { 19491 switch (type) { 19492 default: 19493 case NK_PANEL_WINDOW: return style->window.border; 19494 case NK_PANEL_GROUP: return style->window.group_border; 19495 case NK_PANEL_POPUP: return style->window.popup_border; 19496 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border; 19497 case NK_PANEL_COMBO: return style->window.combo_border; 19498 case NK_PANEL_MENU: return style->window.menu_border; 19499 case NK_PANEL_TOOLTIP: return style->window.menu_border; 19500 }} else return 0; 19501 } 19502 NK_LIB struct nk_color 19503 nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type) 19504 { 19505 switch (type) { 19506 default: 19507 case NK_PANEL_WINDOW: return style->window.border_color; 19508 case NK_PANEL_GROUP: return style->window.group_border_color; 19509 case NK_PANEL_POPUP: return style->window.popup_border_color; 19510 case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color; 19511 case NK_PANEL_COMBO: return style->window.combo_border_color; 19512 case NK_PANEL_MENU: return style->window.menu_border_color; 19513 case NK_PANEL_TOOLTIP: return style->window.menu_border_color;} 19514 } 19515 NK_LIB nk_bool 19516 nk_panel_is_sub(enum nk_panel_type type) 19517 { 19518 return (type & NK_PANEL_SET_SUB)?1:0; 19519 } 19520 NK_LIB nk_bool 19521 nk_panel_is_nonblock(enum nk_panel_type type) 19522 { 19523 return (type & NK_PANEL_SET_NONBLOCK)?1:0; 19524 } 19525 NK_LIB nk_bool 19526 nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type) 19527 { 19528 struct nk_input *in; 19529 struct nk_window *win; 19530 struct nk_panel *layout; 19531 struct nk_command_buffer *out; 19532 const struct nk_style *style; 19533 const struct nk_user_font *font; 19534 19535 struct nk_vec2 scrollbar_size; 19536 struct nk_vec2 panel_padding; 19537 19538 NK_ASSERT(ctx); 19539 NK_ASSERT(ctx->current); 19540 NK_ASSERT(ctx->current->layout); 19541 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 19542 nk_zero(ctx->current->layout, sizeof(*ctx->current->layout)); 19543 if ((ctx->current->flags & NK_WINDOW_HIDDEN) || (ctx->current->flags & NK_WINDOW_CLOSED)) { 19544 nk_zero(ctx->current->layout, sizeof(struct nk_panel)); 19545 ctx->current->layout->type = panel_type; 19546 return 0; 19547 } 19548 /* pull state into local stack */ 19549 style = &ctx->style; 19550 font = style->font; 19551 win = ctx->current; 19552 layout = win->layout; 19553 out = &win->buffer; 19554 in = (win->flags & NK_WINDOW_NO_INPUT) ? 0: &ctx->input; 19555 #ifdef NK_INCLUDE_COMMAND_USERDATA 19556 win->buffer.userdata = ctx->userdata; 19557 #endif 19558 /* pull style configuration into local stack */ 19559 scrollbar_size = style->window.scrollbar_size; 19560 panel_padding = nk_panel_get_padding(style, panel_type); 19561 19562 /* window movement */ 19563 if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) { 19564 nk_bool left_mouse_down; 19565 unsigned int left_mouse_clicked; 19566 int left_mouse_click_in_cursor; 19567 19568 /* calculate draggable window space */ 19569 struct nk_rect header; 19570 header.x = win->bounds.x; 19571 header.y = win->bounds.y; 19572 header.w = win->bounds.w; 19573 if (nk_panel_has_header(win->flags, title)) { 19574 header.h = font->height + 2.0f * style->window.header.padding.y; 19575 header.h += 2.0f * style->window.header.label_padding.y; 19576 } else header.h = panel_padding.y; 19577 19578 /* window movement by dragging */ 19579 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 19580 left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked; 19581 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, 19582 NK_BUTTON_LEFT, header, nk_true); 19583 if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) { 19584 win->bounds.x = win->bounds.x + in->mouse.delta.x; 19585 win->bounds.y = win->bounds.y + in->mouse.delta.y; 19586 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x; 19587 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y; 19588 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE]; 19589 } 19590 } 19591 19592 /* setup panel */ 19593 layout->type = panel_type; 19594 layout->flags = win->flags; 19595 layout->bounds = win->bounds; 19596 layout->bounds.x += panel_padding.x; 19597 layout->bounds.w -= 2*panel_padding.x; 19598 if (win->flags & NK_WINDOW_BORDER) { 19599 layout->border = nk_panel_get_border(style, win->flags, panel_type); 19600 layout->bounds = nk_shrink_rect(layout->bounds, layout->border); 19601 } else layout->border = 0; 19602 layout->at_y = layout->bounds.y; 19603 layout->at_x = layout->bounds.x; 19604 layout->max_x = 0; 19605 layout->header_height = 0; 19606 layout->footer_height = 0; 19607 nk_layout_reset_min_row_height(ctx); 19608 layout->row.index = 0; 19609 layout->row.columns = 0; 19610 layout->row.ratio = 0; 19611 layout->row.item_width = 0; 19612 layout->row.tree_depth = 0; 19613 layout->row.height = panel_padding.y; 19614 layout->has_scrolling = nk_true; 19615 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR)) 19616 layout->bounds.w -= scrollbar_size.x; 19617 if (!nk_panel_is_nonblock(panel_type)) { 19618 layout->footer_height = 0; 19619 if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE) 19620 layout->footer_height = scrollbar_size.y; 19621 layout->bounds.h -= layout->footer_height; 19622 } 19623 19624 /* panel header */ 19625 if (nk_panel_has_header(win->flags, title)) 19626 { 19627 struct nk_text text; 19628 struct nk_rect header; 19629 const struct nk_style_item *background = 0; 19630 19631 /* calculate header bounds */ 19632 header.x = win->bounds.x; 19633 header.y = win->bounds.y; 19634 header.w = win->bounds.w; 19635 header.h = font->height + 2.0f * style->window.header.padding.y; 19636 header.h += (2.0f * style->window.header.label_padding.y); 19637 19638 /* shrink panel by header */ 19639 layout->header_height = header.h; 19640 layout->bounds.y += header.h; 19641 layout->bounds.h -= header.h; 19642 layout->at_y += header.h; 19643 19644 /* select correct header background and text color */ 19645 if (ctx->active == win) { 19646 background = &style->window.header.active; 19647 text.text = style->window.header.label_active; 19648 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) { 19649 background = &style->window.header.hover; 19650 text.text = style->window.header.label_hover; 19651 } else { 19652 background = &style->window.header.normal; 19653 text.text = style->window.header.label_normal; 19654 } 19655 19656 /* draw header background */ 19657 header.h += 1.0f; 19658 19659 switch(background->type) { 19660 case NK_STYLE_ITEM_IMAGE: 19661 text.background = nk_rgba(0,0,0,0); 19662 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 19663 break; 19664 case NK_STYLE_ITEM_NINE_SLICE: 19665 text.background = nk_rgba(0, 0, 0, 0); 19666 nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white); 19667 break; 19668 case NK_STYLE_ITEM_COLOR: 19669 text.background = background->data.color; 19670 nk_fill_rect(out, header, 0, background->data.color); 19671 break; 19672 } 19673 19674 /* window close button */ 19675 {struct nk_rect button; 19676 button.y = header.y + style->window.header.padding.y; 19677 button.h = header.h - 2 * style->window.header.padding.y; 19678 button.w = button.h; 19679 if (win->flags & NK_WINDOW_CLOSABLE) { 19680 nk_flags ws = 0; 19681 if (style->window.header.align == NK_HEADER_RIGHT) { 19682 button.x = (header.w + header.x) - (button.w + style->window.header.padding.x); 19683 header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x; 19684 } else { 19685 button.x = header.x + style->window.header.padding.x; 19686 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; 19687 } 19688 19689 if (nk_do_button_symbol(&ws, &win->buffer, button, 19690 style->window.header.close_symbol, NK_BUTTON_DEFAULT, 19691 &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) 19692 { 19693 layout->flags |= NK_WINDOW_HIDDEN; 19694 layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED; 19695 } 19696 } 19697 19698 /* window minimize button */ 19699 if (win->flags & NK_WINDOW_MINIMIZABLE) { 19700 nk_flags ws = 0; 19701 if (style->window.header.align == NK_HEADER_RIGHT) { 19702 button.x = (header.w + header.x) - button.w; 19703 if (!(win->flags & NK_WINDOW_CLOSABLE)) { 19704 button.x -= style->window.header.padding.x; 19705 header.w -= style->window.header.padding.x; 19706 } 19707 header.w -= button.w + style->window.header.spacing.x; 19708 } else { 19709 button.x = header.x; 19710 header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; 19711 } 19712 if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)? 19713 style->window.header.maximize_symbol: style->window.header.minimize_symbol, 19714 NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) 19715 layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ? 19716 layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED: 19717 layout->flags | NK_WINDOW_MINIMIZED; 19718 }} 19719 19720 {/* window header title */ 19721 int text_len = nk_strlen(title); 19722 struct nk_rect label = {0,0,0,0}; 19723 float t = font->width(font->userdata, font->height, title, text_len); 19724 text.padding = nk_vec2(0,0); 19725 19726 label.x = header.x + style->window.header.padding.x; 19727 label.x += style->window.header.label_padding.x; 19728 label.y = header.y + style->window.header.label_padding.y; 19729 label.h = font->height + 2 * style->window.header.label_padding.y; 19730 label.w = t + 2 * style->window.header.spacing.x; 19731 label.w = NK_CLAMP(0, label.w, header.x + header.w - label.x); 19732 nk_widget_text(out, label, (const char*)title, text_len, &text, NK_TEXT_LEFT, font);} 19733 } 19734 19735 /* draw window background */ 19736 if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) { 19737 struct nk_rect body; 19738 body.x = win->bounds.x; 19739 body.w = win->bounds.w; 19740 body.y = (win->bounds.y + layout->header_height); 19741 body.h = (win->bounds.h - layout->header_height); 19742 19743 switch(style->window.fixed_background.type) { 19744 case NK_STYLE_ITEM_IMAGE: 19745 nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white); 19746 break; 19747 case NK_STYLE_ITEM_NINE_SLICE: 19748 nk_draw_nine_slice(out, body, &style->window.fixed_background.data.slice, nk_white); 19749 break; 19750 case NK_STYLE_ITEM_COLOR: 19751 nk_fill_rect(out, body, 0, style->window.fixed_background.data.color); 19752 break; 19753 } 19754 } 19755 19756 /* set clipping rectangle */ 19757 {struct nk_rect clip; 19758 layout->clip = layout->bounds; 19759 nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y, 19760 layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h); 19761 nk_push_scissor(out, clip); 19762 layout->clip = clip;} 19763 return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED); 19764 } 19765 NK_LIB void 19766 nk_panel_end(struct nk_context *ctx) 19767 { 19768 struct nk_input *in; 19769 struct nk_window *window; 19770 struct nk_panel *layout; 19771 const struct nk_style *style; 19772 struct nk_command_buffer *out; 19773 19774 struct nk_vec2 scrollbar_size; 19775 struct nk_vec2 panel_padding; 19776 19777 NK_ASSERT(ctx); 19778 NK_ASSERT(ctx->current); 19779 NK_ASSERT(ctx->current->layout); 19780 if (!ctx || !ctx->current || !ctx->current->layout) 19781 return; 19782 19783 window = ctx->current; 19784 layout = window->layout; 19785 style = &ctx->style; 19786 out = &window->buffer; 19787 in = (layout->flags & NK_WINDOW_ROM || layout->flags & NK_WINDOW_NO_INPUT) ? 0 :&ctx->input; 19788 if (!nk_panel_is_sub(layout->type)) 19789 nk_push_scissor(out, nk_null_rect); 19790 19791 /* cache configuration data */ 19792 scrollbar_size = style->window.scrollbar_size; 19793 panel_padding = nk_panel_get_padding(style, layout->type); 19794 19795 /* update the current cursor Y-position to point over the last added widget */ 19796 layout->at_y += layout->row.height; 19797 19798 /* dynamic panels */ 19799 if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED)) 19800 { 19801 /* update panel height to fit dynamic growth */ 19802 struct nk_rect empty_space; 19803 if (layout->at_y < (layout->bounds.y + layout->bounds.h)) 19804 layout->bounds.h = layout->at_y - layout->bounds.y; 19805 19806 /* fill top empty space */ 19807 empty_space.x = window->bounds.x; 19808 empty_space.y = layout->bounds.y; 19809 empty_space.h = panel_padding.y; 19810 empty_space.w = window->bounds.w; 19811 nk_fill_rect(out, empty_space, 0, style->window.background); 19812 19813 /* fill left empty space */ 19814 empty_space.x = window->bounds.x; 19815 empty_space.y = layout->bounds.y; 19816 empty_space.w = panel_padding.x + layout->border; 19817 empty_space.h = layout->bounds.h; 19818 nk_fill_rect(out, empty_space, 0, style->window.background); 19819 19820 /* fill right empty space */ 19821 empty_space.x = layout->bounds.x + layout->bounds.w; 19822 empty_space.y = layout->bounds.y; 19823 empty_space.w = panel_padding.x + layout->border; 19824 empty_space.h = layout->bounds.h; 19825 if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) 19826 empty_space.w += scrollbar_size.x; 19827 nk_fill_rect(out, empty_space, 0, style->window.background); 19828 19829 /* fill bottom empty space */ 19830 if (layout->footer_height > 0) { 19831 empty_space.x = window->bounds.x; 19832 empty_space.y = layout->bounds.y + layout->bounds.h; 19833 empty_space.w = window->bounds.w; 19834 empty_space.h = layout->footer_height; 19835 nk_fill_rect(out, empty_space, 0, style->window.background); 19836 } 19837 } 19838 19839 /* scrollbars */ 19840 if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) && 19841 !(layout->flags & NK_WINDOW_MINIMIZED) && 19842 window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT) 19843 { 19844 struct nk_rect scroll; 19845 int scroll_has_scrolling; 19846 float scroll_target; 19847 float scroll_offset; 19848 float scroll_step; 19849 float scroll_inc; 19850 19851 /* mouse wheel scrolling */ 19852 if (nk_panel_is_sub(layout->type)) 19853 { 19854 /* sub-window mouse wheel scrolling */ 19855 struct nk_window *root_window = window; 19856 struct nk_panel *root_panel = window->layout; 19857 while (root_panel->parent) 19858 root_panel = root_panel->parent; 19859 while (root_window->parent) 19860 root_window = root_window->parent; 19861 19862 /* only allow scrolling if parent window is active */ 19863 scroll_has_scrolling = 0; 19864 if ((root_window == ctx->active) && layout->has_scrolling) { 19865 /* and panel is being hovered and inside clip rect*/ 19866 if (nk_input_is_mouse_hovering_rect(in, layout->bounds) && 19867 NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h, 19868 root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h)) 19869 { 19870 /* deactivate all parent scrolling */ 19871 root_panel = window->layout; 19872 while (root_panel->parent) { 19873 root_panel->has_scrolling = nk_false; 19874 root_panel = root_panel->parent; 19875 } 19876 root_panel->has_scrolling = nk_false; 19877 scroll_has_scrolling = nk_true; 19878 } 19879 } 19880 } else if (!nk_panel_is_sub(layout->type)) { 19881 /* window mouse wheel scrolling */ 19882 scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling; 19883 if (in && (in->mouse.scroll_delta.y > 0 || in->mouse.scroll_delta.x > 0) && scroll_has_scrolling) 19884 window->scrolled = nk_true; 19885 else window->scrolled = nk_false; 19886 } else scroll_has_scrolling = nk_false; 19887 19888 { 19889 /* vertical scrollbar */ 19890 nk_flags state = 0; 19891 scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x; 19892 scroll.y = layout->bounds.y; 19893 scroll.w = scrollbar_size.x; 19894 scroll.h = layout->bounds.h; 19895 19896 scroll_offset = (float)*layout->offset_y; 19897 scroll_step = scroll.h * 0.10f; 19898 scroll_inc = scroll.h * 0.01f; 19899 scroll_target = (float)(int)(layout->at_y - scroll.y); 19900 scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling, 19901 scroll_offset, scroll_target, scroll_step, scroll_inc, 19902 &ctx->style.scrollv, in, style->font); 19903 *layout->offset_y = (nk_uint)scroll_offset; 19904 if (in && scroll_has_scrolling) 19905 in->mouse.scroll_delta.y = 0; 19906 } 19907 { 19908 /* horizontal scrollbar */ 19909 nk_flags state = 0; 19910 scroll.x = layout->bounds.x; 19911 scroll.y = layout->bounds.y + layout->bounds.h; 19912 scroll.w = layout->bounds.w; 19913 scroll.h = scrollbar_size.y; 19914 19915 scroll_offset = (float)*layout->offset_x; 19916 scroll_target = (float)(int)(layout->max_x - scroll.x); 19917 scroll_step = layout->max_x * 0.05f; 19918 scroll_inc = layout->max_x * 0.005f; 19919 scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling, 19920 scroll_offset, scroll_target, scroll_step, scroll_inc, 19921 &ctx->style.scrollh, in, style->font); 19922 *layout->offset_x = (nk_uint)scroll_offset; 19923 } 19924 } 19925 19926 /* hide scroll if no user input */ 19927 if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) { 19928 int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta.y != 0; 19929 int is_window_hovered = nk_window_is_hovered(ctx); 19930 int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); 19931 if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active)) 19932 window->scrollbar_hiding_timer += ctx->delta_time_seconds; 19933 else window->scrollbar_hiding_timer = 0; 19934 } else window->scrollbar_hiding_timer = 0; 19935 19936 /* window border */ 19937 if (layout->flags & NK_WINDOW_BORDER) 19938 { 19939 struct nk_color border_color = nk_panel_get_border_color(style, layout->type); 19940 const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) 19941 ? (style->window.border + window->bounds.y + layout->header_height) 19942 : ((layout->flags & NK_WINDOW_DYNAMIC) 19943 ? (layout->bounds.y + layout->bounds.h + layout->footer_height) 19944 : (window->bounds.y + window->bounds.h)); 19945 struct nk_rect b = window->bounds; 19946 b.h = padding_y - window->bounds.y; 19947 nk_stroke_rect(out, b, 0, layout->border, border_color); 19948 } 19949 19950 /* scaler */ 19951 if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED)) 19952 { 19953 /* calculate scaler bounds */ 19954 struct nk_rect scaler; 19955 scaler.w = scrollbar_size.x; 19956 scaler.h = scrollbar_size.y; 19957 scaler.y = layout->bounds.y + layout->bounds.h; 19958 if (layout->flags & NK_WINDOW_SCALE_LEFT) 19959 scaler.x = layout->bounds.x - panel_padding.x * 0.5f; 19960 else scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x; 19961 if (layout->flags & NK_WINDOW_NO_SCROLLBAR) 19962 scaler.x -= scaler.w; 19963 19964 /* draw scaler */ 19965 {const struct nk_style_item *item = &style->window.scaler; 19966 if (item->type == NK_STYLE_ITEM_IMAGE) 19967 nk_draw_image(out, scaler, &item->data.image, nk_white); 19968 else { 19969 if (layout->flags & NK_WINDOW_SCALE_LEFT) { 19970 nk_fill_triangle(out, scaler.x, scaler.y, scaler.x, 19971 scaler.y + scaler.h, scaler.x + scaler.w, 19972 scaler.y + scaler.h, item->data.color); 19973 } else { 19974 nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w, 19975 scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color); 19976 } 19977 }} 19978 19979 /* do window scaling */ 19980 if (!(window->flags & NK_WINDOW_ROM)) { 19981 struct nk_vec2 window_size = style->window.min_size; 19982 int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 19983 int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in, 19984 NK_BUTTON_LEFT, scaler, nk_true); 19985 19986 if (left_mouse_down && left_mouse_click_in_scaler) { 19987 float delta_x = in->mouse.delta.x; 19988 if (layout->flags & NK_WINDOW_SCALE_LEFT) { 19989 delta_x = -delta_x; 19990 window->bounds.x += in->mouse.delta.x; 19991 } 19992 /* dragging in x-direction */ 19993 if (window->bounds.w + delta_x >= window_size.x) { 19994 if ((delta_x < 0) || (delta_x > 0 && in->mouse.pos.x >= scaler.x)) { 19995 window->bounds.w = window->bounds.w + delta_x; 19996 scaler.x += in->mouse.delta.x; 19997 } 19998 } 19999 /* dragging in y-direction (only possible if static window) */ 20000 if (!(layout->flags & NK_WINDOW_DYNAMIC)) { 20001 if (window_size.y < window->bounds.h + in->mouse.delta.y) { 20002 if ((in->mouse.delta.y < 0) || (in->mouse.delta.y > 0 && in->mouse.pos.y >= scaler.y)) { 20003 window->bounds.h = window->bounds.h + in->mouse.delta.y; 20004 scaler.y += in->mouse.delta.y; 20005 } 20006 } 20007 } 20008 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT]; 20009 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + scaler.w/2.0f; 20010 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + scaler.h/2.0f; 20011 } 20012 } 20013 } 20014 if (!nk_panel_is_sub(layout->type)) { 20015 /* window is hidden so clear command buffer */ 20016 if (layout->flags & NK_WINDOW_HIDDEN) 20017 nk_command_buffer_reset(&window->buffer); 20018 /* window is visible and not tab */ 20019 else nk_finish(ctx, window); 20020 } 20021 20022 /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */ 20023 if (layout->flags & NK_WINDOW_REMOVE_ROM) { 20024 layout->flags &= ~(nk_flags)NK_WINDOW_ROM; 20025 layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; 20026 } 20027 window->flags = layout->flags; 20028 20029 /* property garbage collector */ 20030 if (window->property.active && window->property.old != window->property.seq && 20031 window->property.active == window->property.prev) { 20032 nk_zero(&window->property, sizeof(window->property)); 20033 } else { 20034 window->property.old = window->property.seq; 20035 window->property.prev = window->property.active; 20036 window->property.seq = 0; 20037 } 20038 /* edit garbage collector */ 20039 if (window->edit.active && window->edit.old != window->edit.seq && 20040 window->edit.active == window->edit.prev) { 20041 nk_zero(&window->edit, sizeof(window->edit)); 20042 } else { 20043 window->edit.old = window->edit.seq; 20044 window->edit.prev = window->edit.active; 20045 window->edit.seq = 0; 20046 } 20047 /* contextual garbage collector */ 20048 if (window->popup.active_con && window->popup.con_old != window->popup.con_count) { 20049 window->popup.con_count = 0; 20050 window->popup.con_old = 0; 20051 window->popup.active_con = 0; 20052 } else { 20053 window->popup.con_old = window->popup.con_count; 20054 window->popup.con_count = 0; 20055 } 20056 window->popup.combo_count = 0; 20057 /* helper to make sure you have a 'nk_tree_push' for every 'nk_tree_pop' */ 20058 NK_ASSERT(!layout->row.tree_depth); 20059 } 20060 20061 20062 20063 20064 20065 /* =============================================================== 20066 * 20067 * WINDOW 20068 * 20069 * ===============================================================*/ 20070 NK_LIB void* 20071 nk_create_window(struct nk_context *ctx) 20072 { 20073 struct nk_page_element *elem; 20074 elem = nk_create_page_element(ctx); 20075 if (!elem) return 0; 20076 elem->data.win.seq = ctx->seq; 20077 return &elem->data.win; 20078 } 20079 NK_LIB void 20080 nk_free_window(struct nk_context *ctx, struct nk_window *win) 20081 { 20082 /* unlink windows from list */ 20083 struct nk_table *it = win->tables; 20084 if (win->popup.win) { 20085 nk_free_window(ctx, win->popup.win); 20086 win->popup.win = 0; 20087 } 20088 win->next = 0; 20089 win->prev = 0; 20090 20091 while (it) { 20092 /*free window state tables */ 20093 struct nk_table *n = it->next; 20094 nk_remove_table(win, it); 20095 nk_free_table(ctx, it); 20096 if (it == win->tables) 20097 win->tables = n; 20098 it = n; 20099 } 20100 20101 /* link windows into freelist */ 20102 {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win); 20103 struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); 20104 nk_free_page_element(ctx, pe);} 20105 } 20106 NK_LIB struct nk_window* 20107 nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name) 20108 { 20109 struct nk_window *iter; 20110 iter = ctx->begin; 20111 while (iter) { 20112 NK_ASSERT(iter != iter->next); 20113 if (iter->name == hash) { 20114 int max_len = nk_strlen(iter->name_string); 20115 if (!nk_stricmpn(iter->name_string, name, max_len)) 20116 return iter; 20117 } 20118 iter = iter->next; 20119 } 20120 return 0; 20121 } 20122 NK_LIB void 20123 nk_insert_window(struct nk_context *ctx, struct nk_window *win, 20124 enum nk_window_insert_location loc) 20125 { 20126 const struct nk_window *iter; 20127 NK_ASSERT(ctx); 20128 NK_ASSERT(win); 20129 if (!win || !ctx) return; 20130 20131 iter = ctx->begin; 20132 while (iter) { 20133 NK_ASSERT(iter != iter->next); 20134 NK_ASSERT(iter != win); 20135 if (iter == win) return; 20136 iter = iter->next; 20137 } 20138 20139 if (!ctx->begin) { 20140 win->next = 0; 20141 win->prev = 0; 20142 ctx->begin = win; 20143 ctx->end = win; 20144 ctx->count = 1; 20145 return; 20146 } 20147 if (loc == NK_INSERT_BACK) { 20148 struct nk_window *end; 20149 end = ctx->end; 20150 end->flags |= NK_WINDOW_ROM; 20151 end->next = win; 20152 win->prev = ctx->end; 20153 win->next = 0; 20154 ctx->end = win; 20155 ctx->active = ctx->end; 20156 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; 20157 } else { 20158 /*ctx->end->flags |= NK_WINDOW_ROM;*/ 20159 ctx->begin->prev = win; 20160 win->next = ctx->begin; 20161 win->prev = 0; 20162 ctx->begin = win; 20163 ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM; 20164 } 20165 ctx->count++; 20166 } 20167 NK_LIB void 20168 nk_remove_window(struct nk_context *ctx, struct nk_window *win) 20169 { 20170 if (win == ctx->begin || win == ctx->end) { 20171 if (win == ctx->begin) { 20172 ctx->begin = win->next; 20173 if (win->next) 20174 win->next->prev = 0; 20175 } 20176 if (win == ctx->end) { 20177 ctx->end = win->prev; 20178 if (win->prev) 20179 win->prev->next = 0; 20180 } 20181 } else { 20182 if (win->next) 20183 win->next->prev = win->prev; 20184 if (win->prev) 20185 win->prev->next = win->next; 20186 } 20187 if (win == ctx->active || !ctx->active) { 20188 ctx->active = ctx->end; 20189 if (ctx->end) 20190 ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; 20191 } 20192 win->next = 0; 20193 win->prev = 0; 20194 ctx->count--; 20195 } 20196 NK_API nk_bool 20197 nk_begin(struct nk_context *ctx, const char *title, 20198 struct nk_rect bounds, nk_flags flags) 20199 { 20200 return nk_begin_titled(ctx, title, title, bounds, flags); 20201 } 20202 NK_API nk_bool 20203 nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, 20204 struct nk_rect bounds, nk_flags flags) 20205 { 20206 struct nk_window *win; 20207 struct nk_style *style; 20208 nk_hash name_hash; 20209 int name_len; 20210 int ret = 0; 20211 20212 NK_ASSERT(ctx); 20213 NK_ASSERT(name); 20214 NK_ASSERT(title); 20215 NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font"); 20216 NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call"); 20217 if (!ctx || ctx->current || !title || !name) 20218 return 0; 20219 20220 /* find or create window */ 20221 style = &ctx->style; 20222 name_len = (int)nk_strlen(name); 20223 name_hash = nk_murmur_hash(name, (int)name_len, NK_WINDOW_TITLE); 20224 win = nk_find_window(ctx, name_hash, name); 20225 if (!win) { 20226 /* create new window */ 20227 nk_size name_length = (nk_size)name_len; 20228 win = (struct nk_window*)nk_create_window(ctx); 20229 NK_ASSERT(win); 20230 if (!win) return 0; 20231 20232 if (flags & NK_WINDOW_BACKGROUND) 20233 nk_insert_window(ctx, win, NK_INSERT_FRONT); 20234 else nk_insert_window(ctx, win, NK_INSERT_BACK); 20235 nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON); 20236 20237 win->flags = flags; 20238 win->bounds = bounds; 20239 win->name = name_hash; 20240 name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1); 20241 NK_MEMCPY(win->name_string, name, name_length); 20242 win->name_string[name_length] = 0; 20243 win->popup.win = 0; 20244 if (!ctx->active) 20245 ctx->active = win; 20246 } else { 20247 /* update window */ 20248 win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1); 20249 win->flags |= flags; 20250 if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE))) 20251 win->bounds = bounds; 20252 /* If this assert triggers you either: 20253 * 20254 * I.) Have more than one window with the same name or 20255 * II.) You forgot to actually draw the window. 20256 * More specific you did not call `nk_clear` (nk_clear will be 20257 * automatically called for you if you are using one of the 20258 * provided demo backends). */ 20259 NK_ASSERT(win->seq != ctx->seq); 20260 win->seq = ctx->seq; 20261 if (!ctx->active && !(win->flags & NK_WINDOW_HIDDEN)) { 20262 ctx->active = win; 20263 ctx->end = win; 20264 } 20265 } 20266 if (win->flags & NK_WINDOW_HIDDEN) { 20267 ctx->current = win; 20268 win->layout = 0; 20269 return 0; 20270 } else nk_start(ctx, win); 20271 20272 /* window overlapping */ 20273 if (!(win->flags & NK_WINDOW_HIDDEN) && !(win->flags & NK_WINDOW_NO_INPUT)) 20274 { 20275 int inpanel, ishovered; 20276 struct nk_window *iter = win; 20277 float h = ctx->style.font->height + 2.0f * style->window.header.padding.y + 20278 (2.0f * style->window.header.label_padding.y); 20279 struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))? 20280 win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h); 20281 20282 /* activate window if hovered and no other window is overlapping this window */ 20283 inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true); 20284 inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked; 20285 ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds); 20286 if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) { 20287 iter = win->next; 20288 while (iter) { 20289 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? 20290 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); 20291 if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 20292 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && 20293 (!(iter->flags & NK_WINDOW_HIDDEN))) 20294 break; 20295 20296 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && 20297 NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 20298 iter->popup.win->bounds.x, iter->popup.win->bounds.y, 20299 iter->popup.win->bounds.w, iter->popup.win->bounds.h)) 20300 break; 20301 iter = iter->next; 20302 } 20303 } 20304 20305 /* activate window if clicked */ 20306 if (iter && inpanel && (win != ctx->end)) { 20307 iter = win->next; 20308 while (iter) { 20309 /* try to find a panel with higher priority in the same position */ 20310 struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? 20311 iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); 20312 if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y, 20313 iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && 20314 !(iter->flags & NK_WINDOW_HIDDEN)) 20315 break; 20316 if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && 20317 NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, 20318 iter->popup.win->bounds.x, iter->popup.win->bounds.y, 20319 iter->popup.win->bounds.w, iter->popup.win->bounds.h)) 20320 break; 20321 iter = iter->next; 20322 } 20323 } 20324 if (iter && !(win->flags & NK_WINDOW_ROM) && (win->flags & NK_WINDOW_BACKGROUND)) { 20325 win->flags |= (nk_flags)NK_WINDOW_ROM; 20326 iter->flags &= ~(nk_flags)NK_WINDOW_ROM; 20327 ctx->active = iter; 20328 if (!(iter->flags & NK_WINDOW_BACKGROUND)) { 20329 /* current window is active in that position so transfer to top 20330 * at the highest priority in stack */ 20331 nk_remove_window(ctx, iter); 20332 nk_insert_window(ctx, iter, NK_INSERT_BACK); 20333 } 20334 } else { 20335 if (!iter && ctx->end != win) { 20336 if (!(win->flags & NK_WINDOW_BACKGROUND)) { 20337 /* current window is active in that position so transfer to top 20338 * at the highest priority in stack */ 20339 nk_remove_window(ctx, win); 20340 nk_insert_window(ctx, win, NK_INSERT_BACK); 20341 } 20342 win->flags &= ~(nk_flags)NK_WINDOW_ROM; 20343 ctx->active = win; 20344 } 20345 if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND)) 20346 win->flags |= NK_WINDOW_ROM; 20347 } 20348 } 20349 win->layout = (struct nk_panel*)nk_create_panel(ctx); 20350 ctx->current = win; 20351 ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW); 20352 win->layout->offset_x = &win->scrollbar.x; 20353 win->layout->offset_y = &win->scrollbar.y; 20354 return ret; 20355 } 20356 NK_API void 20357 nk_end(struct nk_context *ctx) 20358 { 20359 struct nk_panel *layout; 20360 NK_ASSERT(ctx); 20361 NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`"); 20362 if (!ctx || !ctx->current) 20363 return; 20364 20365 layout = ctx->current->layout; 20366 if (!layout || (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN))) { 20367 ctx->current = 0; 20368 return; 20369 } 20370 nk_panel_end(ctx); 20371 nk_free_panel(ctx, ctx->current->layout); 20372 ctx->current = 0; 20373 } 20374 NK_API struct nk_rect 20375 nk_window_get_bounds(const struct nk_context *ctx) 20376 { 20377 NK_ASSERT(ctx); 20378 NK_ASSERT(ctx->current); 20379 if (!ctx || !ctx->current) return nk_rect(0,0,0,0); 20380 return ctx->current->bounds; 20381 } 20382 NK_API struct nk_vec2 20383 nk_window_get_position(const struct nk_context *ctx) 20384 { 20385 NK_ASSERT(ctx); 20386 NK_ASSERT(ctx->current); 20387 if (!ctx || !ctx->current) return nk_vec2(0,0); 20388 return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y); 20389 } 20390 NK_API struct nk_vec2 20391 nk_window_get_size(const struct nk_context *ctx) 20392 { 20393 NK_ASSERT(ctx); 20394 NK_ASSERT(ctx->current); 20395 if (!ctx || !ctx->current) return nk_vec2(0,0); 20396 return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h); 20397 } 20398 NK_API float 20399 nk_window_get_width(const struct nk_context *ctx) 20400 { 20401 NK_ASSERT(ctx); 20402 NK_ASSERT(ctx->current); 20403 if (!ctx || !ctx->current) return 0; 20404 return ctx->current->bounds.w; 20405 } 20406 NK_API float 20407 nk_window_get_height(const struct nk_context *ctx) 20408 { 20409 NK_ASSERT(ctx); 20410 NK_ASSERT(ctx->current); 20411 if (!ctx || !ctx->current) return 0; 20412 return ctx->current->bounds.h; 20413 } 20414 NK_API struct nk_rect 20415 nk_window_get_content_region(struct nk_context *ctx) 20416 { 20417 NK_ASSERT(ctx); 20418 NK_ASSERT(ctx->current); 20419 if (!ctx || !ctx->current) return nk_rect(0,0,0,0); 20420 return ctx->current->layout->clip; 20421 } 20422 NK_API struct nk_vec2 20423 nk_window_get_content_region_min(struct nk_context *ctx) 20424 { 20425 NK_ASSERT(ctx); 20426 NK_ASSERT(ctx->current); 20427 NK_ASSERT(ctx->current->layout); 20428 if (!ctx || !ctx->current) return nk_vec2(0,0); 20429 return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y); 20430 } 20431 NK_API struct nk_vec2 20432 nk_window_get_content_region_max(struct nk_context *ctx) 20433 { 20434 NK_ASSERT(ctx); 20435 NK_ASSERT(ctx->current); 20436 NK_ASSERT(ctx->current->layout); 20437 if (!ctx || !ctx->current) return nk_vec2(0,0); 20438 return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w, 20439 ctx->current->layout->clip.y + ctx->current->layout->clip.h); 20440 } 20441 NK_API struct nk_vec2 20442 nk_window_get_content_region_size(struct nk_context *ctx) 20443 { 20444 NK_ASSERT(ctx); 20445 NK_ASSERT(ctx->current); 20446 NK_ASSERT(ctx->current->layout); 20447 if (!ctx || !ctx->current) return nk_vec2(0,0); 20448 return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h); 20449 } 20450 NK_API struct nk_command_buffer* 20451 nk_window_get_canvas(struct nk_context *ctx) 20452 { 20453 NK_ASSERT(ctx); 20454 NK_ASSERT(ctx->current); 20455 NK_ASSERT(ctx->current->layout); 20456 if (!ctx || !ctx->current) return 0; 20457 return &ctx->current->buffer; 20458 } 20459 NK_API struct nk_panel* 20460 nk_window_get_panel(struct nk_context *ctx) 20461 { 20462 NK_ASSERT(ctx); 20463 NK_ASSERT(ctx->current); 20464 if (!ctx || !ctx->current) return 0; 20465 return ctx->current->layout; 20466 } 20467 NK_API void 20468 nk_window_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y) 20469 { 20470 struct nk_window *win; 20471 NK_ASSERT(ctx); 20472 NK_ASSERT(ctx->current); 20473 if (!ctx || !ctx->current) 20474 return ; 20475 win = ctx->current; 20476 if (offset_x) 20477 *offset_x = win->scrollbar.x; 20478 if (offset_y) 20479 *offset_y = win->scrollbar.y; 20480 } 20481 NK_API nk_bool 20482 nk_window_has_focus(const struct nk_context *ctx) 20483 { 20484 NK_ASSERT(ctx); 20485 NK_ASSERT(ctx->current); 20486 NK_ASSERT(ctx->current->layout); 20487 if (!ctx || !ctx->current) return 0; 20488 return ctx->current == ctx->active; 20489 } 20490 NK_API nk_bool 20491 nk_window_is_hovered(struct nk_context *ctx) 20492 { 20493 NK_ASSERT(ctx); 20494 NK_ASSERT(ctx->current); 20495 if (!ctx || !ctx->current || (ctx->current->flags & NK_WINDOW_HIDDEN)) 20496 return 0; 20497 else { 20498 struct nk_rect actual_bounds = ctx->current->bounds; 20499 if (ctx->begin->flags & NK_WINDOW_MINIMIZED) { 20500 actual_bounds.h = ctx->current->layout->header_height; 20501 } 20502 return nk_input_is_mouse_hovering_rect(&ctx->input, actual_bounds); 20503 } 20504 } 20505 NK_API nk_bool 20506 nk_window_is_any_hovered(struct nk_context *ctx) 20507 { 20508 struct nk_window *iter; 20509 NK_ASSERT(ctx); 20510 if (!ctx) return 0; 20511 iter = ctx->begin; 20512 while (iter) { 20513 /* check if window is being hovered */ 20514 if(!(iter->flags & NK_WINDOW_HIDDEN)) { 20515 /* check if window popup is being hovered */ 20516 if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds)) 20517 return 1; 20518 20519 if (iter->flags & NK_WINDOW_MINIMIZED) { 20520 struct nk_rect header = iter->bounds; 20521 header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y; 20522 if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) 20523 return 1; 20524 } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) { 20525 return 1; 20526 } 20527 } 20528 iter = iter->next; 20529 } 20530 return 0; 20531 } 20532 NK_API nk_bool 20533 nk_item_is_any_active(struct nk_context *ctx) 20534 { 20535 int any_hovered = nk_window_is_any_hovered(ctx); 20536 int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); 20537 return any_hovered || any_active; 20538 } 20539 NK_API nk_bool 20540 nk_window_is_collapsed(struct nk_context *ctx, const char *name) 20541 { 20542 int title_len; 20543 nk_hash title_hash; 20544 struct nk_window *win; 20545 NK_ASSERT(ctx); 20546 if (!ctx) return 0; 20547 20548 title_len = (int)nk_strlen(name); 20549 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 20550 win = nk_find_window(ctx, title_hash, name); 20551 if (!win) return 0; 20552 return win->flags & NK_WINDOW_MINIMIZED; 20553 } 20554 NK_API nk_bool 20555 nk_window_is_closed(struct nk_context *ctx, const char *name) 20556 { 20557 int title_len; 20558 nk_hash title_hash; 20559 struct nk_window *win; 20560 NK_ASSERT(ctx); 20561 if (!ctx) return 1; 20562 20563 title_len = (int)nk_strlen(name); 20564 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 20565 win = nk_find_window(ctx, title_hash, name); 20566 if (!win) return 1; 20567 return (win->flags & NK_WINDOW_CLOSED); 20568 } 20569 NK_API nk_bool 20570 nk_window_is_hidden(struct nk_context *ctx, const char *name) 20571 { 20572 int title_len; 20573 nk_hash title_hash; 20574 struct nk_window *win; 20575 NK_ASSERT(ctx); 20576 if (!ctx) return 1; 20577 20578 title_len = (int)nk_strlen(name); 20579 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 20580 win = nk_find_window(ctx, title_hash, name); 20581 if (!win) return 1; 20582 return (win->flags & NK_WINDOW_HIDDEN); 20583 } 20584 NK_API nk_bool 20585 nk_window_is_active(struct nk_context *ctx, const char *name) 20586 { 20587 int title_len; 20588 nk_hash title_hash; 20589 struct nk_window *win; 20590 NK_ASSERT(ctx); 20591 if (!ctx) return 0; 20592 20593 title_len = (int)nk_strlen(name); 20594 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 20595 win = nk_find_window(ctx, title_hash, name); 20596 if (!win) return 0; 20597 return win == ctx->active; 20598 } 20599 NK_API struct nk_window* 20600 nk_window_find(struct nk_context *ctx, const char *name) 20601 { 20602 int title_len; 20603 nk_hash title_hash; 20604 title_len = (int)nk_strlen(name); 20605 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 20606 return nk_find_window(ctx, title_hash, name); 20607 } 20608 NK_API void 20609 nk_window_close(struct nk_context *ctx, const char *name) 20610 { 20611 struct nk_window *win; 20612 NK_ASSERT(ctx); 20613 if (!ctx) return; 20614 win = nk_window_find(ctx, name); 20615 if (!win) return; 20616 NK_ASSERT(ctx->current != win && "You cannot close a currently active window"); 20617 if (ctx->current == win) return; 20618 win->flags |= NK_WINDOW_HIDDEN; 20619 win->flags |= NK_WINDOW_CLOSED; 20620 } 20621 NK_API void 20622 nk_window_set_bounds(struct nk_context *ctx, 20623 const char *name, struct nk_rect bounds) 20624 { 20625 struct nk_window *win; 20626 NK_ASSERT(ctx); 20627 if (!ctx) return; 20628 win = nk_window_find(ctx, name); 20629 if (!win) return; 20630 NK_ASSERT(ctx->current != win && "You cannot update a currently in procecss window"); 20631 win->bounds = bounds; 20632 } 20633 NK_API void 20634 nk_window_set_position(struct nk_context *ctx, 20635 const char *name, struct nk_vec2 pos) 20636 { 20637 struct nk_window *win = nk_window_find(ctx, name); 20638 if (!win) return; 20639 win->bounds.x = pos.x; 20640 win->bounds.y = pos.y; 20641 } 20642 NK_API void 20643 nk_window_set_size(struct nk_context *ctx, 20644 const char *name, struct nk_vec2 size) 20645 { 20646 struct nk_window *win = nk_window_find(ctx, name); 20647 if (!win) return; 20648 win->bounds.w = size.x; 20649 win->bounds.h = size.y; 20650 } 20651 NK_API void 20652 nk_window_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y) 20653 { 20654 struct nk_window *win; 20655 NK_ASSERT(ctx); 20656 NK_ASSERT(ctx->current); 20657 if (!ctx || !ctx->current) 20658 return; 20659 win = ctx->current; 20660 win->scrollbar.x = offset_x; 20661 win->scrollbar.y = offset_y; 20662 } 20663 NK_API void 20664 nk_window_collapse(struct nk_context *ctx, const char *name, 20665 enum nk_collapse_states c) 20666 { 20667 int title_len; 20668 nk_hash title_hash; 20669 struct nk_window *win; 20670 NK_ASSERT(ctx); 20671 if (!ctx) return; 20672 20673 title_len = (int)nk_strlen(name); 20674 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 20675 win = nk_find_window(ctx, title_hash, name); 20676 if (!win) return; 20677 if (c == NK_MINIMIZED) 20678 win->flags |= NK_WINDOW_MINIMIZED; 20679 else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED; 20680 } 20681 NK_API void 20682 nk_window_collapse_if(struct nk_context *ctx, const char *name, 20683 enum nk_collapse_states c, int cond) 20684 { 20685 NK_ASSERT(ctx); 20686 if (!ctx || !cond) return; 20687 nk_window_collapse(ctx, name, c); 20688 } 20689 NK_API void 20690 nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s) 20691 { 20692 int title_len; 20693 nk_hash title_hash; 20694 struct nk_window *win; 20695 NK_ASSERT(ctx); 20696 if (!ctx) return; 20697 20698 title_len = (int)nk_strlen(name); 20699 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 20700 win = nk_find_window(ctx, title_hash, name); 20701 if (!win) return; 20702 if (s == NK_HIDDEN) { 20703 win->flags |= NK_WINDOW_HIDDEN; 20704 } else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN; 20705 } 20706 NK_API void 20707 nk_window_show_if(struct nk_context *ctx, const char *name, 20708 enum nk_show_states s, int cond) 20709 { 20710 NK_ASSERT(ctx); 20711 if (!ctx || !cond) return; 20712 nk_window_show(ctx, name, s); 20713 } 20714 20715 NK_API void 20716 nk_window_set_focus(struct nk_context *ctx, const char *name) 20717 { 20718 int title_len; 20719 nk_hash title_hash; 20720 struct nk_window *win; 20721 NK_ASSERT(ctx); 20722 if (!ctx) return; 20723 20724 title_len = (int)nk_strlen(name); 20725 title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); 20726 win = nk_find_window(ctx, title_hash, name); 20727 if (win && ctx->end != win) { 20728 nk_remove_window(ctx, win); 20729 nk_insert_window(ctx, win, NK_INSERT_BACK); 20730 } 20731 ctx->active = win; 20732 } 20733 20734 20735 20736 20737 /* =============================================================== 20738 * 20739 * POPUP 20740 * 20741 * ===============================================================*/ 20742 NK_API nk_bool 20743 nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type, 20744 const char *title, nk_flags flags, struct nk_rect rect) 20745 { 20746 struct nk_window *popup; 20747 struct nk_window *win; 20748 struct nk_panel *panel; 20749 20750 int title_len; 20751 nk_hash title_hash; 20752 nk_size allocated; 20753 20754 NK_ASSERT(ctx); 20755 NK_ASSERT(title); 20756 NK_ASSERT(ctx->current); 20757 NK_ASSERT(ctx->current->layout); 20758 if (!ctx || !ctx->current || !ctx->current->layout) 20759 return 0; 20760 20761 win = ctx->current; 20762 panel = win->layout; 20763 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups"); 20764 (void)panel; 20765 title_len = (int)nk_strlen(title); 20766 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP); 20767 20768 popup = win->popup.win; 20769 if (!popup) { 20770 popup = (struct nk_window*)nk_create_window(ctx); 20771 popup->parent = win; 20772 win->popup.win = popup; 20773 win->popup.active = 0; 20774 win->popup.type = NK_PANEL_POPUP; 20775 } 20776 20777 /* make sure we have correct popup */ 20778 if (win->popup.name != title_hash) { 20779 if (!win->popup.active) { 20780 nk_zero(popup, sizeof(*popup)); 20781 win->popup.name = title_hash; 20782 win->popup.active = 1; 20783 win->popup.type = NK_PANEL_POPUP; 20784 } else return 0; 20785 } 20786 20787 /* popup position is local to window */ 20788 ctx->current = popup; 20789 rect.x += win->layout->clip.x; 20790 rect.y += win->layout->clip.y; 20791 20792 /* setup popup data */ 20793 popup->parent = win; 20794 popup->bounds = rect; 20795 popup->seq = ctx->seq; 20796 popup->layout = (struct nk_panel*)nk_create_panel(ctx); 20797 popup->flags = flags; 20798 popup->flags |= NK_WINDOW_BORDER; 20799 if (type == NK_POPUP_DYNAMIC) 20800 popup->flags |= NK_WINDOW_DYNAMIC; 20801 20802 popup->buffer = win->buffer; 20803 nk_start_popup(ctx, win); 20804 allocated = ctx->memory.allocated; 20805 nk_push_scissor(&popup->buffer, nk_null_rect); 20806 20807 if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) { 20808 /* popup is running therefore invalidate parent panels */ 20809 struct nk_panel *root; 20810 root = win->layout; 20811 while (root) { 20812 root->flags |= NK_WINDOW_ROM; 20813 root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; 20814 root = root->parent; 20815 } 20816 win->popup.active = 1; 20817 popup->layout->offset_x = &popup->scrollbar.x; 20818 popup->layout->offset_y = &popup->scrollbar.y; 20819 popup->layout->parent = win->layout; 20820 return 1; 20821 } else { 20822 /* popup was closed/is invalid so cleanup */ 20823 struct nk_panel *root; 20824 root = win->layout; 20825 while (root) { 20826 root->flags |= NK_WINDOW_REMOVE_ROM; 20827 root = root->parent; 20828 } 20829 win->popup.buf.active = 0; 20830 win->popup.active = 0; 20831 ctx->memory.allocated = allocated; 20832 ctx->current = win; 20833 nk_free_panel(ctx, popup->layout); 20834 popup->layout = 0; 20835 return 0; 20836 } 20837 } 20838 NK_LIB nk_bool 20839 nk_nonblock_begin(struct nk_context *ctx, 20840 nk_flags flags, struct nk_rect body, struct nk_rect header, 20841 enum nk_panel_type panel_type) 20842 { 20843 struct nk_window *popup; 20844 struct nk_window *win; 20845 struct nk_panel *panel; 20846 int is_active = nk_true; 20847 20848 NK_ASSERT(ctx); 20849 NK_ASSERT(ctx->current); 20850 NK_ASSERT(ctx->current->layout); 20851 if (!ctx || !ctx->current || !ctx->current->layout) 20852 return 0; 20853 20854 /* popups cannot have popups */ 20855 win = ctx->current; 20856 panel = win->layout; 20857 NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP)); 20858 (void)panel; 20859 popup = win->popup.win; 20860 if (!popup) { 20861 /* create window for nonblocking popup */ 20862 popup = (struct nk_window*)nk_create_window(ctx); 20863 popup->parent = win; 20864 win->popup.win = popup; 20865 win->popup.type = panel_type; 20866 nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON); 20867 } else { 20868 /* close the popup if user pressed outside or in the header */ 20869 int pressed, in_body, in_header; 20870 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE 20871 pressed = nk_input_is_mouse_released(&ctx->input, NK_BUTTON_LEFT); 20872 #else 20873 pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); 20874 #endif 20875 in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); 20876 in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header); 20877 if (pressed && (!in_body || in_header)) 20878 is_active = nk_false; 20879 } 20880 win->popup.header = header; 20881 20882 if (!is_active) { 20883 /* remove read only mode from all parent panels */ 20884 struct nk_panel *root = win->layout; 20885 while (root) { 20886 root->flags |= NK_WINDOW_REMOVE_ROM; 20887 root = root->parent; 20888 } 20889 return is_active; 20890 } 20891 popup->bounds = body; 20892 popup->parent = win; 20893 popup->layout = (struct nk_panel*)nk_create_panel(ctx); 20894 popup->flags = flags; 20895 popup->flags |= NK_WINDOW_BORDER; 20896 popup->flags |= NK_WINDOW_DYNAMIC; 20897 popup->seq = ctx->seq; 20898 win->popup.active = 1; 20899 NK_ASSERT(popup->layout); 20900 20901 nk_start_popup(ctx, win); 20902 popup->buffer = win->buffer; 20903 nk_push_scissor(&popup->buffer, nk_null_rect); 20904 ctx->current = popup; 20905 20906 nk_panel_begin(ctx, 0, panel_type); 20907 win->buffer = popup->buffer; 20908 popup->layout->parent = win->layout; 20909 popup->layout->offset_x = &popup->scrollbar.x; 20910 popup->layout->offset_y = &popup->scrollbar.y; 20911 20912 /* set read only mode to all parent panels */ 20913 {struct nk_panel *root; 20914 root = win->layout; 20915 while (root) { 20916 root->flags |= NK_WINDOW_ROM; 20917 root = root->parent; 20918 }} 20919 return is_active; 20920 } 20921 NK_API void 20922 nk_popup_close(struct nk_context *ctx) 20923 { 20924 struct nk_window *popup; 20925 NK_ASSERT(ctx); 20926 if (!ctx || !ctx->current) return; 20927 20928 popup = ctx->current; 20929 NK_ASSERT(popup->parent); 20930 NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP); 20931 popup->flags |= NK_WINDOW_HIDDEN; 20932 } 20933 NK_API void 20934 nk_popup_end(struct nk_context *ctx) 20935 { 20936 struct nk_window *win; 20937 struct nk_window *popup; 20938 20939 NK_ASSERT(ctx); 20940 NK_ASSERT(ctx->current); 20941 NK_ASSERT(ctx->current->layout); 20942 if (!ctx || !ctx->current || !ctx->current->layout) 20943 return; 20944 20945 popup = ctx->current; 20946 if (!popup->parent) return; 20947 win = popup->parent; 20948 if (popup->flags & NK_WINDOW_HIDDEN) { 20949 struct nk_panel *root; 20950 root = win->layout; 20951 while (root) { 20952 root->flags |= NK_WINDOW_REMOVE_ROM; 20953 root = root->parent; 20954 } 20955 win->popup.active = 0; 20956 } 20957 nk_push_scissor(&popup->buffer, nk_null_rect); 20958 nk_end(ctx); 20959 20960 win->buffer = popup->buffer; 20961 nk_finish_popup(ctx, win); 20962 ctx->current = win; 20963 nk_push_scissor(&win->buffer, win->layout->clip); 20964 } 20965 NK_API void 20966 nk_popup_get_scroll(struct nk_context *ctx, nk_uint *offset_x, nk_uint *offset_y) 20967 { 20968 struct nk_window *popup; 20969 20970 NK_ASSERT(ctx); 20971 NK_ASSERT(ctx->current); 20972 NK_ASSERT(ctx->current->layout); 20973 if (!ctx || !ctx->current || !ctx->current->layout) 20974 return; 20975 20976 popup = ctx->current; 20977 if (offset_x) 20978 *offset_x = popup->scrollbar.x; 20979 if (offset_y) 20980 *offset_y = popup->scrollbar.y; 20981 } 20982 NK_API void 20983 nk_popup_set_scroll(struct nk_context *ctx, nk_uint offset_x, nk_uint offset_y) 20984 { 20985 struct nk_window *popup; 20986 20987 NK_ASSERT(ctx); 20988 NK_ASSERT(ctx->current); 20989 NK_ASSERT(ctx->current->layout); 20990 if (!ctx || !ctx->current || !ctx->current->layout) 20991 return; 20992 20993 popup = ctx->current; 20994 popup->scrollbar.x = offset_x; 20995 popup->scrollbar.y = offset_y; 20996 } 20997 20998 20999 21000 21001 /* ============================================================== 21002 * 21003 * CONTEXTUAL 21004 * 21005 * ===============================================================*/ 21006 NK_API nk_bool 21007 nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size, 21008 struct nk_rect trigger_bounds) 21009 { 21010 struct nk_window *win; 21011 struct nk_window *popup; 21012 struct nk_rect body; 21013 21014 NK_STORAGE const struct nk_rect null_rect = {-1,-1,0,0}; 21015 int is_clicked = 0; 21016 int is_open = 0; 21017 int ret = 0; 21018 21019 NK_ASSERT(ctx); 21020 NK_ASSERT(ctx->current); 21021 NK_ASSERT(ctx->current->layout); 21022 if (!ctx || !ctx->current || !ctx->current->layout) 21023 return 0; 21024 21025 win = ctx->current; 21026 ++win->popup.con_count; 21027 if (ctx->current != ctx->active) 21028 return 0; 21029 21030 /* check if currently active contextual is active */ 21031 popup = win->popup.win; 21032 is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL); 21033 is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds); 21034 if (win->popup.active_con && win->popup.con_count != win->popup.active_con) 21035 return 0; 21036 if (!is_open && win->popup.active_con) 21037 win->popup.active_con = 0; 21038 if ((!is_open && !is_clicked)) 21039 return 0; 21040 21041 /* calculate contextual position on click */ 21042 win->popup.active_con = win->popup.con_count; 21043 if (is_clicked) { 21044 body.x = ctx->input.mouse.pos.x; 21045 body.y = ctx->input.mouse.pos.y; 21046 } else { 21047 body.x = popup->bounds.x; 21048 body.y = popup->bounds.y; 21049 } 21050 body.w = size.x; 21051 body.h = size.y; 21052 21053 /* start nonblocking contextual popup */ 21054 ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body, 21055 null_rect, NK_PANEL_CONTEXTUAL); 21056 if (ret) win->popup.type = NK_PANEL_CONTEXTUAL; 21057 else { 21058 win->popup.active_con = 0; 21059 win->popup.type = NK_PANEL_NONE; 21060 if (win->popup.win) 21061 win->popup.win->flags = 0; 21062 } 21063 return ret; 21064 } 21065 NK_API nk_bool 21066 nk_contextual_item_text(struct nk_context *ctx, const char *text, int len, 21067 nk_flags alignment) 21068 { 21069 struct nk_window *win; 21070 const struct nk_input *in; 21071 const struct nk_style *style; 21072 21073 struct nk_rect bounds; 21074 enum nk_widget_layout_states state; 21075 21076 NK_ASSERT(ctx); 21077 NK_ASSERT(ctx->current); 21078 NK_ASSERT(ctx->current->layout); 21079 if (!ctx || !ctx->current || !ctx->current->layout) 21080 return 0; 21081 21082 win = ctx->current; 21083 style = &ctx->style; 21084 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 21085 if (!state) return nk_false; 21086 21087 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21088 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, 21089 text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) { 21090 nk_contextual_close(ctx); 21091 return nk_true; 21092 } 21093 return nk_false; 21094 } 21095 NK_API nk_bool 21096 nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align) 21097 { 21098 return nk_contextual_item_text(ctx, label, nk_strlen(label), align); 21099 } 21100 NK_API nk_bool 21101 nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img, 21102 const char *text, int len, nk_flags align) 21103 { 21104 struct nk_window *win; 21105 const struct nk_input *in; 21106 const struct nk_style *style; 21107 21108 struct nk_rect bounds; 21109 enum nk_widget_layout_states state; 21110 21111 NK_ASSERT(ctx); 21112 NK_ASSERT(ctx->current); 21113 NK_ASSERT(ctx->current->layout); 21114 if (!ctx || !ctx->current || !ctx->current->layout) 21115 return 0; 21116 21117 win = ctx->current; 21118 style = &ctx->style; 21119 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 21120 if (!state) return nk_false; 21121 21122 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21123 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds, 21124 img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){ 21125 nk_contextual_close(ctx); 21126 return nk_true; 21127 } 21128 return nk_false; 21129 } 21130 NK_API nk_bool 21131 nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img, 21132 const char *label, nk_flags align) 21133 { 21134 return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align); 21135 } 21136 NK_API nk_bool 21137 nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, 21138 const char *text, int len, nk_flags align) 21139 { 21140 struct nk_window *win; 21141 const struct nk_input *in; 21142 const struct nk_style *style; 21143 21144 struct nk_rect bounds; 21145 enum nk_widget_layout_states state; 21146 21147 NK_ASSERT(ctx); 21148 NK_ASSERT(ctx->current); 21149 NK_ASSERT(ctx->current->layout); 21150 if (!ctx || !ctx->current || !ctx->current->layout) 21151 return 0; 21152 21153 win = ctx->current; 21154 style = &ctx->style; 21155 state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); 21156 if (!state) return nk_false; 21157 21158 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21159 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, 21160 symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) { 21161 nk_contextual_close(ctx); 21162 return nk_true; 21163 } 21164 return nk_false; 21165 } 21166 NK_API nk_bool 21167 nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, 21168 const char *text, nk_flags align) 21169 { 21170 return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align); 21171 } 21172 NK_API void 21173 nk_contextual_close(struct nk_context *ctx) 21174 { 21175 NK_ASSERT(ctx); 21176 NK_ASSERT(ctx->current); 21177 NK_ASSERT(ctx->current->layout); 21178 if (!ctx || !ctx->current || !ctx->current->layout) return; 21179 nk_popup_close(ctx); 21180 } 21181 NK_API void 21182 nk_contextual_end(struct nk_context *ctx) 21183 { 21184 struct nk_window *popup; 21185 struct nk_panel *panel; 21186 NK_ASSERT(ctx); 21187 NK_ASSERT(ctx->current); 21188 if (!ctx || !ctx->current) return; 21189 21190 popup = ctx->current; 21191 panel = popup->layout; 21192 NK_ASSERT(popup->parent); 21193 NK_ASSERT(panel->type & NK_PANEL_SET_POPUP); 21194 if (panel->flags & NK_WINDOW_DYNAMIC) { 21195 /* Close behavior 21196 This is a bit of a hack solution since we do not know before we end our popup 21197 how big it will be. We therefore do not directly know when a 21198 click outside the non-blocking popup must close it at that direct frame. 21199 Instead it will be closed in the next frame.*/ 21200 struct nk_rect body = {0,0,0,0}; 21201 if (panel->at_y < (panel->bounds.y + panel->bounds.h)) { 21202 struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type); 21203 body = panel->bounds; 21204 body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height); 21205 body.h = (panel->bounds.y + panel->bounds.h) - body.y; 21206 } 21207 {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); 21208 int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); 21209 if (pressed && in_body) 21210 popup->flags |= NK_WINDOW_HIDDEN; 21211 } 21212 } 21213 if (popup->flags & NK_WINDOW_HIDDEN) 21214 popup->seq = 0; 21215 nk_popup_end(ctx); 21216 return; 21217 } 21218 21219 21220 21221 21222 21223 /* =============================================================== 21224 * 21225 * MENU 21226 * 21227 * ===============================================================*/ 21228 NK_API void 21229 nk_menubar_begin(struct nk_context *ctx) 21230 { 21231 struct nk_panel *layout; 21232 NK_ASSERT(ctx); 21233 NK_ASSERT(ctx->current); 21234 NK_ASSERT(ctx->current->layout); 21235 if (!ctx || !ctx->current || !ctx->current->layout) 21236 return; 21237 21238 layout = ctx->current->layout; 21239 NK_ASSERT(layout->at_y == layout->bounds.y); 21240 /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin. 21241 If you want a menubar the first nuklear function after `nk_begin` has to be a 21242 `nk_menubar_begin` call. Inside the menubar you then have to allocate space for 21243 widgets (also supports multiple rows). 21244 Example: 21245 if (nk_begin(...)) { 21246 nk_menubar_begin(...); 21247 nk_layout_xxxx(...); 21248 nk_button(...); 21249 nk_layout_xxxx(...); 21250 nk_button(...); 21251 nk_menubar_end(...); 21252 } 21253 nk_end(...); 21254 */ 21255 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) 21256 return; 21257 21258 layout->menu.x = layout->at_x; 21259 layout->menu.y = layout->at_y + layout->row.height; 21260 layout->menu.w = layout->bounds.w; 21261 layout->menu.offset.x = *layout->offset_x; 21262 layout->menu.offset.y = *layout->offset_y; 21263 *layout->offset_y = 0; 21264 } 21265 NK_API void 21266 nk_menubar_end(struct nk_context *ctx) 21267 { 21268 struct nk_window *win; 21269 struct nk_panel *layout; 21270 struct nk_command_buffer *out; 21271 21272 NK_ASSERT(ctx); 21273 NK_ASSERT(ctx->current); 21274 NK_ASSERT(ctx->current->layout); 21275 if (!ctx || !ctx->current || !ctx->current->layout) 21276 return; 21277 21278 win = ctx->current; 21279 out = &win->buffer; 21280 layout = win->layout; 21281 if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) 21282 return; 21283 21284 layout->menu.h = layout->at_y - layout->menu.y; 21285 layout->menu.h += layout->row.height + ctx->style.window.spacing.y; 21286 21287 layout->bounds.y += layout->menu.h; 21288 layout->bounds.h -= layout->menu.h; 21289 21290 *layout->offset_x = layout->menu.offset.x; 21291 *layout->offset_y = layout->menu.offset.y; 21292 layout->at_y = layout->bounds.y - layout->row.height; 21293 21294 layout->clip.y = layout->bounds.y; 21295 layout->clip.h = layout->bounds.h; 21296 nk_push_scissor(out, layout->clip); 21297 } 21298 NK_INTERN int 21299 nk_menu_begin(struct nk_context *ctx, struct nk_window *win, 21300 const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size) 21301 { 21302 int is_open = 0; 21303 int is_active = 0; 21304 struct nk_rect body; 21305 struct nk_window *popup; 21306 nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU); 21307 21308 NK_ASSERT(ctx); 21309 NK_ASSERT(ctx->current); 21310 NK_ASSERT(ctx->current->layout); 21311 if (!ctx || !ctx->current || !ctx->current->layout) 21312 return 0; 21313 21314 body.x = header.x; 21315 body.w = size.x; 21316 body.y = header.y + header.h; 21317 body.h = size.y; 21318 21319 popup = win->popup.win; 21320 is_open = popup ? nk_true : nk_false; 21321 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU); 21322 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || 21323 (!is_open && !is_active && !is_clicked)) return 0; 21324 if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU)) 21325 return 0; 21326 21327 win->popup.type = NK_PANEL_MENU; 21328 win->popup.name = hash; 21329 return 1; 21330 } 21331 NK_API nk_bool 21332 nk_menu_begin_text(struct nk_context *ctx, const char *title, int len, 21333 nk_flags align, struct nk_vec2 size) 21334 { 21335 struct nk_window *win; 21336 const struct nk_input *in; 21337 struct nk_rect header; 21338 int is_clicked = nk_false; 21339 nk_flags state; 21340 21341 NK_ASSERT(ctx); 21342 NK_ASSERT(ctx->current); 21343 NK_ASSERT(ctx->current->layout); 21344 if (!ctx || !ctx->current || !ctx->current->layout) 21345 return 0; 21346 21347 win = ctx->current; 21348 state = nk_widget(&header, ctx); 21349 if (!state) return 0; 21350 in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21351 if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header, 21352 title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) 21353 is_clicked = nk_true; 21354 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 21355 } 21356 NK_API nk_bool nk_menu_begin_label(struct nk_context *ctx, 21357 const char *text, nk_flags align, struct nk_vec2 size) 21358 { 21359 return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size); 21360 } 21361 NK_API nk_bool 21362 nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img, 21363 struct nk_vec2 size) 21364 { 21365 struct nk_window *win; 21366 struct nk_rect header; 21367 const struct nk_input *in; 21368 int is_clicked = nk_false; 21369 nk_flags state; 21370 21371 NK_ASSERT(ctx); 21372 NK_ASSERT(ctx->current); 21373 NK_ASSERT(ctx->current->layout); 21374 if (!ctx || !ctx->current || !ctx->current->layout) 21375 return 0; 21376 21377 win = ctx->current; 21378 state = nk_widget(&header, ctx); 21379 if (!state) return 0; 21380 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21381 if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header, 21382 img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in)) 21383 is_clicked = nk_true; 21384 return nk_menu_begin(ctx, win, id, is_clicked, header, size); 21385 } 21386 NK_API nk_bool 21387 nk_menu_begin_symbol(struct nk_context *ctx, const char *id, 21388 enum nk_symbol_type sym, struct nk_vec2 size) 21389 { 21390 struct nk_window *win; 21391 const struct nk_input *in; 21392 struct nk_rect header; 21393 int is_clicked = nk_false; 21394 nk_flags state; 21395 21396 NK_ASSERT(ctx); 21397 NK_ASSERT(ctx->current); 21398 NK_ASSERT(ctx->current->layout); 21399 if (!ctx || !ctx->current || !ctx->current->layout) 21400 return 0; 21401 21402 win = ctx->current; 21403 state = nk_widget(&header, ctx); 21404 if (!state) return 0; 21405 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21406 if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header, 21407 sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) 21408 is_clicked = nk_true; 21409 return nk_menu_begin(ctx, win, id, is_clicked, header, size); 21410 } 21411 NK_API nk_bool 21412 nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len, 21413 nk_flags align, struct nk_image img, struct nk_vec2 size) 21414 { 21415 struct nk_window *win; 21416 struct nk_rect header; 21417 const struct nk_input *in; 21418 int is_clicked = nk_false; 21419 nk_flags state; 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 0; 21426 21427 win = ctx->current; 21428 state = nk_widget(&header, ctx); 21429 if (!state) return 0; 21430 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21431 if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, 21432 header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, 21433 ctx->style.font, in)) 21434 is_clicked = nk_true; 21435 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 21436 } 21437 NK_API nk_bool 21438 nk_menu_begin_image_label(struct nk_context *ctx, 21439 const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size) 21440 { 21441 return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size); 21442 } 21443 NK_API nk_bool 21444 nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len, 21445 nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size) 21446 { 21447 struct nk_window *win; 21448 struct nk_rect header; 21449 const struct nk_input *in; 21450 int is_clicked = nk_false; 21451 nk_flags state; 21452 21453 NK_ASSERT(ctx); 21454 NK_ASSERT(ctx->current); 21455 NK_ASSERT(ctx->current->layout); 21456 if (!ctx || !ctx->current || !ctx->current->layout) 21457 return 0; 21458 21459 win = ctx->current; 21460 state = nk_widget(&header, ctx); 21461 if (!state) return 0; 21462 21463 in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 21464 if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, 21465 header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, 21466 ctx->style.font, in)) is_clicked = nk_true; 21467 return nk_menu_begin(ctx, win, title, is_clicked, header, size); 21468 } 21469 NK_API nk_bool 21470 nk_menu_begin_symbol_label(struct nk_context *ctx, 21471 const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size ) 21472 { 21473 return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size); 21474 } 21475 NK_API nk_bool 21476 nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align) 21477 { 21478 return nk_contextual_item_text(ctx, title, len, align); 21479 } 21480 NK_API nk_bool 21481 nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align) 21482 { 21483 return nk_contextual_item_label(ctx, label, align); 21484 } 21485 NK_API nk_bool 21486 nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img, 21487 const char *label, nk_flags align) 21488 { 21489 return nk_contextual_item_image_label(ctx, img, label, align); 21490 } 21491 NK_API nk_bool 21492 nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img, 21493 const char *text, int len, nk_flags align) 21494 { 21495 return nk_contextual_item_image_text(ctx, img, text, len, align); 21496 } 21497 NK_API nk_bool nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 21498 const char *text, int len, nk_flags align) 21499 { 21500 return nk_contextual_item_symbol_text(ctx, sym, text, len, align); 21501 } 21502 NK_API nk_bool nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 21503 const char *label, nk_flags align) 21504 { 21505 return nk_contextual_item_symbol_label(ctx, sym, label, align); 21506 } 21507 NK_API void nk_menu_close(struct nk_context *ctx) 21508 { 21509 nk_contextual_close(ctx); 21510 } 21511 NK_API void 21512 nk_menu_end(struct nk_context *ctx) 21513 { 21514 nk_contextual_end(ctx); 21515 } 21516 21517 21518 21519 21520 21521 /* =============================================================== 21522 * 21523 * LAYOUT 21524 * 21525 * ===============================================================*/ 21526 NK_API void 21527 nk_layout_set_min_row_height(struct nk_context *ctx, float height) 21528 { 21529 struct nk_window *win; 21530 struct nk_panel *layout; 21531 21532 NK_ASSERT(ctx); 21533 NK_ASSERT(ctx->current); 21534 NK_ASSERT(ctx->current->layout); 21535 if (!ctx || !ctx->current || !ctx->current->layout) 21536 return; 21537 21538 win = ctx->current; 21539 layout = win->layout; 21540 layout->row.min_height = height; 21541 } 21542 NK_API void 21543 nk_layout_reset_min_row_height(struct nk_context *ctx) 21544 { 21545 struct nk_window *win; 21546 struct nk_panel *layout; 21547 21548 NK_ASSERT(ctx); 21549 NK_ASSERT(ctx->current); 21550 NK_ASSERT(ctx->current->layout); 21551 if (!ctx || !ctx->current || !ctx->current->layout) 21552 return; 21553 21554 win = ctx->current; 21555 layout = win->layout; 21556 layout->row.min_height = ctx->style.font->height; 21557 layout->row.min_height += ctx->style.text.padding.y*2; 21558 layout->row.min_height += ctx->style.window.min_row_height_padding*2; 21559 } 21560 NK_LIB float 21561 nk_layout_row_calculate_usable_space(const struct nk_style *style, enum nk_panel_type type, 21562 float total_space, int columns) 21563 { 21564 float panel_spacing; 21565 float panel_space; 21566 21567 struct nk_vec2 spacing; 21568 21569 NK_UNUSED(type); 21570 21571 spacing = style->window.spacing; 21572 21573 /* calculate the usable panel space */ 21574 panel_spacing = (float)NK_MAX(columns - 1, 0) * spacing.x; 21575 panel_space = total_space - panel_spacing; 21576 return panel_space; 21577 } 21578 NK_LIB void 21579 nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, 21580 float height, int cols) 21581 { 21582 struct nk_panel *layout; 21583 const struct nk_style *style; 21584 struct nk_command_buffer *out; 21585 21586 struct nk_vec2 item_spacing; 21587 struct nk_color color; 21588 21589 NK_ASSERT(ctx); 21590 NK_ASSERT(ctx->current); 21591 NK_ASSERT(ctx->current->layout); 21592 if (!ctx || !ctx->current || !ctx->current->layout) 21593 return; 21594 21595 /* prefetch some configuration data */ 21596 layout = win->layout; 21597 style = &ctx->style; 21598 out = &win->buffer; 21599 color = style->window.background; 21600 item_spacing = style->window.spacing; 21601 21602 /* if one of these triggers you forgot to add an `if` condition around either 21603 a window, group, popup, combobox or contextual menu `begin` and `end` block. 21604 Example: 21605 if (nk_begin(...) {...} nk_end(...); or 21606 if (nk_group_begin(...) { nk_group_end(...);} */ 21607 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); 21608 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); 21609 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); 21610 21611 /* update the current row and set the current row layout */ 21612 layout->row.index = 0; 21613 layout->at_y += layout->row.height; 21614 layout->row.columns = cols; 21615 if (height == 0.0f) 21616 layout->row.height = NK_MAX(height, layout->row.min_height) + item_spacing.y; 21617 else layout->row.height = height + item_spacing.y; 21618 21619 layout->row.item_offset = 0; 21620 if (layout->flags & NK_WINDOW_DYNAMIC) { 21621 /* draw background for dynamic panels */ 21622 struct nk_rect background; 21623 background.x = win->bounds.x; 21624 background.w = win->bounds.w; 21625 background.y = layout->at_y - 1.0f; 21626 background.h = layout->row.height + 1.0f; 21627 nk_fill_rect(out, background, 0, color); 21628 } 21629 } 21630 NK_LIB void 21631 nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, 21632 float height, int cols, int width) 21633 { 21634 /* update the current row and set the current row layout */ 21635 struct nk_window *win; 21636 NK_ASSERT(ctx); 21637 NK_ASSERT(ctx->current); 21638 NK_ASSERT(ctx->current->layout); 21639 if (!ctx || !ctx->current || !ctx->current->layout) 21640 return; 21641 21642 win = ctx->current; 21643 nk_panel_layout(ctx, win, height, cols); 21644 if (fmt == NK_DYNAMIC) 21645 win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED; 21646 else win->layout->row.type = NK_LAYOUT_STATIC_FIXED; 21647 21648 win->layout->row.ratio = 0; 21649 win->layout->row.filled = 0; 21650 win->layout->row.item_offset = 0; 21651 win->layout->row.item_width = (float)width; 21652 } 21653 NK_API float 21654 nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width) 21655 { 21656 struct nk_window *win; 21657 NK_ASSERT(ctx); 21658 NK_ASSERT(pixel_width); 21659 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 21660 win = ctx->current; 21661 return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f); 21662 } 21663 NK_API void 21664 nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols) 21665 { 21666 nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0); 21667 } 21668 NK_API void 21669 nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols) 21670 { 21671 nk_row_layout(ctx, NK_STATIC, height, cols, item_width); 21672 } 21673 NK_API void 21674 nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, 21675 float row_height, int cols) 21676 { 21677 struct nk_window *win; 21678 struct nk_panel *layout; 21679 21680 NK_ASSERT(ctx); 21681 NK_ASSERT(ctx->current); 21682 NK_ASSERT(ctx->current->layout); 21683 if (!ctx || !ctx->current || !ctx->current->layout) 21684 return; 21685 21686 win = ctx->current; 21687 layout = win->layout; 21688 nk_panel_layout(ctx, win, row_height, cols); 21689 if (fmt == NK_DYNAMIC) 21690 layout->row.type = NK_LAYOUT_DYNAMIC_ROW; 21691 else layout->row.type = NK_LAYOUT_STATIC_ROW; 21692 21693 layout->row.ratio = 0; 21694 layout->row.filled = 0; 21695 layout->row.item_width = 0; 21696 layout->row.item_offset = 0; 21697 layout->row.columns = cols; 21698 } 21699 NK_API void 21700 nk_layout_row_push(struct nk_context *ctx, float ratio_or_width) 21701 { 21702 struct nk_window *win; 21703 struct nk_panel *layout; 21704 21705 NK_ASSERT(ctx); 21706 NK_ASSERT(ctx->current); 21707 NK_ASSERT(ctx->current->layout); 21708 if (!ctx || !ctx->current || !ctx->current->layout) 21709 return; 21710 21711 win = ctx->current; 21712 layout = win->layout; 21713 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW); 21714 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW) 21715 return; 21716 21717 if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) { 21718 float ratio = ratio_or_width; 21719 if ((ratio + layout->row.filled) > 1.0f) return; 21720 if (ratio > 0.0f) 21721 layout->row.item_width = NK_SATURATE(ratio); 21722 else layout->row.item_width = 1.0f - layout->row.filled; 21723 } else layout->row.item_width = ratio_or_width; 21724 } 21725 NK_API void 21726 nk_layout_row_end(struct nk_context *ctx) 21727 { 21728 struct nk_window *win; 21729 struct nk_panel *layout; 21730 21731 NK_ASSERT(ctx); 21732 NK_ASSERT(ctx->current); 21733 NK_ASSERT(ctx->current->layout); 21734 if (!ctx || !ctx->current || !ctx->current->layout) 21735 return; 21736 21737 win = ctx->current; 21738 layout = win->layout; 21739 NK_ASSERT(layout->row.type == NK_LAYOUT_STATIC_ROW || layout->row.type == NK_LAYOUT_DYNAMIC_ROW); 21740 if (layout->row.type != NK_LAYOUT_STATIC_ROW && layout->row.type != NK_LAYOUT_DYNAMIC_ROW) 21741 return; 21742 layout->row.item_width = 0; 21743 layout->row.item_offset = 0; 21744 } 21745 NK_API void 21746 nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt, 21747 float height, int cols, const float *ratio) 21748 { 21749 int i; 21750 int n_undef = 0; 21751 struct nk_window *win; 21752 struct nk_panel *layout; 21753 21754 NK_ASSERT(ctx); 21755 NK_ASSERT(ctx->current); 21756 NK_ASSERT(ctx->current->layout); 21757 if (!ctx || !ctx->current || !ctx->current->layout) 21758 return; 21759 21760 win = ctx->current; 21761 layout = win->layout; 21762 nk_panel_layout(ctx, win, height, cols); 21763 if (fmt == NK_DYNAMIC) { 21764 /* calculate width of undefined widget ratios */ 21765 float r = 0; 21766 layout->row.ratio = ratio; 21767 for (i = 0; i < cols; ++i) { 21768 if (ratio[i] < 0.0f) 21769 n_undef++; 21770 else r += ratio[i]; 21771 } 21772 r = NK_SATURATE(1.0f - r); 21773 layout->row.type = NK_LAYOUT_DYNAMIC; 21774 layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0; 21775 } else { 21776 layout->row.ratio = ratio; 21777 layout->row.type = NK_LAYOUT_STATIC; 21778 layout->row.item_width = 0; 21779 layout->row.item_offset = 0; 21780 } 21781 layout->row.item_offset = 0; 21782 layout->row.filled = 0; 21783 } 21784 NK_API void 21785 nk_layout_row_template_begin(struct nk_context *ctx, float height) 21786 { 21787 struct nk_window *win; 21788 struct nk_panel *layout; 21789 21790 NK_ASSERT(ctx); 21791 NK_ASSERT(ctx->current); 21792 NK_ASSERT(ctx->current->layout); 21793 if (!ctx || !ctx->current || !ctx->current->layout) 21794 return; 21795 21796 win = ctx->current; 21797 layout = win->layout; 21798 nk_panel_layout(ctx, win, height, 1); 21799 layout->row.type = NK_LAYOUT_TEMPLATE; 21800 layout->row.columns = 0; 21801 layout->row.ratio = 0; 21802 layout->row.item_width = 0; 21803 layout->row.item_height = 0; 21804 layout->row.item_offset = 0; 21805 layout->row.filled = 0; 21806 layout->row.item.x = 0; 21807 layout->row.item.y = 0; 21808 layout->row.item.w = 0; 21809 layout->row.item.h = 0; 21810 } 21811 NK_API void 21812 nk_layout_row_template_push_dynamic(struct nk_context *ctx) 21813 { 21814 struct nk_window *win; 21815 struct nk_panel *layout; 21816 21817 NK_ASSERT(ctx); 21818 NK_ASSERT(ctx->current); 21819 NK_ASSERT(ctx->current->layout); 21820 if (!ctx || !ctx->current || !ctx->current->layout) 21821 return; 21822 21823 win = ctx->current; 21824 layout = win->layout; 21825 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 21826 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 21827 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 21828 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 21829 layout->row.templates[layout->row.columns++] = -1.0f; 21830 } 21831 NK_API void 21832 nk_layout_row_template_push_variable(struct nk_context *ctx, float min_width) 21833 { 21834 struct nk_window *win; 21835 struct nk_panel *layout; 21836 21837 NK_ASSERT(ctx); 21838 NK_ASSERT(ctx->current); 21839 NK_ASSERT(ctx->current->layout); 21840 if (!ctx || !ctx->current || !ctx->current->layout) 21841 return; 21842 21843 win = ctx->current; 21844 layout = win->layout; 21845 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 21846 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 21847 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 21848 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 21849 layout->row.templates[layout->row.columns++] = -min_width; 21850 } 21851 NK_API void 21852 nk_layout_row_template_push_static(struct nk_context *ctx, float width) 21853 { 21854 struct nk_window *win; 21855 struct nk_panel *layout; 21856 21857 NK_ASSERT(ctx); 21858 NK_ASSERT(ctx->current); 21859 NK_ASSERT(ctx->current->layout); 21860 if (!ctx || !ctx->current || !ctx->current->layout) 21861 return; 21862 21863 win = ctx->current; 21864 layout = win->layout; 21865 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 21866 NK_ASSERT(layout->row.columns < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 21867 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 21868 if (layout->row.columns >= NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS) return; 21869 layout->row.templates[layout->row.columns++] = width; 21870 } 21871 NK_API void 21872 nk_layout_row_template_end(struct nk_context *ctx) 21873 { 21874 struct nk_window *win; 21875 struct nk_panel *layout; 21876 21877 int i = 0; 21878 int variable_count = 0; 21879 int min_variable_count = 0; 21880 float min_fixed_width = 0.0f; 21881 float total_fixed_width = 0.0f; 21882 float max_variable_width = 0.0f; 21883 21884 NK_ASSERT(ctx); 21885 NK_ASSERT(ctx->current); 21886 NK_ASSERT(ctx->current->layout); 21887 if (!ctx || !ctx->current || !ctx->current->layout) 21888 return; 21889 21890 win = ctx->current; 21891 layout = win->layout; 21892 NK_ASSERT(layout->row.type == NK_LAYOUT_TEMPLATE); 21893 if (layout->row.type != NK_LAYOUT_TEMPLATE) return; 21894 for (i = 0; i < layout->row.columns; ++i) { 21895 float width = layout->row.templates[i]; 21896 if (width >= 0.0f) { 21897 total_fixed_width += width; 21898 min_fixed_width += width; 21899 } else if (width < -1.0f) { 21900 width = -width; 21901 total_fixed_width += width; 21902 max_variable_width = NK_MAX(max_variable_width, width); 21903 variable_count++; 21904 } else { 21905 min_variable_count++; 21906 variable_count++; 21907 } 21908 } 21909 if (variable_count) { 21910 float space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, 21911 layout->bounds.w, layout->row.columns); 21912 float var_width = (NK_MAX(space-min_fixed_width,0.0f)) / (float)variable_count; 21913 int enough_space = var_width >= max_variable_width; 21914 if (!enough_space) 21915 var_width = (NK_MAX(space-total_fixed_width,0)) / (float)min_variable_count; 21916 for (i = 0; i < layout->row.columns; ++i) { 21917 float *width = &layout->row.templates[i]; 21918 *width = (*width >= 0.0f)? *width: (*width < -1.0f && !enough_space)? -(*width): var_width; 21919 } 21920 } 21921 } 21922 NK_API void 21923 nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt, 21924 float height, int widget_count) 21925 { 21926 struct nk_window *win; 21927 struct nk_panel *layout; 21928 21929 NK_ASSERT(ctx); 21930 NK_ASSERT(ctx->current); 21931 NK_ASSERT(ctx->current->layout); 21932 if (!ctx || !ctx->current || !ctx->current->layout) 21933 return; 21934 21935 win = ctx->current; 21936 layout = win->layout; 21937 nk_panel_layout(ctx, win, height, widget_count); 21938 if (fmt == NK_STATIC) 21939 layout->row.type = NK_LAYOUT_STATIC_FREE; 21940 else layout->row.type = NK_LAYOUT_DYNAMIC_FREE; 21941 21942 layout->row.ratio = 0; 21943 layout->row.filled = 0; 21944 layout->row.item_width = 0; 21945 layout->row.item_offset = 0; 21946 } 21947 NK_API void 21948 nk_layout_space_end(struct nk_context *ctx) 21949 { 21950 struct nk_window *win; 21951 struct nk_panel *layout; 21952 21953 NK_ASSERT(ctx); 21954 NK_ASSERT(ctx->current); 21955 NK_ASSERT(ctx->current->layout); 21956 if (!ctx || !ctx->current || !ctx->current->layout) 21957 return; 21958 21959 win = ctx->current; 21960 layout = win->layout; 21961 layout->row.item_width = 0; 21962 layout->row.item_height = 0; 21963 layout->row.item_offset = 0; 21964 nk_zero(&layout->row.item, sizeof(layout->row.item)); 21965 } 21966 NK_API void 21967 nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect) 21968 { 21969 struct nk_window *win; 21970 struct nk_panel *layout; 21971 21972 NK_ASSERT(ctx); 21973 NK_ASSERT(ctx->current); 21974 NK_ASSERT(ctx->current->layout); 21975 if (!ctx || !ctx->current || !ctx->current->layout) 21976 return; 21977 21978 win = ctx->current; 21979 layout = win->layout; 21980 layout->row.item = rect; 21981 } 21982 NK_API struct nk_rect 21983 nk_layout_space_bounds(struct nk_context *ctx) 21984 { 21985 struct nk_rect ret; 21986 struct nk_window *win; 21987 struct nk_panel *layout; 21988 21989 NK_ASSERT(ctx); 21990 NK_ASSERT(ctx->current); 21991 NK_ASSERT(ctx->current->layout); 21992 win = ctx->current; 21993 layout = win->layout; 21994 21995 ret.x = layout->clip.x; 21996 ret.y = layout->clip.y; 21997 ret.w = layout->clip.w; 21998 ret.h = layout->row.height; 21999 return ret; 22000 } 22001 NK_API struct nk_rect 22002 nk_layout_widget_bounds(struct nk_context *ctx) 22003 { 22004 struct nk_rect ret; 22005 struct nk_window *win; 22006 struct nk_panel *layout; 22007 22008 NK_ASSERT(ctx); 22009 NK_ASSERT(ctx->current); 22010 NK_ASSERT(ctx->current->layout); 22011 win = ctx->current; 22012 layout = win->layout; 22013 22014 ret.x = layout->at_x; 22015 ret.y = layout->at_y; 22016 ret.w = layout->bounds.w - NK_MAX(layout->at_x - layout->bounds.x,0); 22017 ret.h = layout->row.height; 22018 return ret; 22019 } 22020 NK_API struct nk_vec2 22021 nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret) 22022 { 22023 struct nk_window *win; 22024 struct nk_panel *layout; 22025 22026 NK_ASSERT(ctx); 22027 NK_ASSERT(ctx->current); 22028 NK_ASSERT(ctx->current->layout); 22029 win = ctx->current; 22030 layout = win->layout; 22031 22032 ret.x += layout->at_x - (float)*layout->offset_x; 22033 ret.y += layout->at_y - (float)*layout->offset_y; 22034 return ret; 22035 } 22036 NK_API struct nk_vec2 22037 nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret) 22038 { 22039 struct nk_window *win; 22040 struct nk_panel *layout; 22041 22042 NK_ASSERT(ctx); 22043 NK_ASSERT(ctx->current); 22044 NK_ASSERT(ctx->current->layout); 22045 win = ctx->current; 22046 layout = win->layout; 22047 22048 ret.x += -layout->at_x + (float)*layout->offset_x; 22049 ret.y += -layout->at_y + (float)*layout->offset_y; 22050 return ret; 22051 } 22052 NK_API struct nk_rect 22053 nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret) 22054 { 22055 struct nk_window *win; 22056 struct nk_panel *layout; 22057 22058 NK_ASSERT(ctx); 22059 NK_ASSERT(ctx->current); 22060 NK_ASSERT(ctx->current->layout); 22061 win = ctx->current; 22062 layout = win->layout; 22063 22064 ret.x += layout->at_x - (float)*layout->offset_x; 22065 ret.y += layout->at_y - (float)*layout->offset_y; 22066 return ret; 22067 } 22068 NK_API struct nk_rect 22069 nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret) 22070 { 22071 struct nk_window *win; 22072 struct nk_panel *layout; 22073 22074 NK_ASSERT(ctx); 22075 NK_ASSERT(ctx->current); 22076 NK_ASSERT(ctx->current->layout); 22077 win = ctx->current; 22078 layout = win->layout; 22079 22080 ret.x += -layout->at_x + (float)*layout->offset_x; 22081 ret.y += -layout->at_y + (float)*layout->offset_y; 22082 return ret; 22083 } 22084 NK_LIB void 22085 nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win) 22086 { 22087 struct nk_panel *layout = win->layout; 22088 struct nk_vec2 spacing = ctx->style.window.spacing; 22089 const float row_height = layout->row.height - spacing.y; 22090 nk_panel_layout(ctx, win, row_height, layout->row.columns); 22091 } 22092 NK_LIB void 22093 nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, 22094 struct nk_window *win, int modify) 22095 { 22096 struct nk_panel *layout; 22097 const struct nk_style *style; 22098 22099 struct nk_vec2 spacing; 22100 22101 float item_offset = 0; 22102 float item_width = 0; 22103 float item_spacing = 0; 22104 float panel_space = 0; 22105 22106 NK_ASSERT(ctx); 22107 NK_ASSERT(ctx->current); 22108 NK_ASSERT(ctx->current->layout); 22109 if (!ctx || !ctx->current || !ctx->current->layout) 22110 return; 22111 22112 win = ctx->current; 22113 layout = win->layout; 22114 style = &ctx->style; 22115 NK_ASSERT(bounds); 22116 22117 spacing = style->window.spacing; 22118 panel_space = nk_layout_row_calculate_usable_space(&ctx->style, layout->type, 22119 layout->bounds.w, layout->row.columns); 22120 22121 #define NK_FRAC(x) (x - (float)(int)x) /* will be used to remove fookin gaps */ 22122 /* calculate the width of one item inside the current layout space */ 22123 switch (layout->row.type) { 22124 case NK_LAYOUT_DYNAMIC_FIXED: { 22125 /* scaling fixed size widgets item width */ 22126 float w = NK_MAX(1.0f,panel_space) / (float)layout->row.columns; 22127 item_offset = (float)layout->row.index * w; 22128 item_width = w + NK_FRAC(item_offset); 22129 item_spacing = (float)layout->row.index * spacing.x; 22130 } break; 22131 case NK_LAYOUT_DYNAMIC_ROW: { 22132 /* scaling single ratio widget width */ 22133 float w = layout->row.item_width * panel_space; 22134 item_offset = layout->row.item_offset; 22135 item_width = w + NK_FRAC(item_offset); 22136 item_spacing = 0; 22137 22138 if (modify) { 22139 layout->row.item_offset += w + spacing.x; 22140 layout->row.filled += layout->row.item_width; 22141 layout->row.index = 0; 22142 } 22143 } break; 22144 case NK_LAYOUT_DYNAMIC_FREE: { 22145 /* panel width depended free widget placing */ 22146 bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x); 22147 bounds->x -= (float)*layout->offset_x; 22148 bounds->y = layout->at_y + (layout->row.height * layout->row.item.y); 22149 bounds->y -= (float)*layout->offset_y; 22150 bounds->w = layout->bounds.w * layout->row.item.w + NK_FRAC(bounds->x); 22151 bounds->h = layout->row.height * layout->row.item.h + NK_FRAC(bounds->y); 22152 return; 22153 } 22154 case NK_LAYOUT_DYNAMIC: { 22155 /* scaling arrays of panel width ratios for every widget */ 22156 float ratio, w; 22157 NK_ASSERT(layout->row.ratio); 22158 ratio = (layout->row.ratio[layout->row.index] < 0) ? 22159 layout->row.item_width : layout->row.ratio[layout->row.index]; 22160 22161 w = (ratio * panel_space); 22162 item_spacing = (float)layout->row.index * spacing.x; 22163 item_offset = layout->row.item_offset; 22164 item_width = w + NK_FRAC(item_offset); 22165 22166 if (modify) { 22167 layout->row.item_offset += w; 22168 layout->row.filled += ratio; 22169 } 22170 } break; 22171 case NK_LAYOUT_STATIC_FIXED: { 22172 /* non-scaling fixed widgets item width */ 22173 item_width = layout->row.item_width; 22174 item_offset = (float)layout->row.index * item_width; 22175 item_spacing = (float)layout->row.index * spacing.x; 22176 } break; 22177 case NK_LAYOUT_STATIC_ROW: { 22178 /* scaling single ratio widget width */ 22179 item_width = layout->row.item_width; 22180 item_offset = layout->row.item_offset; 22181 item_spacing = (float)layout->row.index * spacing.x; 22182 if (modify) layout->row.item_offset += item_width; 22183 } break; 22184 case NK_LAYOUT_STATIC_FREE: { 22185 /* free widget placing */ 22186 bounds->x = layout->at_x + layout->row.item.x; 22187 bounds->w = layout->row.item.w; 22188 if (((bounds->x + bounds->w) > layout->max_x) && modify) 22189 layout->max_x = (bounds->x + bounds->w); 22190 bounds->x -= (float)*layout->offset_x; 22191 bounds->y = layout->at_y + layout->row.item.y; 22192 bounds->y -= (float)*layout->offset_y; 22193 bounds->h = layout->row.item.h; 22194 return; 22195 } 22196 case NK_LAYOUT_STATIC: { 22197 /* non-scaling array of panel pixel width for every widget */ 22198 item_spacing = (float)layout->row.index * spacing.x; 22199 item_width = layout->row.ratio[layout->row.index]; 22200 item_offset = layout->row.item_offset; 22201 if (modify) layout->row.item_offset += item_width; 22202 } break; 22203 case NK_LAYOUT_TEMPLATE: { 22204 /* stretchy row layout with combined dynamic/static widget width*/ 22205 float w; 22206 NK_ASSERT(layout->row.index < layout->row.columns); 22207 NK_ASSERT(layout->row.index < NK_MAX_LAYOUT_ROW_TEMPLATE_COLUMNS); 22208 w = layout->row.templates[layout->row.index]; 22209 item_offset = layout->row.item_offset; 22210 item_width = w + NK_FRAC(item_offset); 22211 item_spacing = (float)layout->row.index * spacing.x; 22212 if (modify) layout->row.item_offset += w; 22213 } break; 22214 #undef NK_FRAC 22215 default: NK_ASSERT(0); break; 22216 }; 22217 22218 /* set the bounds of the newly allocated widget */ 22219 bounds->w = item_width; 22220 bounds->h = layout->row.height - spacing.y; 22221 bounds->y = layout->at_y - (float)*layout->offset_y; 22222 bounds->x = layout->at_x + item_offset + item_spacing; 22223 if (((bounds->x + bounds->w) > layout->max_x) && modify) 22224 layout->max_x = bounds->x + bounds->w; 22225 bounds->x -= (float)*layout->offset_x; 22226 } 22227 NK_LIB void 22228 nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx) 22229 { 22230 struct nk_window *win; 22231 struct nk_panel *layout; 22232 22233 NK_ASSERT(ctx); 22234 NK_ASSERT(ctx->current); 22235 NK_ASSERT(ctx->current->layout); 22236 if (!ctx || !ctx->current || !ctx->current->layout) 22237 return; 22238 22239 /* check if the end of the row has been hit and begin new row if so */ 22240 win = ctx->current; 22241 layout = win->layout; 22242 if (layout->row.index >= layout->row.columns) 22243 nk_panel_alloc_row(ctx, win); 22244 22245 /* calculate widget position and size */ 22246 nk_layout_widget_space(bounds, ctx, win, nk_true); 22247 layout->row.index++; 22248 } 22249 NK_LIB void 22250 nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx) 22251 { 22252 float y; 22253 int index; 22254 struct nk_window *win; 22255 struct nk_panel *layout; 22256 22257 NK_ASSERT(ctx); 22258 NK_ASSERT(ctx->current); 22259 NK_ASSERT(ctx->current->layout); 22260 if (!ctx || !ctx->current || !ctx->current->layout) { 22261 *bounds = nk_rect(0,0,0,0); 22262 return; 22263 } 22264 22265 win = ctx->current; 22266 layout = win->layout; 22267 y = layout->at_y; 22268 index = layout->row.index; 22269 if (layout->row.index >= layout->row.columns) { 22270 layout->at_y += layout->row.height; 22271 layout->row.index = 0; 22272 } 22273 nk_layout_widget_space(bounds, ctx, win, nk_false); 22274 if (!layout->row.index) { 22275 bounds->x -= layout->row.item_offset; 22276 } 22277 layout->at_y = y; 22278 layout->row.index = index; 22279 } 22280 NK_API void 22281 nk_spacer(struct nk_context *ctx ) 22282 { 22283 struct nk_rect dummy_rect = { 0, 0, 0, 0 }; 22284 nk_panel_alloc_space( &dummy_rect, ctx ); 22285 } 22286 22287 22288 22289 22290 /* =============================================================== 22291 * 22292 * TREE 22293 * 22294 * ===============================================================*/ 22295 NK_INTERN int 22296 nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type, 22297 struct nk_image *img, const char *title, enum nk_collapse_states *state) 22298 { 22299 struct nk_window *win; 22300 struct nk_panel *layout; 22301 const struct nk_style *style; 22302 struct nk_command_buffer *out; 22303 const struct nk_input *in; 22304 const struct nk_style_button *button; 22305 enum nk_symbol_type symbol; 22306 float row_height; 22307 22308 struct nk_vec2 item_spacing; 22309 struct nk_rect header = {0,0,0,0}; 22310 struct nk_rect sym = {0,0,0,0}; 22311 struct nk_text text; 22312 22313 nk_flags ws = 0; 22314 enum nk_widget_layout_states widget_state; 22315 22316 NK_ASSERT(ctx); 22317 NK_ASSERT(ctx->current); 22318 NK_ASSERT(ctx->current->layout); 22319 if (!ctx || !ctx->current || !ctx->current->layout) 22320 return 0; 22321 22322 /* cache some data */ 22323 win = ctx->current; 22324 layout = win->layout; 22325 out = &win->buffer; 22326 style = &ctx->style; 22327 item_spacing = style->window.spacing; 22328 22329 /* calculate header bounds and draw background */ 22330 row_height = style->font->height + 2 * style->tab.padding.y; 22331 nk_layout_set_min_row_height(ctx, row_height); 22332 nk_layout_row_dynamic(ctx, row_height, 1); 22333 nk_layout_reset_min_row_height(ctx); 22334 22335 widget_state = nk_widget(&header, ctx); 22336 if (type == NK_TREE_TAB) { 22337 const struct nk_style_item *background = &style->tab.background; 22338 22339 switch(background->type) { 22340 case NK_STYLE_ITEM_IMAGE: 22341 nk_draw_image(out, header, &background->data.image, nk_white); 22342 break; 22343 case NK_STYLE_ITEM_NINE_SLICE: 22344 nk_draw_nine_slice(out, header, &background->data.slice, nk_white); 22345 break; 22346 case NK_STYLE_ITEM_COLOR: 22347 nk_fill_rect(out, header, 0, style->tab.border_color); 22348 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border), 22349 style->tab.rounding, background->data.color); 22350 break; 22351 } 22352 } else text.background = style->window.background; 22353 22354 /* update node state */ 22355 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0; 22356 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0; 22357 if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT)) 22358 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED; 22359 22360 /* select correct button style */ 22361 if (*state == NK_MAXIMIZED) { 22362 symbol = style->tab.sym_maximize; 22363 if (type == NK_TREE_TAB) 22364 button = &style->tab.tab_maximize_button; 22365 else button = &style->tab.node_maximize_button; 22366 } else { 22367 symbol = style->tab.sym_minimize; 22368 if (type == NK_TREE_TAB) 22369 button = &style->tab.tab_minimize_button; 22370 else button = &style->tab.node_minimize_button; 22371 } 22372 22373 {/* draw triangle button */ 22374 sym.w = sym.h = style->font->height; 22375 sym.y = header.y + style->tab.padding.y; 22376 sym.x = header.x + style->tab.padding.x; 22377 nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, 22378 button, 0, style->font); 22379 22380 if (img) { 22381 /* draw optional image icon */ 22382 sym.x = sym.x + sym.w + 4 * item_spacing.x; 22383 nk_draw_image(&win->buffer, sym, img, nk_white); 22384 sym.w = style->font->height + style->tab.spacing.x;} 22385 } 22386 22387 {/* draw label */ 22388 struct nk_rect label; 22389 header.w = NK_MAX(header.w, sym.w + item_spacing.x); 22390 label.x = sym.x + sym.w + item_spacing.x; 22391 label.y = sym.y; 22392 label.w = header.w - (sym.w + item_spacing.y + style->tab.indent); 22393 label.h = style->font->height; 22394 text.text = style->tab.text; 22395 text.padding = nk_vec2(0,0); 22396 nk_widget_text(out, label, title, nk_strlen(title), &text, 22397 NK_TEXT_LEFT, style->font);} 22398 22399 /* increase x-axis cursor widget position pointer */ 22400 if (*state == NK_MAXIMIZED) { 22401 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent; 22402 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent); 22403 layout->bounds.w -= (style->tab.indent + style->window.padding.x); 22404 layout->row.tree_depth++; 22405 return nk_true; 22406 } else return nk_false; 22407 } 22408 NK_INTERN int 22409 nk_tree_base(struct nk_context *ctx, enum nk_tree_type type, 22410 struct nk_image *img, const char *title, enum nk_collapse_states initial_state, 22411 const char *hash, int len, int line) 22412 { 22413 struct nk_window *win = ctx->current; 22414 int title_len = 0; 22415 nk_hash tree_hash = 0; 22416 nk_uint *state = 0; 22417 22418 /* retrieve tree state from internal widget state tables */ 22419 if (!hash) { 22420 title_len = (int)nk_strlen(title); 22421 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line); 22422 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line); 22423 state = nk_find_value(win, tree_hash); 22424 if (!state) { 22425 state = nk_add_value(ctx, win, tree_hash, 0); 22426 *state = initial_state; 22427 } 22428 return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state); 22429 } 22430 NK_API nk_bool 22431 nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type, 22432 const char *title, enum nk_collapse_states *state) 22433 { 22434 return nk_tree_state_base(ctx, type, 0, title, state); 22435 } 22436 NK_API nk_bool 22437 nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type, 22438 struct nk_image img, const char *title, enum nk_collapse_states *state) 22439 { 22440 return nk_tree_state_base(ctx, type, &img, title, state); 22441 } 22442 NK_API void 22443 nk_tree_state_pop(struct nk_context *ctx) 22444 { 22445 struct nk_window *win = 0; 22446 struct nk_panel *layout = 0; 22447 22448 NK_ASSERT(ctx); 22449 NK_ASSERT(ctx->current); 22450 NK_ASSERT(ctx->current->layout); 22451 if (!ctx || !ctx->current || !ctx->current->layout) 22452 return; 22453 22454 win = ctx->current; 22455 layout = win->layout; 22456 layout->at_x -= ctx->style.tab.indent + (float)*layout->offset_x; 22457 layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x; 22458 NK_ASSERT(layout->row.tree_depth); 22459 layout->row.tree_depth--; 22460 } 22461 NK_API nk_bool 22462 nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 22463 const char *title, enum nk_collapse_states initial_state, 22464 const char *hash, int len, int line) 22465 { 22466 return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line); 22467 } 22468 NK_API nk_bool 22469 nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 22470 struct nk_image img, const char *title, enum nk_collapse_states initial_state, 22471 const char *hash, int len,int seed) 22472 { 22473 return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed); 22474 } 22475 NK_API void 22476 nk_tree_pop(struct nk_context *ctx) 22477 { 22478 nk_tree_state_pop(ctx); 22479 } 22480 NK_INTERN int 22481 nk_tree_element_image_push_hashed_base(struct nk_context *ctx, enum nk_tree_type type, 22482 struct nk_image *img, const char *title, int title_len, 22483 enum nk_collapse_states *state, nk_bool *selected) 22484 { 22485 struct nk_window *win; 22486 struct nk_panel *layout; 22487 const struct nk_style *style; 22488 struct nk_command_buffer *out; 22489 const struct nk_input *in; 22490 const struct nk_style_button *button; 22491 enum nk_symbol_type symbol; 22492 float row_height; 22493 struct nk_vec2 padding; 22494 22495 int text_len; 22496 float text_width; 22497 22498 struct nk_vec2 item_spacing; 22499 struct nk_rect header = {0,0,0,0}; 22500 struct nk_rect sym = {0,0,0,0}; 22501 22502 nk_flags ws = 0; 22503 enum nk_widget_layout_states widget_state; 22504 22505 NK_ASSERT(ctx); 22506 NK_ASSERT(ctx->current); 22507 NK_ASSERT(ctx->current->layout); 22508 if (!ctx || !ctx->current || !ctx->current->layout) 22509 return 0; 22510 22511 /* cache some data */ 22512 win = ctx->current; 22513 layout = win->layout; 22514 out = &win->buffer; 22515 style = &ctx->style; 22516 item_spacing = style->window.spacing; 22517 padding = style->selectable.padding; 22518 22519 /* calculate header bounds and draw background */ 22520 row_height = style->font->height + 2 * style->tab.padding.y; 22521 nk_layout_set_min_row_height(ctx, row_height); 22522 nk_layout_row_dynamic(ctx, row_height, 1); 22523 nk_layout_reset_min_row_height(ctx); 22524 22525 widget_state = nk_widget(&header, ctx); 22526 if (type == NK_TREE_TAB) { 22527 const struct nk_style_item *background = &style->tab.background; 22528 22529 switch (background->type) { 22530 case NK_STYLE_ITEM_IMAGE: 22531 nk_draw_image(out, header, &background->data.image, nk_white); 22532 break; 22533 case NK_STYLE_ITEM_NINE_SLICE: 22534 nk_draw_nine_slice(out, header, &background->data.slice, nk_white); 22535 break; 22536 case NK_STYLE_ITEM_COLOR: 22537 nk_fill_rect(out, header, 0, style->tab.border_color); 22538 nk_fill_rect(out, nk_shrink_rect(header, style->tab.border), 22539 style->tab.rounding, background->data.color); 22540 break; 22541 } 22542 } 22543 22544 in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0; 22545 in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0; 22546 22547 /* select correct button style */ 22548 if (*state == NK_MAXIMIZED) { 22549 symbol = style->tab.sym_maximize; 22550 if (type == NK_TREE_TAB) 22551 button = &style->tab.tab_maximize_button; 22552 else button = &style->tab.node_maximize_button; 22553 } else { 22554 symbol = style->tab.sym_minimize; 22555 if (type == NK_TREE_TAB) 22556 button = &style->tab.tab_minimize_button; 22557 else button = &style->tab.node_minimize_button; 22558 } 22559 {/* draw triangle button */ 22560 sym.w = sym.h = style->font->height; 22561 sym.y = header.y + style->tab.padding.y; 22562 sym.x = header.x + style->tab.padding.x; 22563 if (nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, button, in, style->font)) 22564 *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED;} 22565 22566 /* draw label */ 22567 {nk_flags dummy = 0; 22568 struct nk_rect label; 22569 /* calculate size of the text and tooltip */ 22570 text_len = nk_strlen(title); 22571 text_width = style->font->width(style->font->userdata, style->font->height, title, text_len); 22572 text_width += (4 * padding.x); 22573 22574 header.w = NK_MAX(header.w, sym.w + item_spacing.x); 22575 label.x = sym.x + sym.w + item_spacing.x; 22576 label.y = sym.y; 22577 label.w = NK_MIN(header.w - (sym.w + item_spacing.y + style->tab.indent), text_width); 22578 label.h = style->font->height; 22579 22580 if (img) { 22581 nk_do_selectable_image(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT, 22582 selected, img, &style->selectable, in, style->font); 22583 } else nk_do_selectable(&dummy, &win->buffer, label, title, title_len, NK_TEXT_LEFT, 22584 selected, &style->selectable, in, style->font); 22585 } 22586 /* increase x-axis cursor widget position pointer */ 22587 if (*state == NK_MAXIMIZED) { 22588 layout->at_x = header.x + (float)*layout->offset_x + style->tab.indent; 22589 layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent); 22590 layout->bounds.w -= (style->tab.indent + style->window.padding.x); 22591 layout->row.tree_depth++; 22592 return nk_true; 22593 } else return nk_false; 22594 } 22595 NK_INTERN int 22596 nk_tree_element_base(struct nk_context *ctx, enum nk_tree_type type, 22597 struct nk_image *img, const char *title, enum nk_collapse_states initial_state, 22598 nk_bool *selected, const char *hash, int len, int line) 22599 { 22600 struct nk_window *win = ctx->current; 22601 int title_len = 0; 22602 nk_hash tree_hash = 0; 22603 nk_uint *state = 0; 22604 22605 /* retrieve tree state from internal widget state tables */ 22606 if (!hash) { 22607 title_len = (int)nk_strlen(title); 22608 tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line); 22609 } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line); 22610 state = nk_find_value(win, tree_hash); 22611 if (!state) { 22612 state = nk_add_value(ctx, win, tree_hash, 0); 22613 *state = initial_state; 22614 } return nk_tree_element_image_push_hashed_base(ctx, type, img, title, 22615 nk_strlen(title), (enum nk_collapse_states*)state, selected); 22616 } 22617 NK_API nk_bool 22618 nk_tree_element_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 22619 const char *title, enum nk_collapse_states initial_state, 22620 nk_bool *selected, const char *hash, int len, int seed) 22621 { 22622 return nk_tree_element_base(ctx, type, 0, title, initial_state, selected, hash, len, seed); 22623 } 22624 NK_API nk_bool 22625 nk_tree_element_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type, 22626 struct nk_image img, const char *title, enum nk_collapse_states initial_state, 22627 nk_bool *selected, const char *hash, int len,int seed) 22628 { 22629 return nk_tree_element_base(ctx, type, &img, title, initial_state, selected, hash, len, seed); 22630 } 22631 NK_API void 22632 nk_tree_element_pop(struct nk_context *ctx) 22633 { 22634 nk_tree_state_pop(ctx); 22635 } 22636 22637 22638 22639 22640 22641 /* =============================================================== 22642 * 22643 * GROUP 22644 * 22645 * ===============================================================*/ 22646 NK_API nk_bool 22647 nk_group_scrolled_offset_begin(struct nk_context *ctx, 22648 nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags) 22649 { 22650 struct nk_rect bounds; 22651 struct nk_window panel; 22652 struct nk_window *win; 22653 22654 win = ctx->current; 22655 nk_panel_alloc_space(&bounds, ctx); 22656 {const struct nk_rect *c = &win->layout->clip; 22657 if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) && 22658 !(flags & NK_WINDOW_MOVABLE)) { 22659 return 0; 22660 }} 22661 if (win->flags & NK_WINDOW_ROM) 22662 flags |= NK_WINDOW_ROM; 22663 22664 /* initialize a fake window to create the panel from */ 22665 nk_zero(&panel, sizeof(panel)); 22666 panel.bounds = bounds; 22667 panel.flags = flags; 22668 panel.scrollbar.x = *x_offset; 22669 panel.scrollbar.y = *y_offset; 22670 panel.buffer = win->buffer; 22671 panel.layout = (struct nk_panel*)nk_create_panel(ctx); 22672 ctx->current = &panel; 22673 nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP); 22674 22675 win->buffer = panel.buffer; 22676 win->buffer.clip = panel.layout->clip; 22677 panel.layout->offset_x = x_offset; 22678 panel.layout->offset_y = y_offset; 22679 panel.layout->parent = win->layout; 22680 win->layout = panel.layout; 22681 22682 ctx->current = win; 22683 if ((panel.layout->flags & NK_WINDOW_CLOSED) || 22684 (panel.layout->flags & NK_WINDOW_MINIMIZED)) 22685 { 22686 nk_flags f = panel.layout->flags; 22687 nk_group_scrolled_end(ctx); 22688 if (f & NK_WINDOW_CLOSED) 22689 return NK_WINDOW_CLOSED; 22690 if (f & NK_WINDOW_MINIMIZED) 22691 return NK_WINDOW_MINIMIZED; 22692 } 22693 return 1; 22694 } 22695 NK_API void 22696 nk_group_scrolled_end(struct nk_context *ctx) 22697 { 22698 struct nk_window *win; 22699 struct nk_panel *parent; 22700 struct nk_panel *g; 22701 22702 struct nk_rect clip; 22703 struct nk_window pan; 22704 struct nk_vec2 panel_padding; 22705 22706 NK_ASSERT(ctx); 22707 NK_ASSERT(ctx->current); 22708 if (!ctx || !ctx->current) 22709 return; 22710 22711 /* make sure nk_group_begin was called correctly */ 22712 NK_ASSERT(ctx->current); 22713 win = ctx->current; 22714 NK_ASSERT(win->layout); 22715 g = win->layout; 22716 NK_ASSERT(g->parent); 22717 parent = g->parent; 22718 22719 /* dummy window */ 22720 nk_zero_struct(pan); 22721 panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP); 22722 pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h); 22723 pan.bounds.x = g->bounds.x - panel_padding.x; 22724 pan.bounds.w = g->bounds.w + 2 * panel_padding.x; 22725 pan.bounds.h = g->bounds.h + g->header_height + g->menu.h; 22726 if (g->flags & NK_WINDOW_BORDER) { 22727 pan.bounds.x -= g->border; 22728 pan.bounds.y -= g->border; 22729 pan.bounds.w += 2*g->border; 22730 pan.bounds.h += 2*g->border; 22731 } 22732 if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) { 22733 pan.bounds.w += ctx->style.window.scrollbar_size.x; 22734 pan.bounds.h += ctx->style.window.scrollbar_size.y; 22735 } 22736 pan.scrollbar.x = *g->offset_x; 22737 pan.scrollbar.y = *g->offset_y; 22738 pan.flags = g->flags; 22739 pan.buffer = win->buffer; 22740 pan.layout = g; 22741 pan.parent = win; 22742 ctx->current = &pan; 22743 22744 /* make sure group has correct clipping rectangle */ 22745 nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y, 22746 pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x); 22747 nk_push_scissor(&pan.buffer, clip); 22748 nk_end(ctx); 22749 22750 win->buffer = pan.buffer; 22751 nk_push_scissor(&win->buffer, parent->clip); 22752 ctx->current = win; 22753 win->layout = parent; 22754 g->bounds = pan.bounds; 22755 return; 22756 } 22757 NK_API nk_bool 22758 nk_group_scrolled_begin(struct nk_context *ctx, 22759 struct nk_scroll *scroll, const char *title, nk_flags flags) 22760 { 22761 return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags); 22762 } 22763 NK_API nk_bool 22764 nk_group_begin_titled(struct nk_context *ctx, const char *id, 22765 const char *title, nk_flags flags) 22766 { 22767 int id_len; 22768 nk_hash id_hash; 22769 struct nk_window *win; 22770 nk_uint *x_offset; 22771 nk_uint *y_offset; 22772 22773 NK_ASSERT(ctx); 22774 NK_ASSERT(id); 22775 NK_ASSERT(ctx->current); 22776 NK_ASSERT(ctx->current->layout); 22777 if (!ctx || !ctx->current || !ctx->current->layout || !id) 22778 return 0; 22779 22780 /* find persistent group scrollbar value */ 22781 win = ctx->current; 22782 id_len = (int)nk_strlen(id); 22783 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); 22784 x_offset = nk_find_value(win, id_hash); 22785 if (!x_offset) { 22786 x_offset = nk_add_value(ctx, win, id_hash, 0); 22787 y_offset = nk_add_value(ctx, win, id_hash+1, 0); 22788 22789 NK_ASSERT(x_offset); 22790 NK_ASSERT(y_offset); 22791 if (!x_offset || !y_offset) return 0; 22792 *x_offset = *y_offset = 0; 22793 } else y_offset = nk_find_value(win, id_hash+1); 22794 return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); 22795 } 22796 NK_API nk_bool 22797 nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags) 22798 { 22799 return nk_group_begin_titled(ctx, title, title, flags); 22800 } 22801 NK_API void 22802 nk_group_end(struct nk_context *ctx) 22803 { 22804 nk_group_scrolled_end(ctx); 22805 } 22806 NK_API void 22807 nk_group_get_scroll(struct nk_context *ctx, const char *id, nk_uint *x_offset, nk_uint *y_offset) 22808 { 22809 int id_len; 22810 nk_hash id_hash; 22811 struct nk_window *win; 22812 nk_uint *x_offset_ptr; 22813 nk_uint *y_offset_ptr; 22814 22815 NK_ASSERT(ctx); 22816 NK_ASSERT(id); 22817 NK_ASSERT(ctx->current); 22818 NK_ASSERT(ctx->current->layout); 22819 if (!ctx || !ctx->current || !ctx->current->layout || !id) 22820 return; 22821 22822 /* find persistent group scrollbar value */ 22823 win = ctx->current; 22824 id_len = (int)nk_strlen(id); 22825 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); 22826 x_offset_ptr = nk_find_value(win, id_hash); 22827 if (!x_offset_ptr) { 22828 x_offset_ptr = nk_add_value(ctx, win, id_hash, 0); 22829 y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0); 22830 22831 NK_ASSERT(x_offset_ptr); 22832 NK_ASSERT(y_offset_ptr); 22833 if (!x_offset_ptr || !y_offset_ptr) return; 22834 *x_offset_ptr = *y_offset_ptr = 0; 22835 } else y_offset_ptr = nk_find_value(win, id_hash+1); 22836 if (x_offset) 22837 *x_offset = *x_offset_ptr; 22838 if (y_offset) 22839 *y_offset = *y_offset_ptr; 22840 } 22841 NK_API void 22842 nk_group_set_scroll(struct nk_context *ctx, const char *id, nk_uint x_offset, nk_uint y_offset) 22843 { 22844 int id_len; 22845 nk_hash id_hash; 22846 struct nk_window *win; 22847 nk_uint *x_offset_ptr; 22848 nk_uint *y_offset_ptr; 22849 22850 NK_ASSERT(ctx); 22851 NK_ASSERT(id); 22852 NK_ASSERT(ctx->current); 22853 NK_ASSERT(ctx->current->layout); 22854 if (!ctx || !ctx->current || !ctx->current->layout || !id) 22855 return; 22856 22857 /* find persistent group scrollbar value */ 22858 win = ctx->current; 22859 id_len = (int)nk_strlen(id); 22860 id_hash = nk_murmur_hash(id, (int)id_len, NK_PANEL_GROUP); 22861 x_offset_ptr = nk_find_value(win, id_hash); 22862 if (!x_offset_ptr) { 22863 x_offset_ptr = nk_add_value(ctx, win, id_hash, 0); 22864 y_offset_ptr = nk_add_value(ctx, win, id_hash+1, 0); 22865 22866 NK_ASSERT(x_offset_ptr); 22867 NK_ASSERT(y_offset_ptr); 22868 if (!x_offset_ptr || !y_offset_ptr) return; 22869 *x_offset_ptr = *y_offset_ptr = 0; 22870 } else y_offset_ptr = nk_find_value(win, id_hash+1); 22871 *x_offset_ptr = x_offset; 22872 *y_offset_ptr = y_offset; 22873 } 22874 22875 22876 22877 22878 /* =============================================================== 22879 * 22880 * LIST VIEW 22881 * 22882 * ===============================================================*/ 22883 NK_API nk_bool 22884 nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view, 22885 const char *title, nk_flags flags, int row_height, int row_count) 22886 { 22887 int title_len; 22888 nk_hash title_hash; 22889 nk_uint *x_offset; 22890 nk_uint *y_offset; 22891 22892 int result; 22893 struct nk_window *win; 22894 struct nk_panel *layout; 22895 const struct nk_style *style; 22896 struct nk_vec2 item_spacing; 22897 22898 NK_ASSERT(ctx); 22899 NK_ASSERT(view); 22900 NK_ASSERT(title); 22901 if (!ctx || !view || !title) return 0; 22902 22903 win = ctx->current; 22904 style = &ctx->style; 22905 item_spacing = style->window.spacing; 22906 row_height += NK_MAX(0, (int)item_spacing.y); 22907 22908 /* find persistent list view scrollbar offset */ 22909 title_len = (int)nk_strlen(title); 22910 title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP); 22911 x_offset = nk_find_value(win, title_hash); 22912 if (!x_offset) { 22913 x_offset = nk_add_value(ctx, win, title_hash, 0); 22914 y_offset = nk_add_value(ctx, win, title_hash+1, 0); 22915 22916 NK_ASSERT(x_offset); 22917 NK_ASSERT(y_offset); 22918 if (!x_offset || !y_offset) return 0; 22919 *x_offset = *y_offset = 0; 22920 } else y_offset = nk_find_value(win, title_hash+1); 22921 view->scroll_value = *y_offset; 22922 view->scroll_pointer = y_offset; 22923 22924 *y_offset = 0; 22925 result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); 22926 win = ctx->current; 22927 layout = win->layout; 22928 22929 view->total_height = row_height * NK_MAX(row_count,1); 22930 view->begin = (int)NK_MAX(((float)view->scroll_value / (float)row_height), 0.0f); 22931 view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height),0); 22932 view->count = NK_MIN(view->count, row_count - view->begin); 22933 view->end = view->begin + view->count; 22934 view->ctx = ctx; 22935 return result; 22936 } 22937 NK_API void 22938 nk_list_view_end(struct nk_list_view *view) 22939 { 22940 struct nk_context *ctx; 22941 struct nk_window *win; 22942 struct nk_panel *layout; 22943 22944 NK_ASSERT(view); 22945 NK_ASSERT(view->ctx); 22946 NK_ASSERT(view->scroll_pointer); 22947 if (!view || !view->ctx) return; 22948 22949 ctx = view->ctx; 22950 win = ctx->current; 22951 layout = win->layout; 22952 layout->at_y = layout->bounds.y + (float)view->total_height; 22953 *view->scroll_pointer = *view->scroll_pointer + view->scroll_value; 22954 nk_group_end(view->ctx); 22955 } 22956 22957 22958 22959 22960 22961 /* =============================================================== 22962 * 22963 * WIDGET 22964 * 22965 * ===============================================================*/ 22966 NK_API struct nk_rect 22967 nk_widget_bounds(struct nk_context *ctx) 22968 { 22969 struct nk_rect bounds; 22970 NK_ASSERT(ctx); 22971 NK_ASSERT(ctx->current); 22972 if (!ctx || !ctx->current) 22973 return nk_rect(0,0,0,0); 22974 nk_layout_peek(&bounds, ctx); 22975 return bounds; 22976 } 22977 NK_API struct nk_vec2 22978 nk_widget_position(struct nk_context *ctx) 22979 { 22980 struct nk_rect bounds; 22981 NK_ASSERT(ctx); 22982 NK_ASSERT(ctx->current); 22983 if (!ctx || !ctx->current) 22984 return nk_vec2(0,0); 22985 22986 nk_layout_peek(&bounds, ctx); 22987 return nk_vec2(bounds.x, bounds.y); 22988 } 22989 NK_API struct nk_vec2 22990 nk_widget_size(struct nk_context *ctx) 22991 { 22992 struct nk_rect bounds; 22993 NK_ASSERT(ctx); 22994 NK_ASSERT(ctx->current); 22995 if (!ctx || !ctx->current) 22996 return nk_vec2(0,0); 22997 22998 nk_layout_peek(&bounds, ctx); 22999 return nk_vec2(bounds.w, bounds.h); 23000 } 23001 NK_API float 23002 nk_widget_width(struct nk_context *ctx) 23003 { 23004 struct nk_rect bounds; 23005 NK_ASSERT(ctx); 23006 NK_ASSERT(ctx->current); 23007 if (!ctx || !ctx->current) 23008 return 0; 23009 23010 nk_layout_peek(&bounds, ctx); 23011 return bounds.w; 23012 } 23013 NK_API float 23014 nk_widget_height(struct nk_context *ctx) 23015 { 23016 struct nk_rect bounds; 23017 NK_ASSERT(ctx); 23018 NK_ASSERT(ctx->current); 23019 if (!ctx || !ctx->current) 23020 return 0; 23021 23022 nk_layout_peek(&bounds, ctx); 23023 return bounds.h; 23024 } 23025 NK_API nk_bool 23026 nk_widget_is_hovered(struct nk_context *ctx) 23027 { 23028 struct nk_rect c, v; 23029 struct nk_rect bounds; 23030 NK_ASSERT(ctx); 23031 NK_ASSERT(ctx->current); 23032 if (!ctx || !ctx->current || ctx->active != ctx->current) 23033 return 0; 23034 23035 c = ctx->current->layout->clip; 23036 c.x = (float)((int)c.x); 23037 c.y = (float)((int)c.y); 23038 c.w = (float)((int)c.w); 23039 c.h = (float)((int)c.h); 23040 23041 nk_layout_peek(&bounds, ctx); 23042 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 23043 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 23044 return 0; 23045 return nk_input_is_mouse_hovering_rect(&ctx->input, bounds); 23046 } 23047 NK_API nk_bool 23048 nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn) 23049 { 23050 struct nk_rect c, v; 23051 struct nk_rect bounds; 23052 NK_ASSERT(ctx); 23053 NK_ASSERT(ctx->current); 23054 if (!ctx || !ctx->current || ctx->active != ctx->current) 23055 return 0; 23056 23057 c = ctx->current->layout->clip; 23058 c.x = (float)((int)c.x); 23059 c.y = (float)((int)c.y); 23060 c.w = (float)((int)c.w); 23061 c.h = (float)((int)c.h); 23062 23063 nk_layout_peek(&bounds, ctx); 23064 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 23065 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 23066 return 0; 23067 return nk_input_mouse_clicked(&ctx->input, btn, bounds); 23068 } 23069 NK_API nk_bool 23070 nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, nk_bool down) 23071 { 23072 struct nk_rect c, v; 23073 struct nk_rect bounds; 23074 NK_ASSERT(ctx); 23075 NK_ASSERT(ctx->current); 23076 if (!ctx || !ctx->current || ctx->active != ctx->current) 23077 return 0; 23078 23079 c = ctx->current->layout->clip; 23080 c.x = (float)((int)c.x); 23081 c.y = (float)((int)c.y); 23082 c.w = (float)((int)c.w); 23083 c.h = (float)((int)c.h); 23084 23085 nk_layout_peek(&bounds, ctx); 23086 nk_unify(&v, &c, bounds.x, bounds.y, bounds.x + bounds.w, bounds.y + bounds.h); 23087 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds.x, bounds.y, bounds.w, bounds.h)) 23088 return 0; 23089 return nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down); 23090 } 23091 NK_API enum nk_widget_layout_states 23092 nk_widget(struct nk_rect *bounds, const struct nk_context *ctx) 23093 { 23094 struct nk_rect c, v; 23095 struct nk_window *win; 23096 struct nk_panel *layout; 23097 const struct nk_input *in; 23098 23099 NK_ASSERT(ctx); 23100 NK_ASSERT(ctx->current); 23101 NK_ASSERT(ctx->current->layout); 23102 if (!ctx || !ctx->current || !ctx->current->layout) 23103 return NK_WIDGET_INVALID; 23104 23105 /* allocate space and check if the widget needs to be updated and drawn */ 23106 nk_panel_alloc_space(bounds, ctx); 23107 win = ctx->current; 23108 layout = win->layout; 23109 in = &ctx->input; 23110 c = layout->clip; 23111 23112 /* if one of these triggers you forgot to add an `if` condition around either 23113 a window, group, popup, combobox or contextual menu `begin` and `end` block. 23114 Example: 23115 if (nk_begin(...) {...} nk_end(...); or 23116 if (nk_group_begin(...) { nk_group_end(...);} */ 23117 NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); 23118 NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); 23119 NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); 23120 23121 /* need to convert to int here to remove floating point errors */ 23122 bounds->x = (float)((int)bounds->x); 23123 bounds->y = (float)((int)bounds->y); 23124 bounds->w = (float)((int)bounds->w); 23125 bounds->h = (float)((int)bounds->h); 23126 23127 c.x = (float)((int)c.x); 23128 c.y = (float)((int)c.y); 23129 c.w = (float)((int)c.w); 23130 c.h = (float)((int)c.h); 23131 23132 nk_unify(&v, &c, bounds->x, bounds->y, bounds->x + bounds->w, bounds->y + bounds->h); 23133 if (!NK_INTERSECT(c.x, c.y, c.w, c.h, bounds->x, bounds->y, bounds->w, bounds->h)) 23134 return NK_WIDGET_INVALID; 23135 if (!NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, v.x, v.y, v.w, v.h)) 23136 return NK_WIDGET_ROM; 23137 return NK_WIDGET_VALID; 23138 } 23139 NK_API enum nk_widget_layout_states 23140 nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx, 23141 struct nk_vec2 item_padding) 23142 { 23143 /* update the bounds to stand without padding */ 23144 enum nk_widget_layout_states state; 23145 NK_UNUSED(item_padding); 23146 23147 NK_ASSERT(ctx); 23148 NK_ASSERT(ctx->current); 23149 NK_ASSERT(ctx->current->layout); 23150 if (!ctx || !ctx->current || !ctx->current->layout) 23151 return NK_WIDGET_INVALID; 23152 23153 state = nk_widget(bounds, ctx); 23154 return state; 23155 } 23156 NK_API void 23157 nk_spacing(struct nk_context *ctx, int cols) 23158 { 23159 struct nk_window *win; 23160 struct nk_panel *layout; 23161 struct nk_rect none; 23162 int i, index, rows; 23163 23164 NK_ASSERT(ctx); 23165 NK_ASSERT(ctx->current); 23166 NK_ASSERT(ctx->current->layout); 23167 if (!ctx || !ctx->current || !ctx->current->layout) 23168 return; 23169 23170 /* spacing over row boundaries */ 23171 win = ctx->current; 23172 layout = win->layout; 23173 index = (layout->row.index + cols) % layout->row.columns; 23174 rows = (layout->row.index + cols) / layout->row.columns; 23175 if (rows) { 23176 for (i = 0; i < rows; ++i) 23177 nk_panel_alloc_row(ctx, win); 23178 cols = index; 23179 } 23180 /* non table layout need to allocate space */ 23181 if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED && 23182 layout->row.type != NK_LAYOUT_STATIC_FIXED) { 23183 for (i = 0; i < cols; ++i) 23184 nk_panel_alloc_space(&none, ctx); 23185 } layout->row.index = index; 23186 } 23187 23188 23189 23190 23191 23192 /* =============================================================== 23193 * 23194 * TEXT 23195 * 23196 * ===============================================================*/ 23197 NK_LIB void 23198 nk_widget_text(struct nk_command_buffer *o, struct nk_rect b, 23199 const char *string, int len, const struct nk_text *t, 23200 nk_flags a, const struct nk_user_font *f) 23201 { 23202 struct nk_rect label; 23203 float text_width; 23204 23205 NK_ASSERT(o); 23206 NK_ASSERT(t); 23207 if (!o || !t) return; 23208 23209 b.h = NK_MAX(b.h, 2 * t->padding.y); 23210 label.x = 0; label.w = 0; 23211 label.y = b.y + t->padding.y; 23212 label.h = NK_MIN(f->height, b.h - 2 * t->padding.y); 23213 23214 text_width = f->width(f->userdata, f->height, (const char*)string, len); 23215 text_width += (2.0f * t->padding.x); 23216 23217 /* align in x-axis */ 23218 if (a & NK_TEXT_ALIGN_LEFT) { 23219 label.x = b.x + t->padding.x; 23220 label.w = NK_MAX(0, b.w - 2 * t->padding.x); 23221 } else if (a & NK_TEXT_ALIGN_CENTERED) { 23222 label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width); 23223 label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2); 23224 label.x = NK_MAX(b.x + t->padding.x, label.x); 23225 label.w = NK_MIN(b.x + b.w, label.x + label.w); 23226 if (label.w >= label.x) label.w -= label.x; 23227 } else if (a & NK_TEXT_ALIGN_RIGHT) { 23228 label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width)); 23229 label.w = (float)text_width + 2 * t->padding.x; 23230 } else return; 23231 23232 /* align in y-axis */ 23233 if (a & NK_TEXT_ALIGN_MIDDLE) { 23234 label.y = b.y + b.h/2.0f - (float)f->height/2.0f; 23235 label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f)); 23236 } else if (a & NK_TEXT_ALIGN_BOTTOM) { 23237 label.y = b.y + b.h - f->height; 23238 label.h = f->height; 23239 } 23240 nk_draw_text(o, label, (const char*)string, len, f, t->background, t->text); 23241 } 23242 NK_LIB void 23243 nk_widget_text_wrap(struct nk_command_buffer *o, struct nk_rect b, 23244 const char *string, int len, const struct nk_text *t, 23245 const struct nk_user_font *f) 23246 { 23247 float width; 23248 int glyphs = 0; 23249 int fitting = 0; 23250 int done = 0; 23251 struct nk_rect line; 23252 struct nk_text text; 23253 NK_INTERN nk_rune seperator[] = {' '}; 23254 23255 NK_ASSERT(o); 23256 NK_ASSERT(t); 23257 if (!o || !t) return; 23258 23259 text.padding = nk_vec2(0,0); 23260 text.background = t->background; 23261 text.text = t->text; 23262 23263 b.w = NK_MAX(b.w, 2 * t->padding.x); 23264 b.h = NK_MAX(b.h, 2 * t->padding.y); 23265 b.h = b.h - 2 * t->padding.y; 23266 23267 line.x = b.x + t->padding.x; 23268 line.y = b.y + t->padding.y; 23269 line.w = b.w - 2 * t->padding.x; 23270 line.h = 2 * t->padding.y + f->height; 23271 23272 fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); 23273 while (done < len) { 23274 if (!fitting || line.y + line.h >= (b.y + b.h)) break; 23275 nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f); 23276 done += fitting; 23277 line.y += f->height + 2 * t->padding.y; 23278 fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); 23279 } 23280 } 23281 NK_API void 23282 nk_text_colored(struct nk_context *ctx, const char *str, int len, 23283 nk_flags alignment, struct nk_color color) 23284 { 23285 struct nk_window *win; 23286 const struct nk_style *style; 23287 23288 struct nk_vec2 item_padding; 23289 struct nk_rect bounds; 23290 struct nk_text text; 23291 23292 NK_ASSERT(ctx); 23293 NK_ASSERT(ctx->current); 23294 NK_ASSERT(ctx->current->layout); 23295 if (!ctx || !ctx->current || !ctx->current->layout) return; 23296 23297 win = ctx->current; 23298 style = &ctx->style; 23299 nk_panel_alloc_space(&bounds, ctx); 23300 item_padding = style->text.padding; 23301 23302 text.padding.x = item_padding.x; 23303 text.padding.y = item_padding.y; 23304 text.background = style->window.background; 23305 text.text = color; 23306 nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font); 23307 } 23308 NK_API void 23309 nk_text_wrap_colored(struct nk_context *ctx, const char *str, 23310 int len, struct nk_color color) 23311 { 23312 struct nk_window *win; 23313 const struct nk_style *style; 23314 23315 struct nk_vec2 item_padding; 23316 struct nk_rect bounds; 23317 struct nk_text text; 23318 23319 NK_ASSERT(ctx); 23320 NK_ASSERT(ctx->current); 23321 NK_ASSERT(ctx->current->layout); 23322 if (!ctx || !ctx->current || !ctx->current->layout) return; 23323 23324 win = ctx->current; 23325 style = &ctx->style; 23326 nk_panel_alloc_space(&bounds, ctx); 23327 item_padding = style->text.padding; 23328 23329 text.padding.x = item_padding.x; 23330 text.padding.y = item_padding.y; 23331 text.background = style->window.background; 23332 text.text = color; 23333 nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font); 23334 } 23335 #ifdef NK_INCLUDE_STANDARD_VARARGS 23336 NK_API void 23337 nk_labelf_colored(struct nk_context *ctx, nk_flags flags, 23338 struct nk_color color, const char *fmt, ...) 23339 { 23340 va_list args; 23341 va_start(args, fmt); 23342 nk_labelfv_colored(ctx, flags, color, fmt, args); 23343 va_end(args); 23344 } 23345 NK_API void 23346 nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color, 23347 const char *fmt, ...) 23348 { 23349 va_list args; 23350 va_start(args, fmt); 23351 nk_labelfv_colored_wrap(ctx, color, fmt, args); 23352 va_end(args); 23353 } 23354 NK_API void 23355 nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...) 23356 { 23357 va_list args; 23358 va_start(args, fmt); 23359 nk_labelfv(ctx, flags, fmt, args); 23360 va_end(args); 23361 } 23362 NK_API void 23363 nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...) 23364 { 23365 va_list args; 23366 va_start(args, fmt); 23367 nk_labelfv_wrap(ctx, fmt, args); 23368 va_end(args); 23369 } 23370 NK_API void 23371 nk_labelfv_colored(struct nk_context *ctx, nk_flags flags, 23372 struct nk_color color, const char *fmt, va_list args) 23373 { 23374 char buf[256]; 23375 nk_strfmt(buf, NK_LEN(buf), fmt, args); 23376 nk_label_colored(ctx, buf, flags, color); 23377 } 23378 23379 NK_API void 23380 nk_labelfv_colored_wrap(struct nk_context *ctx, struct nk_color color, 23381 const char *fmt, va_list args) 23382 { 23383 char buf[256]; 23384 nk_strfmt(buf, NK_LEN(buf), fmt, args); 23385 nk_label_colored_wrap(ctx, buf, color); 23386 } 23387 23388 NK_API void 23389 nk_labelfv(struct nk_context *ctx, nk_flags flags, const char *fmt, va_list args) 23390 { 23391 char buf[256]; 23392 nk_strfmt(buf, NK_LEN(buf), fmt, args); 23393 nk_label(ctx, buf, flags); 23394 } 23395 23396 NK_API void 23397 nk_labelfv_wrap(struct nk_context *ctx, const char *fmt, va_list args) 23398 { 23399 char buf[256]; 23400 nk_strfmt(buf, NK_LEN(buf), fmt, args); 23401 nk_label_wrap(ctx, buf); 23402 } 23403 23404 NK_API void 23405 nk_value_bool(struct nk_context *ctx, const char *prefix, int value) 23406 { 23407 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false")); 23408 } 23409 NK_API void 23410 nk_value_int(struct nk_context *ctx, const char *prefix, int value) 23411 { 23412 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value); 23413 } 23414 NK_API void 23415 nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value) 23416 { 23417 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value); 23418 } 23419 NK_API void 23420 nk_value_float(struct nk_context *ctx, const char *prefix, float value) 23421 { 23422 double double_value = (double)value; 23423 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value); 23424 } 23425 NK_API void 23426 nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c) 23427 { 23428 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a); 23429 } 23430 NK_API void 23431 nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color) 23432 { 23433 double c[4]; nk_color_dv(c, color); 23434 nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)", 23435 p, c[0], c[1], c[2], c[3]); 23436 } 23437 NK_API void 23438 nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color) 23439 { 23440 char hex[16]; 23441 nk_color_hex_rgba(hex, color); 23442 nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex); 23443 } 23444 #endif 23445 NK_API void 23446 nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment) 23447 { 23448 NK_ASSERT(ctx); 23449 if (!ctx) return; 23450 nk_text_colored(ctx, str, len, alignment, ctx->style.text.color); 23451 } 23452 NK_API void 23453 nk_text_wrap(struct nk_context *ctx, const char *str, int len) 23454 { 23455 NK_ASSERT(ctx); 23456 if (!ctx) return; 23457 nk_text_wrap_colored(ctx, str, len, ctx->style.text.color); 23458 } 23459 NK_API void 23460 nk_label(struct nk_context *ctx, const char *str, nk_flags alignment) 23461 { 23462 nk_text(ctx, str, nk_strlen(str), alignment); 23463 } 23464 NK_API void 23465 nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align, 23466 struct nk_color color) 23467 { 23468 nk_text_colored(ctx, str, nk_strlen(str), align, color); 23469 } 23470 NK_API void 23471 nk_label_wrap(struct nk_context *ctx, const char *str) 23472 { 23473 nk_text_wrap(ctx, str, nk_strlen(str)); 23474 } 23475 NK_API void 23476 nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color) 23477 { 23478 nk_text_wrap_colored(ctx, str, nk_strlen(str), color); 23479 } 23480 23481 23482 23483 23484 23485 /* =============================================================== 23486 * 23487 * IMAGE 23488 * 23489 * ===============================================================*/ 23490 NK_API nk_handle 23491 nk_handle_ptr(void *ptr) 23492 { 23493 nk_handle handle = {0}; 23494 handle.ptr = ptr; 23495 return handle; 23496 } 23497 NK_API nk_handle 23498 nk_handle_id(int id) 23499 { 23500 nk_handle handle; 23501 nk_zero_struct(handle); 23502 handle.id = id; 23503 return handle; 23504 } 23505 NK_API struct nk_image 23506 nk_subimage_ptr(void *ptr, nk_ushort w, nk_ushort h, struct nk_rect r) 23507 { 23508 struct nk_image s; 23509 nk_zero(&s, sizeof(s)); 23510 s.handle.ptr = ptr; 23511 s.w = w; s.h = h; 23512 s.region[0] = (nk_ushort)r.x; 23513 s.region[1] = (nk_ushort)r.y; 23514 s.region[2] = (nk_ushort)r.w; 23515 s.region[3] = (nk_ushort)r.h; 23516 return s; 23517 } 23518 NK_API struct nk_image 23519 nk_subimage_id(int id, nk_ushort w, nk_ushort h, struct nk_rect r) 23520 { 23521 struct nk_image s; 23522 nk_zero(&s, sizeof(s)); 23523 s.handle.id = id; 23524 s.w = w; s.h = h; 23525 s.region[0] = (nk_ushort)r.x; 23526 s.region[1] = (nk_ushort)r.y; 23527 s.region[2] = (nk_ushort)r.w; 23528 s.region[3] = (nk_ushort)r.h; 23529 return s; 23530 } 23531 NK_API struct nk_image 23532 nk_subimage_handle(nk_handle handle, nk_ushort w, nk_ushort h, struct nk_rect r) 23533 { 23534 struct nk_image s; 23535 nk_zero(&s, sizeof(s)); 23536 s.handle = handle; 23537 s.w = w; s.h = h; 23538 s.region[0] = (nk_ushort)r.x; 23539 s.region[1] = (nk_ushort)r.y; 23540 s.region[2] = (nk_ushort)r.w; 23541 s.region[3] = (nk_ushort)r.h; 23542 return s; 23543 } 23544 NK_API struct nk_image 23545 nk_image_handle(nk_handle handle) 23546 { 23547 struct nk_image s; 23548 nk_zero(&s, sizeof(s)); 23549 s.handle = handle; 23550 s.w = 0; s.h = 0; 23551 s.region[0] = 0; 23552 s.region[1] = 0; 23553 s.region[2] = 0; 23554 s.region[3] = 0; 23555 return s; 23556 } 23557 NK_API struct nk_image 23558 nk_image_ptr(void *ptr) 23559 { 23560 struct nk_image s; 23561 nk_zero(&s, sizeof(s)); 23562 NK_ASSERT(ptr); 23563 s.handle.ptr = ptr; 23564 s.w = 0; s.h = 0; 23565 s.region[0] = 0; 23566 s.region[1] = 0; 23567 s.region[2] = 0; 23568 s.region[3] = 0; 23569 return s; 23570 } 23571 NK_API struct nk_image 23572 nk_image_id(int id) 23573 { 23574 struct nk_image s; 23575 nk_zero(&s, sizeof(s)); 23576 s.handle.id = id; 23577 s.w = 0; s.h = 0; 23578 s.region[0] = 0; 23579 s.region[1] = 0; 23580 s.region[2] = 0; 23581 s.region[3] = 0; 23582 return s; 23583 } 23584 NK_API nk_bool 23585 nk_image_is_subimage(const struct nk_image* img) 23586 { 23587 NK_ASSERT(img); 23588 return !(img->w == 0 && img->h == 0); 23589 } 23590 NK_API void 23591 nk_image(struct nk_context *ctx, struct nk_image img) 23592 { 23593 struct nk_window *win; 23594 struct nk_rect bounds; 23595 23596 NK_ASSERT(ctx); 23597 NK_ASSERT(ctx->current); 23598 NK_ASSERT(ctx->current->layout); 23599 if (!ctx || !ctx->current || !ctx->current->layout) return; 23600 23601 win = ctx->current; 23602 if (!nk_widget(&bounds, ctx)) return; 23603 nk_draw_image(&win->buffer, bounds, &img, nk_white); 23604 } 23605 NK_API void 23606 nk_image_color(struct nk_context *ctx, struct nk_image img, struct nk_color col) 23607 { 23608 struct nk_window *win; 23609 struct nk_rect bounds; 23610 23611 NK_ASSERT(ctx); 23612 NK_ASSERT(ctx->current); 23613 NK_ASSERT(ctx->current->layout); 23614 if (!ctx || !ctx->current || !ctx->current->layout) return; 23615 23616 win = ctx->current; 23617 if (!nk_widget(&bounds, ctx)) return; 23618 nk_draw_image(&win->buffer, bounds, &img, col); 23619 } 23620 23621 23622 23623 23624 23625 /* =============================================================== 23626 * 23627 * 9-SLICE 23628 * 23629 * ===============================================================*/ 23630 NK_API struct nk_nine_slice 23631 nk_sub9slice_ptr(void *ptr, nk_ushort w, nk_ushort h, struct nk_rect rgn, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b) 23632 { 23633 struct nk_nine_slice s; 23634 struct nk_image *i = &s.img; 23635 nk_zero(&s, sizeof(s)); 23636 i->handle.ptr = ptr; 23637 i->w = w; i->h = h; 23638 i->region[0] = (nk_ushort)rgn.x; 23639 i->region[1] = (nk_ushort)rgn.y; 23640 i->region[2] = (nk_ushort)rgn.w; 23641 i->region[3] = (nk_ushort)rgn.h; 23642 s.l = l; s.t = t; s.r = r; s.b = b; 23643 return s; 23644 } 23645 NK_API struct nk_nine_slice 23646 nk_sub9slice_id(int id, nk_ushort w, nk_ushort h, struct nk_rect rgn, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b) 23647 { 23648 struct nk_nine_slice s; 23649 struct nk_image *i = &s.img; 23650 nk_zero(&s, sizeof(s)); 23651 i->handle.id = id; 23652 i->w = w; i->h = h; 23653 i->region[0] = (nk_ushort)rgn.x; 23654 i->region[1] = (nk_ushort)rgn.y; 23655 i->region[2] = (nk_ushort)rgn.w; 23656 i->region[3] = (nk_ushort)rgn.h; 23657 s.l = l; s.t = t; s.r = r; s.b = b; 23658 return s; 23659 } 23660 NK_API struct nk_nine_slice 23661 nk_sub9slice_handle(nk_handle handle, nk_ushort w, nk_ushort h, struct nk_rect rgn, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b) 23662 { 23663 struct nk_nine_slice s; 23664 struct nk_image *i = &s.img; 23665 nk_zero(&s, sizeof(s)); 23666 i->handle = handle; 23667 i->w = w; i->h = h; 23668 i->region[0] = (nk_ushort)rgn.x; 23669 i->region[1] = (nk_ushort)rgn.y; 23670 i->region[2] = (nk_ushort)rgn.w; 23671 i->region[3] = (nk_ushort)rgn.h; 23672 s.l = l; s.t = t; s.r = r; s.b = b; 23673 return s; 23674 } 23675 NK_API struct nk_nine_slice 23676 nk_nine_slice_handle(nk_handle handle, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b) 23677 { 23678 struct nk_nine_slice s; 23679 struct nk_image *i = &s.img; 23680 nk_zero(&s, sizeof(s)); 23681 i->handle = handle; 23682 i->w = 0; i->h = 0; 23683 i->region[0] = 0; 23684 i->region[1] = 0; 23685 i->region[2] = 0; 23686 i->region[3] = 0; 23687 s.l = l; s.t = t; s.r = r; s.b = b; 23688 return s; 23689 } 23690 NK_API struct nk_nine_slice 23691 nk_nine_slice_ptr(void *ptr, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b) 23692 { 23693 struct nk_nine_slice s; 23694 struct nk_image *i = &s.img; 23695 nk_zero(&s, sizeof(s)); 23696 NK_ASSERT(ptr); 23697 i->handle.ptr = ptr; 23698 i->w = 0; i->h = 0; 23699 i->region[0] = 0; 23700 i->region[1] = 0; 23701 i->region[2] = 0; 23702 i->region[3] = 0; 23703 s.l = l; s.t = t; s.r = r; s.b = b; 23704 return s; 23705 } 23706 NK_API struct nk_nine_slice 23707 nk_nine_slice_id(int id, nk_ushort l, nk_ushort t, nk_ushort r, nk_ushort b) 23708 { 23709 struct nk_nine_slice s; 23710 struct nk_image *i = &s.img; 23711 nk_zero(&s, sizeof(s)); 23712 i->handle.id = id; 23713 i->w = 0; i->h = 0; 23714 i->region[0] = 0; 23715 i->region[1] = 0; 23716 i->region[2] = 0; 23717 i->region[3] = 0; 23718 s.l = l; s.t = t; s.r = r; s.b = b; 23719 return s; 23720 } 23721 NK_API int 23722 nk_nine_slice_is_sub9slice(const struct nk_nine_slice* slice) 23723 { 23724 NK_ASSERT(slice); 23725 return !(slice->img.w == 0 && slice->img.h == 0); 23726 } 23727 23728 23729 23730 23731 23732 /* ============================================================== 23733 * 23734 * BUTTON 23735 * 23736 * ===============================================================*/ 23737 NK_LIB void 23738 nk_draw_symbol(struct nk_command_buffer *out, enum nk_symbol_type type, 23739 struct nk_rect content, struct nk_color background, struct nk_color foreground, 23740 float border_width, const struct nk_user_font *font) 23741 { 23742 switch (type) { 23743 case NK_SYMBOL_X: 23744 case NK_SYMBOL_UNDERSCORE: 23745 case NK_SYMBOL_PLUS: 23746 case NK_SYMBOL_MINUS: { 23747 /* single character text symbol */ 23748 const char *X = (type == NK_SYMBOL_X) ? "x": 23749 (type == NK_SYMBOL_UNDERSCORE) ? "_": 23750 (type == NK_SYMBOL_PLUS) ? "+": "-"; 23751 struct nk_text text; 23752 text.padding = nk_vec2(0,0); 23753 text.background = background; 23754 text.text = foreground; 23755 nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font); 23756 } break; 23757 case NK_SYMBOL_CIRCLE_SOLID: 23758 case NK_SYMBOL_CIRCLE_OUTLINE: 23759 case NK_SYMBOL_RECT_SOLID: 23760 case NK_SYMBOL_RECT_OUTLINE: { 23761 /* simple empty/filled shapes */ 23762 if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) { 23763 nk_fill_rect(out, content, 0, foreground); 23764 if (type == NK_SYMBOL_RECT_OUTLINE) 23765 nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background); 23766 } else { 23767 nk_fill_circle(out, content, foreground); 23768 if (type == NK_SYMBOL_CIRCLE_OUTLINE) 23769 nk_fill_circle(out, nk_shrink_rect(content, 1), background); 23770 } 23771 } break; 23772 case NK_SYMBOL_TRIANGLE_UP: 23773 case NK_SYMBOL_TRIANGLE_DOWN: 23774 case NK_SYMBOL_TRIANGLE_LEFT: 23775 case NK_SYMBOL_TRIANGLE_RIGHT: { 23776 enum nk_heading heading; 23777 struct nk_vec2 points[3]; 23778 heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT : 23779 (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT: 23780 (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN; 23781 nk_triangle_from_direction(points, content, 0, 0, heading); 23782 nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y, 23783 points[2].x, points[2].y, foreground); 23784 } break; 23785 default: 23786 case NK_SYMBOL_NONE: 23787 case NK_SYMBOL_MAX: break; 23788 } 23789 } 23790 NK_LIB nk_bool 23791 nk_button_behavior(nk_flags *state, struct nk_rect r, 23792 const struct nk_input *i, enum nk_button_behavior behavior) 23793 { 23794 int ret = 0; 23795 nk_widget_state_reset(state); 23796 if (!i) return 0; 23797 if (nk_input_is_mouse_hovering_rect(i, r)) { 23798 *state = NK_WIDGET_STATE_HOVERED; 23799 if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT)) 23800 *state = NK_WIDGET_STATE_ACTIVE; 23801 if (nk_input_has_mouse_click_in_button_rect(i, NK_BUTTON_LEFT, r)) { 23802 ret = (behavior != NK_BUTTON_DEFAULT) ? 23803 nk_input_is_mouse_down(i, NK_BUTTON_LEFT): 23804 #ifdef NK_BUTTON_TRIGGER_ON_RELEASE 23805 nk_input_is_mouse_released(i, NK_BUTTON_LEFT); 23806 #else 23807 nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT); 23808 #endif 23809 } 23810 } 23811 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r)) 23812 *state |= NK_WIDGET_STATE_ENTERED; 23813 else if (nk_input_is_mouse_prev_hovering_rect(i, r)) 23814 *state |= NK_WIDGET_STATE_LEFT; 23815 return ret; 23816 } 23817 NK_LIB const struct nk_style_item* 23818 nk_draw_button(struct nk_command_buffer *out, 23819 const struct nk_rect *bounds, nk_flags state, 23820 const struct nk_style_button *style) 23821 { 23822 const struct nk_style_item *background; 23823 if (state & NK_WIDGET_STATE_HOVER) 23824 background = &style->hover; 23825 else if (state & NK_WIDGET_STATE_ACTIVED) 23826 background = &style->active; 23827 else background = &style->normal; 23828 23829 switch(background->type) { 23830 case NK_STYLE_ITEM_IMAGE: 23831 nk_draw_image(out, *bounds, &background->data.image, nk_white); 23832 break; 23833 case NK_STYLE_ITEM_NINE_SLICE: 23834 nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white); 23835 break; 23836 case NK_STYLE_ITEM_COLOR: 23837 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 23838 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 23839 break; 23840 } 23841 return background; 23842 } 23843 NK_LIB nk_bool 23844 nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, 23845 const struct nk_style_button *style, const struct nk_input *in, 23846 enum nk_button_behavior behavior, struct nk_rect *content) 23847 { 23848 struct nk_rect bounds; 23849 NK_ASSERT(style); 23850 NK_ASSERT(state); 23851 NK_ASSERT(out); 23852 if (!out || !style) 23853 return nk_false; 23854 23855 /* calculate button content space */ 23856 content->x = r.x + style->padding.x + style->border + style->rounding; 23857 content->y = r.y + style->padding.y + style->border + style->rounding; 23858 content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2); 23859 content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2); 23860 23861 /* execute button behavior */ 23862 bounds.x = r.x - style->touch_padding.x; 23863 bounds.y = r.y - style->touch_padding.y; 23864 bounds.w = r.w + 2 * style->touch_padding.x; 23865 bounds.h = r.h + 2 * style->touch_padding.y; 23866 return nk_button_behavior(state, bounds, in, behavior); 23867 } 23868 NK_LIB void 23869 nk_draw_button_text(struct nk_command_buffer *out, 23870 const struct nk_rect *bounds, const struct nk_rect *content, nk_flags state, 23871 const struct nk_style_button *style, const char *txt, int len, 23872 nk_flags text_alignment, const struct nk_user_font *font) 23873 { 23874 struct nk_text text; 23875 const struct nk_style_item *background; 23876 background = nk_draw_button(out, bounds, state, style); 23877 23878 /* select correct colors/images */ 23879 if (background->type == NK_STYLE_ITEM_COLOR) 23880 text.background = background->data.color; 23881 else text.background = style->text_background; 23882 if (state & NK_WIDGET_STATE_HOVER) 23883 text.text = style->text_hover; 23884 else if (state & NK_WIDGET_STATE_ACTIVED) 23885 text.text = style->text_active; 23886 else text.text = style->text_normal; 23887 23888 text.padding = nk_vec2(0,0); 23889 nk_widget_text(out, *content, txt, len, &text, text_alignment, font); 23890 } 23891 NK_LIB nk_bool 23892 nk_do_button_text(nk_flags *state, 23893 struct nk_command_buffer *out, struct nk_rect bounds, 23894 const char *string, int len, nk_flags align, enum nk_button_behavior behavior, 23895 const struct nk_style_button *style, const struct nk_input *in, 23896 const struct nk_user_font *font) 23897 { 23898 struct nk_rect content; 23899 int ret = nk_false; 23900 23901 NK_ASSERT(state); 23902 NK_ASSERT(style); 23903 NK_ASSERT(out); 23904 NK_ASSERT(string); 23905 NK_ASSERT(font); 23906 if (!out || !style || !font || !string) 23907 return nk_false; 23908 23909 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 23910 if (style->draw_begin) style->draw_begin(out, style->userdata); 23911 nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font); 23912 if (style->draw_end) style->draw_end(out, style->userdata); 23913 return ret; 23914 } 23915 NK_LIB void 23916 nk_draw_button_symbol(struct nk_command_buffer *out, 23917 const struct nk_rect *bounds, const struct nk_rect *content, 23918 nk_flags state, const struct nk_style_button *style, 23919 enum nk_symbol_type type, const struct nk_user_font *font) 23920 { 23921 struct nk_color sym, bg; 23922 const struct nk_style_item *background; 23923 23924 /* select correct colors/images */ 23925 background = nk_draw_button(out, bounds, state, style); 23926 if (background->type == NK_STYLE_ITEM_COLOR) 23927 bg = background->data.color; 23928 else bg = style->text_background; 23929 23930 if (state & NK_WIDGET_STATE_HOVER) 23931 sym = style->text_hover; 23932 else if (state & NK_WIDGET_STATE_ACTIVED) 23933 sym = style->text_active; 23934 else sym = style->text_normal; 23935 nk_draw_symbol(out, type, *content, bg, sym, 1, font); 23936 } 23937 NK_LIB nk_bool 23938 nk_do_button_symbol(nk_flags *state, 23939 struct nk_command_buffer *out, struct nk_rect bounds, 23940 enum nk_symbol_type symbol, enum nk_button_behavior behavior, 23941 const struct nk_style_button *style, const struct nk_input *in, 23942 const struct nk_user_font *font) 23943 { 23944 int ret; 23945 struct nk_rect content; 23946 23947 NK_ASSERT(state); 23948 NK_ASSERT(style); 23949 NK_ASSERT(font); 23950 NK_ASSERT(out); 23951 if (!out || !style || !font || !state) 23952 return nk_false; 23953 23954 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 23955 if (style->draw_begin) style->draw_begin(out, style->userdata); 23956 nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font); 23957 if (style->draw_end) style->draw_end(out, style->userdata); 23958 return ret; 23959 } 23960 NK_LIB void 23961 nk_draw_button_image(struct nk_command_buffer *out, 23962 const struct nk_rect *bounds, const struct nk_rect *content, 23963 nk_flags state, const struct nk_style_button *style, const struct nk_image *img) 23964 { 23965 nk_draw_button(out, bounds, state, style); 23966 nk_draw_image(out, *content, img, nk_white); 23967 } 23968 NK_LIB nk_bool 23969 nk_do_button_image(nk_flags *state, 23970 struct nk_command_buffer *out, struct nk_rect bounds, 23971 struct nk_image img, enum nk_button_behavior b, 23972 const struct nk_style_button *style, const struct nk_input *in) 23973 { 23974 int ret; 23975 struct nk_rect content; 23976 23977 NK_ASSERT(state); 23978 NK_ASSERT(style); 23979 NK_ASSERT(out); 23980 if (!out || !style || !state) 23981 return nk_false; 23982 23983 ret = nk_do_button(state, out, bounds, style, in, b, &content); 23984 content.x += style->image_padding.x; 23985 content.y += style->image_padding.y; 23986 content.w -= 2 * style->image_padding.x; 23987 content.h -= 2 * style->image_padding.y; 23988 23989 if (style->draw_begin) style->draw_begin(out, style->userdata); 23990 nk_draw_button_image(out, &bounds, &content, *state, style, &img); 23991 if (style->draw_end) style->draw_end(out, style->userdata); 23992 return ret; 23993 } 23994 NK_LIB void 23995 nk_draw_button_text_symbol(struct nk_command_buffer *out, 23996 const struct nk_rect *bounds, const struct nk_rect *label, 23997 const struct nk_rect *symbol, nk_flags state, const struct nk_style_button *style, 23998 const char *str, int len, enum nk_symbol_type type, 23999 const struct nk_user_font *font) 24000 { 24001 struct nk_color sym; 24002 struct nk_text text; 24003 const struct nk_style_item *background; 24004 24005 /* select correct background colors/images */ 24006 background = nk_draw_button(out, bounds, state, style); 24007 if (background->type == NK_STYLE_ITEM_COLOR) 24008 text.background = background->data.color; 24009 else text.background = style->text_background; 24010 24011 /* select correct text colors */ 24012 if (state & NK_WIDGET_STATE_HOVER) { 24013 sym = style->text_hover; 24014 text.text = style->text_hover; 24015 } else if (state & NK_WIDGET_STATE_ACTIVED) { 24016 sym = style->text_active; 24017 text.text = style->text_active; 24018 } else { 24019 sym = style->text_normal; 24020 text.text = style->text_normal; 24021 } 24022 24023 text.padding = nk_vec2(0,0); 24024 nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font); 24025 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); 24026 } 24027 NK_LIB nk_bool 24028 nk_do_button_text_symbol(nk_flags *state, 24029 struct nk_command_buffer *out, struct nk_rect bounds, 24030 enum nk_symbol_type symbol, const char *str, int len, nk_flags align, 24031 enum nk_button_behavior behavior, const struct nk_style_button *style, 24032 const struct nk_user_font *font, const struct nk_input *in) 24033 { 24034 int ret; 24035 struct nk_rect tri = {0,0,0,0}; 24036 struct nk_rect content; 24037 24038 NK_ASSERT(style); 24039 NK_ASSERT(out); 24040 NK_ASSERT(font); 24041 if (!out || !style || !font) 24042 return nk_false; 24043 24044 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 24045 tri.y = content.y + (content.h/2) - font->height/2; 24046 tri.w = font->height; tri.h = font->height; 24047 if (align & NK_TEXT_ALIGN_LEFT) { 24048 tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w); 24049 tri.x = NK_MAX(tri.x, 0); 24050 } else tri.x = content.x + 2 * style->padding.x; 24051 24052 /* draw button */ 24053 if (style->draw_begin) style->draw_begin(out, style->userdata); 24054 nk_draw_button_text_symbol(out, &bounds, &content, &tri, 24055 *state, style, str, len, symbol, font); 24056 if (style->draw_end) style->draw_end(out, style->userdata); 24057 return ret; 24058 } 24059 NK_LIB void 24060 nk_draw_button_text_image(struct nk_command_buffer *out, 24061 const struct nk_rect *bounds, const struct nk_rect *label, 24062 const struct nk_rect *image, nk_flags state, const struct nk_style_button *style, 24063 const char *str, int len, const struct nk_user_font *font, 24064 const struct nk_image *img) 24065 { 24066 struct nk_text text; 24067 const struct nk_style_item *background; 24068 background = nk_draw_button(out, bounds, state, style); 24069 24070 /* select correct colors */ 24071 if (background->type == NK_STYLE_ITEM_COLOR) 24072 text.background = background->data.color; 24073 else text.background = style->text_background; 24074 if (state & NK_WIDGET_STATE_HOVER) 24075 text.text = style->text_hover; 24076 else if (state & NK_WIDGET_STATE_ACTIVED) 24077 text.text = style->text_active; 24078 else text.text = style->text_normal; 24079 24080 text.padding = nk_vec2(0,0); 24081 nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); 24082 nk_draw_image(out, *image, img, nk_white); 24083 } 24084 NK_LIB nk_bool 24085 nk_do_button_text_image(nk_flags *state, 24086 struct nk_command_buffer *out, struct nk_rect bounds, 24087 struct nk_image img, const char* str, int len, nk_flags align, 24088 enum nk_button_behavior behavior, const struct nk_style_button *style, 24089 const struct nk_user_font *font, const struct nk_input *in) 24090 { 24091 int ret; 24092 struct nk_rect icon; 24093 struct nk_rect content; 24094 24095 NK_ASSERT(style); 24096 NK_ASSERT(state); 24097 NK_ASSERT(font); 24098 NK_ASSERT(out); 24099 if (!out || !font || !style || !str) 24100 return nk_false; 24101 24102 ret = nk_do_button(state, out, bounds, style, in, behavior, &content); 24103 icon.y = bounds.y + style->padding.y; 24104 icon.w = icon.h = bounds.h - 2 * style->padding.y; 24105 if (align & NK_TEXT_ALIGN_LEFT) { 24106 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 24107 icon.x = NK_MAX(icon.x, 0); 24108 } else icon.x = bounds.x + 2 * style->padding.x; 24109 24110 icon.x += style->image_padding.x; 24111 icon.y += style->image_padding.y; 24112 icon.w -= 2 * style->image_padding.x; 24113 icon.h -= 2 * style->image_padding.y; 24114 24115 if (style->draw_begin) style->draw_begin(out, style->userdata); 24116 nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img); 24117 if (style->draw_end) style->draw_end(out, style->userdata); 24118 return ret; 24119 } 24120 NK_API void 24121 nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) 24122 { 24123 NK_ASSERT(ctx); 24124 if (!ctx) return; 24125 ctx->button_behavior = behavior; 24126 } 24127 NK_API nk_bool 24128 nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) 24129 { 24130 struct nk_config_stack_button_behavior *button_stack; 24131 struct nk_config_stack_button_behavior_element *element; 24132 24133 NK_ASSERT(ctx); 24134 if (!ctx) return 0; 24135 24136 button_stack = &ctx->stacks.button_behaviors; 24137 NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements)); 24138 if (button_stack->head >= (int)NK_LEN(button_stack->elements)) 24139 return 0; 24140 24141 element = &button_stack->elements[button_stack->head++]; 24142 element->address = &ctx->button_behavior; 24143 element->old_value = ctx->button_behavior; 24144 ctx->button_behavior = behavior; 24145 return 1; 24146 } 24147 NK_API nk_bool 24148 nk_button_pop_behavior(struct nk_context *ctx) 24149 { 24150 struct nk_config_stack_button_behavior *button_stack; 24151 struct nk_config_stack_button_behavior_element *element; 24152 24153 NK_ASSERT(ctx); 24154 if (!ctx) return 0; 24155 24156 button_stack = &ctx->stacks.button_behaviors; 24157 NK_ASSERT(button_stack->head > 0); 24158 if (button_stack->head < 1) 24159 return 0; 24160 24161 element = &button_stack->elements[--button_stack->head]; 24162 *element->address = element->old_value; 24163 return 1; 24164 } 24165 NK_API nk_bool 24166 nk_button_text_styled(struct nk_context *ctx, 24167 const struct nk_style_button *style, const char *title, int len) 24168 { 24169 struct nk_window *win; 24170 struct nk_panel *layout; 24171 const struct nk_input *in; 24172 24173 struct nk_rect bounds; 24174 enum nk_widget_layout_states state; 24175 24176 NK_ASSERT(ctx); 24177 NK_ASSERT(style); 24178 NK_ASSERT(ctx->current); 24179 NK_ASSERT(ctx->current->layout); 24180 if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0; 24181 24182 win = ctx->current; 24183 layout = win->layout; 24184 state = nk_widget(&bounds, ctx); 24185 24186 if (!state) return 0; 24187 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24188 return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, 24189 title, len, style->text_alignment, ctx->button_behavior, 24190 style, in, ctx->style.font); 24191 } 24192 NK_API nk_bool 24193 nk_button_text(struct nk_context *ctx, const char *title, int len) 24194 { 24195 NK_ASSERT(ctx); 24196 if (!ctx) return 0; 24197 return nk_button_text_styled(ctx, &ctx->style.button, title, len); 24198 } 24199 NK_API nk_bool nk_button_label_styled(struct nk_context *ctx, 24200 const struct nk_style_button *style, const char *title) 24201 { 24202 return nk_button_text_styled(ctx, style, title, nk_strlen(title)); 24203 } 24204 NK_API nk_bool nk_button_label(struct nk_context *ctx, const char *title) 24205 { 24206 return nk_button_text(ctx, title, nk_strlen(title)); 24207 } 24208 NK_API nk_bool 24209 nk_button_color(struct nk_context *ctx, struct nk_color color) 24210 { 24211 struct nk_window *win; 24212 struct nk_panel *layout; 24213 const struct nk_input *in; 24214 struct nk_style_button button; 24215 24216 int ret = 0; 24217 struct nk_rect bounds; 24218 struct nk_rect content; 24219 enum nk_widget_layout_states state; 24220 24221 NK_ASSERT(ctx); 24222 NK_ASSERT(ctx->current); 24223 NK_ASSERT(ctx->current->layout); 24224 if (!ctx || !ctx->current || !ctx->current->layout) 24225 return 0; 24226 24227 win = ctx->current; 24228 layout = win->layout; 24229 24230 state = nk_widget(&bounds, ctx); 24231 if (!state) return 0; 24232 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24233 24234 button = ctx->style.button; 24235 button.normal = nk_style_item_color(color); 24236 button.hover = nk_style_item_color(color); 24237 button.active = nk_style_item_color(color); 24238 ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds, 24239 &button, in, ctx->button_behavior, &content); 24240 nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button); 24241 return ret; 24242 } 24243 NK_API nk_bool 24244 nk_button_symbol_styled(struct nk_context *ctx, 24245 const struct nk_style_button *style, enum nk_symbol_type symbol) 24246 { 24247 struct nk_window *win; 24248 struct nk_panel *layout; 24249 const struct nk_input *in; 24250 24251 struct nk_rect bounds; 24252 enum nk_widget_layout_states state; 24253 24254 NK_ASSERT(ctx); 24255 NK_ASSERT(ctx->current); 24256 NK_ASSERT(ctx->current->layout); 24257 if (!ctx || !ctx->current || !ctx->current->layout) 24258 return 0; 24259 24260 win = ctx->current; 24261 layout = win->layout; 24262 state = nk_widget(&bounds, ctx); 24263 if (!state) return 0; 24264 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24265 return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds, 24266 symbol, ctx->button_behavior, style, in, ctx->style.font); 24267 } 24268 NK_API nk_bool 24269 nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol) 24270 { 24271 NK_ASSERT(ctx); 24272 if (!ctx) return 0; 24273 return nk_button_symbol_styled(ctx, &ctx->style.button, symbol); 24274 } 24275 NK_API nk_bool 24276 nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style, 24277 struct nk_image img) 24278 { 24279 struct nk_window *win; 24280 struct nk_panel *layout; 24281 const struct nk_input *in; 24282 24283 struct nk_rect bounds; 24284 enum nk_widget_layout_states state; 24285 24286 NK_ASSERT(ctx); 24287 NK_ASSERT(ctx->current); 24288 NK_ASSERT(ctx->current->layout); 24289 if (!ctx || !ctx->current || !ctx->current->layout) 24290 return 0; 24291 24292 win = ctx->current; 24293 layout = win->layout; 24294 24295 state = nk_widget(&bounds, ctx); 24296 if (!state) return 0; 24297 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24298 return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds, 24299 img, ctx->button_behavior, style, in); 24300 } 24301 NK_API nk_bool 24302 nk_button_image(struct nk_context *ctx, struct nk_image img) 24303 { 24304 NK_ASSERT(ctx); 24305 if (!ctx) return 0; 24306 return nk_button_image_styled(ctx, &ctx->style.button, img); 24307 } 24308 NK_API nk_bool 24309 nk_button_symbol_text_styled(struct nk_context *ctx, 24310 const struct nk_style_button *style, enum nk_symbol_type symbol, 24311 const char *text, int len, nk_flags align) 24312 { 24313 struct nk_window *win; 24314 struct nk_panel *layout; 24315 const struct nk_input *in; 24316 24317 struct nk_rect bounds; 24318 enum nk_widget_layout_states state; 24319 24320 NK_ASSERT(ctx); 24321 NK_ASSERT(ctx->current); 24322 NK_ASSERT(ctx->current->layout); 24323 if (!ctx || !ctx->current || !ctx->current->layout) 24324 return 0; 24325 24326 win = ctx->current; 24327 layout = win->layout; 24328 24329 state = nk_widget(&bounds, ctx); 24330 if (!state) return 0; 24331 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24332 return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, 24333 symbol, text, len, align, ctx->button_behavior, 24334 style, ctx->style.font, in); 24335 } 24336 NK_API nk_bool 24337 nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, 24338 const char* text, int len, nk_flags align) 24339 { 24340 NK_ASSERT(ctx); 24341 if (!ctx) return 0; 24342 return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align); 24343 } 24344 NK_API nk_bool nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, 24345 const char *label, nk_flags align) 24346 { 24347 return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align); 24348 } 24349 NK_API nk_bool nk_button_symbol_label_styled(struct nk_context *ctx, 24350 const struct nk_style_button *style, enum nk_symbol_type symbol, 24351 const char *title, nk_flags align) 24352 { 24353 return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align); 24354 } 24355 NK_API nk_bool 24356 nk_button_image_text_styled(struct nk_context *ctx, 24357 const struct nk_style_button *style, struct nk_image img, const char *text, 24358 int len, nk_flags align) 24359 { 24360 struct nk_window *win; 24361 struct nk_panel *layout; 24362 const struct nk_input *in; 24363 24364 struct nk_rect bounds; 24365 enum nk_widget_layout_states state; 24366 24367 NK_ASSERT(ctx); 24368 NK_ASSERT(ctx->current); 24369 NK_ASSERT(ctx->current->layout); 24370 if (!ctx || !ctx->current || !ctx->current->layout) 24371 return 0; 24372 24373 win = ctx->current; 24374 layout = win->layout; 24375 24376 state = nk_widget(&bounds, ctx); 24377 if (!state) return 0; 24378 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24379 return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, 24380 bounds, img, text, len, align, ctx->button_behavior, 24381 style, ctx->style.font, in); 24382 } 24383 NK_API nk_bool 24384 nk_button_image_text(struct nk_context *ctx, struct nk_image img, 24385 const char *text, int len, nk_flags align) 24386 { 24387 return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align); 24388 } 24389 NK_API nk_bool nk_button_image_label(struct nk_context *ctx, struct nk_image img, 24390 const char *label, nk_flags align) 24391 { 24392 return nk_button_image_text(ctx, img, label, nk_strlen(label), align); 24393 } 24394 NK_API nk_bool nk_button_image_label_styled(struct nk_context *ctx, 24395 const struct nk_style_button *style, struct nk_image img, 24396 const char *label, nk_flags text_alignment) 24397 { 24398 return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment); 24399 } 24400 24401 24402 24403 24404 24405 /* =============================================================== 24406 * 24407 * TOGGLE 24408 * 24409 * ===============================================================*/ 24410 NK_LIB nk_bool 24411 nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, 24412 nk_flags *state, nk_bool active) 24413 { 24414 nk_widget_state_reset(state); 24415 if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) { 24416 *state = NK_WIDGET_STATE_ACTIVE; 24417 active = !active; 24418 } 24419 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select)) 24420 *state |= NK_WIDGET_STATE_ENTERED; 24421 else if (nk_input_is_mouse_prev_hovering_rect(in, select)) 24422 *state |= NK_WIDGET_STATE_LEFT; 24423 return active; 24424 } 24425 NK_LIB void 24426 nk_draw_checkbox(struct nk_command_buffer *out, 24427 nk_flags state, const struct nk_style_toggle *style, nk_bool active, 24428 const struct nk_rect *label, const struct nk_rect *selector, 24429 const struct nk_rect *cursors, const char *string, int len, 24430 const struct nk_user_font *font) 24431 { 24432 const struct nk_style_item *background; 24433 const struct nk_style_item *cursor; 24434 struct nk_text text; 24435 24436 /* select correct colors/images */ 24437 if (state & NK_WIDGET_STATE_HOVER) { 24438 background = &style->hover; 24439 cursor = &style->cursor_hover; 24440 text.text = style->text_hover; 24441 } else if (state & NK_WIDGET_STATE_ACTIVED) { 24442 background = &style->hover; 24443 cursor = &style->cursor_hover; 24444 text.text = style->text_active; 24445 } else { 24446 background = &style->normal; 24447 cursor = &style->cursor_normal; 24448 text.text = style->text_normal; 24449 } 24450 24451 /* draw background and cursor */ 24452 if (background->type == NK_STYLE_ITEM_COLOR) { 24453 nk_fill_rect(out, *selector, 0, style->border_color); 24454 nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color); 24455 } else nk_draw_image(out, *selector, &background->data.image, nk_white); 24456 if (active) { 24457 if (cursor->type == NK_STYLE_ITEM_IMAGE) 24458 nk_draw_image(out, *cursors, &cursor->data.image, nk_white); 24459 else nk_fill_rect(out, *cursors, 0, cursor->data.color); 24460 } 24461 24462 text.padding.x = 0; 24463 text.padding.y = 0; 24464 text.background = style->text_background; 24465 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); 24466 } 24467 NK_LIB void 24468 nk_draw_option(struct nk_command_buffer *out, 24469 nk_flags state, const struct nk_style_toggle *style, nk_bool active, 24470 const struct nk_rect *label, const struct nk_rect *selector, 24471 const struct nk_rect *cursors, const char *string, int len, 24472 const struct nk_user_font *font) 24473 { 24474 const struct nk_style_item *background; 24475 const struct nk_style_item *cursor; 24476 struct nk_text text; 24477 24478 /* select correct colors/images */ 24479 if (state & NK_WIDGET_STATE_HOVER) { 24480 background = &style->hover; 24481 cursor = &style->cursor_hover; 24482 text.text = style->text_hover; 24483 } else if (state & NK_WIDGET_STATE_ACTIVED) { 24484 background = &style->hover; 24485 cursor = &style->cursor_hover; 24486 text.text = style->text_active; 24487 } else { 24488 background = &style->normal; 24489 cursor = &style->cursor_normal; 24490 text.text = style->text_normal; 24491 } 24492 24493 /* draw background and cursor */ 24494 if (background->type == NK_STYLE_ITEM_COLOR) { 24495 nk_fill_circle(out, *selector, style->border_color); 24496 nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color); 24497 } else nk_draw_image(out, *selector, &background->data.image, nk_white); 24498 if (active) { 24499 if (cursor->type == NK_STYLE_ITEM_IMAGE) 24500 nk_draw_image(out, *cursors, &cursor->data.image, nk_white); 24501 else nk_fill_circle(out, *cursors, cursor->data.color); 24502 } 24503 24504 text.padding.x = 0; 24505 text.padding.y = 0; 24506 text.background = style->text_background; 24507 nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); 24508 } 24509 NK_LIB nk_bool 24510 nk_do_toggle(nk_flags *state, 24511 struct nk_command_buffer *out, struct nk_rect r, 24512 nk_bool *active, const char *str, int len, enum nk_toggle_type type, 24513 const struct nk_style_toggle *style, const struct nk_input *in, 24514 const struct nk_user_font *font) 24515 { 24516 int was_active; 24517 struct nk_rect bounds; 24518 struct nk_rect select; 24519 struct nk_rect cursor; 24520 struct nk_rect label; 24521 24522 NK_ASSERT(style); 24523 NK_ASSERT(out); 24524 NK_ASSERT(font); 24525 if (!out || !style || !font || !active) 24526 return 0; 24527 24528 r.w = NK_MAX(r.w, font->height + 2 * style->padding.x); 24529 r.h = NK_MAX(r.h, font->height + 2 * style->padding.y); 24530 24531 /* add additional touch padding for touch screen devices */ 24532 bounds.x = r.x - style->touch_padding.x; 24533 bounds.y = r.y - style->touch_padding.y; 24534 bounds.w = r.w + 2 * style->touch_padding.x; 24535 bounds.h = r.h + 2 * style->touch_padding.y; 24536 24537 /* calculate the selector space */ 24538 select.w = font->height; 24539 select.h = select.w; 24540 select.y = r.y + r.h/2.0f - select.h/2.0f; 24541 select.x = r.x; 24542 24543 /* calculate the bounds of the cursor inside the selector */ 24544 cursor.x = select.x + style->padding.x + style->border; 24545 cursor.y = select.y + style->padding.y + style->border; 24546 cursor.w = select.w - (2 * style->padding.x + 2 * style->border); 24547 cursor.h = select.h - (2 * style->padding.y + 2 * style->border); 24548 24549 /* label behind the selector */ 24550 label.x = select.x + select.w + style->spacing; 24551 label.y = select.y; 24552 label.w = NK_MAX(r.x + r.w, label.x) - label.x; 24553 label.h = select.w; 24554 24555 /* update selector */ 24556 was_active = *active; 24557 *active = nk_toggle_behavior(in, bounds, state, *active); 24558 24559 /* draw selector */ 24560 if (style->draw_begin) 24561 style->draw_begin(out, style->userdata); 24562 if (type == NK_TOGGLE_CHECK) { 24563 nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font); 24564 } else { 24565 nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font); 24566 } 24567 if (style->draw_end) 24568 style->draw_end(out, style->userdata); 24569 return (was_active != *active); 24570 } 24571 /*---------------------------------------------------------------- 24572 * 24573 * CHECKBOX 24574 * 24575 * --------------------------------------------------------------*/ 24576 NK_API nk_bool 24577 nk_check_text(struct nk_context *ctx, const char *text, int len, nk_bool active) 24578 { 24579 struct nk_window *win; 24580 struct nk_panel *layout; 24581 const struct nk_input *in; 24582 const struct nk_style *style; 24583 24584 struct nk_rect bounds; 24585 enum nk_widget_layout_states state; 24586 24587 NK_ASSERT(ctx); 24588 NK_ASSERT(ctx->current); 24589 NK_ASSERT(ctx->current->layout); 24590 if (!ctx || !ctx->current || !ctx->current->layout) 24591 return active; 24592 24593 win = ctx->current; 24594 style = &ctx->style; 24595 layout = win->layout; 24596 24597 state = nk_widget(&bounds, ctx); 24598 if (!state) return active; 24599 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24600 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active, 24601 text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font); 24602 return active; 24603 } 24604 NK_API unsigned int 24605 nk_check_flags_text(struct nk_context *ctx, const char *text, int len, 24606 unsigned int flags, unsigned int value) 24607 { 24608 int old_active; 24609 NK_ASSERT(ctx); 24610 NK_ASSERT(text); 24611 if (!ctx || !text) return flags; 24612 old_active = (int)((flags & value) & value); 24613 if (nk_check_text(ctx, text, len, old_active)) 24614 flags |= value; 24615 else flags &= ~value; 24616 return flags; 24617 } 24618 NK_API nk_bool 24619 nk_checkbox_text(struct nk_context *ctx, const char *text, int len, nk_bool *active) 24620 { 24621 int old_val; 24622 NK_ASSERT(ctx); 24623 NK_ASSERT(text); 24624 NK_ASSERT(active); 24625 if (!ctx || !text || !active) return 0; 24626 old_val = *active; 24627 *active = nk_check_text(ctx, text, len, *active); 24628 return old_val != *active; 24629 } 24630 NK_API nk_bool 24631 nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len, 24632 unsigned int *flags, unsigned int value) 24633 { 24634 nk_bool active; 24635 NK_ASSERT(ctx); 24636 NK_ASSERT(text); 24637 NK_ASSERT(flags); 24638 if (!ctx || !text || !flags) return 0; 24639 24640 active = (int)((*flags & value) & value); 24641 if (nk_checkbox_text(ctx, text, len, &active)) { 24642 if (active) *flags |= value; 24643 else *flags &= ~value; 24644 return 1; 24645 } 24646 return 0; 24647 } 24648 NK_API nk_bool nk_check_label(struct nk_context *ctx, const char *label, nk_bool active) 24649 { 24650 return nk_check_text(ctx, label, nk_strlen(label), active); 24651 } 24652 NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label, 24653 unsigned int flags, unsigned int value) 24654 { 24655 return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value); 24656 } 24657 NK_API nk_bool nk_checkbox_label(struct nk_context *ctx, const char *label, nk_bool *active) 24658 { 24659 return nk_checkbox_text(ctx, label, nk_strlen(label), active); 24660 } 24661 NK_API nk_bool nk_checkbox_flags_label(struct nk_context *ctx, const char *label, 24662 unsigned int *flags, unsigned int value) 24663 { 24664 return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value); 24665 } 24666 /*---------------------------------------------------------------- 24667 * 24668 * OPTION 24669 * 24670 * --------------------------------------------------------------*/ 24671 NK_API nk_bool 24672 nk_option_text(struct nk_context *ctx, const char *text, int len, nk_bool is_active) 24673 { 24674 struct nk_window *win; 24675 struct nk_panel *layout; 24676 const struct nk_input *in; 24677 const struct nk_style *style; 24678 24679 struct nk_rect bounds; 24680 enum nk_widget_layout_states state; 24681 24682 NK_ASSERT(ctx); 24683 NK_ASSERT(ctx->current); 24684 NK_ASSERT(ctx->current->layout); 24685 if (!ctx || !ctx->current || !ctx->current->layout) 24686 return is_active; 24687 24688 win = ctx->current; 24689 style = &ctx->style; 24690 layout = win->layout; 24691 24692 state = nk_widget(&bounds, ctx); 24693 if (!state) return (int)state; 24694 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24695 nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active, 24696 text, len, NK_TOGGLE_OPTION, &style->option, in, style->font); 24697 return is_active; 24698 } 24699 NK_API nk_bool 24700 nk_radio_text(struct nk_context *ctx, const char *text, int len, nk_bool *active) 24701 { 24702 int old_value; 24703 NK_ASSERT(ctx); 24704 NK_ASSERT(text); 24705 NK_ASSERT(active); 24706 if (!ctx || !text || !active) return 0; 24707 old_value = *active; 24708 *active = nk_option_text(ctx, text, len, old_value); 24709 return old_value != *active; 24710 } 24711 NK_API nk_bool 24712 nk_option_label(struct nk_context *ctx, const char *label, nk_bool active) 24713 { 24714 return nk_option_text(ctx, label, nk_strlen(label), active); 24715 } 24716 NK_API nk_bool 24717 nk_radio_label(struct nk_context *ctx, const char *label, nk_bool *active) 24718 { 24719 return nk_radio_text(ctx, label, nk_strlen(label), active); 24720 } 24721 24722 24723 24724 24725 24726 /* =============================================================== 24727 * 24728 * SELECTABLE 24729 * 24730 * ===============================================================*/ 24731 NK_LIB void 24732 nk_draw_selectable(struct nk_command_buffer *out, 24733 nk_flags state, const struct nk_style_selectable *style, nk_bool active, 24734 const struct nk_rect *bounds, 24735 const struct nk_rect *icon, const struct nk_image *img, enum nk_symbol_type sym, 24736 const char *string, int len, nk_flags align, const struct nk_user_font *font) 24737 { 24738 const struct nk_style_item *background; 24739 struct nk_text text; 24740 text.padding = style->padding; 24741 24742 /* select correct colors/images */ 24743 if (!active) { 24744 if (state & NK_WIDGET_STATE_ACTIVED) { 24745 background = &style->pressed; 24746 text.text = style->text_pressed; 24747 } else if (state & NK_WIDGET_STATE_HOVER) { 24748 background = &style->hover; 24749 text.text = style->text_hover; 24750 } else { 24751 background = &style->normal; 24752 text.text = style->text_normal; 24753 } 24754 } else { 24755 if (state & NK_WIDGET_STATE_ACTIVED) { 24756 background = &style->pressed_active; 24757 text.text = style->text_pressed_active; 24758 } else if (state & NK_WIDGET_STATE_HOVER) { 24759 background = &style->hover_active; 24760 text.text = style->text_hover_active; 24761 } else { 24762 background = &style->normal_active; 24763 text.text = style->text_normal_active; 24764 } 24765 } 24766 /* draw selectable background and text */ 24767 switch (background->type) { 24768 case NK_STYLE_ITEM_IMAGE: 24769 text.background = nk_rgba(0, 0, 0, 0); 24770 nk_draw_image(out, *bounds, &background->data.image, nk_white); 24771 break; 24772 case NK_STYLE_ITEM_NINE_SLICE: 24773 text.background = nk_rgba(0, 0, 0, 0); 24774 nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white); 24775 break; 24776 case NK_STYLE_ITEM_COLOR: 24777 text.background = background->data.color; 24778 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 24779 break; 24780 } 24781 if (icon) { 24782 if (img) nk_draw_image(out, *icon, img, nk_white); 24783 else nk_draw_symbol(out, sym, *icon, text.background, text.text, 1, font); 24784 } 24785 nk_widget_text(out, *bounds, string, len, &text, align, font); 24786 } 24787 NK_LIB nk_bool 24788 nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, 24789 struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, 24790 const struct nk_style_selectable *style, const struct nk_input *in, 24791 const struct nk_user_font *font) 24792 { 24793 int old_value; 24794 struct nk_rect touch; 24795 24796 NK_ASSERT(state); 24797 NK_ASSERT(out); 24798 NK_ASSERT(str); 24799 NK_ASSERT(len); 24800 NK_ASSERT(value); 24801 NK_ASSERT(style); 24802 NK_ASSERT(font); 24803 24804 if (!state || !out || !str || !len || !value || !style || !font) return 0; 24805 old_value = *value; 24806 24807 /* remove padding */ 24808 touch.x = bounds.x - style->touch_padding.x; 24809 touch.y = bounds.y - style->touch_padding.y; 24810 touch.w = bounds.w + style->touch_padding.x * 2; 24811 touch.h = bounds.h + style->touch_padding.y * 2; 24812 24813 /* update button */ 24814 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 24815 *value = !(*value); 24816 24817 /* draw selectable */ 24818 if (style->draw_begin) style->draw_begin(out, style->userdata); 24819 nk_draw_selectable(out, *state, style, *value, &bounds, 0,0,NK_SYMBOL_NONE, str, len, align, font); 24820 if (style->draw_end) style->draw_end(out, style->userdata); 24821 return old_value != *value; 24822 } 24823 NK_LIB nk_bool 24824 nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, 24825 struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, 24826 const struct nk_image *img, const struct nk_style_selectable *style, 24827 const struct nk_input *in, const struct nk_user_font *font) 24828 { 24829 nk_bool old_value; 24830 struct nk_rect touch; 24831 struct nk_rect icon; 24832 24833 NK_ASSERT(state); 24834 NK_ASSERT(out); 24835 NK_ASSERT(str); 24836 NK_ASSERT(len); 24837 NK_ASSERT(value); 24838 NK_ASSERT(style); 24839 NK_ASSERT(font); 24840 24841 if (!state || !out || !str || !len || !value || !style || !font) return 0; 24842 old_value = *value; 24843 24844 /* toggle behavior */ 24845 touch.x = bounds.x - style->touch_padding.x; 24846 touch.y = bounds.y - style->touch_padding.y; 24847 touch.w = bounds.w + style->touch_padding.x * 2; 24848 touch.h = bounds.h + style->touch_padding.y * 2; 24849 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 24850 *value = !(*value); 24851 24852 icon.y = bounds.y + style->padding.y; 24853 icon.w = icon.h = bounds.h - 2 * style->padding.y; 24854 if (align & NK_TEXT_ALIGN_LEFT) { 24855 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 24856 icon.x = NK_MAX(icon.x, 0); 24857 } else icon.x = bounds.x + 2 * style->padding.x; 24858 24859 icon.x += style->image_padding.x; 24860 icon.y += style->image_padding.y; 24861 icon.w -= 2 * style->image_padding.x; 24862 icon.h -= 2 * style->image_padding.y; 24863 24864 /* draw selectable */ 24865 if (style->draw_begin) style->draw_begin(out, style->userdata); 24866 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, NK_SYMBOL_NONE, str, len, align, font); 24867 if (style->draw_end) style->draw_end(out, style->userdata); 24868 return old_value != *value; 24869 } 24870 NK_LIB nk_bool 24871 nk_do_selectable_symbol(nk_flags *state, struct nk_command_buffer *out, 24872 struct nk_rect bounds, const char *str, int len, nk_flags align, nk_bool *value, 24873 enum nk_symbol_type sym, const struct nk_style_selectable *style, 24874 const struct nk_input *in, const struct nk_user_font *font) 24875 { 24876 int old_value; 24877 struct nk_rect touch; 24878 struct nk_rect icon; 24879 24880 NK_ASSERT(state); 24881 NK_ASSERT(out); 24882 NK_ASSERT(str); 24883 NK_ASSERT(len); 24884 NK_ASSERT(value); 24885 NK_ASSERT(style); 24886 NK_ASSERT(font); 24887 24888 if (!state || !out || !str || !len || !value || !style || !font) return 0; 24889 old_value = *value; 24890 24891 /* toggle behavior */ 24892 touch.x = bounds.x - style->touch_padding.x; 24893 touch.y = bounds.y - style->touch_padding.y; 24894 touch.w = bounds.w + style->touch_padding.x * 2; 24895 touch.h = bounds.h + style->touch_padding.y * 2; 24896 if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) 24897 *value = !(*value); 24898 24899 icon.y = bounds.y + style->padding.y; 24900 icon.w = icon.h = bounds.h - 2 * style->padding.y; 24901 if (align & NK_TEXT_ALIGN_LEFT) { 24902 icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); 24903 icon.x = NK_MAX(icon.x, 0); 24904 } else icon.x = bounds.x + 2 * style->padding.x; 24905 24906 icon.x += style->image_padding.x; 24907 icon.y += style->image_padding.y; 24908 icon.w -= 2 * style->image_padding.x; 24909 icon.h -= 2 * style->image_padding.y; 24910 24911 /* draw selectable */ 24912 if (style->draw_begin) style->draw_begin(out, style->userdata); 24913 nk_draw_selectable(out, *state, style, *value, &bounds, &icon, 0, sym, str, len, align, font); 24914 if (style->draw_end) style->draw_end(out, style->userdata); 24915 return old_value != *value; 24916 } 24917 24918 NK_API nk_bool 24919 nk_selectable_text(struct nk_context *ctx, const char *str, int len, 24920 nk_flags align, nk_bool *value) 24921 { 24922 struct nk_window *win; 24923 struct nk_panel *layout; 24924 const struct nk_input *in; 24925 const struct nk_style *style; 24926 24927 enum nk_widget_layout_states state; 24928 struct nk_rect bounds; 24929 24930 NK_ASSERT(ctx); 24931 NK_ASSERT(value); 24932 NK_ASSERT(ctx->current); 24933 NK_ASSERT(ctx->current->layout); 24934 if (!ctx || !ctx->current || !ctx->current->layout || !value) 24935 return 0; 24936 24937 win = ctx->current; 24938 layout = win->layout; 24939 style = &ctx->style; 24940 24941 state = nk_widget(&bounds, ctx); 24942 if (!state) return 0; 24943 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24944 return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds, 24945 str, len, align, value, &style->selectable, in, style->font); 24946 } 24947 NK_API nk_bool 24948 nk_selectable_image_text(struct nk_context *ctx, struct nk_image img, 24949 const char *str, int len, nk_flags align, nk_bool *value) 24950 { 24951 struct nk_window *win; 24952 struct nk_panel *layout; 24953 const struct nk_input *in; 24954 const struct nk_style *style; 24955 24956 enum nk_widget_layout_states state; 24957 struct nk_rect bounds; 24958 24959 NK_ASSERT(ctx); 24960 NK_ASSERT(value); 24961 NK_ASSERT(ctx->current); 24962 NK_ASSERT(ctx->current->layout); 24963 if (!ctx || !ctx->current || !ctx->current->layout || !value) 24964 return 0; 24965 24966 win = ctx->current; 24967 layout = win->layout; 24968 style = &ctx->style; 24969 24970 state = nk_widget(&bounds, ctx); 24971 if (!state) return 0; 24972 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 24973 return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds, 24974 str, len, align, value, &img, &style->selectable, in, style->font); 24975 } 24976 NK_API nk_bool 24977 nk_selectable_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 24978 const char *str, int len, nk_flags align, nk_bool *value) 24979 { 24980 struct nk_window *win; 24981 struct nk_panel *layout; 24982 const struct nk_input *in; 24983 const struct nk_style *style; 24984 24985 enum nk_widget_layout_states state; 24986 struct nk_rect bounds; 24987 24988 NK_ASSERT(ctx); 24989 NK_ASSERT(value); 24990 NK_ASSERT(ctx->current); 24991 NK_ASSERT(ctx->current->layout); 24992 if (!ctx || !ctx->current || !ctx->current->layout || !value) 24993 return 0; 24994 24995 win = ctx->current; 24996 layout = win->layout; 24997 style = &ctx->style; 24998 24999 state = nk_widget(&bounds, ctx); 25000 if (!state) return 0; 25001 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 25002 return nk_do_selectable_symbol(&ctx->last_widget_state, &win->buffer, bounds, 25003 str, len, align, value, sym, &style->selectable, in, style->font); 25004 } 25005 NK_API nk_bool 25006 nk_selectable_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 25007 const char *title, nk_flags align, nk_bool *value) 25008 { 25009 return nk_selectable_symbol_text(ctx, sym, title, nk_strlen(title), align, value); 25010 } 25011 NK_API nk_bool nk_select_text(struct nk_context *ctx, const char *str, int len, 25012 nk_flags align, nk_bool value) 25013 { 25014 nk_selectable_text(ctx, str, len, align, &value);return value; 25015 } 25016 NK_API nk_bool nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, nk_bool *value) 25017 { 25018 return nk_selectable_text(ctx, str, nk_strlen(str), align, value); 25019 } 25020 NK_API nk_bool nk_selectable_image_label(struct nk_context *ctx,struct nk_image img, 25021 const char *str, nk_flags align, nk_bool *value) 25022 { 25023 return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value); 25024 } 25025 NK_API nk_bool nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, nk_bool value) 25026 { 25027 nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value; 25028 } 25029 NK_API nk_bool nk_select_image_label(struct nk_context *ctx, struct nk_image img, 25030 const char *str, nk_flags align, nk_bool value) 25031 { 25032 nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value; 25033 } 25034 NK_API nk_bool nk_select_image_text(struct nk_context *ctx, struct nk_image img, 25035 const char *str, int len, nk_flags align, nk_bool value) 25036 { 25037 nk_selectable_image_text(ctx, img, str, len, align, &value);return value; 25038 } 25039 NK_API nk_bool 25040 nk_select_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 25041 const char *title, int title_len, nk_flags align, nk_bool value) 25042 { 25043 nk_selectable_symbol_text(ctx, sym, title, title_len, align, &value);return value; 25044 } 25045 NK_API nk_bool 25046 nk_select_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 25047 const char *title, nk_flags align, nk_bool value) 25048 { 25049 return nk_select_symbol_text(ctx, sym, title, nk_strlen(title), align, value); 25050 } 25051 25052 25053 25054 25055 25056 /* =============================================================== 25057 * 25058 * SLIDER 25059 * 25060 * ===============================================================*/ 25061 NK_LIB float 25062 nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, 25063 struct nk_rect *visual_cursor, struct nk_input *in, 25064 struct nk_rect bounds, float slider_min, float slider_max, float slider_value, 25065 float slider_step, float slider_steps) 25066 { 25067 int left_mouse_down; 25068 int left_mouse_click_in_cursor; 25069 25070 /* check if visual cursor is being dragged */ 25071 nk_widget_state_reset(state); 25072 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 25073 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in, 25074 NK_BUTTON_LEFT, *visual_cursor, nk_true); 25075 25076 if (left_mouse_down && left_mouse_click_in_cursor) { 25077 float ratio = 0; 25078 const float d = in->mouse.pos.x - (visual_cursor->x+visual_cursor->w*0.5f); 25079 const float pxstep = bounds.w / slider_steps; 25080 25081 /* only update value if the next slider step is reached */ 25082 *state = NK_WIDGET_STATE_ACTIVE; 25083 if (NK_ABS(d) >= pxstep) { 25084 const float steps = (float)((int)(NK_ABS(d) / pxstep)); 25085 slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps); 25086 slider_value = NK_CLAMP(slider_min, slider_value, slider_max); 25087 ratio = (slider_value - slider_min)/slider_step; 25088 logical_cursor->x = bounds.x + (logical_cursor->w * ratio); 25089 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x; 25090 } 25091 } 25092 25093 /* slider widget state */ 25094 if (nk_input_is_mouse_hovering_rect(in, bounds)) 25095 *state = NK_WIDGET_STATE_HOVERED; 25096 if (*state & NK_WIDGET_STATE_HOVER && 25097 !nk_input_is_mouse_prev_hovering_rect(in, bounds)) 25098 *state |= NK_WIDGET_STATE_ENTERED; 25099 else if (nk_input_is_mouse_prev_hovering_rect(in, bounds)) 25100 *state |= NK_WIDGET_STATE_LEFT; 25101 return slider_value; 25102 } 25103 NK_LIB void 25104 nk_draw_slider(struct nk_command_buffer *out, nk_flags state, 25105 const struct nk_style_slider *style, const struct nk_rect *bounds, 25106 const struct nk_rect *visual_cursor, float min, float value, float max) 25107 { 25108 struct nk_rect fill; 25109 struct nk_rect bar; 25110 const struct nk_style_item *background; 25111 25112 /* select correct slider images/colors */ 25113 struct nk_color bar_color; 25114 const struct nk_style_item *cursor; 25115 25116 NK_UNUSED(min); 25117 NK_UNUSED(max); 25118 NK_UNUSED(value); 25119 25120 if (state & NK_WIDGET_STATE_ACTIVED) { 25121 background = &style->active; 25122 bar_color = style->bar_active; 25123 cursor = &style->cursor_active; 25124 } else if (state & NK_WIDGET_STATE_HOVER) { 25125 background = &style->hover; 25126 bar_color = style->bar_hover; 25127 cursor = &style->cursor_hover; 25128 } else { 25129 background = &style->normal; 25130 bar_color = style->bar_normal; 25131 cursor = &style->cursor_normal; 25132 } 25133 /* calculate slider background bar */ 25134 bar.x = bounds->x; 25135 bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12; 25136 bar.w = bounds->w; 25137 bar.h = bounds->h/6; 25138 25139 /* filled background bar style */ 25140 fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x; 25141 fill.x = bar.x; 25142 fill.y = bar.y; 25143 fill.h = bar.h; 25144 25145 /* draw background */ 25146 switch(background->type) { 25147 case NK_STYLE_ITEM_IMAGE: 25148 nk_draw_image(out, *bounds, &background->data.image, nk_white); 25149 break; 25150 case NK_STYLE_ITEM_NINE_SLICE: 25151 nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white); 25152 break; 25153 case NK_STYLE_ITEM_COLOR: 25154 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 25155 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 25156 break; 25157 } 25158 25159 /* draw slider bar */ 25160 nk_fill_rect(out, bar, style->rounding, bar_color); 25161 nk_fill_rect(out, fill, style->rounding, style->bar_filled); 25162 25163 /* draw cursor */ 25164 if (cursor->type == NK_STYLE_ITEM_IMAGE) 25165 nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white); 25166 else 25167 nk_fill_circle(out, *visual_cursor, cursor->data.color); 25168 } 25169 NK_LIB float 25170 nk_do_slider(nk_flags *state, 25171 struct nk_command_buffer *out, struct nk_rect bounds, 25172 float min, float val, float max, float step, 25173 const struct nk_style_slider *style, struct nk_input *in, 25174 const struct nk_user_font *font) 25175 { 25176 float slider_range; 25177 float slider_min; 25178 float slider_max; 25179 float slider_value; 25180 float slider_steps; 25181 float cursor_offset; 25182 25183 struct nk_rect visual_cursor; 25184 struct nk_rect logical_cursor; 25185 25186 NK_ASSERT(style); 25187 NK_ASSERT(out); 25188 if (!out || !style) 25189 return 0; 25190 25191 /* remove padding from slider bounds */ 25192 bounds.x = bounds.x + style->padding.x; 25193 bounds.y = bounds.y + style->padding.y; 25194 bounds.h = NK_MAX(bounds.h, 2*style->padding.y); 25195 bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x); 25196 bounds.w -= 2 * style->padding.x; 25197 bounds.h -= 2 * style->padding.y; 25198 25199 /* optional buttons */ 25200 if (style->show_buttons) { 25201 nk_flags ws; 25202 struct nk_rect button; 25203 button.y = bounds.y; 25204 button.w = bounds.h; 25205 button.h = bounds.h; 25206 25207 /* decrement button */ 25208 button.x = bounds.x; 25209 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT, 25210 &style->dec_button, in, font)) 25211 val -= step; 25212 25213 /* increment button */ 25214 button.x = (bounds.x + bounds.w) - button.w; 25215 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT, 25216 &style->inc_button, in, font)) 25217 val += step; 25218 25219 bounds.x = bounds.x + button.w + style->spacing.x; 25220 bounds.w = bounds.w - (2*button.w + 2*style->spacing.x); 25221 } 25222 25223 /* remove one cursor size to support visual cursor */ 25224 bounds.x += style->cursor_size.x*0.5f; 25225 bounds.w -= style->cursor_size.x; 25226 25227 /* make sure the provided values are correct */ 25228 slider_max = NK_MAX(min, max); 25229 slider_min = NK_MIN(min, max); 25230 slider_value = NK_CLAMP(slider_min, val, slider_max); 25231 slider_range = slider_max - slider_min; 25232 slider_steps = slider_range / step; 25233 cursor_offset = (slider_value - slider_min) / step; 25234 25235 /* calculate cursor 25236 Basically you have two cursors. One for visual representation and interaction 25237 and one for updating the actual cursor value. */ 25238 logical_cursor.h = bounds.h; 25239 logical_cursor.w = bounds.w / slider_steps; 25240 logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset); 25241 logical_cursor.y = bounds.y; 25242 25243 visual_cursor.h = style->cursor_size.y; 25244 visual_cursor.w = style->cursor_size.x; 25245 visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f; 25246 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; 25247 25248 slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor, 25249 in, bounds, slider_min, slider_max, slider_value, step, slider_steps); 25250 visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; 25251 25252 /* draw slider */ 25253 if (style->draw_begin) style->draw_begin(out, style->userdata); 25254 nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max); 25255 if (style->draw_end) style->draw_end(out, style->userdata); 25256 return slider_value; 25257 } 25258 NK_API nk_bool 25259 nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value, 25260 float value_step) 25261 { 25262 struct nk_window *win; 25263 struct nk_panel *layout; 25264 struct nk_input *in; 25265 const struct nk_style *style; 25266 25267 int ret = 0; 25268 float old_value; 25269 struct nk_rect bounds; 25270 enum nk_widget_layout_states state; 25271 25272 NK_ASSERT(ctx); 25273 NK_ASSERT(ctx->current); 25274 NK_ASSERT(ctx->current->layout); 25275 NK_ASSERT(value); 25276 if (!ctx || !ctx->current || !ctx->current->layout || !value) 25277 return ret; 25278 25279 win = ctx->current; 25280 style = &ctx->style; 25281 layout = win->layout; 25282 25283 state = nk_widget(&bounds, ctx); 25284 if (!state) return ret; 25285 in = (/*state == NK_WIDGET_ROM || */ layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 25286 25287 old_value = *value; 25288 *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value, 25289 old_value, max_value, value_step, &style->slider, in, style->font); 25290 return (old_value > *value || old_value < *value); 25291 } 25292 NK_API float 25293 nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step) 25294 { 25295 nk_slider_float(ctx, min, &val, max, step); return val; 25296 } 25297 NK_API int 25298 nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step) 25299 { 25300 float value = (float)val; 25301 nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); 25302 return (int)value; 25303 } 25304 NK_API nk_bool 25305 nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step) 25306 { 25307 int ret; 25308 float value = (float)*val; 25309 ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); 25310 *val = (int)value; 25311 return ret; 25312 } 25313 25314 25315 25316 25317 25318 /* =============================================================== 25319 * 25320 * PROGRESS 25321 * 25322 * ===============================================================*/ 25323 NK_LIB nk_size 25324 nk_progress_behavior(nk_flags *state, struct nk_input *in, 25325 struct nk_rect r, struct nk_rect cursor, nk_size max, nk_size value, nk_bool modifiable) 25326 { 25327 int left_mouse_down = 0; 25328 int left_mouse_click_in_cursor = 0; 25329 25330 nk_widget_state_reset(state); 25331 if (!in || !modifiable) return value; 25332 left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 25333 left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in, 25334 NK_BUTTON_LEFT, cursor, nk_true); 25335 if (nk_input_is_mouse_hovering_rect(in, r)) 25336 *state = NK_WIDGET_STATE_HOVERED; 25337 25338 if (in && left_mouse_down && left_mouse_click_in_cursor) { 25339 if (left_mouse_down && left_mouse_click_in_cursor) { 25340 float ratio = NK_MAX(0, (float)(in->mouse.pos.x - cursor.x)) / (float)cursor.w; 25341 value = (nk_size)NK_CLAMP(0, (float)max * ratio, (float)max); 25342 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor.x + cursor.w/2.0f; 25343 *state |= NK_WIDGET_STATE_ACTIVE; 25344 } 25345 } 25346 /* set progressbar widget state */ 25347 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r)) 25348 *state |= NK_WIDGET_STATE_ENTERED; 25349 else if (nk_input_is_mouse_prev_hovering_rect(in, r)) 25350 *state |= NK_WIDGET_STATE_LEFT; 25351 return value; 25352 } 25353 NK_LIB void 25354 nk_draw_progress(struct nk_command_buffer *out, nk_flags state, 25355 const struct nk_style_progress *style, const struct nk_rect *bounds, 25356 const struct nk_rect *scursor, nk_size value, nk_size max) 25357 { 25358 const struct nk_style_item *background; 25359 const struct nk_style_item *cursor; 25360 25361 NK_UNUSED(max); 25362 NK_UNUSED(value); 25363 25364 /* select correct colors/images to draw */ 25365 if (state & NK_WIDGET_STATE_ACTIVED) { 25366 background = &style->active; 25367 cursor = &style->cursor_active; 25368 } else if (state & NK_WIDGET_STATE_HOVER){ 25369 background = &style->hover; 25370 cursor = &style->cursor_hover; 25371 } else { 25372 background = &style->normal; 25373 cursor = &style->cursor_normal; 25374 } 25375 25376 /* draw background */ 25377 switch(background->type) { 25378 case NK_STYLE_ITEM_IMAGE: 25379 nk_draw_image(out, *bounds, &background->data.image, nk_white); 25380 break; 25381 case NK_STYLE_ITEM_NINE_SLICE: 25382 nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white); 25383 break; 25384 case NK_STYLE_ITEM_COLOR: 25385 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 25386 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 25387 break; 25388 } 25389 25390 /* draw cursor */ 25391 switch(cursor->type) { 25392 case NK_STYLE_ITEM_IMAGE: 25393 nk_draw_image(out, *scursor, &cursor->data.image, nk_white); 25394 break; 25395 case NK_STYLE_ITEM_NINE_SLICE: 25396 nk_draw_nine_slice(out, *scursor, &cursor->data.slice, nk_white); 25397 break; 25398 case NK_STYLE_ITEM_COLOR: 25399 nk_fill_rect(out, *scursor, style->rounding, cursor->data.color); 25400 nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color); 25401 break; 25402 } 25403 } 25404 NK_LIB nk_size 25405 nk_do_progress(nk_flags *state, 25406 struct nk_command_buffer *out, struct nk_rect bounds, 25407 nk_size value, nk_size max, nk_bool modifiable, 25408 const struct nk_style_progress *style, struct nk_input *in) 25409 { 25410 float prog_scale; 25411 nk_size prog_value; 25412 struct nk_rect cursor; 25413 25414 NK_ASSERT(style); 25415 NK_ASSERT(out); 25416 if (!out || !style) return 0; 25417 25418 /* calculate progressbar cursor */ 25419 cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border); 25420 cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border); 25421 cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border)); 25422 prog_scale = (float)value / (float)max; 25423 25424 /* update progressbar */ 25425 prog_value = NK_MIN(value, max); 25426 prog_value = nk_progress_behavior(state, in, bounds, cursor,max, prog_value, modifiable); 25427 cursor.w = cursor.w * prog_scale; 25428 25429 /* draw progressbar */ 25430 if (style->draw_begin) style->draw_begin(out, style->userdata); 25431 nk_draw_progress(out, *state, style, &bounds, &cursor, value, max); 25432 if (style->draw_end) style->draw_end(out, style->userdata); 25433 return prog_value; 25434 } 25435 NK_API nk_bool 25436 nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, nk_bool is_modifyable) 25437 { 25438 struct nk_window *win; 25439 struct nk_panel *layout; 25440 const struct nk_style *style; 25441 struct nk_input *in; 25442 25443 struct nk_rect bounds; 25444 enum nk_widget_layout_states state; 25445 nk_size old_value; 25446 25447 NK_ASSERT(ctx); 25448 NK_ASSERT(cur); 25449 NK_ASSERT(ctx->current); 25450 NK_ASSERT(ctx->current->layout); 25451 if (!ctx || !ctx->current || !ctx->current->layout || !cur) 25452 return 0; 25453 25454 win = ctx->current; 25455 style = &ctx->style; 25456 layout = win->layout; 25457 state = nk_widget(&bounds, ctx); 25458 if (!state) return 0; 25459 25460 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 25461 old_value = *cur; 25462 *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds, 25463 *cur, max, is_modifyable, &style->progress, in); 25464 return (*cur != old_value); 25465 } 25466 NK_API nk_size 25467 nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, nk_bool modifyable) 25468 { 25469 nk_progress(ctx, &cur, max, modifyable); 25470 return cur; 25471 } 25472 25473 25474 25475 25476 25477 /* =============================================================== 25478 * 25479 * SCROLLBAR 25480 * 25481 * ===============================================================*/ 25482 NK_LIB float 25483 nk_scrollbar_behavior(nk_flags *state, struct nk_input *in, 25484 int has_scrolling, const struct nk_rect *scroll, 25485 const struct nk_rect *cursor, const struct nk_rect *empty0, 25486 const struct nk_rect *empty1, float scroll_offset, 25487 float target, float scroll_step, enum nk_orientation o) 25488 { 25489 nk_flags ws = 0; 25490 int left_mouse_down; 25491 unsigned int left_mouse_clicked; 25492 int left_mouse_click_in_cursor; 25493 float scroll_delta; 25494 25495 nk_widget_state_reset(state); 25496 if (!in) return scroll_offset; 25497 25498 left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; 25499 left_mouse_clicked = in->mouse.buttons[NK_BUTTON_LEFT].clicked; 25500 left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, 25501 NK_BUTTON_LEFT, *cursor, nk_true); 25502 if (nk_input_is_mouse_hovering_rect(in, *scroll)) 25503 *state = NK_WIDGET_STATE_HOVERED; 25504 25505 scroll_delta = (o == NK_VERTICAL) ? in->mouse.scroll_delta.y: in->mouse.scroll_delta.x; 25506 if (left_mouse_down && left_mouse_click_in_cursor && !left_mouse_clicked) { 25507 /* update cursor by mouse dragging */ 25508 float pixel, delta; 25509 *state = NK_WIDGET_STATE_ACTIVE; 25510 if (o == NK_VERTICAL) { 25511 float cursor_y; 25512 pixel = in->mouse.delta.y; 25513 delta = (pixel / scroll->h) * target; 25514 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h); 25515 cursor_y = scroll->y + ((scroll_offset/target) * scroll->h); 25516 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f; 25517 } else { 25518 float cursor_x; 25519 pixel = in->mouse.delta.x; 25520 delta = (pixel / scroll->w) * target; 25521 scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w); 25522 cursor_x = scroll->x + ((scroll_offset/target) * scroll->w); 25523 in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f; 25524 } 25525 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)|| 25526 nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) { 25527 /* scroll page up by click on empty space or shortcut */ 25528 if (o == NK_VERTICAL) 25529 scroll_offset = NK_MAX(0, scroll_offset - scroll->h); 25530 else scroll_offset = NK_MAX(0, scroll_offset - scroll->w); 25531 } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) || 25532 nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) { 25533 /* scroll page down by click on empty space or shortcut */ 25534 if (o == NK_VERTICAL) 25535 scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h); 25536 else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w); 25537 } else if (has_scrolling) { 25538 if ((scroll_delta < 0 || (scroll_delta > 0))) { 25539 /* update cursor by mouse scrolling */ 25540 scroll_offset = scroll_offset + scroll_step * (-scroll_delta); 25541 if (o == NK_VERTICAL) 25542 scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h); 25543 else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w); 25544 } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) { 25545 /* update cursor to the beginning */ 25546 if (o == NK_VERTICAL) scroll_offset = 0; 25547 } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) { 25548 /* update cursor to the end */ 25549 if (o == NK_VERTICAL) scroll_offset = target - scroll->h; 25550 } 25551 } 25552 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll)) 25553 *state |= NK_WIDGET_STATE_ENTERED; 25554 else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll)) 25555 *state |= NK_WIDGET_STATE_LEFT; 25556 return scroll_offset; 25557 } 25558 NK_LIB void 25559 nk_draw_scrollbar(struct nk_command_buffer *out, nk_flags state, 25560 const struct nk_style_scrollbar *style, const struct nk_rect *bounds, 25561 const struct nk_rect *scroll) 25562 { 25563 const struct nk_style_item *background; 25564 const struct nk_style_item *cursor; 25565 25566 /* select correct colors/images to draw */ 25567 if (state & NK_WIDGET_STATE_ACTIVED) { 25568 background = &style->active; 25569 cursor = &style->cursor_active; 25570 } else if (state & NK_WIDGET_STATE_HOVER) { 25571 background = &style->hover; 25572 cursor = &style->cursor_hover; 25573 } else { 25574 background = &style->normal; 25575 cursor = &style->cursor_normal; 25576 } 25577 25578 /* draw background */ 25579 switch (background->type) { 25580 case NK_STYLE_ITEM_IMAGE: 25581 nk_draw_image(out, *bounds, &background->data.image, nk_white); 25582 break; 25583 case NK_STYLE_ITEM_NINE_SLICE: 25584 nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white); 25585 break; 25586 case NK_STYLE_ITEM_COLOR: 25587 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 25588 nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); 25589 break; 25590 } 25591 25592 /* draw cursor */ 25593 switch (cursor->type) { 25594 case NK_STYLE_ITEM_IMAGE: 25595 nk_draw_image(out, *scroll, &cursor->data.image, nk_white); 25596 break; 25597 case NK_STYLE_ITEM_NINE_SLICE: 25598 nk_draw_nine_slice(out, *scroll, &cursor->data.slice, nk_white); 25599 break; 25600 case NK_STYLE_ITEM_COLOR: 25601 nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color); 25602 nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color); 25603 break; 25604 } 25605 } 25606 NK_LIB float 25607 nk_do_scrollbarv(nk_flags *state, 25608 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, 25609 float offset, float target, float step, float button_pixel_inc, 25610 const struct nk_style_scrollbar *style, struct nk_input *in, 25611 const struct nk_user_font *font) 25612 { 25613 struct nk_rect empty_north; 25614 struct nk_rect empty_south; 25615 struct nk_rect cursor; 25616 25617 float scroll_step; 25618 float scroll_offset; 25619 float scroll_off; 25620 float scroll_ratio; 25621 25622 NK_ASSERT(out); 25623 NK_ASSERT(style); 25624 NK_ASSERT(state); 25625 if (!out || !style) return 0; 25626 25627 scroll.w = NK_MAX(scroll.w, 1); 25628 scroll.h = NK_MAX(scroll.h, 0); 25629 if (target <= scroll.h) return 0; 25630 25631 /* optional scrollbar buttons */ 25632 if (style->show_buttons) { 25633 nk_flags ws; 25634 float scroll_h; 25635 struct nk_rect button; 25636 25637 button.x = scroll.x; 25638 button.w = scroll.w; 25639 button.h = scroll.w; 25640 25641 scroll_h = NK_MAX(scroll.h - 2 * button.h,0); 25642 scroll_step = NK_MIN(step, button_pixel_inc); 25643 25644 /* decrement button */ 25645 button.y = scroll.y; 25646 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, 25647 NK_BUTTON_REPEATER, &style->dec_button, in, font)) 25648 offset = offset - scroll_step; 25649 25650 /* increment button */ 25651 button.y = scroll.y + scroll.h - button.h; 25652 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, 25653 NK_BUTTON_REPEATER, &style->inc_button, in, font)) 25654 offset = offset + scroll_step; 25655 25656 scroll.y = scroll.y + button.h; 25657 scroll.h = scroll_h; 25658 } 25659 25660 /* calculate scrollbar constants */ 25661 scroll_step = NK_MIN(step, scroll.h); 25662 scroll_offset = NK_CLAMP(0, offset, target - scroll.h); 25663 scroll_ratio = scroll.h / target; 25664 scroll_off = scroll_offset / target; 25665 25666 /* calculate scrollbar cursor bounds */ 25667 cursor.h = NK_MAX((scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y), 0); 25668 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y; 25669 cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x); 25670 cursor.x = scroll.x + style->border + style->padding.x; 25671 25672 /* calculate empty space around cursor */ 25673 empty_north.x = scroll.x; 25674 empty_north.y = scroll.y; 25675 empty_north.w = scroll.w; 25676 empty_north.h = NK_MAX(cursor.y - scroll.y, 0); 25677 25678 empty_south.x = scroll.x; 25679 empty_south.y = cursor.y + cursor.h; 25680 empty_south.w = scroll.w; 25681 empty_south.h = NK_MAX((scroll.y + scroll.h) - (cursor.y + cursor.h), 0); 25682 25683 /* update scrollbar */ 25684 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, 25685 &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL); 25686 scroll_off = scroll_offset / target; 25687 cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y; 25688 25689 /* draw scrollbar */ 25690 if (style->draw_begin) style->draw_begin(out, style->userdata); 25691 nk_draw_scrollbar(out, *state, style, &scroll, &cursor); 25692 if (style->draw_end) style->draw_end(out, style->userdata); 25693 return scroll_offset; 25694 } 25695 NK_LIB float 25696 nk_do_scrollbarh(nk_flags *state, 25697 struct nk_command_buffer *out, struct nk_rect scroll, int has_scrolling, 25698 float offset, float target, float step, float button_pixel_inc, 25699 const struct nk_style_scrollbar *style, struct nk_input *in, 25700 const struct nk_user_font *font) 25701 { 25702 struct nk_rect cursor; 25703 struct nk_rect empty_west; 25704 struct nk_rect empty_east; 25705 25706 float scroll_step; 25707 float scroll_offset; 25708 float scroll_off; 25709 float scroll_ratio; 25710 25711 NK_ASSERT(out); 25712 NK_ASSERT(style); 25713 if (!out || !style) return 0; 25714 25715 /* scrollbar background */ 25716 scroll.h = NK_MAX(scroll.h, 1); 25717 scroll.w = NK_MAX(scroll.w, 2 * scroll.h); 25718 if (target <= scroll.w) return 0; 25719 25720 /* optional scrollbar buttons */ 25721 if (style->show_buttons) { 25722 nk_flags ws; 25723 float scroll_w; 25724 struct nk_rect button; 25725 button.y = scroll.y; 25726 button.w = scroll.h; 25727 button.h = scroll.h; 25728 25729 scroll_w = scroll.w - 2 * button.w; 25730 scroll_step = NK_MIN(step, button_pixel_inc); 25731 25732 /* decrement button */ 25733 button.x = scroll.x; 25734 if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, 25735 NK_BUTTON_REPEATER, &style->dec_button, in, font)) 25736 offset = offset - scroll_step; 25737 25738 /* increment button */ 25739 button.x = scroll.x + scroll.w - button.w; 25740 if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, 25741 NK_BUTTON_REPEATER, &style->inc_button, in, font)) 25742 offset = offset + scroll_step; 25743 25744 scroll.x = scroll.x + button.w; 25745 scroll.w = scroll_w; 25746 } 25747 25748 /* calculate scrollbar constants */ 25749 scroll_step = NK_MIN(step, scroll.w); 25750 scroll_offset = NK_CLAMP(0, offset, target - scroll.w); 25751 scroll_ratio = scroll.w / target; 25752 scroll_off = scroll_offset / target; 25753 25754 /* calculate cursor bounds */ 25755 cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x); 25756 cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x; 25757 cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y); 25758 cursor.y = scroll.y + style->border + style->padding.y; 25759 25760 /* calculate empty space around cursor */ 25761 empty_west.x = scroll.x; 25762 empty_west.y = scroll.y; 25763 empty_west.w = cursor.x - scroll.x; 25764 empty_west.h = scroll.h; 25765 25766 empty_east.x = cursor.x + cursor.w; 25767 empty_east.y = scroll.y; 25768 empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w); 25769 empty_east.h = scroll.h; 25770 25771 /* update scrollbar */ 25772 scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, 25773 &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL); 25774 scroll_off = scroll_offset / target; 25775 cursor.x = scroll.x + (scroll_off * scroll.w); 25776 25777 /* draw scrollbar */ 25778 if (style->draw_begin) style->draw_begin(out, style->userdata); 25779 nk_draw_scrollbar(out, *state, style, &scroll, &cursor); 25780 if (style->draw_end) style->draw_end(out, style->userdata); 25781 return scroll_offset; 25782 } 25783 25784 25785 25786 25787 25788 /* =============================================================== 25789 * 25790 * TEXT EDITOR 25791 * 25792 * ===============================================================*/ 25793 /* stb_textedit.h - v1.8 - public domain - Sean Barrett */ 25794 struct nk_text_find { 25795 float x,y; /* position of n'th character */ 25796 float height; /* height of line */ 25797 int first_char, length; /* first char of row, and length */ 25798 int prev_first; /*_ first char of previous row */ 25799 }; 25800 25801 struct nk_text_edit_row { 25802 float x0,x1; 25803 /* starting x location, end x location (allows for align=right, etc) */ 25804 float baseline_y_delta; 25805 /* position of baseline relative to previous row's baseline*/ 25806 float ymin,ymax; 25807 /* height of row above and below baseline */ 25808 int num_chars; 25809 }; 25810 25811 /* forward declarations */ 25812 NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int); 25813 NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int); 25814 NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int); 25815 #define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) 25816 25817 NK_INTERN float 25818 nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id, 25819 const struct nk_user_font *font) 25820 { 25821 int len = 0; 25822 nk_rune unicode = 0; 25823 const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len); 25824 return font->width(font->userdata, font->height, str, len); 25825 } 25826 NK_INTERN void 25827 nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit, 25828 int line_start_id, float row_height, const struct nk_user_font *font) 25829 { 25830 int l; 25831 int glyphs = 0; 25832 nk_rune unicode; 25833 const char *remaining; 25834 int len = nk_str_len_char(&edit->string); 25835 const char *end = nk_str_get_const(&edit->string) + len; 25836 const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l); 25837 const struct nk_vec2 size = nk_text_calculate_text_bounds(font, 25838 text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE); 25839 25840 r->x0 = 0.0f; 25841 r->x1 = size.x; 25842 r->baseline_y_delta = size.y; 25843 r->ymin = 0.0f; 25844 r->ymax = size.y; 25845 r->num_chars = glyphs; 25846 } 25847 NK_INTERN int 25848 nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y, 25849 const struct nk_user_font *font, float row_height) 25850 { 25851 struct nk_text_edit_row r; 25852 int n = edit->string.len; 25853 float base_y = 0, prev_x; 25854 int i=0, k; 25855 25856 r.x0 = r.x1 = 0; 25857 r.ymin = r.ymax = 0; 25858 r.num_chars = 0; 25859 25860 /* search rows to find one that straddles 'y' */ 25861 while (i < n) { 25862 nk_textedit_layout_row(&r, edit, i, row_height, font); 25863 if (r.num_chars <= 0) 25864 return n; 25865 25866 if (i==0 && y < base_y + r.ymin) 25867 return 0; 25868 25869 if (y < base_y + r.ymax) 25870 break; 25871 25872 i += r.num_chars; 25873 base_y += r.baseline_y_delta; 25874 } 25875 25876 /* below all text, return 'after' last character */ 25877 if (i >= n) 25878 return n; 25879 25880 /* check if it's before the beginning of the line */ 25881 if (x < r.x0) 25882 return i; 25883 25884 /* check if it's before the end of the line */ 25885 if (x < r.x1) { 25886 /* search characters in row for one that straddles 'x' */ 25887 k = i; 25888 prev_x = r.x0; 25889 for (i=0; i < r.num_chars; ++i) { 25890 float w = nk_textedit_get_width(edit, k, i, font); 25891 if (x < prev_x+w) { 25892 if (x < prev_x+w/2) 25893 return k+i; 25894 else return k+i+1; 25895 } 25896 prev_x += w; 25897 } 25898 /* shouldn't happen, but if it does, fall through to end-of-line case */ 25899 } 25900 25901 /* if the last character is a newline, return that. 25902 * otherwise return 'after' the last character */ 25903 if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n') 25904 return i+r.num_chars-1; 25905 else return i+r.num_chars; 25906 } 25907 NK_LIB void 25908 nk_textedit_click(struct nk_text_edit *state, float x, float y, 25909 const struct nk_user_font *font, float row_height) 25910 { 25911 /* API click: on mouse down, move the cursor to the clicked location, 25912 * and reset the selection */ 25913 state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height); 25914 state->select_start = state->cursor; 25915 state->select_end = state->cursor; 25916 state->has_preferred_x = 0; 25917 } 25918 NK_LIB void 25919 nk_textedit_drag(struct nk_text_edit *state, float x, float y, 25920 const struct nk_user_font *font, float row_height) 25921 { 25922 /* API drag: on mouse drag, move the cursor and selection endpoint 25923 * to the clicked location */ 25924 int p = nk_textedit_locate_coord(state, x, y, font, row_height); 25925 if (state->select_start == state->select_end) 25926 state->select_start = state->cursor; 25927 state->cursor = state->select_end = p; 25928 } 25929 NK_INTERN void 25930 nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state, 25931 int n, int single_line, const struct nk_user_font *font, float row_height) 25932 { 25933 /* find the x/y location of a character, and remember info about the previous 25934 * row in case we get a move-up event (for page up, we'll have to rescan) */ 25935 struct nk_text_edit_row r; 25936 int prev_start = 0; 25937 int z = state->string.len; 25938 int i=0, first; 25939 25940 nk_zero_struct(r); 25941 if (n == z) { 25942 /* if it's at the end, then find the last line -- simpler than trying to 25943 explicitly handle this case in the regular code */ 25944 nk_textedit_layout_row(&r, state, 0, row_height, font); 25945 if (single_line) { 25946 find->first_char = 0; 25947 find->length = z; 25948 } else { 25949 while (i < z) { 25950 prev_start = i; 25951 i += r.num_chars; 25952 nk_textedit_layout_row(&r, state, i, row_height, font); 25953 } 25954 25955 find->first_char = i; 25956 find->length = r.num_chars; 25957 } 25958 find->x = r.x1; 25959 find->y = r.ymin; 25960 find->height = r.ymax - r.ymin; 25961 find->prev_first = prev_start; 25962 return; 25963 } 25964 25965 /* search rows to find the one that straddles character n */ 25966 find->y = 0; 25967 25968 for(;;) { 25969 nk_textedit_layout_row(&r, state, i, row_height, font); 25970 if (n < i + r.num_chars) break; 25971 prev_start = i; 25972 i += r.num_chars; 25973 find->y += r.baseline_y_delta; 25974 } 25975 25976 find->first_char = first = i; 25977 find->length = r.num_chars; 25978 find->height = r.ymax - r.ymin; 25979 find->prev_first = prev_start; 25980 25981 /* now scan to find xpos */ 25982 find->x = r.x0; 25983 for (i=0; first+i < n; ++i) 25984 find->x += nk_textedit_get_width(state, first, i, font); 25985 } 25986 NK_INTERN void 25987 nk_textedit_clamp(struct nk_text_edit *state) 25988 { 25989 /* make the selection/cursor state valid if client altered the string */ 25990 int n = state->string.len; 25991 if (NK_TEXT_HAS_SELECTION(state)) { 25992 if (state->select_start > n) state->select_start = n; 25993 if (state->select_end > n) state->select_end = n; 25994 /* if clamping forced them to be equal, move the cursor to match */ 25995 if (state->select_start == state->select_end) 25996 state->cursor = state->select_start; 25997 } 25998 if (state->cursor > n) state->cursor = n; 25999 } 26000 NK_API void 26001 nk_textedit_delete(struct nk_text_edit *state, int where, int len) 26002 { 26003 /* delete characters while updating undo */ 26004 nk_textedit_makeundo_delete(state, where, len); 26005 nk_str_delete_runes(&state->string, where, len); 26006 state->has_preferred_x = 0; 26007 } 26008 NK_API void 26009 nk_textedit_delete_selection(struct nk_text_edit *state) 26010 { 26011 /* delete the section */ 26012 nk_textedit_clamp(state); 26013 if (NK_TEXT_HAS_SELECTION(state)) { 26014 if (state->select_start < state->select_end) { 26015 nk_textedit_delete(state, state->select_start, 26016 state->select_end - state->select_start); 26017 state->select_end = state->cursor = state->select_start; 26018 } else { 26019 nk_textedit_delete(state, state->select_end, 26020 state->select_start - state->select_end); 26021 state->select_start = state->cursor = state->select_end; 26022 } 26023 state->has_preferred_x = 0; 26024 } 26025 } 26026 NK_INTERN void 26027 nk_textedit_sortselection(struct nk_text_edit *state) 26028 { 26029 /* canonicalize the selection so start <= end */ 26030 if (state->select_end < state->select_start) { 26031 int temp = state->select_end; 26032 state->select_end = state->select_start; 26033 state->select_start = temp; 26034 } 26035 } 26036 NK_INTERN void 26037 nk_textedit_move_to_first(struct nk_text_edit *state) 26038 { 26039 /* move cursor to first character of selection */ 26040 if (NK_TEXT_HAS_SELECTION(state)) { 26041 nk_textedit_sortselection(state); 26042 state->cursor = state->select_start; 26043 state->select_end = state->select_start; 26044 state->has_preferred_x = 0; 26045 } 26046 } 26047 NK_INTERN void 26048 nk_textedit_move_to_last(struct nk_text_edit *state) 26049 { 26050 /* move cursor to last character of selection */ 26051 if (NK_TEXT_HAS_SELECTION(state)) { 26052 nk_textedit_sortselection(state); 26053 nk_textedit_clamp(state); 26054 state->cursor = state->select_end; 26055 state->select_start = state->select_end; 26056 state->has_preferred_x = 0; 26057 } 26058 } 26059 NK_INTERN int 26060 nk_is_word_boundary( struct nk_text_edit *state, int idx) 26061 { 26062 int len; 26063 nk_rune c; 26064 if (idx <= 0) return 1; 26065 if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1; 26066 return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' || 26067 c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' || 26068 c == '|'); 26069 } 26070 NK_INTERN int 26071 nk_textedit_move_to_word_previous(struct nk_text_edit *state) 26072 { 26073 int c = state->cursor - 1; 26074 while( c >= 0 && !nk_is_word_boundary(state, c)) 26075 --c; 26076 26077 if( c < 0 ) 26078 c = 0; 26079 26080 return c; 26081 } 26082 NK_INTERN int 26083 nk_textedit_move_to_word_next(struct nk_text_edit *state) 26084 { 26085 const int len = state->string.len; 26086 int c = state->cursor+1; 26087 while( c < len && !nk_is_word_boundary(state, c)) 26088 ++c; 26089 26090 if( c > len ) 26091 c = len; 26092 26093 return c; 26094 } 26095 NK_INTERN void 26096 nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state) 26097 { 26098 /* update selection and cursor to match each other */ 26099 if (!NK_TEXT_HAS_SELECTION(state)) 26100 state->select_start = state->select_end = state->cursor; 26101 else state->cursor = state->select_end; 26102 } 26103 NK_API nk_bool 26104 nk_textedit_cut(struct nk_text_edit *state) 26105 { 26106 /* API cut: delete selection */ 26107 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 26108 return 0; 26109 if (NK_TEXT_HAS_SELECTION(state)) { 26110 nk_textedit_delete_selection(state); /* implicitly clamps */ 26111 state->has_preferred_x = 0; 26112 return 1; 26113 } 26114 return 0; 26115 } 26116 NK_API nk_bool 26117 nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len) 26118 { 26119 /* API paste: replace existing selection with passed-in text */ 26120 int glyphs; 26121 const char *text = (const char *) ctext; 26122 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0; 26123 26124 /* if there's a selection, the paste should delete it */ 26125 nk_textedit_clamp(state); 26126 nk_textedit_delete_selection(state); 26127 26128 /* try to insert the characters */ 26129 glyphs = nk_utf_len(ctext, len); 26130 if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) { 26131 nk_textedit_makeundo_insert(state, state->cursor, glyphs); 26132 state->cursor += len; 26133 state->has_preferred_x = 0; 26134 return 1; 26135 } 26136 /* remove the undo since we didn't actually insert the characters */ 26137 if (state->undo.undo_point) 26138 --state->undo.undo_point; 26139 return 0; 26140 } 26141 NK_API void 26142 nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len) 26143 { 26144 nk_rune unicode; 26145 int glyph_len; 26146 int text_len = 0; 26147 26148 NK_ASSERT(state); 26149 NK_ASSERT(text); 26150 if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return; 26151 26152 glyph_len = nk_utf_decode(text, &unicode, total_len); 26153 while ((text_len < total_len) && glyph_len) 26154 { 26155 /* don't insert a backward delete, just process the event */ 26156 if (unicode == 127) goto next; 26157 /* can't add newline in single-line mode */ 26158 if (unicode == '\n' && state->single_line) goto next; 26159 /* filter incoming text */ 26160 if (state->filter && !state->filter(state, unicode)) goto next; 26161 26162 if (!NK_TEXT_HAS_SELECTION(state) && 26163 state->cursor < state->string.len) 26164 { 26165 if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) { 26166 nk_textedit_makeundo_replace(state, state->cursor, 1, 1); 26167 nk_str_delete_runes(&state->string, state->cursor, 1); 26168 } 26169 if (nk_str_insert_text_utf8(&state->string, state->cursor, 26170 text+text_len, 1)) 26171 { 26172 ++state->cursor; 26173 state->has_preferred_x = 0; 26174 } 26175 } else { 26176 nk_textedit_delete_selection(state); /* implicitly clamps */ 26177 if (nk_str_insert_text_utf8(&state->string, state->cursor, 26178 text+text_len, 1)) 26179 { 26180 nk_textedit_makeundo_insert(state, state->cursor, 1); 26181 state->cursor = NK_MIN(state->cursor + 1, state->string.len); 26182 state->has_preferred_x = 0; 26183 } 26184 } 26185 next: 26186 text_len += glyph_len; 26187 glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len); 26188 } 26189 } 26190 NK_LIB void 26191 nk_textedit_key(struct nk_text_edit *state, enum nk_keys key, int shift_mod, 26192 const struct nk_user_font *font, float row_height) 26193 { 26194 retry: 26195 switch (key) 26196 { 26197 case NK_KEY_NONE: 26198 case NK_KEY_CTRL: 26199 case NK_KEY_ENTER: 26200 case NK_KEY_SHIFT: 26201 case NK_KEY_TAB: 26202 case NK_KEY_COPY: 26203 case NK_KEY_CUT: 26204 case NK_KEY_PASTE: 26205 case NK_KEY_MAX: 26206 default: break; 26207 case NK_KEY_TEXT_UNDO: 26208 nk_textedit_undo(state); 26209 state->has_preferred_x = 0; 26210 break; 26211 26212 case NK_KEY_TEXT_REDO: 26213 nk_textedit_redo(state); 26214 state->has_preferred_x = 0; 26215 break; 26216 26217 case NK_KEY_TEXT_SELECT_ALL: 26218 nk_textedit_select_all(state); 26219 state->has_preferred_x = 0; 26220 break; 26221 26222 case NK_KEY_TEXT_INSERT_MODE: 26223 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 26224 state->mode = NK_TEXT_EDIT_MODE_INSERT; 26225 break; 26226 case NK_KEY_TEXT_REPLACE_MODE: 26227 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 26228 state->mode = NK_TEXT_EDIT_MODE_REPLACE; 26229 break; 26230 case NK_KEY_TEXT_RESET_MODE: 26231 if (state->mode == NK_TEXT_EDIT_MODE_INSERT || 26232 state->mode == NK_TEXT_EDIT_MODE_REPLACE) 26233 state->mode = NK_TEXT_EDIT_MODE_VIEW; 26234 break; 26235 26236 case NK_KEY_LEFT: 26237 if (shift_mod) { 26238 nk_textedit_clamp(state); 26239 nk_textedit_prep_selection_at_cursor(state); 26240 /* move selection left */ 26241 if (state->select_end > 0) 26242 --state->select_end; 26243 state->cursor = state->select_end; 26244 state->has_preferred_x = 0; 26245 } else { 26246 /* if currently there's a selection, 26247 * move cursor to start of selection */ 26248 if (NK_TEXT_HAS_SELECTION(state)) 26249 nk_textedit_move_to_first(state); 26250 else if (state->cursor > 0) 26251 --state->cursor; 26252 state->has_preferred_x = 0; 26253 } break; 26254 26255 case NK_KEY_RIGHT: 26256 if (shift_mod) { 26257 nk_textedit_prep_selection_at_cursor(state); 26258 /* move selection right */ 26259 ++state->select_end; 26260 nk_textedit_clamp(state); 26261 state->cursor = state->select_end; 26262 state->has_preferred_x = 0; 26263 } else { 26264 /* if currently there's a selection, 26265 * move cursor to end of selection */ 26266 if (NK_TEXT_HAS_SELECTION(state)) 26267 nk_textedit_move_to_last(state); 26268 else ++state->cursor; 26269 nk_textedit_clamp(state); 26270 state->has_preferred_x = 0; 26271 } break; 26272 26273 case NK_KEY_TEXT_WORD_LEFT: 26274 if (shift_mod) { 26275 if( !NK_TEXT_HAS_SELECTION( state ) ) 26276 nk_textedit_prep_selection_at_cursor(state); 26277 state->cursor = nk_textedit_move_to_word_previous(state); 26278 state->select_end = state->cursor; 26279 nk_textedit_clamp(state ); 26280 } else { 26281 if (NK_TEXT_HAS_SELECTION(state)) 26282 nk_textedit_move_to_first(state); 26283 else { 26284 state->cursor = nk_textedit_move_to_word_previous(state); 26285 nk_textedit_clamp(state ); 26286 } 26287 } break; 26288 26289 case NK_KEY_TEXT_WORD_RIGHT: 26290 if (shift_mod) { 26291 if( !NK_TEXT_HAS_SELECTION( state ) ) 26292 nk_textedit_prep_selection_at_cursor(state); 26293 state->cursor = nk_textedit_move_to_word_next(state); 26294 state->select_end = state->cursor; 26295 nk_textedit_clamp(state); 26296 } else { 26297 if (NK_TEXT_HAS_SELECTION(state)) 26298 nk_textedit_move_to_last(state); 26299 else { 26300 state->cursor = nk_textedit_move_to_word_next(state); 26301 nk_textedit_clamp(state ); 26302 } 26303 } break; 26304 26305 case NK_KEY_DOWN: { 26306 struct nk_text_find find; 26307 struct nk_text_edit_row row; 26308 int i, sel = shift_mod; 26309 26310 if (state->single_line) { 26311 /* on windows, up&down in single-line behave like left&right */ 26312 key = NK_KEY_RIGHT; 26313 goto retry; 26314 } 26315 26316 if (sel) 26317 nk_textedit_prep_selection_at_cursor(state); 26318 else if (NK_TEXT_HAS_SELECTION(state)) 26319 nk_textedit_move_to_last(state); 26320 26321 /* compute current position of cursor point */ 26322 nk_textedit_clamp(state); 26323 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 26324 font, row_height); 26325 26326 /* now find character position down a row */ 26327 if (find.length) 26328 { 26329 float x; 26330 float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 26331 int start = find.first_char + find.length; 26332 26333 state->cursor = start; 26334 nk_textedit_layout_row(&row, state, state->cursor, row_height, font); 26335 x = row.x0; 26336 26337 for (i=0; i < row.num_chars && x < row.x1; ++i) { 26338 float dx = nk_textedit_get_width(state, start, i, font); 26339 x += dx; 26340 if (x > goal_x) 26341 break; 26342 ++state->cursor; 26343 } 26344 nk_textedit_clamp(state); 26345 26346 state->has_preferred_x = 1; 26347 state->preferred_x = goal_x; 26348 if (sel) 26349 state->select_end = state->cursor; 26350 } 26351 } break; 26352 26353 case NK_KEY_UP: { 26354 struct nk_text_find find; 26355 struct nk_text_edit_row row; 26356 int i, sel = shift_mod; 26357 26358 if (state->single_line) { 26359 /* on windows, up&down become left&right */ 26360 key = NK_KEY_LEFT; 26361 goto retry; 26362 } 26363 26364 if (sel) 26365 nk_textedit_prep_selection_at_cursor(state); 26366 else if (NK_TEXT_HAS_SELECTION(state)) 26367 nk_textedit_move_to_first(state); 26368 26369 /* compute current position of cursor point */ 26370 nk_textedit_clamp(state); 26371 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 26372 font, row_height); 26373 26374 /* can only go up if there's a previous row */ 26375 if (find.prev_first != find.first_char) { 26376 /* now find character position up a row */ 26377 float x; 26378 float goal_x = state->has_preferred_x ? state->preferred_x : find.x; 26379 26380 state->cursor = find.prev_first; 26381 nk_textedit_layout_row(&row, state, state->cursor, row_height, font); 26382 x = row.x0; 26383 26384 for (i=0; i < row.num_chars && x < row.x1; ++i) { 26385 float dx = nk_textedit_get_width(state, find.prev_first, i, font); 26386 x += dx; 26387 if (x > goal_x) 26388 break; 26389 ++state->cursor; 26390 } 26391 nk_textedit_clamp(state); 26392 26393 state->has_preferred_x = 1; 26394 state->preferred_x = goal_x; 26395 if (sel) state->select_end = state->cursor; 26396 } 26397 } break; 26398 26399 case NK_KEY_DEL: 26400 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 26401 break; 26402 if (NK_TEXT_HAS_SELECTION(state)) 26403 nk_textedit_delete_selection(state); 26404 else { 26405 int n = state->string.len; 26406 if (state->cursor < n) 26407 nk_textedit_delete(state, state->cursor, 1); 26408 } 26409 state->has_preferred_x = 0; 26410 break; 26411 26412 case NK_KEY_BACKSPACE: 26413 if (state->mode == NK_TEXT_EDIT_MODE_VIEW) 26414 break; 26415 if (NK_TEXT_HAS_SELECTION(state)) 26416 nk_textedit_delete_selection(state); 26417 else { 26418 nk_textedit_clamp(state); 26419 if (state->cursor > 0) { 26420 nk_textedit_delete(state, state->cursor-1, 1); 26421 --state->cursor; 26422 } 26423 } 26424 state->has_preferred_x = 0; 26425 break; 26426 26427 case NK_KEY_TEXT_START: 26428 if (shift_mod) { 26429 nk_textedit_prep_selection_at_cursor(state); 26430 state->cursor = state->select_end = 0; 26431 state->has_preferred_x = 0; 26432 } else { 26433 state->cursor = state->select_start = state->select_end = 0; 26434 state->has_preferred_x = 0; 26435 } 26436 break; 26437 26438 case NK_KEY_TEXT_END: 26439 if (shift_mod) { 26440 nk_textedit_prep_selection_at_cursor(state); 26441 state->cursor = state->select_end = state->string.len; 26442 state->has_preferred_x = 0; 26443 } else { 26444 state->cursor = state->string.len; 26445 state->select_start = state->select_end = 0; 26446 state->has_preferred_x = 0; 26447 } 26448 break; 26449 26450 case NK_KEY_TEXT_LINE_START: { 26451 if (shift_mod) { 26452 struct nk_text_find find; 26453 nk_textedit_clamp(state); 26454 nk_textedit_prep_selection_at_cursor(state); 26455 if (state->string.len && state->cursor == state->string.len) 26456 --state->cursor; 26457 nk_textedit_find_charpos(&find, state,state->cursor, state->single_line, 26458 font, row_height); 26459 state->cursor = state->select_end = find.first_char; 26460 state->has_preferred_x = 0; 26461 } else { 26462 struct nk_text_find find; 26463 if (state->string.len && state->cursor == state->string.len) 26464 --state->cursor; 26465 nk_textedit_clamp(state); 26466 nk_textedit_move_to_first(state); 26467 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 26468 font, row_height); 26469 state->cursor = find.first_char; 26470 state->has_preferred_x = 0; 26471 } 26472 } break; 26473 26474 case NK_KEY_TEXT_LINE_END: { 26475 if (shift_mod) { 26476 struct nk_text_find find; 26477 nk_textedit_clamp(state); 26478 nk_textedit_prep_selection_at_cursor(state); 26479 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 26480 font, row_height); 26481 state->has_preferred_x = 0; 26482 state->cursor = find.first_char + find.length; 26483 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') 26484 --state->cursor; 26485 state->select_end = state->cursor; 26486 } else { 26487 struct nk_text_find find; 26488 nk_textedit_clamp(state); 26489 nk_textedit_move_to_first(state); 26490 nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, 26491 font, row_height); 26492 26493 state->has_preferred_x = 0; 26494 state->cursor = find.first_char + find.length; 26495 if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') 26496 --state->cursor; 26497 }} break; 26498 } 26499 } 26500 NK_INTERN void 26501 nk_textedit_flush_redo(struct nk_text_undo_state *state) 26502 { 26503 state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; 26504 state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; 26505 } 26506 NK_INTERN void 26507 nk_textedit_discard_undo(struct nk_text_undo_state *state) 26508 { 26509 /* discard the oldest entry in the undo list */ 26510 if (state->undo_point > 0) { 26511 /* if the 0th undo state has characters, clean those up */ 26512 if (state->undo_rec[0].char_storage >= 0) { 26513 int n = state->undo_rec[0].insert_length, i; 26514 /* delete n characters from all other records */ 26515 state->undo_char_point = (short)(state->undo_char_point - n); 26516 NK_MEMCPY(state->undo_char, state->undo_char + n, 26517 (nk_size)state->undo_char_point*sizeof(nk_rune)); 26518 for (i=0; i < state->undo_point; ++i) { 26519 if (state->undo_rec[i].char_storage >= 0) 26520 state->undo_rec[i].char_storage = (short) 26521 (state->undo_rec[i].char_storage - n); 26522 } 26523 } 26524 --state->undo_point; 26525 NK_MEMCPY(state->undo_rec, state->undo_rec+1, 26526 (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0]))); 26527 } 26528 } 26529 NK_INTERN void 26530 nk_textedit_discard_redo(struct nk_text_undo_state *state) 26531 { 26532 /* discard the oldest entry in the redo list--it's bad if this 26533 ever happens, but because undo & redo have to store the actual 26534 characters in different cases, the redo character buffer can 26535 fill up even though the undo buffer didn't */ 26536 nk_size num; 26537 int k = NK_TEXTEDIT_UNDOSTATECOUNT-1; 26538 if (state->redo_point <= k) { 26539 /* if the k'th undo state has characters, clean those up */ 26540 if (state->undo_rec[k].char_storage >= 0) { 26541 int n = state->undo_rec[k].insert_length, i; 26542 /* delete n characters from all other records */ 26543 state->redo_char_point = (short)(state->redo_char_point + n); 26544 num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point); 26545 NK_MEMCPY(state->undo_char + state->redo_char_point, 26546 state->undo_char + state->redo_char_point-n, num * sizeof(char)); 26547 for (i = state->redo_point; i < k; ++i) { 26548 if (state->undo_rec[i].char_storage >= 0) { 26549 state->undo_rec[i].char_storage = (short) 26550 (state->undo_rec[i].char_storage + n); 26551 } 26552 } 26553 } 26554 ++state->redo_point; 26555 num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point); 26556 if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1, 26557 state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0])); 26558 } 26559 } 26560 NK_INTERN struct nk_text_undo_record* 26561 nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars) 26562 { 26563 /* any time we create a new undo record, we discard redo*/ 26564 nk_textedit_flush_redo(state); 26565 26566 /* if we have no free records, we have to make room, 26567 * by sliding the existing records down */ 26568 if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 26569 nk_textedit_discard_undo(state); 26570 26571 /* if the characters to store won't possibly fit in the buffer, 26572 * we can't undo */ 26573 if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) { 26574 state->undo_point = 0; 26575 state->undo_char_point = 0; 26576 return 0; 26577 } 26578 26579 /* if we don't have enough free characters in the buffer, 26580 * we have to make room */ 26581 while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT) 26582 nk_textedit_discard_undo(state); 26583 return &state->undo_rec[state->undo_point++]; 26584 } 26585 NK_INTERN nk_rune* 26586 nk_textedit_createundo(struct nk_text_undo_state *state, int pos, 26587 int insert_len, int delete_len) 26588 { 26589 struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len); 26590 if (r == 0) 26591 return 0; 26592 26593 r->where = pos; 26594 r->insert_length = (short) insert_len; 26595 r->delete_length = (short) delete_len; 26596 26597 if (insert_len == 0) { 26598 r->char_storage = -1; 26599 return 0; 26600 } else { 26601 r->char_storage = state->undo_char_point; 26602 state->undo_char_point = (short)(state->undo_char_point + insert_len); 26603 return &state->undo_char[r->char_storage]; 26604 } 26605 } 26606 NK_API void 26607 nk_textedit_undo(struct nk_text_edit *state) 26608 { 26609 struct nk_text_undo_state *s = &state->undo; 26610 struct nk_text_undo_record u, *r; 26611 if (s->undo_point == 0) 26612 return; 26613 26614 /* we need to do two things: apply the undo record, and create a redo record */ 26615 u = s->undo_rec[s->undo_point-1]; 26616 r = &s->undo_rec[s->redo_point-1]; 26617 r->char_storage = -1; 26618 26619 r->insert_length = u.delete_length; 26620 r->delete_length = u.insert_length; 26621 r->where = u.where; 26622 26623 if (u.delete_length) 26624 { 26625 /* if the undo record says to delete characters, then the redo record will 26626 need to re-insert the characters that get deleted, so we need to store 26627 them. 26628 there are three cases: 26629 - there's enough room to store the characters 26630 - characters stored for *redoing* don't leave room for redo 26631 - characters stored for *undoing* don't leave room for redo 26632 if the last is true, we have to bail */ 26633 if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) { 26634 /* the undo records take up too much character space; there's no space 26635 * to store the redo characters */ 26636 r->insert_length = 0; 26637 } else { 26638 int i; 26639 /* there's definitely room to store the characters eventually */ 26640 while (s->undo_char_point + u.delete_length > s->redo_char_point) { 26641 /* there's currently not enough room, so discard a redo record */ 26642 nk_textedit_discard_redo(s); 26643 /* should never happen: */ 26644 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 26645 return; 26646 } 26647 26648 r = &s->undo_rec[s->redo_point-1]; 26649 r->char_storage = (short)(s->redo_char_point - u.delete_length); 26650 s->redo_char_point = (short)(s->redo_char_point - u.delete_length); 26651 26652 /* now save the characters */ 26653 for (i=0; i < u.delete_length; ++i) 26654 s->undo_char[r->char_storage + i] = 26655 nk_str_rune_at(&state->string, u.where + i); 26656 } 26657 /* now we can carry out the deletion */ 26658 nk_str_delete_runes(&state->string, u.where, u.delete_length); 26659 } 26660 26661 /* check type of recorded action: */ 26662 if (u.insert_length) { 26663 /* easy case: was a deletion, so we need to insert n characters */ 26664 nk_str_insert_text_runes(&state->string, u.where, 26665 &s->undo_char[u.char_storage], u.insert_length); 26666 s->undo_char_point = (short)(s->undo_char_point - u.insert_length); 26667 } 26668 state->cursor = (short)(u.where + u.insert_length); 26669 26670 s->undo_point--; 26671 s->redo_point--; 26672 } 26673 NK_API void 26674 nk_textedit_redo(struct nk_text_edit *state) 26675 { 26676 struct nk_text_undo_state *s = &state->undo; 26677 struct nk_text_undo_record *u, r; 26678 if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) 26679 return; 26680 26681 /* we need to do two things: apply the redo record, and create an undo record */ 26682 u = &s->undo_rec[s->undo_point]; 26683 r = s->undo_rec[s->redo_point]; 26684 26685 /* we KNOW there must be room for the undo record, because the redo record 26686 was derived from an undo record */ 26687 u->delete_length = r.insert_length; 26688 u->insert_length = r.delete_length; 26689 u->where = r.where; 26690 u->char_storage = -1; 26691 26692 if (r.delete_length) { 26693 /* the redo record requires us to delete characters, so the undo record 26694 needs to store the characters */ 26695 if (s->undo_char_point + u->insert_length > s->redo_char_point) { 26696 u->insert_length = 0; 26697 u->delete_length = 0; 26698 } else { 26699 int i; 26700 u->char_storage = s->undo_char_point; 26701 s->undo_char_point = (short)(s->undo_char_point + u->insert_length); 26702 26703 /* now save the characters */ 26704 for (i=0; i < u->insert_length; ++i) { 26705 s->undo_char[u->char_storage + i] = 26706 nk_str_rune_at(&state->string, u->where + i); 26707 } 26708 } 26709 nk_str_delete_runes(&state->string, r.where, r.delete_length); 26710 } 26711 26712 if (r.insert_length) { 26713 /* easy case: need to insert n characters */ 26714 nk_str_insert_text_runes(&state->string, r.where, 26715 &s->undo_char[r.char_storage], r.insert_length); 26716 } 26717 state->cursor = r.where + r.insert_length; 26718 26719 s->undo_point++; 26720 s->redo_point++; 26721 } 26722 NK_INTERN void 26723 nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length) 26724 { 26725 nk_textedit_createundo(&state->undo, where, 0, length); 26726 } 26727 NK_INTERN void 26728 nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length) 26729 { 26730 int i; 26731 nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0); 26732 if (p) { 26733 for (i=0; i < length; ++i) 26734 p[i] = nk_str_rune_at(&state->string, where+i); 26735 } 26736 } 26737 NK_INTERN void 26738 nk_textedit_makeundo_replace(struct nk_text_edit *state, int where, 26739 int old_length, int new_length) 26740 { 26741 int i; 26742 nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length); 26743 if (p) { 26744 for (i=0; i < old_length; ++i) 26745 p[i] = nk_str_rune_at(&state->string, where+i); 26746 } 26747 } 26748 NK_LIB void 26749 nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, 26750 nk_plugin_filter filter) 26751 { 26752 /* reset the state to default */ 26753 state->undo.undo_point = 0; 26754 state->undo.undo_char_point = 0; 26755 state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; 26756 state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; 26757 state->select_end = state->select_start = 0; 26758 state->cursor = 0; 26759 state->has_preferred_x = 0; 26760 state->preferred_x = 0; 26761 state->cursor_at_end_of_line = 0; 26762 state->initialized = 1; 26763 state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE); 26764 state->mode = NK_TEXT_EDIT_MODE_VIEW; 26765 state->filter = filter; 26766 state->scrollbar = nk_vec2(0,0); 26767 } 26768 NK_API void 26769 nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size) 26770 { 26771 NK_ASSERT(state); 26772 NK_ASSERT(memory); 26773 if (!state || !memory || !size) return; 26774 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 26775 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 26776 nk_str_init_fixed(&state->string, memory, size); 26777 } 26778 NK_API void 26779 nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size) 26780 { 26781 NK_ASSERT(state); 26782 NK_ASSERT(alloc); 26783 if (!state || !alloc) return; 26784 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 26785 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 26786 nk_str_init(&state->string, alloc, size); 26787 } 26788 #ifdef NK_INCLUDE_DEFAULT_ALLOCATOR 26789 NK_API void 26790 nk_textedit_init_default(struct nk_text_edit *state) 26791 { 26792 NK_ASSERT(state); 26793 if (!state) return; 26794 NK_MEMSET(state, 0, sizeof(struct nk_text_edit)); 26795 nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); 26796 nk_str_init_default(&state->string); 26797 } 26798 #endif 26799 NK_API void 26800 nk_textedit_select_all(struct nk_text_edit *state) 26801 { 26802 NK_ASSERT(state); 26803 state->select_start = 0; 26804 state->select_end = state->string.len; 26805 } 26806 NK_API void 26807 nk_textedit_free(struct nk_text_edit *state) 26808 { 26809 NK_ASSERT(state); 26810 if (!state) return; 26811 nk_str_free(&state->string); 26812 } 26813 26814 26815 26816 26817 26818 /* =============================================================== 26819 * 26820 * FILTER 26821 * 26822 * ===============================================================*/ 26823 NK_API nk_bool 26824 nk_filter_default(const struct nk_text_edit *box, nk_rune unicode) 26825 { 26826 NK_UNUSED(unicode); 26827 NK_UNUSED(box); 26828 return nk_true; 26829 } 26830 NK_API nk_bool 26831 nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode) 26832 { 26833 NK_UNUSED(box); 26834 if (unicode > 128) return nk_false; 26835 else return nk_true; 26836 } 26837 NK_API nk_bool 26838 nk_filter_float(const struct nk_text_edit *box, nk_rune unicode) 26839 { 26840 NK_UNUSED(box); 26841 if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-') 26842 return nk_false; 26843 else return nk_true; 26844 } 26845 NK_API nk_bool 26846 nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode) 26847 { 26848 NK_UNUSED(box); 26849 if ((unicode < '0' || unicode > '9') && unicode != '-') 26850 return nk_false; 26851 else return nk_true; 26852 } 26853 NK_API nk_bool 26854 nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode) 26855 { 26856 NK_UNUSED(box); 26857 if ((unicode < '0' || unicode > '9') && 26858 (unicode < 'a' || unicode > 'f') && 26859 (unicode < 'A' || unicode > 'F')) 26860 return nk_false; 26861 else return nk_true; 26862 } 26863 NK_API nk_bool 26864 nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode) 26865 { 26866 NK_UNUSED(box); 26867 if (unicode < '0' || unicode > '7') 26868 return nk_false; 26869 else return nk_true; 26870 } 26871 NK_API nk_bool 26872 nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode) 26873 { 26874 NK_UNUSED(box); 26875 if (unicode != '0' && unicode != '1') 26876 return nk_false; 26877 else return nk_true; 26878 } 26879 26880 /* =============================================================== 26881 * 26882 * EDIT 26883 * 26884 * ===============================================================*/ 26885 NK_LIB void 26886 nk_edit_draw_text(struct nk_command_buffer *out, 26887 const struct nk_style_edit *style, float pos_x, float pos_y, 26888 float x_offset, const char *text, int byte_len, float row_height, 26889 const struct nk_user_font *font, struct nk_color background, 26890 struct nk_color foreground, nk_bool is_selected) 26891 { 26892 NK_ASSERT(out); 26893 NK_ASSERT(font); 26894 NK_ASSERT(style); 26895 if (!text || !byte_len || !out || !style) return; 26896 26897 {int glyph_len = 0; 26898 nk_rune unicode = 0; 26899 int text_len = 0; 26900 float line_width = 0; 26901 float glyph_width; 26902 const char *line = text; 26903 float line_offset = 0; 26904 int line_count = 0; 26905 26906 struct nk_text txt; 26907 txt.padding = nk_vec2(0,0); 26908 txt.background = background; 26909 txt.text = foreground; 26910 26911 glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len); 26912 if (!glyph_len) return; 26913 while ((text_len < byte_len) && glyph_len) 26914 { 26915 if (unicode == '\n') { 26916 /* new line separator so draw previous line */ 26917 struct nk_rect label; 26918 label.y = pos_y + line_offset; 26919 label.h = row_height; 26920 label.w = line_width; 26921 label.x = pos_x; 26922 if (!line_count) 26923 label.x += x_offset; 26924 26925 if (is_selected) /* selection needs to draw different background color */ 26926 nk_fill_rect(out, label, 0, background); 26927 nk_widget_text(out, label, line, (int)((text + text_len) - line), 26928 &txt, NK_TEXT_CENTERED, font); 26929 26930 text_len++; 26931 line_count++; 26932 line_width = 0; 26933 line = text + text_len; 26934 line_offset += row_height; 26935 glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len)); 26936 continue; 26937 } 26938 if (unicode == '\r') { 26939 text_len++; 26940 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); 26941 continue; 26942 } 26943 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); 26944 line_width += (float)glyph_width; 26945 text_len += glyph_len; 26946 glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); 26947 continue; 26948 } 26949 if (line_width > 0) { 26950 /* draw last line */ 26951 struct nk_rect label; 26952 label.y = pos_y + line_offset; 26953 label.h = row_height; 26954 label.w = line_width; 26955 label.x = pos_x; 26956 if (!line_count) 26957 label.x += x_offset; 26958 26959 if (is_selected) 26960 nk_fill_rect(out, label, 0, background); 26961 nk_widget_text(out, label, line, (int)((text + text_len) - line), 26962 &txt, NK_TEXT_LEFT, font); 26963 }} 26964 } 26965 NK_LIB nk_flags 26966 nk_do_edit(nk_flags *state, struct nk_command_buffer *out, 26967 struct nk_rect bounds, nk_flags flags, nk_plugin_filter filter, 26968 struct nk_text_edit *edit, const struct nk_style_edit *style, 26969 struct nk_input *in, const struct nk_user_font *font) 26970 { 26971 struct nk_rect area; 26972 nk_flags ret = 0; 26973 float row_height; 26974 char prev_state = 0; 26975 char is_hovered = 0; 26976 char select_all = 0; 26977 char cursor_follow = 0; 26978 struct nk_rect old_clip; 26979 struct nk_rect clip; 26980 26981 NK_ASSERT(state); 26982 NK_ASSERT(out); 26983 NK_ASSERT(style); 26984 if (!state || !out || !style) 26985 return ret; 26986 26987 /* visible text area calculation */ 26988 area.x = bounds.x + style->padding.x + style->border; 26989 area.y = bounds.y + style->padding.y + style->border; 26990 area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border); 26991 area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border); 26992 if (flags & NK_EDIT_MULTILINE) 26993 area.w = NK_MAX(0, area.w - style->scrollbar_size.x); 26994 row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h; 26995 26996 /* calculate clipping rectangle */ 26997 old_clip = out->clip; 26998 nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h); 26999 27000 /* update edit state */ 27001 prev_state = (char)edit->active; 27002 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds); 27003 if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) { 27004 edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, 27005 bounds.x, bounds.y, bounds.w, bounds.h); 27006 } 27007 27008 /* (de)activate text editor */ 27009 if (!prev_state && edit->active) { 27010 const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ? 27011 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE; 27012 /* keep scroll position when re-activating edit widget */ 27013 struct nk_vec2 oldscrollbar = edit->scrollbar; 27014 nk_textedit_clear_state(edit, type, filter); 27015 edit->scrollbar = oldscrollbar; 27016 if (flags & NK_EDIT_AUTO_SELECT) 27017 select_all = nk_true; 27018 if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) { 27019 edit->cursor = edit->string.len; 27020 in = 0; 27021 } 27022 } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW; 27023 if (flags & NK_EDIT_READ_ONLY) 27024 edit->mode = NK_TEXT_EDIT_MODE_VIEW; 27025 else if (flags & NK_EDIT_ALWAYS_INSERT_MODE) 27026 edit->mode = NK_TEXT_EDIT_MODE_INSERT; 27027 27028 ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE; 27029 if (prev_state != edit->active) 27030 ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED; 27031 27032 /* handle user input */ 27033 if (edit->active && in) 27034 { 27035 int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down; 27036 const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x; 27037 const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y; 27038 27039 /* mouse click handler */ 27040 is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area); 27041 if (select_all) { 27042 nk_textedit_select_all(edit); 27043 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && 27044 in->mouse.buttons[NK_BUTTON_LEFT].clicked) { 27045 nk_textedit_click(edit, mouse_x, mouse_y, font, row_height); 27046 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && 27047 (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) { 27048 nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height); 27049 cursor_follow = nk_true; 27050 } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked && 27051 in->mouse.buttons[NK_BUTTON_RIGHT].down) { 27052 nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height); 27053 nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height); 27054 cursor_follow = nk_true; 27055 } 27056 27057 {int i; /* keyboard input */ 27058 int old_mode = edit->mode; 27059 for (i = 0; i < NK_KEY_MAX; ++i) { 27060 if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */ 27061 if (nk_input_is_key_pressed(in, (enum nk_keys)i)) { 27062 nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height); 27063 cursor_follow = nk_true; 27064 } 27065 } 27066 if (old_mode != edit->mode) { 27067 in->keyboard.text_len = 0; 27068 }} 27069 27070 /* text input */ 27071 edit->filter = filter; 27072 if (in->keyboard.text_len) { 27073 nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len); 27074 cursor_follow = nk_true; 27075 in->keyboard.text_len = 0; 27076 } 27077 27078 /* enter key handler */ 27079 if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) { 27080 cursor_follow = nk_true; 27081 if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod) 27082 nk_textedit_text(edit, "\n", 1); 27083 else if (flags & NK_EDIT_SIG_ENTER) 27084 ret |= NK_EDIT_COMMITED; 27085 else nk_textedit_text(edit, "\n", 1); 27086 } 27087 27088 /* cut & copy handler */ 27089 {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY); 27090 int cut = nk_input_is_key_pressed(in, NK_KEY_CUT); 27091 if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD)) 27092 { 27093 int glyph_len; 27094 nk_rune unicode; 27095 const char *text; 27096 int b = edit->select_start; 27097 int e = edit->select_end; 27098 27099 int begin = NK_MIN(b, e); 27100 int end = NK_MAX(b, e); 27101 text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len); 27102 if (edit->clip.copy) 27103 edit->clip.copy(edit->clip.userdata, text, end - begin); 27104 if (cut && !(flags & NK_EDIT_READ_ONLY)){ 27105 nk_textedit_cut(edit); 27106 cursor_follow = nk_true; 27107 } 27108 }} 27109 27110 /* paste handler */ 27111 {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE); 27112 if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) { 27113 edit->clip.paste(edit->clip.userdata, edit); 27114 cursor_follow = nk_true; 27115 }} 27116 27117 /* tab handler */ 27118 {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB); 27119 if (tab && (flags & NK_EDIT_ALLOW_TAB)) { 27120 nk_textedit_text(edit, " ", 4); 27121 cursor_follow = nk_true; 27122 }} 27123 } 27124 27125 /* set widget state */ 27126 if (edit->active) 27127 *state = NK_WIDGET_STATE_ACTIVE; 27128 else nk_widget_state_reset(state); 27129 27130 if (is_hovered) 27131 *state |= NK_WIDGET_STATE_HOVERED; 27132 27133 /* DRAW EDIT */ 27134 {const char *text = nk_str_get_const(&edit->string); 27135 int len = nk_str_len_char(&edit->string); 27136 27137 {/* select background colors/images */ 27138 const struct nk_style_item *background; 27139 if (*state & NK_WIDGET_STATE_ACTIVED) 27140 background = &style->active; 27141 else if (*state & NK_WIDGET_STATE_HOVER) 27142 background = &style->hover; 27143 else background = &style->normal; 27144 27145 /* draw background frame */ 27146 switch(background->type) { 27147 case NK_STYLE_ITEM_IMAGE: 27148 nk_draw_image(out, bounds, &background->data.image, nk_white); 27149 break; 27150 case NK_STYLE_ITEM_NINE_SLICE: 27151 nk_draw_nine_slice(out, bounds, &background->data.slice, nk_white); 27152 break; 27153 case NK_STYLE_ITEM_COLOR: 27154 nk_fill_rect(out, bounds, style->rounding, background->data.color); 27155 nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color); 27156 break; 27157 }} 27158 27159 27160 area.w = NK_MAX(0, area.w - style->cursor_size); 27161 if (edit->active) 27162 { 27163 int total_lines = 1; 27164 struct nk_vec2 text_size = nk_vec2(0,0); 27165 27166 /* text pointer positions */ 27167 const char *cursor_ptr = 0; 27168 const char *select_begin_ptr = 0; 27169 const char *select_end_ptr = 0; 27170 27171 /* 2D pixel positions */ 27172 struct nk_vec2 cursor_pos = nk_vec2(0,0); 27173 struct nk_vec2 selection_offset_start = nk_vec2(0,0); 27174 struct nk_vec2 selection_offset_end = nk_vec2(0,0); 27175 27176 int selection_begin = NK_MIN(edit->select_start, edit->select_end); 27177 int selection_end = NK_MAX(edit->select_start, edit->select_end); 27178 27179 /* calculate total line count + total space + cursor/selection position */ 27180 float line_width = 0.0f; 27181 if (text && len) 27182 { 27183 /* utf8 encoding */ 27184 float glyph_width; 27185 int glyph_len = 0; 27186 nk_rune unicode = 0; 27187 int text_len = 0; 27188 int glyphs = 0; 27189 int row_begin = 0; 27190 27191 glyph_len = nk_utf_decode(text, &unicode, len); 27192 glyph_width = font->width(font->userdata, font->height, text, glyph_len); 27193 line_width = 0; 27194 27195 /* iterate all lines */ 27196 while ((text_len < len) && glyph_len) 27197 { 27198 /* set cursor 2D position and line */ 27199 if (!cursor_ptr && glyphs == edit->cursor) 27200 { 27201 int glyph_offset; 27202 struct nk_vec2 out_offset; 27203 struct nk_vec2 row_size; 27204 const char *remaining; 27205 27206 /* calculate 2d position */ 27207 cursor_pos.y = (float)(total_lines-1) * row_height; 27208 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 27209 text_len-row_begin, row_height, &remaining, 27210 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 27211 cursor_pos.x = row_size.x; 27212 cursor_ptr = text + text_len; 27213 } 27214 27215 /* set start selection 2D position and line */ 27216 if (!select_begin_ptr && edit->select_start != edit->select_end && 27217 glyphs == selection_begin) 27218 { 27219 int glyph_offset; 27220 struct nk_vec2 out_offset; 27221 struct nk_vec2 row_size; 27222 const char *remaining; 27223 27224 /* calculate 2d position */ 27225 selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height; 27226 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 27227 text_len-row_begin, row_height, &remaining, 27228 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 27229 selection_offset_start.x = row_size.x; 27230 select_begin_ptr = text + text_len; 27231 } 27232 27233 /* set end selection 2D position and line */ 27234 if (!select_end_ptr && edit->select_start != edit->select_end && 27235 glyphs == selection_end) 27236 { 27237 int glyph_offset; 27238 struct nk_vec2 out_offset; 27239 struct nk_vec2 row_size; 27240 const char *remaining; 27241 27242 /* calculate 2d position */ 27243 selection_offset_end.y = (float)(total_lines-1) * row_height; 27244 row_size = nk_text_calculate_text_bounds(font, text+row_begin, 27245 text_len-row_begin, row_height, &remaining, 27246 &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); 27247 selection_offset_end.x = row_size.x; 27248 select_end_ptr = text + text_len; 27249 } 27250 if (unicode == '\n') { 27251 text_size.x = NK_MAX(text_size.x, line_width); 27252 total_lines++; 27253 line_width = 0; 27254 text_len++; 27255 glyphs++; 27256 row_begin = text_len; 27257 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); 27258 glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); 27259 continue; 27260 } 27261 27262 glyphs++; 27263 text_len += glyph_len; 27264 line_width += (float)glyph_width; 27265 27266 glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); 27267 glyph_width = font->width(font->userdata, font->height, 27268 text+text_len, glyph_len); 27269 continue; 27270 } 27271 text_size.y = (float)total_lines * row_height; 27272 27273 /* handle case when cursor is at end of text buffer */ 27274 if (!cursor_ptr && edit->cursor == edit->string.len) { 27275 cursor_pos.x = line_width; 27276 cursor_pos.y = text_size.y - row_height; 27277 } 27278 } 27279 { 27280 /* scrollbar */ 27281 if (cursor_follow) 27282 { 27283 /* update scrollbar to follow cursor */ 27284 if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) { 27285 /* horizontal scroll */ 27286 const float scroll_increment = area.w * 0.25f; 27287 if (cursor_pos.x < edit->scrollbar.x) 27288 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment); 27289 if (cursor_pos.x >= edit->scrollbar.x + area.w) 27290 edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - area.w + scroll_increment); 27291 } else edit->scrollbar.x = 0; 27292 27293 if (flags & NK_EDIT_MULTILINE) { 27294 /* vertical scroll */ 27295 if (cursor_pos.y < edit->scrollbar.y) 27296 edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height); 27297 if (cursor_pos.y >= edit->scrollbar.y + row_height) 27298 edit->scrollbar.y = edit->scrollbar.y + row_height; 27299 } else edit->scrollbar.y = 0; 27300 } 27301 27302 /* scrollbar widget */ 27303 if (flags & NK_EDIT_MULTILINE) 27304 { 27305 nk_flags ws; 27306 struct nk_rect scroll; 27307 float scroll_target; 27308 float scroll_offset; 27309 float scroll_step; 27310 float scroll_inc; 27311 27312 scroll = area; 27313 scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x; 27314 scroll.w = style->scrollbar_size.x; 27315 27316 scroll_offset = edit->scrollbar.y; 27317 scroll_step = scroll.h * 0.10f; 27318 scroll_inc = scroll.h * 0.01f; 27319 scroll_target = text_size.y; 27320 edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0, 27321 scroll_offset, scroll_target, scroll_step, scroll_inc, 27322 &style->scrollbar, in, font); 27323 } 27324 } 27325 27326 /* draw text */ 27327 {struct nk_color background_color; 27328 struct nk_color text_color; 27329 struct nk_color sel_background_color; 27330 struct nk_color sel_text_color; 27331 struct nk_color cursor_color; 27332 struct nk_color cursor_text_color; 27333 const struct nk_style_item *background; 27334 nk_push_scissor(out, clip); 27335 27336 /* select correct colors to draw */ 27337 if (*state & NK_WIDGET_STATE_ACTIVED) { 27338 background = &style->active; 27339 text_color = style->text_active; 27340 sel_text_color = style->selected_text_hover; 27341 sel_background_color = style->selected_hover; 27342 cursor_color = style->cursor_hover; 27343 cursor_text_color = style->cursor_text_hover; 27344 } else if (*state & NK_WIDGET_STATE_HOVER) { 27345 background = &style->hover; 27346 text_color = style->text_hover; 27347 sel_text_color = style->selected_text_hover; 27348 sel_background_color = style->selected_hover; 27349 cursor_text_color = style->cursor_text_hover; 27350 cursor_color = style->cursor_hover; 27351 } else { 27352 background = &style->normal; 27353 text_color = style->text_normal; 27354 sel_text_color = style->selected_text_normal; 27355 sel_background_color = style->selected_normal; 27356 cursor_color = style->cursor_normal; 27357 cursor_text_color = style->cursor_text_normal; 27358 } 27359 if (background->type == NK_STYLE_ITEM_IMAGE) 27360 background_color = nk_rgba(0,0,0,0); 27361 else 27362 background_color = background->data.color; 27363 27364 27365 if (edit->select_start == edit->select_end) { 27366 /* no selection so just draw the complete text */ 27367 const char *begin = nk_str_get_const(&edit->string); 27368 int l = nk_str_len_char(&edit->string); 27369 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 27370 area.y - edit->scrollbar.y, 0, begin, l, row_height, font, 27371 background_color, text_color, nk_false); 27372 } else { 27373 /* edit has selection so draw 1-3 text chunks */ 27374 if (edit->select_start != edit->select_end && selection_begin > 0){ 27375 /* draw unselected text before selection */ 27376 const char *begin = nk_str_get_const(&edit->string); 27377 NK_ASSERT(select_begin_ptr); 27378 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 27379 area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin), 27380 row_height, font, background_color, text_color, nk_false); 27381 } 27382 if (edit->select_start != edit->select_end) { 27383 /* draw selected text */ 27384 NK_ASSERT(select_begin_ptr); 27385 if (!select_end_ptr) { 27386 const char *begin = nk_str_get_const(&edit->string); 27387 select_end_ptr = begin + nk_str_len_char(&edit->string); 27388 } 27389 nk_edit_draw_text(out, style, 27390 area.x - edit->scrollbar.x, 27391 area.y + selection_offset_start.y - edit->scrollbar.y, 27392 selection_offset_start.x, 27393 select_begin_ptr, (int)(select_end_ptr - select_begin_ptr), 27394 row_height, font, sel_background_color, sel_text_color, nk_true); 27395 } 27396 if ((edit->select_start != edit->select_end && 27397 selection_end < edit->string.len)) 27398 { 27399 /* draw unselected text after selected text */ 27400 const char *begin = select_end_ptr; 27401 const char *end = nk_str_get_const(&edit->string) + 27402 nk_str_len_char(&edit->string); 27403 NK_ASSERT(select_end_ptr); 27404 nk_edit_draw_text(out, style, 27405 area.x - edit->scrollbar.x, 27406 area.y + selection_offset_end.y - edit->scrollbar.y, 27407 selection_offset_end.x, 27408 begin, (int)(end - begin), row_height, font, 27409 background_color, text_color, nk_true); 27410 } 27411 } 27412 27413 /* cursor */ 27414 if (edit->select_start == edit->select_end) 27415 { 27416 if (edit->cursor >= nk_str_len(&edit->string) || 27417 (cursor_ptr && *cursor_ptr == '\n')) { 27418 /* draw cursor at end of line */ 27419 struct nk_rect cursor; 27420 cursor.w = style->cursor_size; 27421 cursor.h = font->height; 27422 cursor.x = area.x + cursor_pos.x - edit->scrollbar.x; 27423 cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f; 27424 cursor.y -= edit->scrollbar.y; 27425 nk_fill_rect(out, cursor, 0, cursor_color); 27426 } else { 27427 /* draw cursor inside text */ 27428 int glyph_len; 27429 struct nk_rect label; 27430 struct nk_text txt; 27431 27432 nk_rune unicode; 27433 NK_ASSERT(cursor_ptr); 27434 glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4); 27435 27436 label.x = area.x + cursor_pos.x - edit->scrollbar.x; 27437 label.y = area.y + cursor_pos.y - edit->scrollbar.y; 27438 label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len); 27439 label.h = row_height; 27440 27441 txt.padding = nk_vec2(0,0); 27442 txt.background = cursor_color;; 27443 txt.text = cursor_text_color; 27444 nk_fill_rect(out, label, 0, cursor_color); 27445 nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font); 27446 } 27447 }} 27448 } else { 27449 /* not active so just draw text */ 27450 int l = nk_str_len_char(&edit->string); 27451 const char *begin = nk_str_get_const(&edit->string); 27452 27453 const struct nk_style_item *background; 27454 struct nk_color background_color; 27455 struct nk_color text_color; 27456 nk_push_scissor(out, clip); 27457 if (*state & NK_WIDGET_STATE_ACTIVED) { 27458 background = &style->active; 27459 text_color = style->text_active; 27460 } else if (*state & NK_WIDGET_STATE_HOVER) { 27461 background = &style->hover; 27462 text_color = style->text_hover; 27463 } else { 27464 background = &style->normal; 27465 text_color = style->text_normal; 27466 } 27467 if (background->type == NK_STYLE_ITEM_IMAGE) 27468 background_color = nk_rgba(0,0,0,0); 27469 else 27470 background_color = background->data.color; 27471 nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, 27472 area.y - edit->scrollbar.y, 0, begin, l, row_height, font, 27473 background_color, text_color, nk_false); 27474 } 27475 nk_push_scissor(out, old_clip);} 27476 return ret; 27477 } 27478 NK_API void 27479 nk_edit_focus(struct nk_context *ctx, nk_flags flags) 27480 { 27481 nk_hash hash; 27482 struct nk_window *win; 27483 27484 NK_ASSERT(ctx); 27485 NK_ASSERT(ctx->current); 27486 if (!ctx || !ctx->current) return; 27487 27488 win = ctx->current; 27489 hash = win->edit.seq; 27490 win->edit.active = nk_true; 27491 win->edit.name = hash; 27492 if (flags & NK_EDIT_ALWAYS_INSERT_MODE) 27493 win->edit.mode = NK_TEXT_EDIT_MODE_INSERT; 27494 } 27495 NK_API void 27496 nk_edit_unfocus(struct nk_context *ctx) 27497 { 27498 struct nk_window *win; 27499 NK_ASSERT(ctx); 27500 NK_ASSERT(ctx->current); 27501 if (!ctx || !ctx->current) return; 27502 27503 win = ctx->current; 27504 win->edit.active = nk_false; 27505 win->edit.name = 0; 27506 } 27507 NK_API nk_flags 27508 nk_edit_string(struct nk_context *ctx, nk_flags flags, 27509 char *memory, int *len, int max, nk_plugin_filter filter) 27510 { 27511 nk_hash hash; 27512 nk_flags state; 27513 struct nk_text_edit *edit; 27514 struct nk_window *win; 27515 27516 NK_ASSERT(ctx); 27517 NK_ASSERT(memory); 27518 NK_ASSERT(len); 27519 if (!ctx || !memory || !len) 27520 return 0; 27521 27522 filter = (!filter) ? nk_filter_default: filter; 27523 win = ctx->current; 27524 hash = win->edit.seq; 27525 edit = &ctx->text_edit; 27526 nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)? 27527 NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter); 27528 27529 if (win->edit.active && hash == win->edit.name) { 27530 if (flags & NK_EDIT_NO_CURSOR) 27531 edit->cursor = nk_utf_len(memory, *len); 27532 else edit->cursor = win->edit.cursor; 27533 if (!(flags & NK_EDIT_SELECTABLE)) { 27534 edit->select_start = win->edit.cursor; 27535 edit->select_end = win->edit.cursor; 27536 } else { 27537 edit->select_start = win->edit.sel_start; 27538 edit->select_end = win->edit.sel_end; 27539 } 27540 edit->mode = win->edit.mode; 27541 edit->scrollbar.x = (float)win->edit.scrollbar.x; 27542 edit->scrollbar.y = (float)win->edit.scrollbar.y; 27543 edit->active = nk_true; 27544 } else edit->active = nk_false; 27545 27546 max = NK_MAX(1, max); 27547 *len = NK_MIN(*len, max-1); 27548 nk_str_init_fixed(&edit->string, memory, (nk_size)max); 27549 edit->string.buffer.allocated = (nk_size)*len; 27550 edit->string.len = nk_utf_len(memory, *len); 27551 state = nk_edit_buffer(ctx, flags, edit, filter); 27552 *len = (int)edit->string.buffer.allocated; 27553 27554 if (edit->active) { 27555 win->edit.cursor = edit->cursor; 27556 win->edit.sel_start = edit->select_start; 27557 win->edit.sel_end = edit->select_end; 27558 win->edit.mode = edit->mode; 27559 win->edit.scrollbar.x = (nk_uint)edit->scrollbar.x; 27560 win->edit.scrollbar.y = (nk_uint)edit->scrollbar.y; 27561 } return state; 27562 } 27563 NK_API nk_flags 27564 nk_edit_buffer(struct nk_context *ctx, nk_flags flags, 27565 struct nk_text_edit *edit, nk_plugin_filter filter) 27566 { 27567 struct nk_window *win; 27568 struct nk_style *style; 27569 struct nk_input *in; 27570 27571 enum nk_widget_layout_states state; 27572 struct nk_rect bounds; 27573 27574 nk_flags ret_flags = 0; 27575 unsigned char prev_state; 27576 nk_hash hash; 27577 27578 /* make sure correct values */ 27579 NK_ASSERT(ctx); 27580 NK_ASSERT(edit); 27581 NK_ASSERT(ctx->current); 27582 NK_ASSERT(ctx->current->layout); 27583 if (!ctx || !ctx->current || !ctx->current->layout) 27584 return 0; 27585 27586 win = ctx->current; 27587 style = &ctx->style; 27588 state = nk_widget(&bounds, ctx); 27589 if (!state) return state; 27590 in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 27591 27592 /* check if edit is currently hot item */ 27593 hash = win->edit.seq++; 27594 if (win->edit.active && hash == win->edit.name) { 27595 if (flags & NK_EDIT_NO_CURSOR) 27596 edit->cursor = edit->string.len; 27597 if (!(flags & NK_EDIT_SELECTABLE)) { 27598 edit->select_start = edit->cursor; 27599 edit->select_end = edit->cursor; 27600 } 27601 if (flags & NK_EDIT_CLIPBOARD) 27602 edit->clip = ctx->clip; 27603 edit->active = (unsigned char)win->edit.active; 27604 } else edit->active = nk_false; 27605 edit->mode = win->edit.mode; 27606 27607 filter = (!filter) ? nk_filter_default: filter; 27608 prev_state = (unsigned char)edit->active; 27609 in = (flags & NK_EDIT_READ_ONLY) ? 0: in; 27610 ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags, 27611 filter, edit, &style->edit, in, style->font); 27612 27613 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 27614 ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT]; 27615 if (edit->active && prev_state != edit->active) { 27616 /* current edit is now hot */ 27617 win->edit.active = nk_true; 27618 win->edit.name = hash; 27619 } else if (prev_state && !edit->active) { 27620 /* current edit is now cold */ 27621 win->edit.active = nk_false; 27622 } return ret_flags; 27623 } 27624 NK_API nk_flags 27625 nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags, 27626 char *buffer, int max, nk_plugin_filter filter) 27627 { 27628 nk_flags result; 27629 int len = nk_strlen(buffer); 27630 result = nk_edit_string(ctx, flags, buffer, &len, max, filter); 27631 buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0'; 27632 return result; 27633 } 27634 27635 27636 27637 27638 27639 /* =============================================================== 27640 * 27641 * PROPERTY 27642 * 27643 * ===============================================================*/ 27644 NK_LIB void 27645 nk_drag_behavior(nk_flags *state, const struct nk_input *in, 27646 struct nk_rect drag, struct nk_property_variant *variant, 27647 float inc_per_pixel) 27648 { 27649 int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; 27650 int left_mouse_click_in_cursor = in && 27651 nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true); 27652 27653 nk_widget_state_reset(state); 27654 if (nk_input_is_mouse_hovering_rect(in, drag)) 27655 *state = NK_WIDGET_STATE_HOVERED; 27656 27657 if (left_mouse_down && left_mouse_click_in_cursor) { 27658 float delta, pixels; 27659 pixels = in->mouse.delta.x; 27660 delta = pixels * inc_per_pixel; 27661 switch (variant->kind) { 27662 default: break; 27663 case NK_PROPERTY_INT: 27664 variant->value.i = variant->value.i + (int)delta; 27665 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); 27666 break; 27667 case NK_PROPERTY_FLOAT: 27668 variant->value.f = variant->value.f + (float)delta; 27669 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); 27670 break; 27671 case NK_PROPERTY_DOUBLE: 27672 variant->value.d = variant->value.d + (double)delta; 27673 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); 27674 break; 27675 } 27676 *state = NK_WIDGET_STATE_ACTIVE; 27677 } 27678 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag)) 27679 *state |= NK_WIDGET_STATE_ENTERED; 27680 else if (nk_input_is_mouse_prev_hovering_rect(in, drag)) 27681 *state |= NK_WIDGET_STATE_LEFT; 27682 } 27683 NK_LIB void 27684 nk_property_behavior(nk_flags *ws, const struct nk_input *in, 27685 struct nk_rect property, struct nk_rect label, struct nk_rect edit, 27686 struct nk_rect empty, int *state, struct nk_property_variant *variant, 27687 float inc_per_pixel) 27688 { 27689 nk_widget_state_reset(ws); 27690 if (in && *state == NK_PROPERTY_DEFAULT) { 27691 if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT)) 27692 *state = NK_PROPERTY_EDIT; 27693 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true)) 27694 *state = NK_PROPERTY_DRAG; 27695 else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true)) 27696 *state = NK_PROPERTY_DRAG; 27697 } 27698 if (*state == NK_PROPERTY_DRAG) { 27699 nk_drag_behavior(ws, in, property, variant, inc_per_pixel); 27700 if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT; 27701 } 27702 } 27703 NK_LIB void 27704 nk_draw_property(struct nk_command_buffer *out, const struct nk_style_property *style, 27705 const struct nk_rect *bounds, const struct nk_rect *label, nk_flags state, 27706 const char *name, int len, const struct nk_user_font *font) 27707 { 27708 struct nk_text text; 27709 const struct nk_style_item *background; 27710 27711 /* select correct background and text color */ 27712 if (state & NK_WIDGET_STATE_ACTIVED) { 27713 background = &style->active; 27714 text.text = style->label_active; 27715 } else if (state & NK_WIDGET_STATE_HOVER) { 27716 background = &style->hover; 27717 text.text = style->label_hover; 27718 } else { 27719 background = &style->normal; 27720 text.text = style->label_normal; 27721 } 27722 27723 /* draw background */ 27724 switch(background->type) { 27725 case NK_STYLE_ITEM_IMAGE: 27726 text.background = nk_rgba(0, 0, 0, 0); 27727 nk_draw_image(out, *bounds, &background->data.image, nk_white); 27728 break; 27729 case NK_STYLE_ITEM_NINE_SLICE: 27730 text.background = nk_rgba(0, 0, 0, 0); 27731 nk_draw_nine_slice(out, *bounds, &background->data.slice, nk_white); 27732 break; 27733 case NK_STYLE_ITEM_COLOR: 27734 text.background = background->data.color; 27735 nk_fill_rect(out, *bounds, style->rounding, background->data.color); 27736 nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color); 27737 break; 27738 } 27739 27740 /* draw label */ 27741 text.padding = nk_vec2(0,0); 27742 nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font); 27743 } 27744 NK_LIB void 27745 nk_do_property(nk_flags *ws, 27746 struct nk_command_buffer *out, struct nk_rect property, 27747 const char *name, struct nk_property_variant *variant, 27748 float inc_per_pixel, char *buffer, int *len, 27749 int *state, int *cursor, int *select_begin, int *select_end, 27750 const struct nk_style_property *style, 27751 enum nk_property_filter filter, struct nk_input *in, 27752 const struct nk_user_font *font, struct nk_text_edit *text_edit, 27753 enum nk_button_behavior behavior) 27754 { 27755 const nk_plugin_filter filters[] = { 27756 nk_filter_decimal, 27757 nk_filter_float 27758 }; 27759 nk_bool active, old; 27760 int num_len = 0, name_len; 27761 char string[NK_MAX_NUMBER_BUFFER]; 27762 float size; 27763 27764 char *dst = 0; 27765 int *length; 27766 27767 struct nk_rect left; 27768 struct nk_rect right; 27769 struct nk_rect label; 27770 struct nk_rect edit; 27771 struct nk_rect empty; 27772 27773 /* left decrement button */ 27774 left.h = font->height/2; 27775 left.w = left.h; 27776 left.x = property.x + style->border + style->padding.x; 27777 left.y = property.y + style->border + property.h/2.0f - left.h/2; 27778 27779 /* text label */ 27780 name_len = nk_strlen(name); 27781 size = font->width(font->userdata, font->height, name, name_len); 27782 label.x = left.x + left.w + style->padding.x; 27783 label.w = (float)size + 2 * style->padding.x; 27784 label.y = property.y + style->border + style->padding.y; 27785 label.h = property.h - (2 * style->border + 2 * style->padding.y); 27786 27787 /* right increment button */ 27788 right.y = left.y; 27789 right.w = left.w; 27790 right.h = left.h; 27791 right.x = property.x + property.w - (right.w + style->padding.x); 27792 27793 /* edit */ 27794 if (*state == NK_PROPERTY_EDIT) { 27795 size = font->width(font->userdata, font->height, buffer, *len); 27796 size += style->edit.cursor_size; 27797 length = len; 27798 dst = buffer; 27799 } else { 27800 switch (variant->kind) { 27801 default: break; 27802 case NK_PROPERTY_INT: 27803 nk_itoa(string, variant->value.i); 27804 num_len = nk_strlen(string); 27805 break; 27806 case NK_PROPERTY_FLOAT: 27807 NK_DTOA(string, (double)variant->value.f); 27808 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); 27809 break; 27810 case NK_PROPERTY_DOUBLE: 27811 NK_DTOA(string, variant->value.d); 27812 num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); 27813 break; 27814 } 27815 size = font->width(font->userdata, font->height, string, num_len); 27816 dst = string; 27817 length = &num_len; 27818 } 27819 27820 edit.w = (float)size + 2 * style->padding.x; 27821 edit.w = NK_MIN(edit.w, right.x - (label.x + label.w)); 27822 edit.x = right.x - (edit.w + style->padding.x); 27823 edit.y = property.y + style->border; 27824 edit.h = property.h - (2 * style->border); 27825 27826 /* empty left space activator */ 27827 empty.w = edit.x - (label.x + label.w); 27828 empty.x = label.x + label.w; 27829 empty.y = property.y; 27830 empty.h = property.h; 27831 27832 /* update property */ 27833 old = (*state == NK_PROPERTY_EDIT); 27834 nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel); 27835 27836 /* draw property */ 27837 if (style->draw_begin) style->draw_begin(out, style->userdata); 27838 nk_draw_property(out, style, &property, &label, *ws, name, name_len, font); 27839 if (style->draw_end) style->draw_end(out, style->userdata); 27840 27841 /* execute right button */ 27842 if (nk_do_button_symbol(ws, out, left, style->sym_left, behavior, &style->dec_button, in, font)) { 27843 switch (variant->kind) { 27844 default: break; 27845 case NK_PROPERTY_INT: 27846 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break; 27847 case NK_PROPERTY_FLOAT: 27848 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break; 27849 case NK_PROPERTY_DOUBLE: 27850 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break; 27851 } 27852 } 27853 /* execute left button */ 27854 if (nk_do_button_symbol(ws, out, right, style->sym_right, behavior, &style->inc_button, in, font)) { 27855 switch (variant->kind) { 27856 default: break; 27857 case NK_PROPERTY_INT: 27858 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break; 27859 case NK_PROPERTY_FLOAT: 27860 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break; 27861 case NK_PROPERTY_DOUBLE: 27862 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break; 27863 } 27864 } 27865 if (old != NK_PROPERTY_EDIT && (*state == NK_PROPERTY_EDIT)) { 27866 /* property has been activated so setup buffer */ 27867 NK_MEMCPY(buffer, dst, (nk_size)*length); 27868 *cursor = nk_utf_len(buffer, *length); 27869 *len = *length; 27870 length = len; 27871 dst = buffer; 27872 active = 0; 27873 } else active = (*state == NK_PROPERTY_EDIT); 27874 27875 /* execute and run text edit field */ 27876 nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]); 27877 text_edit->active = (unsigned char)active; 27878 text_edit->string.len = *length; 27879 text_edit->cursor = NK_CLAMP(0, *cursor, *length); 27880 text_edit->select_start = NK_CLAMP(0,*select_begin, *length); 27881 text_edit->select_end = NK_CLAMP(0,*select_end, *length); 27882 text_edit->string.buffer.allocated = (nk_size)*length; 27883 text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER; 27884 text_edit->string.buffer.memory.ptr = dst; 27885 text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER; 27886 text_edit->mode = NK_TEXT_EDIT_MODE_INSERT; 27887 nk_do_edit(ws, out, edit, NK_EDIT_FIELD|NK_EDIT_AUTO_SELECT, 27888 filters[filter], text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font); 27889 27890 *length = text_edit->string.len; 27891 *cursor = text_edit->cursor; 27892 *select_begin = text_edit->select_start; 27893 *select_end = text_edit->select_end; 27894 if (text_edit->active && nk_input_is_key_pressed(in, NK_KEY_ENTER)) 27895 text_edit->active = nk_false; 27896 27897 if (active && !text_edit->active) { 27898 /* property is now not active so convert edit text to value*/ 27899 *state = NK_PROPERTY_DEFAULT; 27900 buffer[*len] = '\0'; 27901 switch (variant->kind) { 27902 default: break; 27903 case NK_PROPERTY_INT: 27904 variant->value.i = nk_strtoi(buffer, 0); 27905 variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); 27906 break; 27907 case NK_PROPERTY_FLOAT: 27908 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); 27909 variant->value.f = nk_strtof(buffer, 0); 27910 variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); 27911 break; 27912 case NK_PROPERTY_DOUBLE: 27913 nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); 27914 variant->value.d = nk_strtod(buffer, 0); 27915 variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); 27916 break; 27917 } 27918 } 27919 } 27920 NK_LIB struct nk_property_variant 27921 nk_property_variant_int(int value, int min_value, int max_value, int step) 27922 { 27923 struct nk_property_variant result; 27924 result.kind = NK_PROPERTY_INT; 27925 result.value.i = value; 27926 result.min_value.i = min_value; 27927 result.max_value.i = max_value; 27928 result.step.i = step; 27929 return result; 27930 } 27931 NK_LIB struct nk_property_variant 27932 nk_property_variant_float(float value, float min_value, float max_value, float step) 27933 { 27934 struct nk_property_variant result; 27935 result.kind = NK_PROPERTY_FLOAT; 27936 result.value.f = value; 27937 result.min_value.f = min_value; 27938 result.max_value.f = max_value; 27939 result.step.f = step; 27940 return result; 27941 } 27942 NK_LIB struct nk_property_variant 27943 nk_property_variant_double(double value, double min_value, double max_value, 27944 double step) 27945 { 27946 struct nk_property_variant result; 27947 result.kind = NK_PROPERTY_DOUBLE; 27948 result.value.d = value; 27949 result.min_value.d = min_value; 27950 result.max_value.d = max_value; 27951 result.step.d = step; 27952 return result; 27953 } 27954 NK_LIB void 27955 nk_property(struct nk_context *ctx, const char *name, struct nk_property_variant *variant, 27956 float inc_per_pixel, const enum nk_property_filter filter) 27957 { 27958 struct nk_window *win; 27959 struct nk_panel *layout; 27960 struct nk_input *in; 27961 const struct nk_style *style; 27962 27963 struct nk_rect bounds; 27964 enum nk_widget_layout_states s; 27965 27966 int *state = 0; 27967 nk_hash hash = 0; 27968 char *buffer = 0; 27969 int *len = 0; 27970 int *cursor = 0; 27971 int *select_begin = 0; 27972 int *select_end = 0; 27973 int old_state; 27974 27975 char dummy_buffer[NK_MAX_NUMBER_BUFFER]; 27976 int dummy_state = NK_PROPERTY_DEFAULT; 27977 int dummy_length = 0; 27978 int dummy_cursor = 0; 27979 int dummy_select_begin = 0; 27980 int dummy_select_end = 0; 27981 27982 NK_ASSERT(ctx); 27983 NK_ASSERT(ctx->current); 27984 NK_ASSERT(ctx->current->layout); 27985 if (!ctx || !ctx->current || !ctx->current->layout) 27986 return; 27987 27988 win = ctx->current; 27989 layout = win->layout; 27990 style = &ctx->style; 27991 s = nk_widget(&bounds, ctx); 27992 if (!s) return; 27993 27994 /* calculate hash from name */ 27995 if (name[0] == '#') { 27996 hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++); 27997 name++; /* special number hash */ 27998 } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42); 27999 28000 /* check if property is currently hot item */ 28001 if (win->property.active && hash == win->property.name) { 28002 buffer = win->property.buffer; 28003 len = &win->property.length; 28004 cursor = &win->property.cursor; 28005 state = &win->property.state; 28006 select_begin = &win->property.select_start; 28007 select_end = &win->property.select_end; 28008 } else { 28009 buffer = dummy_buffer; 28010 len = &dummy_length; 28011 cursor = &dummy_cursor; 28012 state = &dummy_state; 28013 select_begin = &dummy_select_begin; 28014 select_end = &dummy_select_end; 28015 } 28016 28017 /* execute property widget */ 28018 old_state = *state; 28019 ctx->text_edit.clip = ctx->clip; 28020 in = ((s == NK_WIDGET_ROM && !win->property.active) || 28021 layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 28022 nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name, 28023 variant, inc_per_pixel, buffer, len, state, cursor, select_begin, 28024 select_end, &style->property, filter, in, style->font, &ctx->text_edit, 28025 ctx->button_behavior); 28026 28027 if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) { 28028 /* current property is now hot */ 28029 win->property.active = 1; 28030 NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len); 28031 win->property.length = *len; 28032 win->property.cursor = *cursor; 28033 win->property.state = *state; 28034 win->property.name = hash; 28035 win->property.select_start = *select_begin; 28036 win->property.select_end = *select_end; 28037 if (*state == NK_PROPERTY_DRAG) { 28038 ctx->input.mouse.grab = nk_true; 28039 ctx->input.mouse.grabbed = nk_true; 28040 } 28041 } 28042 /* check if previously active property is now inactive */ 28043 if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) { 28044 if (old_state == NK_PROPERTY_DRAG) { 28045 ctx->input.mouse.grab = nk_false; 28046 ctx->input.mouse.grabbed = nk_false; 28047 ctx->input.mouse.ungrab = nk_true; 28048 } 28049 win->property.select_start = 0; 28050 win->property.select_end = 0; 28051 win->property.active = 0; 28052 } 28053 } 28054 NK_API void 28055 nk_property_int(struct nk_context *ctx, const char *name, 28056 int min, int *val, int max, int step, float inc_per_pixel) 28057 { 28058 struct nk_property_variant variant; 28059 NK_ASSERT(ctx); 28060 NK_ASSERT(name); 28061 NK_ASSERT(val); 28062 28063 if (!ctx || !ctx->current || !name || !val) return; 28064 variant = nk_property_variant_int(*val, min, max, step); 28065 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); 28066 *val = variant.value.i; 28067 } 28068 NK_API void 28069 nk_property_float(struct nk_context *ctx, const char *name, 28070 float min, float *val, float max, float step, float inc_per_pixel) 28071 { 28072 struct nk_property_variant variant; 28073 NK_ASSERT(ctx); 28074 NK_ASSERT(name); 28075 NK_ASSERT(val); 28076 28077 if (!ctx || !ctx->current || !name || !val) return; 28078 variant = nk_property_variant_float(*val, min, max, step); 28079 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 28080 *val = variant.value.f; 28081 } 28082 NK_API void 28083 nk_property_double(struct nk_context *ctx, const char *name, 28084 double min, double *val, double max, double step, float inc_per_pixel) 28085 { 28086 struct nk_property_variant variant; 28087 NK_ASSERT(ctx); 28088 NK_ASSERT(name); 28089 NK_ASSERT(val); 28090 28091 if (!ctx || !ctx->current || !name || !val) return; 28092 variant = nk_property_variant_double(*val, min, max, step); 28093 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 28094 *val = variant.value.d; 28095 } 28096 NK_API int 28097 nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, 28098 int max, int step, float inc_per_pixel) 28099 { 28100 struct nk_property_variant variant; 28101 NK_ASSERT(ctx); 28102 NK_ASSERT(name); 28103 28104 if (!ctx || !ctx->current || !name) return val; 28105 variant = nk_property_variant_int(val, min, max, step); 28106 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); 28107 val = variant.value.i; 28108 return val; 28109 } 28110 NK_API float 28111 nk_propertyf(struct nk_context *ctx, const char *name, float min, 28112 float val, float max, float step, float inc_per_pixel) 28113 { 28114 struct nk_property_variant variant; 28115 NK_ASSERT(ctx); 28116 NK_ASSERT(name); 28117 28118 if (!ctx || !ctx->current || !name) return val; 28119 variant = nk_property_variant_float(val, min, max, step); 28120 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 28121 val = variant.value.f; 28122 return val; 28123 } 28124 NK_API double 28125 nk_propertyd(struct nk_context *ctx, const char *name, double min, 28126 double val, double max, double step, float inc_per_pixel) 28127 { 28128 struct nk_property_variant variant; 28129 NK_ASSERT(ctx); 28130 NK_ASSERT(name); 28131 28132 if (!ctx || !ctx->current || !name) return val; 28133 variant = nk_property_variant_double(val, min, max, step); 28134 nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); 28135 val = variant.value.d; 28136 return val; 28137 } 28138 28139 28140 28141 28142 28143 /* ============================================================== 28144 * 28145 * CHART 28146 * 28147 * ===============================================================*/ 28148 NK_API nk_bool 28149 nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type, 28150 struct nk_color color, struct nk_color highlight, 28151 int count, float min_value, float max_value) 28152 { 28153 struct nk_window *win; 28154 struct nk_chart *chart; 28155 const struct nk_style *config; 28156 const struct nk_style_chart *style; 28157 28158 const struct nk_style_item *background; 28159 struct nk_rect bounds = {0, 0, 0, 0}; 28160 28161 NK_ASSERT(ctx); 28162 NK_ASSERT(ctx->current); 28163 NK_ASSERT(ctx->current->layout); 28164 28165 if (!ctx || !ctx->current || !ctx->current->layout) return 0; 28166 if (!nk_widget(&bounds, ctx)) { 28167 chart = &ctx->current->layout->chart; 28168 nk_zero(chart, sizeof(*chart)); 28169 return 0; 28170 } 28171 28172 win = ctx->current; 28173 config = &ctx->style; 28174 chart = &win->layout->chart; 28175 style = &config->chart; 28176 28177 /* setup basic generic chart */ 28178 nk_zero(chart, sizeof(*chart)); 28179 chart->x = bounds.x + style->padding.x; 28180 chart->y = bounds.y + style->padding.y; 28181 chart->w = bounds.w - 2 * style->padding.x; 28182 chart->h = bounds.h - 2 * style->padding.y; 28183 chart->w = NK_MAX(chart->w, 2 * style->padding.x); 28184 chart->h = NK_MAX(chart->h, 2 * style->padding.y); 28185 28186 /* add first slot into chart */ 28187 {struct nk_chart_slot *slot = &chart->slots[chart->slot++]; 28188 slot->type = type; 28189 slot->count = count; 28190 slot->color = color; 28191 slot->highlight = highlight; 28192 slot->min = NK_MIN(min_value, max_value); 28193 slot->max = NK_MAX(min_value, max_value); 28194 slot->range = slot->max - slot->min;} 28195 28196 /* draw chart background */ 28197 background = &style->background; 28198 28199 switch(background->type) { 28200 case NK_STYLE_ITEM_IMAGE: 28201 nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white); 28202 break; 28203 case NK_STYLE_ITEM_NINE_SLICE: 28204 nk_draw_nine_slice(&win->buffer, bounds, &background->data.slice, nk_white); 28205 break; 28206 case NK_STYLE_ITEM_COLOR: 28207 nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color); 28208 nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border), 28209 style->rounding, style->background.data.color); 28210 break; 28211 } 28212 return 1; 28213 } 28214 NK_API nk_bool 28215 nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type, 28216 int count, float min_value, float max_value) 28217 { 28218 return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, 28219 ctx->style.chart.selected_color, count, min_value, max_value); 28220 } 28221 NK_API void 28222 nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type, 28223 struct nk_color color, struct nk_color highlight, 28224 int count, float min_value, float max_value) 28225 { 28226 NK_ASSERT(ctx); 28227 NK_ASSERT(ctx->current); 28228 NK_ASSERT(ctx->current->layout); 28229 NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT); 28230 if (!ctx || !ctx->current || !ctx->current->layout) return; 28231 if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return; 28232 28233 /* add another slot into the graph */ 28234 {struct nk_chart *chart = &ctx->current->layout->chart; 28235 struct nk_chart_slot *slot = &chart->slots[chart->slot++]; 28236 slot->type = type; 28237 slot->count = count; 28238 slot->color = color; 28239 slot->highlight = highlight; 28240 slot->min = NK_MIN(min_value, max_value); 28241 slot->max = NK_MAX(min_value, max_value); 28242 slot->range = slot->max - slot->min;} 28243 } 28244 NK_API void 28245 nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type, 28246 int count, float min_value, float max_value) 28247 { 28248 nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, 28249 ctx->style.chart.selected_color, count, min_value, max_value); 28250 } 28251 NK_INTERN nk_flags 28252 nk_chart_push_line(struct nk_context *ctx, struct nk_window *win, 28253 struct nk_chart *g, float value, int slot) 28254 { 28255 struct nk_panel *layout = win->layout; 28256 const struct nk_input *i = &ctx->input; 28257 struct nk_command_buffer *out = &win->buffer; 28258 28259 nk_flags ret = 0; 28260 struct nk_vec2 cur; 28261 struct nk_rect bounds; 28262 struct nk_color color; 28263 float step; 28264 float range; 28265 float ratio; 28266 28267 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 28268 step = g->w / (float)g->slots[slot].count; 28269 range = g->slots[slot].max - g->slots[slot].min; 28270 ratio = (value - g->slots[slot].min) / range; 28271 28272 if (g->slots[slot].index == 0) { 28273 /* first data point does not have a connection */ 28274 g->slots[slot].last.x = g->x; 28275 g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h; 28276 28277 bounds.x = g->slots[slot].last.x - 2; 28278 bounds.y = g->slots[slot].last.y - 2; 28279 bounds.w = bounds.h = 4; 28280 28281 color = g->slots[slot].color; 28282 if (!(layout->flags & NK_WINDOW_ROM) && 28283 NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){ 28284 ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0; 28285 ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down && 28286 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 28287 color = g->slots[slot].highlight; 28288 } 28289 nk_fill_rect(out, bounds, 0, color); 28290 g->slots[slot].index += 1; 28291 return ret; 28292 } 28293 28294 /* draw a line between the last data point and the new one */ 28295 color = g->slots[slot].color; 28296 cur.x = g->x + (float)(step * (float)g->slots[slot].index); 28297 cur.y = (g->y + g->h) - (ratio * (float)g->h); 28298 nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color); 28299 28300 bounds.x = cur.x - 3; 28301 bounds.y = cur.y - 3; 28302 bounds.w = bounds.h = 6; 28303 28304 /* user selection of current data point */ 28305 if (!(layout->flags & NK_WINDOW_ROM)) { 28306 if (nk_input_is_mouse_hovering_rect(i, bounds)) { 28307 ret = NK_CHART_HOVERING; 28308 ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down && 28309 i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 28310 color = g->slots[slot].highlight; 28311 } 28312 } 28313 nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color); 28314 28315 /* save current data point position */ 28316 g->slots[slot].last.x = cur.x; 28317 g->slots[slot].last.y = cur.y; 28318 g->slots[slot].index += 1; 28319 return ret; 28320 } 28321 NK_INTERN nk_flags 28322 nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win, 28323 struct nk_chart *chart, float value, int slot) 28324 { 28325 struct nk_command_buffer *out = &win->buffer; 28326 const struct nk_input *in = &ctx->input; 28327 struct nk_panel *layout = win->layout; 28328 28329 float ratio; 28330 nk_flags ret = 0; 28331 struct nk_color color; 28332 struct nk_rect item = {0,0,0,0}; 28333 28334 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 28335 if (chart->slots[slot].index >= chart->slots[slot].count) 28336 return nk_false; 28337 if (chart->slots[slot].count) { 28338 float padding = (float)(chart->slots[slot].count-1); 28339 item.w = (chart->w - padding) / (float)(chart->slots[slot].count); 28340 } 28341 28342 /* calculate bounds of current bar chart entry */ 28343 color = chart->slots[slot].color;; 28344 item.h = chart->h * NK_ABS((value/chart->slots[slot].range)); 28345 if (value >= 0) { 28346 ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range); 28347 item.y = (chart->y + chart->h) - chart->h * ratio; 28348 } else { 28349 ratio = (value - chart->slots[slot].max) / chart->slots[slot].range; 28350 item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h; 28351 } 28352 item.x = chart->x + ((float)chart->slots[slot].index * item.w); 28353 item.x = item.x + ((float)chart->slots[slot].index); 28354 28355 /* user chart bar selection */ 28356 if (!(layout->flags & NK_WINDOW_ROM) && 28357 NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) { 28358 ret = NK_CHART_HOVERING; 28359 ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down && 28360 in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; 28361 color = chart->slots[slot].highlight; 28362 } 28363 nk_fill_rect(out, item, 0, color); 28364 chart->slots[slot].index += 1; 28365 return ret; 28366 } 28367 NK_API nk_flags 28368 nk_chart_push_slot(struct nk_context *ctx, float value, int slot) 28369 { 28370 nk_flags flags; 28371 struct nk_window *win; 28372 28373 NK_ASSERT(ctx); 28374 NK_ASSERT(ctx->current); 28375 NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); 28376 NK_ASSERT(slot < ctx->current->layout->chart.slot); 28377 if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false; 28378 if (slot >= ctx->current->layout->chart.slot) return nk_false; 28379 28380 win = ctx->current; 28381 if (win->layout->chart.slot < slot) return nk_false; 28382 switch (win->layout->chart.slots[slot].type) { 28383 case NK_CHART_LINES: 28384 flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break; 28385 case NK_CHART_COLUMN: 28386 flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break; 28387 default: 28388 case NK_CHART_MAX: 28389 flags = 0; 28390 } 28391 return flags; 28392 } 28393 NK_API nk_flags 28394 nk_chart_push(struct nk_context *ctx, float value) 28395 { 28396 return nk_chart_push_slot(ctx, value, 0); 28397 } 28398 NK_API void 28399 nk_chart_end(struct nk_context *ctx) 28400 { 28401 struct nk_window *win; 28402 struct nk_chart *chart; 28403 28404 NK_ASSERT(ctx); 28405 NK_ASSERT(ctx->current); 28406 if (!ctx || !ctx->current) 28407 return; 28408 28409 win = ctx->current; 28410 chart = &win->layout->chart; 28411 NK_MEMSET(chart, 0, sizeof(*chart)); 28412 return; 28413 } 28414 NK_API void 28415 nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values, 28416 int count, int offset) 28417 { 28418 int i = 0; 28419 float min_value; 28420 float max_value; 28421 28422 NK_ASSERT(ctx); 28423 NK_ASSERT(values); 28424 if (!ctx || !values || !count) return; 28425 28426 min_value = values[offset]; 28427 max_value = values[offset]; 28428 for (i = 0; i < count; ++i) { 28429 min_value = NK_MIN(values[i + offset], min_value); 28430 max_value = NK_MAX(values[i + offset], max_value); 28431 } 28432 28433 if (nk_chart_begin(ctx, type, count, min_value, max_value)) { 28434 for (i = 0; i < count; ++i) 28435 nk_chart_push(ctx, values[i + offset]); 28436 nk_chart_end(ctx); 28437 } 28438 } 28439 NK_API void 28440 nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata, 28441 float(*value_getter)(void* user, int index), int count, int offset) 28442 { 28443 int i = 0; 28444 float min_value; 28445 float max_value; 28446 28447 NK_ASSERT(ctx); 28448 NK_ASSERT(value_getter); 28449 if (!ctx || !value_getter || !count) return; 28450 28451 max_value = min_value = value_getter(userdata, offset); 28452 for (i = 0; i < count; ++i) { 28453 float value = value_getter(userdata, i + offset); 28454 min_value = NK_MIN(value, min_value); 28455 max_value = NK_MAX(value, max_value); 28456 } 28457 28458 if (nk_chart_begin(ctx, type, count, min_value, max_value)) { 28459 for (i = 0; i < count; ++i) 28460 nk_chart_push(ctx, value_getter(userdata, i + offset)); 28461 nk_chart_end(ctx); 28462 } 28463 } 28464 28465 28466 28467 28468 28469 /* ============================================================== 28470 * 28471 * COLOR PICKER 28472 * 28473 * ===============================================================*/ 28474 NK_LIB nk_bool 28475 nk_color_picker_behavior(nk_flags *state, 28476 const struct nk_rect *bounds, const struct nk_rect *matrix, 28477 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, 28478 struct nk_colorf *color, const struct nk_input *in) 28479 { 28480 float hsva[4]; 28481 nk_bool value_changed = 0; 28482 nk_bool hsv_changed = 0; 28483 28484 NK_ASSERT(state); 28485 NK_ASSERT(matrix); 28486 NK_ASSERT(hue_bar); 28487 NK_ASSERT(color); 28488 28489 /* color matrix */ 28490 nk_colorf_hsva_fv(hsva, *color); 28491 if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) { 28492 hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1)); 28493 hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1)); 28494 value_changed = hsv_changed = 1; 28495 } 28496 /* hue bar */ 28497 if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) { 28498 hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1)); 28499 value_changed = hsv_changed = 1; 28500 } 28501 /* alpha bar */ 28502 if (alpha_bar) { 28503 if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) { 28504 hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1)); 28505 value_changed = 1; 28506 } 28507 } 28508 nk_widget_state_reset(state); 28509 if (hsv_changed) { 28510 *color = nk_hsva_colorfv(hsva); 28511 *state = NK_WIDGET_STATE_ACTIVE; 28512 } 28513 if (value_changed) { 28514 color->a = hsva[3]; 28515 *state = NK_WIDGET_STATE_ACTIVE; 28516 } 28517 /* set color picker widget state */ 28518 if (nk_input_is_mouse_hovering_rect(in, *bounds)) 28519 *state = NK_WIDGET_STATE_HOVERED; 28520 if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds)) 28521 *state |= NK_WIDGET_STATE_ENTERED; 28522 else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds)) 28523 *state |= NK_WIDGET_STATE_LEFT; 28524 return value_changed; 28525 } 28526 NK_LIB void 28527 nk_draw_color_picker(struct nk_command_buffer *o, const struct nk_rect *matrix, 28528 const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, 28529 struct nk_colorf col) 28530 { 28531 NK_STORAGE const struct nk_color black = {0,0,0,255}; 28532 NK_STORAGE const struct nk_color white = {255, 255, 255, 255}; 28533 NK_STORAGE const struct nk_color black_trans = {0,0,0,0}; 28534 28535 const float crosshair_size = 7.0f; 28536 struct nk_color temp; 28537 float hsva[4]; 28538 float line_y; 28539 int i; 28540 28541 NK_ASSERT(o); 28542 NK_ASSERT(matrix); 28543 NK_ASSERT(hue_bar); 28544 28545 /* draw hue bar */ 28546 nk_colorf_hsva_fv(hsva, col); 28547 for (i = 0; i < 6; ++i) { 28548 NK_GLOBAL const struct nk_color hue_colors[] = { 28549 {255, 0, 0, 255}, {255,255,0,255}, {0,255,0,255}, {0, 255,255,255}, 28550 {0,0,255,255}, {255, 0, 255, 255}, {255, 0, 0, 255} 28551 }; 28552 nk_fill_rect_multi_color(o, 28553 nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f, 28554 hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i], 28555 hue_colors[i+1], hue_colors[i+1]); 28556 } 28557 line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f); 28558 nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2, 28559 line_y, 1, nk_rgb(255,255,255)); 28560 28561 /* draw alpha bar */ 28562 if (alpha_bar) { 28563 float alpha = NK_SATURATE(col.a); 28564 line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f); 28565 28566 nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black); 28567 nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2, 28568 line_y, 1, nk_rgb(255,255,255)); 28569 } 28570 28571 /* draw color matrix */ 28572 temp = nk_hsv_f(hsva[0], 1.0f, 1.0f); 28573 nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white); 28574 nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black); 28575 28576 /* draw cross-hair */ 28577 {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2]; 28578 p.x = (float)(int)(matrix->x + S * matrix->w); 28579 p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h); 28580 nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white); 28581 nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white); 28582 nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white); 28583 nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);} 28584 } 28585 NK_LIB nk_bool 28586 nk_do_color_picker(nk_flags *state, 28587 struct nk_command_buffer *out, struct nk_colorf *col, 28588 enum nk_color_format fmt, struct nk_rect bounds, 28589 struct nk_vec2 padding, const struct nk_input *in, 28590 const struct nk_user_font *font) 28591 { 28592 int ret = 0; 28593 struct nk_rect matrix; 28594 struct nk_rect hue_bar; 28595 struct nk_rect alpha_bar; 28596 float bar_w; 28597 28598 NK_ASSERT(out); 28599 NK_ASSERT(col); 28600 NK_ASSERT(state); 28601 NK_ASSERT(font); 28602 if (!out || !col || !state || !font) 28603 return ret; 28604 28605 bar_w = font->height; 28606 bounds.x += padding.x; 28607 bounds.y += padding.x; 28608 bounds.w -= 2 * padding.x; 28609 bounds.h -= 2 * padding.y; 28610 28611 matrix.x = bounds.x; 28612 matrix.y = bounds.y; 28613 matrix.h = bounds.h; 28614 matrix.w = bounds.w - (3 * padding.x + 2 * bar_w); 28615 28616 hue_bar.w = bar_w; 28617 hue_bar.y = bounds.y; 28618 hue_bar.h = matrix.h; 28619 hue_bar.x = matrix.x + matrix.w + padding.x; 28620 28621 alpha_bar.x = hue_bar.x + hue_bar.w + padding.x; 28622 alpha_bar.y = bounds.y; 28623 alpha_bar.w = bar_w; 28624 alpha_bar.h = matrix.h; 28625 28626 ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar, 28627 (fmt == NK_RGBA) ? &alpha_bar:0, col, in); 28628 nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *col); 28629 return ret; 28630 } 28631 NK_API nk_bool 28632 nk_color_pick(struct nk_context * ctx, struct nk_colorf *color, 28633 enum nk_color_format fmt) 28634 { 28635 struct nk_window *win; 28636 struct nk_panel *layout; 28637 const struct nk_style *config; 28638 const struct nk_input *in; 28639 28640 enum nk_widget_layout_states state; 28641 struct nk_rect bounds; 28642 28643 NK_ASSERT(ctx); 28644 NK_ASSERT(color); 28645 NK_ASSERT(ctx->current); 28646 NK_ASSERT(ctx->current->layout); 28647 if (!ctx || !ctx->current || !ctx->current->layout || !color) 28648 return 0; 28649 28650 win = ctx->current; 28651 config = &ctx->style; 28652 layout = win->layout; 28653 state = nk_widget(&bounds, ctx); 28654 if (!state) return 0; 28655 in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; 28656 return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds, 28657 nk_vec2(0,0), in, config->font); 28658 } 28659 NK_API struct nk_colorf 28660 nk_color_picker(struct nk_context *ctx, struct nk_colorf color, 28661 enum nk_color_format fmt) 28662 { 28663 nk_color_pick(ctx, &color, fmt); 28664 return color; 28665 } 28666 28667 28668 28669 28670 28671 /* ============================================================== 28672 * 28673 * COMBO 28674 * 28675 * ===============================================================*/ 28676 NK_INTERN nk_bool 28677 nk_combo_begin(struct nk_context *ctx, struct nk_window *win, 28678 struct nk_vec2 size, nk_bool is_clicked, struct nk_rect header) 28679 { 28680 struct nk_window *popup; 28681 int is_open = 0; 28682 int is_active = 0; 28683 struct nk_rect body; 28684 nk_hash hash; 28685 28686 NK_ASSERT(ctx); 28687 NK_ASSERT(ctx->current); 28688 NK_ASSERT(ctx->current->layout); 28689 if (!ctx || !ctx->current || !ctx->current->layout) 28690 return 0; 28691 28692 popup = win->popup.win; 28693 body.x = header.x; 28694 body.w = size.x; 28695 body.y = header.y + header.h-ctx->style.window.combo_border; 28696 body.h = size.y; 28697 28698 hash = win->popup.combo_count++; 28699 is_open = (popup) ? nk_true:nk_false; 28700 is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO); 28701 if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || 28702 (!is_open && !is_active && !is_clicked)) return 0; 28703 if (!nk_nonblock_begin(ctx, 0, body, 28704 (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0; 28705 28706 win->popup.type = NK_PANEL_COMBO; 28707 win->popup.name = hash; 28708 return 1; 28709 } 28710 NK_API nk_bool 28711 nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len, 28712 struct nk_vec2 size) 28713 { 28714 const struct nk_input *in; 28715 struct nk_window *win; 28716 struct nk_style *style; 28717 28718 enum nk_widget_layout_states s; 28719 int is_clicked = nk_false; 28720 struct nk_rect header; 28721 const struct nk_style_item *background; 28722 struct nk_text text; 28723 28724 NK_ASSERT(ctx); 28725 NK_ASSERT(selected); 28726 NK_ASSERT(ctx->current); 28727 NK_ASSERT(ctx->current->layout); 28728 if (!ctx || !ctx->current || !ctx->current->layout || !selected) 28729 return 0; 28730 28731 win = ctx->current; 28732 style = &ctx->style; 28733 s = nk_widget(&header, ctx); 28734 if (s == NK_WIDGET_INVALID) 28735 return 0; 28736 28737 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 28738 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 28739 is_clicked = nk_true; 28740 28741 /* draw combo box header background and border */ 28742 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 28743 background = &style->combo.active; 28744 text.text = style->combo.label_active; 28745 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 28746 background = &style->combo.hover; 28747 text.text = style->combo.label_hover; 28748 } else { 28749 background = &style->combo.normal; 28750 text.text = style->combo.label_normal; 28751 } 28752 28753 switch(background->type) { 28754 case NK_STYLE_ITEM_IMAGE: 28755 text.background = nk_rgba(0, 0, 0, 0); 28756 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 28757 break; 28758 case NK_STYLE_ITEM_NINE_SLICE: 28759 text.background = nk_rgba(0, 0, 0, 0); 28760 nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white); 28761 break; 28762 case NK_STYLE_ITEM_COLOR: 28763 text.background = background->data.color; 28764 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 28765 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 28766 break; 28767 } 28768 { 28769 /* print currently selected text item */ 28770 struct nk_rect label; 28771 struct nk_rect button; 28772 struct nk_rect content; 28773 int draw_button_symbol; 28774 28775 enum nk_symbol_type sym; 28776 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 28777 sym = style->combo.sym_hover; 28778 else if (is_clicked) 28779 sym = style->combo.sym_active; 28780 else 28781 sym = style->combo.sym_normal; 28782 28783 /* represents whether or not the combo's button symbol should be drawn */ 28784 draw_button_symbol = sym != NK_SYMBOL_NONE; 28785 28786 /* calculate button */ 28787 button.w = header.h - 2 * style->combo.button_padding.y; 28788 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 28789 button.y = header.y + style->combo.button_padding.y; 28790 button.h = button.w; 28791 28792 content.x = button.x + style->combo.button.padding.x; 28793 content.y = button.y + style->combo.button.padding.y; 28794 content.w = button.w - 2 * style->combo.button.padding.x; 28795 content.h = button.h - 2 * style->combo.button.padding.y; 28796 28797 /* draw selected label */ 28798 text.padding = nk_vec2(0,0); 28799 label.x = header.x + style->combo.content_padding.x; 28800 label.y = header.y + style->combo.content_padding.y; 28801 label.h = header.h - 2 * style->combo.content_padding.y; 28802 if (draw_button_symbol) 28803 label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x; 28804 else 28805 label.w = header.w - 2 * style->combo.content_padding.x; 28806 nk_widget_text(&win->buffer, label, selected, len, &text, 28807 NK_TEXT_LEFT, ctx->style.font); 28808 28809 /* draw open/close button */ 28810 if (draw_button_symbol) 28811 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 28812 &ctx->style.combo.button, sym, style->font); 28813 } 28814 return nk_combo_begin(ctx, win, size, is_clicked, header); 28815 } 28816 NK_API nk_bool 28817 nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size) 28818 { 28819 return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size); 28820 } 28821 NK_API nk_bool 28822 nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size) 28823 { 28824 struct nk_window *win; 28825 struct nk_style *style; 28826 const struct nk_input *in; 28827 28828 struct nk_rect header; 28829 int is_clicked = nk_false; 28830 enum nk_widget_layout_states s; 28831 const struct nk_style_item *background; 28832 28833 NK_ASSERT(ctx); 28834 NK_ASSERT(ctx->current); 28835 NK_ASSERT(ctx->current->layout); 28836 if (!ctx || !ctx->current || !ctx->current->layout) 28837 return 0; 28838 28839 win = ctx->current; 28840 style = &ctx->style; 28841 s = nk_widget(&header, ctx); 28842 if (s == NK_WIDGET_INVALID) 28843 return 0; 28844 28845 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 28846 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 28847 is_clicked = nk_true; 28848 28849 /* draw combo box header background and border */ 28850 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) 28851 background = &style->combo.active; 28852 else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 28853 background = &style->combo.hover; 28854 else background = &style->combo.normal; 28855 28856 switch(background->type) { 28857 case NK_STYLE_ITEM_IMAGE: 28858 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 28859 break; 28860 case NK_STYLE_ITEM_NINE_SLICE: 28861 nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white); 28862 break; 28863 case NK_STYLE_ITEM_COLOR: 28864 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 28865 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 28866 break; 28867 } 28868 { 28869 struct nk_rect content; 28870 struct nk_rect button; 28871 struct nk_rect bounds; 28872 int draw_button_symbol; 28873 28874 enum nk_symbol_type sym; 28875 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 28876 sym = style->combo.sym_hover; 28877 else if (is_clicked) 28878 sym = style->combo.sym_active; 28879 else sym = style->combo.sym_normal; 28880 28881 /* represents whether or not the combo's button symbol should be drawn */ 28882 draw_button_symbol = sym != NK_SYMBOL_NONE; 28883 28884 /* calculate button */ 28885 button.w = header.h - 2 * style->combo.button_padding.y; 28886 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 28887 button.y = header.y + style->combo.button_padding.y; 28888 button.h = button.w; 28889 28890 content.x = button.x + style->combo.button.padding.x; 28891 content.y = button.y + style->combo.button.padding.y; 28892 content.w = button.w - 2 * style->combo.button.padding.x; 28893 content.h = button.h - 2 * style->combo.button.padding.y; 28894 28895 /* draw color */ 28896 bounds.h = header.h - 4 * style->combo.content_padding.y; 28897 bounds.y = header.y + 2 * style->combo.content_padding.y; 28898 bounds.x = header.x + 2 * style->combo.content_padding.x; 28899 if (draw_button_symbol) 28900 bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x; 28901 else 28902 bounds.w = header.w - 4 * style->combo.content_padding.x; 28903 nk_fill_rect(&win->buffer, bounds, 0, color); 28904 28905 /* draw open/close button */ 28906 if (draw_button_symbol) 28907 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 28908 &ctx->style.combo.button, sym, style->font); 28909 } 28910 return nk_combo_begin(ctx, win, size, is_clicked, header); 28911 } 28912 NK_API nk_bool 28913 nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size) 28914 { 28915 struct nk_window *win; 28916 struct nk_style *style; 28917 const struct nk_input *in; 28918 28919 struct nk_rect header; 28920 int is_clicked = nk_false; 28921 enum nk_widget_layout_states s; 28922 const struct nk_style_item *background; 28923 struct nk_color sym_background; 28924 struct nk_color symbol_color; 28925 28926 NK_ASSERT(ctx); 28927 NK_ASSERT(ctx->current); 28928 NK_ASSERT(ctx->current->layout); 28929 if (!ctx || !ctx->current || !ctx->current->layout) 28930 return 0; 28931 28932 win = ctx->current; 28933 style = &ctx->style; 28934 s = nk_widget(&header, ctx); 28935 if (s == NK_WIDGET_INVALID) 28936 return 0; 28937 28938 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 28939 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 28940 is_clicked = nk_true; 28941 28942 /* draw combo box header background and border */ 28943 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 28944 background = &style->combo.active; 28945 symbol_color = style->combo.symbol_active; 28946 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 28947 background = &style->combo.hover; 28948 symbol_color = style->combo.symbol_hover; 28949 } else { 28950 background = &style->combo.normal; 28951 symbol_color = style->combo.symbol_hover; 28952 } 28953 28954 switch(background->type) { 28955 case NK_STYLE_ITEM_IMAGE: 28956 sym_background = nk_rgba(0, 0, 0, 0); 28957 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 28958 break; 28959 case NK_STYLE_ITEM_NINE_SLICE: 28960 sym_background = nk_rgba(0, 0, 0, 0); 28961 nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white); 28962 break; 28963 case NK_STYLE_ITEM_COLOR: 28964 sym_background = background->data.color; 28965 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 28966 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 28967 break; 28968 } 28969 { 28970 struct nk_rect bounds = {0,0,0,0}; 28971 struct nk_rect content; 28972 struct nk_rect button; 28973 28974 enum nk_symbol_type sym; 28975 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 28976 sym = style->combo.sym_hover; 28977 else if (is_clicked) 28978 sym = style->combo.sym_active; 28979 else sym = style->combo.sym_normal; 28980 28981 /* calculate button */ 28982 button.w = header.h - 2 * style->combo.button_padding.y; 28983 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; 28984 button.y = header.y + style->combo.button_padding.y; 28985 button.h = button.w; 28986 28987 content.x = button.x + style->combo.button.padding.x; 28988 content.y = button.y + style->combo.button.padding.y; 28989 content.w = button.w - 2 * style->combo.button.padding.x; 28990 content.h = button.h - 2 * style->combo.button.padding.y; 28991 28992 /* draw symbol */ 28993 bounds.h = header.h - 2 * style->combo.content_padding.y; 28994 bounds.y = header.y + style->combo.content_padding.y; 28995 bounds.x = header.x + style->combo.content_padding.x; 28996 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; 28997 nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color, 28998 1.0f, style->font); 28999 29000 /* draw open/close button */ 29001 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, 29002 &ctx->style.combo.button, sym, style->font); 29003 } 29004 return nk_combo_begin(ctx, win, size, is_clicked, header); 29005 } 29006 NK_API nk_bool 29007 nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len, 29008 enum nk_symbol_type symbol, struct nk_vec2 size) 29009 { 29010 struct nk_window *win; 29011 struct nk_style *style; 29012 struct nk_input *in; 29013 29014 struct nk_rect header; 29015 int is_clicked = nk_false; 29016 enum nk_widget_layout_states s; 29017 const struct nk_style_item *background; 29018 struct nk_color symbol_color; 29019 struct nk_text text; 29020 29021 NK_ASSERT(ctx); 29022 NK_ASSERT(ctx->current); 29023 NK_ASSERT(ctx->current->layout); 29024 if (!ctx || !ctx->current || !ctx->current->layout) 29025 return 0; 29026 29027 win = ctx->current; 29028 style = &ctx->style; 29029 s = nk_widget(&header, ctx); 29030 if (!s) return 0; 29031 29032 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 29033 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 29034 is_clicked = nk_true; 29035 29036 /* draw combo box header background and border */ 29037 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 29038 background = &style->combo.active; 29039 symbol_color = style->combo.symbol_active; 29040 text.text = style->combo.label_active; 29041 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 29042 background = &style->combo.hover; 29043 symbol_color = style->combo.symbol_hover; 29044 text.text = style->combo.label_hover; 29045 } else { 29046 background = &style->combo.normal; 29047 symbol_color = style->combo.symbol_normal; 29048 text.text = style->combo.label_normal; 29049 } 29050 29051 switch(background->type) { 29052 case NK_STYLE_ITEM_IMAGE: 29053 text.background = nk_rgba(0, 0, 0, 0); 29054 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 29055 break; 29056 case NK_STYLE_ITEM_NINE_SLICE: 29057 text.background = nk_rgba(0, 0, 0, 0); 29058 nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white); 29059 break; 29060 case NK_STYLE_ITEM_COLOR: 29061 text.background = background->data.color; 29062 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 29063 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 29064 break; 29065 } 29066 { 29067 struct nk_rect content; 29068 struct nk_rect button; 29069 struct nk_rect label; 29070 struct nk_rect image; 29071 29072 enum nk_symbol_type sym; 29073 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 29074 sym = style->combo.sym_hover; 29075 else if (is_clicked) 29076 sym = style->combo.sym_active; 29077 else sym = style->combo.sym_normal; 29078 29079 /* calculate button */ 29080 button.w = header.h - 2 * style->combo.button_padding.y; 29081 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 29082 button.y = header.y + style->combo.button_padding.y; 29083 button.h = button.w; 29084 29085 content.x = button.x + style->combo.button.padding.x; 29086 content.y = button.y + style->combo.button.padding.y; 29087 content.w = button.w - 2 * style->combo.button.padding.x; 29088 content.h = button.h - 2 * style->combo.button.padding.y; 29089 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 29090 &ctx->style.combo.button, sym, style->font); 29091 29092 /* draw symbol */ 29093 image.x = header.x + style->combo.content_padding.x; 29094 image.y = header.y + style->combo.content_padding.y; 29095 image.h = header.h - 2 * style->combo.content_padding.y; 29096 image.w = image.h; 29097 nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color, 29098 1.0f, style->font); 29099 29100 /* draw label */ 29101 text.padding = nk_vec2(0,0); 29102 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; 29103 label.y = header.y + style->combo.content_padding.y; 29104 label.w = (button.x - style->combo.content_padding.x) - label.x; 29105 label.h = header.h - 2 * style->combo.content_padding.y; 29106 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); 29107 } 29108 return nk_combo_begin(ctx, win, size, is_clicked, header); 29109 } 29110 NK_API nk_bool 29111 nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size) 29112 { 29113 struct nk_window *win; 29114 struct nk_style *style; 29115 const struct nk_input *in; 29116 29117 struct nk_rect header; 29118 int is_clicked = nk_false; 29119 enum nk_widget_layout_states s; 29120 const struct nk_style_item *background; 29121 29122 NK_ASSERT(ctx); 29123 NK_ASSERT(ctx->current); 29124 NK_ASSERT(ctx->current->layout); 29125 if (!ctx || !ctx->current || !ctx->current->layout) 29126 return 0; 29127 29128 win = ctx->current; 29129 style = &ctx->style; 29130 s = nk_widget(&header, ctx); 29131 if (s == NK_WIDGET_INVALID) 29132 return 0; 29133 29134 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 29135 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 29136 is_clicked = nk_true; 29137 29138 /* draw combo box header background and border */ 29139 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) 29140 background = &style->combo.active; 29141 else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 29142 background = &style->combo.hover; 29143 else background = &style->combo.normal; 29144 29145 switch (background->type) { 29146 case NK_STYLE_ITEM_IMAGE: 29147 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 29148 break; 29149 case NK_STYLE_ITEM_NINE_SLICE: 29150 nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white); 29151 break; 29152 case NK_STYLE_ITEM_COLOR: 29153 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 29154 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 29155 break; 29156 } 29157 { 29158 struct nk_rect bounds = {0,0,0,0}; 29159 struct nk_rect content; 29160 struct nk_rect button; 29161 int draw_button_symbol; 29162 29163 enum nk_symbol_type sym; 29164 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 29165 sym = style->combo.sym_hover; 29166 else if (is_clicked) 29167 sym = style->combo.sym_active; 29168 else sym = style->combo.sym_normal; 29169 29170 /* represents whether or not the combo's button symbol should be drawn */ 29171 draw_button_symbol = sym != NK_SYMBOL_NONE; 29172 29173 /* calculate button */ 29174 button.w = header.h - 2 * style->combo.button_padding.y; 29175 button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; 29176 button.y = header.y + style->combo.button_padding.y; 29177 button.h = button.w; 29178 29179 content.x = button.x + style->combo.button.padding.x; 29180 content.y = button.y + style->combo.button.padding.y; 29181 content.w = button.w - 2 * style->combo.button.padding.x; 29182 content.h = button.h - 2 * style->combo.button.padding.y; 29183 29184 /* draw image */ 29185 bounds.h = header.h - 2 * style->combo.content_padding.y; 29186 bounds.y = header.y + style->combo.content_padding.y; 29187 bounds.x = header.x + style->combo.content_padding.x; 29188 if (draw_button_symbol) 29189 bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; 29190 else 29191 bounds.w = header.w - 2 * style->combo.content_padding.x; 29192 nk_draw_image(&win->buffer, bounds, &img, nk_white); 29193 29194 /* draw open/close button */ 29195 if (draw_button_symbol) 29196 nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, 29197 &ctx->style.combo.button, sym, style->font); 29198 } 29199 return nk_combo_begin(ctx, win, size, is_clicked, header); 29200 } 29201 NK_API nk_bool 29202 nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len, 29203 struct nk_image img, struct nk_vec2 size) 29204 { 29205 struct nk_window *win; 29206 struct nk_style *style; 29207 struct nk_input *in; 29208 29209 struct nk_rect header; 29210 int is_clicked = nk_false; 29211 enum nk_widget_layout_states s; 29212 const struct nk_style_item *background; 29213 struct nk_text text; 29214 29215 NK_ASSERT(ctx); 29216 NK_ASSERT(ctx->current); 29217 NK_ASSERT(ctx->current->layout); 29218 if (!ctx || !ctx->current || !ctx->current->layout) 29219 return 0; 29220 29221 win = ctx->current; 29222 style = &ctx->style; 29223 s = nk_widget(&header, ctx); 29224 if (!s) return 0; 29225 29226 in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; 29227 if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) 29228 is_clicked = nk_true; 29229 29230 /* draw combo box header background and border */ 29231 if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { 29232 background = &style->combo.active; 29233 text.text = style->combo.label_active; 29234 } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { 29235 background = &style->combo.hover; 29236 text.text = style->combo.label_hover; 29237 } else { 29238 background = &style->combo.normal; 29239 text.text = style->combo.label_normal; 29240 } 29241 29242 switch(background->type) { 29243 case NK_STYLE_ITEM_IMAGE: 29244 text.background = nk_rgba(0, 0, 0, 0); 29245 nk_draw_image(&win->buffer, header, &background->data.image, nk_white); 29246 break; 29247 case NK_STYLE_ITEM_NINE_SLICE: 29248 text.background = nk_rgba(0, 0, 0, 0); 29249 nk_draw_nine_slice(&win->buffer, header, &background->data.slice, nk_white); 29250 break; 29251 case NK_STYLE_ITEM_COLOR: 29252 text.background = background->data.color; 29253 nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); 29254 nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); 29255 break; 29256 } 29257 { 29258 struct nk_rect content; 29259 struct nk_rect button; 29260 struct nk_rect label; 29261 struct nk_rect image; 29262 int draw_button_symbol; 29263 29264 enum nk_symbol_type sym; 29265 if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) 29266 sym = style->combo.sym_hover; 29267 else if (is_clicked) 29268 sym = style->combo.sym_active; 29269 else sym = style->combo.sym_normal; 29270 29271 /* represents whether or not the combo's button symbol should be drawn */ 29272 draw_button_symbol = sym != NK_SYMBOL_NONE; 29273 29274 /* calculate button */ 29275 button.w = header.h - 2 * style->combo.button_padding.y; 29276 button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; 29277 button.y = header.y + style->combo.button_padding.y; 29278 button.h = button.w; 29279 29280 content.x = button.x + style->combo.button.padding.x; 29281 content.y = button.y + style->combo.button.padding.y; 29282 content.w = button.w - 2 * style->combo.button.padding.x; 29283 content.h = button.h - 2 * style->combo.button.padding.y; 29284 if (draw_button_symbol) 29285 nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, 29286 &ctx->style.combo.button, sym, style->font); 29287 29288 /* draw image */ 29289 image.x = header.x + style->combo.content_padding.x; 29290 image.y = header.y + style->combo.content_padding.y; 29291 image.h = header.h - 2 * style->combo.content_padding.y; 29292 image.w = image.h; 29293 nk_draw_image(&win->buffer, image, &img, nk_white); 29294 29295 /* draw label */ 29296 text.padding = nk_vec2(0,0); 29297 label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; 29298 label.y = header.y + style->combo.content_padding.y; 29299 label.h = header.h - 2 * style->combo.content_padding.y; 29300 if (draw_button_symbol) 29301 label.w = (button.x - style->combo.content_padding.x) - label.x; 29302 else 29303 label.w = (header.x + header.w - style->combo.content_padding.x) - label.x; 29304 nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); 29305 } 29306 return nk_combo_begin(ctx, win, size, is_clicked, header); 29307 } 29308 NK_API nk_bool 29309 nk_combo_begin_symbol_label(struct nk_context *ctx, 29310 const char *selected, enum nk_symbol_type type, struct nk_vec2 size) 29311 { 29312 return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size); 29313 } 29314 NK_API nk_bool 29315 nk_combo_begin_image_label(struct nk_context *ctx, 29316 const char *selected, struct nk_image img, struct nk_vec2 size) 29317 { 29318 return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size); 29319 } 29320 NK_API nk_bool 29321 nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align) 29322 { 29323 return nk_contextual_item_text(ctx, text, len, align); 29324 } 29325 NK_API nk_bool 29326 nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align) 29327 { 29328 return nk_contextual_item_label(ctx, label, align); 29329 } 29330 NK_API nk_bool 29331 nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text, 29332 int len, nk_flags alignment) 29333 { 29334 return nk_contextual_item_image_text(ctx, img, text, len, alignment); 29335 } 29336 NK_API nk_bool 29337 nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img, 29338 const char *text, nk_flags alignment) 29339 { 29340 return nk_contextual_item_image_label(ctx, img, text, alignment); 29341 } 29342 NK_API nk_bool 29343 nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, 29344 const char *text, int len, nk_flags alignment) 29345 { 29346 return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment); 29347 } 29348 NK_API nk_bool 29349 nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, 29350 const char *label, nk_flags alignment) 29351 { 29352 return nk_contextual_item_symbol_label(ctx, sym, label, alignment); 29353 } 29354 NK_API void nk_combo_end(struct nk_context *ctx) 29355 { 29356 nk_contextual_end(ctx); 29357 } 29358 NK_API void nk_combo_close(struct nk_context *ctx) 29359 { 29360 nk_contextual_close(ctx); 29361 } 29362 NK_API int 29363 nk_combo(struct nk_context *ctx, const char **items, int count, 29364 int selected, int item_height, struct nk_vec2 size) 29365 { 29366 int i = 0; 29367 int max_height; 29368 struct nk_vec2 item_spacing; 29369 struct nk_vec2 window_padding; 29370 29371 NK_ASSERT(ctx); 29372 NK_ASSERT(items); 29373 NK_ASSERT(ctx->current); 29374 if (!ctx || !items ||!count) 29375 return selected; 29376 29377 item_spacing = ctx->style.window.spacing; 29378 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 29379 max_height = count * item_height + count * (int)item_spacing.y; 29380 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 29381 size.y = NK_MIN(size.y, (float)max_height); 29382 if (nk_combo_begin_label(ctx, items[selected], size)) { 29383 nk_layout_row_dynamic(ctx, (float)item_height, 1); 29384 for (i = 0; i < count; ++i) { 29385 if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT)) 29386 selected = i; 29387 } 29388 nk_combo_end(ctx); 29389 } 29390 return selected; 29391 } 29392 NK_API int 29393 nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator, 29394 int separator, int selected, int count, int item_height, struct nk_vec2 size) 29395 { 29396 int i; 29397 int max_height; 29398 struct nk_vec2 item_spacing; 29399 struct nk_vec2 window_padding; 29400 const char *current_item; 29401 const char *iter; 29402 int length = 0; 29403 29404 NK_ASSERT(ctx); 29405 NK_ASSERT(items_separated_by_separator); 29406 if (!ctx || !items_separated_by_separator) 29407 return selected; 29408 29409 /* calculate popup window */ 29410 item_spacing = ctx->style.window.spacing; 29411 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 29412 max_height = count * item_height + count * (int)item_spacing.y; 29413 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 29414 size.y = NK_MIN(size.y, (float)max_height); 29415 29416 /* find selected item */ 29417 current_item = items_separated_by_separator; 29418 for (i = 0; i < count; ++i) { 29419 iter = current_item; 29420 while (*iter && *iter != separator) iter++; 29421 length = (int)(iter - current_item); 29422 if (i == selected) break; 29423 current_item = iter + 1; 29424 } 29425 29426 if (nk_combo_begin_text(ctx, current_item, length, size)) { 29427 current_item = items_separated_by_separator; 29428 nk_layout_row_dynamic(ctx, (float)item_height, 1); 29429 for (i = 0; i < count; ++i) { 29430 iter = current_item; 29431 while (*iter && *iter != separator) iter++; 29432 length = (int)(iter - current_item); 29433 if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT)) 29434 selected = i; 29435 current_item = current_item + length + 1; 29436 } 29437 nk_combo_end(ctx); 29438 } 29439 return selected; 29440 } 29441 NK_API int 29442 nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros, 29443 int selected, int count, int item_height, struct nk_vec2 size) 29444 { 29445 return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size); 29446 } 29447 NK_API int 29448 nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**), 29449 void *userdata, int selected, int count, int item_height, struct nk_vec2 size) 29450 { 29451 int i; 29452 int max_height; 29453 struct nk_vec2 item_spacing; 29454 struct nk_vec2 window_padding; 29455 const char *item; 29456 29457 NK_ASSERT(ctx); 29458 NK_ASSERT(item_getter); 29459 if (!ctx || !item_getter) 29460 return selected; 29461 29462 /* calculate popup window */ 29463 item_spacing = ctx->style.window.spacing; 29464 window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); 29465 max_height = count * item_height + count * (int)item_spacing.y; 29466 max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; 29467 size.y = NK_MIN(size.y, (float)max_height); 29468 29469 item_getter(userdata, selected, &item); 29470 if (nk_combo_begin_label(ctx, item, size)) { 29471 nk_layout_row_dynamic(ctx, (float)item_height, 1); 29472 for (i = 0; i < count; ++i) { 29473 item_getter(userdata, i, &item); 29474 if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT)) 29475 selected = i; 29476 } 29477 nk_combo_end(ctx); 29478 } return selected; 29479 } 29480 NK_API void 29481 nk_combobox(struct nk_context *ctx, const char **items, int count, 29482 int *selected, int item_height, struct nk_vec2 size) 29483 { 29484 *selected = nk_combo(ctx, items, count, *selected, item_height, size); 29485 } 29486 NK_API void 29487 nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros, 29488 int *selected, int count, int item_height, struct nk_vec2 size) 29489 { 29490 *selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size); 29491 } 29492 NK_API void 29493 nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator, 29494 int separator, int *selected, int count, int item_height, struct nk_vec2 size) 29495 { 29496 *selected = nk_combo_separator(ctx, items_separated_by_separator, separator, 29497 *selected, count, item_height, size); 29498 } 29499 NK_API void 29500 nk_combobox_callback(struct nk_context *ctx, 29501 void(*item_getter)(void* data, int id, const char **out_text), 29502 void *userdata, int *selected, int count, int item_height, struct nk_vec2 size) 29503 { 29504 *selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size); 29505 } 29506 29507 29508 29509 29510 29511 /* =============================================================== 29512 * 29513 * TOOLTIP 29514 * 29515 * ===============================================================*/ 29516 NK_API nk_bool 29517 nk_tooltip_begin(struct nk_context *ctx, float width) 29518 { 29519 int x,y,w,h; 29520 struct nk_window *win; 29521 const struct nk_input *in; 29522 struct nk_rect bounds; 29523 int ret; 29524 29525 NK_ASSERT(ctx); 29526 NK_ASSERT(ctx->current); 29527 NK_ASSERT(ctx->current->layout); 29528 if (!ctx || !ctx->current || !ctx->current->layout) 29529 return 0; 29530 29531 /* make sure that no nonblocking popup is currently active */ 29532 win = ctx->current; 29533 in = &ctx->input; 29534 if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK)) 29535 return 0; 29536 29537 w = nk_iceilf(width); 29538 h = nk_iceilf(nk_null_rect.h); 29539 x = nk_ifloorf(in->mouse.pos.x + 1) - (int)win->layout->clip.x; 29540 y = nk_ifloorf(in->mouse.pos.y + 1) - (int)win->layout->clip.y; 29541 29542 bounds.x = (float)x; 29543 bounds.y = (float)y; 29544 bounds.w = (float)w; 29545 bounds.h = (float)h; 29546 29547 ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC, 29548 "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds); 29549 if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM; 29550 win->popup.type = NK_PANEL_TOOLTIP; 29551 ctx->current->layout->type = NK_PANEL_TOOLTIP; 29552 return ret; 29553 } 29554 29555 NK_API void 29556 nk_tooltip_end(struct nk_context *ctx) 29557 { 29558 NK_ASSERT(ctx); 29559 NK_ASSERT(ctx->current); 29560 if (!ctx || !ctx->current) return; 29561 ctx->current->seq--; 29562 nk_popup_close(ctx); 29563 nk_popup_end(ctx); 29564 } 29565 NK_API void 29566 nk_tooltip(struct nk_context *ctx, const char *text) 29567 { 29568 const struct nk_style *style; 29569 struct nk_vec2 padding; 29570 29571 int text_len; 29572 float text_width; 29573 float text_height; 29574 29575 NK_ASSERT(ctx); 29576 NK_ASSERT(ctx->current); 29577 NK_ASSERT(ctx->current->layout); 29578 NK_ASSERT(text); 29579 if (!ctx || !ctx->current || !ctx->current->layout || !text) 29580 return; 29581 29582 /* fetch configuration data */ 29583 style = &ctx->style; 29584 padding = style->window.padding; 29585 29586 /* calculate size of the text and tooltip */ 29587 text_len = nk_strlen(text); 29588 text_width = style->font->width(style->font->userdata, 29589 style->font->height, text, text_len); 29590 text_width += (4 * padding.x); 29591 text_height = (style->font->height + 2 * padding.y); 29592 29593 /* execute tooltip and fill with text */ 29594 if (nk_tooltip_begin(ctx, (float)text_width)) { 29595 nk_layout_row_dynamic(ctx, (float)text_height, 1); 29596 nk_text(ctx, text, text_len, NK_TEXT_LEFT); 29597 nk_tooltip_end(ctx); 29598 } 29599 } 29600 #ifdef NK_INCLUDE_STANDARD_VARARGS 29601 NK_API void 29602 nk_tooltipf(struct nk_context *ctx, const char *fmt, ...) 29603 { 29604 va_list args; 29605 va_start(args, fmt); 29606 nk_tooltipfv(ctx, fmt, args); 29607 va_end(args); 29608 } 29609 NK_API void 29610 nk_tooltipfv(struct nk_context *ctx, const char *fmt, va_list args) 29611 { 29612 char buf[256]; 29613 nk_strfmt(buf, NK_LEN(buf), fmt, args); 29614 nk_tooltip(ctx, buf); 29615 } 29616 #endif 29617 29618 29619 29620 #endif /* NK_IMPLEMENTATION */ 29621 29622 /* 29623 /// ## License 29624 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none 29625 /// ------------------------------------------------------------------------------ 29626 /// This software is available under 2 licenses -- choose whichever you prefer. 29627 /// ------------------------------------------------------------------------------ 29628 /// ALTERNATIVE A - MIT License 29629 /// Copyright (c) 2016-2018 Micha Mettke 29630 /// Permission is hereby granted, free of charge, to any person obtaining a copy of 29631 /// this software and associated documentation files (the "Software"), to deal in 29632 /// the Software without restriction, including without limitation the rights to 29633 /// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 29634 /// of the Software, and to permit persons to whom the Software is furnished to do 29635 /// so, subject to the following conditions: 29636 /// The above copyright notice and this permission notice shall be included in all 29637 /// copies or substantial portions of the Software. 29638 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29639 /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29640 /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29641 /// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29642 /// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29643 /// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 29644 /// SOFTWARE. 29645 /// ------------------------------------------------------------------------------ 29646 /// ALTERNATIVE B - Public Domain (www.unlicense.org) 29647 /// This is free and unencumbered software released into the public domain. 29648 /// Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 29649 /// software, either in source code form or as a compiled binary, for any purpose, 29650 /// commercial or non-commercial, and by any means. 29651 /// In jurisdictions that recognize copyright laws, the author or authors of this 29652 /// software dedicate any and all copyright interest in the software to the public 29653 /// domain. We make this dedication for the benefit of the public at large and to 29654 /// the detriment of our heirs and successors. We intend this dedication to be an 29655 /// overt act of relinquishment in perpetuity of all present and future rights to 29656 /// this software under copyright law. 29657 /// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 29658 /// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 29659 /// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 29660 /// AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 29661 /// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 29662 /// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 29663 /// ------------------------------------------------------------------------------ 29664 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 29665 29666 /// ## Changelog 29667 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~none 29668 /// [date] ([x.y.z]) - [description] 29669 /// - [date]: date on which the change has been pushed 29670 /// - [x.y.z]: Version string, represented in Semantic Versioning format 29671 /// - [x]: Major version with API and library breaking changes 29672 /// - [y]: Minor version with non-breaking API and library changes 29673 /// - [z]: Patch version with no direct changes to the API 29674 /// 29675 /// - 2022/12/23 (4.10.6) - Fix incorrect glyph index in nk_font_bake() 29676 /// - 2022/12/17 (4.10.5) - Fix nk_font_bake_pack() using TTC font offset incorrectly 29677 /// - 2022/10/24 (4.10.4) - Fix nk_str_{append,insert}_str_utf8 always returning 0 29678 /// - 2022/09/03 (4.10.3) - Renamed the `null` texture variable to `tex_null` 29679 /// - 2022/08/01 (4.10.2) - Fix Apple Silicon with incorrect NK_SITE_TYPE and NK_POINTER_TYPE 29680 /// - 2022/08/01 (4.10.1) - Fix cursor jumping back to beginning of text when typing more than 29681 /// nk_edit_xxx limit 29682 /// - 2022/05/27 (4.10.0) - Add nk_input_has_mouse_click_in_button_rect() to fix window move bug 29683 /// - 2022/04/18 (4.9.7) - Change button behavior when NK_BUTTON_TRIGGER_ON_RELEASE is defined to 29684 /// only trigger when the mouse position was inside the same button on down 29685 /// - 2022/02/03 (4.9.6) - Allow overriding the NK_INV_SQRT function, similar to NK_SIN and NK_COS 29686 /// - 2021/12/22 (4.9.5) - Revert layout bounds not accounting for padding due to regressions 29687 /// - 2021/12/22 (4.9.4) - Fix checking hovering when window is minimized 29688 /// - 2021/12/22 (4.09.3) - Fix layout bounds not accounting for padding 29689 /// - 2021/12/19 (4.09.2) - Update to stb_rect_pack.h v1.01 and stb_truetype.h v1.26 29690 /// - 2021/12/16 (4.09.1) - Fix the majority of GCC warnings 29691 /// - 2021/10/16 (4.09.0) - Added nk_spacer() widget 29692 /// - 2021/09/22 (4.08.6) - Fix "may be used uninitialized" warnings in nk_widget 29693 /// - 2021/09/22 (4.08.5) - GCC __builtin_offsetof only exists in version 4 and later 29694 /// - 2021/09/15 (4.08.4) - Fix "'num_len' may be used uninitialized" in nk_do_property 29695 /// - 2021/09/15 (4.08.3) - Fix "Templates cannot be declared to have 'C' Linkage" 29696 /// - 2021/09/08 (4.08.2) - Fix warnings in C89 builds 29697 /// - 2021/09/08 (4.08.1) - Use compiler builtins for NK_OFFSETOF when possible 29698 /// - 2021/08/17 (4.08.0) - Implemented 9-slice scaling support for widget styles 29699 /// - 2021/08/16 (4.07.5) - Replace usage of memset in nk_font_atlas_bake with NK_MEMSET 29700 /// - 2021/08/15 (4.07.4) - Fix conversion and sign conversion warnings 29701 /// - 2021/08/08 (4.07.3) - Fix crash when baking merged fonts 29702 /// - 2021/08/08 (4.07.2) - Fix Multiline Edit wrong offset 29703 /// - 2021/03/17 (4.07.1) - Fix warning about unused parameter 29704 /// - 2021/03/17 (4.07.0) - Fix nk_property hover bug 29705 /// - 2021/03/15 (4.06.4) - Change nk_propertyi back to int 29706 /// - 2021/03/15 (4.06.3) - Update documentation for functions that now return nk_bool 29707 /// - 2020/12/19 (4.06.2) - Fix additional C++ style comments which are not allowed in ISO C90. 29708 /// - 2020/10/11 (4.06.1) - Fix C++ style comments which are not allowed in ISO C90. 29709 /// - 2020/10/07 (4.06.0) - Fix nk_combo return type wrongly changed to nk_bool 29710 /// - 2020/09/05 (4.05.0) - Use the nk_font_atlas allocator for stb_truetype memory management. 29711 /// - 2020/09/04 (4.04.1) - Replace every boolean int by nk_bool 29712 /// - 2020/09/04 (4.04.0) - Add nk_bool with NK_INCLUDE_STANDARD_BOOL 29713 /// - 2020/06/13 (4.03.1) - Fix nk_pool allocation sizes. 29714 /// - 2020/06/04 (4.03.0) - Made nk_combo header symbols optional. 29715 /// - 2020/05/27 (4.02.5) - Fix nk_do_edit: Keep scroll position when re-activating edit widget. 29716 /// - 2020/05/09 (4.02.4) - Fix nk_menubar height calculation bug 29717 /// - 2020/05/08 (4.02.3) - Fix missing stdarg.h with NK_INCLUDE_STANDARD_VARARGS 29718 /// - 2020/04/30 (4.02.2) - Fix nk_edit border drawing bug 29719 /// - 2020/04/09 (4.02.1) - Removed unused nk_sqrt function to fix compiler warnings 29720 /// - Fixed compiler warnings if you bring your own methods for 29721 /// nk_cos/nk_sin/nk_strtod/nk_memset/nk_memcopy/nk_dtoa 29722 /// - 2020/04/06 (4.01.10) - Fix bug: Do not use pool before checking for NULL 29723 /// - 2020/03/22 (4.01.9) - Fix bug where layout state wasn't restored correctly after 29724 /// popping a tree. 29725 /// - 2020/03/11 (4.01.8) - Fix bug where padding is subtracted from widget 29726 /// - 2020/03/06 (4.01.7) - Fix bug where width padding was applied twice 29727 /// - 2020/02/06 (4.01.6) - Update stb_truetype.h and stb_rect_pack.h and separate them 29728 /// - 2019/12/10 (4.01.5) - Fix off-by-one error in NK_INTERSECT 29729 /// - 2019/10/09 (4.01.4) - Fix bug for autoscrolling in nk_do_edit 29730 /// - 2019/09/20 (4.01.3) - Fixed a bug wherein combobox cannot be closed by clicking the header 29731 /// when NK_BUTTON_TRIGGER_ON_RELEASE is defined. 29732 /// - 2019/09/10 (4.01.2) - Fixed the nk_cos function, which deviated significantly. 29733 /// - 2019/09/08 (4.01.1) - Fixed a bug wherein re-baking of fonts caused a segmentation 29734 /// fault due to dst_font->glyph_count not being zeroed on subsequent 29735 /// bakes of the same set of fonts. 29736 /// - 2019/06/23 (4.01.0) - Added nk_***_get_scroll and nk_***_set_scroll for groups, windows, and popups. 29737 /// - 2019/06/12 (4.00.3) - Fix panel background drawing bug. 29738 /// - 2018/10/31 (4.00.2) - Added NK_KEYSTATE_BASED_INPUT to "fix" state based backends 29739 /// like GLFW without breaking key repeat behavior on event based. 29740 /// - 2018/04/01 (4.00.1) - Fixed calling `nk_convert` multiple time per single frame. 29741 /// - 2018/04/01 (4.00.0) - BREAKING CHANGE: nk_draw_list_clear no longer tries to 29742 /// clear provided buffers. So make sure to either free 29743 /// or clear each passed buffer after calling nk_convert. 29744 /// - 2018/02/23 (3.00.6) - Fixed slider dragging behavior. 29745 /// - 2018/01/31 (3.00.5) - Fixed overcalculation of cursor data in font baking process. 29746 /// - 2018/01/31 (3.00.4) - Removed name collision with stb_truetype. 29747 /// - 2018/01/28 (3.00.3) - Fixed panel window border drawing bug. 29748 /// - 2018/01/12 (3.00.2) - Added `nk_group_begin_titled` for separated group identifier and title. 29749 /// - 2018/01/07 (3.00.1) - Started to change documentation style. 29750 /// - 2018/01/05 (3.00.0) - BREAKING CHANGE: The previous color picker API was broken 29751 /// because of conversions between float and byte color representation. 29752 /// Color pickers now use floating point values to represent 29753 /// HSV values. To get back the old behavior I added some additional 29754 /// color conversion functions to cast between nk_color and 29755 /// nk_colorf. 29756 /// - 2017/12/23 (2.00.7) - Fixed small warning. 29757 /// - 2017/12/23 (2.00.7) - Fixed `nk_edit_buffer` behavior if activated to allow input. 29758 /// - 2017/12/23 (2.00.7) - Fixed modifyable progressbar dragging visuals and input behavior. 29759 /// - 2017/12/04 (2.00.6) - Added formatted string tooltip widget. 29760 /// - 2017/11/18 (2.00.5) - Fixed window becoming hidden with flag `NK_WINDOW_NO_INPUT`. 29761 /// - 2017/11/15 (2.00.4) - Fixed font merging. 29762 /// - 2017/11/07 (2.00.3) - Fixed window size and position modifier functions. 29763 /// - 2017/09/14 (2.00.2) - Fixed `nk_edit_buffer` and `nk_edit_focus` behavior. 29764 /// - 2017/09/14 (2.00.1) - Fixed window closing behavior. 29765 /// - 2017/09/14 (2.00.0) - BREAKING CHANGE: Modifying window position and size functions now 29766 /// require the name of the window and must happen outside the window 29767 /// building process (between function call nk_begin and nk_end). 29768 /// - 2017/09/11 (1.40.9) - Fixed window background flag if background window is declared last. 29769 /// - 2017/08/27 (1.40.8) - Fixed `nk_item_is_any_active` for hidden windows. 29770 /// - 2017/08/27 (1.40.7) - Fixed window background flag. 29771 /// - 2017/07/07 (1.40.6) - Fixed missing clipping rect check for hovering/clicked 29772 /// query for widgets. 29773 /// - 2017/07/07 (1.40.5) - Fixed drawing bug for vertex output for lines and stroked 29774 /// and filled rectangles. 29775 /// - 2017/07/07 (1.40.4) - Fixed bug in nk_convert trying to add windows that are in 29776 /// process of being destroyed. 29777 /// - 2017/07/07 (1.40.3) - Fixed table internal bug caused by storing table size in 29778 /// window instead of directly in table. 29779 /// - 2017/06/30 (1.40.2) - Removed unneeded semicolon in C++ NK_ALIGNOF macro. 29780 /// - 2017/06/30 (1.40.1) - Fixed drawing lines smaller or equal zero. 29781 /// - 2017/06/08 (1.40.0) - Removed the breaking part of last commit. Auto layout now only 29782 /// comes in effect if you pass in zero was row height argument. 29783 /// - 2017/06/08 (1.40.0) - BREAKING CHANGE: while not directly API breaking it will change 29784 /// how layouting works. From now there will be an internal minimum 29785 /// row height derived from font height. If you need a row smaller than 29786 /// that you can directly set it by `nk_layout_set_min_row_height` and 29787 /// reset the value back by calling `nk_layout_reset_min_row_height. 29788 /// - 2017/06/08 (1.39.1) - Fixed property text edit handling bug caused by past `nk_widget` fix. 29789 /// - 2017/06/08 (1.39.0) - Added function to retrieve window space without calling a `nk_layout_xxx` function. 29790 /// - 2017/06/06 (1.38.5) - Fixed `nk_convert` return flag for command buffer. 29791 /// - 2017/05/23 (1.38.4) - Fixed activation behavior for widgets partially clipped. 29792 /// - 2017/05/10 (1.38.3) - Fixed wrong min window size mouse scaling over boundaries. 29793 /// - 2017/05/09 (1.38.2) - Fixed vertical scrollbar drawing with not enough space. 29794 /// - 2017/05/09 (1.38.1) - Fixed scaler dragging behavior if window size hits minimum size. 29795 /// - 2017/05/06 (1.38.0) - Added platform double-click support. 29796 /// - 2017/04/20 (1.37.1) - Fixed key repeat found inside glfw demo backends. 29797 /// - 2017/04/20 (1.37.0) - Extended properties with selection and clipboard support. 29798 /// - 2017/04/20 (1.36.2) - Fixed #405 overlapping rows with zero padding and spacing. 29799 /// - 2017/04/09 (1.36.1) - Fixed #403 with another widget float error. 29800 /// - 2017/04/09 (1.36.0) - Added window `NK_WINDOW_NO_INPUT` and `NK_WINDOW_NOT_INTERACTIVE` flags. 29801 /// - 2017/04/09 (1.35.3) - Fixed buffer heap corruption. 29802 /// - 2017/03/25 (1.35.2) - Fixed popup overlapping for `NK_WINDOW_BACKGROUND` windows. 29803 /// - 2017/03/25 (1.35.1) - Fixed windows closing behavior. 29804 /// - 2017/03/18 (1.35.0) - Added horizontal scroll requested in #377. 29805 /// - 2017/03/18 (1.34.3) - Fixed long window header titles. 29806 /// - 2017/03/04 (1.34.2) - Fixed text edit filtering. 29807 /// - 2017/03/04 (1.34.1) - Fixed group closable flag. 29808 /// - 2017/02/25 (1.34.0) - Added custom draw command for better language binding support. 29809 /// - 2017/01/24 (1.33.0) - Added programmatic way to remove edit focus. 29810 /// - 2017/01/24 (1.32.3) - Fixed wrong define for basic type definitions for windows. 29811 /// - 2017/01/21 (1.32.2) - Fixed input capture from hidden or closed windows. 29812 /// - 2017/01/21 (1.32.1) - Fixed slider behavior and drawing. 29813 /// - 2017/01/13 (1.32.0) - Added flag to put scaler into the bottom left corner. 29814 /// - 2017/01/13 (1.31.0) - Added additional row layouting method to combine both 29815 /// dynamic and static widgets. 29816 /// - 2016/12/31 (1.30.0) - Extended scrollbar offset from 16-bit to 32-bit. 29817 /// - 2016/12/31 (1.29.2) - Fixed closing window bug of minimized windows. 29818 /// - 2016/12/03 (1.29.1) - Fixed wrapped text with no seperator and C89 error. 29819 /// - 2016/12/03 (1.29.0) - Changed text wrapping to process words not characters. 29820 /// - 2016/11/22 (1.28.6) - Fixed window minimized closing bug. 29821 /// - 2016/11/19 (1.28.5) - Fixed abstract combo box closing behavior. 29822 /// - 2016/11/19 (1.28.4) - Fixed tooltip flickering. 29823 /// - 2016/11/19 (1.28.3) - Fixed memory leak caused by popup repeated closing. 29824 /// - 2016/11/18 (1.28.2) - Fixed memory leak caused by popup panel allocation. 29825 /// - 2016/11/10 (1.28.1) - Fixed some warnings and C++ error. 29826 /// - 2016/11/10 (1.28.0) - Added additional `nk_button` versions which allows to directly 29827 /// pass in a style struct to change buttons visual. 29828 /// - 2016/11/10 (1.27.0) - Added additional `nk_tree` versions to support external state 29829 /// storage. Just like last the `nk_group` commit the main 29830 /// advantage is that you optionally can minimize nuklears runtime 29831 /// memory consumption or handle hash collisions. 29832 /// - 2016/11/09 (1.26.0) - Added additional `nk_group` version to support external scrollbar 29833 /// offset storage. Main advantage is that you can externalize 29834 /// the memory management for the offset. It could also be helpful 29835 /// if you have a hash collision in `nk_group_begin` but really 29836 /// want the name. In addition I added `nk_list_view` which allows 29837 /// to draw big lists inside a group without actually having to 29838 /// commit the whole list to nuklear (issue #269). 29839 /// - 2016/10/30 (1.25.1) - Fixed clipping rectangle bug inside `nk_draw_list`. 29840 /// - 2016/10/29 (1.25.0) - Pulled `nk_panel` memory management into nuklear and out of 29841 /// the hands of the user. From now on users don't have to care 29842 /// about panels unless they care about some information. If you 29843 /// still need the panel just call `nk_window_get_panel`. 29844 /// - 2016/10/21 (1.24.0) - Changed widget border drawing to stroked rectangle from filled 29845 /// rectangle for less overdraw and widget background transparency. 29846 /// - 2016/10/18 (1.23.0) - Added `nk_edit_focus` for manually edit widget focus control. 29847 /// - 2016/09/29 (1.22.7) - Fixed deduction of basic type in non `<stdint.h>` compilation. 29848 /// - 2016/09/29 (1.22.6) - Fixed edit widget UTF-8 text cursor drawing bug. 29849 /// - 2016/09/28 (1.22.5) - Fixed edit widget UTF-8 text appending/inserting/removing. 29850 /// - 2016/09/28 (1.22.4) - Fixed drawing bug inside edit widgets which offset all text 29851 /// text in every edit widget if one of them is scrolled. 29852 /// - 2016/09/28 (1.22.3) - Fixed small bug in edit widgets if not active. The wrong 29853 /// text length is passed. It should have been in bytes but 29854 /// was passed as glyphs. 29855 /// - 2016/09/20 (1.22.2) - Fixed color button size calculation. 29856 /// - 2016/09/20 (1.22.1) - Fixed some `nk_vsnprintf` behavior bugs and removed `<stdio.h>` 29857 /// again from `NK_INCLUDE_STANDARD_VARARGS`. 29858 /// - 2016/09/18 (1.22.0) - C89 does not support vsnprintf only C99 and newer as well 29859 /// as C++11 and newer. In addition to use vsnprintf you have 29860 /// to include <stdio.h>. So just defining `NK_INCLUDE_STD_VAR_ARGS` 29861 /// is not enough. That behavior is now fixed. By default if 29862 /// both varargs as well as stdio is selected I try to use 29863 /// vsnprintf if not possible I will revert to vsprintf. If 29864 /// varargs but not stdio was defined I will use my own function. 29865 /// - 2016/09/15 (1.21.2) - Fixed panel `close` behavior for deeper panel levels. 29866 /// - 2016/09/15 (1.21.1) - Fixed C++ errors and wrong argument to `nk_panel_get_xxxx`. 29867 /// - 2016/09/13 (1.21.0) - !BREAKING! Fixed nonblocking popup behavior in menu, combo, 29868 /// and contextual which prevented closing in y-direction if 29869 /// popup did not reach max height. 29870 /// In addition the height parameter was changed into vec2 29871 /// for width and height to have more control over the popup size. 29872 /// - 2016/09/13 (1.20.3) - Cleaned up and extended type selection. 29873 /// - 2016/09/13 (1.20.2) - Fixed slider behavior hopefully for the last time. This time 29874 /// all calculation are correct so no more hackery. 29875 /// - 2016/09/13 (1.20.1) - Internal change to divide window/panel flags into panel flags and types. 29876 /// Suprisinly spend years in C and still happened to confuse types 29877 /// with flags. Probably something to take note. 29878 /// - 2016/09/08 (1.20.0) - Added additional helper function to make it easier to just 29879 /// take the produced buffers from `nk_convert` and unplug the 29880 /// iteration process from `nk_context`. So now you can 29881 /// just use the vertex,element and command buffer + two pointer 29882 /// inside the command buffer retrieved by calls `nk__draw_begin` 29883 /// and `nk__draw_end` and macro `nk_draw_foreach_bounded`. 29884 /// - 2016/09/08 (1.19.0) - Added additional asserts to make sure every `nk_xxx_begin` call 29885 /// for windows, popups, combobox, menu and contextual is guarded by 29886 /// `if` condition and does not produce false drawing output. 29887 /// - 2016/09/08 (1.18.0) - Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT` 29888 /// to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and 29889 /// `NK_SYMBOL_RECT_OUTLINE`. 29890 /// - 2016/09/08 (1.17.0) - Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE` 29891 /// to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and 29892 /// `NK_SYMBOL_CIRCLE_OUTLINE`. 29893 /// - 2016/09/08 (1.16.0) - Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES` 29894 /// is not defined by supporting the biggest compiler GCC, clang and MSVC. 29895 /// - 2016/09/07 (1.15.3) - Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error. 29896 /// - 2016/09/04 (1.15.2) - Fixed wrong combobox height calculation. 29897 /// - 2016/09/03 (1.15.1) - Fixed gaps inside combo boxes in OpenGL. 29898 /// - 2016/09/02 (1.15.0) - Changed nuklear to not have any default vertex layout and 29899 /// instead made it user provided. The range of types to convert 29900 /// to is quite limited at the moment, but I would be more than 29901 /// happy to accept PRs to add additional. 29902 /// - 2016/08/30 (1.14.2) - Removed unused variables. 29903 /// - 2016/08/30 (1.14.1) - Fixed C++ build errors. 29904 /// - 2016/08/30 (1.14.0) - Removed mouse dragging from SDL demo since it does not work correctly. 29905 /// - 2016/08/30 (1.13.4) - Tweaked some default styling variables. 29906 /// - 2016/08/30 (1.13.3) - Hopefully fixed drawing bug in slider, in general I would 29907 /// refrain from using slider with a big number of steps. 29908 /// - 2016/08/30 (1.13.2) - Fixed close and minimize button which would fire even if the 29909 /// window was in Read Only Mode. 29910 /// - 2016/08/30 (1.13.1) - Fixed popup panel padding handling which was previously just 29911 /// a hack for combo box and menu. 29912 /// - 2016/08/30 (1.13.0) - Removed `NK_WINDOW_DYNAMIC` flag from public API since 29913 /// it is bugged and causes issues in window selection. 29914 /// - 2016/08/30 (1.12.0) - Removed scaler size. The size of the scaler is now 29915 /// determined by the scrollbar size. 29916 /// - 2016/08/30 (1.11.2) - Fixed some drawing bugs caused by changes from 1.11.0. 29917 /// - 2016/08/30 (1.11.1) - Fixed overlapping minimized window selection. 29918 /// - 2016/08/30 (1.11.0) - Removed some internal complexity and overly complex code 29919 /// handling panel padding and panel border. 29920 /// - 2016/08/29 (1.10.0) - Added additional height parameter to `nk_combobox_xxx`. 29921 /// - 2016/08/29 (1.10.0) - Fixed drawing bug in dynamic popups. 29922 /// - 2016/08/29 (1.10.0) - Added experimental mouse scrolling to popups, menus and comboboxes. 29923 /// - 2016/08/26 (1.10.0) - Added window name string prepresentation to account for 29924 /// hash collisions. Currently limited to `NK_WINDOW_MAX_NAME` 29925 /// which in term can be redefined if not big enough. 29926 /// - 2016/08/26 (1.10.0) - Added stacks for temporary style/UI changes in code. 29927 /// - 2016/08/25 (1.10.0) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released' 29928 /// to account for key press and release happening in one frame. 29929 /// - 2016/08/25 (1.10.0) - Added additional nk_edit flag to directly jump to the end on activate. 29930 /// - 2016/08/17 (1.09.6) - Removed invalid check for value zero in `nk_propertyx`. 29931 /// - 2016/08/16 (1.09.5) - Fixed ROM mode for deeper levels of popup windows parents. 29932 /// - 2016/08/15 (1.09.4) - Editbox are now still active if enter was pressed with flag 29933 /// `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep 29934 /// typing after committing. 29935 /// - 2016/08/15 (1.09.4) - Removed redundant code. 29936 /// - 2016/08/15 (1.09.4) - Fixed negative numbers in `nk_strtoi` and remove unused variable. 29937 /// - 2016/08/15 (1.09.3) - Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background 29938 /// window only as selected by hovering and not by clicking. 29939 /// - 2016/08/14 (1.09.2) - Fixed a bug in font atlas which caused wrong loading 29940 /// of glyphs for font with multiple ranges. 29941 /// - 2016/08/12 (1.09.1) - Added additional function to check if window is currently 29942 /// hidden and therefore not visible. 29943 /// - 2016/08/12 (1.09.1) - nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED` 29944 /// instead of the old flag `NK_WINDOW_HIDDEN`. 29945 /// - 2016/08/09 (1.09.0) - Added additional double version to nk_property and changed 29946 /// the underlying implementation to not cast to float and instead 29947 /// work directly on the given values. 29948 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal 29949 /// floating pointer number to string conversion for additional 29950 /// precision. 29951 /// - 2016/08/09 (1.08.0) - Added additional define to overwrite library internal 29952 /// string to floating point number conversion for additional 29953 /// precision. 29954 /// - 2016/08/08 (1.07.2) - Fixed compiling error without define `NK_INCLUDE_FIXED_TYPE`. 29955 /// - 2016/08/08 (1.07.1) - Fixed possible floating point error inside `nk_widget` leading 29956 /// to wrong wiget width calculation which results in widgets falsely 29957 /// becoming tagged as not inside window and cannot be accessed. 29958 /// - 2016/08/08 (1.07.0) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and 29959 /// closing a window (NK_WINDOW_CLOSED). A window can be hidden/shown 29960 /// by using `nk_window_show` and closed by either clicking the close 29961 /// icon in a window or by calling `nk_window_close`. Only closed 29962 /// windows get removed at the end of the frame while hidden windows 29963 /// remain. 29964 /// - 2016/08/08 (1.06.0) - Added `nk_edit_string_zero_terminated` as a second option to 29965 /// `nk_edit_string` which takes, edits and outputs a '\0' terminated string. 29966 /// - 2016/08/08 (1.05.4) - Fixed scrollbar auto hiding behavior. 29967 /// - 2016/08/08 (1.05.3) - Fixed wrong panel padding selection in `nk_layout_widget_space`. 29968 /// - 2016/08/07 (1.05.2) - Fixed old bug in dynamic immediate mode layout API, calculating 29969 /// wrong item spacing and panel width. 29970 /// - 2016/08/07 (1.05.1) - Hopefully finally fixed combobox popup drawing bug. 29971 /// - 2016/08/07 (1.05.0) - Split varargs away from `NK_INCLUDE_STANDARD_IO` into own 29972 /// define `NK_INCLUDE_STANDARD_VARARGS` to allow more fine 29973 /// grained controlled over library includes. 29974 /// - 2016/08/06 (1.04.5) - Changed memset calls to `NK_MEMSET`. 29975 /// - 2016/08/04 (1.04.4) - Fixed fast window scaling behavior. 29976 /// - 2016/08/04 (1.04.3) - Fixed window scaling, movement bug which appears if you 29977 /// move/scale a window and another window is behind it. 29978 /// If you are fast enough then the window behind gets activated 29979 /// and the operation is blocked. I now require activating 29980 /// by hovering only if mouse is not pressed. 29981 /// - 2016/08/04 (1.04.2) - Fixed changing fonts. 29982 /// - 2016/08/03 (1.04.1) - Fixed `NK_WINDOW_BACKGROUND` behavior. 29983 /// - 2016/08/03 (1.04.0) - Added color parameter to `nk_draw_image`. 29984 /// - 2016/08/03 (1.04.0) - Added additional window padding style attributes for 29985 /// sub windows (combo, menu, ...). 29986 /// - 2016/08/03 (1.04.0) - Added functions to show/hide software cursor. 29987 /// - 2016/08/03 (1.04.0) - Added `NK_WINDOW_BACKGROUND` flag to force a window 29988 /// to be always in the background of the screen. 29989 /// - 2016/08/03 (1.03.2) - Removed invalid assert macro for NK_RGB color picker. 29990 /// - 2016/08/01 (1.03.1) - Added helper macros into header include guard. 29991 /// - 2016/07/29 (1.03.0) - Moved the window/table pool into the header part to 29992 /// simplify memory management by removing the need to 29993 /// allocate the pool. 29994 /// - 2016/07/29 (1.02.0) - Added auto scrollbar hiding window flag which if enabled 29995 /// will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT 29996 /// seconds without window interaction. To make it work 29997 /// you have to also set a delta time inside the `nk_context`. 29998 /// - 2016/07/25 (1.01.1) - Fixed small panel and panel border drawing bugs. 29999 /// - 2016/07/15 (1.01.0) - Added software cursor to `nk_style` and `nk_context`. 30000 /// - 2016/07/15 (1.01.0) - Added const correctness to `nk_buffer_push' data argument. 30001 /// - 2016/07/15 (1.01.0) - Removed internal font baking API and simplified 30002 /// font atlas memory management by converting pointer 30003 /// arrays for fonts and font configurations to lists. 30004 /// - 2016/07/15 (1.00.0) - Changed button API to use context dependent button 30005 /// behavior instead of passing it for every function call. 30006 /// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 30007 /// ## Gallery 30008 /// ![Figure [blue]: Feature overview with blue color styling](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png) 30009 /// ![Figure [red]: Feature overview with red color styling](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png) 30010 /// ![Figure [widgets]: Widget overview](https://cloud.githubusercontent.com/assets/8057201/11282359/3325e3c6-8eff-11e5-86cb-cf02b0596087.png) 30011 /// ![Figure [blackwhite]: Black and white](https://cloud.githubusercontent.com/assets/8057201/11033668/59ab5d04-86e5-11e5-8091-c56f16411565.png) 30012 /// ![Figure [filexp]: File explorer](https://cloud.githubusercontent.com/assets/8057201/10718115/02a9ba08-7b6b-11e5-950f-adacdd637739.png) 30013 /// ![Figure [opengl]: OpenGL Editor](https://cloud.githubusercontent.com/assets/8057201/12779619/2a20d72c-ca69-11e5-95fe-4edecf820d5c.png) 30014 /// ![Figure [nodedit]: Node Editor](https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif) 30015 /// ![Figure [skinning]: Using skinning in Nuklear](https://cloud.githubusercontent.com/assets/8057201/15991632/76494854-30b8-11e6-9555-a69840d0d50b.png) 30016 /// ![Figure [bf]: Heavy modified version](https://cloud.githubusercontent.com/assets/8057201/14902576/339926a8-0d9c-11e6-9fee-a8b73af04473.png) 30017 /// 30018 /// ## Credits 30019 /// Developed by Micha Mettke and every direct or indirect github contributor. <br /><br /> 30020 /// 30021 /// Embeds [stb_texedit](https://github.com/nothings/stb/blob/master/stb_textedit.h), [stb_truetype](https://github.com/nothings/stb/blob/master/stb_truetype.h) and [stb_rectpack](https://github.com/nothings/stb/blob/master/stb_rect_pack.h) by Sean Barret (public domain) <br /> 30022 /// Uses [stddoc.c](https://github.com/r-lyeh/stddoc.c) from r-lyeh@github.com for documentation generation <br /><br /> 30023 /// Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). <br /> 30024 /// 30025 /// Big thank you to Omar Cornut (ocornut@github) for his [imgui library](https://github.com/ocornut/imgui) and 30026 /// giving me the inspiration for this library, Casey Muratori for handmade hero 30027 /// and his original immediate mode graphical user interface idea and Sean 30028 /// Barret for his amazing single header libraries which restored my faith 30029 /// in libraries and brought me to create some of my own. Finally Apoorva Joshi 30030 /// for his single header file packer. 30031 */ 30032