diff --git a/deps/nuklear/.gitattributes b/deps/nuklear/.gitattributes deleted file mode 100644 index 5a5328c3..00000000 --- a/deps/nuklear/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ -# Github language settings -*.h linguist-language=c -*.c linguist-language=c diff --git a/deps/nuklear/.gitignore b/deps/nuklear/.gitignore deleted file mode 100644 index a9f3b636..00000000 --- a/deps/nuklear/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -demo/*/*.exe -demo/*/*.obj diff --git a/deps/nuklear/.travis.yml b/deps/nuklear/.travis.yml deleted file mode 100644 index 6d13e555..00000000 --- a/deps/nuklear/.travis.yml +++ /dev/null @@ -1,15 +0,0 @@ -language: c - -os: - - linux - -compiler: - - gcc - - clang - -before_install: - - if [ $TRAVIS_OS_NAME == linux ]; then sudo add-apt-repository -y ppa:pyglfw/pyglfw && sudo apt-get update -qq && sudo apt-get install -y --no-install-recommends libglfw3 libglfw3-dev libglew-dev; fi - -script: - - make -C demo/glfw_opengl3 - - make -C demo/glfw_opengl2 diff --git a/deps/nuklear/CHANGELOG.md b/deps/nuklear/CHANGELOG.md deleted file mode 100644 index fd981d4d..00000000 --- a/deps/nuklear/CHANGELOG.md +++ /dev/null @@ -1,192 +0,0 @@ -# Changelog -- 2016/12/31 (1.20) - Extended scrollbar offset from 16-bit to 32-bit -- 2016/12/31 (1.192)- Fixed closing window bug of minimized windows -- 2016/12/03 (1.191)- Fixed wrapped text with no seperator and C89 error -- 2016/12/03 (1.19) - Changed text wrapping to process words not characters -- 2016/11/22 (1.184)- Fixed window minimized closing bug -- 2016/11/19 (1.184)- Fixed abstract combo box closing behavior -- 2016/11/19 (1.184)- Fixed tooltip flickering -- 2016/11/19 (1.183)- Fixed memory leak caused by popup repeated closing -- 2016/11/18 (1.182)- Fixed memory leak caused by popup panel allocation -- 2016/11/10 (1.181)- Fixed some warnings and C++ error -- 2016/11/10 (1.180)- Added additional `nk_button` versions which allows to directly - pass in a style struct to change buttons visual. -- 2016/11/10 (1.180)- Added additional 'nk_tree' versions to support external state - storage. Just like last the `nk_group` commit the main - advantage is that you optionally can minimize nuklears runtime - memory consumption or handle hash collisions. -- 2016/11/09 (1.180)- Added additional `nk_group` version to support external scrollbar - offset storage. Main advantage is that you can externalize - the memory management for the offset. It could also be helpful - if you have a hash collision in `nk_group_begin` but really - want the name. In addition I added `nk_list_view` which allows - to draw big lists inside a group without actually having to - commit the whole list to nuklear (issue #269). -- 2016/10/30 (1.171)- Fixed clipping rectangle bug inside `nk_draw_list` -- 2016/10/29 (1.170)- Pulled `nk_panel` memory management into nuklear and out of - the hands of the user. From now on users don't have to care - about panels unless they care about some information. If you - still need the panel just call `nk_window_get_panel`. -- 2016/10/21 (1.160)- Changed widget border drawing to stroked rectangle from filled - rectangle for less overdraw and widget background transparency. -- 2016/10/18 (1.160)- Added `nk_edit_focus` for manually edit widget focus control -- 2016/09/29 (1.157)- Fixed deduction of basic type in non `` compilation -- 2016/09/29 (1.156)- Fixed edit widget UTF-8 text cursor drawing bug -- 2016/09/28 (1.156)- Fixed edit widget UTF-8 text appending/inserting/removing -- 2016/09/28 (1.156)- Fixed drawing bug inside edit widgets which offset all text - text in every edit widget if one of them is scrolled. -- 2016/09/28 (1.155)- Fixed small bug in edit widgets if not active. The wrong - text length is passed. It should have been in bytes but - was passed as glyphes. -- 2016/09/20 (1.154)- Fixed color button size calculation -- 2016/09/20 (1.153)- Fixed some `nk_vsnprintf` behavior bugs and removed - `` again from `NK_INCLUDE_STANDARD_VARARGS`. -- 2016/09/18 (1.152)- C89 does not support vsnprintf only C99 and newer as well - as C++11 and newer. In addition to use vsnprintf you have - to include . So just defining `NK_INCLUDE_STD_VAR_ARGS` - is not enough. That behavior is now fixed. By default if - both varargs as well as stdio is selected I try to use - vsnprintf if not possible I will revert to vsprintf. If - varargs but not stdio was defined I will use my own function. -- 2016/09/15 (1.151)- Fixed panel `close` behavior for deeper panel levels -- 2016/09/15 (1.151)- Fixed C++ errors and wrong argument to `nk_panel_get_xxxx` -- 2016/09/13 (1.15) - !BREAKING! Fixed nonblocking popup behavior in menu, combo, - and contextual which prevented closing in y-direction if - popup did not reach max height. - In addition the height parameter was changed into vec2 - for width and height to have more control over the popup size. -- 2016/09/13 (1.15) - Cleaned up and extended type selection -- 2016/09/13 (1.141)- Fixed slider behavior hopefully for the last time. This time - all calculation are correct so no more hackery. -- 2016/09/13 (1.141)- Internal change to divide window/panel flags into panel flags and types. - Suprisinly spend years in C and still happened to confuse types - with flags. Probably something to take note. -- 2016/09/08 (1.14)- Added additional helper function to make it easier to just - take the produced buffers from `nk_convert` and unplug the - iteration process from `nk_context`. So now you can - just use the vertex,element and command buffer + two pointer - inside the command buffer retrieved by calls `nk__draw_begin` - and `nk__draw_end` and macro `nk_draw_foreach_bounded`. -- 2016/09/08 (1.14)- Added additional asserts to make sure every `nk_xxx_begin` call - for windows, popups, combobox, menu and contextual is guarded by - `if` condition and does not produce false drawing output. -- 2016/09/08 (1.14)- Changed confusing name for `NK_SYMBOL_RECT_FILLED`, `NK_SYMBOL_RECT` - to hopefully easier to understand `NK_SYMBOL_RECT_FILLED` and - `NK_SYMBOL_RECT_OUTLINE`. -- 2016/09/08 (1.14)- Changed confusing name for `NK_SYMBOL_CIRLCE_FILLED`, `NK_SYMBOL_CIRCLE` - to hopefully easier to understand `NK_SYMBOL_CIRCLE_FILLED` and - `NK_SYMBOL_CIRCLE_OUTLINE`. -- 2016/09/08 (1.14)- Added additional checks to select correct types if `NK_INCLUDE_FIXED_TYPES` - is not defined by supporting the biggest compiler GCC, clang and MSVC. -- 2016/09/07 (1.133)- Fixed `NK_INCLUDE_COMMAND_USERDATA` define to not cause an error -- 2016/09/04 (1.132)- Fixed wrong combobox height calculation -- 2016/09/03 (1.131)- Fixed gaps inside combo boxes in OpenGL -- 2016/09/02 (1.13) - Changed nuklear to not have any default vertex layout and - instead made it user provided. The range of types to convert - to is quite limited at the moment, but I would be more than - happy to accept PRs to add additional. -- 2016/08/30 (1.12) - Removed unused variables -- 2016/08/30 (1.12) - Fixed C++ build errors -- 2016/08/30 (1.12) - Removed mouse dragging from SDL demo since it does not work correctly -- 2016/08/30 (1.12) - Tweaked some default styling variables -- 2016/08/30 (1.12) - Hopefully fixed drawing bug in slider, in general I would - refrain from using slider with a big number of steps. -- 2016/08/30 (1.12) - Fixed close and minimize button which would fire even if the - window was in Read Only Mode. -- 2016/08/30 (1.12) - Fixed popup panel padding handling which was previously just - a hack for combo box and menu. -- 2016/08/30 (1.12) - Removed `NK_WINDOW_DYNAMIC` flag from public API since - it is bugged and causes issues in window selection. -- 2016/08/30 (1.12) - Removed scaler size. The size of the scaler is now - determined by the scrollbar size -- 2016/08/30 (1.12) - Fixed some drawing bugs caused by changes from 1.11 -- 2016/08/30 (1.12) - Fixed overlapping minimized window selection -- 2016/08/30 (1.11) - Removed some internal complexity and overly complex code - handling panel padding and panel border. -- 2016/08/29 (1.10) - Added additional height parameter to `nk_combobox_xxx` -- 2016/08/29 (1.10) - Fixed drawing bug in dynamic popups -- 2016/08/29 (1.10) - Added experimental mouse scrolling to popups, menus and comboboxes -- 2016/08/26 (1.10) - Added window name string prepresentation to account for - hash collisions. Currently limited to NK_WINDOW_MAX_NAME - which in term can be redefined if not big enough. -- 2016/08/26 (1.10) - Added stacks for temporary style/UI changes in code -- 2016/08/25 (1.10) - Changed `nk_input_is_key_pressed` and 'nk_input_is_key_released' - to account for key press and release happening in one frame. -- 2016/08/25 (1.10) - Added additional nk_edit flag to directly jump to the end on activate -- 2016/08/17 (1.096)- Removed invalid check for value zero in nk_propertyx -- 2016/08/16 (1.095)- Fixed ROM mode for deeper levels of popup windows parents. -- 2016/08/15 (1.094)- Editbox are now still active if enter was pressed with flag - `NK_EDIT_SIG_ENTER`. Main reasoning is to be able to keep - typing after commiting. -- 2016/08/15 (1.094)- Removed redundant code -- 2016/08/15 (1.094)- Fixed negative numbers in `nk_strtoi` and remove unused variable -- 2016/08/15 (1.093)- Fixed `NK_WINDOW_BACKGROUND` flag behavior to select a background - window only as selected by hovering and not by clicking. -- 2016/08/14 (1.092)- Fixed a bug in font atlas which caused wrong loading - of glyphes for font with multiple ranges. -- 2016/08/12 (1.091)- Added additional function to check if window is currently - hidden and therefore not visible. -- 2016/08/12 (1.091)- nk_window_is_closed now queries the correct flag `NK_WINDOW_CLOSED` - instead of the old flag `NK_WINDOW_HIDDEN` -- 2016/08/09 (1.09) - Added additional double version to nk_property and changed - the underlying implementation to not cast to float and instead - work directly on the given values. -- 2016/08/09 (1.08) - Added additional define to overwrite library internal - floating pointer number to string conversion for additional - precision. -- 2016/08/09 (1.08) - Added additional define to overwrite library internal - string to floating point number conversion for additional - precision. -- 2016/08/08 (1.072)- Fixed compiling error without define NK_INCLUDE_FIXED_TYPE -- 2016/08/08 (1.071)- Fixed possible floating point error inside `nk_widget` leading - to wrong wiget width calculation which results in widgets falsly - becomming tagged as not inside window and cannot be accessed. -- 2016/08/08 (1.07) - Nuklear now differentiates between hiding a window (NK_WINDOW_HIDDEN) and - closing a window (NK_WINDOW_CLOSED). A window can be hidden/shown - by using `nk_window_show` and closed by either clicking the close - icon in a window or by calling `nk_window_close`. Only closed - windows get removed at the end of the frame while hidden windows - remain. -- 2016/08/08 (1.06) - Added `nk_edit_string_zero_terminated` as a second option to - `nk_edit_string` which takes, edits and outputs a '\0' terminated string. -- 2016/08/08 (1.054)- Fixed scrollbar auto hiding behavior -- 2016/08/08 (1.053)- Fixed wrong panel padding selection in `nk_layout_widget_space` -- 2016/08/07 (1.052)- Fixed old bug in dynamic immediate mode layout API, calculating - wrong item spacing and panel width. -- 2016/08/07 (1.051)- Hopefully finally fixed combobox popup drawing bug -- 2016/08/07 (1.05) - Split varargs away from NK_INCLUDE_STANDARD_IO into own - define NK_INCLUDE_STANDARD_VARARGS to allow more fine - grained controlled over library includes. -- 2016/08/06 (1.045)- Changed memset calls to NK_MEMSET -- 2016/08/04 (1.044)- Fixed fast window scaling behavior -- 2016/08/04 (1.043)- Fixed window scaling, movement bug which appears if you - move/scale a window and another window is behind it. - If you are fast enough then the window behind gets activated - and the operation is blocked. I now require activating - by hovering only if mouse is not pressed. -- 2016/08/04 (1.042)- Fixed changing fonts -- 2016/08/03 (1.041)- Fixed `NK_WINDOW_BACKGROUND` behavior -- 2016/08/03 (1.04) - Added color parameter to `nk_draw_image` -- 2016/08/03 (1.04) - Added additional window padding style attributes for - sub windows (combo, menu, ...) -- 2016/08/03 (1.04) - Added functions to show/hide software cursor -- 2016/08/03 (1.04) - Added `NK_WINDOW_BACKGROUND` flag to force a window - to be always in the background of the screen -- 2016/08/03 (1.032)- Removed invalid assert macro for NK_RGB color picker -- 2016/08/01 (1.031)- Added helper macros into header include guard -- 2016/07/29 (1.03) - Moved the window/table pool into the header part to - simplify memory management by removing the need to - allocate the pool. -- 2016/07/29 (1.03) - Added auto scrollbar hiding window flag which if enabled - will hide the window scrollbar after NK_SCROLLBAR_HIDING_TIMEOUT - seconds without window interaction. To make it work - you have to also set a delta time inside the `nk_context`. -- 2016/07/25 (1.02) - Fixed small panel and panel border drawing bugs -- 2016/07/15 (1.01) - Added software cursor to `nk_style` and `nk_context` -- 2016/07/15 (1.01) - Added const correctness to `nk_buffer_push' data argument -- 2016/07/15 (1.01) - Removed internal font baking API and simplified - font atlas memory management by converting pointer - arrays for fonts and font configurations to lists. -- 2016/07/15 (1.01) - Changed button API to use context dependend button - behavior instead of passing it for every function call. - diff --git a/deps/nuklear/Readme.md b/deps/nuklear/Readme.md deleted file mode 100644 index 665b05bc..00000000 --- a/deps/nuklear/Readme.md +++ /dev/null @@ -1,112 +0,0 @@ -[![Build Status](https://travis-ci.org/vurtun/nuklear.svg)](https://travis-ci.org/vurtun/nuklear) - -# Nuklear -This is a minimal state immediate mode graphical user interface toolkit -written in ANSI C and licensed under public domain. It was designed as a simple -embeddable user interface for application and does not have any dependencies, -a default renderbackend or OS window and input handling but instead provides a very modular -library approach by using simple input state for input and draw -commands describing primitive shapes as output. So instead of providing a -layered library that tries to abstract over a number of platform and -render backends it only focuses on the actual UI. - -## Features -- Immediate mode graphical user interface toolkit -- Single header library -- Written in C89 (ANSI C) -- Small codebase (~15kLOC) -- Focus on portability, efficiency and simplicity -- No dependencies (not even the standard library if not wanted) -- Fully skinnable and customizable -- Low memory footprint with total memory control if needed or wanted -- UTF-8 support -- No global or hidden state -- Customizable library modules (you can compile and use only what you need) -- Optional font baker and vertex buffer output - -## Building -This library is self contained in one single header file and can be used either -in header only mode or in implementation mode. The header only mode is used -by default when included and allows including this header in other headers -and does not contain the actual implementation. - -The implementation mode requires to define the preprocessor macro -`NK_IMPLEMENTATION` in *one* .c/.cpp file before `#include`ing this file, e.g.: -```c -#define NK_IMPLEMENTATION -#include "nuklear.h" -``` -IMPORTANT: Every time you include "nuklear.h" you have to define the same optional flags. -This is very important not doing it either leads to compiler errors or even worse stack corruptions. - -## Gallery -![screenshot](https://cloud.githubusercontent.com/assets/8057201/11761525/ae06f0ca-a0c6-11e5-819d-5610b25f6ef4.gif) -![screen](https://cloud.githubusercontent.com/assets/8057201/13538240/acd96876-e249-11e5-9547-5ac0b19667a0.png) -![screen2](https://cloud.githubusercontent.com/assets/8057201/13538243/b04acd4c-e249-11e5-8fd2-ad7744a5b446.png) -![node](https://cloud.githubusercontent.com/assets/8057201/9976995/e81ac04a-5ef7-11e5-872b-acd54fbeee03.gif) -![skinning](https://cloud.githubusercontent.com/assets/8057201/15991632/76494854-30b8-11e6-9555-a69840d0d50b.png) -![gamepad](https://cloud.githubusercontent.com/assets/8057201/14902576/339926a8-0d9c-11e6-9fee-a8b73af04473.png) - -## Example -```c -/* init gui state */ -struct nk_context ctx; -nk_init_fixed(&ctx, calloc(1, MAX_MEMORY), MAX_MEMORY, &font); - -enum {EASY, HARD}; -int op = EASY; -float value = 0.6f; -int i = 20; - -if (nk_begin(&ctx, "Show", nk_rect(50, 50, 220, 220), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) { - /* fixed widget pixel width */ - nk_layout_row_static(&ctx, 30, 80, 1); - if (nk_button_label(&ctx, "button")) { - /* event handling */ - } - - /* fixed widget window ratio width */ - nk_layout_row_dynamic(&ctx, 30, 2); - if (nk_option_label(&ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(&ctx, "hard", op == HARD)) op = HARD; - - /* custom widget pixel width */ - nk_layout_row_begin(&ctx, NK_STATIC, 30, 2); - { - nk_layout_row_push(&ctx, 50); - nk_label(&ctx, "Volume:", NK_TEXT_LEFT); - nk_layout_row_push(&ctx, 110); - nk_slider_float(&ctx, 0, &value, 1.0f, 0.1f); - } - nk_layout_row_end(&ctx); -} -nk_end(&ctx); -``` -![example](https://cloud.githubusercontent.com/assets/8057201/10187981/584ecd68-675c-11e5-897c-822ef534a876.png) - -## Bindings: -Java: https://github.com/glegris/nuklear4j -Golang: https://github.com/golang-ui/nuklear -Rust: https://github.com/snuk182/nuklear-rust -Chicken: https://github.com/wasamasa/nuklear - -## Credits: -Developed by Micha Mettke and every direct or indirect contributor to the GitHub. - - -Embeds `stb_texedit`, `stb_truetype` and `stb_rectpack` by Sean Barret (public domain) -Embeds `ProggyClean.ttf` font by Tristan Grimmer (MIT license). - - -Big thank you to Omar Cornut (ocornut@github) for his [imgui](https://github.com/ocornut/imgui) library and -giving me the inspiration for this library, Casey Muratori for handmade hero -and his original immediate mode graphical user interface idea and Sean -Barret for his amazing single header [libraries](https://github.com/nothings/stb) which restored my faith -in libraries and brought me to create some of my own. - -## License: -This software is dual-licensed to the public domain and under the following -license: you are granted a perpetual, irrevocable license to copy, modify, -publish and distribute this file as you see fit. - diff --git a/deps/nuklear/demo/calculator.c b/deps/nuklear/demo/calculator.c deleted file mode 100644 index b871301b..00000000 --- a/deps/nuklear/demo/calculator.c +++ /dev/null @@ -1,64 +0,0 @@ -/* nuklear - v1.00 - public domain */ -static void -calculator(struct nk_context *ctx) -{ - if (nk_begin(ctx, "Calculator", nk_rect(10, 10, 180, 250), - NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE)) - { - static int set = 0, prev = 0, op = 0; - static const char numbers[] = "789456123"; - static const char ops[] = "+-*/"; - static double a = 0, b = 0; - static double *current = &a; - - size_t i = 0; - int solve = 0; - {int len; char buffer[256]; - nk_layout_row_dynamic(ctx, 35, 1); - len = snprintf(buffer, 256, "%.2f", *current); - nk_edit_string(ctx, NK_EDIT_SIMPLE, buffer, &len, 255, nk_filter_float); - buffer[len] = 0; - *current = atof(buffer);} - - nk_layout_row_dynamic(ctx, 35, 4); - for (i = 0; i < 16; ++i) { - if (i >= 12 && i < 15) { - if (i > 12) continue; - if (nk_button_label(ctx, "C")) { - a = b = op = 0; current = &a; set = 0; - } if (nk_button_label(ctx, "0")) { - *current = *current*10.0f; set = 0; - } if (nk_button_label(ctx, "=")) { - solve = 1; prev = op; op = 0; - } - } else if (((i+1) % 4)) { - if (nk_button_text(ctx, &numbers[(i/4)*3+i%4], 1)) { - *current = *current * 10.0f + numbers[(i/4)*3+i%4] - '0'; - set = 0; - } - } else if (nk_button_text(ctx, &ops[i/4], 1)) { - if (!set) { - if (current != &b) { - current = &b; - } else { - prev = op; - solve = 1; - } - } - op = ops[i/4]; - set = 1; - } - } - if (solve) { - if (prev == '+') a = a + b; - if (prev == '-') a = a - b; - if (prev == '*') a = a * b; - if (prev == '/') a = a / b; - current = &a; - if (set) current = &b; - b = 0; set = 0; - } - } - nk_end(ctx); -} - diff --git a/deps/nuklear/demo/d3d11/build.bat b/deps/nuklear/demo/d3d11/build.bat deleted file mode 100644 index 31bd0e05..00000000 --- a/deps/nuklear/demo/d3d11/build.bat +++ /dev/null @@ -1,9 +0,0 @@ -@echo off - -rem This will use VS2015 for compiler -call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86 - -fxc.exe /nologo /T vs_4_0_level_9_0 /E vs /O3 /Zpc /Ges /Fh nuklear_d3d11_vertex_shader.h /Vn nk_d3d11_vertex_shader /Qstrip_reflect /Qstrip_debug /Qstrip_priv nuklear_d3d11.hlsl -fxc.exe /nologo /T ps_4_0_level_9_0 /E ps /O3 /Zpc /Ges /Fh nuklear_d3d11_pixel_shader.h /Vn nk_d3d11_pixel_shader /Qstrip_reflect /Qstrip_debug /Qstrip_priv nuklear_d3d11.hlsl - -cl /D_CRT_SECURE_NO_DEPRECATE /nologo /W3 /O2 /fp:fast /Gm- /Fedemo.exe main.c user32.lib dxguid.lib d3d11.lib /link /incremental:no diff --git a/deps/nuklear/demo/d3d11/main.c b/deps/nuklear/demo/d3d11/main.c deleted file mode 100644 index 92ece1bb..00000000 --- a/deps/nuklear/demo/d3d11/main.c +++ /dev/null @@ -1,278 +0,0 @@ -/* nuklear - v1.17 - public domain */ -#define COBJMACROS -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include -#include - -#define WINDOW_WIDTH 800 -#define WINDOW_HEIGHT 600 - -#define MAX_VERTEX_BUFFER 512 * 1024 -#define MAX_INDEX_BUFFER 128 * 1024 - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#define NK_D3D11_IMPLEMENTATION -#include "../../nuklear.h" -#include "nuklear_d3d11.h" - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* This are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the include - * and the corresponding function. */ - #define UNUSED(a) (void)a - #define MIN(a,b) ((a) < (b) ? (a) : (b)) - #define MAX(a,b) ((a) < (b) ? (b) : (a)) - #define LEN(a) (sizeof(a)/sizeof(a)[0]) - -/*#include "../style.c"*/ -/*#include "../calculator.c"*/ -/*#include "../overview.c"*/ -/*#include "../node_editor.c"*/ - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -static IDXGISwapChain *swap_chain; -static ID3D11Device *device; -static ID3D11DeviceContext *context; -static ID3D11RenderTargetView* rt_view; - -static void -set_swap_chain_size(int width, int height) -{ - ID3D11Texture2D *back_buffer; - D3D11_RENDER_TARGET_VIEW_DESC desc; - HRESULT hr; - - if (rt_view) - ID3D11RenderTargetView_Release(rt_view); - - ID3D11DeviceContext_OMSetRenderTargets(context, 0, NULL, NULL); - - hr = IDXGISwapChain_ResizeBuffers(swap_chain, 0, width, height, DXGI_FORMAT_UNKNOWN, 0); - if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET || hr == DXGI_ERROR_DRIVER_INTERNAL_ERROR) - { - /* to recover from this, you'll need to recreate device and all the resources */ - MessageBoxW(NULL, L"DXGI device is removed or reset!", L"Error", 0); - exit(0); - } - assert(SUCCEEDED(hr)); - - memset(&desc, 0, sizeof(desc)); - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; - - hr = IDXGISwapChain_GetBuffer(swap_chain, 0, &IID_ID3D11Texture2D, &back_buffer); - assert(SUCCEEDED(hr)); - - hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)back_buffer, &desc, &rt_view); - assert(SUCCEEDED(hr)); - - ID3D11Texture2D_Release(back_buffer); -} - -static LRESULT CALLBACK -WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - switch (msg) - { - case WM_DESTROY: - PostQuitMessage(0); - return 0; - - case WM_SIZE: - if (swap_chain) - { - int width = LOWORD(lparam); - int height = HIWORD(lparam); - set_swap_chain_size(width, height); - nk_d3d11_resize(context, width, height); - } - break; - } - - if (nk_d3d11_handle_event(wnd, msg, wparam, lparam)) - return 0; - - return DefWindowProcW(wnd, msg, wparam, lparam); -} - -int main(void) -{ - struct nk_context *ctx; - struct nk_color background; - - WNDCLASSW wc; - RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT }; - DWORD style = WS_OVERLAPPEDWINDOW; - DWORD exstyle = WS_EX_APPWINDOW; - HWND wnd; - int running = 1; - HRESULT hr; - D3D_FEATURE_LEVEL feature_level; - DXGI_SWAP_CHAIN_DESC swap_chain_desc; - - /* Win32 */ - memset(&wc, 0, sizeof(wc)); - wc.lpfnWndProc = WindowProc; - wc.hInstance = GetModuleHandleW(0); - wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.lpszClassName = L"NuklearWindowClass"; - RegisterClassW(&wc); - - AdjustWindowRectEx(&rect, style, FALSE, exstyle); - - wnd = CreateWindowExW(exstyle, wc.lpszClassName, L"Nuklear Demo", - style | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, - rect.right - rect.left, rect.bottom - rect.top, - NULL, NULL, wc.hInstance, NULL); - - /* D3D11 setup */ - memset(&swap_chain_desc, 0, sizeof(swap_chain_desc)); - swap_chain_desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - swap_chain_desc.BufferDesc.RefreshRate.Numerator = 60; - swap_chain_desc.BufferDesc.RefreshRate.Denominator = 1; - swap_chain_desc.SampleDesc.Count = 1; - swap_chain_desc.SampleDesc.Quality = 0; - swap_chain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; - swap_chain_desc.BufferCount = 1; - swap_chain_desc.OutputWindow = wnd; - swap_chain_desc.Windowed = TRUE; - swap_chain_desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; - swap_chain_desc.Flags = 0; - if (FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, - NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swap_chain_desc, - &swap_chain, &device, &feature_level, &context))) - { - /* if hardware device fails, then try WARP high-performance - software rasterizer, this is useful for RDP sessions */ - hr = D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_WARP, - NULL, 0, NULL, 0, D3D11_SDK_VERSION, &swap_chain_desc, - &swap_chain, &device, &feature_level, &context); - assert(SUCCEEDED(hr)); - } - set_swap_chain_size(WINDOW_WIDTH, WINDOW_HEIGHT); - - /* GUI */ - ctx = nk_d3d11_init(device, WINDOW_WIDTH, WINDOW_HEIGHT, MAX_VERTEX_BUFFER, MAX_INDEX_BUFFER); - /* Load Fonts: if none of these are loaded a default font will be used */ - /* Load Cursor: if you uncomment cursor loading please hide the cursor */ - {struct nk_font_atlas *atlas; - nk_d3d11_font_stash_begin(&atlas); - /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../extra_font/DroidSans.ttf", 14, 0);*/ - /*struct nk_font *robot = nk_font_atlas_add_from_file(atlas, "../../extra_font/Roboto-Regular.ttf", 14, 0);*/ - /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../extra_font/kenvector_future_thin.ttf", 13, 0);*/ - /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../extra_font/ProggyClean.ttf", 12, 0);*/ - /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../extra_font/ProggyTiny.ttf", 10, 0);*/ - /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../extra_font/Cousine-Regular.ttf", 13, 0);*/ - nk_d3d11_font_stash_end(); - /*nk_style_load_all_cursors(ctx, atlas->cursors);*/ - /*nk_style_set_font(ctx, &droid->handle)*/;} - - /* style.c */ - /*set_style(ctx, THEME_WHITE);*/ - /*set_style(ctx, THEME_RED);*/ - /*set_style(ctx, THEME_BLUE);*/ - /*set_style(ctx, THEME_DARK);*/ - - background = nk_rgb(28,48,62); - while (running) - { - /* Input */ - MSG msg; - nk_input_begin(ctx); - while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) - { - if (msg.message == WM_QUIT) - running = 0; - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - nk_input_end(ctx); - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - nk_layout_row_dynamic(ctx, 22, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - - nk_layout_row_dynamic(ctx, 20, 1); - nk_label(ctx, "background:", NK_TEXT_LEFT); - nk_layout_row_dynamic(ctx, 25, 1); - if (nk_combo_begin_color(ctx, background, nk_vec2(nk_widget_width(ctx),400))) { - nk_layout_row_dynamic(ctx, 120, 1); - background = nk_color_picker(ctx, background, NK_RGBA); - nk_layout_row_dynamic(ctx, 25, 1); - background.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, background.r, 255, 1,1); - background.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, background.g, 255, 1,1); - background.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, background.b, 255, 1,1); - background.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, background.a, 255, 1,1); - nk_combo_end(ctx); - } - } - nk_end(ctx); - if (nk_window_is_closed(ctx, "Demo")) break; - - /* -------------- EXAMPLES ---------------- */ - /*calculator(ctx);*/ - /*overview(ctx);*/ - /*node_editor(ctx);*/ - /* ----------------------------------------- */ - - {/* Draw */ - float bg[4]; - nk_color_fv(bg, background); - ID3D11DeviceContext_ClearRenderTargetView(context, rt_view, bg); - ID3D11DeviceContext_OMSetRenderTargets(context, 1, &rt_view, NULL); - nk_d3d11_render(context, NK_ANTI_ALIASING_ON); - hr = IDXGISwapChain_Present(swap_chain, 1, 0); - if (hr == DXGI_ERROR_DEVICE_RESET || hr == DXGI_ERROR_DEVICE_REMOVED) { - /* to recover from this, you'll need to recreate device and all the resources */ - MessageBoxW(NULL, L"D3D11 device is lost or removed!", L"Error", 0); - break; - } else if (hr == DXGI_STATUS_OCCLUDED) { - /* window is not visible, so vsync won't work. Let's sleep a bit to reduce CPU usage */ - Sleep(10); - } - assert(SUCCEEDED(hr));} - } - - ID3D11DeviceContext_ClearState(context); - nk_d3d11_shutdown(); - ID3D11ShaderResourceView_Release(rt_view); - ID3D11DeviceContext_Release(context); - ID3D11Device_Release(device); - IDXGISwapChain_Release(swap_chain); - UnregisterClassW(wc.lpszClassName, wc.hInstance); - return 0; -} diff --git a/deps/nuklear/demo/d3d11/nuklear_d3d11.h b/deps/nuklear/demo/d3d11/nuklear_d3d11.h deleted file mode 100644 index efddf0d2..00000000 --- a/deps/nuklear/demo/d3d11/nuklear_d3d11.h +++ /dev/null @@ -1,617 +0,0 @@ -/* - * Nuklear - v1.17 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_D3D11_H_ -#define NK_D3D11_H_ - -#define WIN32_LEAN_AND_MEAN -#include - -typedef struct ID3D11Device ID3D11Device; -typedef struct ID3D11DeviceContext ID3D11DeviceContext; - -NK_API struct nk_context *nk_d3d11_init(ID3D11Device *device, int width, int height, unsigned int max_vertex_buffer, unsigned int max_index_buffer); -NK_API void nk_d3d11_font_stash_begin(struct nk_font_atlas **atlas); -NK_API void nk_d3d11_font_stash_end(void); -NK_API int nk_d3d11_handle_event(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); -NK_API void nk_d3d11_render(ID3D11DeviceContext *context, enum nk_anti_aliasing); -NK_API void nk_d3d11_resize(ID3D11DeviceContext *context, int width, int height); -NK_API void nk_d3d11_shutdown(void); - -#endif -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_D3D11_IMPLEMENTATION - -#define WIN32_LEAN_AND_MEAN -#define COBJMACROS -#include - -#include -#include -#include -#include - -#include "nuklear_d3d11_vertex_shader.h" -#include "nuklear_d3d11_pixel_shader.h" - -struct nk_d3d11_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -static struct -{ - struct nk_context ctx; - struct nk_font_atlas atlas; - struct nk_buffer cmds; - - struct nk_draw_null_texture null; - unsigned int max_vertex_buffer; - unsigned int max_index_buffer; - - D3D11_VIEWPORT viewport; - ID3D11Device *device; - ID3D11RasterizerState *rasterizer_state; - ID3D11VertexShader *vertex_shader; - ID3D11InputLayout *input_layout; - ID3D11Buffer *const_buffer; - ID3D11PixelShader *pixel_shader; - ID3D11BlendState *blend_state; - ID3D11Buffer *index_buffer; - ID3D11Buffer *vertex_buffer; - ID3D11ShaderResourceView *font_texture_view; - ID3D11SamplerState *sampler_state; -} d3d11; - -NK_API void -nk_d3d11_render(ID3D11DeviceContext *context, enum nk_anti_aliasing AA) -{ - const float blend_factor[4] = { 0.0f, 0.0f, 0.0f, 0.0f }; - const UINT stride = sizeof(struct nk_d3d11_vertex); - const UINT offset = 0; - - ID3D11DeviceContext_IASetInputLayout(context, d3d11.input_layout); - ID3D11DeviceContext_IASetVertexBuffers(context, 0, 1, &d3d11.vertex_buffer, &stride, &offset); - ID3D11DeviceContext_IASetIndexBuffer(context, d3d11.index_buffer, DXGI_FORMAT_R16_UINT, 0); - ID3D11DeviceContext_IASetPrimitiveTopology(context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); - - ID3D11DeviceContext_VSSetShader(context, d3d11.vertex_shader, NULL, 0); - ID3D11DeviceContext_VSSetConstantBuffers(context, 0, 1, &d3d11.const_buffer); - - ID3D11DeviceContext_PSSetShader(context, d3d11.pixel_shader, NULL, 0); - ID3D11DeviceContext_PSSetSamplers(context, 0, 1, &d3d11.sampler_state); - - ID3D11DeviceContext_OMSetBlendState(context, d3d11.blend_state, blend_factor, 0xffffffff); - ID3D11DeviceContext_RSSetState(context, d3d11.rasterizer_state); - ID3D11DeviceContext_RSSetViewports(context, 1, &d3d11.viewport); - - /* Convert from command queue into draw list and draw to screen */ - {/* load draw vertices & elements directly into vertex + element buffer */ - D3D11_MAPPED_SUBRESOURCE vertices; - D3D11_MAPPED_SUBRESOURCE indices; - const struct nk_draw_command *cmd; - UINT offset = 0; - HRESULT hr; - - hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)d3d11.vertex_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &vertices); - NK_ASSERT(SUCCEEDED(hr)); - hr = ID3D11DeviceContext_Map(context, (ID3D11Resource *)d3d11.index_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &indices); - NK_ASSERT(SUCCEEDED(hr)); - - {/* fill converting configuration */ - struct nk_convert_config config; - NK_STORAGE const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_d3d11_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_d3d11_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_d3d11_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - memset(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_d3d11_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_d3d11_vertex); - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.null = d3d11.null; - - {/* setup buffers to load vertices and elements */ - struct nk_buffer vbuf, ibuf; - nk_buffer_init_fixed(&vbuf, vertices.pData, (size_t)d3d11.max_vertex_buffer); - nk_buffer_init_fixed(&ibuf, indices.pData, (size_t)d3d11.max_index_buffer); - nk_convert(&d3d11.ctx, &d3d11.cmds, &vbuf, &ibuf, &config);} - } - - ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)d3d11.vertex_buffer, 0); - ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)d3d11.index_buffer, 0); - - /* iterate over and execute each draw command */ - nk_draw_foreach(cmd, &d3d11.ctx, &d3d11.cmds) - { - D3D11_RECT scissor; - ID3D11ShaderResourceView *texture_view = (ID3D11ShaderResourceView *)cmd->texture.ptr; - if (!cmd->elem_count) continue; - - scissor.left = (LONG)cmd->clip_rect.x; - scissor.right = (LONG)(cmd->clip_rect.x + cmd->clip_rect.w); - scissor.top = (LONG)cmd->clip_rect.y; - scissor.bottom = (LONG)(cmd->clip_rect.y + cmd->clip_rect.h); - - ID3D11DeviceContext_PSSetShaderResources(context, 0, 1, &texture_view); - ID3D11DeviceContext_RSSetScissorRects(context, 1, &scissor); - ID3D11DeviceContext_DrawIndexed(context, (UINT)cmd->elem_count, offset, 0); - offset += cmd->elem_count; - } - nk_clear(&d3d11.ctx);} -} - -static void -nk_d3d11_get_projection_matrix(int width, int height, float *result) -{ - const float L = 0.0f; - const float R = (float)width; - const float T = 0.0f; - const float B = (float)height; - float matrix[4][4] = - { - { 2.0f / (R - L), 0.0f, 0.0f, 0.0f }, - { 0.0f, 2.0f / (T - B), 0.0f, 0.0f }, - { 0.0f, 0.0f, 0.5f, 0.0f }, - { (R + L) / (L - R), (T + B) / (B - T), 0.5f, 1.0f }, - }; - memcpy(result, matrix, sizeof(matrix)); -} - -NK_API void -nk_d3d11_resize(ID3D11DeviceContext *context, int width, int height) -{ - D3D11_MAPPED_SUBRESOURCE mapped; - if (SUCCEEDED(ID3D11DeviceContext_Map(context, (ID3D11Resource *)d3d11.const_buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped))) - { - nk_d3d11_get_projection_matrix(width, height, (float *)mapped.pData); - ID3D11DeviceContext_Unmap(context, (ID3D11Resource *)d3d11.const_buffer, 0); - - d3d11.viewport.Width = (float)width; - d3d11.viewport.Height = (float)height; - } -} - -NK_API int -nk_d3d11_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - switch (msg) - { - case WM_KEYDOWN: - case WM_KEYUP: - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - { - int down = !((lparam >> 31) & 1); - int ctrl = GetKeyState(VK_CONTROL) & (1 << 15); - - switch (wparam) - { - case VK_SHIFT: - case VK_LSHIFT: - case VK_RSHIFT: - nk_input_key(&d3d11.ctx, NK_KEY_SHIFT, down); - return 1; - - case VK_DELETE: - nk_input_key(&d3d11.ctx, NK_KEY_DEL, down); - return 1; - - case VK_RETURN: - nk_input_key(&d3d11.ctx, NK_KEY_ENTER, down); - return 1; - - case VK_TAB: - nk_input_key(&d3d11.ctx, NK_KEY_TAB, down); - return 1; - - case VK_LEFT: - if (ctrl) - nk_input_key(&d3d11.ctx, NK_KEY_TEXT_WORD_LEFT, down); - else - nk_input_key(&d3d11.ctx, NK_KEY_LEFT, down); - return 1; - - case VK_RIGHT: - if (ctrl) - nk_input_key(&d3d11.ctx, NK_KEY_TEXT_WORD_RIGHT, down); - else - nk_input_key(&d3d11.ctx, NK_KEY_RIGHT, down); - return 1; - - case VK_BACK: - nk_input_key(&d3d11.ctx, NK_KEY_BACKSPACE, down); - return 1; - - case VK_HOME: - nk_input_key(&d3d11.ctx, NK_KEY_TEXT_START, down); - nk_input_key(&d3d11.ctx, NK_KEY_SCROLL_START, down); - return 1; - - case VK_END: - nk_input_key(&d3d11.ctx, NK_KEY_TEXT_END, down); - nk_input_key(&d3d11.ctx, NK_KEY_SCROLL_END, down); - return 1; - - case VK_NEXT: - nk_input_key(&d3d11.ctx, NK_KEY_SCROLL_DOWN, down); - return 1; - - case VK_PRIOR: - nk_input_key(&d3d11.ctx, NK_KEY_SCROLL_UP, down); - return 1; - - case 'C': - if (ctrl) { - nk_input_key(&d3d11.ctx, NK_KEY_COPY, down); - return 1; - } - break; - - case 'V': - if (ctrl) { - nk_input_key(&d3d11.ctx, NK_KEY_PASTE, down); - return 1; - } - break; - - case 'X': - if (ctrl) { - nk_input_key(&d3d11.ctx, NK_KEY_CUT, down); - return 1; - } - break; - - case 'Z': - if (ctrl) { - nk_input_key(&d3d11.ctx, NK_KEY_TEXT_UNDO, down); - return 1; - } - break; - - case 'R': - if (ctrl) { - nk_input_key(&d3d11.ctx, NK_KEY_TEXT_REDO, down); - return 1; - } - break; - } - return 0; - } - - case WM_CHAR: - if (wparam >= 32) - { - nk_input_unicode(&d3d11.ctx, (nk_rune)wparam); - return 1; - } - break; - - case WM_LBUTTONDOWN: - nk_input_button(&d3d11.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1); - SetCapture(wnd); - return 1; - - case WM_LBUTTONUP: - nk_input_button(&d3d11.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0); - ReleaseCapture(); - return 1; - - case WM_RBUTTONDOWN: - nk_input_button(&d3d11.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1); - SetCapture(wnd); - return 1; - - case WM_RBUTTONUP: - nk_input_button(&d3d11.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0); - ReleaseCapture(); - return 1; - - case WM_MBUTTONDOWN: - nk_input_button(&d3d11.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1); - SetCapture(wnd); - return 1; - - case WM_MBUTTONUP: - nk_input_button(&d3d11.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0); - ReleaseCapture(); - return 1; - - case WM_MOUSEWHEEL: - nk_input_scroll(&d3d11.ctx, (float)(short)HIWORD(wparam) / WHEEL_DELTA); - return 1; - - case WM_MOUSEMOVE: - nk_input_motion(&d3d11.ctx, (short)LOWORD(lparam), (short)HIWORD(lparam)); - return 1; - } - - return 0; -} - -static void -nk_d3d11_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) -{ - (void)usr; - if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL)) - { - HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); - if (mem) - { - SIZE_T size = GlobalSize(mem) - 1; - if (size) - { - LPCWSTR wstr = (LPCWSTR)GlobalLock(mem); - if (wstr) - { - int utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, size / sizeof(wchar_t), NULL, 0, NULL, NULL); - if (utf8size) - { - char* utf8 = (char*)malloc(utf8size); - if (utf8) - { - WideCharToMultiByte(CP_UTF8, 0, wstr, size / sizeof(wchar_t), utf8, utf8size, NULL, NULL); - nk_textedit_paste(edit, utf8, utf8size); - free(utf8); - } - } - GlobalUnlock(mem); - } - } - } - CloseClipboard(); - } -} - -static void -nk_d3d11_clipbard_copy(nk_handle usr, const char *text, int len) -{ - (void)usr; - if (OpenClipboard(NULL)) - { - int wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0); - if (wsize) - { - HGLOBAL mem = GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t)); - if (mem) - { - wchar_t* wstr = (wchar_t*)GlobalLock(mem); - if (wstr) - { - MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize); - wstr[wsize] = 0; - GlobalUnlock(mem); - SetClipboardData(CF_UNICODETEXT, mem); - } - } - } - CloseClipboard(); - } -} - -NK_API struct nk_context* -nk_d3d11_init(ID3D11Device *device, int width, int height, unsigned int max_vertex_buffer, unsigned int max_index_buffer) -{ - HRESULT hr; - d3d11.max_vertex_buffer = max_vertex_buffer; - d3d11.max_index_buffer = max_index_buffer; - d3d11.device = device; - ID3D11Device_AddRef(device); - - nk_init_default(&d3d11.ctx, 0); - d3d11.ctx.clip.copy = nk_d3d11_clipbard_copy; - d3d11.ctx.clip.paste = nk_d3d11_clipbard_paste; - d3d11.ctx.clip.userdata = nk_handle_ptr(0); - - nk_buffer_init_default(&d3d11.cmds); - - {/* rasterizer state */ - D3D11_RASTERIZER_DESC desc; - memset(&desc, 0, sizeof(desc)); - desc.FillMode = D3D11_FILL_SOLID; - desc.CullMode = D3D11_CULL_NONE; - desc.FrontCounterClockwise = FALSE; - desc.DepthBias = 0; - desc.DepthBiasClamp = 0; - desc.SlopeScaledDepthBias = 0.0f; - desc.DepthClipEnable = TRUE; - desc.ScissorEnable = TRUE; - desc.MultisampleEnable = FALSE; - desc.AntialiasedLineEnable = FALSE; - hr = ID3D11Device_CreateRasterizerState(device,&desc, &d3d11.rasterizer_state); - NK_ASSERT(SUCCEEDED(hr));} - - /* vertex shader */ - {hr = ID3D11Device_CreateVertexShader(device,nk_d3d11_vertex_shader, sizeof(nk_d3d11_vertex_shader), NULL, &d3d11.vertex_shader); - NK_ASSERT(SUCCEEDED(hr));} - - /* input layout */ - {const D3D11_INPUT_ELEMENT_DESC layout[] = { - { "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, offsetof(struct nk_d3d11_vertex, position), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, offsetof(struct nk_d3d11_vertex, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, offsetof(struct nk_d3d11_vertex, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, - }; - hr = ID3D11Device_CreateInputLayout(device,layout, ARRAYSIZE(layout), nk_d3d11_vertex_shader, sizeof(nk_d3d11_vertex_shader), &d3d11.input_layout); - NK_ASSERT(SUCCEEDED(hr));} - - /* constant buffer */ - {float matrix[4*4]; - D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(desc)); - desc.ByteWidth = sizeof(matrix); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - - {D3D11_SUBRESOURCE_DATA data; - data.pSysMem = matrix; - data.SysMemPitch = 0; - data.SysMemSlicePitch = 0; - - nk_d3d11_get_projection_matrix(width, height, matrix); - hr = ID3D11Device_CreateBuffer(device, &desc, &data, &d3d11.const_buffer); - NK_ASSERT(SUCCEEDED(hr));}} - - /* pixel shader */ - {hr = ID3D11Device_CreatePixelShader(device, nk_d3d11_pixel_shader, sizeof(nk_d3d11_pixel_shader), NULL, &d3d11.pixel_shader); - NK_ASSERT(SUCCEEDED(hr));} - - {/* blend state */ - D3D11_BLEND_DESC desc; - memset(&desc, 0, sizeof(desc)); - desc.AlphaToCoverageEnable = FALSE; - desc.RenderTarget[0].BlendEnable = TRUE; - desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; - desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; - desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; - desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; - desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_ZERO; - desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; - desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; - hr = ID3D11Device_CreateBlendState(device, &desc, &d3d11.blend_state); - NK_ASSERT(SUCCEEDED(hr));} - - /* vertex buffer */ - {D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(desc)); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.ByteWidth = max_vertex_buffer; - desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - desc.MiscFlags = 0; - hr = ID3D11Device_CreateBuffer(device, &desc, NULL, &d3d11.vertex_buffer); - NK_ASSERT(SUCCEEDED(hr));} - - /* index buffer */ - {D3D11_BUFFER_DESC desc; - memset(&desc, 0, sizeof(desc)); - desc.Usage = D3D11_USAGE_DYNAMIC; - desc.ByteWidth = max_index_buffer; - desc.BindFlags = D3D11_BIND_INDEX_BUFFER; - desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; - hr = ID3D11Device_CreateBuffer(device, &desc, NULL, &d3d11.index_buffer); - NK_ASSERT(SUCCEEDED(hr));} - - /* sampler state */ - {D3D11_SAMPLER_DESC desc; - memset(&desc, 0, sizeof(desc)); - desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; - desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; - desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; - desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; - desc.MipLODBias = 0.0f; - desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; - desc.MinLOD = 0.0f; - desc.MaxLOD = FLT_MAX; - hr = ID3D11Device_CreateSamplerState(device, &desc, &d3d11.sampler_state); - NK_ASSERT(SUCCEEDED(hr));} - - /* viewport */ - {d3d11.viewport.TopLeftX = 0.0f; - d3d11.viewport.TopLeftY = 0.0f; - d3d11.viewport.Width = (float)width; - d3d11.viewport.Height = (float)height; - d3d11.viewport.MinDepth = 0.0f; - d3d11.viewport.MaxDepth = 1.0f;} - return &d3d11.ctx; -} - -NK_API void -nk_d3d11_font_stash_begin(struct nk_font_atlas **atlas) -{ - nk_font_atlas_init_default(&d3d11.atlas); - nk_font_atlas_begin(&d3d11.atlas); - *atlas = &d3d11.atlas; -} - -NK_API void -nk_d3d11_font_stash_end(void) -{ - const void *image; int w, h; - image = nk_font_atlas_bake(&d3d11.atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - - /* upload font to texture and create texture view */ - {ID3D11Texture2D *font_texture; - HRESULT hr; - - D3D11_TEXTURE2D_DESC desc; - memset(&desc, 0, sizeof(desc)); - desc.Width = (UINT)w; - desc.Height = (UINT)h; - desc.MipLevels = 1; - desc.ArraySize = 1; - desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; - desc.SampleDesc.Count = 1; - desc.SampleDesc.Quality = 0; - desc.Usage = D3D11_USAGE_DEFAULT; - desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; - desc.CPUAccessFlags = 0; - - {D3D11_SUBRESOURCE_DATA data; - data.pSysMem = image; - data.SysMemPitch = (UINT)(w * 4); - data.SysMemSlicePitch = 0; - hr = ID3D11Device_CreateTexture2D(d3d11.device, &desc, &data, &font_texture); - assert(SUCCEEDED(hr));} - - {D3D11_SHADER_RESOURCE_VIEW_DESC srv; - memset(&srv, 0, sizeof(srv)); - srv.Format = desc.Format; - srv.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; - srv.Texture2D.MipLevels = 1; - srv.Texture2D.MostDetailedMip = 0; - hr = ID3D11Device_CreateShaderResourceView(d3d11.device, (ID3D11Resource *)font_texture, &srv, &d3d11.font_texture_view); - assert(SUCCEEDED(hr));} - ID3D11Texture2D_Release(font_texture);} - - nk_font_atlas_end(&d3d11.atlas, nk_handle_ptr(d3d11.font_texture_view), &d3d11.null); - if (d3d11.atlas.default_font) - nk_style_set_font(&d3d11.ctx, &d3d11.atlas.default_font->handle); -} - -NK_API -void nk_d3d11_shutdown(void) -{ - nk_font_atlas_clear(&d3d11.atlas); - nk_buffer_free(&d3d11.cmds); - nk_free(&d3d11.ctx); - - ID3D11SamplerState_Release(d3d11.sampler_state); - ID3D11ShaderResourceView_Release(d3d11.font_texture_view); - ID3D11Buffer_Release(d3d11.vertex_buffer); - ID3D11Buffer_Release(d3d11.index_buffer); - ID3D11BlendState_Release(d3d11.blend_state); - ID3D11PixelShader_Release(d3d11.pixel_shader); - ID3D11Buffer_Release(d3d11.const_buffer); - ID3D11VertexShader_Release(d3d11.vertex_shader); - ID3D11InputLayout_Release(d3d11.input_layout); - ID3D11RasterizerState_Release(d3d11.rasterizer_state); - ID3D11Device_Release(d3d11.device); -} - -#endif - diff --git a/deps/nuklear/demo/d3d11/nuklear_d3d11.hlsl b/deps/nuklear/demo/d3d11/nuklear_d3d11.hlsl deleted file mode 100644 index a932dcab..00000000 --- a/deps/nuklear/demo/d3d11/nuklear_d3d11.hlsl +++ /dev/null @@ -1,36 +0,0 @@ -// -cbuffer buffer0 : register(b0) -{ - float4x4 ProjectionMatrix; -}; - -sampler sampler0 : register(s0); -Texture2D texture0 : register(t0); - -struct VS_INPUT -{ - float2 pos : POSITION; - float4 col : COLOR0; - float2 uv : TEXCOORD0; -}; - -struct PS_INPUT -{ - float4 pos : SV_POSITION; - float4 col : COLOR0; - float2 uv : TEXCOORD0; -}; - -PS_INPUT vs(VS_INPUT input) -{ - PS_INPUT output; - output.pos = mul(ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f)); - output.col = input.col; - output.uv = input.uv; - return output; -} - -float4 ps(PS_INPUT input) : SV_Target -{ - return input.col * texture0.Sample(sampler0, input.uv); -} diff --git a/deps/nuklear/demo/d3d11/nuklear_d3d11_pixel_shader.h b/deps/nuklear/demo/d3d11/nuklear_d3d11_pixel_shader.h deleted file mode 100644 index 1447559e..00000000 --- a/deps/nuklear/demo/d3d11/nuklear_d3d11_pixel_shader.h +++ /dev/null @@ -1,179 +0,0 @@ -#if 0 -// -// Generated by Microsoft (R) D3D Shader Disassembler -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_POSITION 0 xyzw 0 POS float -// COLOR 0 xyzw 1 NONE float xyzw -// TEXCOORD 0 xy 2 NONE float xy -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_Target 0 xyzw 0 TARGET float xyzw -// -// -// Sampler/Resource to DX9 shader sampler mappings: -// -// Target Sampler Source Sampler Source Resource -// -------------- --------------- ---------------- -// s0 s0 t0 -// -// -// Level9 shader bytecode: -// - ps_2_0 - dcl t0 - dcl t1.xy - dcl_2d s0 - texld r0, t1, s0 - mul r0, r0, t0 - mov oC0, r0 - -// approximately 3 instruction slots used (1 texture, 2 arithmetic) -// -// Sampler/Resource to DX9 shader sampler mappings: -// -// Target Sampler Source Sampler Source Resource -// -------------- --------------- ---------------- -// s0 s0 t0 -// -// -// XNA shader bytecode: -// - ps_2_0 - dcl t0 - dcl t1.xy - dcl_2d s0 - texld r0, r2, s0 - mul oC0, r0, r1 - -// approximately 2 instruction slots used (1 texture, 1 arithmetic) -ps_4_0 -dcl_sampler s0, mode_default -dcl_resource_texture2d (float,float,float,float) t0 -dcl_input_ps linear v1.xyzw -dcl_input_ps linear v2.xy -dcl_output o0.xyzw -dcl_temps 1 -sample r0.xyzw, v2.xyxx, t0.xyzw, s0 -mul o0.xyzw, r0.xyzw, v1.xyzw -ret -// Approximately 0 instruction slots used -#endif - -const BYTE nk_d3d11_pixel_shader[] = -{ - 68, 88, 66, 67, 249, 46, - 26, 75, 111, 182, 161, 241, - 199, 179, 191, 89, 44, 229, - 245, 103, 1, 0, 0, 0, - 124, 2, 0, 0, 5, 0, - 0, 0, 52, 0, 0, 0, - 176, 0, 0, 0, 56, 1, - 0, 0, 212, 1, 0, 0, - 72, 2, 0, 0, 88, 78, - 65, 83, 116, 0, 0, 0, - 116, 0, 0, 0, 0, 2, - 255, 255, 76, 0, 0, 0, - 40, 0, 0, 0, 0, 0, - 40, 0, 0, 0, 40, 0, - 0, 0, 40, 0, 1, 0, - 36, 0, 0, 0, 40, 0, - 0, 0, 0, 0, 0, 2, - 255, 255, 31, 0, 0, 2, - 0, 0, 0, 128, 0, 0, - 15, 176, 31, 0, 0, 2, - 0, 0, 0, 128, 1, 0, - 3, 176, 31, 0, 0, 2, - 0, 0, 0, 144, 0, 8, - 15, 160, 66, 0, 0, 3, - 0, 0, 15, 128, 2, 0, - 228, 128, 0, 8, 228, 160, - 5, 0, 0, 3, 0, 8, - 15, 128, 0, 0, 228, 128, - 1, 0, 228, 128, 255, 255, - 0, 0, 65, 111, 110, 57, - 128, 0, 0, 0, 128, 0, - 0, 0, 0, 2, 255, 255, - 88, 0, 0, 0, 40, 0, - 0, 0, 0, 0, 40, 0, - 0, 0, 40, 0, 0, 0, - 40, 0, 1, 0, 36, 0, - 0, 0, 40, 0, 0, 0, - 0, 0, 0, 2, 255, 255, - 31, 0, 0, 2, 0, 0, - 0, 128, 0, 0, 15, 176, - 31, 0, 0, 2, 0, 0, - 0, 128, 1, 0, 3, 176, - 31, 0, 0, 2, 0, 0, - 0, 144, 0, 8, 15, 160, - 66, 0, 0, 3, 0, 0, - 15, 128, 1, 0, 228, 176, - 0, 8, 228, 160, 5, 0, - 0, 3, 0, 0, 15, 128, - 0, 0, 228, 128, 0, 0, - 228, 176, 1, 0, 0, 2, - 0, 8, 15, 128, 0, 0, - 228, 128, 255, 255, 0, 0, - 83, 72, 68, 82, 148, 0, - 0, 0, 64, 0, 0, 0, - 37, 0, 0, 0, 90, 0, - 0, 3, 0, 96, 16, 0, - 0, 0, 0, 0, 88, 24, - 0, 4, 0, 112, 16, 0, - 0, 0, 0, 0, 85, 85, - 0, 0, 98, 16, 0, 3, - 242, 16, 16, 0, 1, 0, - 0, 0, 98, 16, 0, 3, - 50, 16, 16, 0, 2, 0, - 0, 0, 101, 0, 0, 3, - 242, 32, 16, 0, 0, 0, - 0, 0, 104, 0, 0, 2, - 1, 0, 0, 0, 69, 0, - 0, 9, 242, 0, 16, 0, - 0, 0, 0, 0, 70, 16, - 16, 0, 2, 0, 0, 0, - 70, 126, 16, 0, 0, 0, - 0, 0, 0, 96, 16, 0, - 0, 0, 0, 0, 56, 0, - 0, 7, 242, 32, 16, 0, - 0, 0, 0, 0, 70, 14, - 16, 0, 0, 0, 0, 0, - 70, 30, 16, 0, 1, 0, - 0, 0, 62, 0, 0, 1, - 73, 83, 71, 78, 108, 0, - 0, 0, 3, 0, 0, 0, - 8, 0, 0, 0, 80, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 15, 0, 0, 0, 92, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 15, 15, 0, 0, 98, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 2, 0, 0, 0, - 3, 3, 0, 0, 83, 86, - 95, 80, 79, 83, 73, 84, - 73, 79, 78, 0, 67, 79, - 76, 79, 82, 0, 84, 69, - 88, 67, 79, 79, 82, 68, - 0, 171, 79, 83, 71, 78, - 44, 0, 0, 0, 1, 0, - 0, 0, 8, 0, 0, 0, - 32, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 15, 0, 0, 0, - 83, 86, 95, 84, 97, 114, - 103, 101, 116, 0, 171, 171 -}; diff --git a/deps/nuklear/demo/d3d11/nuklear_d3d11_vertex_shader.h b/deps/nuklear/demo/d3d11/nuklear_d3d11_vertex_shader.h deleted file mode 100644 index 770d2dd9..00000000 --- a/deps/nuklear/demo/d3d11/nuklear_d3d11_vertex_shader.h +++ /dev/null @@ -1,350 +0,0 @@ -#if 0 -// -// Generated by Microsoft (R) D3D Shader Disassembler -// -// -// Input signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// POSITION 0 xy 0 NONE float xy -// COLOR 0 xyzw 1 NONE float xyzw -// TEXCOORD 0 xy 2 NONE float xy -// -// -// Output signature: -// -// Name Index Mask Register SysValue Format Used -// -------------------- ----- ------ -------- -------- ------- ------ -// SV_POSITION 0 xyzw 0 POS float xyzw -// COLOR 0 xyzw 1 NONE float xyzw -// TEXCOORD 0 xy 2 NONE float xy -// -// -// Constant buffer to DX9 shader constant mappings: -// -// Target Reg Buffer Start Reg # of Regs Data Conversion -// ---------- ------- --------- --------- ---------------------- -// c1 cb0 0 4 ( FLT, FLT, FLT, FLT) -// -// -// Runtime generated constant mappings: -// -// Target Reg Constant Description -// ---------- -------------------------------------------------- -// c0 Vertex Shader position offset -// -// -// Level9 shader bytecode: -// - vs_2_0 - def c5, 0, 1, 0, 0 - dcl_texcoord v0 - dcl_texcoord1 v1 - dcl_texcoord2 v2 - mul r0, v0.x, c1 - mad r0, c2, v0.y, r0 - mov r1.xy, c5 - mad r0, c3, r1.x, r0 - mad r0, c4, r1.y, r0 - mul r1.xy, r0.w, c0 - add oPos.xy, r0, r1 - mov oPos.zw, r0 - mov oT0, v1 - mov oT1.xy, v2 - -// approximately 10 instruction slots used -// -// Constant buffer to DX9 shader constant mappings: -// -// Target Reg Buffer Start Reg # of Regs Data Conversion -// ---------- ------- --------- --------- ---------------------- -// c0 cb0 0 4 ( FLT, FLT, FLT, FLT) -// -// -// XNA Prepass shader bytecode: -// - vs_2_0 - def c4, 0, 1, 0, 0 - dcl_texcoord v0 - mul r1, r0.x, c0 - mad r0, c1, r0.y, r1 - mov r1.xy, c4 - mad r0, c2, r1.x, r0 - mad r0, c3, r1.y, r0 - mov oPos, r0 - -// approximately 6 instruction slots used -// -// Constant buffer to DX9 shader constant mappings: -// -// Target Reg Buffer Start Reg # of Regs Data Conversion -// ---------- ------- --------- --------- ---------------------- -// c0 cb0 0 4 ( FLT, FLT, FLT, FLT) -// -// -// XNA shader bytecode: -// - vs_2_0 - def c4, 0, 1, 0, 0 - dcl_texcoord v0 - dcl_texcoord1 v1 - dcl_texcoord2 v2 - mov oT0, r1 - mov oT1.xy, r2 - mul r1, r0.x, c0 - mad r0, c1, r0.y, r1 - mov r1.xy, c4 - mad r0, c2, r1.x, r0 - mad r0, c3, r1.y, r0 - mov oPos, r0 - -// approximately 8 instruction slots used -vs_4_0 -dcl_constantbuffer cb0[4], immediateIndexed -dcl_input v0.xy -dcl_input v1.xyzw -dcl_input v2.xy -dcl_output_siv o0.xyzw, position -dcl_output o1.xyzw -dcl_output o2.xy -dcl_temps 1 -mul r0.xyzw, v0.xxxx, cb0[0].xyzw -mad r0.xyzw, cb0[1].xyzw, v0.yyyy, r0.xyzw -mad r0.xyzw, cb0[2].xyzw, l(0.000000, 0.000000, 0.000000, 0.000000), r0.xyzw -mad o0.xyzw, cb0[3].xyzw, l(1.000000, 1.000000, 1.000000, 1.000000), r0.xyzw -mov o1.xyzw, v1.xyzw -mov o2.xy, v2.xyxx -ret -// Approximately 0 instruction slots used -#endif - -const BYTE nk_d3d11_vertex_shader[] = -{ - 68, 88, 66, 67, 215, 245, - 86, 155, 188, 117, 37, 118, - 193, 207, 209, 90, 160, 153, - 246, 188, 1, 0, 0, 0, - 72, 5, 0, 0, 6, 0, - 0, 0, 56, 0, 0, 0, - 48, 1, 0, 0, 248, 1, - 0, 0, 20, 3, 0, 0, - 100, 4, 0, 0, 212, 4, - 0, 0, 88, 78, 65, 83, - 240, 0, 0, 0, 240, 0, - 0, 0, 0, 2, 254, 255, - 192, 0, 0, 0, 48, 0, - 0, 0, 1, 0, 36, 0, - 0, 0, 48, 0, 0, 0, - 48, 0, 0, 0, 36, 0, - 0, 0, 48, 0, 0, 0, - 0, 0, 4, 0, 0, 0, - 0, 0, 0, 0, 0, 2, - 254, 255, 81, 0, 0, 5, - 4, 0, 15, 160, 0, 0, - 0, 0, 0, 0, 128, 63, - 0, 0, 0, 0, 0, 0, - 0, 0, 31, 0, 0, 2, - 5, 0, 0, 128, 0, 0, - 15, 144, 31, 0, 0, 2, - 5, 0, 1, 128, 1, 0, - 15, 144, 31, 0, 0, 2, - 5, 0, 2, 128, 2, 0, - 15, 144, 1, 0, 0, 2, - 0, 0, 15, 224, 1, 0, - 228, 128, 1, 0, 0, 2, - 1, 0, 3, 224, 2, 0, - 228, 128, 5, 0, 0, 3, - 1, 0, 15, 128, 0, 0, - 0, 128, 0, 0, 228, 160, - 4, 0, 0, 4, 0, 0, - 15, 128, 1, 0, 228, 160, - 0, 0, 85, 128, 1, 0, - 228, 128, 1, 0, 0, 2, - 1, 0, 3, 128, 4, 0, - 228, 160, 4, 0, 0, 4, - 0, 0, 15, 128, 2, 0, - 228, 160, 1, 0, 0, 128, - 0, 0, 228, 128, 4, 0, - 0, 4, 0, 0, 15, 128, - 3, 0, 228, 160, 1, 0, - 85, 128, 0, 0, 228, 128, - 1, 0, 0, 2, 0, 0, - 15, 192, 0, 0, 228, 128, - 255, 255, 0, 0, 88, 78, - 65, 80, 192, 0, 0, 0, - 192, 0, 0, 0, 0, 2, - 254, 255, 144, 0, 0, 0, - 48, 0, 0, 0, 1, 0, - 36, 0, 0, 0, 48, 0, - 0, 0, 48, 0, 0, 0, - 36, 0, 0, 0, 48, 0, - 0, 0, 0, 0, 4, 0, - 0, 0, 0, 0, 0, 0, - 0, 2, 254, 255, 81, 0, - 0, 5, 4, 0, 15, 160, - 0, 0, 0, 0, 0, 0, - 128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 0, - 0, 2, 5, 0, 0, 128, - 0, 0, 15, 144, 5, 0, - 0, 3, 1, 0, 15, 128, - 0, 0, 0, 128, 0, 0, - 228, 160, 4, 0, 0, 4, - 0, 0, 15, 128, 1, 0, - 228, 160, 0, 0, 85, 128, - 1, 0, 228, 128, 1, 0, - 0, 2, 1, 0, 3, 128, - 4, 0, 228, 160, 4, 0, - 0, 4, 0, 0, 15, 128, - 2, 0, 228, 160, 1, 0, - 0, 128, 0, 0, 228, 128, - 4, 0, 0, 4, 0, 0, - 15, 128, 3, 0, 228, 160, - 1, 0, 85, 128, 0, 0, - 228, 128, 1, 0, 0, 2, - 0, 0, 15, 192, 0, 0, - 228, 128, 255, 255, 0, 0, - 65, 111, 110, 57, 20, 1, - 0, 0, 20, 1, 0, 0, - 0, 2, 254, 255, 224, 0, - 0, 0, 52, 0, 0, 0, - 1, 0, 36, 0, 0, 0, - 48, 0, 0, 0, 48, 0, - 0, 0, 36, 0, 1, 0, - 48, 0, 0, 0, 0, 0, - 4, 0, 1, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 2, 254, 255, 81, 0, - 0, 5, 5, 0, 15, 160, - 0, 0, 0, 0, 0, 0, - 128, 63, 0, 0, 0, 0, - 0, 0, 0, 0, 31, 0, - 0, 2, 5, 0, 0, 128, - 0, 0, 15, 144, 31, 0, - 0, 2, 5, 0, 1, 128, - 1, 0, 15, 144, 31, 0, - 0, 2, 5, 0, 2, 128, - 2, 0, 15, 144, 5, 0, - 0, 3, 0, 0, 15, 128, - 0, 0, 0, 144, 1, 0, - 228, 160, 4, 0, 0, 4, - 0, 0, 15, 128, 2, 0, - 228, 160, 0, 0, 85, 144, - 0, 0, 228, 128, 1, 0, - 0, 2, 1, 0, 3, 128, - 5, 0, 228, 160, 4, 0, - 0, 4, 0, 0, 15, 128, - 3, 0, 228, 160, 1, 0, - 0, 128, 0, 0, 228, 128, - 4, 0, 0, 4, 0, 0, - 15, 128, 4, 0, 228, 160, - 1, 0, 85, 128, 0, 0, - 228, 128, 5, 0, 0, 3, - 1, 0, 3, 128, 0, 0, - 255, 128, 0, 0, 228, 160, - 2, 0, 0, 3, 0, 0, - 3, 192, 0, 0, 228, 128, - 1, 0, 228, 128, 1, 0, - 0, 2, 0, 0, 12, 192, - 0, 0, 228, 128, 1, 0, - 0, 2, 0, 0, 15, 224, - 1, 0, 228, 144, 1, 0, - 0, 2, 1, 0, 3, 224, - 2, 0, 228, 144, 255, 255, - 0, 0, 83, 72, 68, 82, - 72, 1, 0, 0, 64, 0, - 1, 0, 82, 0, 0, 0, - 89, 0, 0, 4, 70, 142, - 32, 0, 0, 0, 0, 0, - 4, 0, 0, 0, 95, 0, - 0, 3, 50, 16, 16, 0, - 0, 0, 0, 0, 95, 0, - 0, 3, 242, 16, 16, 0, - 1, 0, 0, 0, 95, 0, - 0, 3, 50, 16, 16, 0, - 2, 0, 0, 0, 103, 0, - 0, 4, 242, 32, 16, 0, - 0, 0, 0, 0, 1, 0, - 0, 0, 101, 0, 0, 3, - 242, 32, 16, 0, 1, 0, - 0, 0, 101, 0, 0, 3, - 50, 32, 16, 0, 2, 0, - 0, 0, 104, 0, 0, 2, - 1, 0, 0, 0, 56, 0, - 0, 8, 242, 0, 16, 0, - 0, 0, 0, 0, 6, 16, - 16, 0, 0, 0, 0, 0, - 70, 142, 32, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 50, 0, 0, 10, 242, 0, - 16, 0, 0, 0, 0, 0, - 70, 142, 32, 0, 0, 0, - 0, 0, 1, 0, 0, 0, - 86, 21, 16, 0, 0, 0, - 0, 0, 70, 14, 16, 0, - 0, 0, 0, 0, 50, 0, - 0, 13, 242, 0, 16, 0, - 0, 0, 0, 0, 70, 142, - 32, 0, 0, 0, 0, 0, - 2, 0, 0, 0, 2, 64, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 70, 14, 16, 0, 0, 0, - 0, 0, 50, 0, 0, 13, - 242, 32, 16, 0, 0, 0, - 0, 0, 70, 142, 32, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 2, 64, 0, 0, - 0, 0, 128, 63, 0, 0, - 128, 63, 0, 0, 128, 63, - 0, 0, 128, 63, 70, 14, - 16, 0, 0, 0, 0, 0, - 54, 0, 0, 5, 242, 32, - 16, 0, 1, 0, 0, 0, - 70, 30, 16, 0, 1, 0, - 0, 0, 54, 0, 0, 5, - 50, 32, 16, 0, 2, 0, - 0, 0, 70, 16, 16, 0, - 2, 0, 0, 0, 62, 0, - 0, 1, 73, 83, 71, 78, - 104, 0, 0, 0, 3, 0, - 0, 0, 8, 0, 0, 0, - 80, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 0, 0, - 0, 0, 3, 3, 0, 0, - 89, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 1, 0, - 0, 0, 15, 15, 0, 0, - 95, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, - 3, 0, 0, 0, 2, 0, - 0, 0, 3, 3, 0, 0, - 80, 79, 83, 73, 84, 73, - 79, 78, 0, 67, 79, 76, - 79, 82, 0, 84, 69, 88, - 67, 79, 79, 82, 68, 0, - 79, 83, 71, 78, 108, 0, - 0, 0, 3, 0, 0, 0, - 8, 0, 0, 0, 80, 0, - 0, 0, 0, 0, 0, 0, - 1, 0, 0, 0, 3, 0, - 0, 0, 0, 0, 0, 0, - 15, 0, 0, 0, 92, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 1, 0, 0, 0, - 15, 0, 0, 0, 98, 0, - 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 3, 0, - 0, 0, 2, 0, 0, 0, - 3, 12, 0, 0, 83, 86, - 95, 80, 79, 83, 73, 84, - 73, 79, 78, 0, 67, 79, - 76, 79, 82, 0, 84, 69, - 88, 67, 79, 79, 82, 68, - 0, 171 -}; diff --git a/deps/nuklear/demo/gdi/build.bat b/deps/nuklear/demo/gdi/build.bat deleted file mode 100644 index 38843171..00000000 --- a/deps/nuklear/demo/gdi/build.bat +++ /dev/null @@ -1,6 +0,0 @@ -@echo off - -rem This will use VS2015 for compiler -call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86 - -cl /nologo /W3 /O2 /fp:fast /Gm- /Fedemo.exe main.c user32.lib gdi32.lib /link /incremental:no diff --git a/deps/nuklear/demo/gdi/main.c b/deps/nuklear/demo/gdi/main.c deleted file mode 100644 index e82cd169..00000000 --- a/deps/nuklear/demo/gdi/main.c +++ /dev/null @@ -1,161 +0,0 @@ -/* nuklear - v1.17 - public domain */ -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include - -#define WINDOW_WIDTH 800 -#define WINDOW_HEIGHT 600 - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_IMPLEMENTATION -#define NK_GDI_IMPLEMENTATION -#include "../../nuklear.h" -#include "nuklear_gdi.h" - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* This are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the include - * and the corresponding function. */ -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -/*#include "../style.c"*/ -/*#include "../calculator.c"*/ -/*#include "../overview.c"*/ -/*#include "../node_editor.c"*/ - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -static LRESULT CALLBACK -WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - switch (msg) - { - case WM_DESTROY: - PostQuitMessage(0); - return 0; - } - - if (nk_gdi_handle_event(wnd, msg, wparam, lparam)) - return 0; - - return DefWindowProcW(wnd, msg, wparam, lparam); -} - -int main(void) -{ - GdiFont* font; - struct nk_context *ctx; - - WNDCLASSW wc; - ATOM atom; - RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT }; - DWORD style = WS_OVERLAPPEDWINDOW; - DWORD exstyle = WS_EX_APPWINDOW; - HWND wnd; - HDC dc; - int running = 1; - int needs_refresh = 1; - - /* Win32 */ - memset(&wc, 0, sizeof(wc)); - wc.lpfnWndProc = WindowProc; - wc.hInstance = GetModuleHandleW(0); - wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.lpszClassName = L"NuklearWindowClass"; - atom = RegisterClassW(&wc); - - AdjustWindowRectEx(&rect, style, FALSE, exstyle); - wnd = CreateWindowExW(exstyle, wc.lpszClassName, L"Nuklear Demo", - style | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, - rect.right - rect.left, rect.bottom - rect.top, - NULL, NULL, wc.hInstance, NULL); - dc = GetDC(wnd); - - /* GUI */ - font = nk_gdifont_create("Arial", 14); - ctx = nk_gdi_init(font, dc, WINDOW_WIDTH, WINDOW_HEIGHT); - - /* style.c */ - /*set_style(ctx, THEME_WHITE);*/ - /*set_style(ctx, THEME_RED);*/ - /*set_style(ctx, THEME_BLUE);*/ - /*set_style(ctx, THEME_DARK);*/ - - while (running) - { - /* Input */ - MSG msg; - nk_input_begin(ctx); - if (needs_refresh == 0) { - if (GetMessageW(&msg, NULL, 0, 0) <= 0) - running = 0; - else { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - needs_refresh = 1; - } else needs_refresh = 0; - - while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { - if (msg.message == WM_QUIT) - running = 0; - TranslateMessage(&msg); - DispatchMessageW(&msg); - needs_refresh = 1; - } - nk_input_end(ctx); - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 200, 200), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - nk_layout_row_dynamic(ctx, 22, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - } - nk_end(ctx); - if (nk_window_is_closed(ctx, "Demo")) break; - - /* -------------- EXAMPLES ---------------- */ - /*calculator(ctx);*/ - /*overview(ctx);*/ - /*node_editor(ctx);*/ - /* ----------------------------------------- */ - - /* Draw */ - nk_gdi_render(nk_rgb(30,30,30)); - } - - nk_gdifont_del(font); - ReleaseDC(wnd, dc); - UnregisterClassW(wc.lpszClassName, wc.hInstance); - return 0; -} - diff --git a/deps/nuklear/demo/gdi/nuklear_gdi.h b/deps/nuklear/demo/gdi/nuklear_gdi.h deleted file mode 100644 index 6d3a84a0..00000000 --- a/deps/nuklear/demo/gdi/nuklear_gdi.h +++ /dev/null @@ -1,761 +0,0 @@ -/* - * Nuklear - v1.17 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_GDI_H_ -#define NK_GDI_H_ - -#define WIN32_LEAN_AND_MEAN -#include - -typedef struct GdiFont GdiFont; -NK_API struct nk_context* nk_gdi_init(GdiFont *font, HDC window_dc, unsigned int width, unsigned int height); -NK_API int nk_gdi_handle_event(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); -NK_API void nk_gdi_render(struct nk_color clear); -NK_API void nk_gdi_shutdown(void); - -/* font */ -NK_API GdiFont* nk_gdifont_create(const char *name, int size); -NK_API void nk_gdifont_del(GdiFont *font); -NK_API void nk_gdi_set_font(GdiFont *font); - -#endif - -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_GDI_IMPLEMENTATION - -#include -#include - -struct GdiFont { - struct nk_user_font nk; - int height; - HFONT handle; - HDC dc; -}; - -static struct { - HBITMAP bitmap; - HDC window_dc; - HDC memory_dc; - unsigned int width; - unsigned int height; - struct nk_context ctx; -} gdi; - -static COLORREF -convert_color(struct nk_color c) -{ - return c.r | (c.g << 8) | (c.b << 16); -} - -static void -nk_gdi_scissor(HDC dc, float x, float y, float w, float h) -{ - SelectClipRgn(dc, NULL); - IntersectClipRect(dc, (int)x, (int)y, (int)(x + w + 1), (int)(y + h + 1)); -} - -static void -nk_gdi_stroke_line(HDC dc, short x0, short y0, short x1, - short y1, unsigned int line_thickness, struct nk_color col) -{ - COLORREF color = convert_color(col); - - HPEN pen = NULL; - if (line_thickness == 1) { - SetDCPenColor(dc, color); - } else { - pen = CreatePen(PS_SOLID, line_thickness, color); - SelectObject(dc, pen); - } - - MoveToEx(dc, x0, y0, NULL); - LineTo(dc, x1, y1); - - if (pen) { - SelectObject(dc, GetStockObject(DC_PEN)); - DeleteObject(pen); - } -} - -static void -nk_gdi_stroke_rect(HDC dc, short x, short y, unsigned short w, - unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col) -{ - COLORREF color = convert_color(col); - - HPEN pen = NULL; - if (line_thickness == 1) { - SetDCPenColor(dc, color); - } else { - pen = CreatePen(PS_SOLID, line_thickness, color); - SelectObject(dc, pen); - } - - SetDCBrushColor(dc, OPAQUE); - if (r == 0) { - Rectangle(dc, x, y, x + w, y + h); - } else { - RoundRect(dc, x, y, x + w, y + h, r, r); - } - - if (pen) { - SelectObject(dc, GetStockObject(DC_PEN)); - DeleteObject(pen); - } -} - -static void -nk_gdi_fill_rect(HDC dc, short x, short y, unsigned short w, - unsigned short h, unsigned short r, struct nk_color col) -{ - COLORREF color = convert_color(col); - - if (r == 0) { - RECT rect = { x, y, x + w, y + h }; - SetBkColor(dc, color); - ExtTextOutW(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); - } else { - SetDCPenColor(dc, color); - SetDCBrushColor(dc, color); - RoundRect(dc, x, y, x + w, y + h, r, r); - } -} - -static void -nk_gdi_fill_triangle(HDC dc, short x0, short y0, short x1, - short y1, short x2, short y2, struct nk_color col) -{ - COLORREF color = convert_color(col); - POINT points[] = { - { x0, y0 }, - { x1, y1 }, - { x2, y2 }, - }; - - SetDCPenColor(dc, color); - SetDCBrushColor(dc, color); - Polygon(dc, points, 3); -} - -static void -nk_gdi_stroke_triangle(HDC dc, short x0, short y0, short x1, - short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col) -{ - COLORREF color = convert_color(col); - POINT points[] = { - { x0, y0 }, - { x1, y1 }, - { x2, y2 }, - { x0, y0 }, - }; - - HPEN pen = NULL; - if (line_thickness == 1) { - SetDCPenColor(dc, color); - } else { - pen = CreatePen(PS_SOLID, line_thickness, color); - SelectObject(dc, pen); - } - - Polyline(dc, points, 4); - - if (pen) { - SelectObject(dc, GetStockObject(DC_PEN)); - DeleteObject(pen); - } -} - -static void -nk_gdi_fill_polygon(HDC dc, const struct nk_vec2i *pnts, int count, struct nk_color col) -{ - int i = 0; - #define MAX_POINTS 64 - POINT points[MAX_POINTS]; - COLORREF color = convert_color(col); - SetDCBrushColor(dc, color); - SetDCPenColor(dc, color); - for (i = 0; i < count && i < MAX_POINTS; ++i) { - points[i].x = pnts[i].x; - points[i].y = pnts[i].y; - } - Polygon(dc, points, i); - #undef MAX_POINTS -} - -static void -nk_gdi_stroke_polygon(HDC dc, const struct nk_vec2i *pnts, int count, - unsigned short line_thickness, struct nk_color col) -{ - COLORREF color = convert_color(col); - HPEN pen = NULL; - if (line_thickness == 1) { - SetDCPenColor(dc, color); - } else { - pen = CreatePen(PS_SOLID, line_thickness, color); - SelectObject(dc, pen); - } - - if (count > 0) { - int i; - MoveToEx(dc, pnts[0].x, pnts[0].y, NULL); - for (i = 1; i < count; ++i) - LineTo(dc, pnts[i].x, pnts[i].y); - LineTo(dc, pnts[0].x, pnts[0].y); - } - - if (pen) { - SelectObject(dc, GetStockObject(DC_PEN)); - DeleteObject(pen); - } -} - -static void -nk_gdi_stroke_polyline(HDC dc, const struct nk_vec2i *pnts, - int count, unsigned short line_thickness, struct nk_color col) -{ - COLORREF color = convert_color(col); - HPEN pen = NULL; - if (line_thickness == 1) { - SetDCPenColor(dc, color); - } else { - pen = CreatePen(PS_SOLID, line_thickness, color); - SelectObject(dc, pen); - } - - if (count > 0) { - int i; - MoveToEx(dc, pnts[0].x, pnts[0].y, NULL); - for (i = 1; i < count; ++i) - LineTo(dc, pnts[i].x, pnts[i].y); - } - - if (pen) { - SelectObject(dc, GetStockObject(DC_PEN)); - DeleteObject(pen); - } -} - -static void -nk_gdi_fill_circle(HDC dc, short x, short y, unsigned short w, - unsigned short h, struct nk_color col) -{ - COLORREF color = convert_color(col); - SetDCBrushColor(dc, color); - SetDCPenColor(dc, color); - Ellipse(dc, x, y, x + w, y + h); -} - -static void -nk_gdi_stroke_circle(HDC dc, short x, short y, unsigned short w, - unsigned short h, unsigned short line_thickness, struct nk_color col) -{ - COLORREF color = convert_color(col); - HPEN pen = NULL; - if (line_thickness == 1) { - SetDCPenColor(dc, color); - } else { - pen = CreatePen(PS_SOLID, line_thickness, color); - SelectObject(dc, pen); - } - - SetDCBrushColor(dc, OPAQUE); - Ellipse(dc, x, y, x + w, y + h); - - if (pen) { - SelectObject(dc, GetStockObject(DC_PEN)); - DeleteObject(pen); - } -} - -static void -nk_gdi_stroke_curve(HDC dc, struct nk_vec2i p1, - struct nk_vec2i p2, struct nk_vec2i p3, struct nk_vec2i p4, - unsigned short line_thickness, struct nk_color col) -{ - COLORREF color = convert_color(col); - POINT p[] = { - { p1.x, p1.y }, - { p2.x, p2.y }, - { p3.x, p3.y }, - { p4.x, p4.y }, - }; - - HPEN pen = NULL; - if (line_thickness == 1) { - SetDCPenColor(dc, color); - } else { - pen = CreatePen(PS_SOLID, line_thickness, color); - SelectObject(dc, pen); - } - - SetDCBrushColor(dc, OPAQUE); - PolyBezier(dc, p, 4); - - if (pen) { - SelectObject(dc, GetStockObject(DC_PEN)); - DeleteObject(pen); - } -} - -static void -nk_gdi_draw_text(HDC dc, short x, short y, unsigned short w, unsigned short h, - const char *text, int len, GdiFont *font, struct nk_color cbg, struct nk_color cfg) -{ - int wsize; - WCHAR* wstr; - - if(!text || !font || !len) return; - - wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0); - wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t)); - MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize); - - SetBkColor(dc, convert_color(cbg)); - SetTextColor(dc, convert_color(cfg)); - - SelectObject(dc, font->handle); - ExtTextOutW(dc, x, y, ETO_OPAQUE, NULL, wstr, wsize, NULL); -} - -static void -nk_gdi_clear(HDC dc, struct nk_color col) -{ - COLORREF color = convert_color(col); - RECT rect = { 0, 0, gdi.width, gdi.height }; - SetBkColor(dc, color); - - ExtTextOutW(dc, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL); -} - -static void -nk_gdi_blit(HDC dc) -{ - BitBlt(dc, 0, 0, gdi.width, gdi.height, gdi.memory_dc, 0, 0, SRCCOPY); -} - -GdiFont* -nk_gdifont_create(const char *name, int size) -{ - TEXTMETRICW metric; - GdiFont *font = (GdiFont*)calloc(1, sizeof(GdiFont)); - if (!font) - return NULL; - font->dc = CreateCompatibleDC(0); - font->handle = CreateFont(size, 0, 0, 0, FW_NORMAL, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, CLEARTYPE_QUALITY, DEFAULT_PITCH | FF_DONTCARE, name); - SelectObject(font->dc, font->handle); - GetTextMetricsW(font->dc, &metric); - font->height = metric.tmHeight; - return font; -} - -static float -nk_gdifont_get_text_width(nk_handle handle, float height, const char *text, int len) -{ - GdiFont *font = (GdiFont*)handle.ptr; - SIZE size; - int wsize; - WCHAR* wstr; - if (!font || !text) - return 0; - - wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0); - wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t)); - MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize); - if (GetTextExtentPoint32W(font->dc, wstr, wsize, &size)) - return (float)size.cx; - return -1.0f; -} - -void -nk_gdifont_del(GdiFont *font) -{ - if(!font) return; - DeleteObject(font->handle); - DeleteDC(font->dc); - free(font); -} - -static void -nk_gdi_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) -{ - (void)usr; - if (IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL)) - { - HGLOBAL mem = GetClipboardData(CF_UNICODETEXT); - if (mem) - { - SIZE_T size = GlobalSize(mem) - 1; - if (size) - { - LPCWSTR wstr = (LPCWSTR)GlobalLock(mem); - if (wstr) - { - int utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)(size / sizeof(wchar_t)), NULL, 0, NULL, NULL); - if (utf8size) - { - char* utf8 = (char*)malloc(utf8size); - if (utf8) - { - WideCharToMultiByte(CP_UTF8, 0, wstr, (int)(size / sizeof(wchar_t)), utf8, utf8size, NULL, NULL); - nk_textedit_paste(edit, utf8, utf8size); - free(utf8); - } - } - GlobalUnlock(mem); - } - } - } - CloseClipboard(); - } -} - -static void -nk_gdi_clipbard_copy(nk_handle usr, const char *text, int len) -{ - if (OpenClipboard(NULL)) - { - int wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0); - if (wsize) - { - HGLOBAL mem = (HGLOBAL)GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t)); - if (mem) - { - wchar_t* wstr = (wchar_t*)GlobalLock(mem); - if (wstr) - { - MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize); - wstr[wsize] = 0; - GlobalUnlock(mem); - - SetClipboardData(CF_UNICODETEXT, mem); - } - } - } - CloseClipboard(); - } -} - -NK_API struct nk_context* -nk_gdi_init(GdiFont *gdifont, HDC window_dc, unsigned int width, unsigned int height) -{ - struct nk_user_font *font = &gdifont->nk; - font->userdata = nk_handle_ptr(gdifont); - font->height = (float)gdifont->height; - font->width = nk_gdifont_get_text_width; - - gdi.bitmap = CreateCompatibleBitmap(window_dc, width, height); - gdi.window_dc = window_dc; - gdi.memory_dc = CreateCompatibleDC(window_dc); - gdi.width = width; - gdi.height = height; - SelectObject(gdi.memory_dc, gdi.bitmap); - - nk_init_default(&gdi.ctx, font); - gdi.ctx.clip.copy = nk_gdi_clipbard_copy; - gdi.ctx.clip.paste = nk_gdi_clipbard_paste; - return &gdi.ctx; -} - -NK_API void -nk_gdi_set_font(GdiFont *gdifont) -{ - struct nk_user_font *font = &gdifont->nk; - font->userdata = nk_handle_ptr(gdifont); - font->height = (float)gdifont->height; - font->width = nk_gdifont_get_text_width; - nk_style_set_font(&gdi.ctx, font); -} - -NK_API int -nk_gdi_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - switch (msg) - { - case WM_SIZE: - { - unsigned width = LOWORD(lparam); - unsigned height = LOWORD(lparam); - if (width != gdi.width || height != gdi.height) - { - DeleteObject(gdi.bitmap); - gdi.bitmap = CreateCompatibleBitmap(gdi.window_dc, width, height); - gdi.width = width; - gdi.height = height; - SelectObject(gdi.memory_dc, gdi.bitmap); - } - break; - } - - case WM_PAINT: - { - PAINTSTRUCT paint; - HDC dc = BeginPaint(wnd, &paint); - nk_gdi_blit(dc); - EndPaint(wnd, &paint); - return 1; - } - - case WM_KEYDOWN: - case WM_KEYUP: - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - { - int down = !((lparam >> 31) & 1); - int ctrl = GetKeyState(VK_CONTROL) & (1 << 15); - - switch (wparam) - { - case VK_SHIFT: - case VK_LSHIFT: - case VK_RSHIFT: - nk_input_key(&gdi.ctx, NK_KEY_SHIFT, down); - return 1; - - case VK_DELETE: - nk_input_key(&gdi.ctx, NK_KEY_DEL, down); - return 1; - - case VK_RETURN: - nk_input_key(&gdi.ctx, NK_KEY_ENTER, down); - return 1; - - case VK_TAB: - nk_input_key(&gdi.ctx, NK_KEY_TAB, down); - return 1; - - case VK_LEFT: - if (ctrl) - nk_input_key(&gdi.ctx, NK_KEY_TEXT_WORD_LEFT, down); - else - nk_input_key(&gdi.ctx, NK_KEY_LEFT, down); - return 1; - - case VK_RIGHT: - if (ctrl) - nk_input_key(&gdi.ctx, NK_KEY_TEXT_WORD_RIGHT, down); - else - nk_input_key(&gdi.ctx, NK_KEY_RIGHT, down); - return 1; - - case VK_BACK: - nk_input_key(&gdi.ctx, NK_KEY_BACKSPACE, down); - return 1; - - case VK_HOME: - nk_input_key(&gdi.ctx, NK_KEY_TEXT_START, down); - nk_input_key(&gdi.ctx, NK_KEY_SCROLL_START, down); - return 1; - - case VK_END: - nk_input_key(&gdi.ctx, NK_KEY_TEXT_END, down); - nk_input_key(&gdi.ctx, NK_KEY_SCROLL_END, down); - return 1; - - case VK_NEXT: - nk_input_key(&gdi.ctx, NK_KEY_SCROLL_DOWN, down); - return 1; - - case VK_PRIOR: - nk_input_key(&gdi.ctx, NK_KEY_SCROLL_UP, down); - return 1; - - case 'C': - if (ctrl) { - nk_input_key(&gdi.ctx, NK_KEY_COPY, down); - return 1; - } - break; - - case 'V': - if (ctrl) { - nk_input_key(&gdi.ctx, NK_KEY_PASTE, down); - return 1; - } - break; - - case 'X': - if (ctrl) { - nk_input_key(&gdi.ctx, NK_KEY_CUT, down); - return 1; - } - break; - - case 'Z': - if (ctrl) { - nk_input_key(&gdi.ctx, NK_KEY_TEXT_UNDO, down); - return 1; - } - break; - - case 'R': - if (ctrl) { - nk_input_key(&gdi.ctx, NK_KEY_TEXT_REDO, down); - return 1; - } - break; - } - return 0; - } - - case WM_CHAR: - if (wparam >= 32) - { - nk_input_unicode(&gdi.ctx, (nk_rune)wparam); - return 1; - } - break; - - case WM_LBUTTONDOWN: - nk_input_button(&gdi.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1); - SetCapture(wnd); - return 1; - - case WM_LBUTTONUP: - nk_input_button(&gdi.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0); - ReleaseCapture(); - return 1; - - case WM_RBUTTONDOWN: - nk_input_button(&gdi.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1); - SetCapture(wnd); - return 1; - - case WM_RBUTTONUP: - nk_input_button(&gdi.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0); - ReleaseCapture(); - return 1; - - case WM_MBUTTONDOWN: - nk_input_button(&gdi.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1); - SetCapture(wnd); - return 1; - - case WM_MBUTTONUP: - nk_input_button(&gdi.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0); - ReleaseCapture(); - return 1; - - case WM_MOUSEWHEEL: - nk_input_scroll(&gdi.ctx, (float)(short)HIWORD(wparam) / WHEEL_DELTA); - return 1; - - case WM_MOUSEMOVE: - nk_input_motion(&gdi.ctx, (short)LOWORD(lparam), (short)HIWORD(lparam)); - return 1; - } - - return 0; -} - -NK_API void -nk_gdi_shutdown(void) -{ - DeleteObject(gdi.memory_dc); - DeleteObject(gdi.bitmap); - nk_free(&gdi.ctx); -} - -NK_API void -nk_gdi_render(struct nk_color clear) -{ - const struct nk_command *cmd; - - HDC memory_dc = gdi.memory_dc; - SelectObject(memory_dc, GetStockObject(DC_PEN)); - SelectObject(memory_dc, GetStockObject(DC_BRUSH)); - nk_gdi_clear(memory_dc, clear); - - nk_foreach(cmd, &gdi.ctx) - { - switch (cmd->type) { - case NK_COMMAND_NOP: break; - case NK_COMMAND_SCISSOR: { - const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd; - nk_gdi_scissor(memory_dc, s->x, s->y, s->w, s->h); - } break; - case NK_COMMAND_LINE: { - const struct nk_command_line *l = (const struct nk_command_line *)cmd; - nk_gdi_stroke_line(memory_dc, l->begin.x, l->begin.y, l->end.x, - l->end.y, l->line_thickness, l->color); - } break; - case NK_COMMAND_RECT: { - const struct nk_command_rect *r = (const struct nk_command_rect *)cmd; - nk_gdi_stroke_rect(memory_dc, r->x, r->y, r->w, r->h, - (unsigned short)r->rounding, r->line_thickness, r->color); - } break; - case NK_COMMAND_RECT_FILLED: { - const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd; - nk_gdi_fill_rect(memory_dc, r->x, r->y, r->w, r->h, - (unsigned short)r->rounding, r->color); - } break; - case NK_COMMAND_CIRCLE: { - const struct nk_command_circle *c = (const struct nk_command_circle *)cmd; - nk_gdi_stroke_circle(memory_dc, c->x, c->y, c->w, c->h, c->line_thickness, c->color); - } break; - case NK_COMMAND_CIRCLE_FILLED: { - const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; - nk_gdi_fill_circle(memory_dc, c->x, c->y, c->w, c->h, c->color); - } break; - case NK_COMMAND_TRIANGLE: { - const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd; - nk_gdi_stroke_triangle(memory_dc, t->a.x, t->a.y, t->b.x, t->b.y, - t->c.x, t->c.y, t->line_thickness, t->color); - } break; - case NK_COMMAND_TRIANGLE_FILLED: { - const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd; - nk_gdi_fill_triangle(memory_dc, t->a.x, t->a.y, t->b.x, t->b.y, - t->c.x, t->c.y, t->color); - } break; - case NK_COMMAND_POLYGON: { - const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd; - nk_gdi_stroke_polygon(memory_dc, p->points, p->point_count, p->line_thickness,p->color); - } break; - case NK_COMMAND_POLYGON_FILLED: { - const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd; - nk_gdi_fill_polygon(memory_dc, p->points, p->point_count, p->color); - } break; - case NK_COMMAND_POLYLINE: { - const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd; - nk_gdi_stroke_polyline(memory_dc, p->points, p->point_count, p->line_thickness, p->color); - } break; - case NK_COMMAND_TEXT: { - const struct nk_command_text *t = (const struct nk_command_text*)cmd; - nk_gdi_draw_text(memory_dc, t->x, t->y, t->w, t->h, - (const char*)t->string, t->length, - (GdiFont*)t->font->userdata.ptr, - t->background, t->foreground); - } break; - case NK_COMMAND_CURVE: { - const struct nk_command_curve *q = (const struct nk_command_curve *)cmd; - nk_gdi_stroke_curve(memory_dc, q->begin, q->ctrl[0], q->ctrl[1], - q->end, q->line_thickness, q->color); - } break; - case NK_COMMAND_RECT_MULTI_COLOR: - case NK_COMMAND_IMAGE: - case NK_COMMAND_ARC: - case NK_COMMAND_ARC_FILLED: - default: break; - } - } - nk_gdi_blit(gdi.window_dc); - nk_clear(&gdi.ctx); -} - -#endif - diff --git a/deps/nuklear/demo/gdip/build.bat b/deps/nuklear/demo/gdip/build.bat deleted file mode 100644 index 28f51a37..00000000 --- a/deps/nuklear/demo/gdip/build.bat +++ /dev/null @@ -1,5 +0,0 @@ -@echo off - -call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x86 - -cl /nologo /W3 /O2 /fp:fast /Gm- /Fedemo.exe main.c user32.lib gdiplus.lib /link /incremental:no diff --git a/deps/nuklear/demo/gdip/main.c b/deps/nuklear/demo/gdip/main.c deleted file mode 100644 index 7d623e75..00000000 --- a/deps/nuklear/demo/gdip/main.c +++ /dev/null @@ -1,155 +0,0 @@ -/* nuklear - v1.17 - public domain */ -#define WIN32_LEAN_AND_MEAN -#include -#include -#include -#include -#include - -#define WINDOW_WIDTH 800 -#define WINDOW_HEIGHT 600 - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_IMPLEMENTATION -#define NK_GDIP_IMPLEMENTATION -#include "../../nuklear.h" -#include "nuklear_gdip.h" - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* These are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the include - * and the corresponding function. */ - #define UNUSED(a) (void)a - #define MIN(a,b) ((a) < (b) ? (a) : (b)) - #define MAX(a,b) ((a) < (b) ? (b) : (a)) - #define LEN(a) (sizeof(a)/sizeof(a)[0]) - -/*#include "../style.c"*/ -/*#include "../calculator.c"*/ -/*#include "../overview.c"*/ -/*#include "../node_editor.c"*/ - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -static LRESULT CALLBACK -WindowProc(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - switch (msg) { - case WM_DESTROY: - PostQuitMessage(0); - return 0; - } - if (nk_gdip_handle_event(wnd, msg, wparam, lparam)) - return 0; - return DefWindowProcW(wnd, msg, wparam, lparam); -} - -int main(void) -{ - GdipFont* font; - struct nk_context *ctx; - - WNDCLASSW wc; - RECT rect = { 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT }; - DWORD style = WS_OVERLAPPEDWINDOW; - DWORD exstyle = WS_EX_APPWINDOW; - HWND wnd; - int running = 1; - int needs_refresh = 1; - - /* Win32 */ - memset(&wc, 0, sizeof(wc)); - wc.lpfnWndProc = WindowProc; - wc.hInstance = GetModuleHandleW(0); - wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wc.hCursor = LoadCursor(NULL, IDC_ARROW); - wc.lpszClassName = L"NuklearWindowClass"; - RegisterClassW(&wc); - - AdjustWindowRectEx(&rect, style, FALSE, exstyle); - - wnd = CreateWindowExW(exstyle, wc.lpszClassName, L"Nuklear Demo", - style | WS_VISIBLE, CW_USEDEFAULT, CW_USEDEFAULT, - rect.right - rect.left, rect.bottom - rect.top, - NULL, NULL, wc.hInstance, NULL); - - /* GUI */ - ctx = nk_gdip_init(wnd, WINDOW_WIDTH, WINDOW_HEIGHT); - font = nk_gdipfont_create("Arial", 12); - nk_gdip_set_font(font); - - /* style.c */ - /*set_style(ctx, THEME_WHITE);*/ - /*set_style(ctx, THEME_RED);*/ - /*set_style(ctx, THEME_BLUE);*/ - /*set_style(ctx, THEME_DARK);*/ - - while (running) - { - /* Input */ - MSG msg; - nk_input_begin(ctx); - if (needs_refresh == 0) { - if (GetMessageW(&msg, NULL, 0, 0) <= 0) - running = 0; - else { - TranslateMessage(&msg); - DispatchMessageW(&msg); - } - needs_refresh = 1; - } else needs_refresh = 0; - while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE)) { - if (msg.message == WM_QUIT) - running = 0; - TranslateMessage(&msg); - DispatchMessageW(&msg); - needs_refresh = 1; - } - nk_input_end(ctx); - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 200, 200), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - nk_layout_row_dynamic(ctx, 22, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - } - nk_end(ctx); - if (nk_window_is_closed(ctx, "Demo")) break; - - /* -------------- EXAMPLES ---------------- */ - /*calculator(ctx);*/ - /*overview(ctx);*/ - /*node_editor(ctx);*/ - /* ----------------------------------------- */ - - /* Draw */ - nk_gdip_render(NK_ANTI_ALIASING_ON, nk_rgb(30,30,30)); - } - - nk_gdipfont_del(font); - nk_gdip_shutdown(); - UnregisterClassW(wc.lpszClassName, wc.hInstance); - return 0; -} diff --git a/deps/nuklear/demo/gdip/nuklear_gdip.h b/deps/nuklear/demo/gdip/nuklear_gdip.h deleted file mode 100644 index edefaa42..00000000 --- a/deps/nuklear/demo/gdip/nuklear_gdip.h +++ /dev/null @@ -1,1006 +0,0 @@ -/* - * Nuklear - v1.17 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_GDIP_H_ -#define NK_GDIP_H_ - -#define WIN32_LEAN_AND_MEAN -#include - -/* font */ -typedef struct GdipFont GdipFont; -NK_API GdipFont* nk_gdipfont_create(const char *name, int size); -NK_API void nk_gdipfont_del(GdipFont *font); - -NK_API struct nk_context* nk_gdip_init(HWND hwnd, unsigned int width, unsigned int height); -NK_API void nk_gdip_set_font(GdipFont *font); -NK_API int nk_gdip_handle_event(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam); -NK_API void nk_gdip_render(enum nk_anti_aliasing AA, struct nk_color clear); -NK_API void nk_gdip_shutdown(void); - -#endif -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_GDIP_IMPLEMENTATION - -#include -#include - -/* manually declare everything GDI+ needs, because - GDI+ headers are not usable from C */ -#define WINGDIPAPI __stdcall -#define GDIPCONST const - -typedef struct GpGraphics GpGraphics; -typedef struct GpImage GpImage; -typedef struct GpPen GpPen; -typedef struct GpBrush GpBrush; -typedef struct GpStringFormat GpStringFormat; -typedef struct GpFont GpFont; -typedef struct GpFontFamily GpFontFamily; -typedef struct GpFontCollection GpFontCollection; - -typedef GpImage GpBitmap; -typedef GpBrush GpSolidFill; - -typedef int Status; -typedef Status GpStatus; - -typedef float REAL; -typedef DWORD ARGB; -typedef POINT GpPoint; - -typedef enum { - TextRenderingHintSystemDefault = 0, - TextRenderingHintSingleBitPerPixelGridFit = 1, - TextRenderingHintSingleBitPerPixel = 2, - TextRenderingHintAntiAliasGridFit = 3, - TextRenderingHintAntiAlias = 4, - TextRenderingHintClearTypeGridFit = 5 -} TextRenderingHint; - -typedef enum { - StringFormatFlagsDirectionRightToLeft = 0x00000001, - StringFormatFlagsDirectionVertical = 0x00000002, - StringFormatFlagsNoFitBlackBox = 0x00000004, - StringFormatFlagsDisplayFormatControl = 0x00000020, - StringFormatFlagsNoFontFallback = 0x00000400, - StringFormatFlagsMeasureTrailingSpaces = 0x00000800, - StringFormatFlagsNoWrap = 0x00001000, - StringFormatFlagsLineLimit = 0x00002000, - StringFormatFlagsNoClip = 0x00004000 -} StringFormatFlags; - -typedef enum -{ - QualityModeInvalid = -1, - QualityModeDefault = 0, - QualityModeLow = 1, - QualityModeHigh = 2 -} QualityMode; - -typedef enum -{ - SmoothingModeInvalid = QualityModeInvalid, - SmoothingModeDefault = QualityModeDefault, - SmoothingModeHighSpeed = QualityModeLow, - SmoothingModeHighQuality = QualityModeHigh, - SmoothingModeNone, - SmoothingModeAntiAlias, - SmoothingModeAntiAlias8x4 = SmoothingModeAntiAlias, - SmoothingModeAntiAlias8x8 -} SmoothingMode; - -typedef enum -{ - FontStyleRegular = 0, - FontStyleBold = 1, - FontStyleItalic = 2, - FontStyleBoldItalic = 3, - FontStyleUnderline = 4, - FontStyleStrikeout = 8 -} FontStyle; - -typedef enum { - FillModeAlternate, - FillModeWinding -} FillMode; - -typedef enum { - CombineModeReplace, - CombineModeIntersect, - CombineModeUnion, - CombineModeXor, - CombineModeExclude, - CombineModeComplement -} CombineMode; - -typedef enum { - UnitWorld, - UnitDisplay, - UnitPixel, - UnitPoint, - UnitInch, - UnitDocument, - UnitMillimeter -} Unit; - -typedef struct { - FLOAT X; - FLOAT Y; - FLOAT Width; - FLOAT Height; -} RectF; - -typedef enum { - DebugEventLevelFatal, - DebugEventLevelWarning -} DebugEventLevel; - -typedef VOID (WINAPI *DebugEventProc)(DebugEventLevel level, CHAR *message); - -typedef struct { - UINT32 GdiplusVersion; - DebugEventProc DebugEventCallback; - BOOL SuppressBackgroundThread; - BOOL SuppressExternalCodecs; -} GdiplusStartupInput; - -typedef Status (WINAPI *NotificationHookProc)(OUT ULONG_PTR *token); -typedef VOID (WINAPI *NotificationUnhookProc)(ULONG_PTR token); - -typedef struct { - NotificationHookProc NotificationHook; - NotificationUnhookProc NotificationUnhook; -} GdiplusStartupOutput; - -/* startup & shutdown */ - -Status WINAPI GdiplusStartup( - OUT ULONG_PTR *token, - const GdiplusStartupInput *input, - OUT GdiplusStartupOutput *output); - -VOID WINAPI GdiplusShutdown(ULONG_PTR token); - -/* image */ - -GpStatus WINGDIPAPI -GdipCreateBitmapFromGraphics(INT width, - INT height, - GpGraphics* target, - GpBitmap** bitmap); - -GpStatus WINGDIPAPI -GdipDisposeImage(GpImage *image); - -GpStatus WINGDIPAPI -GdipGetImageGraphicsContext(GpImage *image, GpGraphics **graphics); - -/* pen */ - -GpStatus WINGDIPAPI -GdipCreatePen1(ARGB color, REAL width, Unit unit, GpPen **pen); - -GpStatus WINGDIPAPI -GdipDeletePen(GpPen *pen); - -GpStatus WINGDIPAPI -GdipSetPenWidth(GpPen *pen, REAL width); - -GpStatus WINGDIPAPI -GdipSetPenColor(GpPen *pen, ARGB argb); - -/* brush */ - -GpStatus WINGDIPAPI -GdipCreateSolidFill(ARGB color, GpSolidFill **brush); - -GpStatus WINGDIPAPI -GdipDeleteBrush(GpBrush *brush); - -GpStatus WINGDIPAPI -GdipSetSolidFillColor(GpSolidFill *brush, ARGB color); - -/* font */ - -GpStatus WINGDIPAPI -GdipCreateFont( - GDIPCONST GpFontFamily *fontFamily, - REAL emSize, - INT style, - Unit unit, - GpFont **font -); - -GpStatus WINGDIPAPI -GdipDeleteFont(GpFont* font); - -GpStatus WINGDIPAPI -GdipGetFontSize(GpFont *font, REAL *size); - -GpStatus WINGDIPAPI -GdipCreateFontFamilyFromName(GDIPCONST WCHAR *name, - GpFontCollection *fontCollection, - GpFontFamily **fontFamily); - -GpStatus WINGDIPAPI -GdipDeleteFontFamily(GpFontFamily *fontFamily); - -GpStatus WINGDIPAPI -GdipStringFormatGetGenericTypographic(GpStringFormat **format); - -GpStatus WINGDIPAPI -GdipSetStringFormatFlags(GpStringFormat *format, INT flags); - -GpStatus WINGDIPAPI -GdipDeleteStringFormat(GpStringFormat *format); - -/* graphics */ - - -GpStatus WINGDIPAPI -GdipCreateFromHWND(HWND hwnd, GpGraphics **graphics); - -GpStatus WINGDIPAPI -GdipCreateFromHDC(HDC hdc, GpGraphics **graphics); - -GpStatus WINGDIPAPI -GdipDeleteGraphics(GpGraphics *graphics); - -GpStatus WINGDIPAPI -GdipSetSmoothingMode(GpGraphics *graphics, SmoothingMode smoothingMode); - -GpStatus WINGDIPAPI -GdipSetClipRectI(GpGraphics *graphics, INT x, INT y, - INT width, INT height, CombineMode combineMode); - -GpStatus WINGDIPAPI -GdipDrawLineI(GpGraphics *graphics, GpPen *pen, INT x1, INT y1, - INT x2, INT y2); - -GpStatus WINGDIPAPI -GdipDrawArcI(GpGraphics *graphics, GpPen *pen, INT x, INT y, - INT width, INT height, REAL startAngle, REAL sweepAngle); - -GpStatus WINGDIPAPI -GdipFillPieI(GpGraphics *graphics, GpBrush *brush, INT x, INT y, - INT width, INT height, REAL startAngle, REAL sweepAngle); - -GpStatus WINGDIPAPI -GdipDrawRectangleI(GpGraphics *graphics, GpPen *pen, INT x, INT y, - INT width, INT height); - -GpStatus WINGDIPAPI -GdipFillRectangleI(GpGraphics *graphics, GpBrush *brush, INT x, INT y, - INT width, INT height); - -GpStatus WINGDIPAPI -GdipFillPolygonI(GpGraphics *graphics, GpBrush *brush, - GDIPCONST GpPoint *points, INT count, FillMode fillMode); - -GpStatus WINGDIPAPI -GdipDrawPolygonI(GpGraphics *graphics, GpPen *pen, GDIPCONST GpPoint *points, - INT count); - -GpStatus WINGDIPAPI -GdipFillEllipseI(GpGraphics *graphics, GpBrush *brush, INT x, INT y, - INT width, INT height); - -GpStatus WINGDIPAPI -GdipDrawEllipseI(GpGraphics *graphics, GpPen *pen, INT x, INT y, - INT width, INT height); - -GpStatus WINGDIPAPI -GdipDrawBezierI(GpGraphics *graphics, GpPen *pen, INT x1, INT y1, - INT x2, INT y2, INT x3, INT y3, INT x4, INT y4); - -GpStatus WINGDIPAPI -GdipDrawString( - GpGraphics *graphics, - GDIPCONST WCHAR *string, - INT length, - GDIPCONST GpFont *font, - GDIPCONST RectF *layoutRect, - GDIPCONST GpStringFormat *stringFormat, - GDIPCONST GpBrush *brush -); - -GpStatus WINGDIPAPI -GdipGraphicsClear(GpGraphics *graphics, ARGB color); - -GpStatus WINGDIPAPI -GdipDrawImageI(GpGraphics *graphics, GpImage *image, INT x, INT y); - -GpStatus WINGDIPAPI -GdipMeasureString( - GpGraphics *graphics, - GDIPCONST WCHAR *string, - INT length, - GDIPCONST GpFont *font, - GDIPCONST RectF *layoutRect, - GDIPCONST GpStringFormat *stringFormat, - RectF *boundingBox, - INT *codepointsFitted, - INT *linesFilled -); - -GpStatus WINGDIPAPI -GdipSetTextRenderingHint(GpGraphics *graphics, TextRenderingHint mode); - -struct GdipFont -{ - struct nk_user_font nk; - GpFont* handle; -}; - -static struct { - ULONG_PTR token; - - GpGraphics *window; - GpGraphics *memory; - GpImage *bitmap; - GpPen *pen; - GpSolidFill *brush; - GpStringFormat *format; - - struct nk_context ctx; -} gdip; - -static ARGB convert_color(struct nk_color c) -{ - return (c.a << 24) | (c.r << 16) | (c.g << 8) | c.b; -} - -static void -nk_gdip_scissor(float x, float y, float w, float h) -{ - GdipSetClipRectI(gdip.memory, (INT)x, (INT)y, (INT)(w + 1), (INT)(h + 1), CombineModeReplace); -} - -static void -nk_gdip_stroke_line(short x0, short y0, short x1, - short y1, unsigned int line_thickness, struct nk_color col) -{ - GdipSetPenWidth(gdip.pen, (REAL)line_thickness); - GdipSetPenColor(gdip.pen, convert_color(col)); - GdipDrawLineI(gdip.memory, gdip.pen, x0, y0, x1, y1); -} - -static void -nk_gdip_stroke_rect(short x, short y, unsigned short w, - unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col) -{ - GdipSetPenWidth(gdip.pen, (REAL)line_thickness); - GdipSetPenColor(gdip.pen, convert_color(col)); - if (r == 0) { - GdipDrawRectangleI(gdip.memory, gdip.pen, x, y, w, h); - } else { - INT d = 2 * r; - GdipDrawArcI(gdip.memory, gdip.pen, x, y, d, d, 180, 90); - GdipDrawLineI(gdip.memory, gdip.pen, x + r, y, x + w - r, y); - GdipDrawArcI(gdip.memory, gdip.pen, x + w - d, y, d, d, 270, 90); - GdipDrawLineI(gdip.memory, gdip.pen, x + w, y + r, x + w, y + h - r); - GdipDrawArcI(gdip.memory, gdip.pen, x + w - d, y + h - d, d, d, 0, 90); - GdipDrawLineI(gdip.memory, gdip.pen, x, y + r, x, y + h - r); - GdipDrawArcI(gdip.memory, gdip.pen, x, y + h - d, d, d, 90, 90); - GdipDrawLineI(gdip.memory, gdip.pen, x + r, y + h, x + w - r, y + h); - } -} - -static void -nk_gdip_fill_rect(short x, short y, unsigned short w, - unsigned short h, unsigned short r, struct nk_color col) -{ - GdipSetSolidFillColor(gdip.brush, convert_color(col)); - if (r == 0) { - GdipFillRectangleI(gdip.memory, gdip.brush, x, y, w, h); - } else { - INT d = 2 * r; - GdipFillRectangleI(gdip.memory, gdip.brush, x + r, y, w - d, h); - GdipFillRectangleI(gdip.memory, gdip.brush, x, y + r, w, h - d); - GdipFillPieI(gdip.memory, gdip.brush, x, y, d, d, 180, 90); - GdipFillPieI(gdip.memory, gdip.brush, x + w - d, y, d, d, 270, 90); - GdipFillPieI(gdip.memory, gdip.brush, x + w - d, y + h - d, d, d, 0, 90); - GdipFillPieI(gdip.memory, gdip.brush, x, y + h - d, d, d, 90, 90); - } -} - -static void -nk_gdip_fill_triangle(short x0, short y0, short x1, - short y1, short x2, short y2, struct nk_color col) -{ - POINT points[] = { - { x0, y0 }, - { x1, y1 }, - { x2, y2 }, - }; - - GdipSetSolidFillColor(gdip.brush, convert_color(col)); - GdipFillPolygonI(gdip.memory, gdip.brush, points, 3, FillModeAlternate); -} - -static void -nk_gdip_stroke_triangle(short x0, short y0, short x1, - short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col) -{ - POINT points[] = { - { x0, y0 }, - { x1, y1 }, - { x2, y2 }, - { x0, y0 }, - }; - GdipSetPenWidth(gdip.pen, (REAL)line_thickness); - GdipSetPenColor(gdip.pen, convert_color(col)); - GdipDrawPolygonI(gdip.memory, gdip.pen, points, 4); -} - -static void -nk_gdip_fill_polygon(const struct nk_vec2i *pnts, int count, struct nk_color col) -{ - int i = 0; - #define MAX_POINTS 64 - POINT points[MAX_POINTS]; - GdipSetSolidFillColor(gdip.brush, convert_color(col)); - for (i = 0; i < count && i < MAX_POINTS; ++i) { - points[i].x = pnts[i].x; - points[i].y = pnts[i].y; - } - GdipFillPolygonI(gdip.memory, gdip.brush, points, i, FillModeAlternate); - #undef MAX_POINTS -} - -static void -nk_gdip_stroke_polygon(const struct nk_vec2i *pnts, int count, - unsigned short line_thickness, struct nk_color col) -{ - GdipSetPenWidth(gdip.pen, (REAL)line_thickness); - GdipSetPenColor(gdip.pen, convert_color(col)); - if (count > 0) { - int i; - for (i = 1; i < count; ++i) - GdipDrawLineI(gdip.memory, gdip.pen, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y); - GdipDrawLineI(gdip.memory, gdip.pen, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y); - } -} - -static void -nk_gdip_stroke_polyline(const struct nk_vec2i *pnts, - int count, unsigned short line_thickness, struct nk_color col) -{ - GdipSetPenWidth(gdip.pen, (REAL)line_thickness); - GdipSetPenColor(gdip.pen, convert_color(col)); - if (count > 0) { - int i; - for (i = 1; i < count; ++i) - GdipDrawLineI(gdip.memory, gdip.pen, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y); - } -} - -static void -nk_gdip_fill_circle(short x, short y, unsigned short w, - unsigned short h, struct nk_color col) -{ - GdipSetSolidFillColor(gdip.brush, convert_color(col)); - GdipFillEllipseI(gdip.memory, gdip.brush, x, y, w, h); -} - -static void -nk_gdip_stroke_circle(short x, short y, unsigned short w, - unsigned short h, unsigned short line_thickness, struct nk_color col) -{ - GdipSetPenWidth(gdip.pen, (REAL)line_thickness); - GdipSetPenColor(gdip.pen, convert_color(col)); - GdipDrawEllipseI(gdip.memory, gdip.pen, x, y, w, h); -} - -static void -nk_gdip_stroke_curve(struct nk_vec2i p1, - struct nk_vec2i p2, struct nk_vec2i p3, struct nk_vec2i p4, - unsigned short line_thickness, struct nk_color col) -{ - GdipSetPenWidth(gdip.pen, (REAL)line_thickness); - GdipSetPenColor(gdip.pen, convert_color(col)); - GdipDrawBezierI(gdip.memory, gdip.pen, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y, p4.x, p4.y); -} - -static void -nk_gdip_draw_text(short x, short y, unsigned short w, unsigned short h, - const char *text, int len, GdipFont *font, struct nk_color cbg, struct nk_color cfg) -{ - int wsize; - WCHAR* wstr; - RectF layout = { (FLOAT)x, (FLOAT)y, (FLOAT)w, (FLOAT)h }; - - if(!text || !font || !len) return; - - wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0); - wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t)); - MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize); - - GdipSetSolidFillColor(gdip.brush, convert_color(cbg)); - GdipFillRectangleI(gdip.memory, gdip.brush, x, y, w, h); - GdipSetSolidFillColor(gdip.brush, convert_color(cfg)); - GdipDrawString(gdip.memory, wstr, wsize, font->handle, &layout, gdip.format, gdip.brush); -} - -static void -nk_gdip_clear(struct nk_color col) -{ - GdipGraphicsClear(gdip.memory, convert_color(col)); -} - -static void -nk_gdip_blit(GpGraphics *graphics) -{ - GdipDrawImageI(graphics, gdip.bitmap, 0, 0); -} - -GdipFont* -nk_gdipfont_create(const char *name, int size) -{ - GdipFont *font = (GdipFont*)calloc(1, sizeof(GdipFont)); - GpFontFamily *family; - - int wsize = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0); - WCHAR* wname = (WCHAR*)_alloca((wsize + 1) * sizeof(wchar_t)); - MultiByteToWideChar(CP_UTF8, 0, name, -1, wname, wsize); - wname[wsize] = 0; - - GdipCreateFontFamilyFromName(wname, NULL, &family); - GdipCreateFont(family, (REAL)size, FontStyleRegular, UnitPixel, &font->handle); - GdipDeleteFontFamily(family); - - return font; -} - -static float -nk_gdipfont_get_text_width(nk_handle handle, float height, const char *text, int len) -{ - GdipFont *font = (GdipFont *)handle.ptr; - RectF layout = { 0.0f, 0.0f, 65536.0f, 65536.0f }; - RectF bbox; - int wsize; - WCHAR* wstr; - if (!font || !text) - return 0; - - (void)height; - wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0); - wstr = (WCHAR*)_alloca(wsize * sizeof(wchar_t)); - MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize); - - GdipMeasureString(gdip.memory, wstr, wsize, font->handle, &layout, gdip.format, &bbox, NULL, NULL); - return bbox.Width; -} - -void -nk_gdipfont_del(GdipFont *font) -{ - if(!font) return; - GdipDeleteFont(font->handle); - free(font); -} - -static void -nk_gdip_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) -{ - HGLOBAL mem; - SIZE_T size; - LPCWSTR wstr; - int utf8size; - char* utf8; - (void)usr; - - if (!IsClipboardFormatAvailable(CF_UNICODETEXT) && OpenClipboard(NULL)) - return; - - mem = (HGLOBAL)GetClipboardData(CF_UNICODETEXT); - if (!mem) { - CloseClipboard(); - return; - } - - size = GlobalSize(mem) - 1; - if (!size) { - CloseClipboard(); - return; - } - - wstr = (LPCWSTR)GlobalLock(mem); - if (!wstr) { - CloseClipboard(); - return; - } - - utf8size = WideCharToMultiByte(CP_UTF8, 0, wstr, (int)(size / sizeof(wchar_t)), NULL, 0, NULL, NULL); - if (!utf8size) { - GlobalUnlock(mem); - CloseClipboard(); - return; - } - - utf8 = (char*)malloc(utf8size); - if (!utf8) { - GlobalUnlock(mem); - CloseClipboard(); - return; - } - - WideCharToMultiByte(CP_UTF8, 0, wstr, (int)(size / sizeof(wchar_t)), utf8, utf8size, NULL, NULL); - nk_textedit_paste(edit, utf8, utf8size); - free(utf8); - GlobalUnlock(mem); - CloseClipboard(); -} - -static void -nk_gdip_clipbard_copy(nk_handle usr, const char *text, int len) -{ - HGLOBAL mem; - wchar_t* wstr; - int wsize; - (void)usr; - - if (!OpenClipboard(NULL)) - return; - - wsize = MultiByteToWideChar(CP_UTF8, 0, text, len, NULL, 0); - if (!wsize) { - CloseClipboard(); - return; - } - - mem = (HGLOBAL)GlobalAlloc(GMEM_MOVEABLE, (wsize + 1) * sizeof(wchar_t)); - if (!mem) { - CloseClipboard(); - return; - } - - wstr = (wchar_t*)GlobalLock(mem); - if (!wstr) { - GlobalFree(mem); - CloseClipboard(); - return; - } - - MultiByteToWideChar(CP_UTF8, 0, text, len, wstr, wsize); - wstr[wsize] = 0; - GlobalUnlock(mem); - if (!SetClipboardData(CF_UNICODETEXT, mem)) - GlobalFree(mem); - CloseClipboard(); -} - -NK_API struct nk_context* -nk_gdip_init(HWND hwnd, unsigned int width, unsigned int height) -{ - GdiplusStartupInput startup = { 1, NULL, FALSE, TRUE }; - GdiplusStartup(&gdip.token, &startup, NULL); - - GdipCreateFromHWND(hwnd, &gdip.window); - GdipCreateBitmapFromGraphics(width, height, gdip.window, &gdip.bitmap); - GdipGetImageGraphicsContext(gdip.bitmap, &gdip.memory); - GdipCreatePen1(0, 1.0f, UnitPixel, &gdip.pen); - GdipCreateSolidFill(0, &gdip.brush); - GdipStringFormatGetGenericTypographic(&gdip.format); - GdipSetStringFormatFlags(gdip.format, StringFormatFlagsNoFitBlackBox | - StringFormatFlagsMeasureTrailingSpaces | StringFormatFlagsNoWrap | - StringFormatFlagsNoClip); - - nk_init_default(&gdip.ctx, NULL); - gdip.ctx.clip.copy = nk_gdip_clipbard_copy; - gdip.ctx.clip.paste = nk_gdip_clipbard_paste; - return &gdip.ctx; -} - -NK_API void -nk_gdip_set_font(GdipFont *gdipfont) -{ - struct nk_user_font *font = &gdipfont->nk; - font->userdata = nk_handle_ptr(gdipfont); - GdipGetFontSize(gdipfont->handle, &font->height); - font->width = nk_gdipfont_get_text_width; - nk_style_set_font(&gdip.ctx, font); -} - -NK_API int -nk_gdip_handle_event(HWND wnd, UINT msg, WPARAM wparam, LPARAM lparam) -{ - switch (msg) - { - case WM_SIZE: - if (gdip.window) - { - unsigned int width = LOWORD(lparam); - unsigned int height = HIWORD(lparam); - GdipDeleteGraphics(gdip.window); - GdipDeleteGraphics(gdip.memory); - GdipDisposeImage(gdip.bitmap); - GdipCreateFromHWND(wnd, &gdip.window); - GdipCreateBitmapFromGraphics(width, height, gdip.window, &gdip.bitmap); - GdipGetImageGraphicsContext(gdip.bitmap, &gdip.memory); - } - break; - - case WM_PAINT: - { - PAINTSTRUCT paint; - HDC dc = BeginPaint(wnd, &paint); - GpGraphics *graphics; - GdipCreateFromHDC(dc, &graphics); - nk_gdip_blit(graphics); - GdipDeleteGraphics(graphics); - EndPaint(wnd, &paint); - return 1; - } - - case WM_KEYDOWN: - case WM_KEYUP: - case WM_SYSKEYDOWN: - case WM_SYSKEYUP: - { - int down = !((lparam >> 31) & 1); - int ctrl = GetKeyState(VK_CONTROL) & (1 << 15); - - switch (wparam) - { - case VK_SHIFT: - case VK_LSHIFT: - case VK_RSHIFT: - nk_input_key(&gdip.ctx, NK_KEY_SHIFT, down); - return 1; - - case VK_DELETE: - nk_input_key(&gdip.ctx, NK_KEY_DEL, down); - return 1; - - case VK_RETURN: - nk_input_key(&gdip.ctx, NK_KEY_ENTER, down); - return 1; - - case VK_TAB: - nk_input_key(&gdip.ctx, NK_KEY_TAB, down); - return 1; - - case VK_LEFT: - if (ctrl) - nk_input_key(&gdip.ctx, NK_KEY_TEXT_WORD_LEFT, down); - else - nk_input_key(&gdip.ctx, NK_KEY_LEFT, down); - return 1; - - case VK_RIGHT: - if (ctrl) - nk_input_key(&gdip.ctx, NK_KEY_TEXT_WORD_RIGHT, down); - else - nk_input_key(&gdip.ctx, NK_KEY_RIGHT, down); - return 1; - - case VK_BACK: - nk_input_key(&gdip.ctx, NK_KEY_BACKSPACE, down); - return 1; - - case VK_HOME: - nk_input_key(&gdip.ctx, NK_KEY_TEXT_START, down); - nk_input_key(&gdip.ctx, NK_KEY_SCROLL_START, down); - return 1; - - case VK_END: - nk_input_key(&gdip.ctx, NK_KEY_TEXT_END, down); - nk_input_key(&gdip.ctx, NK_KEY_SCROLL_END, down); - return 1; - - case VK_NEXT: - nk_input_key(&gdip.ctx, NK_KEY_SCROLL_DOWN, down); - return 1; - - case VK_PRIOR: - nk_input_key(&gdip.ctx, NK_KEY_SCROLL_UP, down); - return 1; - - case 'C': - if (ctrl) { - nk_input_key(&gdip.ctx, NK_KEY_COPY, down); - return 1; - } - break; - - case 'V': - if (ctrl) { - nk_input_key(&gdip.ctx, NK_KEY_PASTE, down); - return 1; - } - break; - - case 'X': - if (ctrl) { - nk_input_key(&gdip.ctx, NK_KEY_CUT, down); - return 1; - } - break; - - case 'Z': - if (ctrl) { - nk_input_key(&gdip.ctx, NK_KEY_TEXT_UNDO, down); - return 1; - } - break; - - case 'R': - if (ctrl) { - nk_input_key(&gdip.ctx, NK_KEY_TEXT_REDO, down); - return 1; - } - break; - } - return 0; - } - - case WM_CHAR: - if (wparam >= 32) - { - nk_input_unicode(&gdip.ctx, (nk_rune)wparam); - return 1; - } - break; - - case WM_LBUTTONDOWN: - nk_input_button(&gdip.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1); - SetCapture(wnd); - return 1; - - case WM_LBUTTONUP: - nk_input_button(&gdip.ctx, NK_BUTTON_LEFT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0); - ReleaseCapture(); - return 1; - - case WM_RBUTTONDOWN: - nk_input_button(&gdip.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 1); - SetCapture(wnd); - return 1; - - case WM_RBUTTONUP: - nk_input_button(&gdip.ctx, NK_BUTTON_RIGHT, (short)LOWORD(lparam), (short)HIWORD(lparam), 0); - ReleaseCapture(); - return 1; - - case WM_MBUTTONDOWN: - nk_input_button(&gdip.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 1); - SetCapture(wnd); - return 1; - - case WM_MBUTTONUP: - nk_input_button(&gdip.ctx, NK_BUTTON_MIDDLE, (short)LOWORD(lparam), (short)HIWORD(lparam), 0); - ReleaseCapture(); - return 1; - - case WM_MOUSEWHEEL: - nk_input_scroll(&gdip.ctx, (float)(short)HIWORD(wparam) / WHEEL_DELTA); - return 1; - - case WM_MOUSEMOVE: - nk_input_motion(&gdip.ctx, (short)LOWORD(lparam), (short)HIWORD(lparam)); - return 1; - } - - return 0; -} - -NK_API void -nk_gdip_shutdown(void) -{ - GdipDeleteGraphics(gdip.window); - GdipDeleteGraphics(gdip.memory); - GdipDisposeImage(gdip.bitmap); - GdipDeletePen(gdip.pen); - GdipDeleteBrush(gdip.brush); - GdipDeleteStringFormat(gdip.format); - GdiplusShutdown(gdip.token); - - nk_free(&gdip.ctx); -} - -NK_API void -nk_gdip_render(enum nk_anti_aliasing AA, struct nk_color clear) -{ - const struct nk_command *cmd; - - GdipSetTextRenderingHint(gdip.memory, AA != NK_ANTI_ALIASING_OFF ? - TextRenderingHintClearTypeGridFit : TextRenderingHintSingleBitPerPixelGridFit); - GdipSetSmoothingMode(gdip.memory, AA != NK_ANTI_ALIASING_OFF ? - SmoothingModeHighQuality : SmoothingModeNone); - nk_gdip_clear(clear); - - nk_foreach(cmd, &gdip.ctx) - { - switch (cmd->type) { - case NK_COMMAND_NOP: break; - case NK_COMMAND_SCISSOR: { - const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd; - nk_gdip_scissor(s->x, s->y, s->w, s->h); - } break; - case NK_COMMAND_LINE: { - const struct nk_command_line *l = (const struct nk_command_line *)cmd; - nk_gdip_stroke_line(l->begin.x, l->begin.y, l->end.x, - l->end.y, l->line_thickness, l->color); - } break; - case NK_COMMAND_RECT: { - const struct nk_command_rect *r = (const struct nk_command_rect *)cmd; - nk_gdip_stroke_rect(r->x, r->y, r->w, r->h, - (unsigned short)r->rounding, r->line_thickness, r->color); - } break; - case NK_COMMAND_RECT_FILLED: { - const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd; - nk_gdip_fill_rect(r->x, r->y, r->w, r->h, - (unsigned short)r->rounding, r->color); - } break; - case NK_COMMAND_CIRCLE: { - const struct nk_command_circle *c = (const struct nk_command_circle *)cmd; - nk_gdip_stroke_circle(c->x, c->y, c->w, c->h, c->line_thickness, c->color); - } break; - case NK_COMMAND_CIRCLE_FILLED: { - const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; - nk_gdip_fill_circle(c->x, c->y, c->w, c->h, c->color); - } break; - case NK_COMMAND_TRIANGLE: { - const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd; - nk_gdip_stroke_triangle(t->a.x, t->a.y, t->b.x, t->b.y, - t->c.x, t->c.y, t->line_thickness, t->color); - } break; - case NK_COMMAND_TRIANGLE_FILLED: { - const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd; - nk_gdip_fill_triangle(t->a.x, t->a.y, t->b.x, t->b.y, - t->c.x, t->c.y, t->color); - } break; - case NK_COMMAND_POLYGON: { - const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd; - nk_gdip_stroke_polygon(p->points, p->point_count, p->line_thickness,p->color); - } break; - case NK_COMMAND_POLYGON_FILLED: { - const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd; - nk_gdip_fill_polygon(p->points, p->point_count, p->color); - } break; - case NK_COMMAND_POLYLINE: { - const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd; - nk_gdip_stroke_polyline(p->points, p->point_count, p->line_thickness, p->color); - } break; - case NK_COMMAND_TEXT: { - const struct nk_command_text *t = (const struct nk_command_text*)cmd; - nk_gdip_draw_text(t->x, t->y, t->w, t->h, - (const char*)t->string, t->length, - (GdipFont*)t->font->userdata.ptr, - t->background, t->foreground); - } break; - case NK_COMMAND_CURVE: { - const struct nk_command_curve *q = (const struct nk_command_curve *)cmd; - nk_gdip_stroke_curve(q->begin, q->ctrl[0], q->ctrl[1], - q->end, q->line_thickness, q->color); - } break; - case NK_COMMAND_RECT_MULTI_COLOR: - case NK_COMMAND_IMAGE: - case NK_COMMAND_ARC: - case NK_COMMAND_ARC_FILLED: - default: break; - } - } - nk_gdip_blit(gdip.window); - nk_clear(&gdip.ctx); -} - -#endif - diff --git a/deps/nuklear/demo/glfw_opengl2/main.c b/deps/nuklear/demo/glfw_opengl2/main.c deleted file mode 100644 index 1c0f284f..00000000 --- a/deps/nuklear/demo/glfw_opengl2/main.c +++ /dev/null @@ -1,165 +0,0 @@ -/* nuklear - v1.17 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#define NK_GLFW_GL2_IMPLEMENTATION -#include "../../nuklear.h" -#include "nuklear_glfw_gl2.h" - -#define WINDOW_WIDTH 1200 -#define WINDOW_HEIGHT 800 - -#define MAX_VERTEX_BUFFER 512 * 1024 -#define MAX_ELEMENT_BUFFER 128 * 1024 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* This are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the include - * and the corresponding function. */ -/*#include "../style.c"*/ -/*#include "../calculator.c"*/ -/*#include "../overview.c"*/ -/*#include "../node_editor.c"*/ - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -static void error_callback(int e, const char *d) -{printf("Error %d: %s\n", e, d);} - -int main(void) -{ - /* Platform */ - static GLFWwindow *win; - int width = 0, height = 0; - struct nk_context *ctx; - struct nk_color background; - - /* GLFW */ - glfwSetErrorCallback(error_callback); - if (!glfwInit()) { - fprintf(stdout, "[GFLW] failed to init!\n"); - exit(1); - } - win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL); - glfwMakeContextCurrent(win); - glfwGetWindowSize(win, &width, &height); - - /* GUI */ - ctx = nk_glfw3_init(win, NK_GLFW3_INSTALL_CALLBACKS); - /* Load Fonts: if none of these are loaded a default font will be used */ - /* Load Cursor: if you uncomment cursor loading please hide the cursor */ - {struct nk_font_atlas *atlas; - nk_glfw3_font_stash_begin(&atlas); - /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/ - /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 14, 0);*/ - /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/ - /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/ - /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/ - /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/ - nk_glfw3_font_stash_end(); - /*nk_style_load_all_cursors(ctx, atlas->cursors);*/ - /*nk_style_set_font(ctx, &droid->handle);*/} - - /* style.c */ - /*set_style(ctx, THEME_WHITE);*/ - /*set_style(ctx, THEME_RED);*/ - /*set_style(ctx, THEME_BLUE);*/ - /*set_style(ctx, THEME_DARK);*/ - - background = nk_rgb(28,48,62); - while (!glfwWindowShouldClose(win)) - { - /* Input */ - glfwPollEvents(); - nk_glfw3_new_frame(); - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - - nk_layout_row_dynamic(ctx, 25, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - - nk_layout_row_dynamic(ctx, 20, 1); - nk_label(ctx, "background:", NK_TEXT_LEFT); - nk_layout_row_dynamic(ctx, 25, 1); - if (nk_combo_begin_color(ctx, background, nk_vec2(nk_widget_width(ctx),400))) { - nk_layout_row_dynamic(ctx, 120, 1); - background = nk_color_picker(ctx, background, NK_RGBA); - nk_layout_row_dynamic(ctx, 25, 1); - background.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, background.r, 255, 1,1); - background.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, background.g, 255, 1,1); - background.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, background.b, 255, 1,1); - background.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, background.a, 255, 1,1); - nk_combo_end(ctx); - } - } - nk_end(ctx); - - /* -------------- EXAMPLES ---------------- */ - /*calculator(ctx);*/ - /*overview(ctx);*/ - /*node_editor(ctx);*/ - /* ----------------------------------------- */ - - /* Draw */ - {float bg[4]; - nk_color_fv(bg, background); - glfwGetWindowSize(win, &width, &height); - glViewport(0, 0, width, height); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(bg[0], bg[1], bg[2], bg[3]); - /* IMPORTANT: `nk_glfw_render` modifies some global OpenGL state - * with blending, scissor, face culling and depth test and defaults everything - * back into a default state. Make sure to either save and restore or - * reset your own state after drawing rendering the UI. */ - nk_glfw3_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER); - glfwSwapBuffers(win);} - } - nk_glfw3_shutdown(); - glfwTerminate(); - return 0; -} - diff --git a/deps/nuklear/demo/glfw_opengl2/nuklear_glfw_gl2.h b/deps/nuklear/demo/glfw_opengl2/nuklear_glfw_gl2.h deleted file mode 100644 index a2a615c6..00000000 --- a/deps/nuklear/demo/glfw_opengl2/nuklear_glfw_gl2.h +++ /dev/null @@ -1,350 +0,0 @@ -/* - * Nuklear - v1.17 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_GLFW_GL2_H_ -#define NK_GLFW_GL2_H_ - -#include - -enum nk_glfw_init_state{ - NK_GLFW3_DEFAULT = 0, - NK_GLFW3_INSTALL_CALLBACKS -}; -NK_API struct nk_context* nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state); -NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas); -NK_API void nk_glfw3_font_stash_end(void); - -NK_API void nk_glfw3_new_frame(void); -NK_API void nk_glfw3_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer); -NK_API void nk_glfw3_shutdown(void); - -NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint); -NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff); - -#endif - -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_GLFW_GL2_IMPLEMENTATION - -#ifndef NK_GLFW_TEXT_MAX -#define NK_GLFW_TEXT_MAX 256 -#endif - -struct nk_glfw_device { - struct nk_buffer cmds; - struct nk_draw_null_texture null; - GLuint font_tex; -}; - -struct nk_glfw_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -static struct nk_glfw { - GLFWwindow *win; - int width, height; - int display_width, display_height; - struct nk_glfw_device ogl; - struct nk_context ctx; - struct nk_font_atlas atlas; - struct nk_vec2 fb_scale; - unsigned int text[NK_GLFW_TEXT_MAX]; - int text_len; - float scroll; -} glfw; - -NK_INTERN void -nk_glfw3_device_upload_atlas(const void *image, int width, int height) -{ - struct nk_glfw_device *dev = &glfw.ogl; - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - -NK_API void -nk_glfw3_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) -{ - /* setup global state */ - struct nk_glfw_device *dev = &glfw.ogl; - glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - /* setup viewport/project */ - glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0.0f, glfw.width, glfw.height, 0.0f, -1.0f, 1.0f); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - { - GLsizei vs = sizeof(struct nk_glfw_vertex); - size_t vp = offsetof(struct nk_glfw_vertex, position); - size_t vt = offsetof(struct nk_glfw_vertex, uv); - size_t vc = offsetof(struct nk_glfw_vertex, col); - - /* convert from command queue into draw list and draw to screen */ - const struct nk_draw_command *cmd; - const nk_draw_index *offset = NULL; - struct nk_buffer vbuf, ebuf; - - /* fill convert configuration */ - struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - NK_MEMSET(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_glfw_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex); - config.null = dev->null; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - - /* convert shapes into vertexes */ - nk_buffer_init_default(&vbuf); - nk_buffer_init_default(&ebuf); - nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config); - - /* setup vertex buffer pointer */ - {const void *vertices = nk_buffer_memory_const(&vbuf); - glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp)); - glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt)); - glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));} - - /* iterate over and execute each draw command */ - offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf); - nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds) - { - if (!cmd->elem_count) continue; - glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor( - (GLint)(cmd->clip_rect.x * glfw.fb_scale.x), - (GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y), - (GLint)(cmd->clip_rect.w * glfw.fb_scale.x), - (GLint)(cmd->clip_rect.h * glfw.fb_scale.y)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); - offset += cmd->elem_count; - } - nk_clear(&glfw.ctx); - nk_buffer_free(&vbuf); - nk_buffer_free(&ebuf); - } - - /* default OpenGL state */ - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, 0); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glPopAttrib(); -} - -NK_API void -nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint) -{ - (void)win; - if (glfw.text_len < NK_GLFW_TEXT_MAX) - glfw.text[glfw.text_len++] = codepoint; -} - -NK_API void -nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff) -{ - (void)win; (void)xoff; - glfw.scroll += (float)yoff; -} - -NK_INTERN void -nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) -{ - const char *text = glfwGetClipboardString(glfw.win); - if (text) nk_textedit_paste(edit, text, nk_strlen(text)); - (void)usr; -} - -NK_INTERN void -nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len) -{ - char *str = 0; - (void)usr; - if (!len) return; - str = (char*)malloc((size_t)len+1); - if (!str) return; - memcpy(str, text, (size_t)len); - str[len] = '\0'; - glfwSetClipboardString(glfw.win, str); - free(str); -} - -NK_API struct nk_context* -nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state) -{ - glfw.win = win; - if (init_state == NK_GLFW3_INSTALL_CALLBACKS) { - glfwSetScrollCallback(win, nk_gflw3_scroll_callback); - glfwSetCharCallback(win, nk_glfw3_char_callback); - } - - nk_init_default(&glfw.ctx, 0); - glfw.ctx.clip.copy = nk_glfw3_clipbard_copy; - glfw.ctx.clip.paste = nk_glfw3_clipbard_paste; - glfw.ctx.clip.userdata = nk_handle_ptr(0); - nk_buffer_init_default(&glfw.ogl.cmds); - return &glfw.ctx; -} - -NK_API void -nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas) -{ - nk_font_atlas_init_default(&glfw.atlas); - nk_font_atlas_begin(&glfw.atlas); - *atlas = &glfw.atlas; -} - -NK_API void -nk_glfw3_font_stash_end(void) -{ - const void *image; int w, h; - image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - nk_glfw3_device_upload_atlas(image, w, h); - nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null); - if (glfw.atlas.default_font) - nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle); -} - -NK_API void -nk_glfw3_new_frame(void) -{ - int i; - double x, y; - struct nk_context *ctx = &glfw.ctx; - struct GLFWwindow *win = glfw.win; - - glfwGetWindowSize(win, &glfw.width, &glfw.height); - glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height); - glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width; - glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height; - - nk_input_begin(ctx); - for (i = 0; i < glfw.text_len; ++i) - nk_input_unicode(ctx, glfw.text[i]); - - /* optional grabbing behavior */ - if (ctx->input.mouse.grab) - glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - else if (ctx->input.mouse.ungrab) - glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL); - - nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS|| - glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS); - - if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || - glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) { - nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS); - } else { - nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_COPY, 0); - nk_input_key(ctx, NK_KEY_PASTE, 0); - nk_input_key(ctx, NK_KEY_CUT, 0); - nk_input_key(ctx, NK_KEY_SHIFT, 0); - } - - glfwGetCursorPos(win, &x, &y); - nk_input_motion(ctx, (int)x, (int)y); - if (ctx->input.mouse.grabbed) { - glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y); - ctx->input.mouse.pos.x = ctx->input.mouse.prev.x; - ctx->input.mouse.pos.y = ctx->input.mouse.prev.y; - } - - nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS); - nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS); - nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS); - nk_input_scroll(ctx, glfw.scroll); - nk_input_end(&glfw.ctx); - glfw.text_len = 0; - glfw.scroll = 0; -} - -NK_API -void nk_glfw3_shutdown(void) -{ - struct nk_glfw_device *dev = &glfw.ogl; - nk_font_atlas_clear(&glfw.atlas); - nk_free(&glfw.ctx); - glDeleteTextures(1, &dev->font_tex); - nk_buffer_free(&dev->cmds); - memset(&glfw, 0, sizeof(glfw)); -} - -#endif diff --git a/deps/nuklear/demo/glfw_opengl3/main.c b/deps/nuklear/demo/glfw_opengl3/main.c deleted file mode 100644 index d74ee562..00000000 --- a/deps/nuklear/demo/glfw_opengl3/main.c +++ /dev/null @@ -1,180 +0,0 @@ -/* nuklear - v1.17 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#define NK_GLFW_GL3_IMPLEMENTATION -#include "../../nuklear.h" -#include "nuklear_glfw_gl3.h" - -#define WINDOW_WIDTH 1200 -#define WINDOW_HEIGHT 800 - -#define MAX_VERTEX_BUFFER 512 * 1024 -#define MAX_ELEMENT_BUFFER 128 * 1024 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* This are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the include - * and the corresponding function. */ -/*#include "../style.c"*/ -/*#include "../calculator.c"*/ -/*#include "../overview.c"*/ -/*#include "../node_editor.c"*/ - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -static void error_callback(int e, const char *d) -{printf("Error %d: %s\n", e, d);} - -int main(void) -{ - /* Platform */ - static GLFWwindow *win; - int width = 0, height = 0; - struct nk_context *ctx; - struct nk_color background; - - /* GLFW */ - glfwSetErrorCallback(error_callback); - if (!glfwInit()) { - fprintf(stdout, "[GFLW] failed to init!\n"); - exit(1); - } - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#ifdef __APPLE__ - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); -#endif - win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL); - glfwMakeContextCurrent(win); - glfwGetWindowSize(win, &width, &height); - - /* OpenGL */ - glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); - glewExperimental = 1; - if (glewInit() != GLEW_OK) { - fprintf(stderr, "Failed to setup GLEW\n"); - exit(1); - } - - ctx = nk_glfw3_init(win, NK_GLFW3_INSTALL_CALLBACKS); - /* Load Fonts: if none of these are loaded a default font will be used */ - /* Load Cursor: if you uncomment cursor loading please hide the cursor */ - {struct nk_font_atlas *atlas; - nk_glfw3_font_stash_begin(&atlas); - /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/ - /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 14, 0);*/ - /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/ - /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/ - /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/ - /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/ - nk_glfw3_font_stash_end(); - /*nk_style_load_all_cursors(ctx, atlas->cursors);*/ - /*nk_style_set_font(ctx, &droid->handle);*/} - - /* style.c */ - /*set_style(ctx, THEME_WHITE);*/ - /*set_style(ctx, THEME_RED);*/ - /*set_style(ctx, THEME_BLUE);*/ - /*set_style(ctx, THEME_DARK);*/ - - background = nk_rgb(28,48,62); - while (!glfwWindowShouldClose(win)) - { - /* Input */ - glfwPollEvents(); - nk_glfw3_new_frame(); - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 230, 250), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - - nk_layout_row_dynamic(ctx, 25, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - - nk_layout_row_dynamic(ctx, 20, 1); - nk_label(ctx, "background:", NK_TEXT_LEFT); - nk_layout_row_dynamic(ctx, 25, 1); - if (nk_combo_begin_color(ctx, background, nk_vec2(nk_widget_width(ctx),400))) { - nk_layout_row_dynamic(ctx, 120, 1); - background = nk_color_picker(ctx, background, NK_RGBA); - nk_layout_row_dynamic(ctx, 25, 1); - background.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, background.r, 255, 1,1); - background.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, background.g, 255, 1,1); - background.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, background.b, 255, 1,1); - background.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, background.a, 255, 1,1); - nk_combo_end(ctx); - } - } - nk_end(ctx); - - /* -------------- EXAMPLES ---------------- */ - /*calculator(ctx);*/ - /*overview(ctx);*/ - /*node_editor(ctx);*/ - /* ----------------------------------------- */ - - /* Draw */ - {float bg[4]; - nk_color_fv(bg, background); - glfwGetWindowSize(win, &width, &height); - glViewport(0, 0, width, height); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(bg[0], bg[1], bg[2], bg[3]); - /* IMPORTANT: `nk_glfw_render` modifies some global OpenGL state - * with blending, scissor, face culling, depth test and viewport and - * defaults everything back into a default state. - * Make sure to either a.) save and restore or b.) reset your own state after - * rendering the UI. */ - nk_glfw3_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER); - glfwSwapBuffers(win);} - } - nk_glfw3_shutdown(); - glfwTerminate(); - return 0; -} - diff --git a/deps/nuklear/demo/glfw_opengl3/nuklear_glfw_gl3.h b/deps/nuklear/demo/glfw_opengl3/nuklear_glfw_gl3.h deleted file mode 100644 index d0eea353..00000000 --- a/deps/nuklear/demo/glfw_opengl3/nuklear_glfw_gl3.h +++ /dev/null @@ -1,456 +0,0 @@ -/* - * Nuklear - v1.17 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_GLFW_GL3_H_ -#define NK_GLFW_GL3_H_ - -#include - -enum nk_glfw_init_state{ - NK_GLFW3_DEFAULT=0, - NK_GLFW3_INSTALL_CALLBACKS -}; - -NK_API struct nk_context* nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state); -NK_API void nk_glfw3_shutdown(void); -NK_API void nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas); -NK_API void nk_glfw3_font_stash_end(void); -NK_API void nk_glfw3_new_frame(void); -NK_API void nk_glfw3_render(enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer); - -NK_API void nk_glfw3_device_destroy(void); -NK_API void nk_glfw3_device_create(void); - -NK_API void nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint); -NK_API void nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff); - -#endif -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_GLFW_GL3_IMPLEMENTATION - -#ifndef NK_GLFW_TEXT_MAX -#define NK_GLFW_TEXT_MAX 256 -#endif - -struct nk_glfw_device { - struct nk_buffer cmds; - struct nk_draw_null_texture null; - GLuint vbo, vao, ebo; - GLuint prog; - GLuint vert_shdr; - GLuint frag_shdr; - GLint attrib_pos; - GLint attrib_uv; - GLint attrib_col; - GLint uniform_tex; - GLint uniform_proj; - GLuint font_tex; -}; - -struct nk_glfw_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -static struct nk_glfw { - GLFWwindow *win; - int width, height; - int display_width, display_height; - struct nk_glfw_device ogl; - struct nk_context ctx; - struct nk_font_atlas atlas; - struct nk_vec2 fb_scale; - unsigned int text[NK_GLFW_TEXT_MAX]; - int text_len; - float scroll; -} glfw; - -#ifdef __APPLE__ - #define NK_SHADER_VERSION "#version 150\n" -#else - #define NK_SHADER_VERSION "#version 300 es\n" -#endif - -NK_API void -nk_glfw3_device_create(void) -{ - GLint status; - static const GLchar *vertex_shader = - NK_SHADER_VERSION - "uniform mat4 ProjMtx;\n" - "in vec2 Position;\n" - "in vec2 TexCoord;\n" - "in vec4 Color;\n" - "out vec2 Frag_UV;\n" - "out vec4 Frag_Color;\n" - "void main() {\n" - " Frag_UV = TexCoord;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" - "}\n"; - static const GLchar *fragment_shader = - NK_SHADER_VERSION - "precision mediump float;\n" - "uniform sampler2D Texture;\n" - "in vec2 Frag_UV;\n" - "in vec4 Frag_Color;\n" - "out vec4 Out_Color;\n" - "void main(){\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" - "}\n"; - - struct nk_glfw_device *dev = &glfw.ogl; - nk_buffer_init_default(&dev->cmds); - dev->prog = glCreateProgram(); - dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); - dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); - glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); - glCompileShader(dev->vert_shdr); - glCompileShader(dev->frag_shdr); - glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glAttachShader(dev->prog, dev->vert_shdr); - glAttachShader(dev->prog, dev->frag_shdr); - glLinkProgram(dev->prog); - glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); - assert(status == GL_TRUE); - - dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); - dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); - dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); - dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); - dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); - - { - /* buffer setup */ - GLsizei vs = sizeof(struct nk_glfw_vertex); - size_t vp = offsetof(struct nk_glfw_vertex, position); - size_t vt = offsetof(struct nk_glfw_vertex, uv); - size_t vc = offsetof(struct nk_glfw_vertex, col); - - glGenBuffers(1, &dev->vbo); - glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); - - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); - } - - glBindTexture(GL_TEXTURE_2D, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); -} - -NK_INTERN void -nk_glfw3_device_upload_atlas(const void *image, int width, int height) -{ - struct nk_glfw_device *dev = &glfw.ogl; - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - -NK_API void -nk_glfw3_device_destroy(void) -{ - struct nk_glfw_device *dev = &glfw.ogl; - glDetachShader(dev->prog, dev->vert_shdr); - glDetachShader(dev->prog, dev->frag_shdr); - glDeleteShader(dev->vert_shdr); - glDeleteShader(dev->frag_shdr); - glDeleteProgram(dev->prog); - glDeleteTextures(1, &dev->font_tex); - glDeleteBuffers(1, &dev->vbo); - glDeleteBuffers(1, &dev->ebo); - nk_buffer_free(&dev->cmds); -} - -NK_API void -nk_glfw3_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) -{ - struct nk_glfw_device *dev = &glfw.ogl; - GLfloat ortho[4][4] = { - {2.0f, 0.0f, 0.0f, 0.0f}, - {0.0f,-2.0f, 0.0f, 0.0f}, - {0.0f, 0.0f,-1.0f, 0.0f}, - {-1.0f,1.0f, 0.0f, 1.0f}, - }; - ortho[0][0] /= (GLfloat)glfw.width; - ortho[1][1] /= (GLfloat)glfw.height; - - /* setup global state */ - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - /* setup program */ - glUseProgram(dev->prog); - glUniform1i(dev->uniform_tex, 0); - glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); - glViewport(0,0,(GLsizei)glfw.display_width,(GLsizei)glfw.display_height); - { - /* convert from command queue into draw list and draw to screen */ - const struct nk_draw_command *cmd; - void *vertices, *elements; - const nk_draw_index *offset = NULL; - - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW); - - /* load draw vertices & elements directly into vertex + element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); - { - /* fill convert configuration */ - struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - NK_MEMSET(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_glfw_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex); - config.null = dev->null; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - - /* setup buffers to load vertices and elements */ - {struct nk_buffer vbuf, ebuf; - nk_buffer_init_fixed(&vbuf, vertices, (size_t)max_vertex_buffer); - nk_buffer_init_fixed(&ebuf, elements, (size_t)max_element_buffer); - nk_convert(&glfw.ctx, &dev->cmds, &vbuf, &ebuf, &config);} - } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - - /* iterate over and execute each draw command */ - nk_draw_foreach(cmd, &glfw.ctx, &dev->cmds) - { - if (!cmd->elem_count) continue; - glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor( - (GLint)(cmd->clip_rect.x * glfw.fb_scale.x), - (GLint)((glfw.height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * glfw.fb_scale.y), - (GLint)(cmd->clip_rect.w * glfw.fb_scale.x), - (GLint)(cmd->clip_rect.h * glfw.fb_scale.y)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); - offset += cmd->elem_count; - } - nk_clear(&glfw.ctx); - } - - /* default OpenGL state */ - glUseProgram(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); -} - -NK_API void -nk_glfw3_char_callback(GLFWwindow *win, unsigned int codepoint) -{ - (void)win; - if (glfw.text_len < NK_GLFW_TEXT_MAX) - glfw.text[glfw.text_len++] = codepoint; -} - -NK_API void -nk_gflw3_scroll_callback(GLFWwindow *win, double xoff, double yoff) -{ - (void)win; (void)xoff; - glfw.scroll += (float)yoff; -} - -NK_INTERN void -nk_glfw3_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) -{ - const char *text = glfwGetClipboardString(glfw.win); - if (text) nk_textedit_paste(edit, text, nk_strlen(text)); - (void)usr; -} - -NK_INTERN void -nk_glfw3_clipbard_copy(nk_handle usr, const char *text, int len) -{ - char *str = 0; - (void)usr; - if (!len) return; - str = (char*)malloc((size_t)len+1); - if (!str) return; - memcpy(str, text, (size_t)len); - str[len] = '\0'; - glfwSetClipboardString(glfw.win, str); - free(str); -} - -NK_API struct nk_context* -nk_glfw3_init(GLFWwindow *win, enum nk_glfw_init_state init_state) -{ - glfw.win = win; - if (init_state == NK_GLFW3_INSTALL_CALLBACKS) { - glfwSetScrollCallback(win, nk_gflw3_scroll_callback); - glfwSetCharCallback(win, nk_glfw3_char_callback); - } - - nk_init_default(&glfw.ctx, 0); - glfw.ctx.clip.copy = nk_glfw3_clipbard_copy; - glfw.ctx.clip.paste = nk_glfw3_clipbard_paste; - glfw.ctx.clip.userdata = nk_handle_ptr(0); - nk_glfw3_device_create(); - return &glfw.ctx; -} - -NK_API void -nk_glfw3_font_stash_begin(struct nk_font_atlas **atlas) -{ - nk_font_atlas_init_default(&glfw.atlas); - nk_font_atlas_begin(&glfw.atlas); - *atlas = &glfw.atlas; -} - -NK_API void -nk_glfw3_font_stash_end(void) -{ - const void *image; int w, h; - image = nk_font_atlas_bake(&glfw.atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - nk_glfw3_device_upload_atlas(image, w, h); - nk_font_atlas_end(&glfw.atlas, nk_handle_id((int)glfw.ogl.font_tex), &glfw.ogl.null); - if (glfw.atlas.default_font) - nk_style_set_font(&glfw.ctx, &glfw.atlas.default_font->handle); -} - -NK_API void -nk_glfw3_new_frame(void) -{ - int i; - double x, y; - struct nk_context *ctx = &glfw.ctx; - struct GLFWwindow *win = glfw.win; - - glfwGetWindowSize(win, &glfw.width, &glfw.height); - glfwGetFramebufferSize(win, &glfw.display_width, &glfw.display_height); - glfw.fb_scale.x = (float)glfw.display_width/(float)glfw.width; - glfw.fb_scale.y = (float)glfw.display_height/(float)glfw.height; - - nk_input_begin(ctx); - for (i = 0; i < glfw.text_len; ++i) - nk_input_unicode(ctx, glfw.text[i]); - - /* optional grabbing behavior */ - if (ctx->input.mouse.grab) - glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_HIDDEN); - else if (ctx->input.mouse.ungrab) - glfwSetInputMode(glfw.win, GLFW_CURSOR, GLFW_CURSOR_NORMAL); - - nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SCROLL_START, glfwGetKey(win, GLFW_KEY_HOME) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SCROLL_END, glfwGetKey(win, GLFW_KEY_END) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SCROLL_DOWN, glfwGetKey(win, GLFW_KEY_PAGE_DOWN) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SCROLL_UP, glfwGetKey(win, GLFW_KEY_PAGE_UP) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SHIFT, glfwGetKey(win, GLFW_KEY_LEFT_SHIFT) == GLFW_PRESS|| - glfwGetKey(win, GLFW_KEY_RIGHT_SHIFT) == GLFW_PRESS); - - if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || - glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) { - nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_V) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_UNDO, glfwGetKey(win, GLFW_KEY_Z) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_REDO, glfwGetKey(win, GLFW_KEY_R) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_LINE_START, glfwGetKey(win, GLFW_KEY_B) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TEXT_LINE_END, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS); - } else { - nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_COPY, 0); - nk_input_key(ctx, NK_KEY_PASTE, 0); - nk_input_key(ctx, NK_KEY_CUT, 0); - nk_input_key(ctx, NK_KEY_SHIFT, 0); - } - - glfwGetCursorPos(win, &x, &y); - nk_input_motion(ctx, (int)x, (int)y); - if (ctx->input.mouse.grabbed) { - glfwSetCursorPos(glfw.win, ctx->input.mouse.prev.x, ctx->input.mouse.prev.y); - ctx->input.mouse.pos.x = ctx->input.mouse.prev.x; - ctx->input.mouse.pos.y = ctx->input.mouse.prev.y; - } - - nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS); - nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS); - nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS); - nk_input_scroll(ctx, glfw.scroll); - nk_input_end(&glfw.ctx); - glfw.text_len = 0; - glfw.scroll = 0; -} - -NK_API -void nk_glfw3_shutdown(void) -{ - nk_font_atlas_clear(&glfw.atlas); - nk_free(&glfw.ctx); - nk_glfw3_device_destroy(); - memset(&glfw, 0, sizeof(glfw)); -} - -#endif diff --git a/deps/nuklear/demo/node_editor.c b/deps/nuklear/demo/node_editor.c deleted file mode 100644 index 6949f590..00000000 --- a/deps/nuklear/demo/node_editor.c +++ /dev/null @@ -1,343 +0,0 @@ -/* nuklear - v1.00 - public domain */ -/* This is a simple node editor just to show a simple implementation and that - * it is possible to achieve it with this library. While all nodes inside this - * example use a simple color modifier as content you could change them - * to have your custom content depending on the node time. - * Biggest difference to most usual implementation is that this example does - * not have connectors on the right position of the property that it links. - * This is mainly done out of laziness and could be implemented as well but - * requires calculating the position of all rows and add connectors. - * In addition adding and removing nodes is quite limited at the - * moment since it is based on a simple fixed array. If this is to be converted - * into something more serious it is probably best to extend it.*/ -struct node { - int ID; - char name[32]; - struct nk_rect bounds; - float value; - struct nk_color color; - int input_count; - int output_count; - struct node *next; - struct node *prev; -}; - -struct node_link { - int input_id; - int input_slot; - int output_id; - int output_slot; - struct nk_vec2 in; - struct nk_vec2 out; -}; - -struct node_linking { - int active; - struct node *node; - int input_id; - int input_slot; -}; - -struct node_editor { - int initialized; - struct node node_buf[32]; - struct node_link links[64]; - struct node *begin; - struct node *end; - int node_count; - int link_count; - struct nk_rect bounds; - struct node *selected; - int show_grid; - struct nk_vec2 scrolling; - struct node_linking linking; -}; -static struct node_editor nodeEditor; - -static void -node_editor_push(struct node_editor *editor, struct node *node) -{ - if (!editor->begin) { - node->next = NULL; - node->prev = NULL; - editor->begin = node; - editor->end = node; - } else { - node->prev = editor->end; - if (editor->end) - editor->end->next = node; - node->next = NULL; - editor->end = node; - } -} - -static void -node_editor_pop(struct node_editor *editor, struct node *node) -{ - if (node->next) - node->next->prev = node->prev; - if (node->prev) - node->prev->next = node->next; - if (editor->end == node) - editor->end = node->prev; - if (editor->begin == node) - editor->begin = node->next; - node->next = NULL; - node->prev = NULL; -} - -static struct node* -node_editor_find(struct node_editor *editor, int ID) -{ - struct node *iter = editor->begin; - while (iter) { - if (iter->ID == ID) - return iter; - iter = iter->next; - } - return NULL; -} - -static void -node_editor_add(struct node_editor *editor, const char *name, struct nk_rect bounds, - struct nk_color col, int in_count, int out_count) -{ - static int IDs = 0; - struct node *node; - assert((nk_size)editor->node_count < LEN(editor->node_buf)); - node = &editor->node_buf[editor->node_count++]; - node->ID = IDs++; - node->value = 0; - node->color = nk_rgb(255, 0, 0); - node->input_count = in_count; - node->output_count = out_count; - node->color = col; - node->bounds = bounds; - strcpy(node->name, name); - node_editor_push(editor, node); -} - -static void -node_editor_link(struct node_editor *editor, int in_id, int in_slot, - int out_id, int out_slot) -{ - struct node_link *link; - assert((nk_size)editor->link_count < LEN(editor->links)); - link = &editor->links[editor->link_count++]; - link->input_id = in_id; - link->input_slot = in_slot; - link->output_id = out_id; - link->output_slot = out_slot; -} - -static void -node_editor_init(struct node_editor *editor) -{ - memset(editor, 0, sizeof(*editor)); - editor->begin = NULL; - editor->end = NULL; - node_editor_add(editor, "Source", nk_rect(40, 10, 180, 220), nk_rgb(255, 0, 0), 0, 1); - node_editor_add(editor, "Source", nk_rect(40, 260, 180, 220), nk_rgb(0, 255, 0), 0, 1); - node_editor_add(editor, "Combine", nk_rect(400, 100, 180, 220), nk_rgb(0,0,255), 2, 2); - node_editor_link(editor, 0, 0, 2, 0); - node_editor_link(editor, 1, 0, 2, 1); - editor->show_grid = nk_true; -} - -static int -node_editor(struct nk_context *ctx) -{ - int n = 0; - struct nk_rect total_space; - const struct nk_input *in = &ctx->input; - struct nk_command_buffer *canvas; - struct node *updated = 0; - struct node_editor *nodedit = &nodeEditor; - - if (!nodeEditor.initialized) { - node_editor_init(&nodeEditor); - nodeEditor.initialized = 1; - } - - if (nk_begin(ctx, "NodeEdit", nk_rect(0, 0, 800, 600), - NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE|NK_WINDOW_CLOSABLE)) - { - /* allocate complete window space */ - canvas = nk_window_get_canvas(ctx); - total_space = nk_window_get_content_region(ctx); - nk_layout_space_begin(ctx, NK_STATIC, total_space.h, nodedit->node_count); - { - struct node *it = nodedit->begin; - struct nk_rect size = nk_layout_space_bounds(ctx); - - if (nodedit->show_grid) { - /* display grid */ - float x, y; - const float grid_size = 32.0f; - const struct nk_color grid_color = nk_rgb(50, 50, 50); - for (x = (float)fmod(size.x - nodedit->scrolling.x, grid_size); x < size.w; x += grid_size) - nk_stroke_line(canvas, x+size.x, size.y, x+size.x, size.y+size.h, 1.0f, grid_color); - for (y = (float)fmod(size.y - nodedit->scrolling.y, grid_size); y < size.h; y += grid_size) - nk_stroke_line(canvas, size.x, y+size.y, size.x+size.w, y+size.y, 1.0f, grid_color); - } - - /* execute each node as a movable group */ - struct nk_panel *node; - while (it) { - /* calculate scrolled node window position and size */ - nk_layout_space_push(ctx, nk_rect(it->bounds.x - nodedit->scrolling.x, - it->bounds.y - nodedit->scrolling.y, it->bounds.w, it->bounds.h)); - - /* execute node window */ - if (nk_group_begin(ctx, it->name, NK_WINDOW_MOVABLE|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER|NK_WINDOW_TITLE)) - { - /* always have last selected node on top */ - - node = nk_window_get_panel(ctx); - if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, node->bounds) && - (!(it->prev && nk_input_mouse_clicked(in, NK_BUTTON_LEFT, - nk_layout_space_rect_to_screen(ctx, node->bounds)))) && - nodedit->end != it) - { - updated = it; - } - - /* ================= NODE CONTENT =====================*/ - nk_layout_row_dynamic(ctx, 25, 1); - nk_button_color(ctx, it->color); - it->color.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, it->color.r, 255, 1,1); - it->color.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, it->color.g, 255, 1,1); - it->color.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, it->color.b, 255, 1,1); - it->color.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, it->color.a, 255, 1,1); - /* ====================================================*/ - nk_group_end(ctx); - } - { - /* node connector and linking */ - float space; - struct nk_rect bounds; - bounds = nk_layout_space_rect_to_local(ctx, node->bounds); - bounds.x += nodedit->scrolling.x; - bounds.y += nodedit->scrolling.y; - it->bounds = bounds; - - /* output connector */ - space = node->bounds.h / (float)((it->output_count) + 1); - for (n = 0; n < it->output_count; ++n) { - struct nk_rect circle; - circle.x = node->bounds.x + node->bounds.w-4; - circle.y = node->bounds.y + space * (float)(n+1); - circle.w = 8; circle.h = 8; - nk_fill_circle(canvas, circle, nk_rgb(100, 100, 100)); - - /* start linking process */ - if (nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, circle, nk_true)) { - nodedit->linking.active = nk_true; - nodedit->linking.node = it; - nodedit->linking.input_id = it->ID; - nodedit->linking.input_slot = n; - } - - /* draw curve from linked node slot to mouse position */ - if (nodedit->linking.active && nodedit->linking.node == it && - nodedit->linking.input_slot == n) { - struct nk_vec2 l0 = nk_vec2(circle.x + 3, circle.y + 3); - struct nk_vec2 l1 = in->mouse.pos; - nk_stroke_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y, - l1.x - 50.0f, l1.y, l1.x, l1.y, 1.0f, nk_rgb(100, 100, 100)); - } - } - - /* input connector */ - space = node->bounds.h / (float)((it->input_count) + 1); - for (n = 0; n < it->input_count; ++n) { - struct nk_rect circle; - circle.x = node->bounds.x-4; - circle.y = node->bounds.y + space * (float)(n+1); - circle.w = 8; circle.h = 8; - nk_fill_circle(canvas, circle, nk_rgb(100, 100, 100)); - if (nk_input_is_mouse_released(in, NK_BUTTON_LEFT) && - nk_input_is_mouse_hovering_rect(in, circle) && - nodedit->linking.active && nodedit->linking.node != it) { - nodedit->linking.active = nk_false; - node_editor_link(nodedit, nodedit->linking.input_id, - nodedit->linking.input_slot, it->ID, n); - } - } - } - it = it->next; - } - - /* reset linking connection */ - if (nodedit->linking.active && nk_input_is_mouse_released(in, NK_BUTTON_LEFT)) { - nodedit->linking.active = nk_false; - nodedit->linking.node = NULL; - fprintf(stdout, "linking failed\n"); - } - - /* draw each link */ - for (n = 0; n < nodedit->link_count; ++n) { - struct node_link *link = &nodedit->links[n]; - struct node *ni = node_editor_find(nodedit, link->input_id); - struct node *no = node_editor_find(nodedit, link->output_id); - float spacei = node->bounds.h / (float)((ni->output_count) + 1); - float spaceo = node->bounds.h / (float)((no->input_count) + 1); - struct nk_vec2 l0 = nk_layout_space_to_screen(ctx, - nk_vec2(ni->bounds.x + ni->bounds.w, 3.0f + ni->bounds.y + spacei * (float)(link->input_slot+1))); - struct nk_vec2 l1 = nk_layout_space_to_screen(ctx, - nk_vec2(no->bounds.x, 3.0f + no->bounds.y + spaceo * (float)(link->output_slot+1))); - - l0.x -= nodedit->scrolling.x; - l0.y -= nodedit->scrolling.y; - l1.x -= nodedit->scrolling.x; - l1.y -= nodedit->scrolling.y; - nk_stroke_curve(canvas, l0.x, l0.y, l0.x + 50.0f, l0.y, - l1.x - 50.0f, l1.y, l1.x, l1.y, 1.0f, nk_rgb(100, 100, 100)); - } - - if (updated) { - /* reshuffle nodes to have least recently selected node on top */ - node_editor_pop(nodedit, updated); - node_editor_push(nodedit, updated); - } - - /* node selection */ - if (nk_input_mouse_clicked(in, NK_BUTTON_LEFT, nk_layout_space_bounds(ctx))) { - it = nodedit->begin; - nodedit->selected = NULL; - nodedit->bounds = nk_rect(in->mouse.pos.x, in->mouse.pos.y, 100, 200); - while (it) { - struct nk_rect b = nk_layout_space_rect_to_screen(ctx, it->bounds); - b.x -= nodedit->scrolling.x; - b.y -= nodedit->scrolling.y; - if (nk_input_is_mouse_hovering_rect(in, b)) - nodedit->selected = it; - it = it->next; - } - } - - /* contextual menu */ - if (nk_contextual_begin(ctx, 0, nk_vec2(100, 220), nk_window_get_bounds(ctx))) { - const char *grid_option[] = {"Show Grid", "Hide Grid"}; - nk_layout_row_dynamic(ctx, 25, 1); - if (nk_contextual_item_label(ctx, "New", NK_TEXT_CENTERED)) - node_editor_add(nodedit, "New", nk_rect(400, 260, 180, 220), - nk_rgb(255, 255, 255), 1, 2); - if (nk_contextual_item_label(ctx, grid_option[nodedit->show_grid],NK_TEXT_CENTERED)) - nodedit->show_grid = !nodedit->show_grid; - nk_contextual_end(ctx); - } - } - nk_layout_space_end(ctx); - - /* window content scrolling */ - if (nk_input_is_mouse_hovering_rect(in, nk_window_get_bounds(ctx)) && - nk_input_is_mouse_down(in, NK_BUTTON_MIDDLE)) { - nodedit->scrolling.x += in->mouse.delta.x; - nodedit->scrolling.y += in->mouse.delta.y; - } - } - nk_end(ctx); - return !nk_window_is_closed(ctx, "NodeEdit"); -} - diff --git a/deps/nuklear/demo/overview.c b/deps/nuklear/demo/overview.c deleted file mode 100644 index 7f2c4853..00000000 --- a/deps/nuklear/demo/overview.c +++ /dev/null @@ -1,1188 +0,0 @@ - -static int -overview(struct nk_context *ctx) -{ - /* window flags */ - static int show_menu = nk_true; - static int titlebar = nk_true; - static int border = nk_true; - static int resize = nk_true; - static int movable = nk_true; - static int no_scrollbar = nk_false; - static nk_flags window_flags = 0; - static int minimizable = nk_true; - - /* popups */ - static enum nk_style_header_align header_align = NK_HEADER_RIGHT; - static int show_app_about = nk_false; - - /* window flags */ - window_flags = 0; - ctx->style.window.header.align = header_align; - if (border) window_flags |= NK_WINDOW_BORDER; - if (resize) window_flags |= NK_WINDOW_SCALABLE; - if (movable) window_flags |= NK_WINDOW_MOVABLE; - if (no_scrollbar) window_flags |= NK_WINDOW_NO_SCROLLBAR; - if (minimizable) window_flags |= NK_WINDOW_MINIMIZABLE; - - if (nk_begin(ctx, "Overview", nk_rect(10, 10, 400, 600), window_flags)) - { - if (show_menu) - { - /* menubar */ - enum menu_states {MENU_DEFAULT, MENU_WINDOWS}; - static nk_size mprog = 60; - static int mslider = 10; - static int mcheck = nk_true; - - nk_menubar_begin(ctx); - nk_layout_row_begin(ctx, NK_STATIC, 25, 4); - nk_layout_row_push(ctx, 45); - if (nk_menu_begin_label(ctx, "MENU", NK_TEXT_LEFT, nk_vec2(120, 200))) - { - static size_t prog = 40; - static int slider = 10; - static int check = nk_true; - nk_layout_row_dynamic(ctx, 25, 1); - if (nk_menu_item_label(ctx, "Hide", NK_TEXT_LEFT)) - show_menu = nk_false; - if (nk_menu_item_label(ctx, "About", NK_TEXT_LEFT)) - show_app_about = nk_true; - nk_progress(ctx, &prog, 100, NK_MODIFIABLE); - nk_slider_int(ctx, 0, &slider, 16, 1); - nk_checkbox_label(ctx, "check", &check); - nk_menu_end(ctx); - } - nk_layout_row_push(ctx, 70); - nk_progress(ctx, &mprog, 100, NK_MODIFIABLE); - nk_slider_int(ctx, 0, &mslider, 16, 1); - nk_checkbox_label(ctx, "check", &mcheck); - nk_menubar_end(ctx); - } - - if (show_app_about) - { - /* about popup */ - static struct nk_rect s = {20, 100, 300, 190}; - if (nk_popup_begin(ctx, NK_POPUP_STATIC, "About", NK_WINDOW_CLOSABLE, s)) - { - nk_layout_row_dynamic(ctx, 20, 1); - nk_label(ctx, "Nuklear", NK_TEXT_LEFT); - nk_label(ctx, "By Micha Mettke", NK_TEXT_LEFT); - nk_label(ctx, "nuklear is licensed under the public domain License.", NK_TEXT_LEFT); - nk_popup_end(ctx); - } else show_app_about = nk_false; - } - - /* window flags */ - if (nk_tree_push(ctx, NK_TREE_TAB, "Window", NK_MINIMIZED)) { - nk_layout_row_dynamic(ctx, 30, 2); - nk_checkbox_label(ctx, "Titlebar", &titlebar); - nk_checkbox_label(ctx, "Menu", &show_menu); - nk_checkbox_label(ctx, "Border", &border); - nk_checkbox_label(ctx, "Resizable", &resize); - nk_checkbox_label(ctx, "Movable", &movable); - nk_checkbox_label(ctx, "No Scrollbar", &no_scrollbar); - nk_checkbox_label(ctx, "Minimizable", &minimizable); - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_TAB, "Widgets", NK_MINIMIZED)) - { - enum options {A,B,C}; - static int checkbox; - static int option; - if (nk_tree_push(ctx, NK_TREE_NODE, "Text", NK_MINIMIZED)) - { - /* Text Widgets */ - nk_layout_row_dynamic(ctx, 20, 1); - nk_label(ctx, "Label aligned left", NK_TEXT_LEFT); - nk_label(ctx, "Label aligned centered", NK_TEXT_CENTERED); - nk_label(ctx, "Label aligned right", NK_TEXT_RIGHT); - nk_label_colored(ctx, "Blue text", NK_TEXT_LEFT, nk_rgb(0,0,255)); - nk_label_colored(ctx, "Yellow text", NK_TEXT_LEFT, nk_rgb(255,255,0)); - nk_text(ctx, "Text without /0", 15, NK_TEXT_RIGHT); - - nk_layout_row_static(ctx, 100, 200, 1); - nk_label_wrap(ctx, "This is a very long line to hopefully get this text to be wrapped into multiple lines to show line wrapping"); - nk_layout_row_dynamic(ctx, 100, 1); - nk_label_wrap(ctx, "This is another long text to show dynamic window changes on multiline text"); - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Button", NK_MINIMIZED)) - { - /* Buttons Widgets */ - nk_layout_row_static(ctx, 30, 100, 3); - if (nk_button_label(ctx, "Button")) - fprintf(stdout, "Button pressed!\n"); - nk_button_set_behavior(ctx, NK_BUTTON_REPEATER); - if (nk_button_label(ctx, "Repeater")) - fprintf(stdout, "Repeater is being pressed!\n"); - nk_button_set_behavior(ctx, NK_BUTTON_DEFAULT); - nk_button_color(ctx, nk_rgb(0,0,255)); - - nk_layout_row_static(ctx, 25, 25, 8); - nk_button_symbol(ctx, NK_SYMBOL_CIRCLE_SOLID); - nk_button_symbol(ctx, NK_SYMBOL_CIRCLE_OUTLINE); - nk_button_symbol(ctx, NK_SYMBOL_RECT_SOLID); - nk_button_symbol(ctx, NK_SYMBOL_RECT_OUTLINE); - nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_UP); - nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_DOWN); - nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_LEFT); - nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_RIGHT); - - nk_layout_row_static(ctx, 30, 100, 2); - nk_button_symbol_label(ctx, NK_SYMBOL_TRIANGLE_LEFT, "prev", NK_TEXT_RIGHT); - nk_button_symbol_label(ctx, NK_SYMBOL_TRIANGLE_RIGHT, "next", NK_TEXT_LEFT); - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Basic", NK_MINIMIZED)) - { - /* Basic widgets */ - static int int_slider = 5; - static float float_slider = 2.5f; - static size_t prog_value = 40; - static float property_float = 2; - static int property_int = 10; - static int property_neg = 10; - - static float range_float_min = 0; - static float range_float_max = 100; - static float range_float_value = 50; - static int range_int_min = 0; - static int range_int_value = 2048; - static int range_int_max = 4096; - static const float ratio[] = {120, 150}; - - nk_layout_row_static(ctx, 30, 100, 1); - nk_checkbox_label(ctx, "Checkbox", &checkbox); - - nk_layout_row_static(ctx, 30, 80, 3); - option = nk_option_label(ctx, "optionA", option == A) ? A : option; - option = nk_option_label(ctx, "optionB", option == B) ? B : option; - option = nk_option_label(ctx, "optionC", option == C) ? C : option; - - - nk_layout_row(ctx, NK_STATIC, 30, 2, ratio); - nk_labelf(ctx, NK_TEXT_LEFT, "Slider int"); - nk_slider_int(ctx, 0, &int_slider, 10, 1); - - nk_label(ctx, "Slider float", NK_TEXT_LEFT); - nk_slider_float(ctx, 0, &float_slider, 5.0, 0.5f); - nk_labelf(ctx, NK_TEXT_LEFT, "Progressbar" , prog_value); - nk_progress(ctx, &prog_value, 100, NK_MODIFIABLE); - - nk_layout_row(ctx, NK_STATIC, 25, 2, ratio); - nk_label(ctx, "Property float:", NK_TEXT_LEFT); - nk_property_float(ctx, "Float:", 0, &property_float, 64.0f, 0.1f, 0.2f); - nk_label(ctx, "Property int:", NK_TEXT_LEFT); - nk_property_int(ctx, "Int:", 0, &property_int, 100.0f, 1, 1); - nk_label(ctx, "Property neg:", NK_TEXT_LEFT); - nk_property_int(ctx, "Neg:", -10, &property_neg, 10, 1, 1); - - nk_layout_row_dynamic(ctx, 25, 1); - nk_label(ctx, "Range:", NK_TEXT_LEFT); - nk_layout_row_dynamic(ctx, 25, 3); - nk_property_float(ctx, "#min:", 0, &range_float_min, range_float_max, 1.0f, 0.2f); - nk_property_float(ctx, "#float:", range_float_min, &range_float_value, range_float_max, 1.0f, 0.2f); - nk_property_float(ctx, "#max:", range_float_min, &range_float_max, 100, 1.0f, 0.2f); - - nk_property_int(ctx, "#min:", INT_MIN, &range_int_min, range_int_max, 1, 10); - nk_property_int(ctx, "#neg:", range_int_min, &range_int_value, range_int_max, 1, 10); - nk_property_int(ctx, "#max:", range_int_min, &range_int_max, INT_MAX, 1, 10); - - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Selectable", NK_MINIMIZED)) - { - if (nk_tree_push(ctx, NK_TREE_NODE, "List", NK_MINIMIZED)) - { - static int selected[4] = {nk_false, nk_false, nk_true, nk_false}; - nk_layout_row_static(ctx, 18, 100, 1); - nk_selectable_label(ctx, "Selectable", NK_TEXT_LEFT, &selected[0]); - nk_selectable_label(ctx, "Selectable", NK_TEXT_LEFT, &selected[1]); - nk_label(ctx, "Not Selectable", NK_TEXT_LEFT); - nk_selectable_label(ctx, "Selectable", NK_TEXT_LEFT, &selected[2]); - nk_selectable_label(ctx, "Selectable", NK_TEXT_LEFT, &selected[3]); - nk_tree_pop(ctx); - } - if (nk_tree_push(ctx, NK_TREE_NODE, "Grid", NK_MINIMIZED)) - { - int i; - static int selected[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1}; - nk_layout_row_static(ctx, 50, 50, 4); - for (i = 0; i < 16; ++i) { - if (nk_selectable_label(ctx, "Z", NK_TEXT_CENTERED, &selected[i])) { - int x = (i % 4), y = i / 4; - if (x > 0) selected[i - 1] ^= 1; - if (x < 3) selected[i + 1] ^= 1; - if (y > 0) selected[i - 4] ^= 1; - if (y < 3) selected[i + 4] ^= 1; - } - } - nk_tree_pop(ctx); - } - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Combo", NK_MINIMIZED)) - { - /* Combobox Widgets - * In this library comboboxes are not limited to being a popup - * list of selectable text. Instead it is a abstract concept of - * having something that is *selected* or displayed, a popup window - * which opens if something needs to be modified and the content - * of the popup which causes the *selected* or displayed value to - * change or if wanted close the combobox. - * - * While strange at first handling comboboxes in a abstract way - * solves the problem of overloaded window content. For example - * changing a color value requires 4 value modifier (slider, property,...) - * for RGBA then you need a label and ways to display the current color. - * If you want to go fancy you even add rgb and hsv ratio boxes. - * While fine for one color if you have a lot of them it because - * tedious to look at and quite wasteful in space. You could add - * a popup which modifies the color but this does not solve the - * fact that it still requires a lot of cluttered space to do. - * - * In these kind of instance abstract comboboxes are quite handy. All - * value modifiers are hidden inside the combobox popup and only - * the color is shown if not open. This combines the clarity of the - * popup with the ease of use of just using the space for modifiers. - * - * Other instances are for example time and especially date picker, - * which only show the currently activated time/data and hide the - * selection logic inside the combobox popup. - */ - static float chart_selection = 8.0f; - static int current_weapon = 0; - static int check_values[5]; - static float position[3]; - static struct nk_color combo_color = {130, 50, 50, 255}; - static struct nk_color combo_color2 = {130, 180, 50, 255}; - static size_t prog_a = 20, prog_b = 40, prog_c = 10, prog_d = 90; - static const char *weapons[] = {"Fist","Pistol","Shotgun","Plasma","BFG"}; - - char buffer[64]; - size_t sum = 0; - - /* default combobox */ - nk_layout_row_static(ctx, 25, 200, 1); - current_weapon = nk_combo(ctx, weapons, LEN(weapons), current_weapon, 25, nk_vec2(200,200)); - - /* slider color combobox */ - if (nk_combo_begin_color(ctx, combo_color, nk_vec2(200,200))) { - float ratios[] = {0.15f, 0.85f}; - nk_layout_row(ctx, NK_DYNAMIC, 30, 2, ratios); - nk_label(ctx, "R:", NK_TEXT_LEFT); - combo_color.r = (nk_byte)nk_slide_int(ctx, 0, combo_color.r, 255, 5); - nk_label(ctx, "G:", NK_TEXT_LEFT); - combo_color.g = (nk_byte)nk_slide_int(ctx, 0, combo_color.g, 255, 5); - nk_label(ctx, "B:", NK_TEXT_LEFT); - combo_color.b = (nk_byte)nk_slide_int(ctx, 0, combo_color.b, 255, 5); - nk_label(ctx, "A:", NK_TEXT_LEFT); - combo_color.a = (nk_byte)nk_slide_int(ctx, 0, combo_color.a , 255, 5); - nk_combo_end(ctx); - } - - /* complex color combobox */ - if (nk_combo_begin_color(ctx, combo_color2, nk_vec2(200,400))) { - enum color_mode {COL_RGB, COL_HSV}; - static int col_mode = COL_RGB; - #ifndef DEMO_DO_NOT_USE_COLOR_PICKER - nk_layout_row_dynamic(ctx, 120, 1); - combo_color2 = nk_color_picker(ctx, combo_color2, NK_RGBA); - #endif - - nk_layout_row_dynamic(ctx, 25, 2); - col_mode = nk_option_label(ctx, "RGB", col_mode == COL_RGB) ? COL_RGB : col_mode; - col_mode = nk_option_label(ctx, "HSV", col_mode == COL_HSV) ? COL_HSV : col_mode; - - nk_layout_row_dynamic(ctx, 25, 1); - if (col_mode == COL_RGB) { - combo_color2.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, combo_color2.r, 255, 1,1); - combo_color2.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, combo_color2.g, 255, 1,1); - combo_color2.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, combo_color2.b, 255, 1,1); - combo_color2.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, combo_color2.a, 255, 1,1); - } else { - nk_byte tmp[4]; - nk_color_hsva_bv(tmp, combo_color2); - tmp[0] = (nk_byte)nk_propertyi(ctx, "#H:", 0, tmp[0], 255, 1,1); - tmp[1] = (nk_byte)nk_propertyi(ctx, "#S:", 0, tmp[1], 255, 1,1); - tmp[2] = (nk_byte)nk_propertyi(ctx, "#V:", 0, tmp[2], 255, 1,1); - tmp[3] = (nk_byte)nk_propertyi(ctx, "#A:", 0, tmp[3], 255, 1,1); - combo_color2 = nk_hsva_bv(tmp); - } - nk_combo_end(ctx); - } - - /* progressbar combobox */ - sum = prog_a + prog_b + prog_c + prog_d; - sprintf(buffer, "%lu", sum); - if (nk_combo_begin_label(ctx, buffer, nk_vec2(200,200))) { - nk_layout_row_dynamic(ctx, 30, 1); - nk_progress(ctx, &prog_a, 100, NK_MODIFIABLE); - nk_progress(ctx, &prog_b, 100, NK_MODIFIABLE); - nk_progress(ctx, &prog_c, 100, NK_MODIFIABLE); - nk_progress(ctx, &prog_d, 100, NK_MODIFIABLE); - nk_combo_end(ctx); - } - - /* checkbox combobox */ - sum = (size_t)(check_values[0] + check_values[1] + check_values[2] + check_values[3] + check_values[4]); - sprintf(buffer, "%lu", sum); - if (nk_combo_begin_label(ctx, buffer, nk_vec2(200,200))) { - nk_layout_row_dynamic(ctx, 30, 1); - nk_checkbox_label(ctx, weapons[0], &check_values[0]); - nk_checkbox_label(ctx, weapons[1], &check_values[1]); - nk_checkbox_label(ctx, weapons[2], &check_values[2]); - nk_checkbox_label(ctx, weapons[3], &check_values[3]); - nk_combo_end(ctx); - } - - /* complex text combobox */ - sprintf(buffer, "%.2f, %.2f, %.2f", position[0], position[1],position[2]); - if (nk_combo_begin_label(ctx, buffer, nk_vec2(200,200))) { - nk_layout_row_dynamic(ctx, 25, 1); - nk_property_float(ctx, "#X:", -1024.0f, &position[0], 1024.0f, 1,0.5f); - nk_property_float(ctx, "#Y:", -1024.0f, &position[1], 1024.0f, 1,0.5f); - nk_property_float(ctx, "#Z:", -1024.0f, &position[2], 1024.0f, 1,0.5f); - nk_combo_end(ctx); - } - - /* chart combobox */ - sprintf(buffer, "%.1f", chart_selection); - if (nk_combo_begin_label(ctx, buffer, nk_vec2(200,250))) { - size_t i = 0; - static const float values[]={26.0f,13.0f,30.0f,15.0f,25.0f,10.0f,20.0f,40.0f, 12.0f, 8.0f, 22.0f, 28.0f, 5.0f}; - nk_layout_row_dynamic(ctx, 150, 1); - nk_chart_begin(ctx, NK_CHART_COLUMN, LEN(values), 0, 50); - for (i = 0; i < LEN(values); ++i) { - nk_flags res = nk_chart_push(ctx, values[i]); - if (res & NK_CHART_CLICKED) { - chart_selection = values[i]; - nk_combo_close(ctx); - } - } - nk_chart_end(ctx); - nk_combo_end(ctx); - } - - { - static int time_selected = 0; - static int date_selected = 0; - static struct tm sel_time; - static struct tm sel_date; - if (!time_selected || !date_selected) { - /* keep time and date updated if nothing is selected */ - time_t cur_time = time(0); - struct tm *n = localtime(&cur_time); - if (!time_selected) - memcpy(&sel_time, n, sizeof(struct tm)); - if (!date_selected) - memcpy(&sel_date, n, sizeof(struct tm)); - } - - /* time combobox */ - sprintf(buffer, "%02d:%02d:%02d", sel_time.tm_hour, sel_time.tm_min, sel_time.tm_sec); - if (nk_combo_begin_label(ctx, buffer, nk_vec2(200,250))) { - time_selected = 1; - nk_layout_row_dynamic(ctx, 25, 1); - sel_time.tm_sec = nk_propertyi(ctx, "#S:", 0, sel_time.tm_sec, 60, 1, 1); - sel_time.tm_min = nk_propertyi(ctx, "#M:", 0, sel_time.tm_min, 60, 1, 1); - sel_time.tm_hour = nk_propertyi(ctx, "#H:", 0, sel_time.tm_hour, 23, 1, 1); - nk_combo_end(ctx); - } - - /* date combobox */ - sprintf(buffer, "%02d-%02d-%02d", sel_date.tm_mday, sel_date.tm_mon+1, sel_date.tm_year+1900); - if (nk_combo_begin_label(ctx, buffer, nk_vec2(350,400))) - { - int i = 0; - const char *month[] = {"January", "February", "March", "Apil", "May", "June", "July", "August", "September", "Ocotober", "November", "December"}; - const char *week_days[] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"}; - const int month_days[] = {31,28,31,30,31,30,31,31,30,31,30,31}; - int year = sel_date.tm_year+1900; - int leap_year = (!(year % 4) && ((year % 100))) || !(year % 400); - int days = (sel_date.tm_mon == 1) ? - month_days[sel_date.tm_mon] + leap_year: - month_days[sel_date.tm_mon]; - - /* header with month and year */ - date_selected = 1; - nk_layout_row_begin(ctx, NK_DYNAMIC, 20, 3); - nk_layout_row_push(ctx, 0.05f); - if (nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_LEFT)) { - if (sel_date.tm_mon == 0) { - sel_date.tm_mon = 11; - sel_date.tm_year = MAX(0, sel_date.tm_year-1); - } else sel_date.tm_mon--; - } - nk_layout_row_push(ctx, 0.9f); - sprintf(buffer, "%s %d", month[sel_date.tm_mon], year); - nk_label(ctx, buffer, NK_TEXT_CENTERED); - nk_layout_row_push(ctx, 0.05f); - if (nk_button_symbol(ctx, NK_SYMBOL_TRIANGLE_RIGHT)) { - if (sel_date.tm_mon == 11) { - sel_date.tm_mon = 0; - sel_date.tm_year++; - } else sel_date.tm_mon++; - } - nk_layout_row_end(ctx); - - /* good old week day formula (double because precision) */ - {int year_n = (sel_date.tm_mon < 2) ? year-1: year; - int y = year_n % 100; - int c = year_n / 100; - int y4 = (int)((float)y / 4); - int c4 = (int)((float)c / 4); - int m = (int)(2.6 * (double)(((sel_date.tm_mon + 10) % 12) + 1) - 0.2); - int week_day = (((1 + m + y + y4 + c4 - 2 * c) % 7) + 7) % 7; - - /* weekdays */ - nk_layout_row_dynamic(ctx, 35, 7); - for (i = 0; i < (int)LEN(week_days); ++i) - nk_label(ctx, week_days[i], NK_TEXT_CENTERED); - - /* days */ - if (week_day > 0) nk_spacing(ctx, week_day); - for (i = 1; i <= days; ++i) { - sprintf(buffer, "%d", i); - if (nk_button_label(ctx, buffer)) { - sel_date.tm_mday = i; - nk_combo_close(ctx); - } - }} - nk_combo_end(ctx); - } - } - - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Input", NK_MINIMIZED)) - { - static const float ratio[] = {120, 150}; - static char field_buffer[64]; - static char text[9][64]; - static int text_len[9]; - static char box_buffer[512]; - static int field_len; - static int box_len; - nk_flags active; - - nk_layout_row(ctx, NK_STATIC, 25, 2, ratio); - nk_label(ctx, "Default:", NK_TEXT_LEFT); - - nk_edit_string(ctx, NK_EDIT_SIMPLE, text[0], &text_len[0], 64, nk_filter_default); - nk_label(ctx, "Int:", NK_TEXT_LEFT); - nk_edit_string(ctx, NK_EDIT_SIMPLE, text[1], &text_len[1], 64, nk_filter_decimal); - nk_label(ctx, "Float:", NK_TEXT_LEFT); - nk_edit_string(ctx, NK_EDIT_SIMPLE, text[2], &text_len[2], 64, nk_filter_float); - nk_label(ctx, "Hex:", NK_TEXT_LEFT); - nk_edit_string(ctx, NK_EDIT_SIMPLE, text[4], &text_len[4], 64, nk_filter_hex); - nk_label(ctx, "Octal:", NK_TEXT_LEFT); - nk_edit_string(ctx, NK_EDIT_SIMPLE, text[5], &text_len[5], 64, nk_filter_oct); - nk_label(ctx, "Binary:", NK_TEXT_LEFT); - nk_edit_string(ctx, NK_EDIT_SIMPLE, text[6], &text_len[6], 64, nk_filter_binary); - - nk_label(ctx, "Password:", NK_TEXT_LEFT); - { - int i = 0; - int old_len = text_len[8]; - char buffer[64]; - for (i = 0; i < text_len[8]; ++i) buffer[i] = '*'; - nk_edit_string(ctx, NK_EDIT_FIELD, buffer, &text_len[8], 64, nk_filter_default); - if (old_len < text_len[8]) - memcpy(&text[8][old_len], &buffer[old_len], (nk_size)(text_len[8] - old_len)); - } - - nk_label(ctx, "Field:", NK_TEXT_LEFT); - nk_edit_string(ctx, NK_EDIT_FIELD, field_buffer, &field_len, 64, nk_filter_default); - - nk_label(ctx, "Box:", NK_TEXT_LEFT); - nk_layout_row_static(ctx, 180, 278, 1); - nk_edit_string(ctx, NK_EDIT_BOX, box_buffer, &box_len, 512, nk_filter_default); - - nk_layout_row(ctx, NK_STATIC, 25, 2, ratio); - active = nk_edit_string(ctx, NK_EDIT_FIELD|NK_EDIT_SIG_ENTER, text[7], &text_len[7], 64, nk_filter_ascii); - if (nk_button_label(ctx, "Submit") || - (active & NK_EDIT_COMMITED)) - { - text[7][text_len[7]] = '\n'; - text_len[7]++; - memcpy(&box_buffer[box_len], &text[7], (nk_size)text_len[7]); - box_len += text_len[7]; - text_len[7] = 0; - } - nk_layout_row_end(ctx); - nk_tree_pop(ctx); - } - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_TAB, "Chart", NK_MINIMIZED)) - { - /* Chart Widgets - * This library has two different rather simple charts. The line and the - * column chart. Both provide a simple way of visualizing values and - * have a retained mode and immediate mode API version. For the retain - * mode version `nk_plot` and `nk_plot_function` you either provide - * an array or a callback to call to handle drawing the graph. - * For the immediate mode version you start by calling `nk_chart_begin` - * and need to provide min and max values for scaling on the Y-axis. - * and then call `nk_chart_push` to push values into the chart. - * Finally `nk_chart_end` needs to be called to end the process. */ - float id = 0; - static int col_index = -1; - static int line_index = -1; - float step = (2*3.141592654f) / 32; - - int i; - int index = -1; - struct nk_rect bounds; - - /* line chart */ - id = 0; - index = -1; - nk_layout_row_dynamic(ctx, 100, 1); - bounds = nk_widget_bounds(ctx); - if (nk_chart_begin(ctx, NK_CHART_LINES, 32, -1.0f, 1.0f)) { - for (i = 0; i < 32; ++i) { - nk_flags res = nk_chart_push(ctx, (float)cos(id)); - if (res & NK_CHART_HOVERING) - index = (int)i; - if (res & NK_CHART_CLICKED) - line_index = (int)i; - id += step; - } - nk_chart_end(ctx); - } - - if (index != -1) { - char buffer[NK_MAX_NUMBER_BUFFER]; - float val = (float)cos((float)index*step); - sprintf(buffer, "Value: %.2f", val); - nk_tooltip(ctx, buffer); - } - if (line_index != -1) { - nk_layout_row_dynamic(ctx, 20, 1); - nk_labelf(ctx, NK_TEXT_LEFT, "Selected value: %.2f", (float)cos((float)index*step)); - } - - /* column chart */ - nk_layout_row_dynamic(ctx, 100, 1); - bounds = nk_widget_bounds(ctx); - if (nk_chart_begin(ctx, NK_CHART_COLUMN, 32, 0.0f, 1.0f)) { - for (i = 0; i < 32; ++i) { - nk_flags res = nk_chart_push(ctx, (float)fabs(sin(id))); - if (res & NK_CHART_HOVERING) - index = (int)i; - if (res & NK_CHART_CLICKED) - col_index = (int)i; - id += step; - } - nk_chart_end(ctx); - } - if (index != -1) { - char buffer[NK_MAX_NUMBER_BUFFER]; - sprintf(buffer, "Value: %.2f", (float)fabs(sin(step * (float)index))); - nk_tooltip(ctx, buffer); - } - if (col_index != -1) { - nk_layout_row_dynamic(ctx, 20, 1); - nk_labelf(ctx, NK_TEXT_LEFT, "Selected value: %.2f", (float)fabs(sin(step * (float)col_index))); - } - - /* mixed chart */ - nk_layout_row_dynamic(ctx, 100, 1); - bounds = nk_widget_bounds(ctx); - if (nk_chart_begin(ctx, NK_CHART_COLUMN, 32, 0.0f, 1.0f)) { - nk_chart_add_slot(ctx, NK_CHART_LINES, 32, -1.0f, 1.0f); - nk_chart_add_slot(ctx, NK_CHART_LINES, 32, -1.0f, 1.0f); - for (id = 0, i = 0; i < 32; ++i) { - nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0); - nk_chart_push_slot(ctx, (float)cos(id), 1); - nk_chart_push_slot(ctx, (float)sin(id), 2); - id += step; - } - } - nk_chart_end(ctx); - - /* mixed colored chart */ - nk_layout_row_dynamic(ctx, 100, 1); - bounds = nk_widget_bounds(ctx); - if (nk_chart_begin_colored(ctx, NK_CHART_LINES, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) { - nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,0,255), nk_rgb(0,0,150),32, -1.0f, 1.0f); - nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,255,0), nk_rgb(0,150,0), 32, -1.0f, 1.0f); - for (id = 0, i = 0; i < 32; ++i) { - nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0); - nk_chart_push_slot(ctx, (float)cos(id), 1); - nk_chart_push_slot(ctx, (float)sin(id), 2); - id += step; - } - } - nk_chart_end(ctx); - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_TAB, "Popup", NK_MINIMIZED)) - { - static struct nk_color color = {255,0,0, 255}; - static int select[4]; - static int popup_active; - const struct nk_input *in = &ctx->input; - struct nk_rect bounds; - - /* menu contextual */ - nk_layout_row_static(ctx, 30, 150, 1); - bounds = nk_widget_bounds(ctx); - nk_label(ctx, "Right click me for menu", NK_TEXT_LEFT); - - if (nk_contextual_begin(ctx, 0, nk_vec2(100, 300), bounds)) { - static size_t prog = 40; - static int slider = 10; - - nk_layout_row_dynamic(ctx, 25, 1); - nk_checkbox_label(ctx, "Menu", &show_menu); - nk_progress(ctx, &prog, 100, NK_MODIFIABLE); - nk_slider_int(ctx, 0, &slider, 16, 1); - if (nk_contextual_item_label(ctx, "About", NK_TEXT_CENTERED)) - show_app_about = nk_true; - nk_selectable_label(ctx, select[0]?"Unselect":"Select", NK_TEXT_LEFT, &select[0]); - nk_selectable_label(ctx, select[1]?"Unselect":"Select", NK_TEXT_LEFT, &select[1]); - nk_selectable_label(ctx, select[2]?"Unselect":"Select", NK_TEXT_LEFT, &select[2]); - nk_selectable_label(ctx, select[3]?"Unselect":"Select", NK_TEXT_LEFT, &select[3]); - nk_contextual_end(ctx); - } - - /* color contextual */ - nk_layout_row_begin(ctx, NK_STATIC, 30, 2); - nk_layout_row_push(ctx, 100); - nk_label(ctx, "Right Click here:", NK_TEXT_LEFT); - nk_layout_row_push(ctx, 50); - bounds = nk_widget_bounds(ctx); - nk_button_color(ctx, color); - nk_layout_row_end(ctx); - - if (nk_contextual_begin(ctx, 0, nk_vec2(350, 60), bounds)) { - nk_layout_row_dynamic(ctx, 30, 4); - color.r = (nk_byte)nk_propertyi(ctx, "#r", 0, color.r, 255, 1, 1); - color.g = (nk_byte)nk_propertyi(ctx, "#g", 0, color.g, 255, 1, 1); - color.b = (nk_byte)nk_propertyi(ctx, "#b", 0, color.b, 255, 1, 1); - color.a = (nk_byte)nk_propertyi(ctx, "#a", 0, color.a, 255, 1, 1); - nk_contextual_end(ctx); - } - - /* popup */ - nk_layout_row_begin(ctx, NK_STATIC, 30, 2); - nk_layout_row_push(ctx, 100); - nk_label(ctx, "Popup:", NK_TEXT_LEFT); - nk_layout_row_push(ctx, 50); - if (nk_button_label(ctx, "Popup")) - popup_active = 1; - nk_layout_row_end(ctx); - - if (popup_active) - { - static struct nk_rect s = {20, 100, 220, 90}; - if (nk_popup_begin(ctx, NK_POPUP_STATIC, "Error", 0, s)) - { - nk_layout_row_dynamic(ctx, 25, 1); - nk_label(ctx, "A terrible error as occured", NK_TEXT_LEFT); - nk_layout_row_dynamic(ctx, 25, 2); - if (nk_button_label(ctx, "OK")) { - popup_active = 0; - nk_popup_close(ctx); - } - if (nk_button_label(ctx, "Cancel")) { - popup_active = 0; - nk_popup_close(ctx); - } - nk_popup_end(ctx); - } else popup_active = nk_false; - } - - /* tooltip */ - nk_layout_row_static(ctx, 30, 150, 1); - bounds = nk_widget_bounds(ctx); - nk_label(ctx, "Hover me for tooltip", NK_TEXT_LEFT); - if (nk_input_is_mouse_hovering_rect(in, bounds)) - nk_tooltip(ctx, "This is a tooltip"); - - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_TAB, "Layout", NK_MINIMIZED)) - { - if (nk_tree_push(ctx, NK_TREE_NODE, "Widget", NK_MINIMIZED)) - { - float ratio_two[] = {0.2f, 0.6f, 0.2f}; - float width_two[] = {100, 200, 50}; - - nk_layout_row_dynamic(ctx, 30, 1); - nk_label(ctx, "Dynamic fixed column layout with generated position and size:", NK_TEXT_LEFT); - nk_layout_row_dynamic(ctx, 30, 3); - nk_button_label(ctx, "button"); - nk_button_label(ctx, "button"); - nk_button_label(ctx, "button"); - - nk_layout_row_dynamic(ctx, 30, 1); - nk_label(ctx, "static fixed column layout with generated position and size:", NK_TEXT_LEFT); - nk_layout_row_static(ctx, 30, 100, 3); - nk_button_label(ctx, "button"); - nk_button_label(ctx, "button"); - nk_button_label(ctx, "button"); - - nk_layout_row_dynamic(ctx, 30, 1); - nk_label(ctx, "Dynamic array-based custom column layout with generated position and custom size:",NK_TEXT_LEFT); - nk_layout_row(ctx, NK_DYNAMIC, 30, 3, ratio_two); - nk_button_label(ctx, "button"); - nk_button_label(ctx, "button"); - nk_button_label(ctx, "button"); - - nk_layout_row_dynamic(ctx, 30, 1); - nk_label(ctx, "Static array-based custom column layout with generated position and custom size:",NK_TEXT_LEFT ); - nk_layout_row(ctx, NK_STATIC, 30, 3, width_two); - nk_button_label(ctx, "button"); - nk_button_label(ctx, "button"); - nk_button_label(ctx, "button"); - - nk_layout_row_dynamic(ctx, 30, 1); - nk_label(ctx, "Dynamic immediate mode custom column layout with generated position and custom size:",NK_TEXT_LEFT); - nk_layout_row_begin(ctx, NK_DYNAMIC, 30, 3); - nk_layout_row_push(ctx, 0.2f); - nk_button_label(ctx, "button"); - nk_layout_row_push(ctx, 0.6f); - nk_button_label(ctx, "button"); - nk_layout_row_push(ctx, 0.2f); - nk_button_label(ctx, "button"); - nk_layout_row_end(ctx); - - nk_layout_row_dynamic(ctx, 30, 1); - nk_label(ctx, "Static immediate mode custom column layout with generated position and custom size:", NK_TEXT_LEFT); - nk_layout_row_begin(ctx, NK_STATIC, 30, 3); - nk_layout_row_push(ctx, 100); - nk_button_label(ctx, "button"); - nk_layout_row_push(ctx, 200); - nk_button_label(ctx, "button"); - nk_layout_row_push(ctx, 50); - nk_button_label(ctx, "button"); - nk_layout_row_end(ctx); - - nk_layout_row_dynamic(ctx, 30, 1); - nk_label(ctx, "Static free space with custom position and custom size:", NK_TEXT_LEFT); - nk_layout_space_begin(ctx, NK_STATIC, 120, 4); - nk_layout_space_push(ctx, nk_rect(100, 0, 100, 30)); - nk_button_label(ctx, "button"); - nk_layout_space_push(ctx, nk_rect(0, 15, 100, 30)); - nk_button_label(ctx, "button"); - nk_layout_space_push(ctx, nk_rect(200, 15, 100, 30)); - nk_button_label(ctx, "button"); - nk_layout_space_push(ctx, nk_rect(100, 30, 100, 30)); - nk_button_label(ctx, "button"); - nk_layout_space_end(ctx); - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Group", NK_MINIMIZED)) - { - static int group_titlebar = nk_false; - static int group_border = nk_true; - static int group_no_scrollbar = nk_false; - static int group_width = 320; - static int group_height = 200; - - nk_flags group_flags = 0; - if (group_border) group_flags |= NK_WINDOW_BORDER; - if (group_no_scrollbar) group_flags |= NK_WINDOW_NO_SCROLLBAR; - if (group_titlebar) group_flags |= NK_WINDOW_TITLE; - - nk_layout_row_dynamic(ctx, 30, 3); - nk_checkbox_label(ctx, "Titlebar", &group_titlebar); - nk_checkbox_label(ctx, "Border", &group_border); - nk_checkbox_label(ctx, "No Scrollbar", &group_no_scrollbar); - - nk_layout_row_begin(ctx, NK_STATIC, 22, 3); - nk_layout_row_push(ctx, 50); - nk_label(ctx, "size:", NK_TEXT_LEFT); - nk_layout_row_push(ctx, 130); - nk_property_int(ctx, "#Width:", 100, &group_width, 500, 10, 1); - nk_layout_row_push(ctx, 130); - nk_property_int(ctx, "#Height:", 100, &group_height, 500, 10, 1); - nk_layout_row_end(ctx); - - nk_layout_row_static(ctx, (float)group_height, group_width, 2); - if (nk_group_begin(ctx, "Group", group_flags)) { - int i = 0; - static int selected[16]; - nk_layout_row_static(ctx, 18, 100, 1); - for (i = 0; i < 16; ++i) - nk_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_CENTERED, &selected[i]); - nk_group_end(ctx); - } - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Notebook", NK_MINIMIZED)) - { - static int current_tab = 0; - struct nk_vec2 item_padding; - struct nk_rect bounds; - float step = (2*3.141592654f) / 32; - enum chart_type {CHART_LINE, CHART_HISTO, CHART_MIXED}; - const char *names[] = {"Lines", "Columns", "Mixed"}; - float id = 0; - int i; - - /* Header */ - nk_style_push_vec2(ctx, &ctx->style.window.spacing, nk_vec2(0,0)); - nk_style_push_float(ctx, &ctx->style.button.rounding, 0); - nk_layout_row_begin(ctx, NK_STATIC, 20, 3); - for (i = 0; i < 3; ++i) { - /* make sure button perfectly fits text */ - const struct nk_user_font *f = ctx->style.font; - float text_width = f->width(f->userdata, f->height, names[i], nk_strlen(names[i])); - float widget_width = text_width + 3 * ctx->style.button.padding.x; - nk_layout_row_push(ctx, widget_width); - if (current_tab == i) { - /* active tab gets highlighted */ - struct nk_style_item button_color = ctx->style.button.normal; - ctx->style.button.normal = ctx->style.button.active; - current_tab = nk_button_label(ctx, names[i]) ? i: current_tab; - ctx->style.button.normal = button_color; - } else current_tab = nk_button_label(ctx, names[i]) ? i: current_tab; - } - nk_style_pop_float(ctx); - - /* Body */ - nk_layout_row_dynamic(ctx, 140, 1); - if (nk_group_begin(ctx, "Notebook", NK_WINDOW_BORDER)) - { - nk_style_pop_vec2(ctx); - switch (current_tab) { - case CHART_LINE: - nk_layout_row_dynamic(ctx, 100, 1); - bounds = nk_widget_bounds(ctx); - if (nk_chart_begin_colored(ctx, NK_CHART_LINES, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) { - nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,0,255), nk_rgb(0,0,150),32, -1.0f, 1.0f); - for (i = 0, id = 0; i < 32; ++i) { - nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0); - nk_chart_push_slot(ctx, (float)cos(id), 1); - id += step; - } - } - nk_chart_end(ctx); - break; - case CHART_HISTO: - nk_layout_row_dynamic(ctx, 100, 1); - bounds = nk_widget_bounds(ctx); - if (nk_chart_begin_colored(ctx, NK_CHART_COLUMN, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) { - for (i = 0, id = 0; i < 32; ++i) { - nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0); - id += step; - } - } - nk_chart_end(ctx); - break; - case CHART_MIXED: - nk_layout_row_dynamic(ctx, 100, 1); - bounds = nk_widget_bounds(ctx); - if (nk_chart_begin_colored(ctx, NK_CHART_LINES, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) { - nk_chart_add_slot_colored(ctx, NK_CHART_LINES, nk_rgb(0,0,255), nk_rgb(0,0,150),32, -1.0f, 1.0f); - nk_chart_add_slot_colored(ctx, NK_CHART_COLUMN, nk_rgb(0,255,0), nk_rgb(0,150,0), 32, 0.0f, 1.0f); - for (i = 0, id = 0; i < 32; ++i) { - nk_chart_push_slot(ctx, (float)fabs(sin(id)), 0); - nk_chart_push_slot(ctx, (float)fabs(cos(id)), 1); - nk_chart_push_slot(ctx, (float)fabs(sin(id)), 2); - id += step; - } - } - nk_chart_end(ctx); - break; - } - nk_group_end(ctx); - } else nk_style_pop_vec2(ctx); - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Simple", NK_MINIMIZED)) - { - nk_layout_row_dynamic(ctx, 300, 2); - if (nk_group_begin(ctx, "Group_Without_Border", 0)) { - int i = 0; - char buffer[64]; - nk_layout_row_static(ctx, 18, 150, 1); - for (i = 0; i < 64; ++i) { - sprintf(buffer, "0x%02x", i); - nk_labelf(ctx, NK_TEXT_LEFT, "%s: scrollable region", buffer); - } - nk_group_end(ctx); - } - if (nk_group_begin(ctx, "Group_With_Border", NK_WINDOW_BORDER)) { - int i = 0; - char buffer[64]; - nk_layout_row_dynamic(ctx, 25, 2); - for (i = 0; i < 64; ++i) { - sprintf(buffer, "%08d", ((((i%7)*10)^32))+(64+(i%2)*2)); - nk_button_label(ctx, buffer); - } - nk_group_end(ctx); - } - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Complex", NK_MINIMIZED)) - { - int i; - nk_layout_space_begin(ctx, NK_STATIC, 500, 64); - nk_layout_space_push(ctx, nk_rect(0,0,150,500)); - if (nk_group_begin(ctx, "Group_left", NK_WINDOW_BORDER)) { - static int selected[32]; - nk_layout_row_static(ctx, 18, 100, 1); - for (i = 0; i < 32; ++i) - nk_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_CENTERED, &selected[i]); - nk_group_end(ctx); - } - - nk_layout_space_push(ctx, nk_rect(160,0,150,240)); - if (nk_group_begin(ctx, "Group_top", NK_WINDOW_BORDER)) { - nk_layout_row_dynamic(ctx, 25, 1); - nk_button_label(ctx, "#FFAA"); - nk_button_label(ctx, "#FFBB"); - nk_button_label(ctx, "#FFCC"); - nk_button_label(ctx, "#FFDD"); - nk_button_label(ctx, "#FFEE"); - nk_button_label(ctx, "#FFFF"); - nk_group_end(ctx); - } - - nk_layout_space_push(ctx, nk_rect(160,250,150,250)); - if (nk_group_begin(ctx, "Group_buttom", NK_WINDOW_BORDER)) { - nk_layout_row_dynamic(ctx, 25, 1); - nk_button_label(ctx, "#FFAA"); - nk_button_label(ctx, "#FFBB"); - nk_button_label(ctx, "#FFCC"); - nk_button_label(ctx, "#FFDD"); - nk_button_label(ctx, "#FFEE"); - nk_button_label(ctx, "#FFFF"); - nk_group_end(ctx); - } - - nk_layout_space_push(ctx, nk_rect(320,0,150,150)); - if (nk_group_begin(ctx, "Group_right_top", NK_WINDOW_BORDER)) { - static int selected[4]; - nk_layout_row_static(ctx, 18, 100, 1); - for (i = 0; i < 4; ++i) - nk_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_CENTERED, &selected[i]); - nk_group_end(ctx); - } - - nk_layout_space_push(ctx, nk_rect(320,160,150,150)); - if (nk_group_begin(ctx, "Group_right_center", NK_WINDOW_BORDER)) { - static int selected[4]; - nk_layout_row_static(ctx, 18, 100, 1); - for (i = 0; i < 4; ++i) - nk_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_CENTERED, &selected[i]); - nk_group_end(ctx); - } - - nk_layout_space_push(ctx, nk_rect(320,320,150,150)); - if (nk_group_begin(ctx, "Group_right_bottom", NK_WINDOW_BORDER)) { - static int selected[4]; - nk_layout_row_static(ctx, 18, 100, 1); - for (i = 0; i < 4; ++i) - nk_selectable_label(ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_CENTERED, &selected[i]); - nk_group_end(ctx); - } - nk_layout_space_end(ctx); - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Splitter", NK_MINIMIZED)) - { - const struct nk_input *in = &ctx->input; - nk_layout_row_static(ctx, 20, 320, 1); - nk_label(ctx, "Use slider and spinner to change tile size", NK_TEXT_LEFT); - nk_label(ctx, "Drag the space between tiles to change tile ratio", NK_TEXT_LEFT); - - if (nk_tree_push(ctx, NK_TREE_NODE, "Vertical", NK_MINIMIZED)) - { - static float a = 100, b = 100, c = 100; - struct nk_rect bounds; - - float row_layout[5]; - row_layout[0] = a; - row_layout[1] = 8; - row_layout[2] = b; - row_layout[3] = 8; - row_layout[4] = c; - - /* header */ - nk_layout_row_static(ctx, 30, 100, 2); - nk_label(ctx, "left:", NK_TEXT_LEFT); - nk_slider_float(ctx, 10.0f, &a, 200.0f, 10.0f); - - nk_label(ctx, "middle:", NK_TEXT_LEFT); - nk_slider_float(ctx, 10.0f, &b, 200.0f, 10.0f); - - nk_label(ctx, "right:", NK_TEXT_LEFT); - nk_slider_float(ctx, 10.0f, &c, 200.0f, 10.0f); - - /* tiles */ - nk_layout_row(ctx, NK_STATIC, 200, 5, row_layout); - - /* left space */ - if (nk_group_begin(ctx, "left", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR)) { - nk_layout_row_dynamic(ctx, 25, 1); - nk_button_label(ctx, "#FFAA"); - nk_button_label(ctx, "#FFBB"); - nk_button_label(ctx, "#FFCC"); - nk_button_label(ctx, "#FFDD"); - nk_button_label(ctx, "#FFEE"); - nk_button_label(ctx, "#FFFF"); - nk_group_end(ctx); - } - - /* scaler */ - bounds = nk_widget_bounds(ctx); - nk_spacing(ctx, 1); - if ((nk_input_is_mouse_hovering_rect(in, bounds) || - nk_input_is_mouse_prev_hovering_rect(in, bounds)) && - nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) - { - a = row_layout[0] + in->mouse.delta.x; - b = row_layout[2] - in->mouse.delta.x; - } - - /* middle space */ - if (nk_group_begin(ctx, "center", NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR)) { - nk_layout_row_dynamic(ctx, 25, 1); - nk_button_label(ctx, "#FFAA"); - nk_button_label(ctx, "#FFBB"); - nk_button_label(ctx, "#FFCC"); - nk_button_label(ctx, "#FFDD"); - nk_button_label(ctx, "#FFEE"); - nk_button_label(ctx, "#FFFF"); - nk_group_end(ctx); - } - - /* scaler */ - bounds = nk_widget_bounds(ctx); - nk_spacing(ctx, 1); - if ((nk_input_is_mouse_hovering_rect(in, bounds) || - nk_input_is_mouse_prev_hovering_rect(in, bounds)) && - nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) - { - b = (row_layout[2] + in->mouse.delta.x); - c = (row_layout[4] - in->mouse.delta.x); - } - - /* right space */ - if (nk_group_begin(ctx, "right", NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR)) { - nk_layout_row_dynamic(ctx, 25, 1); - nk_button_label(ctx, "#FFAA"); - nk_button_label(ctx, "#FFBB"); - nk_button_label(ctx, "#FFCC"); - nk_button_label(ctx, "#FFDD"); - nk_button_label(ctx, "#FFEE"); - nk_button_label(ctx, "#FFFF"); - nk_group_end(ctx); - } - - nk_tree_pop(ctx); - } - - if (nk_tree_push(ctx, NK_TREE_NODE, "Horizontal", NK_MINIMIZED)) - { - static float a = 100, b = 100, c = 100; - struct nk_rect bounds; - - /* header */ - nk_layout_row_static(ctx, 30, 100, 2); - nk_label(ctx, "top:", NK_TEXT_LEFT); - nk_slider_float(ctx, 10.0f, &a, 200.0f, 10.0f); - - nk_label(ctx, "middle:", NK_TEXT_LEFT); - nk_slider_float(ctx, 10.0f, &b, 200.0f, 10.0f); - - nk_label(ctx, "bottom:", NK_TEXT_LEFT); - nk_slider_float(ctx, 10.0f, &c, 200.0f, 10.0f); - - /* top space */ - nk_layout_row_dynamic(ctx, a, 1); - if (nk_group_begin(ctx, "top", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER)) { - nk_layout_row_dynamic(ctx, 25, 3); - nk_button_label(ctx, "#FFAA"); - nk_button_label(ctx, "#FFBB"); - nk_button_label(ctx, "#FFCC"); - nk_button_label(ctx, "#FFDD"); - nk_button_label(ctx, "#FFEE"); - nk_button_label(ctx, "#FFFF"); - nk_group_end(ctx); - } - - /* scaler */ - nk_layout_row_dynamic(ctx, 8, 1); - bounds = nk_widget_bounds(ctx); - nk_spacing(ctx, 1); - if ((nk_input_is_mouse_hovering_rect(in, bounds) || - nk_input_is_mouse_prev_hovering_rect(in, bounds)) && - nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) - { - a = a + in->mouse.delta.y; - b = b - in->mouse.delta.y; - } - - /* middle space */ - nk_layout_row_dynamic(ctx, b, 1); - if (nk_group_begin(ctx, "middle", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER)) { - nk_layout_row_dynamic(ctx, 25, 3); - nk_button_label(ctx, "#FFAA"); - nk_button_label(ctx, "#FFBB"); - nk_button_label(ctx, "#FFCC"); - nk_button_label(ctx, "#FFDD"); - nk_button_label(ctx, "#FFEE"); - nk_button_label(ctx, "#FFFF"); - nk_group_end(ctx); - } - - { - /* scaler */ - nk_layout_row_dynamic(ctx, 8, 1); - bounds = nk_widget_bounds(ctx); - if ((nk_input_is_mouse_hovering_rect(in, bounds) || - nk_input_is_mouse_prev_hovering_rect(in, bounds)) && - nk_input_is_mouse_down(in, NK_BUTTON_LEFT)) - { - b = b + in->mouse.delta.y; - c = c - in->mouse.delta.y; - } - } - - /* bottom space */ - nk_layout_row_dynamic(ctx, c, 1); - if (nk_group_begin(ctx, "bottom", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER)) { - nk_layout_row_dynamic(ctx, 25, 3); - nk_button_label(ctx, "#FFAA"); - nk_button_label(ctx, "#FFBB"); - nk_button_label(ctx, "#FFCC"); - nk_button_label(ctx, "#FFDD"); - nk_button_label(ctx, "#FFEE"); - nk_button_label(ctx, "#FFFF"); - nk_group_end(ctx); - } - nk_tree_pop(ctx); - } - nk_tree_pop(ctx); - } - nk_tree_pop(ctx); - } - } - nk_end(ctx); - return !nk_window_is_closed(ctx, "Overview"); -} - diff --git a/deps/nuklear/demo/sdl_opengl2/main.c b/deps/nuklear/demo/sdl_opengl2/main.c deleted file mode 100644 index 0d96551c..00000000 --- a/deps/nuklear/demo/sdl_opengl2/main.c +++ /dev/null @@ -1,181 +0,0 @@ -/* nuklear - v1.17 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#define NK_SDL_GL2_IMPLEMENTATION -#include "../../nuklear.h" -#include "nuklear_sdl_gl2.h" - -#define WINDOW_WIDTH 1200 -#define WINDOW_HEIGHT 800 - -#define MAX_VERTEX_MEMORY 512 * 1024 -#define MAX_ELEMENT_MEMORY 128 * 1024 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* This are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the include - * and the corresponding function. */ -/*#include "../style.c"*/ -/*#include "../calculator.c"*/ -/*#include "../overview.c"*/ -/*#include "../node_editor.c"*/ - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -int -main(int argc, char* argv[]) -{ - /* Platform */ - SDL_Window *win; - SDL_GLContext glContext; - struct nk_color background; - int win_width, win_height; - int running = 1; - - /* GUI */ - struct nk_context *ctx; - - /* SDL setup */ - SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0"); - SDL_Init(SDL_INIT_VIDEO); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); - SDL_GL_SetAttribute(SDL_GL_STENCIL_SIZE, 8); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2); - win = SDL_CreateWindow("Demo", - SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_ALLOW_HIGHDPI); - glContext = SDL_GL_CreateContext(win); - SDL_GetWindowSize(win, &win_width, &win_height); - - /* GUI */ - ctx = nk_sdl_init(win); - /* Load Fonts: if none of these are loaded a default font will be used */ - /* Load Cursor: if you uncomment cursor loading please hide the cursor */ - {struct nk_font_atlas *atlas; - nk_sdl_font_stash_begin(&atlas); - /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/ - /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 16, 0);*/ - /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/ - /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/ - /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/ - /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/ - nk_sdl_font_stash_end(); - /*nk_style_load_all_cursors(ctx, atlas->cursors);*/ - /*nk_style_set_font(ctx, &roboto->handle)*/;} - - /* style.c */ - /*set_style(ctx, THEME_WHITE);*/ - /*set_style(ctx, THEME_RED);*/ - /*set_style(ctx, THEME_BLUE);*/ - /*set_style(ctx, THEME_DARK);*/ - - background = nk_rgb(28,48,62); - while (running) - { - /* Input */ - SDL_Event evt; - nk_input_begin(ctx); - while (SDL_PollEvent(&evt)) { - if (evt.type == SDL_QUIT) goto cleanup; - nk_sdl_handle_event(&evt); - } - nk_input_end(ctx); - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 210, 250), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - nk_layout_row_dynamic(ctx, 25, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - - nk_layout_row_dynamic(ctx, 20, 1); - nk_label(ctx, "background:", NK_TEXT_LEFT); - nk_layout_row_dynamic(ctx, 25, 1); - if (nk_combo_begin_color(ctx, background, nk_vec2(nk_widget_width(ctx),400))) { - nk_layout_row_dynamic(ctx, 120, 1); - background = nk_color_picker(ctx, background, NK_RGBA); - nk_layout_row_dynamic(ctx, 25, 1); - background.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, background.r, 255, 1,1); - background.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, background.g, 255, 1,1); - background.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, background.b, 255, 1,1); - background.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, background.a, 255, 1,1); - nk_combo_end(ctx); - } - } - nk_end(ctx); - - /* -------------- EXAMPLES ---------------- */ - /*calculator(ctx);*/ - /*overview(ctx);*/ - /*node_editor(ctx);*/ - /* ----------------------------------------- */ - - /* Draw */ - {float bg[4]; - nk_color_fv(bg, background); - SDL_GetWindowSize(win, &win_width, &win_height); - glViewport(0, 0, win_width, win_height); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(bg[0], bg[1], bg[2], bg[3]); - /* IMPORTANT: `nk_sdl_render` modifies some global OpenGL state - * with blending, scissor, face culling, depth test and viewport and - * defaults everything back into a default state. - * Make sure to either a.) save and restore or b.) reset your own state after - * rendering the UI. */ - nk_sdl_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_MEMORY, MAX_ELEMENT_MEMORY); - SDL_GL_SwapWindow(win);} - } - -cleanup: - nk_sdl_shutdown(); - SDL_GL_DeleteContext(glContext); - SDL_DestroyWindow(win); - SDL_Quit(); - return 0; -} - diff --git a/deps/nuklear/demo/sdl_opengl2/nuklear_sdl_gl2.h b/deps/nuklear/demo/sdl_opengl2/nuklear_sdl_gl2.h deleted file mode 100644 index 45c59702..00000000 --- a/deps/nuklear/demo/sdl_opengl2/nuklear_sdl_gl2.h +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Nuklear - v1.17 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_SDL_GL2_H_ -#define NK_SDL_GL2_H_ - -#include -NK_API struct nk_context* nk_sdl_init(SDL_Window *win); -NK_API void nk_sdl_font_stash_begin(struct nk_font_atlas **atlas); -NK_API void nk_sdl_font_stash_end(void); -NK_API int nk_sdl_handle_event(SDL_Event *evt); -NK_API void nk_sdl_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer); -NK_API void nk_sdl_shutdown(void); - -#endif -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_SDL_GL2_IMPLEMENTATION - -struct nk_sdl_device { - struct nk_buffer cmds; - struct nk_draw_null_texture null; - GLuint font_tex; -}; - -struct nk_sdl_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -static struct nk_sdl { - SDL_Window *win; - struct nk_sdl_device ogl; - struct nk_context ctx; - struct nk_font_atlas atlas; -} sdl; - -NK_INTERN void -nk_sdl_device_upload_atlas(const void *image, int width, int height) -{ - struct nk_sdl_device *dev = &sdl.ogl; - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - -NK_API void -nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) -{ - /* setup global state */ - struct nk_sdl_device *dev = &sdl.ogl; - int width, height; - int display_width, display_height; - struct nk_vec2 scale; - - SDL_GetWindowSize(sdl.win, &width, &height); - SDL_GL_GetDrawableSize(sdl.win, &display_width, &display_height); - scale.x = (float)display_width/(float)width; - scale.y = (float)display_height/(float)height; - - glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - /* setup viewport/project */ - glViewport(0,0,(GLsizei)display_width,(GLsizei)display_height); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - { - GLsizei vs = sizeof(struct nk_sdl_vertex); - size_t vp = offsetof(struct nk_sdl_vertex, position); - size_t vt = offsetof(struct nk_sdl_vertex, uv); - size_t vc = offsetof(struct nk_sdl_vertex, col); - - /* convert from command queue into draw list and draw to screen */ - const struct nk_draw_command *cmd; - const nk_draw_index *offset = NULL; - struct nk_buffer vbuf, ebuf; - - /* fill converting configuration */ - struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sdl_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sdl_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_sdl_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - NK_MEMSET(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_sdl_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_sdl_vertex); - config.null = dev->null; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - - /* convert shapes into vertexes */ - nk_buffer_init_default(&vbuf); - nk_buffer_init_default(&ebuf); - nk_convert(&sdl.ctx, &dev->cmds, &vbuf, &ebuf, &config); - - /* setup vertex buffer pointer */ - {const void *vertices = nk_buffer_memory_const(&vbuf); - glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp)); - glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt)); - glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));} - - /* iterate over and execute each draw command */ - offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf); - nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds) - { - if (!cmd->elem_count) continue; - glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor( - (GLint)(cmd->clip_rect.x * scale.x), - (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), - (GLint)(cmd->clip_rect.w * scale.x), - (GLint)(cmd->clip_rect.h * scale.y)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); - offset += cmd->elem_count; - } - nk_clear(&sdl.ctx); - nk_buffer_free(&vbuf); - nk_buffer_free(&ebuf); - } - - /* default OpenGL state */ - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, 0); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glPopAttrib(); -} - -static void -nk_sdl_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) -{ - const char *text = SDL_GetClipboardText(); - if (text) nk_textedit_paste(edit, text, nk_strlen(text)); - (void)usr; -} - -static void -nk_sdl_clipbard_copy(nk_handle usr, const char *text, int len) -{ - char *str = 0; - (void)usr; - if (!len) return; - str = (char*)malloc((size_t)len+1); - if (!str) return; - memcpy(str, text, (size_t)len); - str[len] = '\0'; - SDL_SetClipboardText(str); - free(str); -} - -NK_API struct nk_context* -nk_sdl_init(SDL_Window *win) -{ - sdl.win = win; - nk_init_default(&sdl.ctx, 0); - sdl.ctx.clip.copy = nk_sdl_clipbard_copy; - sdl.ctx.clip.paste = nk_sdl_clipbard_paste; - sdl.ctx.clip.userdata = nk_handle_ptr(0); - nk_buffer_init_default(&sdl.ogl.cmds); - return &sdl.ctx; -} - -NK_API void -nk_sdl_font_stash_begin(struct nk_font_atlas **atlas) -{ - nk_font_atlas_init_default(&sdl.atlas); - nk_font_atlas_begin(&sdl.atlas); - *atlas = &sdl.atlas; -} - -NK_API void -nk_sdl_font_stash_end(void) -{ - const void *image; int w, h; - image = nk_font_atlas_bake(&sdl.atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - nk_sdl_device_upload_atlas(image, w, h); - nk_font_atlas_end(&sdl.atlas, nk_handle_id((int)sdl.ogl.font_tex), &sdl.ogl.null); - if (sdl.atlas.default_font) - nk_style_set_font(&sdl.ctx, &sdl.atlas.default_font->handle); -} - -NK_API int -nk_sdl_handle_event(SDL_Event *evt) -{ - struct nk_context *ctx = &sdl.ctx; - - /* optional grabbing behavior */ - if (ctx->input.mouse.grab) { - SDL_SetRelativeMouseMode(SDL_TRUE); - ctx->input.mouse.grab = 0; - } else if (ctx->input.mouse.ungrab) { - int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y; - SDL_SetRelativeMouseMode(SDL_FALSE); - SDL_WarpMouseInWindow(sdl.win, x, y); - ctx->input.mouse.ungrab = 0; - } - if (evt->type == SDL_KEYUP || evt->type == SDL_KEYDOWN) { - /* key events */ - int down = evt->type == SDL_KEYDOWN; - const Uint8* state = SDL_GetKeyboardState(0); - SDL_Keycode sym = evt->key.keysym.sym; - if (sym == SDLK_RSHIFT || sym == SDLK_LSHIFT) - nk_input_key(ctx, NK_KEY_SHIFT, down); - else if (sym == SDLK_DELETE) - nk_input_key(ctx, NK_KEY_DEL, down); - else if (sym == SDLK_RETURN) - nk_input_key(ctx, NK_KEY_ENTER, down); - else if (sym == SDLK_TAB) - nk_input_key(ctx, NK_KEY_TAB, down); - else if (sym == SDLK_BACKSPACE) - nk_input_key(ctx, NK_KEY_BACKSPACE, down); - else if (sym == SDLK_HOME) { - nk_input_key(ctx, NK_KEY_TEXT_START, down); - nk_input_key(ctx, NK_KEY_SCROLL_START, down); - } else if (sym == SDLK_END) { - nk_input_key(ctx, NK_KEY_TEXT_END, down); - nk_input_key(ctx, NK_KEY_SCROLL_END, down); - } else if (sym == SDLK_PAGEDOWN) { - nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); - } else if (sym == SDLK_PAGEUP) { - nk_input_key(ctx, NK_KEY_SCROLL_UP, down); - } else if (sym == SDLK_z) - nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_r) - nk_input_key(ctx, NK_KEY_TEXT_REDO, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_c) - nk_input_key(ctx, NK_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_v) - nk_input_key(ctx, NK_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_x) - nk_input_key(ctx, NK_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_b) - nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_e) - nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_UP) - nk_input_key(ctx, NK_KEY_UP, down); - else if (sym == SDLK_DOWN) - nk_input_key(ctx, NK_KEY_DOWN, down); - else if (sym == SDLK_LEFT) { - if (state[SDL_SCANCODE_LCTRL]) - nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down); - else nk_input_key(ctx, NK_KEY_LEFT, down); - } else if (sym == SDLK_RIGHT) { - if (state[SDL_SCANCODE_LCTRL]) - nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down); - else nk_input_key(ctx, NK_KEY_RIGHT, down); - } else return 0; - return 1; - } else if (evt->type == SDL_MOUSEBUTTONDOWN || evt->type == SDL_MOUSEBUTTONUP) { - /* mouse button */ - int down = evt->type == SDL_MOUSEBUTTONDOWN; - const int x = evt->button.x, y = evt->button.y; - if (evt->button.button == SDL_BUTTON_LEFT) - nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); - if (evt->button.button == SDL_BUTTON_MIDDLE) - nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); - if (evt->button.button == SDL_BUTTON_RIGHT) - nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); - else return 0; - return 1; - } else if (evt->type == SDL_MOUSEMOTION) { - if (ctx->input.mouse.grabbed) { - int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y; - nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel); - } else nk_input_motion(ctx, evt->motion.x, evt->motion.y); - return 1; - } else if (evt->type == SDL_TEXTINPUT) { - nk_glyph glyph; - memcpy(glyph, evt->text.text, NK_UTF_SIZE); - nk_input_glyph(ctx, glyph); - return 1; - } else if (evt->type == SDL_MOUSEWHEEL) { - nk_input_scroll(ctx,(float)evt->wheel.y); - return 1; - } - return 0; -} - -NK_API -void nk_sdl_shutdown(void) -{ - struct nk_sdl_device *dev = &sdl.ogl; - nk_font_atlas_clear(&sdl.atlas); - nk_free(&sdl.ctx); - glDeleteTextures(1, &dev->font_tex); - nk_buffer_free(&dev->cmds); - memset(&sdl, 0, sizeof(sdl)); -} - -#endif diff --git a/deps/nuklear/demo/sdl_opengl3/main.c b/deps/nuklear/demo/sdl_opengl3/main.c deleted file mode 100644 index aee4f827..00000000 --- a/deps/nuklear/demo/sdl_opengl3/main.c +++ /dev/null @@ -1,195 +0,0 @@ -/* nuklear - v1.17 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#define NK_SDL_GL3_IMPLEMENTATION -#include "../../nuklear.h" -#include "nuklear_sdl_gl3.h" - -#define WINDOW_WIDTH 800 -#define WINDOW_HEIGHT 600 - -#define MAX_VERTEX_MEMORY 512 * 1024 -#define MAX_ELEMENT_MEMORY 128 * 1024 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* This are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the include - * and the corresponding function. */ -/*#include "../style.c"*/ -/*#include "../calculator.c"*/ -/*#include "../overview.c"*/ -/*#include "../node_editor.c"*/ - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -int -main(int argc, char* argv[]) -{ - /* Platform */ - SDL_Window *win; - SDL_GLContext glContext; - struct nk_color background; - int win_width, win_height; - int running = 1; - - /* GUI */ - struct nk_context *ctx; - - /* SDL setup */ - SDL_SetHint(SDL_HINT_VIDEO_HIGHDPI_DISABLED, "0"); - SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_EVENTS); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG); - SDL_GL_SetAttribute (SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); - SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); - win = SDL_CreateWindow("Demo", - SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, - WINDOW_WIDTH, WINDOW_HEIGHT, SDL_WINDOW_OPENGL|SDL_WINDOW_SHOWN|SDL_WINDOW_ALLOW_HIGHDPI); - glContext = SDL_GL_CreateContext(win); - SDL_GetWindowSize(win, &win_width, &win_height); - - /* OpenGL setup */ - glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); - glewExperimental = 1; - if (glewInit() != GLEW_OK) { - fprintf(stderr, "Failed to setup GLEW\n"); - exit(1); - } - - ctx = nk_sdl_init(win); - /* Load Fonts: if none of these are loaded a default font will be used */ - /* Load Cursor: if you uncomment cursor loading please hide the cursor */ - {struct nk_font_atlas *atlas; - nk_sdl_font_stash_begin(&atlas); - /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/ - /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 16, 0);*/ - /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/ - /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/ - /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/ - /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/ - nk_sdl_font_stash_end(); - /*nk_style_load_all_cursors(ctx, atlas->cursors);*/ - /*nk_style_set_font(ctx, &roboto->handle)*/;} - - /* style.c */ - /*set_style(ctx, THEME_WHITE);*/ - /*set_style(ctx, THEME_RED);*/ - /*set_style(ctx, THEME_BLUE);*/ - /*set_style(ctx, THEME_DARK);*/ - - background = nk_rgb(28,48,62); - while (running) - { - /* Input */ - SDL_Event evt; - nk_input_begin(ctx); - while (SDL_PollEvent(&evt)) { - if (evt.type == SDL_QUIT) goto cleanup; - nk_sdl_handle_event(&evt); - } - nk_input_end(ctx); - - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 200, 200), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - nk_menubar_begin(ctx); - nk_layout_row_begin(ctx, NK_STATIC, 25, 2); - nk_layout_row_push(ctx, 45); - if (nk_menu_begin_label(ctx, "FILE", NK_TEXT_LEFT, nk_vec2(120, 200))) { - nk_layout_row_dynamic(ctx, 30, 1); - nk_menu_item_label(ctx, "OPEN", NK_TEXT_LEFT); - nk_menu_item_label(ctx, "CLOSE", NK_TEXT_LEFT); - nk_menu_end(ctx); - } - nk_layout_row_push(ctx, 45); - if (nk_menu_begin_label(ctx, "EDIT", NK_TEXT_LEFT, nk_vec2(120, 200))) { - nk_layout_row_dynamic(ctx, 30, 1); - nk_menu_item_label(ctx, "COPY", NK_TEXT_LEFT); - nk_menu_item_label(ctx, "CUT", NK_TEXT_LEFT); - nk_menu_item_label(ctx, "PASTE", NK_TEXT_LEFT); - nk_menu_end(ctx); - } - nk_layout_row_end(ctx); - nk_menubar_end(ctx); - - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - nk_layout_row_dynamic(ctx, 25, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - } - nk_end(ctx); - - /* -------------- EXAMPLES ---------------- */ - /*calculator(ctx);*/ - /*overview(ctx);*/ - /*node_editor(ctx);*/ - /* ----------------------------------------- */ - - /* Draw */ - {float bg[4]; - nk_color_fv(bg, background); - SDL_GetWindowSize(win, &win_width, &win_height); - glViewport(0, 0, win_width, win_height); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(bg[0], bg[1], bg[2], bg[3]); - /* IMPORTANT: `nk_sdl_render` modifies some global OpenGL state - * with blending, scissor, face culling, depth test and viewport and - * defaults everything back into a default state. - * Make sure to either a.) save and restore or b.) reset your own state after - * rendering the UI. */ - nk_sdl_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_MEMORY, MAX_ELEMENT_MEMORY); - SDL_GL_SwapWindow(win);} - } - -cleanup: - nk_sdl_shutdown(); - SDL_GL_DeleteContext(glContext); - SDL_DestroyWindow(win); - SDL_Quit(); - return 0; -} - diff --git a/deps/nuklear/demo/sdl_opengl3/nuklear_sdl_gl3.h b/deps/nuklear/demo/sdl_opengl3/nuklear_sdl_gl3.h deleted file mode 100644 index 17c0899d..00000000 --- a/deps/nuklear/demo/sdl_opengl3/nuklear_sdl_gl3.h +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Nuklear - v1.17 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_SDL_GL3_H_ -#define NK_SDL_GL3_H_ - -#include -#include - -NK_API struct nk_context* nk_sdl_init(SDL_Window *win); -NK_API void nk_sdl_font_stash_begin(struct nk_font_atlas **atlas); -NK_API void nk_sdl_font_stash_end(void); -NK_API int nk_sdl_handle_event(SDL_Event *evt); -NK_API void nk_sdl_render(enum nk_anti_aliasing , int max_vertex_buffer, int max_element_buffer); -NK_API void nk_sdl_shutdown(void); -NK_API void nk_sdl_device_destroy(void); -NK_API void nk_sdl_device_create(void); - -#endif - -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_SDL_GL3_IMPLEMENTATION - -#include - -struct nk_sdl_device { - struct nk_buffer cmds; - struct nk_draw_null_texture null; - GLuint vbo, vao, ebo; - GLuint prog; - GLuint vert_shdr; - GLuint frag_shdr; - GLint attrib_pos; - GLint attrib_uv; - GLint attrib_col; - GLint uniform_tex; - GLint uniform_proj; - GLuint font_tex; -}; - -struct nk_sdl_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -static struct nk_sdl { - SDL_Window *win; - struct nk_sdl_device ogl; - struct nk_context ctx; - struct nk_font_atlas atlas; -} sdl; - -#ifdef __APPLE__ - #define NK_SHADER_VERSION "#version 150\n" -#else - #define NK_SHADER_VERSION "#version 300 es\n" -#endif -NK_API void -nk_sdl_device_create(void) -{ - GLint status; - static const GLchar *vertex_shader = - NK_SHADER_VERSION - "uniform mat4 ProjMtx;\n" - "in vec2 Position;\n" - "in vec2 TexCoord;\n" - "in vec4 Color;\n" - "out vec2 Frag_UV;\n" - "out vec4 Frag_Color;\n" - "void main() {\n" - " Frag_UV = TexCoord;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" - "}\n"; - static const GLchar *fragment_shader = - NK_SHADER_VERSION - "precision mediump float;\n" - "uniform sampler2D Texture;\n" - "in vec2 Frag_UV;\n" - "in vec4 Frag_Color;\n" - "out vec4 Out_Color;\n" - "void main(){\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" - "}\n"; - - struct nk_sdl_device *dev = &sdl.ogl; - nk_buffer_init_default(&dev->cmds); - dev->prog = glCreateProgram(); - dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); - dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); - glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); - glCompileShader(dev->vert_shdr); - glCompileShader(dev->frag_shdr); - glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glAttachShader(dev->prog, dev->vert_shdr); - glAttachShader(dev->prog, dev->frag_shdr); - glLinkProgram(dev->prog); - glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); - assert(status == GL_TRUE); - - dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); - dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); - dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); - dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); - dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); - - { - /* buffer setup */ - GLsizei vs = sizeof(struct nk_sdl_vertex); - size_t vp = offsetof(struct nk_sdl_vertex, position); - size_t vt = offsetof(struct nk_sdl_vertex, uv); - size_t vc = offsetof(struct nk_sdl_vertex, col); - - glGenBuffers(1, &dev->vbo); - glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); - - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); - } - - glBindTexture(GL_TEXTURE_2D, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); -} - -NK_INTERN void -nk_sdl_device_upload_atlas(const void *image, int width, int height) -{ - struct nk_sdl_device *dev = &sdl.ogl; - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - -NK_API void -nk_sdl_device_destroy(void) -{ - struct nk_sdl_device *dev = &sdl.ogl; - glDetachShader(dev->prog, dev->vert_shdr); - glDetachShader(dev->prog, dev->frag_shdr); - glDeleteShader(dev->vert_shdr); - glDeleteShader(dev->frag_shdr); - glDeleteProgram(dev->prog); - glDeleteTextures(1, &dev->font_tex); - glDeleteBuffers(1, &dev->vbo); - glDeleteBuffers(1, &dev->ebo); - nk_buffer_free(&dev->cmds); -} - -NK_API void -nk_sdl_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) -{ - struct nk_sdl_device *dev = &sdl.ogl; - int width, height; - int display_width, display_height; - struct nk_vec2 scale; - GLfloat ortho[4][4] = { - {2.0f, 0.0f, 0.0f, 0.0f}, - {0.0f,-2.0f, 0.0f, 0.0f}, - {0.0f, 0.0f,-1.0f, 0.0f}, - {-1.0f,1.0f, 0.0f, 1.0f}, - }; - SDL_GetWindowSize(sdl.win, &width, &height); - SDL_GL_GetDrawableSize(sdl.win, &display_width, &display_height); - ortho[0][0] /= (GLfloat)width; - ortho[1][1] /= (GLfloat)height; - - scale.x = (float)display_width/(float)width; - scale.y = (float)display_height/(float)height; - - /* setup global state */ - glViewport(0,0,display_width,display_height); - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - /* setup program */ - glUseProgram(dev->prog); - glUniform1i(dev->uniform_tex, 0); - glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); - { - /* convert from command queue into draw list and draw to screen */ - const struct nk_draw_command *cmd; - void *vertices, *elements; - const nk_draw_index *offset = NULL; - - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW); - - /* load vertices/elements directly into vertex/element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); - { - /* fill convert configuration */ - struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sdl_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_sdl_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_sdl_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - NK_MEMSET(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_sdl_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_sdl_vertex); - config.null = dev->null; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - - /* setup buffers to load vertices and elements */ - {struct nk_buffer vbuf, ebuf; - nk_buffer_init_fixed(&vbuf, vertices, (nk_size)max_vertex_buffer); - nk_buffer_init_fixed(&ebuf, elements, (nk_size)max_element_buffer); - nk_convert(&sdl.ctx, &dev->cmds, &vbuf, &ebuf, &config);} - } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - - /* iterate over and execute each draw command */ - nk_draw_foreach(cmd, &sdl.ctx, &dev->cmds) { - if (!cmd->elem_count) continue; - glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor((GLint)(cmd->clip_rect.x * scale.x), - (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), - (GLint)(cmd->clip_rect.w * scale.x), - (GLint)(cmd->clip_rect.h * scale.y)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); - offset += cmd->elem_count; - } - nk_clear(&sdl.ctx); - } - - glUseProgram(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); -} - -static void -nk_sdl_clipbard_paste(nk_handle usr, struct nk_text_edit *edit) -{ - const char *text = SDL_GetClipboardText(); - if (text) nk_textedit_paste(edit, text, nk_strlen(text)); - (void)usr; -} - -static void -nk_sdl_clipbard_copy(nk_handle usr, const char *text, int len) -{ - char *str = 0; - (void)usr; - if (!len) return; - str = (char*)malloc((size_t)len+1); - if (!str) return; - memcpy(str, text, (size_t)len); - str[len] = '\0'; - SDL_SetClipboardText(str); - free(str); -} - -NK_API struct nk_context* -nk_sdl_init(SDL_Window *win) -{ - sdl.win = win; - nk_init_default(&sdl.ctx, 0); - sdl.ctx.clip.copy = nk_sdl_clipbard_copy; - sdl.ctx.clip.paste = nk_sdl_clipbard_paste; - sdl.ctx.clip.userdata = nk_handle_ptr(0); - nk_sdl_device_create(); - return &sdl.ctx; -} - -NK_API void -nk_sdl_font_stash_begin(struct nk_font_atlas **atlas) -{ - nk_font_atlas_init_default(&sdl.atlas); - nk_font_atlas_begin(&sdl.atlas); - *atlas = &sdl.atlas; -} - -NK_API void -nk_sdl_font_stash_end(void) -{ - const void *image; int w, h; - image = nk_font_atlas_bake(&sdl.atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - nk_sdl_device_upload_atlas(image, w, h); - nk_font_atlas_end(&sdl.atlas, nk_handle_id((int)sdl.ogl.font_tex), &sdl.ogl.null); - if (sdl.atlas.default_font) - nk_style_set_font(&sdl.ctx, &sdl.atlas.default_font->handle); - -} - -NK_API int -nk_sdl_handle_event(SDL_Event *evt) -{ - struct nk_context *ctx = &sdl.ctx; - if (evt->type == SDL_KEYUP || evt->type == SDL_KEYDOWN) { - /* key events */ - int down = evt->type == SDL_KEYDOWN; - const Uint8* state = SDL_GetKeyboardState(0); - SDL_Keycode sym = evt->key.keysym.sym; - if (sym == SDLK_RSHIFT || sym == SDLK_LSHIFT) - nk_input_key(ctx, NK_KEY_SHIFT, down); - else if (sym == SDLK_DELETE) - nk_input_key(ctx, NK_KEY_DEL, down); - else if (sym == SDLK_RETURN) - nk_input_key(ctx, NK_KEY_ENTER, down); - else if (sym == SDLK_TAB) - nk_input_key(ctx, NK_KEY_TAB, down); - else if (sym == SDLK_BACKSPACE) - nk_input_key(ctx, NK_KEY_BACKSPACE, down); - else if (sym == SDLK_HOME) { - nk_input_key(ctx, NK_KEY_TEXT_START, down); - nk_input_key(ctx, NK_KEY_SCROLL_START, down); - } else if (sym == SDLK_END) { - nk_input_key(ctx, NK_KEY_TEXT_END, down); - nk_input_key(ctx, NK_KEY_SCROLL_END, down); - } else if (sym == SDLK_PAGEDOWN) { - nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); - } else if (sym == SDLK_PAGEUP) { - nk_input_key(ctx, NK_KEY_SCROLL_UP, down); - } else if (sym == SDLK_z) - nk_input_key(ctx, NK_KEY_TEXT_UNDO, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_r) - nk_input_key(ctx, NK_KEY_TEXT_REDO, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_c) - nk_input_key(ctx, NK_KEY_COPY, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_v) - nk_input_key(ctx, NK_KEY_PASTE, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_x) - nk_input_key(ctx, NK_KEY_CUT, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_b) - nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_e) - nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down && state[SDL_SCANCODE_LCTRL]); - else if (sym == SDLK_UP) - nk_input_key(ctx, NK_KEY_UP, down); - else if (sym == SDLK_DOWN) - nk_input_key(ctx, NK_KEY_DOWN, down); - else if (sym == SDLK_LEFT) { - if (state[SDL_SCANCODE_LCTRL]) - nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down); - else nk_input_key(ctx, NK_KEY_LEFT, down); - } else if (sym == SDLK_RIGHT) { - if (state[SDL_SCANCODE_LCTRL]) - nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down); - else nk_input_key(ctx, NK_KEY_RIGHT, down); - } else return 0; - return 1; - } else if (evt->type == SDL_MOUSEBUTTONDOWN || evt->type == SDL_MOUSEBUTTONUP) { - /* mouse button */ - int down = evt->type == SDL_MOUSEBUTTONDOWN; - const int x = evt->button.x, y = evt->button.y; - if (evt->button.button == SDL_BUTTON_LEFT) - nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); - if (evt->button.button == SDL_BUTTON_MIDDLE) - nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); - if (evt->button.button == SDL_BUTTON_RIGHT) - nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); - return 1; - } else if (evt->type == SDL_MOUSEMOTION) { - if (ctx->input.mouse.grabbed) { - int x = (int)ctx->input.mouse.prev.x, y = (int)ctx->input.mouse.prev.y; - nk_input_motion(ctx, x + evt->motion.xrel, y + evt->motion.yrel); - } else nk_input_motion(ctx, evt->motion.x, evt->motion.y); - return 1; - } else if (evt->type == SDL_TEXTINPUT) { - nk_glyph glyph; - memcpy(glyph, evt->text.text, NK_UTF_SIZE); - nk_input_glyph(ctx, glyph); - return 1; - } else if (evt->type == SDL_MOUSEWHEEL) { - nk_input_scroll(ctx,(float)evt->wheel.y); - return 1; - } - return 0; -} - -NK_API -void nk_sdl_shutdown(void) -{ - nk_font_atlas_clear(&sdl.atlas); - nk_free(&sdl.ctx); - nk_sdl_device_destroy(); - memset(&sdl, 0, sizeof(sdl)); -} - -#endif diff --git a/deps/nuklear/demo/style.c b/deps/nuklear/demo/style.c deleted file mode 100644 index 8cea1521..00000000 --- a/deps/nuklear/demo/style.c +++ /dev/null @@ -1,132 +0,0 @@ -enum theme {THEME_BLACK, THEME_WHITE, THEME_RED, THEME_BLUE, THEME_DARK}; - -void -set_style(struct nk_context *ctx, enum theme theme) -{ - struct nk_color table[NK_COLOR_COUNT]; - if (theme == THEME_WHITE) { - table[NK_COLOR_TEXT] = nk_rgba(70, 70, 70, 255); - table[NK_COLOR_WINDOW] = nk_rgba(175, 175, 175, 255); - table[NK_COLOR_HEADER] = nk_rgba(175, 175, 175, 255); - table[NK_COLOR_BORDER] = nk_rgba(0, 0, 0, 255); - table[NK_COLOR_BUTTON] = nk_rgba(185, 185, 185, 255); - table[NK_COLOR_BUTTON_HOVER] = nk_rgba(170, 170, 170, 255); - table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(160, 160, 160, 255); - table[NK_COLOR_TOGGLE] = nk_rgba(150, 150, 150, 255); - table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(120, 120, 120, 255); - table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(175, 175, 175, 255); - table[NK_COLOR_SELECT] = nk_rgba(190, 190, 190, 255); - table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(175, 175, 175, 255); - table[NK_COLOR_SLIDER] = nk_rgba(190, 190, 190, 255); - table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(80, 80, 80, 255); - table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(70, 70, 70, 255); - table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(60, 60, 60, 255); - table[NK_COLOR_PROPERTY] = nk_rgba(175, 175, 175, 255); - table[NK_COLOR_EDIT] = nk_rgba(150, 150, 150, 255); - table[NK_COLOR_EDIT_CURSOR] = nk_rgba(0, 0, 0, 255); - table[NK_COLOR_COMBO] = nk_rgba(175, 175, 175, 255); - table[NK_COLOR_CHART] = nk_rgba(160, 160, 160, 255); - table[NK_COLOR_CHART_COLOR] = nk_rgba(45, 45, 45, 255); - table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255); - table[NK_COLOR_SCROLLBAR] = nk_rgba(180, 180, 180, 255); - table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(140, 140, 140, 255); - table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(150, 150, 150, 255); - table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(160, 160, 160, 255); - table[NK_COLOR_TAB_HEADER] = nk_rgba(180, 180, 180, 255); - nk_style_from_table(ctx, table); - } else if (theme == THEME_RED) { - table[NK_COLOR_TEXT] = nk_rgba(190, 190, 190, 255); - table[NK_COLOR_WINDOW] = nk_rgba(30, 33, 40, 215); - table[NK_COLOR_HEADER] = nk_rgba(181, 45, 69, 220); - table[NK_COLOR_BORDER] = nk_rgba(51, 55, 67, 255); - table[NK_COLOR_BUTTON] = nk_rgba(181, 45, 69, 255); - table[NK_COLOR_BUTTON_HOVER] = nk_rgba(190, 50, 70, 255); - table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(195, 55, 75, 255); - table[NK_COLOR_TOGGLE] = nk_rgba(51, 55, 67, 255); - table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 60, 60, 255); - table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(181, 45, 69, 255); - table[NK_COLOR_SELECT] = nk_rgba(51, 55, 67, 255); - table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(181, 45, 69, 255); - table[NK_COLOR_SLIDER] = nk_rgba(51, 55, 67, 255); - table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(181, 45, 69, 255); - table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(186, 50, 74, 255); - table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(191, 55, 79, 255); - table[NK_COLOR_PROPERTY] = nk_rgba(51, 55, 67, 255); - table[NK_COLOR_EDIT] = nk_rgba(51, 55, 67, 225); - table[NK_COLOR_EDIT_CURSOR] = nk_rgba(190, 190, 190, 255); - table[NK_COLOR_COMBO] = nk_rgba(51, 55, 67, 255); - table[NK_COLOR_CHART] = nk_rgba(51, 55, 67, 255); - table[NK_COLOR_CHART_COLOR] = nk_rgba(170, 40, 60, 255); - table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255); - table[NK_COLOR_SCROLLBAR] = nk_rgba(30, 33, 40, 255); - table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255); - table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255); - table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255); - table[NK_COLOR_TAB_HEADER] = nk_rgba(181, 45, 69, 220); - nk_style_from_table(ctx, table); - } else if (theme == THEME_BLUE) { - table[NK_COLOR_TEXT] = nk_rgba(20, 20, 20, 255); - table[NK_COLOR_WINDOW] = nk_rgba(202, 212, 214, 215); - table[NK_COLOR_HEADER] = nk_rgba(137, 182, 224, 220); - table[NK_COLOR_BORDER] = nk_rgba(140, 159, 173, 255); - table[NK_COLOR_BUTTON] = nk_rgba(137, 182, 224, 255); - table[NK_COLOR_BUTTON_HOVER] = nk_rgba(142, 187, 229, 255); - table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(147, 192, 234, 255); - table[NK_COLOR_TOGGLE] = nk_rgba(177, 210, 210, 255); - table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(182, 215, 215, 255); - table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(137, 182, 224, 255); - table[NK_COLOR_SELECT] = nk_rgba(177, 210, 210, 255); - table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(137, 182, 224, 255); - table[NK_COLOR_SLIDER] = nk_rgba(177, 210, 210, 255); - table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(137, 182, 224, 245); - table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(142, 188, 229, 255); - table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(147, 193, 234, 255); - table[NK_COLOR_PROPERTY] = nk_rgba(210, 210, 210, 255); - table[NK_COLOR_EDIT] = nk_rgba(210, 210, 210, 225); - table[NK_COLOR_EDIT_CURSOR] = nk_rgba(20, 20, 20, 255); - table[NK_COLOR_COMBO] = nk_rgba(210, 210, 210, 255); - table[NK_COLOR_CHART] = nk_rgba(210, 210, 210, 255); - table[NK_COLOR_CHART_COLOR] = nk_rgba(137, 182, 224, 255); - table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba( 255, 0, 0, 255); - table[NK_COLOR_SCROLLBAR] = nk_rgba(190, 200, 200, 255); - table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(64, 84, 95, 255); - table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(70, 90, 100, 255); - table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(75, 95, 105, 255); - table[NK_COLOR_TAB_HEADER] = nk_rgba(156, 193, 220, 255); - nk_style_from_table(ctx, table); - } else if (theme == THEME_DARK) { - table[NK_COLOR_TEXT] = nk_rgba(210, 210, 210, 255); - table[NK_COLOR_WINDOW] = nk_rgba(57, 67, 71, 215); - table[NK_COLOR_HEADER] = nk_rgba(51, 51, 56, 220); - table[NK_COLOR_BORDER] = nk_rgba(46, 46, 46, 255); - table[NK_COLOR_BUTTON] = nk_rgba(48, 83, 111, 255); - table[NK_COLOR_BUTTON_HOVER] = nk_rgba(58, 93, 121, 255); - table[NK_COLOR_BUTTON_ACTIVE] = nk_rgba(63, 98, 126, 255); - table[NK_COLOR_TOGGLE] = nk_rgba(50, 58, 61, 255); - table[NK_COLOR_TOGGLE_HOVER] = nk_rgba(45, 53, 56, 255); - table[NK_COLOR_TOGGLE_CURSOR] = nk_rgba(48, 83, 111, 255); - table[NK_COLOR_SELECT] = nk_rgba(57, 67, 61, 255); - table[NK_COLOR_SELECT_ACTIVE] = nk_rgba(48, 83, 111, 255); - table[NK_COLOR_SLIDER] = nk_rgba(50, 58, 61, 255); - table[NK_COLOR_SLIDER_CURSOR] = nk_rgba(48, 83, 111, 245); - table[NK_COLOR_SLIDER_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255); - table[NK_COLOR_SLIDER_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255); - table[NK_COLOR_PROPERTY] = nk_rgba(50, 58, 61, 255); - table[NK_COLOR_EDIT] = nk_rgba(50, 58, 61, 225); - table[NK_COLOR_EDIT_CURSOR] = nk_rgba(210, 210, 210, 255); - table[NK_COLOR_COMBO] = nk_rgba(50, 58, 61, 255); - table[NK_COLOR_CHART] = nk_rgba(50, 58, 61, 255); - table[NK_COLOR_CHART_COLOR] = nk_rgba(48, 83, 111, 255); - table[NK_COLOR_CHART_COLOR_HIGHLIGHT] = nk_rgba(255, 0, 0, 255); - table[NK_COLOR_SCROLLBAR] = nk_rgba(50, 58, 61, 255); - table[NK_COLOR_SCROLLBAR_CURSOR] = nk_rgba(48, 83, 111, 255); - table[NK_COLOR_SCROLLBAR_CURSOR_HOVER] = nk_rgba(53, 88, 116, 255); - table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE] = nk_rgba(58, 93, 121, 255); - table[NK_COLOR_TAB_HEADER] = nk_rgba(48, 83, 111, 255); - nk_style_from_table(ctx, table); - } else { - nk_style_default(ctx); - } -} - - diff --git a/deps/nuklear/demo/x11/main.c b/deps/nuklear/demo/x11/main.c deleted file mode 100644 index 8f4b12c7..00000000 --- a/deps/nuklear/demo/x11/main.c +++ /dev/null @@ -1,203 +0,0 @@ -/* nuklear - v1.17 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_IMPLEMENTATION -#define NK_XLIB_IMPLEMENTATION -#include "../../nuklear.h" -#include "nuklear_xlib.h" - -#define DTIME 20 -#define WINDOW_WIDTH 800 -#define WINDOW_HEIGHT 600 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -typedef struct XWindow XWindow; -struct XWindow { - Display *dpy; - Window root; - Visual *vis; - Colormap cmap; - XWindowAttributes attr; - XSetWindowAttributes swa; - Window win; - int screen; - XFont *font; - unsigned int width; - unsigned int height; -}; - -static void -die(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputs("\n", stderr); - exit(EXIT_FAILURE); -} - -static void* -xcalloc(size_t siz, size_t n) -{ - void *ptr = calloc(siz, n); - if (!ptr) die("Out of memory\n"); - return ptr; -} - -static long -timestamp(void) -{ - struct timeval tv; - if (gettimeofday(&tv, NULL) < 0) return 0; - return (long)((long)tv.tv_sec * 1000 + (long)tv.tv_usec/1000); -} - -static void -sleep_for(long t) -{ - struct timespec req; - const time_t sec = (int)(t/1000); - const long ms = t - (sec * 1000); - req.tv_sec = sec; - req.tv_nsec = ms * 1000000L; - while(-1 == nanosleep(&req, &req)); -} - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* This are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the include - * and the corresponding function. */ -/*#include "../style.c"*/ -/*#include "../calculator.c"*/ -#include "../overview.c" -#include "../node_editor.c" - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -int -main(void) -{ - long dt; - long started; - int running = 1; - XWindow xw; - struct nk_context *ctx; - - /* X11 */ - memset(&xw, 0, sizeof xw); - xw.dpy = XOpenDisplay(NULL); - if (!xw.dpy) die("Could not open a display; perhaps $DISPLAY is not set?"); - - xw.root = DefaultRootWindow(xw.dpy); - xw.screen = XDefaultScreen(xw.dpy); - xw.vis = XDefaultVisual(xw.dpy, xw.screen); - xw.cmap = XCreateColormap(xw.dpy,xw.root,xw.vis,AllocNone); - xw.swa.colormap = xw.cmap; - xw.swa.event_mask = - ExposureMask | KeyPressMask | KeyReleaseMask | - ButtonPress | ButtonReleaseMask| ButtonMotionMask | - Button1MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask| - PointerMotionMask | KeymapStateMask; - xw.win = XCreateWindow(xw.dpy, xw.root, 0, 0, WINDOW_WIDTH, WINDOW_HEIGHT, 0, - XDefaultDepth(xw.dpy, xw.screen), InputOutput, - xw.vis, CWEventMask | CWColormap, &xw.swa); - XStoreName(xw.dpy, xw.win, "X11"); - XMapWindow(xw.dpy, xw.win); - XGetWindowAttributes(xw.dpy, xw.win, &xw.attr); - xw.width = (unsigned int)xw.attr.width; - xw.height = (unsigned int)xw.attr.height; - - /* GUI */ - xw.font = nk_xfont_create(xw.dpy, "fixed"); - ctx = nk_xlib_init(xw.font, xw.dpy, xw.screen, xw.win, xw.width, xw.height); - - /* style.c */ - /*set_style(ctx, THEME_WHITE);*/ - /*set_style(ctx, THEME_RED);*/ - /*set_style(ctx, THEME_BLUE);*/ - /*set_style(ctx, THEME_DARK);*/ - - while (running) - { - /* Input */ - XEvent evt; - started = timestamp(); - nk_input_begin(ctx); - while (XCheckWindowEvent(xw.dpy, xw.win, xw.swa.event_mask, &evt)){ - if (XFilterEvent(&evt, xw.win)) continue; - nk_xlib_handle_event(xw.dpy, xw.screen, xw.win, &evt); - } - nk_input_end(ctx); - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 200, 200), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - nk_layout_row_dynamic(ctx, 25, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - } - nk_end(ctx); - if (nk_window_is_closed(ctx, "Demo")) break; - - /* -------------- EXAMPLES ---------------- */ - /*calculator(ctx);*/ - overview(ctx); - node_editor(ctx); - /* ----------------------------------------- */ - - /* Draw */ - XClearWindow(xw.dpy, xw.win); - nk_xlib_render(xw.win, nk_rgb(30,30,30)); - XFlush(xw.dpy); - - /* Timing */ - dt = timestamp() - started; - if (dt < DTIME) - sleep_for(DTIME - dt); - } - - nk_xfont_del(xw.dpy, xw.font); - nk_xlib_shutdown(); - XUnmapWindow(xw.dpy, xw.win); - XFreeColormap(xw.dpy, xw.cmap); - XDestroyWindow(xw.dpy, xw.win); - XCloseDisplay(xw.dpy); - return 0; -} - diff --git a/deps/nuklear/demo/x11/nuklear_xlib.h b/deps/nuklear/demo/x11/nuklear_xlib.h deleted file mode 100644 index df66d78a..00000000 --- a/deps/nuklear/demo/x11/nuklear_xlib.h +++ /dev/null @@ -1,693 +0,0 @@ -/* - * Nuklear - v1.17 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_XLIB_H_ -#define NK_XLIB_H_ - -#include -/* Font */ -typedef struct XFont XFont; -NK_API XFont* nk_xfont_create(Display *dpy, const char *name); -NK_API void nk_xfont_del(Display *dpy, XFont *font); - -NK_API struct nk_context* nk_xlib_init(XFont *font, Display *dpy, int screen, Window root, unsigned int w, unsigned int h); -NK_API int nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt); -NK_API void nk_xlib_render(Drawable screen, struct nk_color clear); -NK_API void nk_xlib_shutdown(void); -NK_API void nk_xlib_set_font(XFont *font); - -#endif -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_XLIB_IMPLEMENTATION -#include -#include -#include -#include - -typedef struct XSurface XSurface; -struct XFont { - int ascent; - int descent; - int height; - XFontSet set; - XFontStruct *xfont; - struct nk_user_font handle; -}; -struct XSurface { - GC gc; - Display *dpy; - int screen; - Window root; - Drawable drawable; - unsigned int w, h; -}; -static struct { - struct nk_context ctx; - struct XSurface *surf; - Cursor cursor; - Display *dpy; - Window root; -} xlib; - -#ifndef MIN -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#endif -#ifndef MAX -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#endif - -static unsigned long -nk_color_from_byte(const nk_byte *c) -{ - unsigned long res = 0; - res |= (unsigned long)c[0] << 16; - res |= (unsigned long)c[1] << 8; - res |= (unsigned long)c[2] << 0; - return (res); -} - -static XSurface* -nk_xsurf_create(int screen, unsigned int w, unsigned int h) -{ - XSurface *surface = (XSurface*)calloc(1, sizeof(XSurface)); - surface->w = w; - surface->h = h; - surface->dpy = xlib.dpy; - surface->screen = screen; - surface->root = xlib.root; - surface->gc = XCreateGC(xlib.dpy, xlib.root, 0, NULL); - XSetLineAttributes(xlib.dpy, surface->gc, 1, LineSolid, CapButt, JoinMiter); - surface->drawable = XCreatePixmap(xlib.dpy, xlib.root, w, h, - (unsigned int)DefaultDepth(xlib.dpy, screen)); - return surface; -} - -static void -nk_xsurf_resize(XSurface *surf, unsigned int w, unsigned int h) -{ - if(!surf) return; - if (surf->w == w && surf->h == h) return; - surf->w = w; surf->h = h; - if(surf->drawable) XFreePixmap(surf->dpy, surf->drawable); - surf->drawable = XCreatePixmap(surf->dpy, surf->root, w, h, - (unsigned int)DefaultDepth(surf->dpy, surf->screen)); -} - -static void -nk_xsurf_scissor(XSurface *surf, float x, float y, float w, float h) -{ - XRectangle clip_rect; - clip_rect.x = (short)(x-1); - clip_rect.y = (short)(y-1); - clip_rect.width = (unsigned short)(w+2); - clip_rect.height = (unsigned short)(h+2); - XSetClipRectangles(surf->dpy, surf->gc, 0, 0, &clip_rect, 1, Unsorted); -} - -static void -nk_xsurf_stroke_line(XSurface *surf, short x0, short y0, short x1, - short y1, unsigned int line_thickness, struct nk_color col) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - XDrawLine(surf->dpy, surf->drawable, surf->gc, (int)x0, (int)y0, (int)x1, (int)y1); - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -static void -nk_xsurf_stroke_rect(XSurface* surf, short x, short y, unsigned short w, - unsigned short h, unsigned short r, unsigned short line_thickness, struct nk_color col) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - if (r == 0) { - XDrawRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h); - } else { - short xc = x + r; - short yc = y + r; - short wc = (short)(w - 2 * r); - short hc = (short)(h - 2 * r); - - XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y, xc+wc, y); - XDrawLine(surf->dpy, surf->drawable, surf->gc, x+w, yc, x+w, yc+hc); - XDrawLine(surf->dpy, surf->drawable, surf->gc, xc, y+h, xc+wc, y+h); - XDrawLine(surf->dpy, surf->drawable, surf->gc, x, yc, x, yc+hc); - - XDrawArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, y, - (unsigned)r*2, (unsigned)r*2, 0 * 64, 90 * 64); - XDrawArc(surf->dpy, surf->drawable, surf->gc, x, y, - (unsigned)r*2, (unsigned)r*2, 90 * 64, 90 * 64); - XDrawArc(surf->dpy, surf->drawable, surf->gc, x, yc + hc - r, - (unsigned)r*2, (unsigned)2*r, 180 * 64, 90 * 64); - XDrawArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, yc + hc - r, - (unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64); - } - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -static void -nk_xsurf_fill_rect(XSurface* surf, short x, short y, unsigned short w, - unsigned short h, unsigned short r, struct nk_color col) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - if (r == 0) { - XFillRectangle(surf->dpy, surf->drawable, surf->gc, x, y, w, h); - } else { - short xc = x + r; - short yc = y + r; - short wc = (short)(w - 2 * r); - short hc = (short)(h - 2 * r); - - XPoint pnts[12]; - pnts[0].x = x; - pnts[0].y = yc; - pnts[1].x = xc; - pnts[1].y = yc; - pnts[2].x = xc; - pnts[2].y = y; - - pnts[3].x = xc + wc; - pnts[3].y = y; - pnts[4].x = xc + wc; - pnts[4].y = yc; - pnts[5].x = x + w; - pnts[5].y = yc; - - pnts[6].x = x + w; - pnts[6].y = yc + hc; - pnts[7].x = xc + wc; - pnts[7].y = yc + hc; - pnts[8].x = xc + wc; - pnts[8].y = y + h; - - pnts[9].x = xc; - pnts[9].y = y + h; - pnts[10].x = xc; - pnts[10].y = yc + hc; - pnts[11].x = x; - pnts[11].y = yc + hc; - - XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 12, Convex, CoordModeOrigin); - XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, y, - (unsigned)r*2, (unsigned)r*2, 0 * 64, 90 * 64); - XFillArc(surf->dpy, surf->drawable, surf->gc, x, y, - (unsigned)r*2, (unsigned)r*2, 90 * 64, 90 * 64); - XFillArc(surf->dpy, surf->drawable, surf->gc, x, yc + hc - r, - (unsigned)r*2, (unsigned)2*r, 180 * 64, 90 * 64); - XFillArc(surf->dpy, surf->drawable, surf->gc, xc + wc - r, yc + hc - r, - (unsigned)r*2, (unsigned)2*r, -90 * 64, 90 * 64); - } -} - -static void -nk_xsurf_fill_triangle(XSurface *surf, short x0, short y0, short x1, - short y1, short x2, short y2, struct nk_color col) -{ - XPoint pnts[3]; - unsigned long c = nk_color_from_byte(&col.r); - pnts[0].x = (short)x0; - pnts[0].y = (short)y0; - pnts[1].x = (short)x1; - pnts[1].y = (short)y1; - pnts[2].x = (short)x2; - pnts[2].y = (short)y2; - XSetForeground(surf->dpy, surf->gc, c); - XFillPolygon(surf->dpy, surf->drawable, surf->gc, pnts, 3, Convex, CoordModeOrigin); -} - -static void -nk_xsurf_stroke_triangle(XSurface *surf, short x0, short y0, short x1, - short y1, short x2, short y2, unsigned short line_thickness, struct nk_color col) -{ - XPoint pnts[3]; - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - XDrawLine(surf->dpy, surf->drawable, surf->gc, x0, y0, x1, y1); - XDrawLine(surf->dpy, surf->drawable, surf->gc, x1, y1, x2, y2); - XDrawLine(surf->dpy, surf->drawable, surf->gc, x2, y2, x0, y0); - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -static void -nk_xsurf_fill_polygon(XSurface *surf, const struct nk_vec2i *pnts, int count, - struct nk_color col) -{ - int i = 0; - #define MAX_POINTS 64 - XPoint xpnts[MAX_POINTS]; - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - for (i = 0; i < count && i < MAX_POINTS; ++i) { - xpnts[i].x = pnts[i].x; - xpnts[i].y = pnts[i].y; - } - XFillPolygon(surf->dpy, surf->drawable, surf->gc, xpnts, count, Convex, CoordModeOrigin); - #undef MAX_POINTS -} - -static void -nk_xsurf_stroke_polygon(XSurface *surf, const struct nk_vec2i *pnts, int count, - unsigned short line_thickness, struct nk_color col) -{ - int i = 0; - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - for (i = 1; i < count; ++i) - XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i-1].x, pnts[i-1].y, pnts[i].x, pnts[i].y); - XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[count-1].x, pnts[count-1].y, pnts[0].x, pnts[0].y); - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -static void -nk_xsurf_stroke_polyline(XSurface *surf, const struct nk_vec2i *pnts, - int count, unsigned short line_thickness, struct nk_color col) -{ - int i = 0; - unsigned long c = nk_color_from_byte(&col.r); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - XSetForeground(surf->dpy, surf->gc, c); - for (i = 0; i < count-1; ++i) - XDrawLine(surf->dpy, surf->drawable, surf->gc, pnts[i].x, pnts[i].y, pnts[i+1].x, pnts[i+1].y); - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -static void -nk_xsurf_fill_circle(XSurface *surf, short x, short y, unsigned short w, - unsigned short h, struct nk_color col) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetForeground(surf->dpy, surf->gc, c); - XFillArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, - (unsigned)w, (unsigned)h, 0, 360 * 64); -} - -static void -nk_xsurf_stroke_circle(XSurface *surf, short x, short y, unsigned short w, - unsigned short h, unsigned short line_thickness, struct nk_color col) -{ - unsigned long c = nk_color_from_byte(&col.r); - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - XSetForeground(surf->dpy, surf->gc, c); - XDrawArc(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, - (unsigned)w, (unsigned)h, 0, 360 * 64); - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -static void -nk_xsurf_stroke_curve(XSurface *surf, struct nk_vec2i p1, - struct nk_vec2i p2, struct nk_vec2i p3, struct nk_vec2i p4, - unsigned int num_segments, unsigned short line_thickness, struct nk_color col) -{ - unsigned int i_step; - float t_step; - struct nk_vec2i last = p1; - - XSetLineAttributes(surf->dpy, surf->gc, line_thickness, LineSolid, CapButt, JoinMiter); - num_segments = MAX(num_segments, 1); - t_step = 1.0f/(float)num_segments; - for (i_step = 1; i_step <= num_segments; ++i_step) { - float t = t_step * (float)i_step; - float u = 1.0f - t; - float w1 = u*u*u; - float w2 = 3*u*u*t; - float w3 = 3*u*t*t; - float w4 = t * t *t; - float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; - float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; - nk_xsurf_stroke_line(surf, last.x, last.y, (short)x, (short)y, line_thickness,col); - last.x = (short)x; last.y = (short)y; - } - XSetLineAttributes(surf->dpy, surf->gc, 1, LineSolid, CapButt, JoinMiter); -} - -static void -nk_xsurf_draw_text(XSurface *surf, short x, short y, unsigned short w, unsigned short h, - const char *text, int len, XFont *font, struct nk_color cbg, struct nk_color cfg) -{ - int tx, ty; - unsigned long bg = nk_color_from_byte(&cbg.r); - unsigned long fg = nk_color_from_byte(&cfg.r); - - XSetForeground(surf->dpy, surf->gc, bg); - XFillRectangle(surf->dpy, surf->drawable, surf->gc, (int)x, (int)y, (unsigned)w, (unsigned)h); - if(!text || !font || !len) return; - - tx = (int)x; - ty = (int)y + font->ascent; - XSetForeground(surf->dpy, surf->gc, fg); - if(font->set) - XmbDrawString(surf->dpy,surf->drawable,font->set,surf->gc,tx,ty,(const char*)text,(int)len); - else - XDrawString(surf->dpy, surf->drawable, surf->gc, tx, ty, (const char*)text, (int)len); -} - -static void -nk_xsurf_clear(XSurface *surf, unsigned long color) -{ - XSetForeground(surf->dpy, surf->gc, color); - XFillRectangle(surf->dpy, surf->drawable, surf->gc, 0, 0, surf->w, surf->h); -} - -static void -nk_xsurf_blit(Drawable target, XSurface *surf, unsigned int w, unsigned int h) -{ - XCopyArea(surf->dpy, surf->drawable, target, surf->gc, 0, 0, w, h, 0, 0); -} - -static void -nk_xsurf_del(XSurface *surf) -{ - XFreePixmap(surf->dpy, surf->drawable); - XFreeGC(surf->dpy, surf->gc); - free(surf); -} - -XFont* -nk_xfont_create(Display *dpy, const char *name) -{ - int n; - char *def, **missing; - XFont *font = (XFont*)calloc(1, sizeof(XFont)); - font->set = XCreateFontSet(dpy, name, &missing, &n, &def); - if(missing) { - while(n--) - fprintf(stderr, "missing fontset: %s\n", missing[n]); - XFreeStringList(missing); - } - - if(font->set) { - XFontStruct **xfonts; - char **font_names; - XExtentsOfFontSet(font->set); - n = XFontsOfFontSet(font->set, &xfonts, &font_names); - while(n--) { - font->ascent = MAX(font->ascent, (*xfonts)->ascent); - font->descent = MAX(font->descent,(*xfonts)->descent); - xfonts++; - } - } else { - if(!(font->xfont = XLoadQueryFont(dpy, name)) - && !(font->xfont = XLoadQueryFont(dpy, "fixed"))) { - free(font); - return 0; - } - font->ascent = font->xfont->ascent; - font->descent = font->xfont->descent; - } - font->height = font->ascent + font->descent; - return font; -} - -static float -nk_xfont_get_text_width(nk_handle handle, float height, const char *text, int len) -{ - XFont *font = (XFont*)handle.ptr; - XRectangle r; - if(!font || !text) - return 0; - - if(font->set) { - XmbTextExtents(font->set, (const char*)text, len, NULL, &r); - return (float)r.width; - } else{ - int w = XTextWidth(font->xfont, (const char*)text, len); - return (float)w; - } -} - -void -nk_xfont_del(Display *dpy, XFont *font) -{ - if(!font) return; - if(font->set) - XFreeFontSet(dpy, font->set); - else - XFreeFont(dpy, font->xfont); - free(font); -} - -NK_API struct nk_context* -nk_xlib_init(XFont *xfont, Display *dpy, int screen, Window root, - unsigned int w, unsigned int h) -{ - struct nk_user_font *font = &xfont->handle; - font->userdata = nk_handle_ptr(xfont); - font->height = (float)xfont->height; - font->width = nk_xfont_get_text_width; - xlib.dpy = dpy; - xlib.root = root; - - if (!setlocale(LC_ALL,"")) return 0; - if (!XSupportsLocale()) return 0; - if (!XSetLocaleModifiers("@im=none")) return 0; - - /* create invisible cursor */ - {static XColor dummy; char data[1] = {0}; - Pixmap blank = XCreateBitmapFromData(dpy, root, data, 1, 1); - if (blank == None) return 0; - xlib.cursor = XCreatePixmapCursor(dpy, blank, blank, &dummy, &dummy, 0, 0); - XFreePixmap(dpy, blank);} - - xlib.surf = nk_xsurf_create(screen, w, h); - nk_init_default(&xlib.ctx, font); - return &xlib.ctx; -} - -NK_API void -nk_xlib_set_font(XFont *xfont) -{ - struct nk_user_font *font = &xfont->handle; - font->userdata = nk_handle_ptr(xfont); - font->height = (float)xfont->height; - font->width = nk_xfont_get_text_width; - nk_style_set_font(&xlib.ctx, font); -} - -NK_API int -nk_xlib_handle_event(Display *dpy, int screen, Window win, XEvent *evt) -{ - struct nk_context *ctx = &xlib.ctx; - - /* optional grabbing behavior */ - if (ctx->input.mouse.grab) { - XDefineCursor(xlib.dpy, xlib.root, xlib.cursor); - ctx->input.mouse.grab = 0; - } else if (ctx->input.mouse.ungrab) { - XWarpPointer(xlib.dpy, None, xlib.root, 0, 0, 0, 0, - (int)ctx->input.mouse.prev.x, (int)ctx->input.mouse.prev.y); - XUndefineCursor(xlib.dpy, xlib.root); - ctx->input.mouse.ungrab = 0; - } - - if (evt->type == KeyPress || evt->type == KeyRelease) - { - /* Key handler */ - int ret, down = (evt->type == KeyPress); - KeySym *code = XGetKeyboardMapping(xlib.surf->dpy, (KeyCode)evt->xkey.keycode, 1, &ret); - if (*code == XK_Shift_L || *code == XK_Shift_R) nk_input_key(ctx, NK_KEY_SHIFT, down); - else if (*code == XK_Delete) nk_input_key(ctx, NK_KEY_DEL, down); - else if (*code == XK_Return) nk_input_key(ctx, NK_KEY_ENTER, down); - else if (*code == XK_Tab) nk_input_key(ctx, NK_KEY_TAB, down); - else if (*code == XK_Left) nk_input_key(ctx, NK_KEY_LEFT, down); - else if (*code == XK_Right) nk_input_key(ctx, NK_KEY_RIGHT, down); - else if (*code == XK_Up) nk_input_key(ctx, NK_KEY_UP, down); - else if (*code == XK_Down) nk_input_key(ctx, NK_KEY_DOWN, down); - else if (*code == XK_BackSpace) nk_input_key(ctx, NK_KEY_BACKSPACE, down); - else if (*code == XK_Escape) nk_input_key(ctx, NK_KEY_TEXT_RESET_MODE, down); - else if (*code == XK_Page_Up) nk_input_key(ctx, NK_KEY_SCROLL_UP, down); - else if (*code == XK_Page_Down) nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); - else if (*code == XK_Home) { - nk_input_key(ctx, NK_KEY_TEXT_START, down); - nk_input_key(ctx, NK_KEY_SCROLL_START, down); - } else if (*code == XK_End) { - nk_input_key(ctx, NK_KEY_TEXT_END, down); - nk_input_key(ctx, NK_KEY_SCROLL_END, down); - } else { - if (*code == 'c' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_COPY, down); - else if (*code == 'v' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_PASTE, down); - else if (*code == 'x' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_CUT, down); - else if (*code == 'z' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_UNDO, down); - else if (*code == 'r' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_REDO, down); - else if (*code == XK_Left && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down); - else if (*code == XK_Right && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down); - else if (*code == 'b' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down); - else if (*code == 'e' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down); - else { - if (*code == 'i') - nk_input_key(ctx, NK_KEY_TEXT_INSERT_MODE, down); - else if (*code == 'r') - nk_input_key(ctx, NK_KEY_TEXT_REPLACE_MODE, down); - if (down) { - char buf[32]; - KeySym keysym = 0; - if (XLookupString((XKeyEvent*)evt, buf, 32, &keysym, NULL) != NoSymbol) - nk_input_glyph(ctx, buf); - } - } - } - XFree(code); - return 1; - } else if (evt->type == ButtonPress || evt->type == ButtonRelease) { - /* Button handler */ - int down = (evt->type == ButtonPress); - const int x = evt->xbutton.x, y = evt->xbutton.y; - if (evt->xbutton.button == Button1) - nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); - if (evt->xbutton.button == Button2) - nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); - else if (evt->xbutton.button == Button3) - nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); - else if (evt->xbutton.button == Button4) - nk_input_scroll(ctx, 1.0f); - else if (evt->xbutton.button == Button5) - nk_input_scroll(ctx, -1.0f); - else return 0; - return 1; - } else if (evt->type == MotionNotify) { - /* Mouse motion handler */ - const int x = evt->xmotion.x, y = evt->xmotion.y; - nk_input_motion(ctx, x, y); - if (ctx->input.mouse.grabbed) { - ctx->input.mouse.pos.x = ctx->input.mouse.prev.x; - ctx->input.mouse.pos.y = ctx->input.mouse.prev.y; - XWarpPointer(xlib.dpy, None, xlib.surf->root, 0, 0, 0, 0, (int)ctx->input.mouse.pos.x, (int)ctx->input.mouse.pos.y); - } - return 1; - } else if (evt->type == Expose || evt->type == ConfigureNotify) { - /* Window resize handler */ - unsigned int width, height; - XWindowAttributes attr; - XGetWindowAttributes(dpy, win, &attr); - width = (unsigned int)attr.width; - height = (unsigned int)attr.height; - nk_xsurf_resize(xlib.surf, width, height); - return 1; - } else if (evt->type == KeymapNotify) { - XRefreshKeyboardMapping(&evt->xmapping); - return 1; - } - return 0; -} - -NK_API void -nk_xlib_shutdown(void) -{ - nk_xsurf_del(xlib.surf); - nk_free(&xlib.ctx); - XFreeCursor(xlib.dpy, xlib.cursor); - nk_memset(&xlib, 0, sizeof(xlib)); -} - -NK_API void -nk_xlib_render(Drawable screen, struct nk_color clear) -{ - const struct nk_command *cmd; - struct nk_context *ctx = &xlib.ctx; - XSurface *surf = xlib.surf; - - nk_xsurf_clear(xlib.surf, nk_color_from_byte(&clear.r)); - nk_foreach(cmd, &xlib.ctx) - { - switch (cmd->type) { - case NK_COMMAND_NOP: break; - case NK_COMMAND_SCISSOR: { - const struct nk_command_scissor *s =(const struct nk_command_scissor*)cmd; - nk_xsurf_scissor(surf, s->x, s->y, s->w, s->h); - } break; - case NK_COMMAND_LINE: { - const struct nk_command_line *l = (const struct nk_command_line *)cmd; - nk_xsurf_stroke_line(surf, l->begin.x, l->begin.y, l->end.x, - l->end.y, l->line_thickness, l->color); - } break; - case NK_COMMAND_RECT: { - const struct nk_command_rect *r = (const struct nk_command_rect *)cmd; - nk_xsurf_stroke_rect(surf, r->x, r->y, r->w, r->h, - (unsigned short)r->rounding, r->line_thickness, r->color); - } break; - case NK_COMMAND_RECT_FILLED: { - const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled *)cmd; - nk_xsurf_fill_rect(surf, r->x, r->y, r->w, r->h, - (unsigned short)r->rounding, r->color); - } break; - case NK_COMMAND_CIRCLE: { - const struct nk_command_circle *c = (const struct nk_command_circle *)cmd; - nk_xsurf_stroke_circle(surf, c->x, c->y, c->w, c->h, c->line_thickness, c->color); - } break; - case NK_COMMAND_CIRCLE_FILLED: { - const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; - nk_xsurf_fill_circle(surf, c->x, c->y, c->w, c->h, c->color); - } break; - case NK_COMMAND_TRIANGLE: { - const struct nk_command_triangle*t = (const struct nk_command_triangle*)cmd; - nk_xsurf_stroke_triangle(surf, t->a.x, t->a.y, t->b.x, t->b.y, - t->c.x, t->c.y, t->line_thickness, t->color); - } break; - case NK_COMMAND_TRIANGLE_FILLED: { - const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled *)cmd; - nk_xsurf_fill_triangle(surf, t->a.x, t->a.y, t->b.x, t->b.y, - t->c.x, t->c.y, t->color); - } break; - case NK_COMMAND_POLYGON: { - const struct nk_command_polygon *p =(const struct nk_command_polygon*)cmd; - nk_xsurf_stroke_polygon(surf, p->points, p->point_count, p->line_thickness,p->color); - } break; - case NK_COMMAND_POLYGON_FILLED: { - const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled *)cmd; - nk_xsurf_fill_polygon(surf, p->points, p->point_count, p->color); - } break; - case NK_COMMAND_POLYLINE: { - const struct nk_command_polyline *p = (const struct nk_command_polyline *)cmd; - nk_xsurf_stroke_polyline(surf, p->points, p->point_count, p->line_thickness, p->color); - } break; - case NK_COMMAND_TEXT: { - const struct nk_command_text *t = (const struct nk_command_text*)cmd; - nk_xsurf_draw_text(surf, t->x, t->y, t->w, t->h, - (const char*)t->string, t->length, - (XFont*)t->font->userdata.ptr, - t->background, t->foreground); - } break; - case NK_COMMAND_CURVE: { - const struct nk_command_curve *q = (const struct nk_command_curve *)cmd; - nk_xsurf_stroke_curve(surf, q->begin, q->ctrl[0], q->ctrl[1], - q->end, 22, q->line_thickness, q->color); - } break; - case NK_COMMAND_RECT_MULTI_COLOR: - case NK_COMMAND_IMAGE: - case NK_COMMAND_ARC: - case NK_COMMAND_ARC_FILLED: - default: break; - } - } - nk_clear(ctx); - nk_xsurf_blit(screen, surf, surf->w, surf->h); -} -#endif diff --git a/deps/nuklear/demo/x11_opengl2/main.c b/deps/nuklear/demo/x11_opengl2/main.c deleted file mode 100644 index cfe5604c..00000000 --- a/deps/nuklear/demo/x11_opengl2/main.c +++ /dev/null @@ -1,320 +0,0 @@ -/* nuklear - v1.17 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#define NK_XLIB_GL2_IMPLEMENTATION -#include "../../nuklear.h" -#include "nuklear_xlib_gl2.h" - -#define WINDOW_WIDTH 1200 -#define WINDOW_HEIGHT 800 - -#define MAX_VERTEX_BUFFER 512 * 1024 -#define MAX_ELEMENT_BUFFER 128 * 1024 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* This are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the include - * and the corresponding function. */ -/*#include "../style.c"*/ -/*#include "../calculator.c"*/ -/*#include "../overview.c"*/ -/*#include "../node_editor.c"*/ - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -struct XWindow { - Display *dpy; - Window win; - XVisualInfo *vis; - Colormap cmap; - XSetWindowAttributes swa; - XWindowAttributes attr; - GLXFBConfig fbc; - int width, height; -}; -static int gl_err = FALSE; -static int gl_error_handler(Display *dpy, XErrorEvent *ev) -{UNUSED((dpy, ev)); gl_err = TRUE;return 0;} - -static void -die(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputs("\n", stderr); - exit(EXIT_FAILURE); -} - -static int -has_extension(const char *string, const char *ext) -{ - const char *start, *where, *term; - where = strchr(ext, ' '); - if (where || *ext == '\0') - return FALSE; - - for (start = string;;) { - where = strstr((const char*)start, ext); - if (!where) break; - term = where + strlen(ext); - if (where == start || *(where - 1) == ' ') { - if (*term == ' ' || *term == '\0') - return TRUE; - } - start = term; - } - return FALSE; -} - -int main(int argc, char **argv) -{ - /* Platform */ - int running = 1; - struct XWindow win; - GLXContext glContext; - struct nk_context *ctx; - struct nk_color background; - - memset(&win, 0, sizeof(win)); - win.dpy = XOpenDisplay(NULL); - if (!win.dpy) die("Failed to open X display\n"); - { - /* check glx version */ - int glx_major, glx_minor; - if (!glXQueryVersion(win.dpy, &glx_major, &glx_minor)) - die("[X11]: Error: Failed to query OpenGL version\n"); - if ((glx_major == 1 && glx_minor < 3) || (glx_major < 1)) - die("[X11]: Error: Invalid GLX version!\n"); - } - { - /* find and pick matching framebuffer visual */ - int fb_count; - static GLint attr[] = { - GLX_X_RENDERABLE, True, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 24, - GLX_STENCIL_SIZE, 8, - GLX_DOUBLEBUFFER, True, - None - }; - GLXFBConfig *fbc; - fbc = glXChooseFBConfig(win.dpy, DefaultScreen(win.dpy), attr, &fb_count); - if (!fbc) die("[X11]: Error: failed to retrieve framebuffer configuration\n"); - { - /* pick framebuffer with most samples per pixel */ - int i; - int fb_best = -1, best_num_samples = -1; - for (i = 0; i < fb_count; ++i) { - XVisualInfo *vi = glXGetVisualFromFBConfig(win.dpy, fbc[i]); - if (vi) { - int sample_buffer, samples; - glXGetFBConfigAttrib(win.dpy, fbc[i], GLX_SAMPLE_BUFFERS, &sample_buffer); - glXGetFBConfigAttrib(win.dpy, fbc[i], GLX_SAMPLES, &samples); - if ((fb_best < 0) || (sample_buffer && samples > best_num_samples)) - fb_best = i; best_num_samples = samples; - } - } - win.fbc = fbc[fb_best]; - XFree(fbc); - win.vis = glXGetVisualFromFBConfig(win.dpy, win.fbc); - } - } - { - /* create window */ - win.cmap = XCreateColormap(win.dpy, RootWindow(win.dpy, win.vis->screen), win.vis->visual, AllocNone); - win.swa.colormap = win.cmap; - win.swa.background_pixmap = None; - win.swa.border_pixel = 0; - win.swa.event_mask = - ExposureMask | KeyPressMask | KeyReleaseMask | - ButtonPress | ButtonReleaseMask| ButtonMotionMask | - Button1MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask| - PointerMotionMask| StructureNotifyMask; - win.win = XCreateWindow(win.dpy, RootWindow(win.dpy, win.vis->screen), 0, 0, - WINDOW_WIDTH, WINDOW_HEIGHT, 0, win.vis->depth, InputOutput, - win.vis->visual, CWBorderPixel|CWColormap|CWEventMask, &win.swa); - if (!win.win) die("[X11]: Failed to create window\n"); - XFree(win.vis); - XStoreName(win.dpy, win.win, "Demo"); - XMapWindow(win.dpy, win.win); - } - { - /* create opengl context */ - typedef GLXContext(*glxCreateContext)(Display*, GLXFBConfig, GLXContext, Bool, const int*); - int(*old_handler)(Display*, XErrorEvent*) = XSetErrorHandler(gl_error_handler); - const char *extensions_str = glXQueryExtensionsString(win.dpy, DefaultScreen(win.dpy)); - glxCreateContext create_context = (glxCreateContext) - glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB"); - - gl_err = FALSE; - if (!has_extension(extensions_str, "GLX_ARB_create_context") || !create_context) { - fprintf(stdout, "[X11]: glXCreateContextAttribARB() not found...\n"); - fprintf(stdout, "[X11]: ... using old-style GLX context\n"); - glContext = glXCreateNewContext(win.dpy, win.fbc, GLX_RGBA_TYPE, 0, True); - } else { - GLint attr[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 0, - None - }; - glContext = create_context(win.dpy, win.fbc, 0, True, attr); - XSync(win.dpy, False); - if (gl_err || !glContext) { - /* Could not create GL 3.0 context. Fallback to old 2.x context. - * If a version below 3.0 is requested, implementations will - * return the newest context version compatible with OpenGL - * version less than version 3.0.*/ - attr[1] = 1; attr[3] = 0; - gl_err = FALSE; - fprintf(stdout, "[X11] Failed to create OpenGL 3.0 context\n"); - fprintf(stdout, "[X11] ... using old-style GLX context!\n"); - glContext = create_context(win.dpy, win.fbc, 0, True, attr); - } - } - XSync(win.dpy, False); - XSetErrorHandler(old_handler); - if (gl_err || !glContext) - die("[X11]: Failed to create an OpenGL context\n"); - glXMakeCurrent(win.dpy, win.win, glContext); - } - - ctx = nk_x11_init(win.dpy, win.win); - /* Load Fonts: if none of these are loaded a default font will be used */ - /* Load Cursor: if you uncomment cursor loading please hide the cursor */ - {struct nk_font_atlas *atlas; - nk_x11_font_stash_begin(&atlas); - /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/ - /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 14, 0);*/ - /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/ - /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/ - /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/ - /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/ - nk_x11_font_stash_end(); - /*nk_style_load_all_cursors(ctx, atlas->cursors);*/ - /*nk_style_set_font(ctx, &droid->handle);*/} - - /* style.c */ - /*set_style(ctx, THEME_WHITE);*/ - /*set_style(ctx, THEME_RED);*/ - /*set_style(ctx, THEME_BLUE);*/ - /*set_style(ctx, THEME_DARK);*/ - - background = nk_rgb(28,48,62); - while (running) - { - /* Input */ - XEvent evt; - nk_input_begin(ctx); - while (XCheckWindowEvent(win.dpy, win.win, win.swa.event_mask, &evt)){ - if (XFilterEvent(&evt, win.win)) continue; - nk_x11_handle_event(&evt); - } - nk_input_end(ctx); - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 200, 200), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - nk_layout_row_dynamic(ctx, 25, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - - nk_layout_row_dynamic(ctx, 20, 1); - nk_label(ctx, "background:", NK_TEXT_LEFT); - nk_layout_row_dynamic(ctx, 25, 1); - if (nk_combo_begin_color(ctx, background, nk_vec2(nk_widget_width(ctx),400))) { - nk_layout_row_dynamic(ctx, 120, 1); - background = nk_color_picker(ctx, background, NK_RGBA); - nk_layout_row_dynamic(ctx, 25, 1); - background.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, background.r, 255, 1,1); - background.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, background.g, 255, 1,1); - background.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, background.b, 255, 1,1); - background.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, background.a, 255, 1,1); - nk_combo_end(ctx); - } - } - nk_end(ctx); - if (nk_window_is_closed(ctx, "Demo")) break; - - /* -------------- EXAMPLES ---------------- */ - /*calculator(ctx);*/ - /*overview(ctx);*/ - /*node_editor(ctx);*/ - /* ----------------------------------------- */ - - /* Draw */ - {float bg[4]; - nk_color_fv(bg, background); - XGetWindowAttributes(win.dpy, win.win, &win.attr); - glViewport(0, 0, win.width, win.height); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(bg[0], bg[1], bg[2], bg[3]); - /* IMPORTANT: `nk_x11_render` modifies some global OpenGL state - * with blending, scissor, face culling, depth test and viewport and - * defaults everything back into a default state. - * Make sure to either a.) save and restore or b.) reset your own state after - * rendering the UI. */ - nk_x11_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER); - glXSwapBuffers(win.dpy, win.win);} - } - - nk_x11_shutdown(); - glXMakeCurrent(win.dpy, 0, 0); - glXDestroyContext(win.dpy, glContext); - XUnmapWindow(win.dpy, win.win); - XFreeColormap(win.dpy, win.cmap); - XDestroyWindow(win.dpy, win.win); - XCloseDisplay(win.dpy); - return 0; - -} diff --git a/deps/nuklear/demo/x11_opengl2/nuklear_xlib_gl2.h b/deps/nuklear/demo/x11_opengl2/nuklear_xlib_gl2.h deleted file mode 100644 index a8144550..00000000 --- a/deps/nuklear/demo/x11_opengl2/nuklear_xlib_gl2.h +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Nuklear - v1.17 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_XLIB_GL3_H_ -#define NK_XLIB_GL3_H_ - -#include -NK_API struct nk_context* nk_x11_init(Display *dpy, Window win); -NK_API void nk_x11_font_stash_begin(struct nk_font_atlas **atlas); -NK_API void nk_x11_font_stash_end(void); -NK_API int nk_x11_handle_event(XEvent *evt); -NK_API void nk_x11_render(enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer); -NK_API void nk_x11_shutdown(void); - -#endif -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_XLIB_GL2_IMPLEMENTATION -#include -#include -#include - -#include -#include -#include -#include - -#include - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -struct nk_x11_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -struct nk_x11_device { - struct nk_buffer cmds; - struct nk_draw_null_texture null; - GLuint font_tex; -}; - -static struct nk_x11 { - struct nk_x11_device ogl; - struct nk_context ctx; - struct nk_font_atlas atlas; - Cursor cursor; - Display *dpy; - Window win; -} x11; - -NK_INTERN void -nk_x11_device_upload_atlas(const void *image, int width, int height) -{ - struct nk_x11_device *dev = &x11.ogl; - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - -NK_API void -nk_x11_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) -{ - /* setup global state */ - struct nk_x11_device *dev = &x11.ogl; - int width, height; - - XWindowAttributes attr; - XGetWindowAttributes(x11.dpy, x11.win, &attr); - width = attr.width; - height = attr.height; - - glPushAttrib(GL_ENABLE_BIT|GL_COLOR_BUFFER_BIT|GL_TRANSFORM_BIT); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glEnable(GL_BLEND); - glEnable(GL_TEXTURE_2D); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - /* setup viewport/project */ - glViewport(0,0,(GLsizei)width,(GLsizei)height); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glOrtho(0.0f, width, height, 0.0f, -1.0f, 1.0f); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - { - GLsizei vs = sizeof(struct nk_x11_vertex); - size_t vp = offsetof(struct nk_x11_vertex, position); - size_t vt = offsetof(struct nk_x11_vertex, uv); - size_t vc = offsetof(struct nk_x11_vertex, col); - - /* convert from command queue into draw list and draw to screen */ - const struct nk_draw_command *cmd; - const nk_draw_index *offset = NULL; - struct nk_buffer vbuf, ebuf; - - /* fill convert configuration */ - struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_x11_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_x11_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_x11_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - NK_MEMSET(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_x11_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_x11_vertex); - config.null = dev->null; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - - /* convert shapes into vertexes */ - nk_buffer_init_default(&vbuf); - nk_buffer_init_default(&ebuf); - nk_convert(&x11.ctx, &dev->cmds, &vbuf, &ebuf, &config); - - /* setup vertex buffer pointer */ - {const void *vertices = nk_buffer_memory_const(&vbuf); - glVertexPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vp)); - glTexCoordPointer(2, GL_FLOAT, vs, (const void*)((const nk_byte*)vertices + vt)); - glColorPointer(4, GL_UNSIGNED_BYTE, vs, (const void*)((const nk_byte*)vertices + vc));} - - /* iterate over and execute each draw command */ - offset = (const nk_draw_index*)nk_buffer_memory_const(&ebuf); - nk_draw_foreach(cmd, &x11.ctx, &dev->cmds) - { - if (!cmd->elem_count) continue; - glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor( - (GLint)(cmd->clip_rect.x), - (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h))), - (GLint)(cmd->clip_rect.w), - (GLint)(cmd->clip_rect.h)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); - offset += cmd->elem_count; - } - nk_clear(&x11.ctx); - nk_buffer_free(&vbuf); - nk_buffer_free(&ebuf); - } - - /* default OpenGL state */ - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_SCISSOR_TEST); - glDisable(GL_BLEND); - glDisable(GL_TEXTURE_2D); - - glBindTexture(GL_TEXTURE_2D, 0); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glPopAttrib(); - -} - -NK_API void -nk_x11_font_stash_begin(struct nk_font_atlas **atlas) -{ - nk_font_atlas_init_default(&x11.atlas); - nk_font_atlas_begin(&x11.atlas); - *atlas = &x11.atlas; -} - -NK_API void -nk_x11_font_stash_end(void) -{ - const void *image; int w, h; - image = nk_font_atlas_bake(&x11.atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - nk_x11_device_upload_atlas(image, w, h); - nk_font_atlas_end(&x11.atlas, nk_handle_id((int)x11.ogl.font_tex), &x11.ogl.null); - if (x11.atlas.default_font) - nk_style_set_font(&x11.ctx, &x11.atlas.default_font->handle); -} - -NK_API int -nk_x11_handle_event(XEvent *evt) -{ - struct nk_context *ctx = &x11.ctx; - - /* optional grabbing behavior */ - if (ctx->input.mouse.grab) { - XDefineCursor(x11.dpy, x11.win, x11.cursor); - ctx->input.mouse.grab = 0; - } else if (ctx->input.mouse.ungrab) { - XWarpPointer(x11.dpy, None, x11.win, 0, 0, 0, 0, - (int)ctx->input.mouse.pos.x, (int)ctx->input.mouse.pos.y); - XUndefineCursor(x11.dpy, x11.win); - ctx->input.mouse.ungrab = 0; - } - - if (evt->type == KeyPress || evt->type == KeyRelease) - { - /* Key handler */ - int ret, down = (evt->type == KeyPress); - KeySym *code = XGetKeyboardMapping(x11.dpy, (KeyCode)evt->xkey.keycode, 1, &ret); - if (*code == XK_Shift_L || *code == XK_Shift_R) nk_input_key(ctx, NK_KEY_SHIFT, down); - else if (*code == XK_Delete) nk_input_key(ctx, NK_KEY_DEL, down); - else if (*code == XK_Return) nk_input_key(ctx, NK_KEY_ENTER, down); - else if (*code == XK_Tab) nk_input_key(ctx, NK_KEY_TAB, down); - else if (*code == XK_Left) nk_input_key(ctx, NK_KEY_LEFT, down); - else if (*code == XK_Right) nk_input_key(ctx, NK_KEY_RIGHT, down); - else if (*code == XK_Up) nk_input_key(ctx, NK_KEY_UP, down); - else if (*code == XK_Down) nk_input_key(ctx, NK_KEY_DOWN, down); - else if (*code == XK_BackSpace) nk_input_key(ctx, NK_KEY_BACKSPACE, down); - else if (*code == XK_space && !down) nk_input_char(ctx, ' '); - else if (*code == XK_Page_Up) nk_input_key(ctx, NK_KEY_SCROLL_UP, down); - else if (*code == XK_Page_Down) nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); - else if (*code == XK_Home) { - nk_input_key(ctx, NK_KEY_TEXT_START, down); - nk_input_key(ctx, NK_KEY_SCROLL_START, down); - } else if (*code == XK_End) { - nk_input_key(ctx, NK_KEY_TEXT_END, down); - nk_input_key(ctx, NK_KEY_SCROLL_END, down); - } else { - if (*code == 'c' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_COPY, down); - else if (*code == 'v' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_PASTE, down); - else if (*code == 'x' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_CUT, down); - else if (*code == 'z' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_UNDO, down); - else if (*code == 'r' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_REDO, down); - else if (*code == XK_Left && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down); - else if (*code == XK_Right && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down); - else if (*code == 'b' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down); - else if (*code == 'e' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down); - else { - if (*code == 'i') - nk_input_key(ctx, NK_KEY_TEXT_INSERT_MODE, down); - else if (*code == 'r') - nk_input_key(ctx, NK_KEY_TEXT_REPLACE_MODE, down); - if (down) { - char buf[32]; - KeySym keysym = 0; - if (XLookupString((XKeyEvent*)evt, buf, 32, &keysym, NULL) != NoSymbol) - nk_input_glyph(ctx, buf); - } - } - } - XFree(code); - return 1; - } else if (evt->type == ButtonPress || evt->type == ButtonRelease) { - /* Button handler */ - int down = (evt->type == ButtonPress); - const int x = evt->xbutton.x, y = evt->xbutton.y; - if (evt->xbutton.button == Button1) - nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); - if (evt->xbutton.button == Button2) - nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); - else if (evt->xbutton.button == Button3) - nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); - else if (evt->xbutton.button == Button4) - nk_input_scroll(ctx, 1.0f); - else if (evt->xbutton.button == Button5) - nk_input_scroll(ctx, -1.0f); - else return 0; - return 1; - } else if (evt->type == MotionNotify) { - /* Mouse motion handler */ - const int x = evt->xmotion.x, y = evt->xmotion.y; - nk_input_motion(ctx, x, y); - if (ctx->input.mouse.grabbed) { - ctx->input.mouse.pos.x = ctx->input.mouse.prev.x; - ctx->input.mouse.pos.y = ctx->input.mouse.prev.y; - XWarpPointer(x11.dpy, None, x11.win, 0, 0, 0, 0, (int)ctx->input.mouse.pos.x, (int)ctx->input.mouse.pos.y); - } - return 1; - } else if (evt->type == KeymapNotify) { - XRefreshKeyboardMapping(&evt->xmapping); - return 1; - } - return 0; -} - -NK_API struct nk_context* -nk_x11_init(Display *dpy, Window win) -{ - x11.dpy = dpy; - x11.win = win; - - if (!setlocale(LC_ALL,"")) return 0; - if (!XSupportsLocale()) return 0; - if (!XSetLocaleModifiers("@im=none")) return 0; - - /* create invisible cursor */ - {static XColor dummy; char data[1] = {0}; - Pixmap blank = XCreateBitmapFromData(dpy, win, data, 1, 1); - if (blank == None) return 0; - x11.cursor = XCreatePixmapCursor(dpy, blank, blank, &dummy, &dummy, 0, 0); - XFreePixmap(dpy, blank);} - - nk_buffer_init_default(&x11.ogl.cmds); - nk_init_default(&x11.ctx, 0); - return &x11.ctx; -} - -NK_API void -nk_x11_shutdown(void) -{ - struct nk_x11_device *dev = &x11.ogl; - nk_font_atlas_clear(&x11.atlas); - nk_free(&x11.ctx); - glDeleteTextures(1, &dev->font_tex); - nk_buffer_free(&dev->cmds); - XFreeCursor(x11.dpy, x11.cursor); - memset(&x11, 0, sizeof(x11)); -} - -#endif diff --git a/deps/nuklear/demo/x11_opengl3/main.c b/deps/nuklear/demo/x11_opengl3/main.c deleted file mode 100644 index cd026f9b..00000000 --- a/deps/nuklear/demo/x11_opengl3/main.c +++ /dev/null @@ -1,317 +0,0 @@ -/* nuklear - v1.17 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_STANDARD_VARARGS -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#define NK_XLIB_GL3_IMPLEMENTATION -#define NK_XLIB_LOAD_OPENGL_EXTENSIONS -#include "../../nuklear.h" -#include "nuklear_xlib_gl3.h" - -#define WINDOW_WIDTH 1200 -#define WINDOW_HEIGHT 800 - -#define MAX_VERTEX_BUFFER 512 * 1024 -#define MAX_ELEMENT_BUFFER 128 * 1024 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -/* =============================================================== - * - * EXAMPLE - * - * ===============================================================*/ -/* This are some code examples to provide a small overview of what can be - * done with this library. To try out an example uncomment the include - * and the corresponding function. */ -/*#include "../style.c"*/ -/*#include "../calculator.c"*/ -/*#include "../overview.c"*/ -/*#include "../node_editor.c"*/ - -/* =============================================================== - * - * DEMO - * - * ===============================================================*/ -struct XWindow { - Display *dpy; - Window win; - XVisualInfo *vis; - Colormap cmap; - XSetWindowAttributes swa; - XWindowAttributes attr; - GLXFBConfig fbc; - int width, height; -}; -static int gl_err = FALSE; -static int gl_error_handler(Display *dpy, XErrorEvent *ev) -{UNUSED((dpy, ev)); gl_err = TRUE;return 0;} - -static void -die(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputs("\n", stderr); - exit(EXIT_FAILURE); -} - -static int -has_extension(const char *string, const char *ext) -{ - const char *start, *where, *term; - where = strchr(ext, ' '); - if (where || *ext == '\0') - return FALSE; - - for (start = string;;) { - where = strstr((const char*)start, ext); - if (!where) break; - term = where + strlen(ext); - if (where == start || *(where - 1) == ' ') { - if (*term == ' ' || *term == '\0') - return TRUE; - } - start = term; - } - return FALSE; -} - -int main(int argc, char **argv) -{ - /* Platform */ - int running = 1; - struct XWindow win; - GLXContext glContext; - struct nk_context *ctx; - struct nk_color background; - - memset(&win, 0, sizeof(win)); - win.dpy = XOpenDisplay(NULL); - if (!win.dpy) die("Failed to open X display\n"); - { - /* check glx version */ - int glx_major, glx_minor; - if (!glXQueryVersion(win.dpy, &glx_major, &glx_minor)) - die("[X11]: Error: Failed to query OpenGL version\n"); - if ((glx_major == 1 && glx_minor < 3) || (glx_major < 1)) - die("[X11]: Error: Invalid GLX version!\n"); - } - { - /* find and pick matching framebuffer visual */ - int fb_count; - static GLint attr[] = { - GLX_X_RENDERABLE, True, - GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT, - GLX_RENDER_TYPE, GLX_RGBA_BIT, - GLX_X_VISUAL_TYPE, GLX_TRUE_COLOR, - GLX_RED_SIZE, 8, - GLX_GREEN_SIZE, 8, - GLX_BLUE_SIZE, 8, - GLX_ALPHA_SIZE, 8, - GLX_DEPTH_SIZE, 24, - GLX_STENCIL_SIZE, 8, - GLX_DOUBLEBUFFER, True, - None - }; - GLXFBConfig *fbc; - fbc = glXChooseFBConfig(win.dpy, DefaultScreen(win.dpy), attr, &fb_count); - if (!fbc) die("[X11]: Error: failed to retrieve framebuffer configuration\n"); - { - /* pick framebuffer with most samples per pixel */ - int i; - int fb_best = -1, best_num_samples = -1; - for (i = 0; i < fb_count; ++i) { - XVisualInfo *vi = glXGetVisualFromFBConfig(win.dpy, fbc[i]); - if (vi) { - int sample_buffer, samples; - glXGetFBConfigAttrib(win.dpy, fbc[i], GLX_SAMPLE_BUFFERS, &sample_buffer); - glXGetFBConfigAttrib(win.dpy, fbc[i], GLX_SAMPLES, &samples); - if ((fb_best < 0) || (sample_buffer && samples > best_num_samples)) - fb_best = i; best_num_samples = samples; - } - } - win.fbc = fbc[fb_best]; - XFree(fbc); - win.vis = glXGetVisualFromFBConfig(win.dpy, win.fbc); - } - } - { - /* create window */ - win.cmap = XCreateColormap(win.dpy, RootWindow(win.dpy, win.vis->screen), win.vis->visual, AllocNone); - win.swa.colormap = win.cmap; - win.swa.background_pixmap = None; - win.swa.border_pixel = 0; - win.swa.event_mask = - ExposureMask | KeyPressMask | KeyReleaseMask | - ButtonPress | ButtonReleaseMask| ButtonMotionMask | - Button1MotionMask | Button3MotionMask | Button4MotionMask | Button5MotionMask| - PointerMotionMask| StructureNotifyMask; - win.win = XCreateWindow(win.dpy, RootWindow(win.dpy, win.vis->screen), 0, 0, - WINDOW_WIDTH, WINDOW_HEIGHT, 0, win.vis->depth, InputOutput, - win.vis->visual, CWBorderPixel|CWColormap|CWEventMask, &win.swa); - if (!win.win) die("[X11]: Failed to create window\n"); - XFree(win.vis); - XStoreName(win.dpy, win.win, "Demo"); - XMapWindow(win.dpy, win.win); - } - { - /* create opengl context */ - typedef GLXContext(*glxCreateContext)(Display*, GLXFBConfig, GLXContext, Bool, const int*); - int(*old_handler)(Display*, XErrorEvent*) = XSetErrorHandler(gl_error_handler); - const char *extensions_str = glXQueryExtensionsString(win.dpy, DefaultScreen(win.dpy)); - glxCreateContext create_context = (glxCreateContext) - glXGetProcAddressARB((const GLubyte*)"glXCreateContextAttribsARB"); - - gl_err = FALSE; - if (!has_extension(extensions_str, "GLX_ARB_create_context") || !create_context) { - fprintf(stdout, "[X11]: glXCreateContextAttribARB() not found...\n"); - fprintf(stdout, "[X11]: ... using old-style GLX context\n"); - glContext = glXCreateNewContext(win.dpy, win.fbc, GLX_RGBA_TYPE, 0, True); - } else { - GLint attr[] = { - GLX_CONTEXT_MAJOR_VERSION_ARB, 3, - GLX_CONTEXT_MINOR_VERSION_ARB, 0, - None - }; - glContext = create_context(win.dpy, win.fbc, 0, True, attr); - XSync(win.dpy, False); - if (gl_err || !glContext) { - /* Could not create GL 3.0 context. Fallback to old 2.x context. - * If a version below 3.0 is requested, implementations will - * return the newest context version compatible with OpenGL - * version less than version 3.0.*/ - attr[1] = 1; attr[3] = 0; - gl_err = FALSE; - fprintf(stdout, "[X11] Failed to create OpenGL 3.0 context\n"); - fprintf(stdout, "[X11] ... using old-style GLX context!\n"); - glContext = create_context(win.dpy, win.fbc, 0, True, attr); - } - } - XSync(win.dpy, False); - XSetErrorHandler(old_handler); - if (gl_err || !glContext) - die("[X11]: Failed to create an OpenGL context\n"); - glXMakeCurrent(win.dpy, win.win, glContext); - } - - ctx = nk_x11_init(win.dpy, win.win); - /* Load Fonts: if none of these are loaded a default font will be used */ - {struct nk_font_atlas *atlas; - nk_x11_font_stash_begin(&atlas); - /*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/ - /*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 14, 0);*/ - /*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/ - /*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/ - /*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/ - /*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/ - nk_x11_font_stash_end(); - /*nk_style_load_all_cursors(ctx, atlas->cursors);*/ - /*nk_style_set_font(ctx, &droid->handle);*/} - - /* style.c */ - /*set_style(ctx, THEME_WHITE);*/ - /*set_style(ctx, THEME_RED);*/ - /*set_style(ctx, THEME_BLUE);*/ - /*set_style(ctx, THEME_DARK);*/ - - background = nk_rgb(28,48,62); - while (running) - { - /* Input */ - XEvent evt; - nk_input_begin(ctx); - while (XCheckWindowEvent(win.dpy, win.win, win.swa.event_mask, &evt)){ - if (XFilterEvent(&evt, win.win)) continue; - nk_x11_handle_event(&evt); - } - nk_input_end(ctx); - - /* GUI */ - if (nk_begin(ctx, "Demo", nk_rect(50, 50, 200, 200), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_SCALABLE| - NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE|NK_WINDOW_TITLE)) - { - enum {EASY, HARD}; - static int op = EASY; - static int property = 20; - - nk_layout_row_static(ctx, 30, 80, 1); - if (nk_button_label(ctx, "button")) - fprintf(stdout, "button pressed\n"); - nk_layout_row_dynamic(ctx, 30, 2); - if (nk_option_label(ctx, "easy", op == EASY)) op = EASY; - if (nk_option_label(ctx, "hard", op == HARD)) op = HARD; - nk_layout_row_dynamic(ctx, 25, 1); - nk_property_int(ctx, "Compression:", 0, &property, 100, 10, 1); - - nk_layout_row_dynamic(ctx, 20, 1); - nk_label(ctx, "background:", NK_TEXT_LEFT); - nk_layout_row_dynamic(ctx, 25, 1); - if (nk_combo_begin_color(ctx, background, nk_vec2(nk_widget_width(ctx),400))) { - nk_layout_row_dynamic(ctx, 120, 1); - background = nk_color_picker(ctx, background, NK_RGBA); - nk_layout_row_dynamic(ctx, 25, 1); - background.r = (nk_byte)nk_propertyi(ctx, "#R:", 0, background.r, 255, 1,1); - background.g = (nk_byte)nk_propertyi(ctx, "#G:", 0, background.g, 255, 1,1); - background.b = (nk_byte)nk_propertyi(ctx, "#B:", 0, background.b, 255, 1,1); - background.a = (nk_byte)nk_propertyi(ctx, "#A:", 0, background.a, 255, 1,1); - nk_combo_end(ctx); - } - } - nk_end(ctx); - if (nk_window_is_closed(ctx, "Demo")) break; - - /* -------------- EXAMPLES ---------------- */ - /*calculator(ctx);*/ - /*overview(ctx);*/ - /*node_editor(ctx);*/ - /* ----------------------------------------- */ - - /* Draw */ - {float bg[4]; - nk_color_fv(bg, background); - XGetWindowAttributes(win.dpy, win.win, &win.attr); - glViewport(0, 0, win.width, win.height); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(bg[0], bg[1], bg[2], bg[3]); - /* IMPORTANT: `nk_x11_render` modifies some global OpenGL state - * with blending, scissor, face culling, depth test and viewport and - * defaults everything back into a default state. - * Make sure to either a.) save and restore or b.) reset your own state after - * rendering the UI. */ - nk_x11_render(NK_ANTI_ALIASING_ON, MAX_VERTEX_BUFFER, MAX_ELEMENT_BUFFER); - glXSwapBuffers(win.dpy, win.win);} - } - - nk_x11_shutdown(); - glXMakeCurrent(win.dpy, 0, 0); - glXDestroyContext(win.dpy, glContext); - XUnmapWindow(win.dpy, win.win); - XFreeColormap(win.dpy, win.cmap); - XDestroyWindow(win.dpy, win.win); - XCloseDisplay(win.dpy); - return 0; - -} diff --git a/deps/nuklear/demo/x11_opengl3/nuklear_xlib_gl3.h b/deps/nuklear/demo/x11_opengl3/nuklear_xlib_gl3.h deleted file mode 100644 index b0f56b98..00000000 --- a/deps/nuklear/demo/x11_opengl3/nuklear_xlib_gl3.h +++ /dev/null @@ -1,725 +0,0 @@ -/* - * Nuklear - v1.17 - public domain - * no warrenty implied; use at your own risk. - * authored from 2015-2016 by Micha Mettke - */ -/* - * ============================================================== - * - * API - * - * =============================================================== - */ -#ifndef NK_XLIB_GL3_H_ -#define NK_XLIB_GL3_H_ - -#include -NK_API struct nk_context* nk_x11_init(Display *dpy, Window win); -NK_API void nk_x11_font_stash_begin(struct nk_font_atlas **atlas); -NK_API void nk_x11_font_stash_end(void); -NK_API int nk_x11_handle_event(XEvent *evt); -NK_API void nk_x11_render(enum nk_anti_aliasing, int max_vertex_buffer, int max_element_buffer); -NK_API void nk_x11_shutdown(void); -NK_API int nk_x11_device_create(void); -NK_API void nk_x11_device_destroy(void); - -#endif -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_XLIB_GL3_IMPLEMENTATION -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#ifndef FALSE -#define FALSE 0 -#endif -#ifndef TRUE -#define TRUE 1 -#endif - -#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS -#include - -/* GL_ARB_vertex_buffer_object */ -typedef void(*nkglGenBuffers)(GLsizei, GLuint*); -typedef void(*nkglBindBuffer)(GLenum, GLuint); -typedef void(*nkglBufferData)(GLenum, GLsizeiptr, const GLvoid*, GLenum); -typedef void(*nkglBufferSubData)(GLenum, GLintptr, GLsizeiptr, const GLvoid*); -typedef void*(*nkglMapBuffer)(GLenum, GLenum); -typedef GLboolean(*nkglUnmapBuffer)(GLenum); -typedef void(*nkglDeleteBuffers)(GLsizei, GLuint*); -/* GL_ARB_vertex_array_object */ -typedef void (*nkglGenVertexArrays)(GLsizei, GLuint*); -typedef void (*nkglBindVertexArray)(GLuint); -typedef void (*nkglDeleteVertexArrays)(GLsizei, const GLuint*); -/* GL_ARB_vertex_program / GL_ARB_fragment_program */ -typedef void(*nkglVertexAttribPointer)(GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid*); -typedef void(*nkglEnableVertexAttribArray)(GLuint); -typedef void(*nkglDisableVertexAttribArray)(GLuint); -/* GL_ARB_framebuffer_object */ -typedef void(*nkglGenerateMipmap)(GLenum target); -/* GLSL/OpenGL 2.0 core */ -typedef GLuint(*nkglCreateShader)(GLenum); -typedef void(*nkglShaderSource)(GLuint, GLsizei, const GLchar**, const GLint*); -typedef void(*nkglCompileShader)(GLuint); -typedef void(*nkglGetShaderiv)(GLuint, GLenum, GLint*); -typedef void(*nkglGetShaderInfoLog)(GLuint, GLsizei, GLsizei*, GLchar*); -typedef void(*nkglDeleteShader)(GLuint); -typedef GLuint(*nkglCreateProgram)(void); -typedef void(*nkglAttachShader)(GLuint, GLuint); -typedef void(*nkglDetachShader)(GLuint, GLuint); -typedef void(*nkglLinkProgram)(GLuint); -typedef void(*nkglUseProgram)(GLuint); -typedef void(*nkglGetProgramiv)(GLuint, GLenum, GLint*); -typedef void(*nkglGetProgramInfoLog)(GLuint, GLsizei, GLsizei*, GLchar*); -typedef void(*nkglDeleteProgram)(GLuint); -typedef GLint(*nkglGetUniformLocation)(GLuint, const GLchar*); -typedef GLint(*nkglGetAttribLocation)(GLuint, const GLchar*); -typedef void(*nkglUniform1i)(GLint, GLint); -typedef void(*nkglUniform1f)(GLint, GLfloat); -typedef void(*nkglUniformMatrix3fv)(GLint, GLsizei, GLboolean, const GLfloat*); -typedef void(*nkglUniformMatrix4fv)(GLint, GLsizei, GLboolean, const GLfloat*); - -static nkglGenBuffers glGenBuffers; -static nkglBindBuffer glBindBuffer; -static nkglBufferData glBufferData; -static nkglBufferSubData glBufferSubData; -static nkglMapBuffer glMapBuffer; -static nkglUnmapBuffer glUnmapBuffer; -static nkglDeleteBuffers glDeleteBuffers; -static nkglGenVertexArrays glGenVertexArrays; -static nkglBindVertexArray glBindVertexArray; -static nkglDeleteVertexArrays glDeleteVertexArrays; -static nkglVertexAttribPointer glVertexAttribPointer; -static nkglEnableVertexAttribArray glEnableVertexAttribArray; -static nkglDisableVertexAttribArray glDisableVertexAttribArray; -static nkglGenerateMipmap glGenerateMipmap; -static nkglCreateShader glCreateShader; -static nkglShaderSource glShaderSource; -static nkglCompileShader glCompileShader; -static nkglGetShaderiv glGetShaderiv; -static nkglGetShaderInfoLog glGetShaderInfoLog; -static nkglDeleteShader glDeleteShader; -static nkglCreateProgram glCreateProgram; -static nkglAttachShader glAttachShader; -static nkglDetachShader glDetachShader; -static nkglLinkProgram glLinkProgram; -static nkglUseProgram glUseProgram; -static nkglGetProgramiv glGetProgramiv; -static nkglGetProgramInfoLog glGetProgramInfoLog; -static nkglDeleteProgram glDeleteProgram; -static nkglGetUniformLocation glGetUniformLocation; -static nkglGetAttribLocation glGetAttribLocation; -static nkglUniform1i glUniform1i; -static nkglUniform1f glUniform1f; -static nkglUniformMatrix3fv glUniformMatrix3fv; -static nkglUniformMatrix4fv glUniformMatrix4fv; - -enum graphics_card_vendors { - VENDOR_UNKNOWN, - VENDOR_NVIDIA, - VENDOR_AMD, - VENDOR_INTEL -}; - -struct opengl_info { - /* info */ - const char *vendor_str; - const char *version_str; - const char *extensions_str; - const char *renderer_str; - const char *glsl_version_str; - enum graphics_card_vendors vendor; - /* version */ - float version; - int major_version; - int minor_version; - /* extensions */ - int glsl_available; - int vertex_buffer_obj_available; - int vertex_array_obj_available; - int map_buffer_range_available; - int fragment_program_available; - int frame_buffer_object_available; -}; -#endif - -struct nk_x11_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -struct nk_x11_device { -#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS - struct opengl_info info; -#endif - struct nk_buffer cmds; - struct nk_draw_null_texture null; - GLuint vbo, vao, ebo; - GLuint prog; - GLuint vert_shdr; - GLuint frag_shdr; - GLint attrib_pos; - GLint attrib_uv; - GLint attrib_col; - GLint uniform_tex; - GLint uniform_proj; - GLuint font_tex; -}; - -static struct nk_x11 { - struct nk_x11_device ogl; - struct nk_context ctx; - struct nk_font_atlas atlas; - Cursor cursor; - Display *dpy; - Window win; -} x11; - -#ifdef __APPLE__ - #define NK_SHADER_VERSION "#version 150\n" -#else - #define NK_SHADER_VERSION "#version 300 es\n" -#endif - -#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS -#include - -NK_INTERN int -nk_x11_stricmpn(const char *a, const char *b, int len) -{ - int i = 0; - for (i = 0; i < len && a[i] && b[i]; ++i) - if (a[i] != b[i]) return 1; - if (i != len) return 1; - return 0; -} - -NK_INTERN int -nk_x11_check_extension(struct opengl_info *GL, const char *ext) -{ - const char *start, *where, *term; - where = strchr(ext, ' '); - if (where || *ext == '\0') - return FALSE; - - for (start = GL->extensions_str;;) { - where = strstr((const char*)start, ext); - if (!where) break; - term = where + strlen(ext); - if (where == start || *(where - 1) == ' ') { - if (*term == ' ' || *term == '\0') - return TRUE; - } - start = term; - } - return FALSE; -} - -#define GL_EXT(name) (nk##name)nk_gl_ext(#name) -NK_INTERN __GLXextFuncPtr -nk_gl_ext(const char *name) -{ - __GLXextFuncPtr func; - func = glXGetProcAddress((const GLubyte*)name); - if (!func) { - fprintf(stdout, "[GL]: failed to load extension: %s", name); - return NULL; - } - return func; -} - -NK_INTERN int -nk_load_opengl(struct opengl_info *gl) -{ - int failed = FALSE; - gl->version_str = (const char*)glGetString(GL_VERSION); - glGetIntegerv(GL_MAJOR_VERSION, &gl->major_version); - glGetIntegerv(GL_MINOR_VERSION, &gl->minor_version); - if (gl->major_version < 2) { - fprintf(stderr, "[GL]: Graphics card does not fullfill minimum OpenGL 2.0 support\n"); - return 0; - } - - gl->version = (float)gl->major_version + (float)gl->minor_version * 0.1f; - gl->renderer_str = (const char*)glGetString(GL_RENDERER); - gl->extensions_str = (const char*)glGetString(GL_EXTENSIONS); - gl->glsl_version_str = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); - gl->vendor_str = (const char*)glGetString(GL_VENDOR); - if (!nk_x11_stricmpn(gl->vendor_str, "ATI", 4) || - !nk_x11_stricmpn(gl->vendor_str, "AMD", 4)) - gl->vendor = VENDOR_AMD; - else if (!nk_x11_stricmpn(gl->vendor_str, "NVIDIA", 6)) - gl->vendor = VENDOR_NVIDIA; - else if (!nk_x11_stricmpn(gl->vendor_str, "Intel", 5)) - gl->vendor = VENDOR_INTEL; - else gl->vendor = VENDOR_UNKNOWN; - - /* Extensions */ - gl->glsl_available = (gl->version >= 2.0f); - if (gl->glsl_available) { - /* GLSL core in OpenGL > 2 */ - glCreateShader = GL_EXT(glCreateShader); - glShaderSource = GL_EXT(glShaderSource); - glCompileShader = GL_EXT(glCompileShader); - glGetShaderiv = GL_EXT(glGetShaderiv); - glGetShaderInfoLog = GL_EXT(glGetShaderInfoLog); - glDeleteShader = GL_EXT(glDeleteShader); - glCreateProgram = GL_EXT(glCreateProgram); - glAttachShader = GL_EXT(glAttachShader); - glDetachShader = GL_EXT(glDetachShader); - glLinkProgram = GL_EXT(glLinkProgram); - glUseProgram = GL_EXT(glUseProgram); - glGetProgramiv = GL_EXT(glGetProgramiv); - glGetProgramInfoLog = GL_EXT(glGetProgramInfoLog); - glDeleteProgram = GL_EXT(glDeleteProgram); - glGetUniformLocation = GL_EXT(glGetUniformLocation); - glGetAttribLocation = GL_EXT(glGetAttribLocation); - glUniform1i = GL_EXT(glUniform1i); - glUniform1f = GL_EXT(glUniform1f); - glUniformMatrix3fv = GL_EXT(glUniformMatrix3fv); - glUniformMatrix4fv = GL_EXT(glUniformMatrix4fv); - } - gl->vertex_buffer_obj_available = nk_x11_check_extension(gl, "GL_ARB_vertex_buffer_object"); - if (gl->vertex_buffer_obj_available) { - /* GL_ARB_vertex_buffer_object */ - glGenBuffers = GL_EXT(glGenBuffers); - glBindBuffer = GL_EXT(glBindBuffer); - glBufferData = GL_EXT(glBufferData); - glBufferSubData = GL_EXT(glBufferSubData); - glMapBuffer = GL_EXT(glMapBuffer); - glUnmapBuffer = GL_EXT(glUnmapBuffer); - glDeleteBuffers = GL_EXT(glDeleteBuffers); - } - gl->fragment_program_available = nk_x11_check_extension(gl, "GL_ARB_fragment_program"); - if (gl->fragment_program_available) { - /* GL_ARB_vertex_program / GL_ARB_fragment_program */ - glVertexAttribPointer = GL_EXT(glVertexAttribPointer); - glEnableVertexAttribArray = GL_EXT(glEnableVertexAttribArray); - glDisableVertexAttribArray = GL_EXT(glDisableVertexAttribArray); - } - gl->vertex_array_obj_available = nk_x11_check_extension(gl, "GL_ARB_vertex_array_object"); - if (gl->vertex_array_obj_available) { - /* GL_ARB_vertex_array_object */ - glGenVertexArrays = GL_EXT(glGenVertexArrays); - glBindVertexArray = GL_EXT(glBindVertexArray); - glDeleteVertexArrays = GL_EXT(glDeleteVertexArrays); - } - gl->frame_buffer_object_available = nk_x11_check_extension(gl, "GL_ARB_framebuffer_object"); - if (gl->frame_buffer_object_available) { - /* GL_ARB_framebuffer_object */ - glGenerateMipmap = GL_EXT(glGenerateMipmap); - } - if (!gl->vertex_buffer_obj_available) { - fprintf(stdout, "[GL] Error: GL_ARB_vertex_buffer_object is not available!\n"); - failed = TRUE; - } - if (!gl->fragment_program_available) { - fprintf(stdout, "[GL] Error: GL_ARB_fragment_program is not available!\n"); - failed = TRUE; - } - if (!gl->vertex_array_obj_available) { - fprintf(stdout, "[GL] Error: GL_ARB_vertex_array_object is not available!\n"); - failed = TRUE; - } - if (!gl->frame_buffer_object_available) { - fprintf(stdout, "[GL] Error: GL_ARB_framebuffer_object is not available!\n"); - failed = TRUE; - } - return !failed; -} -#endif - -NK_API int -nk_x11_device_create(void) -{ - GLint status; - static const GLchar *vertex_shader = - NK_SHADER_VERSION - "uniform mat4 ProjMtx;\n" - "in vec2 Position;\n" - "in vec2 TexCoord;\n" - "in vec4 Color;\n" - "out vec2 Frag_UV;\n" - "out vec4 Frag_Color;\n" - "void main() {\n" - " Frag_UV = TexCoord;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" - "}\n"; - static const GLchar *fragment_shader = - NK_SHADER_VERSION - "precision mediump float;\n" - "uniform sampler2D Texture;\n" - "in vec2 Frag_UV;\n" - "in vec4 Frag_Color;\n" - "out vec4 Out_Color;\n" - "void main(){\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" - "}\n"; - - struct nk_x11_device *dev = &x11.ogl; -#ifdef NK_XLIB_LOAD_OPENGL_EXTENSIONS - if (!nk_load_opengl(&dev->info)) return 0; -#endif - nk_buffer_init_default(&dev->cmds); - - dev->prog = glCreateProgram(); - dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); - dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); - glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); - glCompileShader(dev->vert_shdr); - glCompileShader(dev->frag_shdr); - glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glAttachShader(dev->prog, dev->vert_shdr); - glAttachShader(dev->prog, dev->frag_shdr); - glLinkProgram(dev->prog); - glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); - assert(status == GL_TRUE); - - dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); - dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); - dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); - dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); - dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); - - { - /* buffer setup */ - GLsizei vs = sizeof(struct nk_x11_vertex); - size_t vp = offsetof(struct nk_x11_vertex, position); - size_t vt = offsetof(struct nk_x11_vertex, uv); - size_t vc = offsetof(struct nk_x11_vertex, col); - - glGenBuffers(1, &dev->vbo); - glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); - - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); - } - - glBindTexture(GL_TEXTURE_2D, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); - return 1; -} - -NK_INTERN void -nk_x11_device_upload_atlas(const void *image, int width, int height) -{ - struct nk_x11_device *dev = &x11.ogl; - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - -NK_API void -nk_x11_device_destroy(void) -{ - struct nk_x11_device *dev = &x11.ogl; - glDetachShader(dev->prog, dev->vert_shdr); - glDetachShader(dev->prog, dev->frag_shdr); - glDeleteShader(dev->vert_shdr); - glDeleteShader(dev->frag_shdr); - glDeleteProgram(dev->prog); - glDeleteTextures(1, &dev->font_tex); - glDeleteBuffers(1, &dev->vbo); - glDeleteBuffers(1, &dev->ebo); - nk_buffer_free(&dev->cmds); -} - -NK_API void -nk_x11_render(enum nk_anti_aliasing AA, int max_vertex_buffer, int max_element_buffer) -{ - int width, height; - XWindowAttributes attr; - struct nk_x11_device *dev = &x11.ogl; - GLfloat ortho[4][4] = { - {2.0f, 0.0f, 0.0f, 0.0f}, - {0.0f,-2.0f, 0.0f, 0.0f}, - {0.0f, 0.0f,-1.0f, 0.0f}, - {-1.0f,1.0f, 0.0f, 1.0f}, - }; - XGetWindowAttributes(x11.dpy, x11.win, &attr); - width = attr.width; - height = attr.height; - - ortho[0][0] /= (GLfloat)width; - ortho[1][1] /= (GLfloat)height; - - /* setup global state */ - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - /* setup program */ - glUseProgram(dev->prog); - glUniform1i(dev->uniform_tex, 0); - glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); - glViewport(0,0,(GLsizei)width,(GLsizei)height); - { - /* convert from command queue into draw list and draw to screen */ - const struct nk_draw_command *cmd; - void *vertices, *elements; - const nk_draw_index *offset = NULL; - - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glBufferData(GL_ARRAY_BUFFER, max_vertex_buffer, NULL, GL_STREAM_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, max_element_buffer, NULL, GL_STREAM_DRAW); - - /* load draw vertices & elements directly into vertex + element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); - { - /* fill convert configuration */ - struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_x11_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_x11_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_x11_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - NK_MEMSET(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_x11_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_x11_vertex); - config.null = dev->null; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - - /* setup buffers to load vertices and elements */ - {struct nk_buffer vbuf, ebuf; - nk_buffer_init_fixed(&vbuf, vertices, (size_t)max_vertex_buffer); - nk_buffer_init_fixed(&ebuf, elements, (size_t)max_element_buffer); - nk_convert(&x11.ctx, &dev->cmds, &vbuf, &ebuf, &config);} - } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - - /* iterate over and execute each draw command */ - nk_draw_foreach(cmd, &x11.ctx, &dev->cmds) - { - if (!cmd->elem_count) continue; - glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor( - (GLint)(cmd->clip_rect.x), - (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h))), - (GLint)(cmd->clip_rect.w), - (GLint)(cmd->clip_rect.h)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); - offset += cmd->elem_count; - } - nk_clear(&x11.ctx); - } - - /* default OpenGL state */ - glUseProgram(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); -} - -NK_API void -nk_x11_font_stash_begin(struct nk_font_atlas **atlas) -{ - nk_font_atlas_init_default(&x11.atlas); - nk_font_atlas_begin(&x11.atlas); - *atlas = &x11.atlas; -} - -NK_API void -nk_x11_font_stash_end(void) -{ - const void *image; int w, h; - image = nk_font_atlas_bake(&x11.atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - nk_x11_device_upload_atlas(image, w, h); - nk_font_atlas_end(&x11.atlas, nk_handle_id((int)x11.ogl.font_tex), &x11.ogl.null); - if (x11.atlas.default_font) - nk_style_set_font(&x11.ctx, &x11.atlas.default_font->handle); -} - -NK_API int -nk_x11_handle_event(XEvent *evt) -{ - struct nk_context *ctx = &x11.ctx; - - /* optional grabbing behavior */ - if (ctx->input.mouse.grab) { - XDefineCursor(x11.dpy, x11.win, x11.cursor); - ctx->input.mouse.grab = 0; - } else if (ctx->input.mouse.ungrab) { - XWarpPointer(x11.dpy, None, x11.win, 0, 0, 0, 0, - (int)ctx->input.mouse.pos.x, (int)ctx->input.mouse.pos.y); - XUndefineCursor(x11.dpy, x11.win); - ctx->input.mouse.ungrab = 0; - } - - if (evt->type == KeyPress || evt->type == KeyRelease) - { - /* Key handler */ - int ret, down = (evt->type == KeyPress); - KeySym *code = XGetKeyboardMapping(x11.dpy, (KeyCode)evt->xkey.keycode, 1, &ret); - if (*code == XK_Shift_L || *code == XK_Shift_R) nk_input_key(ctx, NK_KEY_SHIFT, down); - else if (*code == XK_Delete) nk_input_key(ctx, NK_KEY_DEL, down); - else if (*code == XK_Return) nk_input_key(ctx, NK_KEY_ENTER, down); - else if (*code == XK_Tab) nk_input_key(ctx, NK_KEY_TAB, down); - else if (*code == XK_Left) nk_input_key(ctx, NK_KEY_LEFT, down); - else if (*code == XK_Right) nk_input_key(ctx, NK_KEY_RIGHT, down); - else if (*code == XK_Up) nk_input_key(ctx, NK_KEY_UP, down); - else if (*code == XK_Down) nk_input_key(ctx, NK_KEY_DOWN, down); - else if (*code == XK_BackSpace) nk_input_key(ctx, NK_KEY_BACKSPACE, down); - else if (*code == XK_space && !down) nk_input_char(ctx, ' '); - else if (*code == XK_Page_Up) nk_input_key(ctx, NK_KEY_SCROLL_UP, down); - else if (*code == XK_Page_Down) nk_input_key(ctx, NK_KEY_SCROLL_DOWN, down); - else if (*code == XK_Home) { - nk_input_key(ctx, NK_KEY_TEXT_START, down); - nk_input_key(ctx, NK_KEY_SCROLL_START, down); - } else if (*code == XK_End) { - nk_input_key(ctx, NK_KEY_TEXT_END, down); - nk_input_key(ctx, NK_KEY_SCROLL_END, down); - } else { - if (*code == 'c' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_COPY, down); - else if (*code == 'v' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_PASTE, down); - else if (*code == 'x' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_CUT, down); - else if (*code == 'z' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_UNDO, down); - else if (*code == 'r' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_REDO, down); - else if (*code == XK_Left && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_WORD_LEFT, down); - else if (*code == XK_Right && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_WORD_RIGHT, down); - else if (*code == 'b' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_LINE_START, down); - else if (*code == 'e' && (evt->xkey.state & ControlMask)) - nk_input_key(ctx, NK_KEY_TEXT_LINE_END, down); - else { - if (*code == 'i') - nk_input_key(ctx, NK_KEY_TEXT_INSERT_MODE, down); - else if (*code == 'r') - nk_input_key(ctx, NK_KEY_TEXT_REPLACE_MODE, down); - if (down) { - char buf[32]; - KeySym keysym = 0; - if (XLookupString((XKeyEvent*)evt, buf, 32, &keysym, NULL) != NoSymbol) - nk_input_glyph(ctx, buf); - } - } - } - XFree(code); - return 1; - } else if (evt->type == ButtonPress || evt->type == ButtonRelease) { - /* Button handler */ - int down = (evt->type == ButtonPress); - const int x = evt->xbutton.x, y = evt->xbutton.y; - if (evt->xbutton.button == Button1) - nk_input_button(ctx, NK_BUTTON_LEFT, x, y, down); - if (evt->xbutton.button == Button2) - nk_input_button(ctx, NK_BUTTON_MIDDLE, x, y, down); - else if (evt->xbutton.button == Button3) - nk_input_button(ctx, NK_BUTTON_RIGHT, x, y, down); - else if (evt->xbutton.button == Button4) - nk_input_scroll(ctx, 1.0f); - else if (evt->xbutton.button == Button5) - nk_input_scroll(ctx, -1.0f); - else return 0; - return 1; - } else if (evt->type == MotionNotify) { - /* Mouse motion handler */ - const int x = evt->xmotion.x, y = evt->xmotion.y; - nk_input_motion(ctx, x, y); - if (ctx->input.mouse.grabbed) { - ctx->input.mouse.pos.x = ctx->input.mouse.prev.x; - ctx->input.mouse.pos.y = ctx->input.mouse.prev.y; - XWarpPointer(x11.dpy, None, x11.win, 0, 0, 0, 0, (int)ctx->input.mouse.pos.x, (int)ctx->input.mouse.pos.y); - } - return 1; - } else if (evt->type == KeymapNotify) { - XRefreshKeyboardMapping(&evt->xmapping); - return 1; - } - return 0; -} - -NK_API struct nk_context* -nk_x11_init(Display *dpy, Window win) -{ - if (!setlocale(LC_ALL,"")) return 0; - if (!XSupportsLocale()) return 0; - if (!XSetLocaleModifiers("@im=none")) return 0; - if (!nk_x11_device_create()) return 0; - - x11.dpy = dpy; - x11.win = win; - - /* create invisible cursor */ - {static XColor dummy; char data[1] = {0}; - Pixmap blank = XCreateBitmapFromData(dpy, win, data, 1, 1); - if (blank == None) return 0; - x11.cursor = XCreatePixmapCursor(dpy, blank, blank, &dummy, &dummy, 0, 0); - XFreePixmap(dpy, blank);} - - nk_init_default(&x11.ctx, 0); - return &x11.ctx; -} - -NK_API void -nk_x11_shutdown(void) -{ - nk_font_atlas_clear(&x11.atlas); - nk_free(&x11.ctx); - nk_x11_device_destroy(); - XFreeCursor(x11.dpy, x11.cursor); - memset(&x11, 0, sizeof(x11)); -} - -#endif diff --git a/deps/nuklear/example/canvas.c b/deps/nuklear/example/canvas.c deleted file mode 100644 index c5f5634b..00000000 --- a/deps/nuklear/example/canvas.c +++ /dev/null @@ -1,489 +0,0 @@ -/* nuklear - v1.05 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define NK_PRIVATE -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#include "../nuklear.h" - -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" - -/* macros */ -#define WINDOW_WIDTH 1200 -#define WINDOW_HEIGHT 800 - -#define MAX_VERTEX_MEMORY 512 * 1024 -#define MAX_ELEMENT_MEMORY 128 * 1024 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -#define NK_SHADER_VERSION "#version 150\n" - -/* =============================================================== - * - * DEVICE - * - * ===============================================================*/ -struct nk_glfw_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -struct device { - struct nk_buffer cmds; - struct nk_draw_null_texture null; - GLuint vbo, vao, ebo; - GLuint prog; - GLuint vert_shdr; - GLuint frag_shdr; - GLint attrib_pos; - GLint attrib_uv; - GLint attrib_col; - GLint uniform_tex; - GLint uniform_proj; - GLuint font_tex; -}; - -static void -die(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputs("\n", stderr); - exit(EXIT_FAILURE); -} - -static struct nk_image -icon_load(const char *filename) -{ - int x,y,n; - GLuint tex; - unsigned char *data = stbi_load(filename, &x, &y, &n, 0); - if (!data) die("[SDL]: failed to load image: %s", filename); - - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - glGenerateMipmap(GL_TEXTURE_2D); - stbi_image_free(data); - return nk_image_id((int)tex); -} - -static void -device_init(struct device *dev) -{ - GLint status; - static const GLchar *vertex_shader = - NK_SHADER_VERSION - "uniform mat4 ProjMtx;\n" - "in vec2 Position;\n" - "in vec2 TexCoord;\n" - "in vec4 Color;\n" - "out vec2 Frag_UV;\n" - "out vec4 Frag_Color;\n" - "void main() {\n" - " Frag_UV = TexCoord;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" - "}\n"; - static const GLchar *fragment_shader = - NK_SHADER_VERSION - "precision mediump float;\n" - "uniform sampler2D Texture;\n" - "in vec2 Frag_UV;\n" - "in vec4 Frag_Color;\n" - "out vec4 Out_Color;\n" - "void main(){\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" - "}\n"; - - nk_buffer_init_default(&dev->cmds); - dev->prog = glCreateProgram(); - dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); - dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); - glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); - glCompileShader(dev->vert_shdr); - glCompileShader(dev->frag_shdr); - glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glAttachShader(dev->prog, dev->vert_shdr); - glAttachShader(dev->prog, dev->frag_shdr); - glLinkProgram(dev->prog); - glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); - assert(status == GL_TRUE); - - dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); - dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); - dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); - dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); - dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); - - { - /* buffer setup */ - GLsizei vs = sizeof(struct nk_glfw_vertex); - size_t vp = offsetof(struct nk_glfw_vertex, position); - size_t vt = offsetof(struct nk_glfw_vertex, uv); - size_t vc = offsetof(struct nk_glfw_vertex, col); - - glGenBuffers(1, &dev->vbo); - glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); - - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); - } - - glBindTexture(GL_TEXTURE_2D, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); -} - -static void -device_upload_atlas(struct device *dev, const void *image, int width, int height) -{ - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - -static void -device_shutdown(struct device *dev) -{ - glDetachShader(dev->prog, dev->vert_shdr); - glDetachShader(dev->prog, dev->frag_shdr); - glDeleteShader(dev->vert_shdr); - glDeleteShader(dev->frag_shdr); - glDeleteProgram(dev->prog); - glDeleteTextures(1, &dev->font_tex); - glDeleteBuffers(1, &dev->vbo); - glDeleteBuffers(1, &dev->ebo); - nk_buffer_free(&dev->cmds); -} - -static void -device_draw(struct device *dev, struct nk_context *ctx, int width, int height, - enum nk_anti_aliasing AA) -{ - GLfloat ortho[4][4] = { - {2.0f, 0.0f, 0.0f, 0.0f}, - {0.0f,-2.0f, 0.0f, 0.0f}, - {0.0f, 0.0f,-1.0f, 0.0f}, - {-1.0f,1.0f, 0.0f, 1.0f}, - }; - ortho[0][0] /= (GLfloat)width; - ortho[1][1] /= (GLfloat)height; - - /* setup global state */ - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - /* setup program */ - glUseProgram(dev->prog); - glUniform1i(dev->uniform_tex, 0); - glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); - { - /* convert from command queue into draw list and draw to screen */ - const struct nk_draw_command *cmd; - void *vertices, *elements; - const nk_draw_index *offset = NULL; - - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW); - - /* load draw vertices & elements directly into vertex + element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); - { - /* fill convert configuration */ - struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - NK_MEMSET(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_glfw_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex); - config.null = dev->null; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - - /* setup buffers to load vertices and elements */ - {struct nk_buffer vbuf, ebuf; - nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY); - nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY); - nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);} - } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - - /* iterate over and execute each draw command */ - nk_draw_foreach(cmd, ctx, &dev->cmds) - { - if (!cmd->elem_count) continue; - glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor( - (GLint)(cmd->clip_rect.x), - (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h))), - (GLint)(cmd->clip_rect.w), - (GLint)(cmd->clip_rect.h)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); - offset += cmd->elem_count; - } - nk_clear(ctx); - } - - /* default OpenGL state */ - glUseProgram(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); -} - -/* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/ -static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);} -static void text_input(GLFWwindow *win, unsigned int codepoint) -{nk_input_unicode((struct nk_context*)glfwGetWindowUserPointer(win), codepoint);} -static void scroll_input(GLFWwindow *win, double _, double yoff) -{UNUSED(_);nk_input_scroll((struct nk_context*)glfwGetWindowUserPointer(win), (float)yoff);} - -static void -pump_input(struct nk_context *ctx, GLFWwindow *win) -{ - double x, y; - nk_input_begin(ctx); - glfwPollEvents(); - - nk_input_key(ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS); - - if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || - glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) { - nk_input_key(ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_P) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS); - nk_input_key(ctx, NK_KEY_SHIFT, 1); - } else { - nk_input_key(ctx, NK_KEY_COPY, 0); - nk_input_key(ctx, NK_KEY_PASTE, 0); - nk_input_key(ctx, NK_KEY_CUT, 0); - nk_input_key(ctx, NK_KEY_SHIFT, 0); - } - - glfwGetCursorPos(win, &x, &y); - nk_input_motion(ctx, (int)x, (int)y); - nk_input_button(ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS); - nk_input_button(ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS); - nk_input_button(ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS); - nk_input_end(ctx); -} - -struct nk_canvas { - struct nk_command_buffer *painter; - struct nk_vec2 item_spacing; - struct nk_vec2 panel_padding; - struct nk_style_item window_background; -}; - -static void -canvas_begin(struct nk_context *ctx, struct nk_canvas *canvas, nk_flags flags, - int x, int y, int width, int height, struct nk_color background_color) -{ - /* save style properties which will be overwritten */ - canvas->panel_padding = ctx->style.window.padding; - canvas->item_spacing = ctx->style.window.spacing; - canvas->window_background = ctx->style.window.fixed_background; - - /* use the complete window space and set background */ - ctx->style.window.spacing = nk_vec2(0,0); - ctx->style.window.padding = nk_vec2(0,0); - ctx->style.window.fixed_background = nk_style_item_color(background_color); - - /* create/update window and set position + size */ - flags = flags & ~NK_WINDOW_DYNAMIC; - nk_begin(ctx, "Window", nk_rect(x, y, width, height), NK_WINDOW_NO_SCROLLBAR|flags); - nk_window_set_bounds(ctx, nk_rect(x, y, width, height)); - - /* allocate the complete window space for drawing */ - {struct nk_rect total_space; - total_space = nk_window_get_content_region(ctx); - nk_layout_row_dynamic(ctx, total_space.h, 1); - nk_widget(&total_space, ctx); - canvas->painter = nk_window_get_canvas(ctx);} -} - -static void -canvas_end(struct nk_context *ctx, struct nk_canvas *canvas) -{ - nk_end(ctx); - ctx->style.window.spacing = canvas->panel_padding; - ctx->style.window.padding = canvas->item_spacing; - ctx->style.window.fixed_background = canvas->window_background; -} - -int main(int argc, char *argv[]) -{ - /* Platform */ - static GLFWwindow *win; - int width = 0, height = 0; - - /* GUI */ - struct device device; - struct nk_font_atlas atlas; - struct nk_context ctx; - - /* GLFW */ - glfwSetErrorCallback(error_callback); - if (!glfwInit()) { - fprintf(stdout, "[GFLW] failed to init!\n"); - exit(1); - } - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL); - glfwMakeContextCurrent(win); - glfwSetWindowUserPointer(win, &ctx); - glfwSetCharCallback(win, text_input); - glfwSetScrollCallback(win, scroll_input); - glfwGetWindowSize(win, &width, &height); - - /* OpenGL */ - glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); - glewExperimental = 1; - if (glewInit() != GLEW_OK) { - fprintf(stderr, "Failed to setup GLEW\n"); - exit(1); - } - - /* GUI */ - {device_init(&device); - {const void *image; int w, h; - struct nk_font *font; - nk_font_atlas_init_default(&atlas); - nk_font_atlas_begin(&atlas); - font = nk_font_atlas_add_default(&atlas, 13, 0); - image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - device_upload_atlas(&device, image, w, h); - nk_font_atlas_end(&atlas, nk_handle_id((int)device.font_tex), &device.null); - nk_init_default(&ctx, &font->handle); - - glEnable(GL_TEXTURE_2D); - while (!glfwWindowShouldClose(win)) - { - /* input */ - pump_input(&ctx, win); - - /* draw */ - {struct nk_canvas canvas; - canvas_begin(&ctx, &canvas, 0, 0, 0, width, height, nk_rgb(250,250,250)); - { - nk_fill_rect(canvas.painter, nk_rect(15,15,210,210), 5, nk_rgb(247, 230, 154)); - nk_fill_rect(canvas.painter, nk_rect(20,20,200,200), 5, nk_rgb(188, 174, 118)); - nk_draw_text(canvas.painter, nk_rect(30, 30, 150, 20), "Text to draw", 12, &font->handle, nk_rgb(188,174,118), nk_rgb(0,0,0)); - nk_fill_rect(canvas.painter, nk_rect(250,20,100,100), 0, nk_rgb(0,0,255)); - nk_fill_circle(canvas.painter, nk_rect(20,250,100,100), nk_rgb(255,0,0)); - nk_fill_triangle(canvas.painter, 250, 250, 350, 250, 300, 350, nk_rgb(0,255,0)); - nk_fill_arc(canvas.painter, 300, 180, 50, 0, 3.141592654f * 3.0f / 4.0f, nk_rgb(255,255,0)); - - {float points[12]; - points[0] = 200; points[1] = 250; - points[2] = 250; points[3] = 350; - points[4] = 225; points[5] = 350; - points[6] = 200; points[7] = 300; - points[8] = 175; points[9] = 350; - points[10] = 150; points[11] = 350; - nk_fill_polygon(canvas.painter, points, 6, nk_rgb(0,0,0));} - - nk_stroke_line(canvas.painter, 15, 10, 200, 10, 2.0f, nk_rgb(189,45,75)); - nk_stroke_rect(canvas.painter, nk_rect(370, 20, 100, 100), 10, 3, nk_rgb(0,0,255)); - nk_stroke_curve(canvas.painter, 380, 200, 405, 270, 455, 120, 480, 200, 2, nk_rgb(0,150,220)); - nk_stroke_circle(canvas.painter, nk_rect(20, 370, 100, 100), 5, nk_rgb(0,255,120)); - nk_stroke_triangle(canvas.painter, 370, 250, 470, 250, 420, 350, 6, nk_rgb(255,0,143)); - } - canvas_end(&ctx, &canvas);} - - /* Draw */ - glfwGetWindowSize(win, &width, &height); - glViewport(0, 0, width, height); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(0.2f, 0.2f, 0.2f, 1.0f); - device_draw(&device, &ctx, width, height, NK_ANTI_ALIASING_ON); - glfwSwapBuffers(win); - }}} - nk_font_atlas_clear(&atlas); - nk_free(&ctx); - device_shutdown(&device); - glfwTerminate(); - return 0; -} - diff --git a/deps/nuklear/example/extended.c b/deps/nuklear/example/extended.c deleted file mode 100644 index e555d654..00000000 --- a/deps/nuklear/example/extended.c +++ /dev/null @@ -1,906 +0,0 @@ -/* nuklear - v1.05 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#include "../nuklear.h" - -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" - -/* macros */ -#define WINDOW_WIDTH 1200 -#define WINDOW_HEIGHT 800 - -#define MAX_VERTEX_MEMORY 512 * 1024 -#define MAX_ELEMENT_MEMORY 128 * 1024 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -#ifdef __APPLE__ - #define NK_SHADER_VERSION "#version 150\n" -#else - #define NK_SHADER_VERSION "#version 300 es\n" -#endif - -struct media { - struct nk_font *font_14; - struct nk_font *font_18; - struct nk_font *font_20; - struct nk_font *font_22; - - struct nk_image unchecked; - struct nk_image checked; - struct nk_image rocket; - struct nk_image cloud; - struct nk_image pen; - struct nk_image play; - struct nk_image pause; - struct nk_image stop; - struct nk_image prev; - struct nk_image next; - struct nk_image tools; - struct nk_image dir; - struct nk_image copy; - struct nk_image convert; - struct nk_image del; - struct nk_image edit; - struct nk_image images[9]; - struct nk_image menu[6]; -}; - -/* =============================================================== - * - * CUSTOM WIDGET - * - * ===============================================================*/ -static int -ui_piemenu(struct nk_context *ctx, struct nk_vec2 pos, float radius, - struct nk_image *icons, int item_count) -{ - int ret = -1; - struct nk_rect total_space; - struct nk_rect bounds; - int active_item = 0; - - /* pie menu popup */ - struct nk_color border = ctx->style.window.border_color; - struct nk_style_item background = ctx->style.window.fixed_background; - ctx->style.window.fixed_background = nk_style_item_hide(); - ctx->style.window.border_color = nk_rgba(0,0,0,0); - - total_space = nk_window_get_content_region(ctx); - ctx->style.window.spacing = nk_vec2(0,0); - ctx->style.window.padding = nk_vec2(0,0); - - if (nk_popup_begin(ctx, NK_POPUP_STATIC, "piemenu", NK_WINDOW_NO_SCROLLBAR, - nk_rect(pos.x - total_space.x - radius, pos.y - radius - total_space.y, - 2*radius,2*radius))) - { - int i = 0; - struct nk_command_buffer* out = nk_window_get_canvas(ctx); - const struct nk_input *in = &ctx->input; - - total_space = nk_window_get_content_region(ctx); - ctx->style.window.spacing = nk_vec2(4,4); - ctx->style.window.padding = nk_vec2(8,8); - nk_layout_row_dynamic(ctx, total_space.h, 1); - nk_widget(&bounds, ctx); - - /* outer circle */ - nk_fill_circle(out, bounds, nk_rgb(50,50,50)); - { - /* circle buttons */ - float step = (2 * 3.141592654f) / (float)(MAX(1,item_count)); - float a_min = 0; float a_max = step; - - struct nk_vec2 center = nk_vec2(bounds.x + bounds.w / 2.0f, bounds.y + bounds.h / 2.0f); - struct nk_vec2 drag = nk_vec2(in->mouse.pos.x - center.x, in->mouse.pos.y - center.y); - float angle = (float)atan2(drag.y, drag.x); - if (angle < -0.0f) angle += 2.0f * 3.141592654f; - active_item = (int)(angle/step); - - for (i = 0; i < item_count; ++i) { - struct nk_rect content; - float rx, ry, dx, dy, a; - nk_fill_arc(out, center.x, center.y, (bounds.w/2.0f), - a_min, a_max, (active_item == i) ? nk_rgb(45,100,255): nk_rgb(60,60,60)); - - /* separator line */ - rx = bounds.w/2.0f; ry = 0; - dx = rx * (float)cos(a_min) - ry * (float)sin(a_min); - dy = rx * (float)sin(a_min) + ry * (float)cos(a_min); - nk_stroke_line(out, center.x, center.y, - center.x + dx, center.y + dy, 1.0f, nk_rgb(50,50,50)); - - /* button content */ - a = a_min + (a_max - a_min)/2.0f; - rx = bounds.w/2.5f; ry = 0; - content.w = 30; content.h = 30; - content.x = center.x + ((rx * (float)cos(a) - ry * (float)sin(a)) - content.w/2.0f); - content.y = center.y + (rx * (float)sin(a) + ry * (float)cos(a) - content.h/2.0f); - nk_draw_image(out, content, &icons[i], nk_rgb(255,255,255)); - a_min = a_max; a_max += step; - } - } - { - /* inner circle */ - struct nk_rect inner; - inner.x = bounds.x + bounds.w/2 - bounds.w/4; - inner.y = bounds.y + bounds.h/2 - bounds.h/4; - inner.w = bounds.w/2; inner.h = bounds.h/2; - nk_fill_circle(out, inner, nk_rgb(45,45,45)); - - /* active icon content */ - bounds.w = inner.w / 2.0f; - bounds.h = inner.h / 2.0f; - bounds.x = inner.x + inner.w/2 - bounds.w/2; - bounds.y = inner.y + inner.h/2 - bounds.h/2; - nk_draw_image(out, bounds, &icons[active_item], nk_rgb(255,255,255)); - } - nk_layout_space_end(ctx); - if (!nk_input_is_mouse_down(&ctx->input, NK_BUTTON_RIGHT)) { - nk_popup_close(ctx); - ret = active_item; - } - } else ret = -2; - ctx->style.window.spacing = nk_vec2(4,4); - ctx->style.window.padding = nk_vec2(8,8); - nk_popup_end(ctx); - - ctx->style.window.fixed_background = background; - ctx->style.window.border_color = border; - return ret; -} - -/* =============================================================== - * - * GRID - * - * ===============================================================*/ -static void -grid_demo(struct nk_context *ctx, struct media *media) -{ - static char text[3][64]; - static int text_len[3]; - static const char *items[] = {"Item 0","item 1","item 2"}; - static int selected_item = 0; - static int check = 1; - - int i; - nk_style_set_font(ctx, &media->font_20->handle); - if (nk_begin(ctx, "Grid Demo", nk_rect(600, 350, 275, 250), - NK_WINDOW_TITLE|NK_WINDOW_BORDER|NK_WINDOW_MOVABLE| - NK_WINDOW_NO_SCROLLBAR)) - { - nk_style_set_font(ctx, &media->font_18->handle); - nk_layout_row_dynamic(ctx, 30, 2); - nk_label(ctx, "Floating point:", NK_TEXT_RIGHT); - nk_edit_string(ctx, NK_EDIT_FIELD, text[0], &text_len[0], 64, nk_filter_float); - nk_label(ctx, "Hexadecimal:", NK_TEXT_RIGHT); - nk_edit_string(ctx, NK_EDIT_FIELD, text[1], &text_len[1], 64, nk_filter_hex); - nk_label(ctx, "Binary:", NK_TEXT_RIGHT); - nk_edit_string(ctx, NK_EDIT_FIELD, text[2], &text_len[2], 64, nk_filter_binary); - nk_label(ctx, "Checkbox:", NK_TEXT_RIGHT); - nk_checkbox_label(ctx, "Check me", &check); - nk_label(ctx, "Combobox:", NK_TEXT_RIGHT); - if (nk_combo_begin_label(ctx, items[selected_item], nk_vec2(nk_widget_width(ctx), 200))) { - nk_layout_row_dynamic(ctx, 25, 1); - for (i = 0; i < 3; ++i) - if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT)) - selected_item = i; - nk_combo_end(ctx); - } - } - nk_end(ctx); - nk_style_set_font(ctx, &media->font_14->handle); -} - -/* =============================================================== - * - * BUTTON DEMO - * - * ===============================================================*/ -static void -ui_header(struct nk_context *ctx, struct media *media, const char *title) -{ - nk_style_set_font(ctx, &media->font_18->handle); - nk_layout_row_dynamic(ctx, 20, 1); - nk_label(ctx, title, NK_TEXT_LEFT); -} - -static void -ui_widget(struct nk_context *ctx, struct media *media, float height) -{ - static const float ratio[] = {0.15f, 0.85f}; - nk_style_set_font(ctx, &media->font_22->handle); - nk_layout_row(ctx, NK_DYNAMIC, height, 2, ratio); - nk_spacing(ctx, 1); -} - -static void -ui_widget_centered(struct nk_context *ctx, struct media *media, float height) -{ - static const float ratio[] = {0.15f, 0.50f, 0.35f}; - nk_style_set_font(ctx, &media->font_22->handle); - nk_layout_row(ctx, NK_DYNAMIC, height, 3, ratio); - nk_spacing(ctx, 1); -} - -static void -button_demo(struct nk_context *ctx, struct media *media) -{ - static int option = 1; - static int toggle0 = 1; - static int toggle1 = 0; - static int toggle2 = 1; - - nk_style_set_font(ctx, &media->font_20->handle); - nk_begin(ctx, "Button Demo", nk_rect(50,50,255,610), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_TITLE); - - /*------------------------------------------------ - * MENU - *------------------------------------------------*/ - nk_menubar_begin(ctx); - { - /* toolbar */ - nk_layout_row_static(ctx, 40, 40, 4); - if (nk_menu_begin_image(ctx, "Music", media->play, nk_vec2(110,120))) - { - /* settings */ - nk_layout_row_dynamic(ctx, 25, 1); - nk_menu_item_image_label(ctx, media->play, "Play", NK_TEXT_RIGHT); - nk_menu_item_image_label(ctx, media->stop, "Stop", NK_TEXT_RIGHT); - nk_menu_item_image_label(ctx, media->pause, "Pause", NK_TEXT_RIGHT); - nk_menu_item_image_label(ctx, media->next, "Next", NK_TEXT_RIGHT); - nk_menu_item_image_label(ctx, media->prev, "Prev", NK_TEXT_RIGHT); - nk_menu_end(ctx); - } - nk_button_image(ctx, media->tools); - nk_button_image(ctx, media->cloud); - nk_button_image(ctx, media->pen); - } - nk_menubar_end(ctx); - - /*------------------------------------------------ - * BUTTON - *------------------------------------------------*/ - ui_header(ctx, media, "Push buttons"); - ui_widget(ctx, media, 35); - if (nk_button_label(ctx, "Push me")) - fprintf(stdout, "pushed!\n"); - ui_widget(ctx, media, 35); - if (nk_button_image_label(ctx, media->rocket, "Styled", NK_TEXT_CENTERED)) - fprintf(stdout, "rocket!\n"); - - /*------------------------------------------------ - * REPEATER - *------------------------------------------------*/ - ui_header(ctx, media, "Repeater"); - ui_widget(ctx, media, 35); - if (nk_button_label(ctx, "Press me")) - fprintf(stdout, "pressed!\n"); - - /*------------------------------------------------ - * TOGGLE - *------------------------------------------------*/ - ui_header(ctx, media, "Toggle buttons"); - ui_widget(ctx, media, 35); - if (nk_button_image_label(ctx, (toggle0) ? media->checked: media->unchecked, "Toggle", NK_TEXT_LEFT)) - toggle0 = !toggle0; - - ui_widget(ctx, media, 35); - if (nk_button_image_label(ctx, (toggle1) ? media->checked: media->unchecked, "Toggle", NK_TEXT_LEFT)) - toggle1 = !toggle1; - - ui_widget(ctx, media, 35); - if (nk_button_image_label(ctx, (toggle2) ? media->checked: media->unchecked, "Toggle", NK_TEXT_LEFT)) - toggle2 = !toggle2; - - /*------------------------------------------------ - * RADIO - *------------------------------------------------*/ - ui_header(ctx, media, "Radio buttons"); - ui_widget(ctx, media, 35); - if (nk_button_symbol_label(ctx, (option == 0)?NK_SYMBOL_CIRCLE_OUTLINE:NK_SYMBOL_CIRCLE_SOLID, "Select", NK_TEXT_LEFT)) - option = 0; - ui_widget(ctx, media, 35); - if (nk_button_symbol_label(ctx, (option == 1)?NK_SYMBOL_CIRCLE_OUTLINE:NK_SYMBOL_CIRCLE_SOLID, "Select", NK_TEXT_LEFT)) - option = 1; - ui_widget(ctx, media, 35); - if (nk_button_symbol_label(ctx, (option == 2)?NK_SYMBOL_CIRCLE_OUTLINE:NK_SYMBOL_CIRCLE_SOLID, "Select", NK_TEXT_LEFT)) - option = 2; - - /*------------------------------------------------ - * CONTEXTUAL - *------------------------------------------------*/ - nk_style_set_font(ctx, &media->font_18->handle); - if (nk_contextual_begin(ctx, NK_WINDOW_NO_SCROLLBAR, nk_vec2(150, 300), nk_window_get_bounds(ctx))) { - nk_layout_row_dynamic(ctx, 30, 1); - if (nk_contextual_item_image_label(ctx, media->copy, "Clone", NK_TEXT_RIGHT)) - fprintf(stdout, "pressed clone!\n"); - if (nk_contextual_item_image_label(ctx, media->del, "Delete", NK_TEXT_RIGHT)) - fprintf(stdout, "pressed delete!\n"); - if (nk_contextual_item_image_label(ctx, media->convert, "Convert", NK_TEXT_RIGHT)) - fprintf(stdout, "pressed convert!\n"); - if (nk_contextual_item_image_label(ctx, media->edit, "Edit", NK_TEXT_RIGHT)) - fprintf(stdout, "pressed edit!\n"); - nk_contextual_end(ctx); - } - nk_style_set_font(ctx, &media->font_14->handle); - nk_end(ctx); -} - -/* =============================================================== - * - * BASIC DEMO - * - * ===============================================================*/ -static void -basic_demo(struct nk_context *ctx, struct media *media) -{ - static int image_active; - static int check0 = 1; - static int check1 = 0; - static size_t prog = 80; - static int selected_item = 0; - static int selected_image = 3; - static int selected_icon = 0; - static const char *items[] = {"Item 0","item 1","item 2"}; - static int piemenu_active = 0; - static struct nk_vec2 piemenu_pos; - - int i = 0; - nk_style_set_font(ctx, &media->font_20->handle); - nk_begin(ctx, "Basic Demo", nk_rect(320, 50, 275, 610), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_TITLE); - - /*------------------------------------------------ - * POPUP BUTTON - *------------------------------------------------*/ - ui_header(ctx, media, "Popup & Scrollbar & Images"); - ui_widget(ctx, media, 35); - if (nk_button_image_label(ctx, media->dir, "Images", NK_TEXT_CENTERED)) - image_active = !image_active; - - /*------------------------------------------------ - * SELECTED IMAGE - *------------------------------------------------*/ - ui_header(ctx, media, "Selected Image"); - ui_widget_centered(ctx, media, 100); - nk_image(ctx, media->images[selected_image]); - - /*------------------------------------------------ - * IMAGE POPUP - *------------------------------------------------*/ - if (image_active) { - struct nk_panel popup; - if (nk_popup_begin(ctx, NK_POPUP_STATIC, "Image Popup", 0, nk_rect(265, 0, 320, 220))) { - nk_layout_row_static(ctx, 82, 82, 3); - for (i = 0; i < 9; ++i) { - if (nk_button_image(ctx, media->images[i])) { - selected_image = i; - image_active = 0; - nk_popup_close(ctx); - } - } - nk_popup_end(ctx); - } - } - /*------------------------------------------------ - * COMBOBOX - *------------------------------------------------*/ - ui_header(ctx, media, "Combo box"); - ui_widget(ctx, media, 40); - if (nk_combo_begin_label(ctx, items[selected_item], nk_vec2(nk_widget_width(ctx), 200))) { - nk_layout_row_dynamic(ctx, 35, 1); - for (i = 0; i < 3; ++i) - if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT)) - selected_item = i; - nk_combo_end(ctx); - } - - ui_widget(ctx, media, 40); - if (nk_combo_begin_image_label(ctx, items[selected_icon], media->images[selected_icon], nk_vec2(nk_widget_width(ctx), 200))) { - nk_layout_row_dynamic(ctx, 35, 1); - for (i = 0; i < 3; ++i) - if (nk_combo_item_image_label(ctx, media->images[i], items[i], NK_TEXT_RIGHT)) - selected_icon = i; - nk_combo_end(ctx); - } - - /*------------------------------------------------ - * CHECKBOX - *------------------------------------------------*/ - ui_header(ctx, media, "Checkbox"); - ui_widget(ctx, media, 30); - nk_checkbox_label(ctx, "Flag 1", &check0); - ui_widget(ctx, media, 30); - nk_checkbox_label(ctx, "Flag 2", &check1); - - /*------------------------------------------------ - * PROGRESSBAR - *------------------------------------------------*/ - ui_header(ctx, media, "Progressbar"); - ui_widget(ctx, media, 35); - nk_progress(ctx, &prog, 100, nk_true); - - /*------------------------------------------------ - * PIEMENU - *------------------------------------------------*/ - if (nk_input_is_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_RIGHT, - nk_window_get_bounds(ctx),nk_true)){ - piemenu_pos = ctx->input.mouse.pos; - piemenu_active = 1; - } - - if (piemenu_active) { - int ret = ui_piemenu(ctx, piemenu_pos, 140, &media->menu[0], 6); - if (ret == -2) piemenu_active = 0; - if (ret != -1) { - fprintf(stdout, "piemenu selected: %d\n", ret); - piemenu_active = 0; - } - } - nk_style_set_font(ctx, &media->font_14->handle); - nk_end(ctx); -} - -/* =============================================================== - * - * DEVICE - * - * ===============================================================*/ -struct nk_glfw_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -struct device { - struct nk_buffer cmds; - struct nk_draw_null_texture null; - GLuint vbo, vao, ebo; - GLuint prog; - GLuint vert_shdr; - GLuint frag_shdr; - GLint attrib_pos; - GLint attrib_uv; - GLint attrib_col; - GLint uniform_tex; - GLint uniform_proj; - GLuint font_tex; -}; - -static void -die(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputs("\n", stderr); - exit(EXIT_FAILURE); -} - -static struct nk_image -icon_load(const char *filename) -{ - int x,y,n; - GLuint tex; - unsigned char *data = stbi_load(filename, &x, &y, &n, 0); - if (!data) die("[SDL]: failed to load image: %s", filename); - - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - glGenerateMipmap(GL_TEXTURE_2D); - stbi_image_free(data); - return nk_image_id((int)tex); -} - -static void -device_init(struct device *dev) -{ - GLint status; - static const GLchar *vertex_shader = - NK_SHADER_VERSION - "uniform mat4 ProjMtx;\n" - "in vec2 Position;\n" - "in vec2 TexCoord;\n" - "in vec4 Color;\n" - "out vec2 Frag_UV;\n" - "out vec4 Frag_Color;\n" - "void main() {\n" - " Frag_UV = TexCoord;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" - "}\n"; - static const GLchar *fragment_shader = - NK_SHADER_VERSION - "precision mediump float;\n" - "uniform sampler2D Texture;\n" - "in vec2 Frag_UV;\n" - "in vec4 Frag_Color;\n" - "out vec4 Out_Color;\n" - "void main(){\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" - "}\n"; - - nk_buffer_init_default(&dev->cmds); - dev->prog = glCreateProgram(); - dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); - dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); - glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); - glCompileShader(dev->vert_shdr); - glCompileShader(dev->frag_shdr); - glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glAttachShader(dev->prog, dev->vert_shdr); - glAttachShader(dev->prog, dev->frag_shdr); - glLinkProgram(dev->prog); - glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); - assert(status == GL_TRUE); - - dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); - dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); - dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); - dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); - dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); - - { - /* buffer setup */ - GLsizei vs = sizeof(struct nk_glfw_vertex); - size_t vp = offsetof(struct nk_glfw_vertex, position); - size_t vt = offsetof(struct nk_glfw_vertex, uv); - size_t vc = offsetof(struct nk_glfw_vertex, col); - - glGenBuffers(1, &dev->vbo); - glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); - - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); - } - - glBindTexture(GL_TEXTURE_2D, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); -} - -static void -device_upload_atlas(struct device *dev, const void *image, int width, int height) -{ - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - -static void -device_shutdown(struct device *dev) -{ - glDetachShader(dev->prog, dev->vert_shdr); - glDetachShader(dev->prog, dev->frag_shdr); - glDeleteShader(dev->vert_shdr); - glDeleteShader(dev->frag_shdr); - glDeleteProgram(dev->prog); - glDeleteTextures(1, &dev->font_tex); - glDeleteBuffers(1, &dev->vbo); - glDeleteBuffers(1, &dev->ebo); - nk_buffer_free(&dev->cmds); -} - -static void -device_draw(struct device *dev, struct nk_context *ctx, int width, int height, - struct nk_vec2 scale, enum nk_anti_aliasing AA) -{ - GLfloat ortho[4][4] = { - {2.0f, 0.0f, 0.0f, 0.0f}, - {0.0f,-2.0f, 0.0f, 0.0f}, - {0.0f, 0.0f,-1.0f, 0.0f}, - {-1.0f,1.0f, 0.0f, 1.0f}, - }; - ortho[0][0] /= (GLfloat)width; - ortho[1][1] /= (GLfloat)height; - - /* setup global state */ - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - /* setup program */ - glUseProgram(dev->prog); - glUniform1i(dev->uniform_tex, 0); - glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); - { - /* convert from command queue into draw list and draw to screen */ - const struct nk_draw_command *cmd; - void *vertices, *elements; - const nk_draw_index *offset = NULL; - - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW); - - /* load draw vertices & elements directly into vertex + element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); - { - /* fill convert configuration */ - struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - NK_MEMSET(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_glfw_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex); - config.null = dev->null; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - - /* setup buffers to load vertices and elements */ - {struct nk_buffer vbuf, ebuf; - nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY); - nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY); - nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);} - } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - - /* iterate over and execute each draw command */ - nk_draw_foreach(cmd, ctx, &dev->cmds) - { - if (!cmd->elem_count) continue; - glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor( - (GLint)(cmd->clip_rect.x * scale.x), - (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), - (GLint)(cmd->clip_rect.w * scale.x), - (GLint)(cmd->clip_rect.h * scale.y)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); - offset += cmd->elem_count; - } - nk_clear(ctx); - } - - /* default OpenGL state */ - glUseProgram(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); -} - -/* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/ -static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);} -static void text_input(GLFWwindow *win, unsigned int codepoint) -{nk_input_unicode((struct nk_context*)glfwGetWindowUserPointer(win), codepoint);} -static void scroll_input(GLFWwindow *win, double _, double yoff) -{UNUSED(_);nk_input_scroll((struct nk_context*)glfwGetWindowUserPointer(win), (float)yoff);} - -int main(int argc, char *argv[]) -{ - /* Platform */ - static GLFWwindow *win; - int width = 0, height = 0; - int display_width=0, display_height=0; - - /* GUI */ - struct device device; - struct nk_font_atlas atlas; - struct media media; - struct nk_context ctx; - - /* GLFW */ - glfwSetErrorCallback(error_callback); - if (!glfwInit()) { - fprintf(stdout, "[GFLW] failed to init!\n"); - exit(1); - } - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#ifdef __APPLE__ - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); -#endif - win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL); - glfwMakeContextCurrent(win); - glfwSetWindowUserPointer(win, &ctx); - glfwSetCharCallback(win, text_input); - glfwSetScrollCallback(win, scroll_input); - glfwGetWindowSize(win, &width, &height); - glfwGetFramebufferSize(win, &display_width, &display_height); - - /* OpenGL */ - glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); - glewExperimental = 1; - if (glewInit() != GLEW_OK) { - fprintf(stderr, "Failed to setup GLEW\n"); - exit(1); - } - - {/* GUI */ - device_init(&device); - {const void *image; int w, h; - struct nk_font_config cfg = nk_font_config(0); - cfg.oversample_h = 3; cfg.oversample_v = 2; - /* Loading one font with different heights is only required if you want higher - * quality text otherwise you can just set the font height directly - * e.g.: ctx->style.font.height = 20. */ - nk_font_atlas_init_default(&atlas); - nk_font_atlas_begin(&atlas); - media.font_14 = nk_font_atlas_add_from_file(&atlas, "../../extra_font/Roboto-Regular.ttf", 14.0f, &cfg); - media.font_18 = nk_font_atlas_add_from_file(&atlas, "../../extra_font/Roboto-Regular.ttf", 18.0f, &cfg); - media.font_20 = nk_font_atlas_add_from_file(&atlas, "../../extra_font/Roboto-Regular.ttf", 20.0f, &cfg); - media.font_22 = nk_font_atlas_add_from_file(&atlas, "../../extra_font/Roboto-Regular.ttf", 22.0f, &cfg); - image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - device_upload_atlas(&device, image, w, h); - nk_font_atlas_end(&atlas, nk_handle_id((int)device.font_tex), &device.null);} - nk_init_default(&ctx, &media.font_14->handle);} - - /* icons */ - glEnable(GL_TEXTURE_2D); - media.unchecked = icon_load("../icon/unchecked.png"); - media.checked = icon_load("../icon/checked.png"); - media.rocket = icon_load("../icon/rocket.png"); - media.cloud = icon_load("../icon/cloud.png"); - media.pen = icon_load("../icon/pen.png"); - media.play = icon_load("../icon/play.png"); - media.pause = icon_load("../icon/pause.png"); - media.stop = icon_load("../icon/stop.png"); - media.next = icon_load("../icon/next.png"); - media.prev = icon_load("../icon/prev.png"); - media.tools = icon_load("../icon/tools.png"); - media.dir = icon_load("../icon/directory.png"); - media.copy = icon_load("../icon/copy.png"); - media.convert = icon_load("../icon/export.png"); - media.del = icon_load("../icon/delete.png"); - media.edit = icon_load("../icon/edit.png"); - media.menu[0] = icon_load("../icon/home.png"); - media.menu[1] = icon_load("../icon/phone.png"); - media.menu[2] = icon_load("../icon/plane.png"); - media.menu[3] = icon_load("../icon/wifi.png"); - media.menu[4] = icon_load("../icon/settings.png"); - media.menu[5] = icon_load("../icon/volume.png"); - - {int i; - for (i = 0; i < 9; ++i) { - char buffer[256]; - sprintf(buffer, "../images/image%d.png", (i+1)); - media.images[i] = icon_load(buffer); - }} - - while (!glfwWindowShouldClose(win)) - { - /* High DPI displays */ - struct nk_vec2 scale; - glfwGetWindowSize(win, &width, &height); - glfwGetFramebufferSize(win, &display_width, &display_height); - scale.x = (float)display_width/(float)width; - scale.y = (float)display_height/(float)height; - - /* Input */ - {double x, y; - nk_input_begin(&ctx); - glfwPollEvents(); - nk_input_key(&ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS); - if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || - glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) { - nk_input_key(&ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_P) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_SHIFT, 1); - } else { - nk_input_key(&ctx, NK_KEY_COPY, 0); - nk_input_key(&ctx, NK_KEY_PASTE, 0); - nk_input_key(&ctx, NK_KEY_CUT, 0); - nk_input_key(&ctx, NK_KEY_SHIFT, 0); - } - glfwGetCursorPos(win, &x, &y); - nk_input_motion(&ctx, (int)x, (int)y); - nk_input_button(&ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS); - nk_input_button(&ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS); - nk_input_button(&ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS); - nk_input_end(&ctx);} - - /* GUI */ - basic_demo(&ctx, &media); - button_demo(&ctx, &media); - grid_demo(&ctx, &media); - - /* Draw */ - glViewport(0, 0, display_width, display_height); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(0.3f, 0.3f, 0.3f, 1.0f); - device_draw(&device, &ctx, width, height, scale, NK_ANTI_ALIASING_ON); - glfwSwapBuffers(win); - } - - glDeleteTextures(1,(const GLuint*)&media.unchecked.handle.id); - glDeleteTextures(1,(const GLuint*)&media.checked.handle.id); - glDeleteTextures(1,(const GLuint*)&media.rocket.handle.id); - glDeleteTextures(1,(const GLuint*)&media.cloud.handle.id); - glDeleteTextures(1,(const GLuint*)&media.pen.handle.id); - glDeleteTextures(1,(const GLuint*)&media.play.handle.id); - glDeleteTextures(1,(const GLuint*)&media.pause.handle.id); - glDeleteTextures(1,(const GLuint*)&media.stop.handle.id); - glDeleteTextures(1,(const GLuint*)&media.next.handle.id); - glDeleteTextures(1,(const GLuint*)&media.prev.handle.id); - glDeleteTextures(1,(const GLuint*)&media.tools.handle.id); - glDeleteTextures(1,(const GLuint*)&media.dir.handle.id); - glDeleteTextures(1,(const GLuint*)&media.del.handle.id); - - nk_font_atlas_clear(&atlas); - nk_free(&ctx); - - device_shutdown(&device); - glfwTerminate(); - return 0; -} - diff --git a/deps/nuklear/example/file_browser.c b/deps/nuklear/example/file_browser.c deleted file mode 100644 index ece4cb83..00000000 --- a/deps/nuklear/example/file_browser.c +++ /dev/null @@ -1,910 +0,0 @@ -/* nuklear - v1.05 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#include "../nuklear.h" - -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" - -/* macros */ -#define WINDOW_WIDTH 1200 -#define WINDOW_HEIGHT 800 - -#define MAX_VERTEX_MEMORY 512 * 1024 -#define MAX_ELEMENT_MEMORY 128 * 1024 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -#ifdef __APPLE__ - #define NK_SHADER_VERSION "#version 150\n" -#else - #define NK_SHADER_VERSION "#version 300 es\n" -#endif - -/* =============================================================== - * - * GUI - * - * ===============================================================*/ -struct icons { - struct nk_image desktop; - struct nk_image home; - struct nk_image computer; - struct nk_image directory; - - struct nk_image default_file; - struct nk_image text_file; - struct nk_image music_file; - struct nk_image font_file; - struct nk_image img_file; - struct nk_image movie_file; -}; - -enum file_groups { - FILE_GROUP_DEFAULT, - FILE_GROUP_TEXT, - FILE_GROUP_MUSIC, - FILE_GROUP_FONT, - FILE_GROUP_IMAGE, - FILE_GROUP_MOVIE, - FILE_GROUP_MAX -}; - -enum file_types { - FILE_DEFAULT, - FILE_TEXT, - FILE_C_SOURCE, - FILE_CPP_SOURCE, - FILE_HEADER, - FILE_CPP_HEADER, - FILE_MP3, - FILE_WAV, - FILE_OGG, - FILE_TTF, - FILE_BMP, - FILE_PNG, - FILE_JPEG, - FILE_PCX, - FILE_TGA, - FILE_GIF, - FILE_MAX -}; - -struct file_group { - enum file_groups group; - const char *name; - struct nk_image *icon; -}; - -struct file { - enum file_types type; - const char *suffix; - enum file_groups group; -}; - -struct media { - int font; - int icon_sheet; - struct icons icons; - struct file_group group[FILE_GROUP_MAX]; - struct file files[FILE_MAX]; -}; - -#define MAX_PATH_LEN 512 -struct file_browser { - /* path */ - char file[MAX_PATH_LEN]; - char home[MAX_PATH_LEN]; - char desktop[MAX_PATH_LEN]; - char directory[MAX_PATH_LEN]; - - /* directory content */ - char **files; - char **directories; - size_t file_count; - size_t dir_count; - struct media *media; -}; - -#ifdef __unix__ -#include -#include -#endif - -#ifndef _WIN32 -# include -#endif - -static void -die(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputs("\n", stderr); - exit(EXIT_FAILURE); -} - -static char* -file_load(const char* path, size_t* siz) -{ - char *buf; - FILE *fd = fopen(path, "rb"); - if (!fd) die("Failed to open file: %s\n", path); - fseek(fd, 0, SEEK_END); - *siz = (size_t)ftell(fd); - fseek(fd, 0, SEEK_SET); - buf = (char*)calloc(*siz, 1); - fread(buf, *siz, 1, fd); - fclose(fd); - return buf; -} - -static char* -str_duplicate(const char *src) -{ - char *ret; - size_t len = strlen(src); - if (!len) return 0; - ret = (char*)malloc(len+1); - if (!ret) return 0; - memcpy(ret, src, len); - ret[len] = '\0'; - return ret; -} - -static void -dir_free_list(char **list, size_t size) -{ - size_t i; - for (i = 0; i < size; ++i) - free(list[i]); - free(list); -} - -static char** -dir_list(const char *dir, int return_subdirs, size_t *count) -{ - size_t n = 0; - char buffer[MAX_PATH_LEN]; - char **results = NULL; - const DIR *none = NULL; - size_t capacity = 32; - size_t size; - DIR *z; - - assert(dir); - assert(count); - strncpy(buffer, dir, MAX_PATH_LEN); - n = strlen(buffer); - - if (n > 0 && (buffer[n-1] != '/')) - buffer[n++] = '/'; - - size = 0; - - z = opendir(dir); - if (z != none) { - int nonempty = 1; - struct dirent *data = readdir(z); - nonempty = (data != NULL); - if (!nonempty) return NULL; - - do { - DIR *y; - char *p; - int is_subdir; - if (data->d_name[0] == '.') - continue; - - strncpy(buffer + n, data->d_name, MAX_PATH_LEN-n); - y = opendir(buffer); - is_subdir = (y != NULL); - if (y != NULL) closedir(y); - - if ((return_subdirs && is_subdir) || (!is_subdir && !return_subdirs)){ - if (!size) { - results = (char**)calloc(sizeof(char*), capacity); - } else if (size >= capacity) { - void *old = results; - capacity = capacity * 2; - results = (char**)realloc(results, capacity * sizeof(char*)); - assert(results); - if (!results) free(old); - } - p = str_duplicate(data->d_name); - results[size++] = p; - } - } while ((data = readdir(z)) != NULL); - } - - if (z) closedir(z); - *count = size; - return results; -} - -static struct file_group -FILE_GROUP(enum file_groups group, const char *name, struct nk_image *icon) -{ - struct file_group fg; - fg.group = group; - fg.name = name; - fg.icon = icon; - return fg; -} - -static struct file -FILE_DEF(enum file_types type, const char *suffix, enum file_groups group) -{ - struct file fd; - fd.type = type; - fd.suffix = suffix; - fd.group = group; - return fd; -} - -static struct nk_image* -media_icon_for_file(struct media *media, const char *file) -{ - int i = 0; - const char *s = file; - char suffix[4]; - int found = 0; - memset(suffix, 0, sizeof(suffix)); - - /* extract suffix .xxx from file */ - while (*s++ != '\0') { - if (found && i < 3) - suffix[i++] = *s; - - if (*s == '.') { - if (found){ - found = 0; - break; - } - found = 1; - } - } - - /* check for all file definition of all groups for fitting suffix*/ - for (i = 0; i < FILE_MAX && found; ++i) { - struct file *d = &media->files[i]; - { - const char *f = d->suffix; - s = suffix; - while (f && *f && *s && *s == *f) { - s++; f++; - } - - /* found correct file definition so */ - if (f && *s == '\0' && *f == '\0') - return media->group[d->group].icon; - } - } - return &media->icons.default_file; -} - -static void -media_init(struct media *media) -{ - /* file groups */ - struct icons *icons = &media->icons; - media->group[FILE_GROUP_DEFAULT] = FILE_GROUP(FILE_GROUP_DEFAULT,"default",&icons->default_file); - media->group[FILE_GROUP_TEXT] = FILE_GROUP(FILE_GROUP_TEXT, "textual", &icons->text_file); - media->group[FILE_GROUP_MUSIC] = FILE_GROUP(FILE_GROUP_MUSIC, "music", &icons->music_file); - media->group[FILE_GROUP_FONT] = FILE_GROUP(FILE_GROUP_FONT, "font", &icons->font_file); - media->group[FILE_GROUP_IMAGE] = FILE_GROUP(FILE_GROUP_IMAGE, "image", &icons->img_file); - media->group[FILE_GROUP_MOVIE] = FILE_GROUP(FILE_GROUP_MOVIE, "movie", &icons->movie_file); - - /* files */ - media->files[FILE_DEFAULT] = FILE_DEF(FILE_DEFAULT, NULL, FILE_GROUP_DEFAULT); - media->files[FILE_TEXT] = FILE_DEF(FILE_TEXT, "txt", FILE_GROUP_TEXT); - media->files[FILE_C_SOURCE] = FILE_DEF(FILE_C_SOURCE, "c", FILE_GROUP_TEXT); - media->files[FILE_CPP_SOURCE] = FILE_DEF(FILE_CPP_SOURCE, "cpp", FILE_GROUP_TEXT); - media->files[FILE_HEADER] = FILE_DEF(FILE_HEADER, "h", FILE_GROUP_TEXT); - media->files[FILE_CPP_HEADER] = FILE_DEF(FILE_HEADER, "hpp", FILE_GROUP_TEXT); - media->files[FILE_MP3] = FILE_DEF(FILE_MP3, "mp3", FILE_GROUP_MUSIC); - media->files[FILE_WAV] = FILE_DEF(FILE_WAV, "wav", FILE_GROUP_MUSIC); - media->files[FILE_OGG] = FILE_DEF(FILE_OGG, "ogg", FILE_GROUP_MUSIC); - media->files[FILE_TTF] = FILE_DEF(FILE_TTF, "ttf", FILE_GROUP_FONT); - media->files[FILE_BMP] = FILE_DEF(FILE_BMP, "bmp", FILE_GROUP_IMAGE); - media->files[FILE_PNG] = FILE_DEF(FILE_PNG, "png", FILE_GROUP_IMAGE); - media->files[FILE_JPEG] = FILE_DEF(FILE_JPEG, "jpg", FILE_GROUP_IMAGE); - media->files[FILE_PCX] = FILE_DEF(FILE_PCX, "pcx", FILE_GROUP_IMAGE); - media->files[FILE_TGA] = FILE_DEF(FILE_TGA, "tga", FILE_GROUP_IMAGE); - media->files[FILE_GIF] = FILE_DEF(FILE_GIF, "gif", FILE_GROUP_IMAGE); -} - -static void -file_browser_reload_directory_content(struct file_browser *browser, const char *path) -{ - strncpy(browser->directory, path, MAX_PATH_LEN); - dir_free_list(browser->files, browser->file_count); - dir_free_list(browser->directories, browser->dir_count); - browser->files = dir_list(path, 0, &browser->file_count); - browser->directories = dir_list(path, 1, &browser->dir_count); -} - -static void -file_browser_init(struct file_browser *browser, struct media *media) -{ - memset(browser, 0, sizeof(*browser)); - browser->media = media; - { - /* load files and sub-directory list */ - const char *home = getenv("HOME"); -#ifdef _WIN32 - if (!home) home = getenv("USERPROFILE"); -#else - if (!home) home = getpwuid(getuid())->pw_dir; - { - size_t l; - strncpy(browser->home, home, MAX_PATH_LEN); - l = strlen(browser->home); - strcpy(browser->home + l, "/"); - strcpy(browser->directory, browser->home); - } -#endif - { - size_t l; - strcpy(browser->desktop, browser->home); - l = strlen(browser->desktop); - strcpy(browser->desktop + l, "desktop/"); - } - browser->files = dir_list(browser->directory, 0, &browser->file_count); - browser->directories = dir_list(browser->directory, 1, &browser->dir_count); - } -} - -static void -file_browser_free(struct file_browser *browser) -{ - if (browser->files) - dir_free_list(browser->files, browser->file_count); - if (browser->directories) - dir_free_list(browser->directories, browser->dir_count); - browser->files = NULL; - browser->directories = NULL; - memset(browser, 0, sizeof(*browser)); -} - -static int -file_browser_run(struct file_browser *browser, struct nk_context *ctx) -{ - int ret = 0; - struct media *media = browser->media; - struct nk_rect total_space; - - if (nk_begin(ctx, "File Browser", nk_rect(50, 50, 800, 600), - NK_WINDOW_BORDER|NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_MOVABLE)) - { - static float ratio[] = {0.25f, NK_UNDEFINED}; - float spacing_x = ctx->style.window.spacing.x; - - /* output path directory selector in the menubar */ - ctx->style.window.spacing.x = 0; - nk_menubar_begin(ctx); - { - char *d = browser->directory; - char *begin = d + 1; - nk_layout_row_dynamic(ctx, 25, 6); - while (*d++) { - if (*d == '/') { - *d = '\0'; - if (nk_button_label(ctx, begin)) { - *d++ = '/'; *d = '\0'; - file_browser_reload_directory_content(browser, browser->directory); - break; - } - *d = '/'; - begin = d + 1; - } - } - } - nk_menubar_end(ctx); - ctx->style.window.spacing.x = spacing_x; - - /* window layout */ - total_space = nk_window_get_content_region(ctx); - nk_layout_row(ctx, NK_DYNAMIC, total_space.h, 2, ratio); - nk_group_begin(ctx, "Special", NK_WINDOW_NO_SCROLLBAR); - { - struct nk_image home = media->icons.home; - struct nk_image desktop = media->icons.desktop; - struct nk_image computer = media->icons.computer; - - nk_layout_row_dynamic(ctx, 40, 1); - if (nk_button_image_label(ctx, home, "home", NK_TEXT_CENTERED)) - file_browser_reload_directory_content(browser, browser->home); - if (nk_button_image_label(ctx,desktop,"desktop",NK_TEXT_CENTERED)) - file_browser_reload_directory_content(browser, browser->desktop); - if (nk_button_image_label(ctx,computer,"computer",NK_TEXT_CENTERED)) - file_browser_reload_directory_content(browser, "/"); - nk_group_end(ctx); - } - - /* output directory content window */ - nk_group_begin(ctx, "Content", 0); - { - int index = -1; - size_t i = 0, j = 0, k = 0; - size_t rows = 0, cols = 0; - size_t count = browser->dir_count + browser->file_count; - - cols = 4; - rows = count / cols; - for (i = 0; i <= rows; i += 1) { - {size_t n = j + cols; - nk_layout_row_dynamic(ctx, 135, (int)cols); - for (; j < count && j < n; ++j) { - /* draw one row of icons */ - if (j < browser->dir_count) { - /* draw and execute directory buttons */ - if (nk_button_image(ctx,media->icons.directory)) - index = (int)j; - } else { - /* draw and execute files buttons */ - struct nk_image *icon; - size_t fileIndex = ((size_t)j - browser->dir_count); - icon = media_icon_for_file(media,browser->files[fileIndex]); - if (nk_button_image(ctx, *icon)) { - strncpy(browser->file, browser->directory, MAX_PATH_LEN); - n = strlen(browser->file); - strncpy(browser->file + n, browser->files[fileIndex], MAX_PATH_LEN - n); - ret = 1; - } - } - }} - {size_t n = k + cols; - nk_layout_row_dynamic(ctx, 20, (int)cols); - for (; k < count && k < n; k++) { - /* draw one row of labels */ - if (k < browser->dir_count) { - nk_label(ctx, browser->directories[k], NK_TEXT_CENTERED); - } else { - size_t t = k-browser->dir_count; - nk_label(ctx,browser->files[t],NK_TEXT_CENTERED); - } - }} - } - - if (index != -1) { - size_t n = strlen(browser->directory); - strncpy(browser->directory + n, browser->directories[index], MAX_PATH_LEN - n); - n = strlen(browser->directory); - if (n < MAX_PATH_LEN - 1) { - browser->directory[n] = '/'; - browser->directory[n+1] = '\0'; - } - file_browser_reload_directory_content(browser, browser->directory); - } - nk_group_end(ctx); - } - } - nk_end(ctx); - return ret; -} - -/* =============================================================== - * - * DEVICE - * - * ===============================================================*/ -struct nk_glfw_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -struct device { - struct nk_buffer cmds; - struct nk_draw_null_texture null; - GLuint vbo, vao, ebo; - GLuint prog; - GLuint vert_shdr; - GLuint frag_shdr; - GLint attrib_pos; - GLint attrib_uv; - GLint attrib_col; - GLint uniform_tex; - GLint uniform_proj; - GLuint font_tex; -}; -static struct nk_image -icon_load(const char *filename) -{ - int x,y,n; - GLuint tex; - unsigned char *data = stbi_load(filename, &x, &y, &n, 0); - if (!data) die("[SDL]: failed to load image: %s", filename); - - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - glGenerateMipmap(GL_TEXTURE_2D); - stbi_image_free(data); - return nk_image_id((int)tex); -} - -static void -device_init(struct device *dev) -{ - GLint status; - static const GLchar *vertex_shader = - NK_SHADER_VERSION - "uniform mat4 ProjMtx;\n" - "in vec2 Position;\n" - "in vec2 TexCoord;\n" - "in vec4 Color;\n" - "out vec2 Frag_UV;\n" - "out vec4 Frag_Color;\n" - "void main() {\n" - " Frag_UV = TexCoord;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" - "}\n"; - static const GLchar *fragment_shader = - NK_SHADER_VERSION - "precision mediump float;\n" - "uniform sampler2D Texture;\n" - "in vec2 Frag_UV;\n" - "in vec4 Frag_Color;\n" - "out vec4 Out_Color;\n" - "void main(){\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" - "}\n"; - - nk_buffer_init_default(&dev->cmds); - dev->prog = glCreateProgram(); - dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); - dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); - glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); - glCompileShader(dev->vert_shdr); - glCompileShader(dev->frag_shdr); - glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glAttachShader(dev->prog, dev->vert_shdr); - glAttachShader(dev->prog, dev->frag_shdr); - glLinkProgram(dev->prog); - glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); - assert(status == GL_TRUE); - - dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); - dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); - dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); - dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); - dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); - - { - /* buffer setup */ - GLsizei vs = sizeof(struct nk_glfw_vertex); - size_t vp = offsetof(struct nk_glfw_vertex, position); - size_t vt = offsetof(struct nk_glfw_vertex, uv); - size_t vc = offsetof(struct nk_glfw_vertex, col); - - glGenBuffers(1, &dev->vbo); - glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); - - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); - } - - glBindTexture(GL_TEXTURE_2D, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); -} - -static void -device_upload_atlas(struct device *dev, const void *image, int width, int height) -{ - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - -static void -device_shutdown(struct device *dev) -{ - glDetachShader(dev->prog, dev->vert_shdr); - glDetachShader(dev->prog, dev->frag_shdr); - glDeleteShader(dev->vert_shdr); - glDeleteShader(dev->frag_shdr); - glDeleteProgram(dev->prog); - glDeleteTextures(1, &dev->font_tex); - glDeleteBuffers(1, &dev->vbo); - glDeleteBuffers(1, &dev->ebo); - nk_buffer_free(&dev->cmds); -} - -static void -device_draw(struct device *dev, struct nk_context *ctx, int width, int height, - struct nk_vec2 scale, enum nk_anti_aliasing AA) -{ - GLfloat ortho[4][4] = { - {2.0f, 0.0f, 0.0f, 0.0f}, - {0.0f,-2.0f, 0.0f, 0.0f}, - {0.0f, 0.0f,-1.0f, 0.0f}, - {-1.0f,1.0f, 0.0f, 1.0f}, - }; - ortho[0][0] /= (GLfloat)width; - ortho[1][1] /= (GLfloat)height; - - /* setup global state */ - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - /* setup program */ - glUseProgram(dev->prog); - glUniform1i(dev->uniform_tex, 0); - glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); - { - /* convert from command queue into draw list and draw to screen */ - const struct nk_draw_command *cmd; - void *vertices, *elements; - const nk_draw_index *offset = NULL; - - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW); - - /* load draw vertices & elements directly into vertex + element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); - { - /* fill convert configuration */ - struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - NK_MEMSET(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_glfw_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex); - config.null = dev->null; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - - /* setup buffers to load vertices and elements */ - {struct nk_buffer vbuf, ebuf; - nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY); - nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY); - nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);} - } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - - /* iterate over and execute each draw command */ - nk_draw_foreach(cmd, ctx, &dev->cmds) { - if (!cmd->elem_count) continue; - glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor( - (GLint)(cmd->clip_rect.x * scale.x), - (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), - (GLint)(cmd->clip_rect.w * scale.x), - (GLint)(cmd->clip_rect.h * scale.y)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); - offset += cmd->elem_count; - } - nk_clear(ctx); - } - - /* default OpenGL state */ - glUseProgram(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); -} - - -/* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/ -static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);} -static void text_input(GLFWwindow *win, unsigned int codepoint) -{nk_input_unicode((struct nk_context*)glfwGetWindowUserPointer(win), codepoint);} -static void scroll_input(GLFWwindow *win, double _, double yoff) -{UNUSED(_);nk_input_scroll((struct nk_context*)glfwGetWindowUserPointer(win), (float)yoff);} - -int main(int argc, char *argv[]) -{ - /* Platform */ - static GLFWwindow *win; - int width = 0, height = 0; - int display_width = 0, display_height = 0; - - /* GUI */ - struct device device; - struct nk_context ctx; - struct nk_font *font; - struct nk_font_atlas atlas; - struct file_browser browser; - struct media media; - - /* GLFW */ - glfwSetErrorCallback(error_callback); - if (!glfwInit()) { - fprintf(stdout, "[GFLW] failed to init!\n"); - exit(1); - } - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#ifdef __APPLE__ - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); -#endif - win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL); - glfwMakeContextCurrent(win); - glfwSetWindowUserPointer(win, &ctx); - glfwSetCharCallback(win, text_input); - glfwSetScrollCallback(win, scroll_input); - - /* OpenGL */ - glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); - glewExperimental = 1; - if (glewInit() != GLEW_OK) { - fprintf(stderr, "Failed to setup GLEW\n"); - exit(1); - } - - {/* GUI */ - device_init(&device); - {const void *image; int w, h; - const char *font_path = (argc > 1) ? argv[1]: 0; - nk_font_atlas_init_default(&atlas); - nk_font_atlas_begin(&atlas); - if (font_path) font = nk_font_atlas_add_from_file(&atlas, font_path, 13.0f, NULL); - else font = nk_font_atlas_add_default(&atlas, 13.0f, NULL); - image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - device_upload_atlas(&device, image, w, h); - nk_font_atlas_end(&atlas, nk_handle_id((int)device.font_tex), &device.null);} - nk_init_default(&ctx, &font->handle);} - - /* icons */ - glEnable(GL_TEXTURE_2D); - media.icons.home = icon_load("../icon/home.png"); - media.icons.directory = icon_load("../icon/directory.png"); - media.icons.computer = icon_load("../icon/computer.png"); - media.icons.desktop = icon_load("../icon/desktop.png"); - media.icons.default_file = icon_load("../icon/default.png"); - media.icons.text_file = icon_load("../icon/text.png"); - media.icons.music_file = icon_load("../icon/music.png"); - media.icons.font_file = icon_load("../icon/font.png"); - media.icons.img_file = icon_load("../icon/img.png"); - media.icons.movie_file = icon_load("../icon/movie.png"); - media_init(&media); - - file_browser_init(&browser, &media); - while (!glfwWindowShouldClose(win)) - { - /* High DPI displays */ - struct nk_vec2 scale; - glfwGetWindowSize(win, &width, &height); - glfwGetFramebufferSize(win, &display_width, &display_height); - scale.x = (float)display_width/(float)width; - scale.y = (float)display_height/(float)height; - - /* Input */ - {double x, y; - nk_input_begin(&ctx); - glfwPollEvents(); - nk_input_key(&ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS); - if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || - glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) { - nk_input_key(&ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_P) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_SHIFT, 1); - } else { - nk_input_key(&ctx, NK_KEY_COPY, 0); - nk_input_key(&ctx, NK_KEY_PASTE, 0); - nk_input_key(&ctx, NK_KEY_CUT, 0); - nk_input_key(&ctx, NK_KEY_SHIFT, 0); - } - glfwGetCursorPos(win, &x, &y); - nk_input_motion(&ctx, (int)x, (int)y); - nk_input_button(&ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS); - nk_input_button(&ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS); - nk_input_button(&ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS); - nk_input_end(&ctx);} - - /* GUI */ - file_browser_run(&browser, &ctx); - - /* Draw */ - glViewport(0, 0, display_width, display_height); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(0.2f, 0.2f, 0.2f, 1.0f); - device_draw(&device, &ctx, width, height, scale, NK_ANTI_ALIASING_ON); - glfwSwapBuffers(win); - } - - glDeleteTextures(1,(const GLuint*)&media.icons.home.handle.id); - glDeleteTextures(1,(const GLuint*)&media.icons.directory.handle.id); - glDeleteTextures(1,(const GLuint*)&media.icons.computer.handle.id); - glDeleteTextures(1,(const GLuint*)&media.icons.desktop.handle.id); - glDeleteTextures(1,(const GLuint*)&media.icons.default_file.handle.id); - glDeleteTextures(1,(const GLuint*)&media.icons.text_file.handle.id); - glDeleteTextures(1,(const GLuint*)&media.icons.music_file.handle.id); - glDeleteTextures(1,(const GLuint*)&media.icons.font_file.handle.id); - glDeleteTextures(1,(const GLuint*)&media.icons.img_file.handle.id); - glDeleteTextures(1,(const GLuint*)&media.icons.movie_file.handle.id); - - file_browser_free(&browser); - nk_font_atlas_clear(&atlas); - nk_free(&ctx); - device_shutdown(&device); - glfwTerminate(); - return 0; -} - - diff --git a/deps/nuklear/example/icon/checked.png b/deps/nuklear/example/icon/checked.png deleted file mode 100644 index e4e05b29..00000000 Binary files a/deps/nuklear/example/icon/checked.png and /dev/null differ diff --git a/deps/nuklear/example/icon/cloud.png b/deps/nuklear/example/icon/cloud.png deleted file mode 100644 index ecc5791e..00000000 Binary files a/deps/nuklear/example/icon/cloud.png and /dev/null differ diff --git a/deps/nuklear/example/icon/computer.png b/deps/nuklear/example/icon/computer.png deleted file mode 100644 index 29db8fc8..00000000 Binary files a/deps/nuklear/example/icon/computer.png and /dev/null differ diff --git a/deps/nuklear/example/icon/copy.png b/deps/nuklear/example/icon/copy.png deleted file mode 100644 index 0a6e979b..00000000 Binary files a/deps/nuklear/example/icon/copy.png and /dev/null differ diff --git a/deps/nuklear/example/icon/default.png b/deps/nuklear/example/icon/default.png deleted file mode 100644 index c11145a0..00000000 Binary files a/deps/nuklear/example/icon/default.png and /dev/null differ diff --git a/deps/nuklear/example/icon/delete.png b/deps/nuklear/example/icon/delete.png deleted file mode 100644 index 7bc6ddeb..00000000 Binary files a/deps/nuklear/example/icon/delete.png and /dev/null differ diff --git a/deps/nuklear/example/icon/desktop.png b/deps/nuklear/example/icon/desktop.png deleted file mode 100644 index b4abcfd7..00000000 Binary files a/deps/nuklear/example/icon/desktop.png and /dev/null differ diff --git a/deps/nuklear/example/icon/directory.png b/deps/nuklear/example/icon/directory.png deleted file mode 100644 index 4c73d37d..00000000 Binary files a/deps/nuklear/example/icon/directory.png and /dev/null differ diff --git a/deps/nuklear/example/icon/edit.png b/deps/nuklear/example/icon/edit.png deleted file mode 100644 index 62ce0b4d..00000000 Binary files a/deps/nuklear/example/icon/edit.png and /dev/null differ diff --git a/deps/nuklear/example/icon/export.png b/deps/nuklear/example/icon/export.png deleted file mode 100644 index ff6b5aa4..00000000 Binary files a/deps/nuklear/example/icon/export.png and /dev/null differ diff --git a/deps/nuklear/example/icon/font.png b/deps/nuklear/example/icon/font.png deleted file mode 100644 index 918e9bfe..00000000 Binary files a/deps/nuklear/example/icon/font.png and /dev/null differ diff --git a/deps/nuklear/example/icon/home.png b/deps/nuklear/example/icon/home.png deleted file mode 100644 index 85606267..00000000 Binary files a/deps/nuklear/example/icon/home.png and /dev/null differ diff --git a/deps/nuklear/example/icon/img.png b/deps/nuklear/example/icon/img.png deleted file mode 100644 index 19859572..00000000 Binary files a/deps/nuklear/example/icon/img.png and /dev/null differ diff --git a/deps/nuklear/example/icon/movie.png b/deps/nuklear/example/icon/movie.png deleted file mode 100644 index 5227883e..00000000 Binary files a/deps/nuklear/example/icon/movie.png and /dev/null differ diff --git a/deps/nuklear/example/icon/music.png b/deps/nuklear/example/icon/music.png deleted file mode 100644 index 0f1415c8..00000000 Binary files a/deps/nuklear/example/icon/music.png and /dev/null differ diff --git a/deps/nuklear/example/icon/next.png b/deps/nuklear/example/icon/next.png deleted file mode 100644 index af0b98dd..00000000 Binary files a/deps/nuklear/example/icon/next.png and /dev/null differ diff --git a/deps/nuklear/example/icon/pause.png b/deps/nuklear/example/icon/pause.png deleted file mode 100644 index 7d6367e1..00000000 Binary files a/deps/nuklear/example/icon/pause.png and /dev/null differ diff --git a/deps/nuklear/example/icon/pen.png b/deps/nuklear/example/icon/pen.png deleted file mode 100644 index 10c851c1..00000000 Binary files a/deps/nuklear/example/icon/pen.png and /dev/null differ diff --git a/deps/nuklear/example/icon/phone.png b/deps/nuklear/example/icon/phone.png deleted file mode 100644 index 5e6f6133..00000000 Binary files a/deps/nuklear/example/icon/phone.png and /dev/null differ diff --git a/deps/nuklear/example/icon/plane.png b/deps/nuklear/example/icon/plane.png deleted file mode 100644 index 3a984895..00000000 Binary files a/deps/nuklear/example/icon/plane.png and /dev/null differ diff --git a/deps/nuklear/example/icon/play.png b/deps/nuklear/example/icon/play.png deleted file mode 100644 index 9c9e8f0a..00000000 Binary files a/deps/nuklear/example/icon/play.png and /dev/null differ diff --git a/deps/nuklear/example/icon/prev.png b/deps/nuklear/example/icon/prev.png deleted file mode 100644 index 0eecc2e0..00000000 Binary files a/deps/nuklear/example/icon/prev.png and /dev/null differ diff --git a/deps/nuklear/example/icon/rocket.png b/deps/nuklear/example/icon/rocket.png deleted file mode 100644 index ea8e187c..00000000 Binary files a/deps/nuklear/example/icon/rocket.png and /dev/null differ diff --git a/deps/nuklear/example/icon/settings.png b/deps/nuklear/example/icon/settings.png deleted file mode 100644 index e6e13f85..00000000 Binary files a/deps/nuklear/example/icon/settings.png and /dev/null differ diff --git a/deps/nuklear/example/icon/stop.png b/deps/nuklear/example/icon/stop.png deleted file mode 100644 index 6742baf9..00000000 Binary files a/deps/nuklear/example/icon/stop.png and /dev/null differ diff --git a/deps/nuklear/example/icon/text.png b/deps/nuklear/example/icon/text.png deleted file mode 100644 index 136e534a..00000000 Binary files a/deps/nuklear/example/icon/text.png and /dev/null differ diff --git a/deps/nuklear/example/icon/tools.png b/deps/nuklear/example/icon/tools.png deleted file mode 100644 index 412ff853..00000000 Binary files a/deps/nuklear/example/icon/tools.png and /dev/null differ diff --git a/deps/nuklear/example/icon/unchecked.png b/deps/nuklear/example/icon/unchecked.png deleted file mode 100644 index fca94d2c..00000000 Binary files a/deps/nuklear/example/icon/unchecked.png and /dev/null differ diff --git a/deps/nuklear/example/icon/volume.png b/deps/nuklear/example/icon/volume.png deleted file mode 100644 index 8e86fa99..00000000 Binary files a/deps/nuklear/example/icon/volume.png and /dev/null differ diff --git a/deps/nuklear/example/icon/wifi.png b/deps/nuklear/example/icon/wifi.png deleted file mode 100644 index 270d55d7..00000000 Binary files a/deps/nuklear/example/icon/wifi.png and /dev/null differ diff --git a/deps/nuklear/example/images/image1.png b/deps/nuklear/example/images/image1.png deleted file mode 100644 index 66a2b633..00000000 Binary files a/deps/nuklear/example/images/image1.png and /dev/null differ diff --git a/deps/nuklear/example/images/image2.png b/deps/nuklear/example/images/image2.png deleted file mode 100644 index 4acafe53..00000000 Binary files a/deps/nuklear/example/images/image2.png and /dev/null differ diff --git a/deps/nuklear/example/images/image3.png b/deps/nuklear/example/images/image3.png deleted file mode 100644 index 4dfe664e..00000000 Binary files a/deps/nuklear/example/images/image3.png and /dev/null differ diff --git a/deps/nuklear/example/images/image4.png b/deps/nuklear/example/images/image4.png deleted file mode 100644 index d2f16d01..00000000 Binary files a/deps/nuklear/example/images/image4.png and /dev/null differ diff --git a/deps/nuklear/example/images/image5.png b/deps/nuklear/example/images/image5.png deleted file mode 100644 index 852fd70f..00000000 Binary files a/deps/nuklear/example/images/image5.png and /dev/null differ diff --git a/deps/nuklear/example/images/image6.png b/deps/nuklear/example/images/image6.png deleted file mode 100644 index 0e261cb5..00000000 Binary files a/deps/nuklear/example/images/image6.png and /dev/null differ diff --git a/deps/nuklear/example/images/image7.png b/deps/nuklear/example/images/image7.png deleted file mode 100644 index f61325bd..00000000 Binary files a/deps/nuklear/example/images/image7.png and /dev/null differ diff --git a/deps/nuklear/example/images/image8.png b/deps/nuklear/example/images/image8.png deleted file mode 100644 index 6b27cb8d..00000000 Binary files a/deps/nuklear/example/images/image8.png and /dev/null differ diff --git a/deps/nuklear/example/images/image9.png b/deps/nuklear/example/images/image9.png deleted file mode 100644 index 516929ea..00000000 Binary files a/deps/nuklear/example/images/image9.png and /dev/null differ diff --git a/deps/nuklear/example/skinning.c b/deps/nuklear/example/skinning.c deleted file mode 100644 index 4634b090..00000000 --- a/deps/nuklear/example/skinning.c +++ /dev/null @@ -1,825 +0,0 @@ -/* nuklear - v1.05 - public domain */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define NK_INCLUDE_FIXED_TYPES -#define NK_INCLUDE_STANDARD_IO -#define NK_INCLUDE_DEFAULT_ALLOCATOR -#define NK_INCLUDE_VERTEX_BUFFER_OUTPUT -#define NK_INCLUDE_FONT_BAKING -#define NK_INCLUDE_DEFAULT_FONT -#define NK_IMPLEMENTATION -#include "../nuklear.h" - -#define STB_IMAGE_IMPLEMENTATION -#include "stb_image.h" - -/* macros */ -#define WINDOW_WIDTH 1200 -#define WINDOW_HEIGHT 800 - -#define MAX_VERTEX_MEMORY 512 * 1024 -#define MAX_ELEMENT_MEMORY 128 * 1024 - -#define UNUSED(a) (void)a -#define MIN(a,b) ((a) < (b) ? (a) : (b)) -#define MAX(a,b) ((a) < (b) ? (b) : (a)) -#define LEN(a) (sizeof(a)/sizeof(a)[0]) - -#ifdef __APPLE__ - #define NK_SHADER_VERSION "#version 150\n" -#else - #define NK_SHADER_VERSION "#version 300 es\n" -#endif - -struct media { - GLint skin; - struct nk_image menu; - struct nk_image check; - struct nk_image check_cursor; - struct nk_image option; - struct nk_image option_cursor; - struct nk_image header; - struct nk_image window; - struct nk_image scrollbar_inc_button; - struct nk_image scrollbar_inc_button_hover; - struct nk_image scrollbar_dec_button; - struct nk_image scrollbar_dec_button_hover; - struct nk_image button; - struct nk_image button_hover; - struct nk_image button_active; - struct nk_image tab_minimize; - struct nk_image tab_maximize; - struct nk_image slider; - struct nk_image slider_hover; - struct nk_image slider_active; -}; - - -/* =============================================================== - * - * DEVICE - * - * ===============================================================*/ -struct nk_glfw_vertex { - float position[2]; - float uv[2]; - nk_byte col[4]; -}; - -struct device { - struct nk_buffer cmds; - struct nk_draw_null_texture null; - GLuint vbo, vao, ebo; - GLuint prog; - GLuint vert_shdr; - GLuint frag_shdr; - GLint attrib_pos; - GLint attrib_uv; - GLint attrib_col; - GLint uniform_tex; - GLint uniform_proj; - GLuint font_tex; -}; - -static void -die(const char *fmt, ...) -{ - va_list ap; - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fputs("\n", stderr); - exit(EXIT_FAILURE); -} - -static GLuint -image_load(const char *filename) -{ - int x,y,n; - GLuint tex; - unsigned char *data = stbi_load(filename, &x, &y, &n, 0); - if (!data) die("failed to load image: %s", filename); - - glGenTextures(1, &tex); - glBindTexture(GL_TEXTURE_2D, tex); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR_MIPMAP_NEAREST); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, x, y, 0, GL_RGBA, GL_UNSIGNED_BYTE, data); - glGenerateMipmap(GL_TEXTURE_2D); - stbi_image_free(data); - return tex; -} - -static void -device_init(struct device *dev) -{ - GLint status; - static const GLchar *vertex_shader = - NK_SHADER_VERSION - "uniform mat4 ProjMtx;\n" - "in vec2 Position;\n" - "in vec2 TexCoord;\n" - "in vec4 Color;\n" - "out vec2 Frag_UV;\n" - "out vec4 Frag_Color;\n" - "void main() {\n" - " Frag_UV = TexCoord;\n" - " Frag_Color = Color;\n" - " gl_Position = ProjMtx * vec4(Position.xy, 0, 1);\n" - "}\n"; - static const GLchar *fragment_shader = - NK_SHADER_VERSION - "precision mediump float;\n" - "uniform sampler2D Texture;\n" - "in vec2 Frag_UV;\n" - "in vec4 Frag_Color;\n" - "out vec4 Out_Color;\n" - "void main(){\n" - " Out_Color = Frag_Color * texture(Texture, Frag_UV.st);\n" - "}\n"; - - nk_buffer_init_default(&dev->cmds); - dev->prog = glCreateProgram(); - dev->vert_shdr = glCreateShader(GL_VERTEX_SHADER); - dev->frag_shdr = glCreateShader(GL_FRAGMENT_SHADER); - glShaderSource(dev->vert_shdr, 1, &vertex_shader, 0); - glShaderSource(dev->frag_shdr, 1, &fragment_shader, 0); - glCompileShader(dev->vert_shdr); - glCompileShader(dev->frag_shdr); - glGetShaderiv(dev->vert_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glGetShaderiv(dev->frag_shdr, GL_COMPILE_STATUS, &status); - assert(status == GL_TRUE); - glAttachShader(dev->prog, dev->vert_shdr); - glAttachShader(dev->prog, dev->frag_shdr); - glLinkProgram(dev->prog); - glGetProgramiv(dev->prog, GL_LINK_STATUS, &status); - assert(status == GL_TRUE); - - dev->uniform_tex = glGetUniformLocation(dev->prog, "Texture"); - dev->uniform_proj = glGetUniformLocation(dev->prog, "ProjMtx"); - dev->attrib_pos = glGetAttribLocation(dev->prog, "Position"); - dev->attrib_uv = glGetAttribLocation(dev->prog, "TexCoord"); - dev->attrib_col = glGetAttribLocation(dev->prog, "Color"); - - { - /* buffer setup */ - GLsizei vs = sizeof(struct nk_glfw_vertex); - size_t vp = offsetof(struct nk_glfw_vertex, position); - size_t vt = offsetof(struct nk_glfw_vertex, uv); - size_t vc = offsetof(struct nk_glfw_vertex, col); - - glGenBuffers(1, &dev->vbo); - glGenBuffers(1, &dev->ebo); - glGenVertexArrays(1, &dev->vao); - - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glEnableVertexAttribArray((GLuint)dev->attrib_pos); - glEnableVertexAttribArray((GLuint)dev->attrib_uv); - glEnableVertexAttribArray((GLuint)dev->attrib_col); - - glVertexAttribPointer((GLuint)dev->attrib_pos, 2, GL_FLOAT, GL_FALSE, vs, (void*)vp); - glVertexAttribPointer((GLuint)dev->attrib_uv, 2, GL_FLOAT, GL_FALSE, vs, (void*)vt); - glVertexAttribPointer((GLuint)dev->attrib_col, 4, GL_UNSIGNED_BYTE, GL_TRUE, vs, (void*)vc); - } - - glBindTexture(GL_TEXTURE_2D, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); -} - -static void -device_upload_atlas(struct device *dev, const void *image, int width, int height) -{ - glGenTextures(1, &dev->font_tex); - glBindTexture(GL_TEXTURE_2D, dev->font_tex); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, (GLsizei)width, (GLsizei)height, 0, - GL_RGBA, GL_UNSIGNED_BYTE, image); -} - -static void -device_shutdown(struct device *dev) -{ - glDetachShader(dev->prog, dev->vert_shdr); - glDetachShader(dev->prog, dev->frag_shdr); - glDeleteShader(dev->vert_shdr); - glDeleteShader(dev->frag_shdr); - glDeleteProgram(dev->prog); - glDeleteTextures(1, &dev->font_tex); - glDeleteBuffers(1, &dev->vbo); - glDeleteBuffers(1, &dev->ebo); - nk_buffer_free(&dev->cmds); -} - -static void -device_draw(struct device *dev, struct nk_context *ctx, int width, int height, - struct nk_vec2 scale, enum nk_anti_aliasing AA) -{ - GLfloat ortho[4][4] = { - {2.0f, 0.0f, 0.0f, 0.0f}, - {0.0f,-2.0f, 0.0f, 0.0f}, - {0.0f, 0.0f,-1.0f, 0.0f}, - {-1.0f,1.0f, 0.0f, 1.0f}, - }; - ortho[0][0] /= (GLfloat)width; - ortho[1][1] /= (GLfloat)height; - - /* setup global state */ - glEnable(GL_BLEND); - glBlendEquation(GL_FUNC_ADD); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glEnable(GL_SCISSOR_TEST); - glActiveTexture(GL_TEXTURE0); - - /* setup program */ - glUseProgram(dev->prog); - glUniform1i(dev->uniform_tex, 0); - glUniformMatrix4fv(dev->uniform_proj, 1, GL_FALSE, &ortho[0][0]); - { - /* convert from command queue into draw list and draw to screen */ - const struct nk_draw_command *cmd; - void *vertices, *elements; - const nk_draw_index *offset = NULL; - - /* allocate vertex and element buffer */ - glBindVertexArray(dev->vao); - glBindBuffer(GL_ARRAY_BUFFER, dev->vbo); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, dev->ebo); - - glBufferData(GL_ARRAY_BUFFER, MAX_VERTEX_MEMORY, NULL, GL_STREAM_DRAW); - glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_ELEMENT_MEMORY, NULL, GL_STREAM_DRAW); - - /* load draw vertices & elements directly into vertex + element buffer */ - vertices = glMapBuffer(GL_ARRAY_BUFFER, GL_WRITE_ONLY); - elements = glMapBuffer(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY); - { - /* fill convert configuration */ - struct nk_convert_config config; - static const struct nk_draw_vertex_layout_element vertex_layout[] = { - {NK_VERTEX_POSITION, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, position)}, - {NK_VERTEX_TEXCOORD, NK_FORMAT_FLOAT, NK_OFFSETOF(struct nk_glfw_vertex, uv)}, - {NK_VERTEX_COLOR, NK_FORMAT_R8G8B8A8, NK_OFFSETOF(struct nk_glfw_vertex, col)}, - {NK_VERTEX_LAYOUT_END} - }; - NK_MEMSET(&config, 0, sizeof(config)); - config.vertex_layout = vertex_layout; - config.vertex_size = sizeof(struct nk_glfw_vertex); - config.vertex_alignment = NK_ALIGNOF(struct nk_glfw_vertex); - config.null = dev->null; - config.circle_segment_count = 22; - config.curve_segment_count = 22; - config.arc_segment_count = 22; - config.global_alpha = 1.0f; - config.shape_AA = AA; - config.line_AA = AA; - - /* setup buffers to load vertices and elements */ - {struct nk_buffer vbuf, ebuf; - nk_buffer_init_fixed(&vbuf, vertices, MAX_VERTEX_MEMORY); - nk_buffer_init_fixed(&ebuf, elements, MAX_ELEMENT_MEMORY); - nk_convert(ctx, &dev->cmds, &vbuf, &ebuf, &config);} - } - glUnmapBuffer(GL_ARRAY_BUFFER); - glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); - - /* iterate over and execute each draw command */ - nk_draw_foreach(cmd, ctx, &dev->cmds) - { - if (!cmd->elem_count) continue; - glBindTexture(GL_TEXTURE_2D, (GLuint)cmd->texture.id); - glScissor( - (GLint)(cmd->clip_rect.x * scale.x), - (GLint)((height - (GLint)(cmd->clip_rect.y + cmd->clip_rect.h)) * scale.y), - (GLint)(cmd->clip_rect.w * scale.x), - (GLint)(cmd->clip_rect.h * scale.y)); - glDrawElements(GL_TRIANGLES, (GLsizei)cmd->elem_count, GL_UNSIGNED_SHORT, offset); - offset += cmd->elem_count; - } - nk_clear(ctx); - } - - /* default OpenGL state */ - glUseProgram(0); - glBindBuffer(GL_ARRAY_BUFFER, 0); - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindVertexArray(0); - glDisable(GL_BLEND); - glDisable(GL_SCISSOR_TEST); -} - -/* glfw callbacks (I don't know if there is a easier way to access text and scroll )*/ -static void error_callback(int e, const char *d){printf("Error %d: %s\n", e, d);} -static void text_input(GLFWwindow *win, unsigned int codepoint) -{nk_input_unicode((struct nk_context*)glfwGetWindowUserPointer(win), codepoint);} -static void scroll_input(GLFWwindow *win, double _, double yoff) -{UNUSED(_);nk_input_scroll((struct nk_context*)glfwGetWindowUserPointer(win), (float)yoff);} - -int main(int argc, char *argv[]) -{ - /* Platform */ - static GLFWwindow *win; - int width = 0, height = 0; - int display_width=0, display_height=0; - - /* GUI */ - struct device device; - struct nk_font_atlas atlas; - struct media media; - struct nk_context ctx; - struct nk_font *font; - - /* GLFW */ - glfwSetErrorCallback(error_callback); - if (!glfwInit()) { - fprintf(stdout, "[GFLW] failed to init!\n"); - exit(1); - } - glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); - glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); - glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); -#ifdef __APPLE__ - glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); -#endif - win = glfwCreateWindow(WINDOW_WIDTH, WINDOW_HEIGHT, "Demo", NULL, NULL); - glfwMakeContextCurrent(win); - glfwSetWindowUserPointer(win, &ctx); - glfwSetCharCallback(win, text_input); - glfwSetScrollCallback(win, scroll_input); - glfwGetWindowSize(win, &width, &height); - glfwGetFramebufferSize(win, &display_width, &display_height); - - /* OpenGL */ - glViewport(0, 0, WINDOW_WIDTH, WINDOW_HEIGHT); - glewExperimental = 1; - if (glewInit() != GLEW_OK) { - fprintf(stderr, "Failed to setup GLEW\n"); - exit(1); - } - - /* GUI */ - {device_init(&device); - {const void *image; int w, h; - const char *font_path = (argc > 1) ? argv[1]: 0; - nk_font_atlas_init_default(&atlas); - nk_font_atlas_begin(&atlas); - if (font_path) font = nk_font_atlas_add_from_file(&atlas, font_path, 13.0f, NULL); - else font = nk_font_atlas_add_default(&atlas, 13.0f, NULL); - image = nk_font_atlas_bake(&atlas, &w, &h, NK_FONT_ATLAS_RGBA32); - device_upload_atlas(&device, image, w, h); - nk_font_atlas_end(&atlas, nk_handle_id((int)device.font_tex), &device.null);} - nk_init_default(&ctx, &font->handle);} - - { /* skin */ - glEnable(GL_TEXTURE_2D); - media.skin = image_load("../skins/gwen.png"); - media.check = nk_subimage_id(media.skin, 512,512, nk_rect(464,32,15,15)); - media.check_cursor = nk_subimage_id(media.skin, 512,512, nk_rect(450,34,11,11)); - media.option = nk_subimage_id(media.skin, 512,512, nk_rect(464,64,15,15)); - media.option_cursor = nk_subimage_id(media.skin, 512,512, nk_rect(451,67,9,9)); - media.header = nk_subimage_id(media.skin, 512,512, nk_rect(128,0,127,24)); - media.window = nk_subimage_id(media.skin, 512,512, nk_rect(128,23,127,104)); - media.scrollbar_inc_button = nk_subimage_id(media.skin, 512,512, nk_rect(464,256,15,15)); - media.scrollbar_inc_button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(464,320,15,15)); - media.scrollbar_dec_button = nk_subimage_id(media.skin, 512,512, nk_rect(464,224,15,15)); - media.scrollbar_dec_button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(464,288,15,15)); - media.button = nk_subimage_id(media.skin, 512,512, nk_rect(384,336,127,31)); - media.button_hover = nk_subimage_id(media.skin, 512,512, nk_rect(384,368,127,31)); - media.button_active = nk_subimage_id(media.skin, 512,512, nk_rect(384,400,127,31)); - media.tab_minimize = nk_subimage_id(media.skin, 512,512, nk_rect(451, 99, 9, 9)); - media.tab_maximize = nk_subimage_id(media.skin, 512,512, nk_rect(467,99,9,9)); - media.slider = nk_subimage_id(media.skin, 512,512, nk_rect(418,33,11,14)); - media.slider_hover = nk_subimage_id(media.skin, 512,512, nk_rect(418,49,11,14)); - media.slider_active = nk_subimage_id(media.skin, 512,512, nk_rect(418,64,11,14)); - - /* window */ - ctx.style.window.background = nk_rgb(204,204,204); - ctx.style.window.fixed_background = nk_style_item_image(media.window); - ctx.style.window.border_color = nk_rgb(67,67,67); - ctx.style.window.combo_border_color = nk_rgb(67,67,67); - ctx.style.window.contextual_border_color = nk_rgb(67,67,67); - ctx.style.window.menu_border_color = nk_rgb(67,67,67); - ctx.style.window.group_border_color = nk_rgb(67,67,67); - ctx.style.window.tooltip_border_color = nk_rgb(67,67,67); - ctx.style.window.scrollbar_size = nk_vec2(16,16); - ctx.style.window.border_color = nk_rgba(0,0,0,0); - ctx.style.window.padding = nk_vec2(8,4); - ctx.style.window.border = 3; - - /* window header */ - ctx.style.window.header; - ctx.style.window.header.normal = nk_style_item_image(media.header); - ctx.style.window.header.hover = nk_style_item_image(media.header); - ctx.style.window.header.active = nk_style_item_image(media.header); - ctx.style.window.header.label_normal = nk_rgb(95,95,95); - ctx.style.window.header.label_hover = nk_rgb(95,95,95); - ctx.style.window.header.label_active = nk_rgb(95,95,95); - - /* scrollbar */ - ctx.style.scrollv.normal = nk_style_item_color(nk_rgb(184,184,184)); - ctx.style.scrollv.hover = nk_style_item_color(nk_rgb(184,184,184)); - ctx.style.scrollv.active = nk_style_item_color(nk_rgb(184,184,184)); - ctx.style.scrollv.cursor_normal = nk_style_item_color(nk_rgb(220,220,220)); - ctx.style.scrollv.cursor_hover = nk_style_item_color(nk_rgb(235,235,235)); - ctx.style.scrollv.cursor_active = nk_style_item_color(nk_rgb(99,202,255)); - ctx.style.scrollv.dec_symbol = NK_SYMBOL_NONE; - ctx.style.scrollv.inc_symbol = NK_SYMBOL_NONE; - ctx.style.scrollv.show_buttons = nk_true; - ctx.style.scrollv.border_color = nk_rgb(81,81,81); - ctx.style.scrollv.cursor_border_color = nk_rgb(81,81,81); - ctx.style.scrollv.border = 1; - ctx.style.scrollv.rounding = 0; - ctx.style.scrollv.border_cursor = 1; - ctx.style.scrollv.rounding_cursor = 2; - - /* scrollbar buttons */ - ctx.style.scrollv.inc_button.normal = nk_style_item_image(media.scrollbar_inc_button); - ctx.style.scrollv.inc_button.hover = nk_style_item_image(media.scrollbar_inc_button_hover); - ctx.style.scrollv.inc_button.active = nk_style_item_image(media.scrollbar_inc_button_hover); - ctx.style.scrollv.inc_button.border_color = nk_rgba(0,0,0,0); - ctx.style.scrollv.inc_button.text_background = nk_rgba(0,0,0,0); - ctx.style.scrollv.inc_button.text_normal = nk_rgba(0,0,0,0); - ctx.style.scrollv.inc_button.text_hover = nk_rgba(0,0,0,0); - ctx.style.scrollv.inc_button.text_active = nk_rgba(0,0,0,0); - ctx.style.scrollv.inc_button.border = 0.0f; - - ctx.style.scrollv.dec_button.normal = nk_style_item_image(media.scrollbar_dec_button); - ctx.style.scrollv.dec_button.hover = nk_style_item_image(media.scrollbar_dec_button_hover); - ctx.style.scrollv.dec_button.active = nk_style_item_image(media.scrollbar_dec_button_hover); - ctx.style.scrollv.dec_button.border_color = nk_rgba(0,0,0,0); - ctx.style.scrollv.dec_button.text_background = nk_rgba(0,0,0,0); - ctx.style.scrollv.dec_button.text_normal = nk_rgba(0,0,0,0); - ctx.style.scrollv.dec_button.text_hover = nk_rgba(0,0,0,0); - ctx.style.scrollv.dec_button.text_active = nk_rgba(0,0,0,0); - ctx.style.scrollv.dec_button.border = 0.0f; - - /* checkbox toggle */ - {struct nk_style_toggle *toggle; - toggle = &ctx.style.checkbox; - toggle->normal = nk_style_item_image(media.check); - toggle->hover = nk_style_item_image(media.check); - toggle->active = nk_style_item_image(media.check); - toggle->cursor_normal = nk_style_item_image(media.check_cursor); - toggle->cursor_hover = nk_style_item_image(media.check_cursor); - toggle->text_normal = nk_rgb(95,95,95); - toggle->text_hover = nk_rgb(95,95,95); - toggle->text_active = nk_rgb(95,95,95);} - - /* option toggle */ - {struct nk_style_toggle *toggle; - toggle = &ctx.style.option; - toggle->normal = nk_style_item_image(media.option); - toggle->hover = nk_style_item_image(media.option); - toggle->active = nk_style_item_image(media.option); - toggle->cursor_normal = nk_style_item_image(media.option_cursor); - toggle->cursor_hover = nk_style_item_image(media.option_cursor); - toggle->text_normal = nk_rgb(95,95,95); - toggle->text_hover = nk_rgb(95,95,95); - toggle->text_active = nk_rgb(95,95,95);} - - /* default button */ - ctx.style.button.normal = nk_style_item_image(media.button); - ctx.style.button.hover = nk_style_item_image(media.button_hover); - ctx.style.button.active = nk_style_item_image(media.button_active); - ctx.style.button.border_color = nk_rgba(0,0,0,0); - ctx.style.button.text_background = nk_rgba(0,0,0,0); - ctx.style.button.text_normal = nk_rgb(95,95,95); - ctx.style.button.text_hover = nk_rgb(95,95,95); - ctx.style.button.text_active = nk_rgb(95,95,95); - - /* default text */ - ctx.style.text.color = nk_rgb(95,95,95); - - /* contextual button */ - ctx.style.contextual_button.normal = nk_style_item_color(nk_rgb(206,206,206)); - ctx.style.contextual_button.hover = nk_style_item_color(nk_rgb(229,229,229)); - ctx.style.contextual_button.active = nk_style_item_color(nk_rgb(99,202,255)); - ctx.style.contextual_button.border_color = nk_rgba(0,0,0,0); - ctx.style.contextual_button.text_background = nk_rgba(0,0,0,0); - ctx.style.contextual_button.text_normal = nk_rgb(95,95,95); - ctx.style.contextual_button.text_hover = nk_rgb(95,95,95); - ctx.style.contextual_button.text_active = nk_rgb(95,95,95); - - /* menu button */ - ctx.style.menu_button.normal = nk_style_item_color(nk_rgb(206,206,206)); - ctx.style.menu_button.hover = nk_style_item_color(nk_rgb(229,229,229)); - ctx.style.menu_button.active = nk_style_item_color(nk_rgb(99,202,255)); - ctx.style.menu_button.border_color = nk_rgba(0,0,0,0); - ctx.style.menu_button.text_background = nk_rgba(0,0,0,0); - ctx.style.menu_button.text_normal = nk_rgb(95,95,95); - ctx.style.menu_button.text_hover = nk_rgb(95,95,95); - ctx.style.menu_button.text_active = nk_rgb(95,95,95); - - /* tree */ - ctx.style.tab.text = nk_rgb(95,95,95); - ctx.style.tab.tab_minimize_button.normal = nk_style_item_image(media.tab_minimize); - ctx.style.tab.tab_minimize_button.hover = nk_style_item_image(media.tab_minimize); - ctx.style.tab.tab_minimize_button.active = nk_style_item_image(media.tab_minimize); - ctx.style.tab.tab_minimize_button.text_background = nk_rgba(0,0,0,0); - ctx.style.tab.tab_minimize_button.text_normal = nk_rgba(0,0,0,0); - ctx.style.tab.tab_minimize_button.text_hover = nk_rgba(0,0,0,0); - ctx.style.tab.tab_minimize_button.text_active = nk_rgba(0,0,0,0); - - ctx.style.tab.tab_maximize_button.normal = nk_style_item_image(media.tab_maximize); - ctx.style.tab.tab_maximize_button.hover = nk_style_item_image(media.tab_maximize); - ctx.style.tab.tab_maximize_button.active = nk_style_item_image(media.tab_maximize); - ctx.style.tab.tab_maximize_button.text_background = nk_rgba(0,0,0,0); - ctx.style.tab.tab_maximize_button.text_normal = nk_rgba(0,0,0,0); - ctx.style.tab.tab_maximize_button.text_hover = nk_rgba(0,0,0,0); - ctx.style.tab.tab_maximize_button.text_active = nk_rgba(0,0,0,0); - - ctx.style.tab.node_minimize_button.normal = nk_style_item_image(media.tab_minimize); - ctx.style.tab.node_minimize_button.hover = nk_style_item_image(media.tab_minimize); - ctx.style.tab.node_minimize_button.active = nk_style_item_image(media.tab_minimize); - ctx.style.tab.node_minimize_button.text_background = nk_rgba(0,0,0,0); - ctx.style.tab.node_minimize_button.text_normal = nk_rgba(0,0,0,0); - ctx.style.tab.node_minimize_button.text_hover = nk_rgba(0,0,0,0); - ctx.style.tab.node_minimize_button.text_active = nk_rgba(0,0,0,0); - - ctx.style.tab.node_maximize_button.normal = nk_style_item_image(media.tab_maximize); - ctx.style.tab.node_maximize_button.hover = nk_style_item_image(media.tab_maximize); - ctx.style.tab.node_maximize_button.active = nk_style_item_image(media.tab_maximize); - ctx.style.tab.node_maximize_button.text_background = nk_rgba(0,0,0,0); - ctx.style.tab.node_maximize_button.text_normal = nk_rgba(0,0,0,0); - ctx.style.tab.node_maximize_button.text_hover = nk_rgba(0,0,0,0); - ctx.style.tab.node_maximize_button.text_active = nk_rgba(0,0,0,0); - - /* selectable */ - ctx.style.selectable.normal = nk_style_item_color(nk_rgb(206,206,206)); - ctx.style.selectable.hover = nk_style_item_color(nk_rgb(206,206,206)); - ctx.style.selectable.pressed = nk_style_item_color(nk_rgb(206,206,206)); - ctx.style.selectable.normal_active = nk_style_item_color(nk_rgb(185,205,248)); - ctx.style.selectable.hover_active = nk_style_item_color(nk_rgb(185,205,248)); - ctx.style.selectable.pressed_active = nk_style_item_color(nk_rgb(185,205,248)); - ctx.style.selectable.text_normal = nk_rgb(95,95,95); - ctx.style.selectable.text_hover = nk_rgb(95,95,95); - ctx.style.selectable.text_pressed = nk_rgb(95,95,95); - ctx.style.selectable.text_normal_active = nk_rgb(95,95,95); - ctx.style.selectable.text_hover_active = nk_rgb(95,95,95); - ctx.style.selectable.text_pressed_active = nk_rgb(95,95,95); - - /* slider */ - ctx.style.slider.normal = nk_style_item_hide(); - ctx.style.slider.hover = nk_style_item_hide(); - ctx.style.slider.active = nk_style_item_hide(); - ctx.style.slider.bar_normal = nk_rgb(156,156,156); - ctx.style.slider.bar_hover = nk_rgb(156,156,156); - ctx.style.slider.bar_active = nk_rgb(156,156,156); - ctx.style.slider.bar_filled = nk_rgb(156,156,156); - ctx.style.slider.cursor_normal = nk_style_item_image(media.slider); - ctx.style.slider.cursor_hover = nk_style_item_image(media.slider_hover); - ctx.style.slider.cursor_active = nk_style_item_image(media.slider_active); - ctx.style.slider.cursor_size = nk_vec2(16.5f,21); - ctx.style.slider.bar_height = 1; - - /* progressbar */ - ctx.style.progress.normal = nk_style_item_color(nk_rgb(231,231,231)); - ctx.style.progress.hover = nk_style_item_color(nk_rgb(231,231,231)); - ctx.style.progress.active = nk_style_item_color(nk_rgb(231,231,231)); - ctx.style.progress.cursor_normal = nk_style_item_color(nk_rgb(63,242,93)); - ctx.style.progress.cursor_hover = nk_style_item_color(nk_rgb(63,242,93)); - ctx.style.progress.cursor_active = nk_style_item_color(nk_rgb(63,242,93)); - ctx.style.progress.border_color = nk_rgb(114,116,115); - ctx.style.progress.padding = nk_vec2(0,0); - ctx.style.progress.border = 2; - ctx.style.progress.rounding = 1; - - /* combo */ - ctx.style.combo.normal = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.combo.hover = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.combo.active = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.combo.border_color = nk_rgb(95,95,95); - ctx.style.combo.label_normal = nk_rgb(95,95,95); - ctx.style.combo.label_hover = nk_rgb(95,95,95); - ctx.style.combo.label_active = nk_rgb(95,95,95); - ctx.style.combo.border = 1; - ctx.style.combo.rounding = 1; - - /* combo button */ - ctx.style.combo.button.normal = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.combo.button.hover = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.combo.button.active = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.combo.button.text_background = nk_rgb(216,216,216); - ctx.style.combo.button.text_normal = nk_rgb(95,95,95); - ctx.style.combo.button.text_hover = nk_rgb(95,95,95); - ctx.style.combo.button.text_active = nk_rgb(95,95,95); - - /* property */ - ctx.style.property.normal = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.property.hover = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.property.active = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.property.border_color = nk_rgb(81,81,81); - ctx.style.property.label_normal = nk_rgb(95,95,95); - ctx.style.property.label_hover = nk_rgb(95,95,95); - ctx.style.property.label_active = nk_rgb(95,95,95); - ctx.style.property.sym_left = NK_SYMBOL_TRIANGLE_LEFT; - ctx.style.property.sym_right = NK_SYMBOL_TRIANGLE_RIGHT; - ctx.style.property.rounding = 10; - ctx.style.property.border = 1; - - /* edit */ - ctx.style.edit.normal = nk_style_item_color(nk_rgb(240,240,240)); - ctx.style.edit.hover = nk_style_item_color(nk_rgb(240,240,240)); - ctx.style.edit.active = nk_style_item_color(nk_rgb(240,240,240)); - ctx.style.edit.border_color = nk_rgb(62,62,62); - ctx.style.edit.cursor_normal = nk_rgb(99,202,255); - ctx.style.edit.cursor_hover = nk_rgb(99,202,255); - ctx.style.edit.cursor_text_normal = nk_rgb(95,95,95); - ctx.style.edit.cursor_text_hover = nk_rgb(95,95,95); - ctx.style.edit.text_normal = nk_rgb(95,95,95); - ctx.style.edit.text_hover = nk_rgb(95,95,95); - ctx.style.edit.text_active = nk_rgb(95,95,95); - ctx.style.edit.selected_normal = nk_rgb(99,202,255); - ctx.style.edit.selected_hover = nk_rgb(99,202,255); - ctx.style.edit.selected_text_normal = nk_rgb(95,95,95); - ctx.style.edit.selected_text_hover = nk_rgb(95,95,95); - ctx.style.edit.border = 1; - ctx.style.edit.rounding = 2; - - /* property buttons */ - ctx.style.property.dec_button.normal = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.property.dec_button.hover = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.property.dec_button.active = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.property.dec_button.text_background = nk_rgba(0,0,0,0); - ctx.style.property.dec_button.text_normal = nk_rgb(95,95,95); - ctx.style.property.dec_button.text_hover = nk_rgb(95,95,95); - ctx.style.property.dec_button.text_active = nk_rgb(95,95,95); - ctx.style.property.inc_button = ctx.style.property.dec_button; - - /* property edit */ - ctx.style.property.edit.normal = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.property.edit.hover = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.property.edit.active = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.property.edit.border_color = nk_rgba(0,0,0,0); - ctx.style.property.edit.cursor_normal = nk_rgb(95,95,95); - ctx.style.property.edit.cursor_hover = nk_rgb(95,95,95); - ctx.style.property.edit.cursor_text_normal = nk_rgb(216,216,216); - ctx.style.property.edit.cursor_text_hover = nk_rgb(216,216,216); - ctx.style.property.edit.text_normal = nk_rgb(95,95,95); - ctx.style.property.edit.text_hover = nk_rgb(95,95,95); - ctx.style.property.edit.text_active = nk_rgb(95,95,95); - ctx.style.property.edit.selected_normal = nk_rgb(95,95,95); - ctx.style.property.edit.selected_hover = nk_rgb(95,95,95); - ctx.style.property.edit.selected_text_normal = nk_rgb(216,216,216); - ctx.style.property.edit.selected_text_hover = nk_rgb(216,216,216); - - /* chart */ - ctx.style.chart.background = nk_style_item_color(nk_rgb(216,216,216)); - ctx.style.chart.border_color = nk_rgb(81,81,81); - ctx.style.chart.color = nk_rgb(95,95,95); - ctx.style.chart.selected_color = nk_rgb(255,0,0); - ctx.style.chart.border = 1; - } - - while (!glfwWindowShouldClose(win)) - { - /* High DPI displays */ - struct nk_vec2 scale; - glfwGetWindowSize(win, &width, &height); - glfwGetFramebufferSize(win, &display_width, &display_height); - scale.x = (float)display_width/(float)width; - scale.y = (float)display_height/(float)height; - - /* Input */ - {double x, y; - nk_input_begin(&ctx); - glfwPollEvents(); - nk_input_key(&ctx, NK_KEY_DEL, glfwGetKey(win, GLFW_KEY_DELETE) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_ENTER, glfwGetKey(win, GLFW_KEY_ENTER) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_TAB, glfwGetKey(win, GLFW_KEY_TAB) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_BACKSPACE, glfwGetKey(win, GLFW_KEY_BACKSPACE) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_LEFT, glfwGetKey(win, GLFW_KEY_LEFT) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_RIGHT, glfwGetKey(win, GLFW_KEY_RIGHT) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_UP, glfwGetKey(win, GLFW_KEY_UP) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_DOWN, glfwGetKey(win, GLFW_KEY_DOWN) == GLFW_PRESS); - if (glfwGetKey(win, GLFW_KEY_LEFT_CONTROL) == GLFW_PRESS || - glfwGetKey(win, GLFW_KEY_RIGHT_CONTROL) == GLFW_PRESS) { - nk_input_key(&ctx, NK_KEY_COPY, glfwGetKey(win, GLFW_KEY_C) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_PASTE, glfwGetKey(win, GLFW_KEY_P) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_X) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_CUT, glfwGetKey(win, GLFW_KEY_E) == GLFW_PRESS); - nk_input_key(&ctx, NK_KEY_SHIFT, 1); - } else { - nk_input_key(&ctx, NK_KEY_COPY, 0); - nk_input_key(&ctx, NK_KEY_PASTE, 0); - nk_input_key(&ctx, NK_KEY_CUT, 0); - nk_input_key(&ctx, NK_KEY_SHIFT, 0); - } - glfwGetCursorPos(win, &x, &y); - nk_input_motion(&ctx, (int)x, (int)y); - nk_input_button(&ctx, NK_BUTTON_LEFT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS); - nk_input_button(&ctx, NK_BUTTON_MIDDLE, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS); - nk_input_button(&ctx, NK_BUTTON_RIGHT, (int)x, (int)y, glfwGetMouseButton(win, GLFW_MOUSE_BUTTON_RIGHT) == GLFW_PRESS); - nk_input_end(&ctx);} - - /* GUI */ - {struct nk_panel layout, tab; - if (nk_begin(&ctx, "Demo", nk_rect(50, 50, 300, 400), - NK_WINDOW_BORDER|NK_WINDOW_MOVABLE|NK_WINDOW_TITLE)) - { - int i; - float id; - static int slider = 10; - static int field_len; - static nk_size prog_value = 60; - static int current_weapon = 0; - static char field_buffer[64]; - static float pos; - static const char *weapons[] = {"Fist","Pistol","Shotgun","Plasma","BFG"}; - const float step = (2*3.141592654f) / 32; - - nk_layout_row_static(&ctx, 30, 120, 1); - if (nk_button_label(&ctx, "button")) - fprintf(stdout, "button pressed\n"); - - nk_layout_row_dynamic(&ctx, 20, 1); - nk_label(&ctx, "Label", NK_TEXT_LEFT); - nk_layout_row_dynamic(&ctx, 30, 2); - nk_check_label(&ctx, "inactive", 0); - nk_check_label(&ctx, "active", 1); - nk_option_label(&ctx, "active", 1); - nk_option_label(&ctx, "inactive", 0); - - nk_layout_row_dynamic(&ctx, 30, 1); - nk_slider_int(&ctx, 0, &slider, 16, 1); - nk_layout_row_dynamic(&ctx, 20, 1); - nk_progress(&ctx, &prog_value, 100, NK_MODIFIABLE); - - nk_layout_row_dynamic(&ctx, 25, 1); - nk_edit_string(&ctx, NK_EDIT_FIELD, field_buffer, &field_len, 64, nk_filter_default); - nk_property_float(&ctx, "#X:", -1024.0f, &pos, 1024.0f, 1, 1); - current_weapon = nk_combo(&ctx, weapons, LEN(weapons), current_weapon, 25, nk_vec2(nk_widget_width(&ctx),200)); - - nk_layout_row_dynamic(&ctx, 100, 1); - if (nk_chart_begin_colored(&ctx, NK_CHART_LINES, nk_rgb(255,0,0), nk_rgb(150,0,0), 32, 0.0f, 1.0f)) { - nk_chart_add_slot_colored(&ctx, NK_CHART_LINES, nk_rgb(0,0,255), nk_rgb(0,0,150),32, -1.0f, 1.0f); - nk_chart_add_slot_colored(&ctx, NK_CHART_LINES, nk_rgb(0,255,0), nk_rgb(0,150,0), 32, -1.0f, 1.0f); - for (id = 0, i = 0; i < 32; ++i) { - nk_chart_push_slot(&ctx, (float)fabs(sin(id)), 0); - nk_chart_push_slot(&ctx, (float)cos(id), 1); - nk_chart_push_slot(&ctx, (float)sin(id), 2); - id += step; - } - } - nk_chart_end(&ctx); - - nk_layout_row_dynamic(&ctx, 250, 1); - if (nk_group_begin(&ctx, "Standard", NK_WINDOW_BORDER|NK_WINDOW_BORDER)) - { - if (nk_tree_push(&ctx, NK_TREE_NODE, "Window", NK_MAXIMIZED)) { - static int selected[8]; - if (nk_tree_push(&ctx, NK_TREE_NODE, "Next", NK_MAXIMIZED)) { - nk_layout_row_dynamic(&ctx, 20, 1); - for (i = 0; i < 4; ++i) - nk_selectable_label(&ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_LEFT, &selected[i]); - nk_tree_pop(&ctx); - } - if (nk_tree_push(&ctx, NK_TREE_NODE, "Previous", NK_MAXIMIZED)) { - nk_layout_row_dynamic(&ctx, 20, 1); - for (i = 4; i < 8; ++i) - nk_selectable_label(&ctx, (selected[i]) ? "Selected": "Unselected", NK_TEXT_LEFT, &selected[i]); - nk_tree_pop(&ctx); - } - nk_tree_pop(&ctx); - } - nk_group_end(&ctx); - } - } - nk_end(&ctx);} - - /* Draw */ - glViewport(0, 0, display_width, display_height); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(0.5882, 0.6666, 0.6666, 1.0f); - device_draw(&device, &ctx, width, height, scale, NK_ANTI_ALIASING_ON); - glfwSwapBuffers(win); - } - glDeleteTextures(1,(const GLuint*)&media.skin); - nk_font_atlas_clear(&atlas); - nk_free(&ctx); - device_shutdown(&device); - glfwTerminate(); - return 0; -} - diff --git a/deps/nuklear/example/skins/gwen.png b/deps/nuklear/example/skins/gwen.png deleted file mode 100644 index 40956c94..00000000 Binary files a/deps/nuklear/example/skins/gwen.png and /dev/null differ diff --git a/deps/nuklear/example/stb_image.h b/deps/nuklear/example/stb_image.h deleted file mode 100644 index 0a9de39b..00000000 --- a/deps/nuklear/example/stb_image.h +++ /dev/null @@ -1,6509 +0,0 @@ -/* stb_image - v2.08 - public domain image loader - http://nothings.org/stb_image.h - no warranty implied; use at your own risk - - Do this: - #define STB_IMAGE_IMPLEMENTATION - before you include this file in *one* C or C++ file to create the implementation. - - // i.e. it should look like this: - #include ... - #include ... - #include ... - #define STB_IMAGE_IMPLEMENTATION - #include "stb_image.h" - - You can #define STBI_ASSERT(x) before the #include to avoid using assert.h. - And #define STBI_MALLOC, STBI_REALLOC, and STBI_FREE to avoid using malloc,realloc,free - - - QUICK NOTES: - Primarily of interest to game developers and other people who can - avoid problematic images and only need the trivial interface - - JPEG baseline & progressive (12 bpc/arithmetic not supported, same as stock IJG lib) - PNG 1/2/4/8-bit-per-channel (16 bpc not supported) - - TGA (not sure what subset, if a subset) - BMP non-1bpp, non-RLE - PSD (composited view only, no extra channels, 8/16 bit-per-channel) - - GIF (*comp always reports as 4-channel) - HDR (radiance rgbE format) - PIC (Softimage PIC) - PNM (PPM and PGM binary only) - - Animated GIF still needs a proper API, but here's one way to do it: - http://gist.github.com/urraka/685d9a6340b26b830d49 - - - decode from memory or through FILE (define STBI_NO_STDIO to remove code) - - decode from arbitrary I/O callbacks - - SIMD acceleration on x86/x64 (SSE2) and ARM (NEON) - - Full documentation under "DOCUMENTATION" below. - - - Revision 2.00 release notes: - - - Progressive JPEG is now supported. - - - PPM and PGM binary formats are now supported, thanks to Ken Miller. - - - x86 platforms now make use of SSE2 SIMD instructions for - JPEG decoding, and ARM platforms can use NEON SIMD if requested. - This work was done by Fabian "ryg" Giesen. SSE2 is used by - default, but NEON must be enabled explicitly; see docs. - - With other JPEG optimizations included in this version, we see - 2x speedup on a JPEG on an x86 machine, and a 1.5x speedup - on a JPEG on an ARM machine, relative to previous versions of this - library. The same results will not obtain for all JPGs and for all - x86/ARM machines. (Note that progressive JPEGs are significantly - slower to decode than regular JPEGs.) This doesn't mean that this - is the fastest JPEG decoder in the land; rather, it brings it - closer to parity with standard libraries. If you want the fastest - decode, look elsewhere. (See "Philosophy" section of docs below.) - - See final bullet items below for more info on SIMD. - - - Added STBI_MALLOC, STBI_REALLOC, and STBI_FREE macros for replacing - the memory allocator. Unlike other STBI libraries, these macros don't - support a context parameter, so if you need to pass a context in to - the allocator, you'll have to store it in a global or a thread-local - variable. - - - Split existing STBI_NO_HDR flag into two flags, STBI_NO_HDR and - STBI_NO_LINEAR. - STBI_NO_HDR: suppress implementation of .hdr reader format - STBI_NO_LINEAR: suppress high-dynamic-range light-linear float API - - - You can suppress implementation of any of the decoders to reduce - your code footprint by #defining one or more of the following - symbols before creating the implementation. - - STBI_NO_JPEG - STBI_NO_PNG - STBI_NO_BMP - STBI_NO_PSD - STBI_NO_TGA - STBI_NO_GIF - STBI_NO_HDR - STBI_NO_PIC - STBI_NO_PNM (.ppm and .pgm) - - - You can request *only* certain decoders and suppress all other ones - (this will be more forward-compatible, as addition of new decoders - doesn't require you to disable them explicitly): - - STBI_ONLY_JPEG - STBI_ONLY_PNG - STBI_ONLY_BMP - STBI_ONLY_PSD - STBI_ONLY_TGA - STBI_ONLY_GIF - STBI_ONLY_HDR - STBI_ONLY_PIC - STBI_ONLY_PNM (.ppm and .pgm) - - Note that you can define multiples of these, and you will get all - of them ("only x" and "only y" is interpreted to mean "only x&y"). - - - If you use STBI_NO_PNG (or _ONLY_ without PNG), and you still - want the zlib decoder to be available, #define STBI_SUPPORT_ZLIB - - - Compilation of all SIMD code can be suppressed with - #define STBI_NO_SIMD - It should not be necessary to disable SIMD unless you have issues - compiling (e.g. using an x86 compiler which doesn't support SSE - intrinsics or that doesn't support the method used to detect - SSE2 support at run-time), and even those can be reported as - bugs so I can refine the built-in compile-time checking to be - smarter. - - - The old STBI_SIMD system which allowed installing a user-defined - IDCT etc. has been removed. If you need this, don't upgrade. My - assumption is that almost nobody was doing this, and those who - were will find the built-in SIMD more satisfactory anyway. - - - RGB values computed for JPEG images are slightly different from - previous versions of stb_image. (This is due to using less - integer precision in SIMD.) The C code has been adjusted so - that the same RGB values will be computed regardless of whether - SIMD support is available, so your app should always produce - consistent results. But these results are slightly different from - previous versions. (Specifically, about 3% of available YCbCr values - will compute different RGB results from pre-1.49 versions by +-1; - most of the deviating values are one smaller in the G channel.) - - - If you must produce consistent results with previous versions of - stb_image, #define STBI_JPEG_OLD and you will get the same results - you used to; however, you will not get the SIMD speedups for - the YCbCr-to-RGB conversion step (although you should still see - significant JPEG speedup from the other changes). - - Please note that STBI_JPEG_OLD is a temporary feature; it will be - removed in future versions of the library. It is only intended for - near-term back-compatibility use. - - - Latest revision history: - 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA - 2.07 (2015-09-13) partial animated GIF support - limited 16-bit PSD support - minor bugs, code cleanup, and compiler warnings - 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value - 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning - 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit - 2.03 (2015-04-12) additional corruption checking - stbi_set_flip_vertically_on_load - fix NEON support; fix mingw support - 2.02 (2015-01-19) fix incorrect assert, fix warning - 2.01 (2015-01-17) fix various warnings - 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG - 2.00 (2014-12-25) optimize JPEG, including x86 SSE2 & ARM NEON SIMD - progressive JPEG - PGM/PPM support - STBI_MALLOC,STBI_REALLOC,STBI_FREE - STBI_NO_*, STBI_ONLY_* - GIF bugfix - 1.48 (2014-12-14) fix incorrectly-named assert() - 1.47 (2014-12-14) 1/2/4-bit PNG support (both grayscale and paletted) - optimize PNG - fix bug in interlaced PNG with user-specified channel count - - See end of file for full revision history. - - - ============================ Contributors ========================= - - Image formats Bug fixes & warning fixes - Sean Barrett (jpeg, png, bmp) Marc LeBlanc - Nicolas Schulz (hdr, psd) Christpher Lloyd - Jonathan Dummer (tga) Dave Moore - Jean-Marc Lienher (gif) Won Chun - Tom Seddon (pic) the Horde3D community - Thatcher Ulrich (psd) Janez Zemva - Ken Miller (pgm, ppm) Jonathan Blow - urraka@github (animated gif) Laurent Gomila - Aruelien Pocheville - Ryamond Barbiero - David Woo - Extensions, features Martin Golini - Jetro Lauha (stbi_info) Roy Eltham - Martin "SpartanJ" Golini (stbi_info) Luke Graham - James "moose2000" Brown (iPhone PNG) Thomas Ruf - Ben "Disch" Wenger (io callbacks) John Bartholomew - Omar Cornut (1/2/4-bit PNG) Ken Hamada - Nicolas Guillemot (vertical flip) Cort Stratton - Richard Mitton (16-bit PSD) Blazej Dariusz Roszkowski - Thibault Reuille - Paul Du Bois - Guillaume George - Jerry Jansson - Hayaki Saito - Johan Duparc - Ronny Chevalier - Optimizations & bugfixes Michal Cichon - Fabian "ryg" Giesen Tero Hanninen - Arseny Kapoulkine Sergio Gonzalez - Cass Everitt - Engin Manap - If your name should be here but Martins Mozeiko - isn't, let Sean know. Joseph Thomson - Phil Jordan - Nathan Reed - Michaelangel007@github - Nick Verigakis - -LICENSE - -This software is in the public domain. Where that dedication is not -recognized, you are granted a perpetual, irrevocable license to copy, -distribute, and modify this file as you see fit. - -*/ - -#ifndef STBI_INCLUDE_STB_IMAGE_H -#define STBI_INCLUDE_STB_IMAGE_H - -// DOCUMENTATION -// -// Limitations: -// - no 16-bit-per-channel PNG -// - no 12-bit-per-channel JPEG -// - no JPEGs with arithmetic coding -// - no 1-bit BMP -// - GIF always returns *comp=4 -// -// Basic usage (see HDR discussion below for HDR usage): -// int x,y,n; -// unsigned char *data = stbi_load(filename, &x, &y, &n, 0); -// // ... process data if not NULL ... -// // ... x = width, y = height, n = # 8-bit components per pixel ... -// // ... replace '0' with '1'..'4' to force that many components per pixel -// // ... but 'n' will always be the number that it would have been if you said 0 -// stbi_image_free(data) -// -// Standard parameters: -// int *x -- outputs image width in pixels -// int *y -- outputs image height in pixels -// int *comp -- outputs # of image components in image file -// int req_comp -- if non-zero, # of image components requested in result -// -// The return value from an image loader is an 'unsigned char *' which points -// to the pixel data, or NULL on an allocation failure or if the image is -// corrupt or invalid. The pixel data consists of *y scanlines of *x pixels, -// with each pixel consisting of N interleaved 8-bit components; the first -// pixel pointed to is top-left-most in the image. There is no padding between -// image scanlines or between pixels, regardless of format. The number of -// components N is 'req_comp' if req_comp is non-zero, or *comp otherwise. -// If req_comp is non-zero, *comp has the number of components that _would_ -// have been output otherwise. E.g. if you set req_comp to 4, you will always -// get RGBA output, but you can check *comp to see if it's trivially opaque -// because e.g. there were only 3 channels in the source image. -// -// An output image with N components has the following components interleaved -// in this order in each pixel: -// -// N=#comp components -// 1 grey -// 2 grey, alpha -// 3 red, green, blue -// 4 red, green, blue, alpha -// -// If image loading fails for any reason, the return value will be NULL, -// and *x, *y, *comp will be unchanged. The function stbi_failure_reason() -// can be queried for an extremely brief, end-user unfriendly explanation -// of why the load failed. Define STBI_NO_FAILURE_STRINGS to avoid -// compiling these strings at all, and STBI_FAILURE_USERMSG to get slightly -// more user-friendly ones. -// -// Paletted PNG, BMP, GIF, and PIC images are automatically depalettized. -// -// =========================================================================== -// -// Philosophy -// -// stb libraries are designed with the following priorities: -// -// 1. easy to use -// 2. easy to maintain -// 3. good performance -// -// Sometimes I let "good performance" creep up in priority over "easy to maintain", -// and for best performance I may provide less-easy-to-use APIs that give higher -// performance, in addition to the easy to use ones. Nevertheless, it's important -// to keep in mind that from the standpoint of you, a client of this library, -// all you care about is #1 and #3, and stb libraries do not emphasize #3 above all. -// -// Some secondary priorities arise directly from the first two, some of which -// make more explicit reasons why performance can't be emphasized. -// -// - Portable ("ease of use") -// - Small footprint ("easy to maintain") -// - No dependencies ("ease of use") -// -// =========================================================================== -// -// I/O callbacks -// -// I/O callbacks allow you to read from arbitrary sources, like packaged -// files or some other source. Data read from callbacks are processed -// through a small internal buffer (currently 128 bytes) to try to reduce -// overhead. -// -// The three functions you must define are "read" (reads some bytes of data), -// "skip" (skips some bytes of data), "eof" (reports if the stream is at the end). -// -// =========================================================================== -// -// SIMD support -// -// The JPEG decoder will try to automatically use SIMD kernels on x86 when -// supported by the compiler. For ARM Neon support, you must explicitly -// request it. -// -// (The old do-it-yourself SIMD API is no longer supported in the current -// code.) -// -// On x86, SSE2 will automatically be used when available based on a run-time -// test; if not, the generic C versions are used as a fall-back. On ARM targets, -// the typical path is to have separate builds for NEON and non-NEON devices -// (at least this is true for iOS and Android). Therefore, the NEON support is -// toggled by a build flag: define STBI_NEON to get NEON loops. -// -// The output of the JPEG decoder is slightly different from versions where -// SIMD support was introduced (that is, for versions before 1.49). The -// difference is only +-1 in the 8-bit RGB channels, and only on a small -// fraction of pixels. You can force the pre-1.49 behavior by defining -// STBI_JPEG_OLD, but this will disable some of the SIMD decoding path -// and hence cost some performance. -// -// If for some reason you do not want to use any of SIMD code, or if -// you have issues compiling it, you can disable it entirely by -// defining STBI_NO_SIMD. -// -// =========================================================================== -// -// HDR image support (disable by defining STBI_NO_HDR) -// -// stb_image now supports loading HDR images in general, and currently -// the Radiance .HDR file format, although the support is provided -// generically. You can still load any file through the existing interface; -// if you attempt to load an HDR file, it will be automatically remapped to -// LDR, assuming gamma 2.2 and an arbitrary scale factor defaulting to 1; -// both of these constants can be reconfigured through this interface: -// -// stbi_hdr_to_ldr_gamma(2.2f); -// stbi_hdr_to_ldr_scale(1.0f); -// -// (note, do not use _inverse_ constants; stbi_image will invert them -// appropriately). -// -// Additionally, there is a new, parallel interface for loading files as -// (linear) floats to preserve the full dynamic range: -// -// float *data = stbi_loadf(filename, &x, &y, &n, 0); -// -// If you load LDR images through this interface, those images will -// be promoted to floating point values, run through the inverse of -// constants corresponding to the above: -// -// stbi_ldr_to_hdr_scale(1.0f); -// stbi_ldr_to_hdr_gamma(2.2f); -// -// Finally, given a filename (or an open file or memory block--see header -// file for details) containing image data, you can query for the "most -// appropriate" interface to use (that is, whether the image is HDR or -// not), using: -// -// stbi_is_hdr(char *filename); -// -// =========================================================================== -// -// iPhone PNG support: -// -// By default we convert iphone-formatted PNGs back to RGB, even though -// they are internally encoded differently. You can disable this conversion -// by by calling stbi_convert_iphone_png_to_rgb(0), in which case -// you will always just get the native iphone "format" through (which -// is BGR stored in RGB). -// -// Call stbi_set_unpremultiply_on_load(1) as well to force a divide per -// pixel to remove any premultiplied alpha *only* if the image file explicitly -// says there's premultiplied data (currently only happens in iPhone images, -// and only if iPhone convert-to-rgb processing is on). -// - - -#ifndef STBI_NO_STDIO -#include -#endif // STBI_NO_STDIO - -#define STBI_VERSION 1 - -enum -{ - STBI_default = 0, // only used for req_comp - - STBI_grey = 1, - STBI_grey_alpha = 2, - STBI_rgb = 3, - STBI_rgb_alpha = 4 -}; - -typedef unsigned char stbi_uc; - -#ifdef __cplusplus -extern "C" { -#endif - -#ifdef STB_IMAGE_STATIC -#define STBIDEF static -#else -#define STBIDEF extern -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// PRIMARY API - works on images of any type -// - -// -// load image by filename, open file, or memory buffer -// - -typedef struct -{ - int (*read) (void *user,char *data,int size); // fill 'data' with 'size' bytes. return number of bytes actually read - void (*skip) (void *user,int n); // skip the next 'n' bytes, or 'unget' the last -n bytes if negative - int (*eof) (void *user); // returns nonzero if we are at end of file/data -} stbi_io_callbacks; - -STBIDEF stbi_uc *stbi_load (char const *filename, int *x, int *y, int *comp, int req_comp); -STBIDEF stbi_uc *stbi_load_from_memory (stbi_uc const *buffer, int len , int *x, int *y, int *comp, int req_comp); -STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk , void *user, int *x, int *y, int *comp, int req_comp); - -#ifndef STBI_NO_STDIO -STBIDEF stbi_uc *stbi_load_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); -// for stbi_load_from_file, file pointer is left pointing immediately after image -#endif - -#ifndef STBI_NO_LINEAR - STBIDEF float *stbi_loadf (char const *filename, int *x, int *y, int *comp, int req_comp); - STBIDEF float *stbi_loadf_from_memory (stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp); - STBIDEF float *stbi_loadf_from_callbacks (stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp); - - #ifndef STBI_NO_STDIO - STBIDEF float *stbi_loadf_from_file (FILE *f, int *x, int *y, int *comp, int req_comp); - #endif -#endif - -#ifndef STBI_NO_HDR - STBIDEF void stbi_hdr_to_ldr_gamma(float gamma); - STBIDEF void stbi_hdr_to_ldr_scale(float scale); -#endif - -#ifndef STBI_NO_LINEAR - STBIDEF void stbi_ldr_to_hdr_gamma(float gamma); - STBIDEF void stbi_ldr_to_hdr_scale(float scale); -#endif // STBI_NO_HDR - -// stbi_is_hdr is always defined, but always returns false if STBI_NO_HDR -STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user); -STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len); -#ifndef STBI_NO_STDIO -STBIDEF int stbi_is_hdr (char const *filename); -STBIDEF int stbi_is_hdr_from_file(FILE *f); -#endif // STBI_NO_STDIO - - -// get a VERY brief reason for failure -// NOT THREADSAFE -STBIDEF const char *stbi_failure_reason (void); - -// free the loaded image -- this is just free() -STBIDEF void stbi_image_free (void *retval_from_stbi_load); - -// get image dimensions & components without fully decoding -STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp); -STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp); - -#ifndef STBI_NO_STDIO -STBIDEF int stbi_info (char const *filename, int *x, int *y, int *comp); -STBIDEF int stbi_info_from_file (FILE *f, int *x, int *y, int *comp); - -#endif - - - -// for image formats that explicitly notate that they have premultiplied alpha, -// we just return the colors as stored in the file. set this flag to force -// unpremultiplication. results are undefined if the unpremultiply overflow. -STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply); - -// indicate whether we should process iphone images back to canonical format, -// or just pass them through "as-is" -STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert); - -// flip the image vertically, so the first pixel in the output array is the bottom left -STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip); - -// ZLIB client - used by PNG, available for other purposes - -STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen); -STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header); -STBIDEF char *stbi_zlib_decode_malloc(const char *buffer, int len, int *outlen); -STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); - -STBIDEF char *stbi_zlib_decode_noheader_malloc(const char *buffer, int len, int *outlen); -STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen); - - -#ifdef __cplusplus -} -#endif - -// -// -//// end header file ///////////////////////////////////////////////////// -#endif // STBI_INCLUDE_STB_IMAGE_H - -#ifdef STB_IMAGE_IMPLEMENTATION - -#if defined(STBI_ONLY_JPEG) || defined(STBI_ONLY_PNG) || defined(STBI_ONLY_BMP) \ - || defined(STBI_ONLY_TGA) || defined(STBI_ONLY_GIF) || defined(STBI_ONLY_PSD) \ - || defined(STBI_ONLY_HDR) || defined(STBI_ONLY_PIC) || defined(STBI_ONLY_PNM) \ - || defined(STBI_ONLY_ZLIB) - #ifndef STBI_ONLY_JPEG - #define STBI_NO_JPEG - #endif - #ifndef STBI_ONLY_PNG - #define STBI_NO_PNG - #endif - #ifndef STBI_ONLY_BMP - #define STBI_NO_BMP - #endif - #ifndef STBI_ONLY_PSD - #define STBI_NO_PSD - #endif - #ifndef STBI_ONLY_TGA - #define STBI_NO_TGA - #endif - #ifndef STBI_ONLY_GIF - #define STBI_NO_GIF - #endif - #ifndef STBI_ONLY_HDR - #define STBI_NO_HDR - #endif - #ifndef STBI_ONLY_PIC - #define STBI_NO_PIC - #endif - #ifndef STBI_ONLY_PNM - #define STBI_NO_PNM - #endif -#endif - -#if defined(STBI_NO_PNG) && !defined(STBI_SUPPORT_ZLIB) && !defined(STBI_NO_ZLIB) -#define STBI_NO_ZLIB -#endif - - -#include -#include // ptrdiff_t on osx -#include -#include - -#if !defined(STBI_NO_LINEAR) || !defined(STBI_NO_HDR) -#include // ldexp -#endif - -#ifndef STBI_NO_STDIO -#include -#endif - -#ifndef STBI_ASSERT -#include -#define STBI_ASSERT(x) assert(x) -#endif - - -#ifndef _MSC_VER - #ifdef __cplusplus - #define stbi_inline inline - #else - #define stbi_inline - #endif -#else - #define stbi_inline __forceinline -#endif - - -#ifdef _MSC_VER -typedef unsigned short stbi__uint16; -typedef signed short stbi__int16; -typedef unsigned int stbi__uint32; -typedef signed int stbi__int32; -#else -#include -typedef uint16_t stbi__uint16; -typedef int16_t stbi__int16; -typedef uint32_t stbi__uint32; -typedef int32_t stbi__int32; -#endif - -// should produce compiler error if size is wrong -typedef unsigned char validate_uint32[sizeof(stbi__uint32)==4 ? 1 : -1]; - -#ifdef _MSC_VER -#define STBI_NOTUSED(v) (void)(v) -#else -#define STBI_NOTUSED(v) (void)sizeof(v) -#endif - -#ifdef _MSC_VER -#define STBI_HAS_LROTL -#endif - -#ifdef STBI_HAS_LROTL - #define stbi_lrot(x,y) _lrotl(x,y) -#else - #define stbi_lrot(x,y) (((x) << (y)) | ((x) >> (32 - (y)))) -#endif - -#if defined(STBI_MALLOC) && defined(STBI_FREE) && defined(STBI_REALLOC) -// ok -#elif !defined(STBI_MALLOC) && !defined(STBI_FREE) && !defined(STBI_REALLOC) -// ok -#else -#error "Must define all or none of STBI_MALLOC, STBI_FREE, and STBI_REALLOC." -#endif - -#ifndef STBI_MALLOC -#define STBI_MALLOC(sz) malloc(sz) -#define STBI_REALLOC(p,sz) realloc(p,sz) -#define STBI_FREE(p) free(p) -#endif - -// x86/x64 detection -#if defined(__x86_64__) || defined(_M_X64) -#define STBI__X64_TARGET -#elif defined(__i386) || defined(_M_IX86) -#define STBI__X86_TARGET -#endif - -#if defined(__GNUC__) && (defined(STBI__X86_TARGET) || defined(STBI__X64_TARGET)) && !defined(__SSE2__) && !defined(STBI_NO_SIMD) -// NOTE: not clear do we actually need this for the 64-bit path? -// gcc doesn't support sse2 intrinsics unless you compile with -msse2, -// (but compiling with -msse2 allows the compiler to use SSE2 everywhere; -// this is just broken and gcc are jerks for not fixing it properly -// http://www.virtualdub.org/blog/pivot/entry.php?id=363 ) -#define STBI_NO_SIMD -#endif - -#if defined(__MINGW32__) && defined(STBI__X86_TARGET) && !defined(STBI_MINGW_ENABLE_SSE2) && !defined(STBI_NO_SIMD) -// Note that __MINGW32__ doesn't actually mean 32-bit, so we have to avoid STBI__X64_TARGET -// -// 32-bit MinGW wants ESP to be 16-byte aligned, but this is not in the -// Windows ABI and VC++ as well as Windows DLLs don't maintain that invariant. -// As a result, enabling SSE2 on 32-bit MinGW is dangerous when not -// simultaneously enabling "-mstackrealign". -// -// See https://github.com/nothings/stb/issues/81 for more information. -// -// So default to no SSE2 on 32-bit MinGW. If you've read this far and added -// -mstackrealign to your build settings, feel free to #define STBI_MINGW_ENABLE_SSE2. -#define STBI_NO_SIMD -#endif - -#if !defined(STBI_NO_SIMD) && defined(STBI__X86_TARGET) -#define STBI_SSE2 -#include - -#ifdef _MSC_VER - -#if _MSC_VER >= 1400 // not VC6 -#include // __cpuid -static int stbi__cpuid3(void) -{ - int info[4]; - __cpuid(info,1); - return info[3]; -} -#else -static int stbi__cpuid3(void) -{ - int res; - __asm { - mov eax,1 - cpuid - mov res,edx - } - return res; -} -#endif - -#define STBI_SIMD_ALIGN(type, name) __declspec(align(16)) type name - -static int stbi__sse2_available() -{ - int info3 = stbi__cpuid3(); - return ((info3 >> 26) & 1) != 0; -} -#else // assume GCC-style if not VC++ -#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) - -static int stbi__sse2_available() -{ -#if defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__) >= 408 // GCC 4.8 or later - // GCC 4.8+ has a nice way to do this - return __builtin_cpu_supports("sse2"); -#else - // portable way to do this, preferably without using GCC inline ASM? - // just bail for now. - return 0; -#endif -} -#endif -#endif - -// ARM NEON -#if defined(STBI_NO_SIMD) && defined(STBI_NEON) -#undef STBI_NEON -#endif - -#ifdef STBI_NEON -#include -// assume GCC or Clang on ARM targets -#define STBI_SIMD_ALIGN(type, name) type name __attribute__((aligned(16))) -#endif - -#ifndef STBI_SIMD_ALIGN -#define STBI_SIMD_ALIGN(type, name) type name -#endif - -/////////////////////////////////////////////// -// -// stbi__context struct and start_xxx functions - -// stbi__context structure is our basic context used by all images, so it -// contains all the IO context, plus some basic image information -typedef struct -{ - stbi__uint32 img_x, img_y; - int img_n, img_out_n; - - stbi_io_callbacks io; - void *io_user_data; - - int read_from_callbacks; - int buflen; - stbi_uc buffer_start[128]; - - stbi_uc *img_buffer, *img_buffer_end; - stbi_uc *img_buffer_original, *img_buffer_original_end; -} stbi__context; - - -static void stbi__refill_buffer(stbi__context *s); - -// initialize a memory-decode context -static void stbi__start_mem(stbi__context *s, stbi_uc const *buffer, int len) -{ - s->io.read = NULL; - s->read_from_callbacks = 0; - s->img_buffer = s->img_buffer_original = (stbi_uc *) buffer; - s->img_buffer_end = s->img_buffer_original_end = (stbi_uc *) buffer+len; -} - -// initialize a callback-based context -static void stbi__start_callbacks(stbi__context *s, stbi_io_callbacks *c, void *user) -{ - s->io = *c; - s->io_user_data = user; - s->buflen = sizeof(s->buffer_start); - s->read_from_callbacks = 1; - s->img_buffer_original = s->buffer_start; - stbi__refill_buffer(s); - s->img_buffer_original_end = s->img_buffer_end; -} - -#ifndef STBI_NO_STDIO - -static int stbi__stdio_read(void *user, char *data, int size) -{ - return (int) fread(data,1,size,(FILE*) user); -} - -static void stbi__stdio_skip(void *user, int n) -{ - fseek((FILE*) user, n, SEEK_CUR); -} - -static int stbi__stdio_eof(void *user) -{ - return feof((FILE*) user); -} - -static stbi_io_callbacks stbi__stdio_callbacks = -{ - stbi__stdio_read, - stbi__stdio_skip, - stbi__stdio_eof, -}; - -static void stbi__start_file(stbi__context *s, FILE *f) -{ - stbi__start_callbacks(s, &stbi__stdio_callbacks, (void *) f); -} - -//static void stop_file(stbi__context *s) { } - -#endif // !STBI_NO_STDIO - -static void stbi__rewind(stbi__context *s) -{ - // conceptually rewind SHOULD rewind to the beginning of the stream, - // but we just rewind to the beginning of the initial buffer, because - // we only use it after doing 'test', which only ever looks at at most 92 bytes - s->img_buffer = s->img_buffer_original; - s->img_buffer_end = s->img_buffer_original_end; -} - -#ifndef STBI_NO_JPEG -static int stbi__jpeg_test(stbi__context *s); -static stbi_uc *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); -static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PNG -static int stbi__png_test(stbi__context *s); -static stbi_uc *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); -static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_BMP -static int stbi__bmp_test(stbi__context *s); -static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); -static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_TGA -static int stbi__tga_test(stbi__context *s); -static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); -static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PSD -static int stbi__psd_test(stbi__context *s); -static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); -static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_HDR -static int stbi__hdr_test(stbi__context *s); -static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); -static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PIC -static int stbi__pic_test(stbi__context *s); -static stbi_uc *stbi__pic_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); -static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_GIF -static int stbi__gif_test(stbi__context *s); -static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); -static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -#ifndef STBI_NO_PNM -static int stbi__pnm_test(stbi__context *s); -static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp); -static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp); -#endif - -// this is not threadsafe -static const char *stbi__g_failure_reason; - -STBIDEF const char *stbi_failure_reason(void) -{ - return stbi__g_failure_reason; -} - -static int stbi__err(const char *str) -{ - stbi__g_failure_reason = str; - return 0; -} - -static void *stbi__malloc(size_t size) -{ - return STBI_MALLOC(size); -} - -// stbi__err - error -// stbi__errpf - error returning pointer to float -// stbi__errpuc - error returning pointer to unsigned char - -#ifdef STBI_NO_FAILURE_STRINGS - #define stbi__err(x,y) 0 -#elif defined(STBI_FAILURE_USERMSG) - #define stbi__err(x,y) stbi__err(y) -#else - #define stbi__err(x,y) stbi__err(x) -#endif - -#define stbi__errpf(x,y) ((float *)(size_t) (stbi__err(x,y)?NULL:NULL)) -#define stbi__errpuc(x,y) ((unsigned char *)(size_t) (stbi__err(x,y)?NULL:NULL)) - -STBIDEF void stbi_image_free(void *retval_from_stbi_load) -{ - STBI_FREE(retval_from_stbi_load); -} - -#ifndef STBI_NO_LINEAR -static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp); -#endif - -#ifndef STBI_NO_HDR -static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp); -#endif - -static int stbi__vertically_flip_on_load = 0; - -STBIDEF void stbi_set_flip_vertically_on_load(int flag_true_if_should_flip) -{ - stbi__vertically_flip_on_load = flag_true_if_should_flip; -} - -static unsigned char *stbi__load_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - #ifndef STBI_NO_JPEG - if (stbi__jpeg_test(s)) return stbi__jpeg_load(s,x,y,comp,req_comp); - #endif - #ifndef STBI_NO_PNG - if (stbi__png_test(s)) return stbi__png_load(s,x,y,comp,req_comp); - #endif - #ifndef STBI_NO_BMP - if (stbi__bmp_test(s)) return stbi__bmp_load(s,x,y,comp,req_comp); - #endif - #ifndef STBI_NO_GIF - if (stbi__gif_test(s)) return stbi__gif_load(s,x,y,comp,req_comp); - #endif - #ifndef STBI_NO_PSD - if (stbi__psd_test(s)) return stbi__psd_load(s,x,y,comp,req_comp); - #endif - #ifndef STBI_NO_PIC - if (stbi__pic_test(s)) return stbi__pic_load(s,x,y,comp,req_comp); - #endif - #ifndef STBI_NO_PNM - if (stbi__pnm_test(s)) return stbi__pnm_load(s,x,y,comp,req_comp); - #endif - - #ifndef STBI_NO_HDR - if (stbi__hdr_test(s)) { - float *hdr = stbi__hdr_load(s, x,y,comp,req_comp); - return stbi__hdr_to_ldr(hdr, *x, *y, req_comp ? req_comp : *comp); - } - #endif - - #ifndef STBI_NO_TGA - // test tga last because it's a crappy test! - if (stbi__tga_test(s)) - return stbi__tga_load(s,x,y,comp,req_comp); - #endif - - return stbi__errpuc("unknown image type", "Image not of any known type, or corrupt"); -} - -static unsigned char *stbi__load_flip(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *result = stbi__load_main(s, x, y, comp, req_comp); - - if (stbi__vertically_flip_on_load && result != NULL) { - int w = *x, h = *y; - int depth = req_comp ? req_comp : *comp; - int row,col,z; - stbi_uc temp; - - // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once - for (row = 0; row < (h>>1); row++) { - for (col = 0; col < w; col++) { - for (z = 0; z < depth; z++) { - temp = result[(row * w + col) * depth + z]; - result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; - result[((h - row - 1) * w + col) * depth + z] = temp; - } - } - } - } - - return result; -} - -#ifndef STBI_NO_HDR -static void stbi__float_postprocess(float *result, int *x, int *y, int *comp, int req_comp) -{ - if (stbi__vertically_flip_on_load && result != NULL) { - int w = *x, h = *y; - int depth = req_comp ? req_comp : *comp; - int row,col,z; - float temp; - - // @OPTIMIZE: use a bigger temp buffer and memcpy multiple pixels at once - for (row = 0; row < (h>>1); row++) { - for (col = 0; col < w; col++) { - for (z = 0; z < depth; z++) { - temp = result[(row * w + col) * depth + z]; - result[(row * w + col) * depth + z] = result[((h - row - 1) * w + col) * depth + z]; - result[((h - row - 1) * w + col) * depth + z] = temp; - } - } - } - } -} -#endif - -#ifndef STBI_NO_STDIO - -static FILE *stbi__fopen(char const *filename, char const *mode) -{ - FILE *f; -#if defined(_MSC_VER) && _MSC_VER >= 1400 - if (0 != fopen_s(&f, filename, mode)) - f=0; -#else - f = fopen(filename, mode); -#endif - return f; -} - - -STBIDEF stbi_uc *stbi_load(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - FILE *f = stbi__fopen(filename, "rb"); - unsigned char *result; - if (!f) return stbi__errpuc("can't fopen", "Unable to open file"); - result = stbi_load_from_file(f,x,y,comp,req_comp); - fclose(f); - return result; -} - -STBIDEF stbi_uc *stbi_load_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *result; - stbi__context s; - stbi__start_file(&s,f); - result = stbi__load_flip(&s,x,y,comp,req_comp); - if (result) { - // need to 'unget' all the characters in the IO buffer - fseek(f, - (int) (s.img_buffer_end - s.img_buffer), SEEK_CUR); - } - return result; -} -#endif //!STBI_NO_STDIO - -STBIDEF stbi_uc *stbi_load_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_mem(&s,buffer,len); - return stbi__load_flip(&s,x,y,comp,req_comp); -} - -STBIDEF stbi_uc *stbi_load_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); - return stbi__load_flip(&s,x,y,comp,req_comp); -} - -#ifndef STBI_NO_LINEAR -static float *stbi__loadf_main(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - unsigned char *data; - #ifndef STBI_NO_HDR - if (stbi__hdr_test(s)) { - float *hdr_data = stbi__hdr_load(s,x,y,comp,req_comp); - if (hdr_data) - stbi__float_postprocess(hdr_data,x,y,comp,req_comp); - return hdr_data; - } - #endif - data = stbi__load_flip(s, x, y, comp, req_comp); - if (data) - return stbi__ldr_to_hdr(data, *x, *y, req_comp ? req_comp : *comp); - return stbi__errpf("unknown image type", "Image not of any known type, or corrupt"); -} - -STBIDEF float *stbi_loadf_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_mem(&s,buffer,len); - return stbi__loadf_main(&s,x,y,comp,req_comp); -} - -STBIDEF float *stbi_loadf_from_callbacks(stbi_io_callbacks const *clbk, void *user, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); - return stbi__loadf_main(&s,x,y,comp,req_comp); -} - -#ifndef STBI_NO_STDIO -STBIDEF float *stbi_loadf(char const *filename, int *x, int *y, int *comp, int req_comp) -{ - float *result; - FILE *f = stbi__fopen(filename, "rb"); - if (!f) return stbi__errpf("can't fopen", "Unable to open file"); - result = stbi_loadf_from_file(f,x,y,comp,req_comp); - fclose(f); - return result; -} - -STBIDEF float *stbi_loadf_from_file(FILE *f, int *x, int *y, int *comp, int req_comp) -{ - stbi__context s; - stbi__start_file(&s,f); - return stbi__loadf_main(&s,x,y,comp,req_comp); -} -#endif // !STBI_NO_STDIO - -#endif // !STBI_NO_LINEAR - -// these is-hdr-or-not is defined independent of whether STBI_NO_LINEAR is -// defined, for API simplicity; if STBI_NO_LINEAR is defined, it always -// reports false! - -STBIDEF int stbi_is_hdr_from_memory(stbi_uc const *buffer, int len) -{ - #ifndef STBI_NO_HDR - stbi__context s; - stbi__start_mem(&s,buffer,len); - return stbi__hdr_test(&s); - #else - STBI_NOTUSED(buffer); - STBI_NOTUSED(len); - return 0; - #endif -} - -#ifndef STBI_NO_STDIO -STBIDEF int stbi_is_hdr (char const *filename) -{ - FILE *f = stbi__fopen(filename, "rb"); - int result=0; - if (f) { - result = stbi_is_hdr_from_file(f); - fclose(f); - } - return result; -} - -STBIDEF int stbi_is_hdr_from_file(FILE *f) -{ - #ifndef STBI_NO_HDR - stbi__context s; - stbi__start_file(&s,f); - return stbi__hdr_test(&s); - #else - STBI_NOTUSED(f); - return 0; - #endif -} -#endif // !STBI_NO_STDIO - -STBIDEF int stbi_is_hdr_from_callbacks(stbi_io_callbacks const *clbk, void *user) -{ - #ifndef STBI_NO_HDR - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *) clbk, user); - return stbi__hdr_test(&s); - #else - STBI_NOTUSED(clbk); - STBI_NOTUSED(user); - return 0; - #endif -} - -static float stbi__h2l_gamma_i=1.0f/2.2f, stbi__h2l_scale_i=1.0f; -static float stbi__l2h_gamma=2.2f, stbi__l2h_scale=1.0f; - -#ifndef STBI_NO_LINEAR -STBIDEF void stbi_ldr_to_hdr_gamma(float gamma) { stbi__l2h_gamma = gamma; } -STBIDEF void stbi_ldr_to_hdr_scale(float scale) { stbi__l2h_scale = scale; } -#endif - -STBIDEF void stbi_hdr_to_ldr_gamma(float gamma) { stbi__h2l_gamma_i = 1/gamma; } -STBIDEF void stbi_hdr_to_ldr_scale(float scale) { stbi__h2l_scale_i = 1/scale; } - - -////////////////////////////////////////////////////////////////////////////// -// -// Common code used by all image loaders -// - -enum -{ - STBI__SCAN_load=0, - STBI__SCAN_type, - STBI__SCAN_header -}; - -static void stbi__refill_buffer(stbi__context *s) -{ - int n = (s->io.read)(s->io_user_data,(char*)s->buffer_start,s->buflen); - if (n == 0) { - // at end of file, treat same as if from memory, but need to handle case - // where s->img_buffer isn't pointing to safe memory, e.g. 0-byte file - s->read_from_callbacks = 0; - s->img_buffer = s->buffer_start; - s->img_buffer_end = s->buffer_start+1; - *s->img_buffer = 0; - } else { - s->img_buffer = s->buffer_start; - s->img_buffer_end = s->buffer_start + n; - } -} - -stbi_inline static stbi_uc stbi__get8(stbi__context *s) -{ - if (s->img_buffer < s->img_buffer_end) - return *s->img_buffer++; - if (s->read_from_callbacks) { - stbi__refill_buffer(s); - return *s->img_buffer++; - } - return 0; -} - -stbi_inline static int stbi__at_eof(stbi__context *s) -{ - if (s->io.read) { - if (!(s->io.eof)(s->io_user_data)) return 0; - // if feof() is true, check if buffer = end - // special case: we've only got the special 0 character at the end - if (s->read_from_callbacks == 0) return 1; - } - - return s->img_buffer >= s->img_buffer_end; -} - -static void stbi__skip(stbi__context *s, int n) -{ - if (n < 0) { - s->img_buffer = s->img_buffer_end; - return; - } - if (s->io.read) { - int blen = (int) (s->img_buffer_end - s->img_buffer); - if (blen < n) { - s->img_buffer = s->img_buffer_end; - (s->io.skip)(s->io_user_data, n - blen); - return; - } - } - s->img_buffer += n; -} - -static int stbi__getn(stbi__context *s, stbi_uc *buffer, int n) -{ - if (s->io.read) { - int blen = (int) (s->img_buffer_end - s->img_buffer); - if (blen < n) { - int res, count; - - memcpy(buffer, s->img_buffer, blen); - - count = (s->io.read)(s->io_user_data, (char*) buffer + blen, n - blen); - res = (count == (n-blen)); - s->img_buffer = s->img_buffer_end; - return res; - } - } - - if (s->img_buffer+n <= s->img_buffer_end) { - memcpy(buffer, s->img_buffer, n); - s->img_buffer += n; - return 1; - } else - return 0; -} - -static int stbi__get16be(stbi__context *s) -{ - int z = stbi__get8(s); - return (z << 8) + stbi__get8(s); -} - -static stbi__uint32 stbi__get32be(stbi__context *s) -{ - stbi__uint32 z = stbi__get16be(s); - return (z << 16) + stbi__get16be(s); -} - -#if defined(STBI_NO_BMP) && defined(STBI_NO_TGA) && defined(STBI_NO_GIF) -// nothing -#else -static int stbi__get16le(stbi__context *s) -{ - int z = stbi__get8(s); - return z + (stbi__get8(s) << 8); -} -#endif - -#ifndef STBI_NO_BMP -static stbi__uint32 stbi__get32le(stbi__context *s) -{ - stbi__uint32 z = stbi__get16le(s); - return z + (stbi__get16le(s) << 16); -} -#endif - -#define STBI__BYTECAST(x) ((stbi_uc) ((x) & 255)) // truncate int to byte without warnings - - -////////////////////////////////////////////////////////////////////////////// -// -// generic converter from built-in img_n to req_comp -// individual types do this automatically as much as possible (e.g. jpeg -// does all cases internally since it needs to colorspace convert anyway, -// and it never has alpha, so very few cases ). png can automatically -// interleave an alpha=255 channel, but falls back to this for other cases -// -// assume data buffer is malloced, so malloc a new one and free that one -// only failure mode is malloc failing - -static stbi_uc stbi__compute_y(int r, int g, int b) -{ - return (stbi_uc) (((r*77) + (g*150) + (29*b)) >> 8); -} - -static unsigned char *stbi__convert_format(unsigned char *data, int img_n, int req_comp, unsigned int x, unsigned int y) -{ - int i,j; - unsigned char *good; - - if (req_comp == img_n) return data; - STBI_ASSERT(req_comp >= 1 && req_comp <= 4); - - good = (unsigned char *) stbi__malloc(req_comp * x * y); - if (good == NULL) { - STBI_FREE(data); - return stbi__errpuc("outofmem", "Out of memory"); - } - - for (j=0; j < (int) y; ++j) { - unsigned char *src = data + j * x * img_n ; - unsigned char *dest = good + j * x * req_comp; - - #define COMBO(a,b) ((a)*8+(b)) - #define CASE(a,b) case COMBO(a,b): for(i=x-1; i >= 0; --i, src += a, dest += b) - // convert source image with img_n components to one with req_comp components; - // avoid switch per pixel, so use switch per scanline and massive macros - switch (COMBO(img_n, req_comp)) { - CASE(1,2) dest[0]=src[0], dest[1]=255; break; - CASE(1,3) dest[0]=dest[1]=dest[2]=src[0]; break; - CASE(1,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=255; break; - CASE(2,1) dest[0]=src[0]; break; - CASE(2,3) dest[0]=dest[1]=dest[2]=src[0]; break; - CASE(2,4) dest[0]=dest[1]=dest[2]=src[0], dest[3]=src[1]; break; - CASE(3,4) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2],dest[3]=255; break; - CASE(3,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; - CASE(3,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = 255; break; - CASE(4,1) dest[0]=stbi__compute_y(src[0],src[1],src[2]); break; - CASE(4,2) dest[0]=stbi__compute_y(src[0],src[1],src[2]), dest[1] = src[3]; break; - CASE(4,3) dest[0]=src[0],dest[1]=src[1],dest[2]=src[2]; break; - default: STBI_ASSERT(0); - } - #undef CASE - } - - STBI_FREE(data); - return good; -} - -#ifndef STBI_NO_LINEAR -static float *stbi__ldr_to_hdr(stbi_uc *data, int x, int y, int comp) -{ - int i,k,n; - float *output = (float *) stbi__malloc(x * y * comp * sizeof(float)); - if (output == NULL) { STBI_FREE(data); return stbi__errpf("outofmem", "Out of memory"); } - // compute number of non-alpha components - if (comp & 1) n = comp; else n = comp-1; - for (i=0; i < x*y; ++i) { - for (k=0; k < n; ++k) { - output[i*comp + k] = (float) (pow(data[i*comp+k]/255.0f, stbi__l2h_gamma) * stbi__l2h_scale); - } - if (k < comp) output[i*comp + k] = data[i*comp+k]/255.0f; - } - STBI_FREE(data); - return output; -} -#endif - -#ifndef STBI_NO_HDR -#define stbi__float2int(x) ((int) (x)) -static stbi_uc *stbi__hdr_to_ldr(float *data, int x, int y, int comp) -{ - int i,k,n; - stbi_uc *output = (stbi_uc *) stbi__malloc(x * y * comp); - if (output == NULL) { STBI_FREE(data); return stbi__errpuc("outofmem", "Out of memory"); } - // compute number of non-alpha components - if (comp & 1) n = comp; else n = comp-1; - for (i=0; i < x*y; ++i) { - for (k=0; k < n; ++k) { - float z = (float) pow(data[i*comp+k]*stbi__h2l_scale_i, stbi__h2l_gamma_i) * 255 + 0.5f; - if (z < 0) z = 0; - if (z > 255) z = 255; - output[i*comp + k] = (stbi_uc) stbi__float2int(z); - } - if (k < comp) { - float z = data[i*comp+k] * 255 + 0.5f; - if (z < 0) z = 0; - if (z > 255) z = 255; - output[i*comp + k] = (stbi_uc) stbi__float2int(z); - } - } - STBI_FREE(data); - return output; -} -#endif - -////////////////////////////////////////////////////////////////////////////// -// -// "baseline" JPEG/JFIF decoder -// -// simple implementation -// - doesn't support delayed output of y-dimension -// - simple interface (only one output format: 8-bit interleaved RGB) -// - doesn't try to recover corrupt jpegs -// - doesn't allow partial loading, loading multiple at once -// - still fast on x86 (copying globals into locals doesn't help x86) -// - allocates lots of intermediate memory (full size of all components) -// - non-interleaved case requires this anyway -// - allows good upsampling (see next) -// high-quality -// - upsampled channels are bilinearly interpolated, even across blocks -// - quality integer IDCT derived from IJG's 'slow' -// performance -// - fast huffman; reasonable integer IDCT -// - some SIMD kernels for common paths on targets with SSE2/NEON -// - uses a lot of intermediate memory, could cache poorly - -#ifndef STBI_NO_JPEG - -// huffman decoding acceleration -#define FAST_BITS 9 // larger handles more cases; smaller stomps less cache - -typedef struct -{ - stbi_uc fast[1 << FAST_BITS]; - // weirdly, repacking this into AoS is a 10% speed loss, instead of a win - stbi__uint16 code[256]; - stbi_uc values[256]; - stbi_uc size[257]; - unsigned int maxcode[18]; - int delta[17]; // old 'firstsymbol' - old 'firstcode' -} stbi__huffman; - -typedef struct -{ - stbi__context *s; - stbi__huffman huff_dc[4]; - stbi__huffman huff_ac[4]; - stbi_uc dequant[4][64]; - stbi__int16 fast_ac[4][1 << FAST_BITS]; - -// sizes for components, interleaved MCUs - int img_h_max, img_v_max; - int img_mcu_x, img_mcu_y; - int img_mcu_w, img_mcu_h; - -// definition of jpeg image component - struct - { - int id; - int h,v; - int tq; - int hd,ha; - int dc_pred; - - int x,y,w2,h2; - stbi_uc *data; - void *raw_data, *raw_coeff; - stbi_uc *linebuf; - short *coeff; // progressive only - int coeff_w, coeff_h; // number of 8x8 coefficient blocks - } img_comp[4]; - - stbi__uint32 code_buffer; // jpeg entropy-coded buffer - int code_bits; // number of valid bits - unsigned char marker; // marker seen while filling entropy buffer - int nomore; // flag if we saw a marker so must stop - - int progressive; - int spec_start; - int spec_end; - int succ_high; - int succ_low; - int eob_run; - - int scan_n, order[4]; - int restart_interval, todo; - -// kernels - void (*idct_block_kernel)(stbi_uc *out, int out_stride, short data[64]); - void (*YCbCr_to_RGB_kernel)(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step); - stbi_uc *(*resample_row_hv_2_kernel)(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs); -} stbi__jpeg; - -static int stbi__build_huffman(stbi__huffman *h, int *count) -{ - int i,j,k=0,code; - // build size list for each symbol (from JPEG spec) - for (i=0; i < 16; ++i) - for (j=0; j < count[i]; ++j) - h->size[k++] = (stbi_uc) (i+1); - h->size[k] = 0; - - // compute actual symbols (from jpeg spec) - code = 0; - k = 0; - for(j=1; j <= 16; ++j) { - // compute delta to add to code to compute symbol id - h->delta[j] = k - code; - if (h->size[k] == j) { - while (h->size[k] == j) - h->code[k++] = (stbi__uint16) (code++); - if (code-1 >= (1 << j)) return stbi__err("bad code lengths","Corrupt JPEG"); - } - // compute largest code + 1 for this size, preshifted as needed later - h->maxcode[j] = code << (16-j); - code <<= 1; - } - h->maxcode[j] = 0xffffffff; - - // build non-spec acceleration table; 255 is flag for not-accelerated - memset(h->fast, 255, 1 << FAST_BITS); - for (i=0; i < k; ++i) { - int s = h->size[i]; - if (s <= FAST_BITS) { - int c = h->code[i] << (FAST_BITS-s); - int m = 1 << (FAST_BITS-s); - for (j=0; j < m; ++j) { - h->fast[c+j] = (stbi_uc) i; - } - } - } - return 1; -} - -// build a table that decodes both magnitude and value of small ACs in -// one go. -static void stbi__build_fast_ac(stbi__int16 *fast_ac, stbi__huffman *h) -{ - int i; - for (i=0; i < (1 << FAST_BITS); ++i) { - stbi_uc fast = h->fast[i]; - fast_ac[i] = 0; - if (fast < 255) { - int rs = h->values[fast]; - int run = (rs >> 4) & 15; - int magbits = rs & 15; - int len = h->size[fast]; - - if (magbits && len + magbits <= FAST_BITS) { - // magnitude code followed by receive_extend code - int k = ((i << len) & ((1 << FAST_BITS) - 1)) >> (FAST_BITS - magbits); - int m = 1 << (magbits - 1); - if (k < m) k += (-1 << magbits) + 1; - // if the result is small enough, we can fit it in fast_ac table - if (k >= -128 && k <= 127) - fast_ac[i] = (stbi__int16) ((k << 8) + (run << 4) + (len + magbits)); - } - } - } -} - -static void stbi__grow_buffer_unsafe(stbi__jpeg *j) -{ - do { - int b = j->nomore ? 0 : stbi__get8(j->s); - if (b == 0xff) { - int c = stbi__get8(j->s); - if (c != 0) { - j->marker = (unsigned char) c; - j->nomore = 1; - return; - } - } - j->code_buffer |= b << (24 - j->code_bits); - j->code_bits += 8; - } while (j->code_bits <= 24); -} - -// (1 << n) - 1 -static stbi__uint32 stbi__bmask[17]={0,1,3,7,15,31,63,127,255,511,1023,2047,4095,8191,16383,32767,65535}; - -// decode a jpeg huffman value from the bitstream -stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h) -{ - unsigned int temp; - int c,k; - - if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); - - // look at the top FAST_BITS and determine what symbol ID it is, - // if the code is <= FAST_BITS - c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); - k = h->fast[c]; - if (k < 255) { - int s = h->size[k]; - if (s > j->code_bits) - return -1; - j->code_buffer <<= s; - j->code_bits -= s; - return h->values[k]; - } - - // naive test is to shift the code_buffer down so k bits are - // valid, then test against maxcode. To speed this up, we've - // preshifted maxcode left so that it has (16-k) 0s at the - // end; in other words, regardless of the number of bits, it - // wants to be compared against something shifted to have 16; - // that way we don't need to shift inside the loop. - temp = j->code_buffer >> 16; - for (k=FAST_BITS+1 ; ; ++k) - if (temp < h->maxcode[k]) - break; - if (k == 17) { - // error! code not found - j->code_bits -= 16; - return -1; - } - - if (k > j->code_bits) - return -1; - - // convert the huffman code to the symbol id - c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k]; - STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]); - - // convert the id to a symbol - j->code_bits -= k; - j->code_buffer <<= k; - return h->values[c]; -} - -// bias[n] = (-1<code_bits < n) stbi__grow_buffer_unsafe(j); - - sgn = (stbi__int32)j->code_buffer >> 31; // sign bit is always in MSB - k = stbi_lrot(j->code_buffer, n); - STBI_ASSERT(n >= 0 && n < (int) (sizeof(stbi__bmask)/sizeof(*stbi__bmask))); - j->code_buffer = k & ~stbi__bmask[n]; - k &= stbi__bmask[n]; - j->code_bits -= n; - return k + (stbi__jbias[n] & ~sgn); -} - -// get some unsigned bits -stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n) -{ - unsigned int k; - if (j->code_bits < n) stbi__grow_buffer_unsafe(j); - k = stbi_lrot(j->code_buffer, n); - j->code_buffer = k & ~stbi__bmask[n]; - k &= stbi__bmask[n]; - j->code_bits -= n; - return k; -} - -stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j) -{ - unsigned int k; - if (j->code_bits < 1) stbi__grow_buffer_unsafe(j); - k = j->code_buffer; - j->code_buffer <<= 1; - --j->code_bits; - return k & 0x80000000; -} - -// given a value that's at position X in the zigzag stream, -// where does it appear in the 8x8 matrix coded as row-major? -static stbi_uc stbi__jpeg_dezigzag[64+15] = -{ - 0, 1, 8, 16, 9, 2, 3, 10, - 17, 24, 32, 25, 18, 11, 4, 5, - 12, 19, 26, 33, 40, 48, 41, 34, - 27, 20, 13, 6, 7, 14, 21, 28, - 35, 42, 49, 56, 57, 50, 43, 36, - 29, 22, 15, 23, 30, 37, 44, 51, - 58, 59, 52, 45, 38, 31, 39, 46, - 53, 60, 61, 54, 47, 55, 62, 63, - // let corrupt input sample past end - 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63 -}; - -// decode one 64-entry block-- -static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman *hdc, stbi__huffman *hac, stbi__int16 *fac, int b, stbi_uc *dequant) -{ - int diff,dc,k; - int t; - - if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); - t = stbi__jpeg_huff_decode(j, hdc); - if (t < 0) return stbi__err("bad huffman code","Corrupt JPEG"); - - // 0 all the ac values now so we can do it 32-bits at a time - memset(data,0,64*sizeof(data[0])); - - diff = t ? stbi__extend_receive(j, t) : 0; - dc = j->img_comp[b].dc_pred + diff; - j->img_comp[b].dc_pred = dc; - data[0] = (short) (dc * dequant[0]); - - // decode AC components, see JPEG spec - k = 1; - do { - unsigned int zig; - int c,r,s; - if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); - c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); - r = fac[c]; - if (r) { // fast-AC path - k += (r >> 4) & 15; // run - s = r & 15; // combined length - j->code_buffer <<= s; - j->code_bits -= s; - // decode into unzigzag'd location - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) ((r >> 8) * dequant[zig]); - } else { - int rs = stbi__jpeg_huff_decode(j, hac); - if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); - s = rs & 15; - r = rs >> 4; - if (s == 0) { - if (rs != 0xf0) break; // end block - k += 16; - } else { - k += r; - // decode into unzigzag'd location - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) (stbi__extend_receive(j,s) * dequant[zig]); - } - } - } while (k < 64); - return 1; -} - -static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__huffman *hdc, int b) -{ - int diff,dc; - int t; - if (j->spec_end != 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - - if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); - - if (j->succ_high == 0) { - // first scan for DC coefficient, must be first - memset(data,0,64*sizeof(data[0])); // 0 all the ac values now - t = stbi__jpeg_huff_decode(j, hdc); - diff = t ? stbi__extend_receive(j, t) : 0; - - dc = j->img_comp[b].dc_pred + diff; - j->img_comp[b].dc_pred = dc; - data[0] = (short) (dc << j->succ_low); - } else { - // refinement scan for DC coefficient - if (stbi__jpeg_get_bit(j)) - data[0] += (short) (1 << j->succ_low); - } - return 1; -} - -// @OPTIMIZE: store non-zigzagged during the decode passes, -// and only de-zigzag when dequantizing -static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__huffman *hac, stbi__int16 *fac) -{ - int k; - if (j->spec_start == 0) return stbi__err("can't merge dc and ac", "Corrupt JPEG"); - - if (j->succ_high == 0) { - int shift = j->succ_low; - - if (j->eob_run) { - --j->eob_run; - return 1; - } - - k = j->spec_start; - do { - unsigned int zig; - int c,r,s; - if (j->code_bits < 16) stbi__grow_buffer_unsafe(j); - c = (j->code_buffer >> (32 - FAST_BITS)) & ((1 << FAST_BITS)-1); - r = fac[c]; - if (r) { // fast-AC path - k += (r >> 4) & 15; // run - s = r & 15; // combined length - j->code_buffer <<= s; - j->code_bits -= s; - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) ((r >> 8) << shift); - } else { - int rs = stbi__jpeg_huff_decode(j, hac); - if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); - s = rs & 15; - r = rs >> 4; - if (s == 0) { - if (r < 15) { - j->eob_run = (1 << r); - if (r) - j->eob_run += stbi__jpeg_get_bits(j, r); - --j->eob_run; - break; - } - k += 16; - } else { - k += r; - zig = stbi__jpeg_dezigzag[k++]; - data[zig] = (short) (stbi__extend_receive(j,s) << shift); - } - } - } while (k <= j->spec_end); - } else { - // refinement scan for these AC coefficients - - short bit = (short) (1 << j->succ_low); - - if (j->eob_run) { - --j->eob_run; - for (k = j->spec_start; k <= j->spec_end; ++k) { - short *p = &data[stbi__jpeg_dezigzag[k]]; - if (*p != 0) - if (stbi__jpeg_get_bit(j)) - if ((*p & bit)==0) { - if (*p > 0) - *p += bit; - else - *p -= bit; - } - } - } else { - k = j->spec_start; - do { - int r,s; - int rs = stbi__jpeg_huff_decode(j, hac); // @OPTIMIZE see if we can use the fast path here, advance-by-r is so slow, eh - if (rs < 0) return stbi__err("bad huffman code","Corrupt JPEG"); - s = rs & 15; - r = rs >> 4; - if (s == 0) { - if (r < 15) { - j->eob_run = (1 << r) - 1; - if (r) - j->eob_run += stbi__jpeg_get_bits(j, r); - r = 64; // force end of block - } else { - // r=15 s=0 should write 16 0s, so we just do - // a run of 15 0s and then write s (which is 0), - // so we don't have to do anything special here - } - } else { - if (s != 1) return stbi__err("bad huffman code", "Corrupt JPEG"); - // sign bit - if (stbi__jpeg_get_bit(j)) - s = bit; - else - s = -bit; - } - - // advance by r - while (k <= j->spec_end) { - short *p = &data[stbi__jpeg_dezigzag[k++]]; - if (*p != 0) { - if (stbi__jpeg_get_bit(j)) - if ((*p & bit)==0) { - if (*p > 0) - *p += bit; - else - *p -= bit; - } - } else { - if (r == 0) { - *p = (short) s; - break; - } - --r; - } - } - } while (k <= j->spec_end); - } - } - return 1; -} - -// take a -128..127 value and stbi__clamp it and convert to 0..255 -stbi_inline static stbi_uc stbi__clamp(int x) -{ - // trick to use a single test to catch both cases - if ((unsigned int) x > 255) { - if (x < 0) return 0; - if (x > 255) return 255; - } - return (stbi_uc) x; -} - -#define stbi__f2f(x) ((int) (((x) * 4096 + 0.5))) -#define stbi__fsh(x) ((x) << 12) - -// derived from jidctint -- DCT_ISLOW -#define STBI__IDCT_1D(s0,s1,s2,s3,s4,s5,s6,s7) \ - int t0,t1,t2,t3,p1,p2,p3,p4,p5,x0,x1,x2,x3; \ - p2 = s2; \ - p3 = s6; \ - p1 = (p2+p3) * stbi__f2f(0.5411961f); \ - t2 = p1 + p3*stbi__f2f(-1.847759065f); \ - t3 = p1 + p2*stbi__f2f( 0.765366865f); \ - p2 = s0; \ - p3 = s4; \ - t0 = stbi__fsh(p2+p3); \ - t1 = stbi__fsh(p2-p3); \ - x0 = t0+t3; \ - x3 = t0-t3; \ - x1 = t1+t2; \ - x2 = t1-t2; \ - t0 = s7; \ - t1 = s5; \ - t2 = s3; \ - t3 = s1; \ - p3 = t0+t2; \ - p4 = t1+t3; \ - p1 = t0+t3; \ - p2 = t1+t2; \ - p5 = (p3+p4)*stbi__f2f( 1.175875602f); \ - t0 = t0*stbi__f2f( 0.298631336f); \ - t1 = t1*stbi__f2f( 2.053119869f); \ - t2 = t2*stbi__f2f( 3.072711026f); \ - t3 = t3*stbi__f2f( 1.501321110f); \ - p1 = p5 + p1*stbi__f2f(-0.899976223f); \ - p2 = p5 + p2*stbi__f2f(-2.562915447f); \ - p3 = p3*stbi__f2f(-1.961570560f); \ - p4 = p4*stbi__f2f(-0.390180644f); \ - t3 += p1+p4; \ - t2 += p2+p3; \ - t1 += p2+p4; \ - t0 += p1+p3; - -static void stbi__idct_block(stbi_uc *out, int out_stride, short data[64]) -{ - int i,val[64],*v=val; - stbi_uc *o; - short *d = data; - - // columns - for (i=0; i < 8; ++i,++d, ++v) { - // if all zeroes, shortcut -- this avoids dequantizing 0s and IDCTing - if (d[ 8]==0 && d[16]==0 && d[24]==0 && d[32]==0 - && d[40]==0 && d[48]==0 && d[56]==0) { - // no shortcut 0 seconds - // (1|2|3|4|5|6|7)==0 0 seconds - // all separate -0.047 seconds - // 1 && 2|3 && 4|5 && 6|7: -0.047 seconds - int dcterm = d[0] << 2; - v[0] = v[8] = v[16] = v[24] = v[32] = v[40] = v[48] = v[56] = dcterm; - } else { - STBI__IDCT_1D(d[ 0],d[ 8],d[16],d[24],d[32],d[40],d[48],d[56]) - // constants scaled things up by 1<<12; let's bring them back - // down, but keep 2 extra bits of precision - x0 += 512; x1 += 512; x2 += 512; x3 += 512; - v[ 0] = (x0+t3) >> 10; - v[56] = (x0-t3) >> 10; - v[ 8] = (x1+t2) >> 10; - v[48] = (x1-t2) >> 10; - v[16] = (x2+t1) >> 10; - v[40] = (x2-t1) >> 10; - v[24] = (x3+t0) >> 10; - v[32] = (x3-t0) >> 10; - } - } - - for (i=0, v=val, o=out; i < 8; ++i,v+=8,o+=out_stride) { - // no fast case since the first 1D IDCT spread components out - STBI__IDCT_1D(v[0],v[1],v[2],v[3],v[4],v[5],v[6],v[7]) - // constants scaled things up by 1<<12, plus we had 1<<2 from first - // loop, plus horizontal and vertical each scale by sqrt(8) so together - // we've got an extra 1<<3, so 1<<17 total we need to remove. - // so we want to round that, which means adding 0.5 * 1<<17, - // aka 65536. Also, we'll end up with -128 to 127 that we want - // to encode as 0..255 by adding 128, so we'll add that before the shift - x0 += 65536 + (128<<17); - x1 += 65536 + (128<<17); - x2 += 65536 + (128<<17); - x3 += 65536 + (128<<17); - // tried computing the shifts into temps, or'ing the temps to see - // if any were out of range, but that was slower - o[0] = stbi__clamp((x0+t3) >> 17); - o[7] = stbi__clamp((x0-t3) >> 17); - o[1] = stbi__clamp((x1+t2) >> 17); - o[6] = stbi__clamp((x1-t2) >> 17); - o[2] = stbi__clamp((x2+t1) >> 17); - o[5] = stbi__clamp((x2-t1) >> 17); - o[3] = stbi__clamp((x3+t0) >> 17); - o[4] = stbi__clamp((x3-t0) >> 17); - } -} - -#ifdef STBI_SSE2 -// sse2 integer IDCT. not the fastest possible implementation but it -// produces bit-identical results to the generic C version so it's -// fully "transparent". -static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) -{ - // This is constructed to match our regular (generic) integer IDCT exactly. - __m128i row0, row1, row2, row3, row4, row5, row6, row7; - __m128i tmp; - - // dot product constant: even elems=x, odd elems=y - #define dct_const(x,y) _mm_setr_epi16((x),(y),(x),(y),(x),(y),(x),(y)) - - // out(0) = c0[even]*x + c0[odd]*y (c0, x, y 16-bit, out 32-bit) - // out(1) = c1[even]*x + c1[odd]*y - #define dct_rot(out0,out1, x,y,c0,c1) \ - __m128i c0##lo = _mm_unpacklo_epi16((x),(y)); \ - __m128i c0##hi = _mm_unpackhi_epi16((x),(y)); \ - __m128i out0##_l = _mm_madd_epi16(c0##lo, c0); \ - __m128i out0##_h = _mm_madd_epi16(c0##hi, c0); \ - __m128i out1##_l = _mm_madd_epi16(c0##lo, c1); \ - __m128i out1##_h = _mm_madd_epi16(c0##hi, c1) - - // out = in << 12 (in 16-bit, out 32-bit) - #define dct_widen(out, in) \ - __m128i out##_l = _mm_srai_epi32(_mm_unpacklo_epi16(_mm_setzero_si128(), (in)), 4); \ - __m128i out##_h = _mm_srai_epi32(_mm_unpackhi_epi16(_mm_setzero_si128(), (in)), 4) - - // wide add - #define dct_wadd(out, a, b) \ - __m128i out##_l = _mm_add_epi32(a##_l, b##_l); \ - __m128i out##_h = _mm_add_epi32(a##_h, b##_h) - - // wide sub - #define dct_wsub(out, a, b) \ - __m128i out##_l = _mm_sub_epi32(a##_l, b##_l); \ - __m128i out##_h = _mm_sub_epi32(a##_h, b##_h) - - // butterfly a/b, add bias, then shift by "s" and pack - #define dct_bfly32o(out0, out1, a,b,bias,s) \ - { \ - __m128i abiased_l = _mm_add_epi32(a##_l, bias); \ - __m128i abiased_h = _mm_add_epi32(a##_h, bias); \ - dct_wadd(sum, abiased, b); \ - dct_wsub(dif, abiased, b); \ - out0 = _mm_packs_epi32(_mm_srai_epi32(sum_l, s), _mm_srai_epi32(sum_h, s)); \ - out1 = _mm_packs_epi32(_mm_srai_epi32(dif_l, s), _mm_srai_epi32(dif_h, s)); \ - } - - // 8-bit interleave step (for transposes) - #define dct_interleave8(a, b) \ - tmp = a; \ - a = _mm_unpacklo_epi8(a, b); \ - b = _mm_unpackhi_epi8(tmp, b) - - // 16-bit interleave step (for transposes) - #define dct_interleave16(a, b) \ - tmp = a; \ - a = _mm_unpacklo_epi16(a, b); \ - b = _mm_unpackhi_epi16(tmp, b) - - #define dct_pass(bias,shift) \ - { \ - /* even part */ \ - dct_rot(t2e,t3e, row2,row6, rot0_0,rot0_1); \ - __m128i sum04 = _mm_add_epi16(row0, row4); \ - __m128i dif04 = _mm_sub_epi16(row0, row4); \ - dct_widen(t0e, sum04); \ - dct_widen(t1e, dif04); \ - dct_wadd(x0, t0e, t3e); \ - dct_wsub(x3, t0e, t3e); \ - dct_wadd(x1, t1e, t2e); \ - dct_wsub(x2, t1e, t2e); \ - /* odd part */ \ - dct_rot(y0o,y2o, row7,row3, rot2_0,rot2_1); \ - dct_rot(y1o,y3o, row5,row1, rot3_0,rot3_1); \ - __m128i sum17 = _mm_add_epi16(row1, row7); \ - __m128i sum35 = _mm_add_epi16(row3, row5); \ - dct_rot(y4o,y5o, sum17,sum35, rot1_0,rot1_1); \ - dct_wadd(x4, y0o, y4o); \ - dct_wadd(x5, y1o, y5o); \ - dct_wadd(x6, y2o, y5o); \ - dct_wadd(x7, y3o, y4o); \ - dct_bfly32o(row0,row7, x0,x7,bias,shift); \ - dct_bfly32o(row1,row6, x1,x6,bias,shift); \ - dct_bfly32o(row2,row5, x2,x5,bias,shift); \ - dct_bfly32o(row3,row4, x3,x4,bias,shift); \ - } - - __m128i rot0_0 = dct_const(stbi__f2f(0.5411961f), stbi__f2f(0.5411961f) + stbi__f2f(-1.847759065f)); - __m128i rot0_1 = dct_const(stbi__f2f(0.5411961f) + stbi__f2f( 0.765366865f), stbi__f2f(0.5411961f)); - __m128i rot1_0 = dct_const(stbi__f2f(1.175875602f) + stbi__f2f(-0.899976223f), stbi__f2f(1.175875602f)); - __m128i rot1_1 = dct_const(stbi__f2f(1.175875602f), stbi__f2f(1.175875602f) + stbi__f2f(-2.562915447f)); - __m128i rot2_0 = dct_const(stbi__f2f(-1.961570560f) + stbi__f2f( 0.298631336f), stbi__f2f(-1.961570560f)); - __m128i rot2_1 = dct_const(stbi__f2f(-1.961570560f), stbi__f2f(-1.961570560f) + stbi__f2f( 3.072711026f)); - __m128i rot3_0 = dct_const(stbi__f2f(-0.390180644f) + stbi__f2f( 2.053119869f), stbi__f2f(-0.390180644f)); - __m128i rot3_1 = dct_const(stbi__f2f(-0.390180644f), stbi__f2f(-0.390180644f) + stbi__f2f( 1.501321110f)); - - // rounding biases in column/row passes, see stbi__idct_block for explanation. - __m128i bias_0 = _mm_set1_epi32(512); - __m128i bias_1 = _mm_set1_epi32(65536 + (128<<17)); - - // load - row0 = _mm_load_si128((const __m128i *) (data + 0*8)); - row1 = _mm_load_si128((const __m128i *) (data + 1*8)); - row2 = _mm_load_si128((const __m128i *) (data + 2*8)); - row3 = _mm_load_si128((const __m128i *) (data + 3*8)); - row4 = _mm_load_si128((const __m128i *) (data + 4*8)); - row5 = _mm_load_si128((const __m128i *) (data + 5*8)); - row6 = _mm_load_si128((const __m128i *) (data + 6*8)); - row7 = _mm_load_si128((const __m128i *) (data + 7*8)); - - // column pass - dct_pass(bias_0, 10); - - { - // 16bit 8x8 transpose pass 1 - dct_interleave16(row0, row4); - dct_interleave16(row1, row5); - dct_interleave16(row2, row6); - dct_interleave16(row3, row7); - - // transpose pass 2 - dct_interleave16(row0, row2); - dct_interleave16(row1, row3); - dct_interleave16(row4, row6); - dct_interleave16(row5, row7); - - // transpose pass 3 - dct_interleave16(row0, row1); - dct_interleave16(row2, row3); - dct_interleave16(row4, row5); - dct_interleave16(row6, row7); - } - - // row pass - dct_pass(bias_1, 17); - - { - // pack - __m128i p0 = _mm_packus_epi16(row0, row1); // a0a1a2a3...a7b0b1b2b3...b7 - __m128i p1 = _mm_packus_epi16(row2, row3); - __m128i p2 = _mm_packus_epi16(row4, row5); - __m128i p3 = _mm_packus_epi16(row6, row7); - - // 8bit 8x8 transpose pass 1 - dct_interleave8(p0, p2); // a0e0a1e1... - dct_interleave8(p1, p3); // c0g0c1g1... - - // transpose pass 2 - dct_interleave8(p0, p1); // a0c0e0g0... - dct_interleave8(p2, p3); // b0d0f0h0... - - // transpose pass 3 - dct_interleave8(p0, p2); // a0b0c0d0... - dct_interleave8(p1, p3); // a4b4c4d4... - - // store - _mm_storel_epi64((__m128i *) out, p0); out += out_stride; - _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p0, 0x4e)); out += out_stride; - _mm_storel_epi64((__m128i *) out, p2); out += out_stride; - _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p2, 0x4e)); out += out_stride; - _mm_storel_epi64((__m128i *) out, p1); out += out_stride; - _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p1, 0x4e)); out += out_stride; - _mm_storel_epi64((__m128i *) out, p3); out += out_stride; - _mm_storel_epi64((__m128i *) out, _mm_shuffle_epi32(p3, 0x4e)); - } - -#undef dct_const -#undef dct_rot -#undef dct_widen -#undef dct_wadd -#undef dct_wsub -#undef dct_bfly32o -#undef dct_interleave8 -#undef dct_interleave16 -#undef dct_pass -} - -#endif // STBI_SSE2 - -#ifdef STBI_NEON - -// NEON integer IDCT. should produce bit-identical -// results to the generic C version. -static void stbi__idct_simd(stbi_uc *out, int out_stride, short data[64]) -{ - int16x8_t row0, row1, row2, row3, row4, row5, row6, row7; - - int16x4_t rot0_0 = vdup_n_s16(stbi__f2f(0.5411961f)); - int16x4_t rot0_1 = vdup_n_s16(stbi__f2f(-1.847759065f)); - int16x4_t rot0_2 = vdup_n_s16(stbi__f2f( 0.765366865f)); - int16x4_t rot1_0 = vdup_n_s16(stbi__f2f( 1.175875602f)); - int16x4_t rot1_1 = vdup_n_s16(stbi__f2f(-0.899976223f)); - int16x4_t rot1_2 = vdup_n_s16(stbi__f2f(-2.562915447f)); - int16x4_t rot2_0 = vdup_n_s16(stbi__f2f(-1.961570560f)); - int16x4_t rot2_1 = vdup_n_s16(stbi__f2f(-0.390180644f)); - int16x4_t rot3_0 = vdup_n_s16(stbi__f2f( 0.298631336f)); - int16x4_t rot3_1 = vdup_n_s16(stbi__f2f( 2.053119869f)); - int16x4_t rot3_2 = vdup_n_s16(stbi__f2f( 3.072711026f)); - int16x4_t rot3_3 = vdup_n_s16(stbi__f2f( 1.501321110f)); - -#define dct_long_mul(out, inq, coeff) \ - int32x4_t out##_l = vmull_s16(vget_low_s16(inq), coeff); \ - int32x4_t out##_h = vmull_s16(vget_high_s16(inq), coeff) - -#define dct_long_mac(out, acc, inq, coeff) \ - int32x4_t out##_l = vmlal_s16(acc##_l, vget_low_s16(inq), coeff); \ - int32x4_t out##_h = vmlal_s16(acc##_h, vget_high_s16(inq), coeff) - -#define dct_widen(out, inq) \ - int32x4_t out##_l = vshll_n_s16(vget_low_s16(inq), 12); \ - int32x4_t out##_h = vshll_n_s16(vget_high_s16(inq), 12) - -// wide add -#define dct_wadd(out, a, b) \ - int32x4_t out##_l = vaddq_s32(a##_l, b##_l); \ - int32x4_t out##_h = vaddq_s32(a##_h, b##_h) - -// wide sub -#define dct_wsub(out, a, b) \ - int32x4_t out##_l = vsubq_s32(a##_l, b##_l); \ - int32x4_t out##_h = vsubq_s32(a##_h, b##_h) - -// butterfly a/b, then shift using "shiftop" by "s" and pack -#define dct_bfly32o(out0,out1, a,b,shiftop,s) \ - { \ - dct_wadd(sum, a, b); \ - dct_wsub(dif, a, b); \ - out0 = vcombine_s16(shiftop(sum_l, s), shiftop(sum_h, s)); \ - out1 = vcombine_s16(shiftop(dif_l, s), shiftop(dif_h, s)); \ - } - -#define dct_pass(shiftop, shift) \ - { \ - /* even part */ \ - int16x8_t sum26 = vaddq_s16(row2, row6); \ - dct_long_mul(p1e, sum26, rot0_0); \ - dct_long_mac(t2e, p1e, row6, rot0_1); \ - dct_long_mac(t3e, p1e, row2, rot0_2); \ - int16x8_t sum04 = vaddq_s16(row0, row4); \ - int16x8_t dif04 = vsubq_s16(row0, row4); \ - dct_widen(t0e, sum04); \ - dct_widen(t1e, dif04); \ - dct_wadd(x0, t0e, t3e); \ - dct_wsub(x3, t0e, t3e); \ - dct_wadd(x1, t1e, t2e); \ - dct_wsub(x2, t1e, t2e); \ - /* odd part */ \ - int16x8_t sum15 = vaddq_s16(row1, row5); \ - int16x8_t sum17 = vaddq_s16(row1, row7); \ - int16x8_t sum35 = vaddq_s16(row3, row5); \ - int16x8_t sum37 = vaddq_s16(row3, row7); \ - int16x8_t sumodd = vaddq_s16(sum17, sum35); \ - dct_long_mul(p5o, sumodd, rot1_0); \ - dct_long_mac(p1o, p5o, sum17, rot1_1); \ - dct_long_mac(p2o, p5o, sum35, rot1_2); \ - dct_long_mul(p3o, sum37, rot2_0); \ - dct_long_mul(p4o, sum15, rot2_1); \ - dct_wadd(sump13o, p1o, p3o); \ - dct_wadd(sump24o, p2o, p4o); \ - dct_wadd(sump23o, p2o, p3o); \ - dct_wadd(sump14o, p1o, p4o); \ - dct_long_mac(x4, sump13o, row7, rot3_0); \ - dct_long_mac(x5, sump24o, row5, rot3_1); \ - dct_long_mac(x6, sump23o, row3, rot3_2); \ - dct_long_mac(x7, sump14o, row1, rot3_3); \ - dct_bfly32o(row0,row7, x0,x7,shiftop,shift); \ - dct_bfly32o(row1,row6, x1,x6,shiftop,shift); \ - dct_bfly32o(row2,row5, x2,x5,shiftop,shift); \ - dct_bfly32o(row3,row4, x3,x4,shiftop,shift); \ - } - - // load - row0 = vld1q_s16(data + 0*8); - row1 = vld1q_s16(data + 1*8); - row2 = vld1q_s16(data + 2*8); - row3 = vld1q_s16(data + 3*8); - row4 = vld1q_s16(data + 4*8); - row5 = vld1q_s16(data + 5*8); - row6 = vld1q_s16(data + 6*8); - row7 = vld1q_s16(data + 7*8); - - // add DC bias - row0 = vaddq_s16(row0, vsetq_lane_s16(1024, vdupq_n_s16(0), 0)); - - // column pass - dct_pass(vrshrn_n_s32, 10); - - // 16bit 8x8 transpose - { -// these three map to a single VTRN.16, VTRN.32, and VSWP, respectively. -// whether compilers actually get this is another story, sadly. -#define dct_trn16(x, y) { int16x8x2_t t = vtrnq_s16(x, y); x = t.val[0]; y = t.val[1]; } -#define dct_trn32(x, y) { int32x4x2_t t = vtrnq_s32(vreinterpretq_s32_s16(x), vreinterpretq_s32_s16(y)); x = vreinterpretq_s16_s32(t.val[0]); y = vreinterpretq_s16_s32(t.val[1]); } -#define dct_trn64(x, y) { int16x8_t x0 = x; int16x8_t y0 = y; x = vcombine_s16(vget_low_s16(x0), vget_low_s16(y0)); y = vcombine_s16(vget_high_s16(x0), vget_high_s16(y0)); } - - // pass 1 - dct_trn16(row0, row1); // a0b0a2b2a4b4a6b6 - dct_trn16(row2, row3); - dct_trn16(row4, row5); - dct_trn16(row6, row7); - - // pass 2 - dct_trn32(row0, row2); // a0b0c0d0a4b4c4d4 - dct_trn32(row1, row3); - dct_trn32(row4, row6); - dct_trn32(row5, row7); - - // pass 3 - dct_trn64(row0, row4); // a0b0c0d0e0f0g0h0 - dct_trn64(row1, row5); - dct_trn64(row2, row6); - dct_trn64(row3, row7); - -#undef dct_trn16 -#undef dct_trn32 -#undef dct_trn64 - } - - // row pass - // vrshrn_n_s32 only supports shifts up to 16, we need - // 17. so do a non-rounding shift of 16 first then follow - // up with a rounding shift by 1. - dct_pass(vshrn_n_s32, 16); - - { - // pack and round - uint8x8_t p0 = vqrshrun_n_s16(row0, 1); - uint8x8_t p1 = vqrshrun_n_s16(row1, 1); - uint8x8_t p2 = vqrshrun_n_s16(row2, 1); - uint8x8_t p3 = vqrshrun_n_s16(row3, 1); - uint8x8_t p4 = vqrshrun_n_s16(row4, 1); - uint8x8_t p5 = vqrshrun_n_s16(row5, 1); - uint8x8_t p6 = vqrshrun_n_s16(row6, 1); - uint8x8_t p7 = vqrshrun_n_s16(row7, 1); - - // again, these can translate into one instruction, but often don't. -#define dct_trn8_8(x, y) { uint8x8x2_t t = vtrn_u8(x, y); x = t.val[0]; y = t.val[1]; } -#define dct_trn8_16(x, y) { uint16x4x2_t t = vtrn_u16(vreinterpret_u16_u8(x), vreinterpret_u16_u8(y)); x = vreinterpret_u8_u16(t.val[0]); y = vreinterpret_u8_u16(t.val[1]); } -#define dct_trn8_32(x, y) { uint32x2x2_t t = vtrn_u32(vreinterpret_u32_u8(x), vreinterpret_u32_u8(y)); x = vreinterpret_u8_u32(t.val[0]); y = vreinterpret_u8_u32(t.val[1]); } - - // sadly can't use interleaved stores here since we only write - // 8 bytes to each scan line! - - // 8x8 8-bit transpose pass 1 - dct_trn8_8(p0, p1); - dct_trn8_8(p2, p3); - dct_trn8_8(p4, p5); - dct_trn8_8(p6, p7); - - // pass 2 - dct_trn8_16(p0, p2); - dct_trn8_16(p1, p3); - dct_trn8_16(p4, p6); - dct_trn8_16(p5, p7); - - // pass 3 - dct_trn8_32(p0, p4); - dct_trn8_32(p1, p5); - dct_trn8_32(p2, p6); - dct_trn8_32(p3, p7); - - // store - vst1_u8(out, p0); out += out_stride; - vst1_u8(out, p1); out += out_stride; - vst1_u8(out, p2); out += out_stride; - vst1_u8(out, p3); out += out_stride; - vst1_u8(out, p4); out += out_stride; - vst1_u8(out, p5); out += out_stride; - vst1_u8(out, p6); out += out_stride; - vst1_u8(out, p7); - -#undef dct_trn8_8 -#undef dct_trn8_16 -#undef dct_trn8_32 - } - -#undef dct_long_mul -#undef dct_long_mac -#undef dct_widen -#undef dct_wadd -#undef dct_wsub -#undef dct_bfly32o -#undef dct_pass -} - -#endif // STBI_NEON - -#define STBI__MARKER_none 0xff -// if there's a pending marker from the entropy stream, return that -// otherwise, fetch from the stream and get a marker. if there's no -// marker, return 0xff, which is never a valid marker value -static stbi_uc stbi__get_marker(stbi__jpeg *j) -{ - stbi_uc x; - if (j->marker != STBI__MARKER_none) { x = j->marker; j->marker = STBI__MARKER_none; return x; } - x = stbi__get8(j->s); - if (x != 0xff) return STBI__MARKER_none; - while (x == 0xff) - x = stbi__get8(j->s); - return x; -} - -// in each scan, we'll have scan_n components, and the order -// of the components is specified by order[] -#define STBI__RESTART(x) ((x) >= 0xd0 && (x) <= 0xd7) - -// after a restart interval, stbi__jpeg_reset the entropy decoder and -// the dc prediction -static void stbi__jpeg_reset(stbi__jpeg *j) -{ - j->code_bits = 0; - j->code_buffer = 0; - j->nomore = 0; - j->img_comp[0].dc_pred = j->img_comp[1].dc_pred = j->img_comp[2].dc_pred = 0; - j->marker = STBI__MARKER_none; - j->todo = j->restart_interval ? j->restart_interval : 0x7fffffff; - j->eob_run = 0; - // no more than 1<<31 MCUs if no restart_interal? that's plenty safe, - // since we don't even allow 1<<30 pixels -} - -static int stbi__parse_entropy_coded_data(stbi__jpeg *z) -{ - stbi__jpeg_reset(z); - if (!z->progressive) { - if (z->scan_n == 1) { - int i,j; - STBI_SIMD_ALIGN(short, data[64]); - int n = z->order[0]; - // non-interleaved data, we just need to process one block at a time, - // in trivial scanline order - // number of blocks to do just depends on how many actual "pixels" this - // component has, independent of interleaved MCU blocking and such - int w = (z->img_comp[n].x+7) >> 3; - int h = (z->img_comp[n].y+7) >> 3; - for (j=0; j < h; ++j) { - for (i=0; i < w; ++i) { - int ha = z->img_comp[n].ha; - if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; - z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); - // every data block is an MCU, so countdown the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); - // if it's NOT a restart, then just bail, so we get corrupt data - // rather than no data - if (!STBI__RESTART(z->marker)) return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } else { // interleaved - int i,j,k,x,y; - STBI_SIMD_ALIGN(short, data[64]); - for (j=0; j < z->img_mcu_y; ++j) { - for (i=0; i < z->img_mcu_x; ++i) { - // scan an interleaved mcu... process scan_n components in order - for (k=0; k < z->scan_n; ++k) { - int n = z->order[k]; - // scan out an mcu's worth of this component; that's just determined - // by the basic H and V specified for the component - for (y=0; y < z->img_comp[n].v; ++y) { - for (x=0; x < z->img_comp[n].h; ++x) { - int x2 = (i*z->img_comp[n].h + x)*8; - int y2 = (j*z->img_comp[n].v + y)*8; - int ha = z->img_comp[n].ha; - if (!stbi__jpeg_decode_block(z, data, z->huff_dc+z->img_comp[n].hd, z->huff_ac+ha, z->fast_ac[ha], n, z->dequant[z->img_comp[n].tq])) return 0; - z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*y2+x2, z->img_comp[n].w2, data); - } - } - } - // after all interleaved components, that's an interleaved MCU, - // so now count down the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); - if (!STBI__RESTART(z->marker)) return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } - } else { - if (z->scan_n == 1) { - int i,j; - int n = z->order[0]; - // non-interleaved data, we just need to process one block at a time, - // in trivial scanline order - // number of blocks to do just depends on how many actual "pixels" this - // component has, independent of interleaved MCU blocking and such - int w = (z->img_comp[n].x+7) >> 3; - int h = (z->img_comp[n].y+7) >> 3; - for (j=0; j < h; ++j) { - for (i=0; i < w; ++i) { - short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); - if (z->spec_start == 0) { - if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) - return 0; - } else { - int ha = z->img_comp[n].ha; - if (!stbi__jpeg_decode_block_prog_ac(z, data, &z->huff_ac[ha], z->fast_ac[ha])) - return 0; - } - // every data block is an MCU, so countdown the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); - if (!STBI__RESTART(z->marker)) return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } else { // interleaved - int i,j,k,x,y; - for (j=0; j < z->img_mcu_y; ++j) { - for (i=0; i < z->img_mcu_x; ++i) { - // scan an interleaved mcu... process scan_n components in order - for (k=0; k < z->scan_n; ++k) { - int n = z->order[k]; - // scan out an mcu's worth of this component; that's just determined - // by the basic H and V specified for the component - for (y=0; y < z->img_comp[n].v; ++y) { - for (x=0; x < z->img_comp[n].h; ++x) { - int x2 = (i*z->img_comp[n].h + x); - int y2 = (j*z->img_comp[n].v + y); - short *data = z->img_comp[n].coeff + 64 * (x2 + y2 * z->img_comp[n].coeff_w); - if (!stbi__jpeg_decode_block_prog_dc(z, data, &z->huff_dc[z->img_comp[n].hd], n)) - return 0; - } - } - } - // after all interleaved components, that's an interleaved MCU, - // so now count down the restart interval - if (--z->todo <= 0) { - if (z->code_bits < 24) stbi__grow_buffer_unsafe(z); - if (!STBI__RESTART(z->marker)) return 1; - stbi__jpeg_reset(z); - } - } - } - return 1; - } - } -} - -static void stbi__jpeg_dequantize(short *data, stbi_uc *dequant) -{ - int i; - for (i=0; i < 64; ++i) - data[i] *= dequant[i]; -} - -static void stbi__jpeg_finish(stbi__jpeg *z) -{ - if (z->progressive) { - // dequantize and idct the data - int i,j,n; - for (n=0; n < z->s->img_n; ++n) { - int w = (z->img_comp[n].x+7) >> 3; - int h = (z->img_comp[n].y+7) >> 3; - for (j=0; j < h; ++j) { - for (i=0; i < w; ++i) { - short *data = z->img_comp[n].coeff + 64 * (i + j * z->img_comp[n].coeff_w); - stbi__jpeg_dequantize(data, z->dequant[z->img_comp[n].tq]); - z->idct_block_kernel(z->img_comp[n].data+z->img_comp[n].w2*j*8+i*8, z->img_comp[n].w2, data); - } - } - } - } -} - -static int stbi__process_marker(stbi__jpeg *z, int m) -{ - int L; - switch (m) { - case STBI__MARKER_none: // no marker found - return stbi__err("expected marker","Corrupt JPEG"); - - case 0xDD: // DRI - specify restart interval - if (stbi__get16be(z->s) != 4) return stbi__err("bad DRI len","Corrupt JPEG"); - z->restart_interval = stbi__get16be(z->s); - return 1; - - case 0xDB: // DQT - define quantization table - L = stbi__get16be(z->s)-2; - while (L > 0) { - int q = stbi__get8(z->s); - int p = q >> 4; - int t = q & 15,i; - if (p != 0) return stbi__err("bad DQT type","Corrupt JPEG"); - if (t > 3) return stbi__err("bad DQT table","Corrupt JPEG"); - for (i=0; i < 64; ++i) - z->dequant[t][stbi__jpeg_dezigzag[i]] = stbi__get8(z->s); - L -= 65; - } - return L==0; - - case 0xC4: // DHT - define huffman table - L = stbi__get16be(z->s)-2; - while (L > 0) { - stbi_uc *v; - int sizes[16],i,n=0; - int q = stbi__get8(z->s); - int tc = q >> 4; - int th = q & 15; - if (tc > 1 || th > 3) return stbi__err("bad DHT header","Corrupt JPEG"); - for (i=0; i < 16; ++i) { - sizes[i] = stbi__get8(z->s); - n += sizes[i]; - } - L -= 17; - if (tc == 0) { - if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0; - v = z->huff_dc[th].values; - } else { - if (!stbi__build_huffman(z->huff_ac+th, sizes)) return 0; - v = z->huff_ac[th].values; - } - for (i=0; i < n; ++i) - v[i] = stbi__get8(z->s); - if (tc != 0) - stbi__build_fast_ac(z->fast_ac[th], z->huff_ac + th); - L -= n; - } - return L==0; - } - // check for comment block or APP blocks - if ((m >= 0xE0 && m <= 0xEF) || m == 0xFE) { - stbi__skip(z->s, stbi__get16be(z->s)-2); - return 1; - } - return 0; -} - -// after we see SOS -static int stbi__process_scan_header(stbi__jpeg *z) -{ - int i; - int Ls = stbi__get16be(z->s); - z->scan_n = stbi__get8(z->s); - if (z->scan_n < 1 || z->scan_n > 4 || z->scan_n > (int) z->s->img_n) return stbi__err("bad SOS component count","Corrupt JPEG"); - if (Ls != 6+2*z->scan_n) return stbi__err("bad SOS len","Corrupt JPEG"); - for (i=0; i < z->scan_n; ++i) { - int id = stbi__get8(z->s), which; - int q = stbi__get8(z->s); - for (which = 0; which < z->s->img_n; ++which) - if (z->img_comp[which].id == id) - break; - if (which == z->s->img_n) return 0; // no match - z->img_comp[which].hd = q >> 4; if (z->img_comp[which].hd > 3) return stbi__err("bad DC huff","Corrupt JPEG"); - z->img_comp[which].ha = q & 15; if (z->img_comp[which].ha > 3) return stbi__err("bad AC huff","Corrupt JPEG"); - z->order[i] = which; - } - - { - int aa; - z->spec_start = stbi__get8(z->s); - z->spec_end = stbi__get8(z->s); // should be 63, but might be 0 - aa = stbi__get8(z->s); - z->succ_high = (aa >> 4); - z->succ_low = (aa & 15); - if (z->progressive) { - if (z->spec_start > 63 || z->spec_end > 63 || z->spec_start > z->spec_end || z->succ_high > 13 || z->succ_low > 13) - return stbi__err("bad SOS", "Corrupt JPEG"); - } else { - if (z->spec_start != 0) return stbi__err("bad SOS","Corrupt JPEG"); - if (z->succ_high != 0 || z->succ_low != 0) return stbi__err("bad SOS","Corrupt JPEG"); - z->spec_end = 63; - } - } - - return 1; -} - -static int stbi__process_frame_header(stbi__jpeg *z, int scan) -{ - stbi__context *s = z->s; - int Lf,p,i,q, h_max=1,v_max=1,c; - Lf = stbi__get16be(s); if (Lf < 11) return stbi__err("bad SOF len","Corrupt JPEG"); // JPEG - p = stbi__get8(s); if (p != 8) return stbi__err("only 8-bit","JPEG format not supported: 8-bit only"); // JPEG baseline - s->img_y = stbi__get16be(s); if (s->img_y == 0) return stbi__err("no header height", "JPEG format not supported: delayed height"); // Legal, but we don't handle it--but neither does IJG - s->img_x = stbi__get16be(s); if (s->img_x == 0) return stbi__err("0 width","Corrupt JPEG"); // JPEG requires - c = stbi__get8(s); - if (c != 3 && c != 1) return stbi__err("bad component count","Corrupt JPEG"); // JFIF requires - s->img_n = c; - for (i=0; i < c; ++i) { - z->img_comp[i].data = NULL; - z->img_comp[i].linebuf = NULL; - } - - if (Lf != 8+3*s->img_n) return stbi__err("bad SOF len","Corrupt JPEG"); - - for (i=0; i < s->img_n; ++i) { - z->img_comp[i].id = stbi__get8(s); - if (z->img_comp[i].id != i+1) // JFIF requires - if (z->img_comp[i].id != i) // some version of jpegtran outputs non-JFIF-compliant files! - return stbi__err("bad component ID","Corrupt JPEG"); - q = stbi__get8(s); - z->img_comp[i].h = (q >> 4); if (!z->img_comp[i].h || z->img_comp[i].h > 4) return stbi__err("bad H","Corrupt JPEG"); - z->img_comp[i].v = q & 15; if (!z->img_comp[i].v || z->img_comp[i].v > 4) return stbi__err("bad V","Corrupt JPEG"); - z->img_comp[i].tq = stbi__get8(s); if (z->img_comp[i].tq > 3) return stbi__err("bad TQ","Corrupt JPEG"); - } - - if (scan != STBI__SCAN_load) return 1; - - if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); - - for (i=0; i < s->img_n; ++i) { - if (z->img_comp[i].h > h_max) h_max = z->img_comp[i].h; - if (z->img_comp[i].v > v_max) v_max = z->img_comp[i].v; - } - - // compute interleaved mcu info - z->img_h_max = h_max; - z->img_v_max = v_max; - z->img_mcu_w = h_max * 8; - z->img_mcu_h = v_max * 8; - z->img_mcu_x = (s->img_x + z->img_mcu_w-1) / z->img_mcu_w; - z->img_mcu_y = (s->img_y + z->img_mcu_h-1) / z->img_mcu_h; - - for (i=0; i < s->img_n; ++i) { - // number of effective pixels (e.g. for non-interleaved MCU) - z->img_comp[i].x = (s->img_x * z->img_comp[i].h + h_max-1) / h_max; - z->img_comp[i].y = (s->img_y * z->img_comp[i].v + v_max-1) / v_max; - // to simplify generation, we'll allocate enough memory to decode - // the bogus oversized data from using interleaved MCUs and their - // big blocks (e.g. a 16x16 iMCU on an image of width 33); we won't - // discard the extra data until colorspace conversion - z->img_comp[i].w2 = z->img_mcu_x * z->img_comp[i].h * 8; - z->img_comp[i].h2 = z->img_mcu_y * z->img_comp[i].v * 8; - z->img_comp[i].raw_data = stbi__malloc(z->img_comp[i].w2 * z->img_comp[i].h2+15); - - if (z->img_comp[i].raw_data == NULL) { - for(--i; i >= 0; --i) { - STBI_FREE(z->img_comp[i].raw_data); - z->img_comp[i].raw_data = NULL; - } - return stbi__err("outofmem", "Out of memory"); - } - // align blocks for idct using mmx/sse - z->img_comp[i].data = (stbi_uc*) (((size_t) z->img_comp[i].raw_data + 15) & ~15); - z->img_comp[i].linebuf = NULL; - if (z->progressive) { - z->img_comp[i].coeff_w = (z->img_comp[i].w2 + 7) >> 3; - z->img_comp[i].coeff_h = (z->img_comp[i].h2 + 7) >> 3; - z->img_comp[i].raw_coeff = STBI_MALLOC(z->img_comp[i].coeff_w * z->img_comp[i].coeff_h * 64 * sizeof(short) + 15); - z->img_comp[i].coeff = (short*) (((size_t) z->img_comp[i].raw_coeff + 15) & ~15); - } else { - z->img_comp[i].coeff = 0; - z->img_comp[i].raw_coeff = 0; - } - } - - return 1; -} - -// use comparisons since in some cases we handle more than one case (e.g. SOF) -#define stbi__DNL(x) ((x) == 0xdc) -#define stbi__SOI(x) ((x) == 0xd8) -#define stbi__EOI(x) ((x) == 0xd9) -#define stbi__SOF(x) ((x) == 0xc0 || (x) == 0xc1 || (x) == 0xc2) -#define stbi__SOS(x) ((x) == 0xda) - -#define stbi__SOF_progressive(x) ((x) == 0xc2) - -static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan) -{ - int m; - z->marker = STBI__MARKER_none; // initialize cached marker to empty - m = stbi__get_marker(z); - if (!stbi__SOI(m)) return stbi__err("no SOI","Corrupt JPEG"); - if (scan == STBI__SCAN_type) return 1; - m = stbi__get_marker(z); - while (!stbi__SOF(m)) { - if (!stbi__process_marker(z,m)) return 0; - m = stbi__get_marker(z); - while (m == STBI__MARKER_none) { - // some files have extra padding after their blocks, so ok, we'll scan - if (stbi__at_eof(z->s)) return stbi__err("no SOF", "Corrupt JPEG"); - m = stbi__get_marker(z); - } - } - z->progressive = stbi__SOF_progressive(m); - if (!stbi__process_frame_header(z, scan)) return 0; - return 1; -} - -// decode image to YCbCr format -static int stbi__decode_jpeg_image(stbi__jpeg *j) -{ - int m; - for (m = 0; m < 4; m++) { - j->img_comp[m].raw_data = NULL; - j->img_comp[m].raw_coeff = NULL; - } - j->restart_interval = 0; - if (!stbi__decode_jpeg_header(j, STBI__SCAN_load)) return 0; - m = stbi__get_marker(j); - while (!stbi__EOI(m)) { - if (stbi__SOS(m)) { - if (!stbi__process_scan_header(j)) return 0; - if (!stbi__parse_entropy_coded_data(j)) return 0; - if (j->marker == STBI__MARKER_none ) { - // handle 0s at the end of image data from IP Kamera 9060 - while (!stbi__at_eof(j->s)) { - int x = stbi__get8(j->s); - if (x == 255) { - j->marker = stbi__get8(j->s); - break; - } else if (x != 0) { - return stbi__err("junk before marker", "Corrupt JPEG"); - } - } - // if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0 - } - } else { - if (!stbi__process_marker(j, m)) return 0; - } - m = stbi__get_marker(j); - } - if (j->progressive) - stbi__jpeg_finish(j); - return 1; -} - -// static jfif-centered resampling (across block boundaries) - -typedef stbi_uc *(*resample_row_func)(stbi_uc *out, stbi_uc *in0, stbi_uc *in1, - int w, int hs); - -#define stbi__div4(x) ((stbi_uc) ((x) >> 2)) - -static stbi_uc *resample_row_1(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - STBI_NOTUSED(out); - STBI_NOTUSED(in_far); - STBI_NOTUSED(w); - STBI_NOTUSED(hs); - return in_near; -} - -static stbi_uc* stbi__resample_row_v_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - // need to generate two samples vertically for every one in input - int i; - STBI_NOTUSED(hs); - for (i=0; i < w; ++i) - out[i] = stbi__div4(3*in_near[i] + in_far[i] + 2); - return out; -} - -static stbi_uc* stbi__resample_row_h_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - // need to generate two samples horizontally for every one in input - int i; - stbi_uc *input = in_near; - - if (w == 1) { - // if only one sample, can't do any interpolation - out[0] = out[1] = input[0]; - return out; - } - - out[0] = input[0]; - out[1] = stbi__div4(input[0]*3 + input[1] + 2); - for (i=1; i < w-1; ++i) { - int n = 3*input[i]+2; - out[i*2+0] = stbi__div4(n+input[i-1]); - out[i*2+1] = stbi__div4(n+input[i+1]); - } - out[i*2+0] = stbi__div4(input[w-2]*3 + input[w-1] + 2); - out[i*2+1] = input[w-1]; - - STBI_NOTUSED(in_far); - STBI_NOTUSED(hs); - - return out; -} - -#define stbi__div16(x) ((stbi_uc) ((x) >> 4)) - -static stbi_uc *stbi__resample_row_hv_2(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - // need to generate 2x2 samples for every one in input - int i,t0,t1; - if (w == 1) { - out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); - return out; - } - - t1 = 3*in_near[0] + in_far[0]; - out[0] = stbi__div4(t1+2); - for (i=1; i < w; ++i) { - t0 = t1; - t1 = 3*in_near[i]+in_far[i]; - out[i*2-1] = stbi__div16(3*t0 + t1 + 8); - out[i*2 ] = stbi__div16(3*t1 + t0 + 8); - } - out[w*2-1] = stbi__div4(t1+2); - - STBI_NOTUSED(hs); - - return out; -} - -#if defined(STBI_SSE2) || defined(STBI_NEON) -static stbi_uc *stbi__resample_row_hv_2_simd(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - // need to generate 2x2 samples for every one in input - int i=0,t0,t1; - - if (w == 1) { - out[0] = out[1] = stbi__div4(3*in_near[0] + in_far[0] + 2); - return out; - } - - t1 = 3*in_near[0] + in_far[0]; - // process groups of 8 pixels for as long as we can. - // note we can't handle the last pixel in a row in this loop - // because we need to handle the filter boundary conditions. - for (; i < ((w-1) & ~7); i += 8) { -#if defined(STBI_SSE2) - // load and perform the vertical filtering pass - // this uses 3*x + y = 4*x + (y - x) - __m128i zero = _mm_setzero_si128(); - __m128i farb = _mm_loadl_epi64((__m128i *) (in_far + i)); - __m128i nearb = _mm_loadl_epi64((__m128i *) (in_near + i)); - __m128i farw = _mm_unpacklo_epi8(farb, zero); - __m128i nearw = _mm_unpacklo_epi8(nearb, zero); - __m128i diff = _mm_sub_epi16(farw, nearw); - __m128i nears = _mm_slli_epi16(nearw, 2); - __m128i curr = _mm_add_epi16(nears, diff); // current row - - // horizontal filter works the same based on shifted vers of current - // row. "prev" is current row shifted right by 1 pixel; we need to - // insert the previous pixel value (from t1). - // "next" is current row shifted left by 1 pixel, with first pixel - // of next block of 8 pixels added in. - __m128i prv0 = _mm_slli_si128(curr, 2); - __m128i nxt0 = _mm_srli_si128(curr, 2); - __m128i prev = _mm_insert_epi16(prv0, t1, 0); - __m128i next = _mm_insert_epi16(nxt0, 3*in_near[i+8] + in_far[i+8], 7); - - // horizontal filter, polyphase implementation since it's convenient: - // even pixels = 3*cur + prev = cur*4 + (prev - cur) - // odd pixels = 3*cur + next = cur*4 + (next - cur) - // note the shared term. - __m128i bias = _mm_set1_epi16(8); - __m128i curs = _mm_slli_epi16(curr, 2); - __m128i prvd = _mm_sub_epi16(prev, curr); - __m128i nxtd = _mm_sub_epi16(next, curr); - __m128i curb = _mm_add_epi16(curs, bias); - __m128i even = _mm_add_epi16(prvd, curb); - __m128i odd = _mm_add_epi16(nxtd, curb); - - // interleave even and odd pixels, then undo scaling. - __m128i int0 = _mm_unpacklo_epi16(even, odd); - __m128i int1 = _mm_unpackhi_epi16(even, odd); - __m128i de0 = _mm_srli_epi16(int0, 4); - __m128i de1 = _mm_srli_epi16(int1, 4); - - // pack and write output - __m128i outv = _mm_packus_epi16(de0, de1); - _mm_storeu_si128((__m128i *) (out + i*2), outv); -#elif defined(STBI_NEON) - // load and perform the vertical filtering pass - // this uses 3*x + y = 4*x + (y - x) - uint8x8_t farb = vld1_u8(in_far + i); - uint8x8_t nearb = vld1_u8(in_near + i); - int16x8_t diff = vreinterpretq_s16_u16(vsubl_u8(farb, nearb)); - int16x8_t nears = vreinterpretq_s16_u16(vshll_n_u8(nearb, 2)); - int16x8_t curr = vaddq_s16(nears, diff); // current row - - // horizontal filter works the same based on shifted vers of current - // row. "prev" is current row shifted right by 1 pixel; we need to - // insert the previous pixel value (from t1). - // "next" is current row shifted left by 1 pixel, with first pixel - // of next block of 8 pixels added in. - int16x8_t prv0 = vextq_s16(curr, curr, 7); - int16x8_t nxt0 = vextq_s16(curr, curr, 1); - int16x8_t prev = vsetq_lane_s16(t1, prv0, 0); - int16x8_t next = vsetq_lane_s16(3*in_near[i+8] + in_far[i+8], nxt0, 7); - - // horizontal filter, polyphase implementation since it's convenient: - // even pixels = 3*cur + prev = cur*4 + (prev - cur) - // odd pixels = 3*cur + next = cur*4 + (next - cur) - // note the shared term. - int16x8_t curs = vshlq_n_s16(curr, 2); - int16x8_t prvd = vsubq_s16(prev, curr); - int16x8_t nxtd = vsubq_s16(next, curr); - int16x8_t even = vaddq_s16(curs, prvd); - int16x8_t odd = vaddq_s16(curs, nxtd); - - // undo scaling and round, then store with even/odd phases interleaved - uint8x8x2_t o; - o.val[0] = vqrshrun_n_s16(even, 4); - o.val[1] = vqrshrun_n_s16(odd, 4); - vst2_u8(out + i*2, o); -#endif - - // "previous" value for next iter - t1 = 3*in_near[i+7] + in_far[i+7]; - } - - t0 = t1; - t1 = 3*in_near[i] + in_far[i]; - out[i*2] = stbi__div16(3*t1 + t0 + 8); - - for (++i; i < w; ++i) { - t0 = t1; - t1 = 3*in_near[i]+in_far[i]; - out[i*2-1] = stbi__div16(3*t0 + t1 + 8); - out[i*2 ] = stbi__div16(3*t1 + t0 + 8); - } - out[w*2-1] = stbi__div4(t1+2); - - STBI_NOTUSED(hs); - - return out; -} -#endif - -static stbi_uc *stbi__resample_row_generic(stbi_uc *out, stbi_uc *in_near, stbi_uc *in_far, int w, int hs) -{ - // resample with nearest-neighbor - int i,j; - STBI_NOTUSED(in_far); - for (i=0; i < w; ++i) - for (j=0; j < hs; ++j) - out[i*hs+j] = in_near[i]; - return out; -} - -#ifdef STBI_JPEG_OLD -// this is the same YCbCr-to-RGB calculation that stb_image has used -// historically before the algorithm changes in 1.49 -#define float2fixed(x) ((int) ((x) * 65536 + 0.5)) -static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) -{ - int i; - for (i=0; i < count; ++i) { - int y_fixed = (y[i] << 16) + 32768; // rounding - int r,g,b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr*float2fixed(1.40200f); - g = y_fixed - cr*float2fixed(0.71414f) - cb*float2fixed(0.34414f); - b = y_fixed + cb*float2fixed(1.77200f); - r >>= 16; - g >>= 16; - b >>= 16; - if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } - if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } - if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } - out[0] = (stbi_uc)r; - out[1] = (stbi_uc)g; - out[2] = (stbi_uc)b; - out[3] = 255; - out += step; - } -} -#else -// this is a reduced-precision calculation of YCbCr-to-RGB introduced -// to make sure the code produces the same results in both SIMD and scalar -#define float2fixed(x) (((int) ((x) * 4096.0f + 0.5f)) << 8) -static void stbi__YCbCr_to_RGB_row(stbi_uc *out, const stbi_uc *y, const stbi_uc *pcb, const stbi_uc *pcr, int count, int step) -{ - int i; - for (i=0; i < count; ++i) { - int y_fixed = (y[i] << 20) + (1<<19); // rounding - int r,g,b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr* float2fixed(1.40200f); - g = y_fixed + (cr*-float2fixed(0.71414f)) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb* float2fixed(1.77200f); - r >>= 20; - g >>= 20; - b >>= 20; - if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } - if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } - if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } - out[0] = (stbi_uc)r; - out[1] = (stbi_uc)g; - out[2] = (stbi_uc)b; - out[3] = 255; - out += step; - } -} -#endif - -#if defined(STBI_SSE2) || defined(STBI_NEON) -static void stbi__YCbCr_to_RGB_simd(stbi_uc *out, stbi_uc const *y, stbi_uc const *pcb, stbi_uc const *pcr, int count, int step) -{ - int i = 0; - -#ifdef STBI_SSE2 - // step == 3 is pretty ugly on the final interleave, and i'm not convinced - // it's useful in practice (you wouldn't use it for textures, for example). - // so just accelerate step == 4 case. - if (step == 4) { - // this is a fairly straightforward implementation and not super-optimized. - __m128i signflip = _mm_set1_epi8(-0x80); - __m128i cr_const0 = _mm_set1_epi16( (short) ( 1.40200f*4096.0f+0.5f)); - __m128i cr_const1 = _mm_set1_epi16( - (short) ( 0.71414f*4096.0f+0.5f)); - __m128i cb_const0 = _mm_set1_epi16( - (short) ( 0.34414f*4096.0f+0.5f)); - __m128i cb_const1 = _mm_set1_epi16( (short) ( 1.77200f*4096.0f+0.5f)); - __m128i y_bias = _mm_set1_epi8((char) (unsigned char) 128); - __m128i xw = _mm_set1_epi16(255); // alpha channel - - for (; i+7 < count; i += 8) { - // load - __m128i y_bytes = _mm_loadl_epi64((__m128i *) (y+i)); - __m128i cr_bytes = _mm_loadl_epi64((__m128i *) (pcr+i)); - __m128i cb_bytes = _mm_loadl_epi64((__m128i *) (pcb+i)); - __m128i cr_biased = _mm_xor_si128(cr_bytes, signflip); // -128 - __m128i cb_biased = _mm_xor_si128(cb_bytes, signflip); // -128 - - // unpack to short (and left-shift cr, cb by 8) - __m128i yw = _mm_unpacklo_epi8(y_bias, y_bytes); - __m128i crw = _mm_unpacklo_epi8(_mm_setzero_si128(), cr_biased); - __m128i cbw = _mm_unpacklo_epi8(_mm_setzero_si128(), cb_biased); - - // color transform - __m128i yws = _mm_srli_epi16(yw, 4); - __m128i cr0 = _mm_mulhi_epi16(cr_const0, crw); - __m128i cb0 = _mm_mulhi_epi16(cb_const0, cbw); - __m128i cb1 = _mm_mulhi_epi16(cbw, cb_const1); - __m128i cr1 = _mm_mulhi_epi16(crw, cr_const1); - __m128i rws = _mm_add_epi16(cr0, yws); - __m128i gwt = _mm_add_epi16(cb0, yws); - __m128i bws = _mm_add_epi16(yws, cb1); - __m128i gws = _mm_add_epi16(gwt, cr1); - - // descale - __m128i rw = _mm_srai_epi16(rws, 4); - __m128i bw = _mm_srai_epi16(bws, 4); - __m128i gw = _mm_srai_epi16(gws, 4); - - // back to byte, set up for transpose - __m128i brb = _mm_packus_epi16(rw, bw); - __m128i gxb = _mm_packus_epi16(gw, xw); - - // transpose to interleave channels - __m128i t0 = _mm_unpacklo_epi8(brb, gxb); - __m128i t1 = _mm_unpackhi_epi8(brb, gxb); - __m128i o0 = _mm_unpacklo_epi16(t0, t1); - __m128i o1 = _mm_unpackhi_epi16(t0, t1); - - // store - _mm_storeu_si128((__m128i *) (out + 0), o0); - _mm_storeu_si128((__m128i *) (out + 16), o1); - out += 32; - } - } -#endif - -#ifdef STBI_NEON - // in this version, step=3 support would be easy to add. but is there demand? - if (step == 4) { - // this is a fairly straightforward implementation and not super-optimized. - uint8x8_t signflip = vdup_n_u8(0x80); - int16x8_t cr_const0 = vdupq_n_s16( (short) ( 1.40200f*4096.0f+0.5f)); - int16x8_t cr_const1 = vdupq_n_s16( - (short) ( 0.71414f*4096.0f+0.5f)); - int16x8_t cb_const0 = vdupq_n_s16( - (short) ( 0.34414f*4096.0f+0.5f)); - int16x8_t cb_const1 = vdupq_n_s16( (short) ( 1.77200f*4096.0f+0.5f)); - - for (; i+7 < count; i += 8) { - // load - uint8x8_t y_bytes = vld1_u8(y + i); - uint8x8_t cr_bytes = vld1_u8(pcr + i); - uint8x8_t cb_bytes = vld1_u8(pcb + i); - int8x8_t cr_biased = vreinterpret_s8_u8(vsub_u8(cr_bytes, signflip)); - int8x8_t cb_biased = vreinterpret_s8_u8(vsub_u8(cb_bytes, signflip)); - - // expand to s16 - int16x8_t yws = vreinterpretq_s16_u16(vshll_n_u8(y_bytes, 4)); - int16x8_t crw = vshll_n_s8(cr_biased, 7); - int16x8_t cbw = vshll_n_s8(cb_biased, 7); - - // color transform - int16x8_t cr0 = vqdmulhq_s16(crw, cr_const0); - int16x8_t cb0 = vqdmulhq_s16(cbw, cb_const0); - int16x8_t cr1 = vqdmulhq_s16(crw, cr_const1); - int16x8_t cb1 = vqdmulhq_s16(cbw, cb_const1); - int16x8_t rws = vaddq_s16(yws, cr0); - int16x8_t gws = vaddq_s16(vaddq_s16(yws, cb0), cr1); - int16x8_t bws = vaddq_s16(yws, cb1); - - // undo scaling, round, convert to byte - uint8x8x4_t o; - o.val[0] = vqrshrun_n_s16(rws, 4); - o.val[1] = vqrshrun_n_s16(gws, 4); - o.val[2] = vqrshrun_n_s16(bws, 4); - o.val[3] = vdup_n_u8(255); - - // store, interleaving r/g/b/a - vst4_u8(out, o); - out += 8*4; - } - } -#endif - - for (; i < count; ++i) { - int y_fixed = (y[i] << 20) + (1<<19); // rounding - int r,g,b; - int cr = pcr[i] - 128; - int cb = pcb[i] - 128; - r = y_fixed + cr* float2fixed(1.40200f); - g = y_fixed + cr*-float2fixed(0.71414f) + ((cb*-float2fixed(0.34414f)) & 0xffff0000); - b = y_fixed + cb* float2fixed(1.77200f); - r >>= 20; - g >>= 20; - b >>= 20; - if ((unsigned) r > 255) { if (r < 0) r = 0; else r = 255; } - if ((unsigned) g > 255) { if (g < 0) g = 0; else g = 255; } - if ((unsigned) b > 255) { if (b < 0) b = 0; else b = 255; } - out[0] = (stbi_uc)r; - out[1] = (stbi_uc)g; - out[2] = (stbi_uc)b; - out[3] = 255; - out += step; - } -} -#endif - -// set up the kernels -static void stbi__setup_jpeg(stbi__jpeg *j) -{ - j->idct_block_kernel = stbi__idct_block; - j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_row; - j->resample_row_hv_2_kernel = stbi__resample_row_hv_2; - -#ifdef STBI_SSE2 - if (stbi__sse2_available()) { - j->idct_block_kernel = stbi__idct_simd; - #ifndef STBI_JPEG_OLD - j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - #endif - j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; - } -#endif - -#ifdef STBI_NEON - j->idct_block_kernel = stbi__idct_simd; - #ifndef STBI_JPEG_OLD - j->YCbCr_to_RGB_kernel = stbi__YCbCr_to_RGB_simd; - #endif - j->resample_row_hv_2_kernel = stbi__resample_row_hv_2_simd; -#endif -} - -// clean up the temporary component buffers -static void stbi__cleanup_jpeg(stbi__jpeg *j) -{ - int i; - for (i=0; i < j->s->img_n; ++i) { - if (j->img_comp[i].raw_data) { - STBI_FREE(j->img_comp[i].raw_data); - j->img_comp[i].raw_data = NULL; - j->img_comp[i].data = NULL; - } - if (j->img_comp[i].raw_coeff) { - STBI_FREE(j->img_comp[i].raw_coeff); - j->img_comp[i].raw_coeff = 0; - j->img_comp[i].coeff = 0; - } - if (j->img_comp[i].linebuf) { - STBI_FREE(j->img_comp[i].linebuf); - j->img_comp[i].linebuf = NULL; - } - } -} - -typedef struct -{ - resample_row_func resample; - stbi_uc *line0,*line1; - int hs,vs; // expansion factor in each axis - int w_lores; // horizontal pixels pre-expansion - int ystep; // how far through vertical expansion we are - int ypos; // which pre-expansion row we're on -} stbi__resample; - -static stbi_uc *load_jpeg_image(stbi__jpeg *z, int *out_x, int *out_y, int *comp, int req_comp) -{ - int n, decode_n; - z->s->img_n = 0; // make stbi__cleanup_jpeg safe - - // validate req_comp - if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); - - // load a jpeg image from whichever source, but leave in YCbCr format - if (!stbi__decode_jpeg_image(z)) { stbi__cleanup_jpeg(z); return NULL; } - - // determine actual number of components to generate - n = req_comp ? req_comp : z->s->img_n; - - if (z->s->img_n == 3 && n < 3) - decode_n = 1; - else - decode_n = z->s->img_n; - - // resample and color-convert - { - int k; - unsigned int i,j; - stbi_uc *output; - stbi_uc *coutput[4]; - - stbi__resample res_comp[4]; - - for (k=0; k < decode_n; ++k) { - stbi__resample *r = &res_comp[k]; - - // allocate line buffer big enough for upsampling off the edges - // with upsample factor of 4 - z->img_comp[k].linebuf = (stbi_uc *) stbi__malloc(z->s->img_x + 3); - if (!z->img_comp[k].linebuf) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } - - r->hs = z->img_h_max / z->img_comp[k].h; - r->vs = z->img_v_max / z->img_comp[k].v; - r->ystep = r->vs >> 1; - r->w_lores = (z->s->img_x + r->hs-1) / r->hs; - r->ypos = 0; - r->line0 = r->line1 = z->img_comp[k].data; - - if (r->hs == 1 && r->vs == 1) r->resample = resample_row_1; - else if (r->hs == 1 && r->vs == 2) r->resample = stbi__resample_row_v_2; - else if (r->hs == 2 && r->vs == 1) r->resample = stbi__resample_row_h_2; - else if (r->hs == 2 && r->vs == 2) r->resample = z->resample_row_hv_2_kernel; - else r->resample = stbi__resample_row_generic; - } - - // can't error after this so, this is safe - output = (stbi_uc *) stbi__malloc(n * z->s->img_x * z->s->img_y + 1); - if (!output) { stbi__cleanup_jpeg(z); return stbi__errpuc("outofmem", "Out of memory"); } - - // now go ahead and resample - for (j=0; j < z->s->img_y; ++j) { - stbi_uc *out = output + n * z->s->img_x * j; - for (k=0; k < decode_n; ++k) { - stbi__resample *r = &res_comp[k]; - int y_bot = r->ystep >= (r->vs >> 1); - coutput[k] = r->resample(z->img_comp[k].linebuf, - y_bot ? r->line1 : r->line0, - y_bot ? r->line0 : r->line1, - r->w_lores, r->hs); - if (++r->ystep >= r->vs) { - r->ystep = 0; - r->line0 = r->line1; - if (++r->ypos < z->img_comp[k].y) - r->line1 += z->img_comp[k].w2; - } - } - if (n >= 3) { - stbi_uc *y = coutput[0]; - if (z->s->img_n == 3) { - z->YCbCr_to_RGB_kernel(out, y, coutput[1], coutput[2], z->s->img_x, n); - } else - for (i=0; i < z->s->img_x; ++i) { - out[0] = out[1] = out[2] = y[i]; - out[3] = 255; // not used if n==3 - out += n; - } - } else { - stbi_uc *y = coutput[0]; - if (n == 1) - for (i=0; i < z->s->img_x; ++i) out[i] = y[i]; - else - for (i=0; i < z->s->img_x; ++i) *out++ = y[i], *out++ = 255; - } - } - stbi__cleanup_jpeg(z); - *out_x = z->s->img_x; - *out_y = z->s->img_y; - if (comp) *comp = z->s->img_n; // report original components, not output - return output; - } -} - -static unsigned char *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - stbi__jpeg j; - j.s = s; - stbi__setup_jpeg(&j); - return load_jpeg_image(&j, x,y,comp,req_comp); -} - -static int stbi__jpeg_test(stbi__context *s) -{ - int r; - stbi__jpeg j; - j.s = s; - stbi__setup_jpeg(&j); - r = stbi__decode_jpeg_header(&j, STBI__SCAN_type); - stbi__rewind(s); - return r; -} - -static int stbi__jpeg_info_raw(stbi__jpeg *j, int *x, int *y, int *comp) -{ - if (!stbi__decode_jpeg_header(j, STBI__SCAN_header)) { - stbi__rewind( j->s ); - return 0; - } - if (x) *x = j->s->img_x; - if (y) *y = j->s->img_y; - if (comp) *comp = j->s->img_n; - return 1; -} - -static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp) -{ - stbi__jpeg j; - j.s = s; - return stbi__jpeg_info_raw(&j, x, y, comp); -} -#endif - -// public domain zlib decode v0.2 Sean Barrett 2006-11-18 -// simple implementation -// - all input must be provided in an upfront buffer -// - all output is written to a single output buffer (can malloc/realloc) -// performance -// - fast huffman - -#ifndef STBI_NO_ZLIB - -// fast-way is faster to check than jpeg huffman, but slow way is slower -#define STBI__ZFAST_BITS 9 // accelerate all cases in default tables -#define STBI__ZFAST_MASK ((1 << STBI__ZFAST_BITS) - 1) - -// zlib-style huffman encoding -// (jpegs packs from left, zlib from right, so can't share code) -typedef struct -{ - stbi__uint16 fast[1 << STBI__ZFAST_BITS]; - stbi__uint16 firstcode[16]; - int maxcode[17]; - stbi__uint16 firstsymbol[16]; - stbi_uc size[288]; - stbi__uint16 value[288]; -} stbi__zhuffman; - -stbi_inline static int stbi__bitreverse16(int n) -{ - n = ((n & 0xAAAA) >> 1) | ((n & 0x5555) << 1); - n = ((n & 0xCCCC) >> 2) | ((n & 0x3333) << 2); - n = ((n & 0xF0F0) >> 4) | ((n & 0x0F0F) << 4); - n = ((n & 0xFF00) >> 8) | ((n & 0x00FF) << 8); - return n; -} - -stbi_inline static int stbi__bit_reverse(int v, int bits) -{ - STBI_ASSERT(bits <= 16); - // to bit reverse n bits, reverse 16 and shift - // e.g. 11 bits, bit reverse and shift away 5 - return stbi__bitreverse16(v) >> (16-bits); -} - -static int stbi__zbuild_huffman(stbi__zhuffman *z, stbi_uc *sizelist, int num) -{ - int i,k=0; - int code, next_code[16], sizes[17]; - - // DEFLATE spec for generating codes - memset(sizes, 0, sizeof(sizes)); - memset(z->fast, 0, sizeof(z->fast)); - for (i=0; i < num; ++i) - ++sizes[sizelist[i]]; - sizes[0] = 0; - for (i=1; i < 16; ++i) - if (sizes[i] > (1 << i)) - return stbi__err("bad sizes", "Corrupt PNG"); - code = 0; - for (i=1; i < 16; ++i) { - next_code[i] = code; - z->firstcode[i] = (stbi__uint16) code; - z->firstsymbol[i] = (stbi__uint16) k; - code = (code + sizes[i]); - if (sizes[i]) - if (code-1 >= (1 << i)) return stbi__err("bad codelengths","Corrupt PNG"); - z->maxcode[i] = code << (16-i); // preshift for inner loop - code <<= 1; - k += sizes[i]; - } - z->maxcode[16] = 0x10000; // sentinel - for (i=0; i < num; ++i) { - int s = sizelist[i]; - if (s) { - int c = next_code[s] - z->firstcode[s] + z->firstsymbol[s]; - stbi__uint16 fastv = (stbi__uint16) ((s << 9) | i); - z->size [c] = (stbi_uc ) s; - z->value[c] = (stbi__uint16) i; - if (s <= STBI__ZFAST_BITS) { - int j = stbi__bit_reverse(next_code[s],s); - while (j < (1 << STBI__ZFAST_BITS)) { - z->fast[j] = fastv; - j += (1 << s); - } - } - ++next_code[s]; - } - } - return 1; -} - -// zlib-from-memory implementation for PNG reading -// because PNG allows splitting the zlib stream arbitrarily, -// and it's annoying structurally to have PNG call ZLIB call PNG, -// we require PNG read all the IDATs and combine them into a single -// memory buffer - -typedef struct -{ - stbi_uc *zbuffer, *zbuffer_end; - int num_bits; - stbi__uint32 code_buffer; - - char *zout; - char *zout_start; - char *zout_end; - int z_expandable; - - stbi__zhuffman z_length, z_distance; -} stbi__zbuf; - -stbi_inline static stbi_uc stbi__zget8(stbi__zbuf *z) -{ - if (z->zbuffer >= z->zbuffer_end) return 0; - return *z->zbuffer++; -} - -static void stbi__fill_bits(stbi__zbuf *z) -{ - do { - STBI_ASSERT(z->code_buffer < (1U << z->num_bits)); - z->code_buffer |= (unsigned int) stbi__zget8(z) << z->num_bits; - z->num_bits += 8; - } while (z->num_bits <= 24); -} - -stbi_inline static unsigned int stbi__zreceive(stbi__zbuf *z, int n) -{ - unsigned int k; - if (z->num_bits < n) stbi__fill_bits(z); - k = z->code_buffer & ((1 << n) - 1); - z->code_buffer >>= n; - z->num_bits -= n; - return k; -} - -static int stbi__zhuffman_decode_slowpath(stbi__zbuf *a, stbi__zhuffman *z) -{ - int b,s,k; - // not resolved by fast table, so compute it the slow way - // use jpeg approach, which requires MSbits at top - k = stbi__bit_reverse(a->code_buffer, 16); - for (s=STBI__ZFAST_BITS+1; ; ++s) - if (k < z->maxcode[s]) - break; - if (s == 16) return -1; // invalid code! - // code size is s, so: - b = (k >> (16-s)) - z->firstcode[s] + z->firstsymbol[s]; - STBI_ASSERT(z->size[b] == s); - a->code_buffer >>= s; - a->num_bits -= s; - return z->value[b]; -} - -stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z) -{ - int b,s; - if (a->num_bits < 16) stbi__fill_bits(a); - b = z->fast[a->code_buffer & STBI__ZFAST_MASK]; - if (b) { - s = b >> 9; - a->code_buffer >>= s; - a->num_bits -= s; - return b & 511; - } - return stbi__zhuffman_decode_slowpath(a, z); -} - -static int stbi__zexpand(stbi__zbuf *z, char *zout, int n) // need to make room for n bytes -{ - char *q; - int cur, limit; - z->zout = zout; - if (!z->z_expandable) return stbi__err("output buffer limit","Corrupt PNG"); - cur = (int) (z->zout - z->zout_start); - limit = (int) (z->zout_end - z->zout_start); - while (cur + n > limit) - limit *= 2; - q = (char *) STBI_REALLOC(z->zout_start, limit); - if (q == NULL) return stbi__err("outofmem", "Out of memory"); - z->zout_start = q; - z->zout = q + cur; - z->zout_end = q + limit; - return 1; -} - -static int stbi__zlength_base[31] = { - 3,4,5,6,7,8,9,10,11,13, - 15,17,19,23,27,31,35,43,51,59, - 67,83,99,115,131,163,195,227,258,0,0 }; - -static int stbi__zlength_extra[31]= -{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,0,0,0 }; - -static int stbi__zdist_base[32] = { 1,2,3,4,5,7,9,13,17,25,33,49,65,97,129,193, -257,385,513,769,1025,1537,2049,3073,4097,6145,8193,12289,16385,24577,0,0}; - -static int stbi__zdist_extra[32] = -{ 0,0,0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9,10,10,11,11,12,12,13,13}; - -static int stbi__parse_huffman_block(stbi__zbuf *a) -{ - char *zout = a->zout; - for(;;) { - int z = stbi__zhuffman_decode(a, &a->z_length); - if (z < 256) { - if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); // error in huffman codes - if (zout >= a->zout_end) { - if (!stbi__zexpand(a, zout, 1)) return 0; - zout = a->zout; - } - *zout++ = (char) z; - } else { - stbi_uc *p; - int len,dist; - if (z == 256) { - a->zout = zout; - return 1; - } - z -= 257; - len = stbi__zlength_base[z]; - if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]); - z = stbi__zhuffman_decode(a, &a->z_distance); - if (z < 0) return stbi__err("bad huffman code","Corrupt PNG"); - dist = stbi__zdist_base[z]; - if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]); - if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG"); - if (zout + len > a->zout_end) { - if (!stbi__zexpand(a, zout, len)) return 0; - zout = a->zout; - } - p = (stbi_uc *) (zout - dist); - if (dist == 1) { // run of one byte; common in images. - stbi_uc v = *p; - if (len) { do *zout++ = v; while (--len); } - } else { - if (len) { do *zout++ = *p++; while (--len); } - } - } - } -} - -static int stbi__compute_huffman_codes(stbi__zbuf *a) -{ - static stbi_uc length_dezigzag[19] = { 16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15 }; - stbi__zhuffman z_codelength; - stbi_uc lencodes[286+32+137];//padding for maximum single op - stbi_uc codelength_sizes[19]; - int i,n; - - int hlit = stbi__zreceive(a,5) + 257; - int hdist = stbi__zreceive(a,5) + 1; - int hclen = stbi__zreceive(a,4) + 4; - - memset(codelength_sizes, 0, sizeof(codelength_sizes)); - for (i=0; i < hclen; ++i) { - int s = stbi__zreceive(a,3); - codelength_sizes[length_dezigzag[i]] = (stbi_uc) s; - } - if (!stbi__zbuild_huffman(&z_codelength, codelength_sizes, 19)) return 0; - - n = 0; - while (n < hlit + hdist) { - int c = stbi__zhuffman_decode(a, &z_codelength); - if (c < 0 || c >= 19) return stbi__err("bad codelengths", "Corrupt PNG"); - if (c < 16) - lencodes[n++] = (stbi_uc) c; - else if (c == 16) { - c = stbi__zreceive(a,2)+3; - memset(lencodes+n, lencodes[n-1], c); - n += c; - } else if (c == 17) { - c = stbi__zreceive(a,3)+3; - memset(lencodes+n, 0, c); - n += c; - } else { - STBI_ASSERT(c == 18); - c = stbi__zreceive(a,7)+11; - memset(lencodes+n, 0, c); - n += c; - } - } - if (n != hlit+hdist) return stbi__err("bad codelengths","Corrupt PNG"); - if (!stbi__zbuild_huffman(&a->z_length, lencodes, hlit)) return 0; - if (!stbi__zbuild_huffman(&a->z_distance, lencodes+hlit, hdist)) return 0; - return 1; -} - -static int stbi__parse_uncomperssed_block(stbi__zbuf *a) -{ - stbi_uc header[4]; - int len,nlen,k; - if (a->num_bits & 7) - stbi__zreceive(a, a->num_bits & 7); // discard - // drain the bit-packed data into header - k = 0; - while (a->num_bits > 0) { - header[k++] = (stbi_uc) (a->code_buffer & 255); // suppress MSVC run-time check - a->code_buffer >>= 8; - a->num_bits -= 8; - } - STBI_ASSERT(a->num_bits == 0); - // now fill header the normal way - while (k < 4) - header[k++] = stbi__zget8(a); - len = header[1] * 256 + header[0]; - nlen = header[3] * 256 + header[2]; - if (nlen != (len ^ 0xffff)) return stbi__err("zlib corrupt","Corrupt PNG"); - if (a->zbuffer + len > a->zbuffer_end) return stbi__err("read past buffer","Corrupt PNG"); - if (a->zout + len > a->zout_end) - if (!stbi__zexpand(a, a->zout, len)) return 0; - memcpy(a->zout, a->zbuffer, len); - a->zbuffer += len; - a->zout += len; - return 1; -} - -static int stbi__parse_zlib_header(stbi__zbuf *a) -{ - int cmf = stbi__zget8(a); - int cm = cmf & 15; - /* int cinfo = cmf >> 4; */ - int flg = stbi__zget8(a); - if ((cmf*256+flg) % 31 != 0) return stbi__err("bad zlib header","Corrupt PNG"); // zlib spec - if (flg & 32) return stbi__err("no preset dict","Corrupt PNG"); // preset dictionary not allowed in png - if (cm != 8) return stbi__err("bad compression","Corrupt PNG"); // DEFLATE required for png - // window = 1 << (8 + cinfo)... but who cares, we fully buffer output - return 1; -} - -// @TODO: should statically initialize these for optimal thread safety -static stbi_uc stbi__zdefault_length[288], stbi__zdefault_distance[32]; -static void stbi__init_zdefaults(void) -{ - int i; // use <= to match clearly with spec - for (i=0; i <= 143; ++i) stbi__zdefault_length[i] = 8; - for ( ; i <= 255; ++i) stbi__zdefault_length[i] = 9; - for ( ; i <= 279; ++i) stbi__zdefault_length[i] = 7; - for ( ; i <= 287; ++i) stbi__zdefault_length[i] = 8; - - for (i=0; i <= 31; ++i) stbi__zdefault_distance[i] = 5; -} - -static int stbi__parse_zlib(stbi__zbuf *a, int parse_header) -{ - int final, type; - if (parse_header) - if (!stbi__parse_zlib_header(a)) return 0; - a->num_bits = 0; - a->code_buffer = 0; - do { - final = stbi__zreceive(a,1); - type = stbi__zreceive(a,2); - if (type == 0) { - if (!stbi__parse_uncomperssed_block(a)) return 0; - } else if (type == 3) { - return 0; - } else { - if (type == 1) { - // use fixed code lengths - if (!stbi__zdefault_distance[31]) stbi__init_zdefaults(); - if (!stbi__zbuild_huffman(&a->z_length , stbi__zdefault_length , 288)) return 0; - if (!stbi__zbuild_huffman(&a->z_distance, stbi__zdefault_distance, 32)) return 0; - } else { - if (!stbi__compute_huffman_codes(a)) return 0; - } - if (!stbi__parse_huffman_block(a)) return 0; - } - } while (!final); - return 1; -} - -static int stbi__do_zlib(stbi__zbuf *a, char *obuf, int olen, int exp, int parse_header) -{ - a->zout_start = obuf; - a->zout = obuf; - a->zout_end = obuf + olen; - a->z_expandable = exp; - - return stbi__parse_zlib(a, parse_header); -} - -STBIDEF char *stbi_zlib_decode_malloc_guesssize(const char *buffer, int len, int initial_size, int *outlen) -{ - stbi__zbuf a; - char *p = (char *) stbi__malloc(initial_size); - if (p == NULL) return NULL; - a.zbuffer = (stbi_uc *) buffer; - a.zbuffer_end = (stbi_uc *) buffer + len; - if (stbi__do_zlib(&a, p, initial_size, 1, 1)) { - if (outlen) *outlen = (int) (a.zout - a.zout_start); - return a.zout_start; - } else { - STBI_FREE(a.zout_start); - return NULL; - } -} - -STBIDEF char *stbi_zlib_decode_malloc(char const *buffer, int len, int *outlen) -{ - return stbi_zlib_decode_malloc_guesssize(buffer, len, 16384, outlen); -} - -STBIDEF char *stbi_zlib_decode_malloc_guesssize_headerflag(const char *buffer, int len, int initial_size, int *outlen, int parse_header) -{ - stbi__zbuf a; - char *p = (char *) stbi__malloc(initial_size); - if (p == NULL) return NULL; - a.zbuffer = (stbi_uc *) buffer; - a.zbuffer_end = (stbi_uc *) buffer + len; - if (stbi__do_zlib(&a, p, initial_size, 1, parse_header)) { - if (outlen) *outlen = (int) (a.zout - a.zout_start); - return a.zout_start; - } else { - STBI_FREE(a.zout_start); - return NULL; - } -} - -STBIDEF int stbi_zlib_decode_buffer(char *obuffer, int olen, char const *ibuffer, int ilen) -{ - stbi__zbuf a; - a.zbuffer = (stbi_uc *) ibuffer; - a.zbuffer_end = (stbi_uc *) ibuffer + ilen; - if (stbi__do_zlib(&a, obuffer, olen, 0, 1)) - return (int) (a.zout - a.zout_start); - else - return -1; -} - -STBIDEF char *stbi_zlib_decode_noheader_malloc(char const *buffer, int len, int *outlen) -{ - stbi__zbuf a; - char *p = (char *) stbi__malloc(16384); - if (p == NULL) return NULL; - a.zbuffer = (stbi_uc *) buffer; - a.zbuffer_end = (stbi_uc *) buffer+len; - if (stbi__do_zlib(&a, p, 16384, 1, 0)) { - if (outlen) *outlen = (int) (a.zout - a.zout_start); - return a.zout_start; - } else { - STBI_FREE(a.zout_start); - return NULL; - } -} - -STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const char *ibuffer, int ilen) -{ - stbi__zbuf a; - a.zbuffer = (stbi_uc *) ibuffer; - a.zbuffer_end = (stbi_uc *) ibuffer + ilen; - if (stbi__do_zlib(&a, obuffer, olen, 0, 0)) - return (int) (a.zout - a.zout_start); - else - return -1; -} -#endif - -// public domain "baseline" PNG decoder v0.10 Sean Barrett 2006-11-18 -// simple implementation -// - only 8-bit samples -// - no CRC checking -// - allocates lots of intermediate memory -// - avoids problem of streaming data between subsystems -// - avoids explicit window management -// performance -// - uses stb_zlib, a PD zlib implementation with fast huffman decoding - -#ifndef STBI_NO_PNG -typedef struct -{ - stbi__uint32 length; - stbi__uint32 type; -} stbi__pngchunk; - -static stbi__pngchunk stbi__get_chunk_header(stbi__context *s) -{ - stbi__pngchunk c; - c.length = stbi__get32be(s); - c.type = stbi__get32be(s); - return c; -} - -static int stbi__check_png_header(stbi__context *s) -{ - static stbi_uc png_sig[8] = { 137,80,78,71,13,10,26,10 }; - int i; - for (i=0; i < 8; ++i) - if (stbi__get8(s) != png_sig[i]) return stbi__err("bad png sig","Not a PNG"); - return 1; -} - -typedef struct -{ - stbi__context *s; - stbi_uc *idata, *expanded, *out; -} stbi__png; - - -enum { - STBI__F_none=0, - STBI__F_sub=1, - STBI__F_up=2, - STBI__F_avg=3, - STBI__F_paeth=4, - // synthetic filters used for first scanline to avoid needing a dummy row of 0s - STBI__F_avg_first, - STBI__F_paeth_first -}; - -static stbi_uc first_row_filter[5] = -{ - STBI__F_none, - STBI__F_sub, - STBI__F_none, - STBI__F_avg_first, - STBI__F_paeth_first -}; - -static int stbi__paeth(int a, int b, int c) -{ - int p = a + b - c; - int pa = abs(p-a); - int pb = abs(p-b); - int pc = abs(p-c); - if (pa <= pb && pa <= pc) return a; - if (pb <= pc) return b; - return c; -} - -static stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 }; - -// create the png data from post-deflated data -static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color) -{ - stbi__context *s = a->s; - stbi__uint32 i,j,stride = x*out_n; - stbi__uint32 img_len, img_width_bytes; - int k; - int img_n = s->img_n; // copy it into a local for later - - STBI_ASSERT(out_n == s->img_n || out_n == s->img_n+1); - a->out = (stbi_uc *) stbi__malloc(x * y * out_n); // extra bytes to write off the end into - if (!a->out) return stbi__err("outofmem", "Out of memory"); - - img_width_bytes = (((img_n * x * depth) + 7) >> 3); - img_len = (img_width_bytes + 1) * y; - if (s->img_x == x && s->img_y == y) { - if (raw_len != img_len) return stbi__err("not enough pixels","Corrupt PNG"); - } else { // interlaced: - if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG"); - } - - for (j=0; j < y; ++j) { - stbi_uc *cur = a->out + stride*j; - stbi_uc *prior = cur - stride; - int filter = *raw++; - int filter_bytes = img_n; - int width = x; - if (filter > 4) - return stbi__err("invalid filter","Corrupt PNG"); - - if (depth < 8) { - STBI_ASSERT(img_width_bytes <= x); - cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place - filter_bytes = 1; - width = img_width_bytes; - } - - // if first row, use special filter that doesn't sample previous row - if (j == 0) filter = first_row_filter[filter]; - - // handle first byte explicitly - for (k=0; k < filter_bytes; ++k) { - switch (filter) { - case STBI__F_none : cur[k] = raw[k]; break; - case STBI__F_sub : cur[k] = raw[k]; break; - case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break; - case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break; - case STBI__F_avg_first : cur[k] = raw[k]; break; - case STBI__F_paeth_first: cur[k] = raw[k]; break; - } - } - - if (depth == 8) { - if (img_n != out_n) - cur[img_n] = 255; // first pixel - raw += img_n; - cur += out_n; - prior += out_n; - } else { - raw += 1; - cur += 1; - prior += 1; - } - - // this is a little gross, so that we don't switch per-pixel or per-component - if (depth < 8 || img_n == out_n) { - int nk = (width - 1)*img_n; - #define CASE(f) \ - case f: \ - for (k=0; k < nk; ++k) - switch (filter) { - // "none" filter turns into a memcpy here; make that explicit. - case STBI__F_none: memcpy(cur, raw, nk); break; - CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); break; - CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); break; - CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); break; - CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); break; - CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); break; - } - #undef CASE - raw += nk; - } else { - STBI_ASSERT(img_n+1 == out_n); - #define CASE(f) \ - case f: \ - for (i=x-1; i >= 1; --i, cur[img_n]=255,raw+=img_n,cur+=out_n,prior+=out_n) \ - for (k=0; k < img_n; ++k) - switch (filter) { - CASE(STBI__F_none) cur[k] = raw[k]; break; - CASE(STBI__F_sub) cur[k] = STBI__BYTECAST(raw[k] + cur[k-out_n]); break; - CASE(STBI__F_up) cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break; - CASE(STBI__F_avg) cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-out_n])>>1)); break; - CASE(STBI__F_paeth) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],prior[k],prior[k-out_n])); break; - CASE(STBI__F_avg_first) cur[k] = STBI__BYTECAST(raw[k] + (cur[k-out_n] >> 1)); break; - CASE(STBI__F_paeth_first) cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-out_n],0,0)); break; - } - #undef CASE - } - } - - // we make a separate pass to expand bits to pixels; for performance, - // this could run two scanlines behind the above code, so it won't - // intefere with filtering but will still be in the cache. - if (depth < 8) { - for (j=0; j < y; ++j) { - stbi_uc *cur = a->out + stride*j; - stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes; - // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit - // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop - stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range - - // note that the final byte might overshoot and write more data than desired. - // we can allocate enough data that this never writes out of memory, but it - // could also overwrite the next scanline. can it overwrite non-empty data - // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel. - // so we need to explicitly clamp the final ones - - if (depth == 4) { - for (k=x*img_n; k >= 2; k-=2, ++in) { - *cur++ = scale * ((*in >> 4) ); - *cur++ = scale * ((*in ) & 0x0f); - } - if (k > 0) *cur++ = scale * ((*in >> 4) ); - } else if (depth == 2) { - for (k=x*img_n; k >= 4; k-=4, ++in) { - *cur++ = scale * ((*in >> 6) ); - *cur++ = scale * ((*in >> 4) & 0x03); - *cur++ = scale * ((*in >> 2) & 0x03); - *cur++ = scale * ((*in ) & 0x03); - } - if (k > 0) *cur++ = scale * ((*in >> 6) ); - if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03); - if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03); - } else if (depth == 1) { - for (k=x*img_n; k >= 8; k-=8, ++in) { - *cur++ = scale * ((*in >> 7) ); - *cur++ = scale * ((*in >> 6) & 0x01); - *cur++ = scale * ((*in >> 5) & 0x01); - *cur++ = scale * ((*in >> 4) & 0x01); - *cur++ = scale * ((*in >> 3) & 0x01); - *cur++ = scale * ((*in >> 2) & 0x01); - *cur++ = scale * ((*in >> 1) & 0x01); - *cur++ = scale * ((*in ) & 0x01); - } - if (k > 0) *cur++ = scale * ((*in >> 7) ); - if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01); - if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01); - if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01); - if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01); - if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01); - if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01); - } - if (img_n != out_n) { - int q; - // insert alpha = 255 - cur = a->out + stride*j; - if (img_n == 1) { - for (q=x-1; q >= 0; --q) { - cur[q*2+1] = 255; - cur[q*2+0] = cur[q]; - } - } else { - STBI_ASSERT(img_n == 3); - for (q=x-1; q >= 0; --q) { - cur[q*4+3] = 255; - cur[q*4+2] = cur[q*3+2]; - cur[q*4+1] = cur[q*3+1]; - cur[q*4+0] = cur[q*3+0]; - } - } - } - } - } - - return 1; -} - -static int stbi__create_png_image(stbi__png *a, stbi_uc *image_data, stbi__uint32 image_data_len, int out_n, int depth, int color, int interlaced) -{ - stbi_uc *final; - int p; - if (!interlaced) - return stbi__create_png_image_raw(a, image_data, image_data_len, out_n, a->s->img_x, a->s->img_y, depth, color); - - // de-interlacing - final = (stbi_uc *) stbi__malloc(a->s->img_x * a->s->img_y * out_n); - for (p=0; p < 7; ++p) { - int xorig[] = { 0,4,0,2,0,1,0 }; - int yorig[] = { 0,0,4,0,2,0,1 }; - int xspc[] = { 8,8,4,4,2,2,1 }; - int yspc[] = { 8,8,8,4,4,2,2 }; - int i,j,x,y; - // pass1_x[4] = 0, pass1_x[5] = 1, pass1_x[12] = 1 - x = (a->s->img_x - xorig[p] + xspc[p]-1) / xspc[p]; - y = (a->s->img_y - yorig[p] + yspc[p]-1) / yspc[p]; - if (x && y) { - stbi__uint32 img_len = ((((a->s->img_n * x * depth) + 7) >> 3) + 1) * y; - if (!stbi__create_png_image_raw(a, image_data, image_data_len, out_n, x, y, depth, color)) { - STBI_FREE(final); - return 0; - } - for (j=0; j < y; ++j) { - for (i=0; i < x; ++i) { - int out_y = j*yspc[p]+yorig[p]; - int out_x = i*xspc[p]+xorig[p]; - memcpy(final + out_y*a->s->img_x*out_n + out_x*out_n, - a->out + (j*x+i)*out_n, out_n); - } - } - STBI_FREE(a->out); - image_data += img_len; - image_data_len -= img_len; - } - } - a->out = final; - - return 1; -} - -static int stbi__compute_transparency(stbi__png *z, stbi_uc tc[3], int out_n) -{ - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi_uc *p = z->out; - - // compute color-based transparency, assuming we've - // already got 255 as the alpha value in the output - STBI_ASSERT(out_n == 2 || out_n == 4); - - if (out_n == 2) { - for (i=0; i < pixel_count; ++i) { - p[1] = (p[0] == tc[0] ? 0 : 255); - p += 2; - } - } else { - for (i=0; i < pixel_count; ++i) { - if (p[0] == tc[0] && p[1] == tc[1] && p[2] == tc[2]) - p[3] = 0; - p += 4; - } - } - return 1; -} - -static int stbi__expand_png_palette(stbi__png *a, stbi_uc *palette, int len, int pal_img_n) -{ - stbi__uint32 i, pixel_count = a->s->img_x * a->s->img_y; - stbi_uc *p, *temp_out, *orig = a->out; - - p = (stbi_uc *) stbi__malloc(pixel_count * pal_img_n); - if (p == NULL) return stbi__err("outofmem", "Out of memory"); - - // between here and free(out) below, exitting would leak - temp_out = p; - - if (pal_img_n == 3) { - for (i=0; i < pixel_count; ++i) { - int n = orig[i]*4; - p[0] = palette[n ]; - p[1] = palette[n+1]; - p[2] = palette[n+2]; - p += 3; - } - } else { - for (i=0; i < pixel_count; ++i) { - int n = orig[i]*4; - p[0] = palette[n ]; - p[1] = palette[n+1]; - p[2] = palette[n+2]; - p[3] = palette[n+3]; - p += 4; - } - } - STBI_FREE(a->out); - a->out = temp_out; - - STBI_NOTUSED(len); - - return 1; -} - -static int stbi__unpremultiply_on_load = 0; -static int stbi__de_iphone_flag = 0; - -STBIDEF void stbi_set_unpremultiply_on_load(int flag_true_if_should_unpremultiply) -{ - stbi__unpremultiply_on_load = flag_true_if_should_unpremultiply; -} - -STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert) -{ - stbi__de_iphone_flag = flag_true_if_should_convert; -} - -static void stbi__de_iphone(stbi__png *z) -{ - stbi__context *s = z->s; - stbi__uint32 i, pixel_count = s->img_x * s->img_y; - stbi_uc *p = z->out; - - if (s->img_out_n == 3) { // convert bgr to rgb - for (i=0; i < pixel_count; ++i) { - stbi_uc t = p[0]; - p[0] = p[2]; - p[2] = t; - p += 3; - } - } else { - STBI_ASSERT(s->img_out_n == 4); - if (stbi__unpremultiply_on_load) { - // convert bgr to rgb and unpremultiply - for (i=0; i < pixel_count; ++i) { - stbi_uc a = p[3]; - stbi_uc t = p[0]; - if (a) { - p[0] = p[2] * 255 / a; - p[1] = p[1] * 255 / a; - p[2] = t * 255 / a; - } else { - p[0] = p[2]; - p[2] = t; - } - p += 4; - } - } else { - // convert bgr to rgb - for (i=0; i < pixel_count; ++i) { - stbi_uc t = p[0]; - p[0] = p[2]; - p[2] = t; - p += 4; - } - } - } -} - -#define STBI__PNG_TYPE(a,b,c,d) (((a) << 24) + ((b) << 16) + ((c) << 8) + (d)) - -static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp) -{ - stbi_uc palette[1024], pal_img_n=0; - stbi_uc has_trans=0, tc[3]; - stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; - int first=1,k,interlace=0, color=0, depth=0, is_iphone=0; - stbi__context *s = z->s; - - z->expanded = NULL; - z->idata = NULL; - z->out = NULL; - - if (!stbi__check_png_header(s)) return 0; - - if (scan == STBI__SCAN_type) return 1; - - for (;;) { - stbi__pngchunk c = stbi__get_chunk_header(s); - switch (c.type) { - case STBI__PNG_TYPE('C','g','B','I'): - is_iphone = 1; - stbi__skip(s, c.length); - break; - case STBI__PNG_TYPE('I','H','D','R'): { - int comp,filter; - if (!first) return stbi__err("multiple IHDR","Corrupt PNG"); - first = 0; - if (c.length != 13) return stbi__err("bad IHDR len","Corrupt PNG"); - s->img_x = stbi__get32be(s); if (s->img_x > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); - s->img_y = stbi__get32be(s); if (s->img_y > (1 << 24)) return stbi__err("too large","Very large image (corrupt?)"); - depth = stbi__get8(s); if (depth != 1 && depth != 2 && depth != 4 && depth != 8) return stbi__err("1/2/4/8-bit only","PNG not supported: 1/2/4/8-bit only"); - color = stbi__get8(s); if (color > 6) return stbi__err("bad ctype","Corrupt PNG"); - if (color == 3) pal_img_n = 3; else if (color & 1) return stbi__err("bad ctype","Corrupt PNG"); - comp = stbi__get8(s); if (comp) return stbi__err("bad comp method","Corrupt PNG"); - filter= stbi__get8(s); if (filter) return stbi__err("bad filter method","Corrupt PNG"); - interlace = stbi__get8(s); if (interlace>1) return stbi__err("bad interlace method","Corrupt PNG"); - if (!s->img_x || !s->img_y) return stbi__err("0-pixel image","Corrupt PNG"); - if (!pal_img_n) { - s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0); - if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode"); - if (scan == STBI__SCAN_header) return 1; - } else { - // if paletted, then pal_n is our final components, and - // img_n is # components to decompress/filter. - s->img_n = 1; - if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG"); - // if SCAN_header, have to scan to see if we have a tRNS - } - break; - } - - case STBI__PNG_TYPE('P','L','T','E'): { - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (c.length > 256*3) return stbi__err("invalid PLTE","Corrupt PNG"); - pal_len = c.length / 3; - if (pal_len * 3 != c.length) return stbi__err("invalid PLTE","Corrupt PNG"); - for (i=0; i < pal_len; ++i) { - palette[i*4+0] = stbi__get8(s); - palette[i*4+1] = stbi__get8(s); - palette[i*4+2] = stbi__get8(s); - palette[i*4+3] = 255; - } - break; - } - - case STBI__PNG_TYPE('t','R','N','S'): { - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (z->idata) return stbi__err("tRNS after IDAT","Corrupt PNG"); - if (pal_img_n) { - if (scan == STBI__SCAN_header) { s->img_n = 4; return 1; } - if (pal_len == 0) return stbi__err("tRNS before PLTE","Corrupt PNG"); - if (c.length > pal_len) return stbi__err("bad tRNS len","Corrupt PNG"); - pal_img_n = 4; - for (i=0; i < c.length; ++i) - palette[i*4+3] = stbi__get8(s); - } else { - if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG"); - if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG"); - has_trans = 1; - for (k=0; k < s->img_n; ++k) - tc[k] = (stbi_uc) (stbi__get16be(s) & 255) * stbi__depth_scale_table[depth]; // non 8-bit images will be larger - } - break; - } - - case STBI__PNG_TYPE('I','D','A','T'): { - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG"); - if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; } - if ((int)(ioff + c.length) < (int)ioff) return 0; - if (ioff + c.length > idata_limit) { - stbi_uc *p; - if (idata_limit == 0) idata_limit = c.length > 4096 ? c.length : 4096; - while (ioff + c.length > idata_limit) - idata_limit *= 2; - p = (stbi_uc *) STBI_REALLOC(z->idata, idata_limit); if (p == NULL) return stbi__err("outofmem", "Out of memory"); - z->idata = p; - } - if (!stbi__getn(s, z->idata+ioff,c.length)) return stbi__err("outofdata","Corrupt PNG"); - ioff += c.length; - break; - } - - case STBI__PNG_TYPE('I','E','N','D'): { - stbi__uint32 raw_len, bpl; - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if (scan != STBI__SCAN_load) return 1; - if (z->idata == NULL) return stbi__err("no IDAT","Corrupt PNG"); - // initial guess for decoded data size to avoid unnecessary reallocs - bpl = (s->img_x * depth + 7) / 8; // bytes per line, per component - raw_len = bpl * s->img_y * s->img_n /* pixels */ + s->img_y /* filter mode per row */; - z->expanded = (stbi_uc *) stbi_zlib_decode_malloc_guesssize_headerflag((char *) z->idata, ioff, raw_len, (int *) &raw_len, !is_iphone); - if (z->expanded == NULL) return 0; // zlib should set error - STBI_FREE(z->idata); z->idata = NULL; - if ((req_comp == s->img_n+1 && req_comp != 3 && !pal_img_n) || has_trans) - s->img_out_n = s->img_n+1; - else - s->img_out_n = s->img_n; - if (!stbi__create_png_image(z, z->expanded, raw_len, s->img_out_n, depth, color, interlace)) return 0; - if (has_trans) - if (!stbi__compute_transparency(z, tc, s->img_out_n)) return 0; - if (is_iphone && stbi__de_iphone_flag && s->img_out_n > 2) - stbi__de_iphone(z); - if (pal_img_n) { - // pal_img_n == 3 or 4 - s->img_n = pal_img_n; // record the actual colors we had - s->img_out_n = pal_img_n; - if (req_comp >= 3) s->img_out_n = req_comp; - if (!stbi__expand_png_palette(z, palette, pal_len, s->img_out_n)) - return 0; - } - STBI_FREE(z->expanded); z->expanded = NULL; - return 1; - } - - default: - // if critical, fail - if (first) return stbi__err("first not IHDR", "Corrupt PNG"); - if ((c.type & (1 << 29)) == 0) { - #ifndef STBI_NO_FAILURE_STRINGS - // not threadsafe - static char invalid_chunk[] = "XXXX PNG chunk not known"; - invalid_chunk[0] = STBI__BYTECAST(c.type >> 24); - invalid_chunk[1] = STBI__BYTECAST(c.type >> 16); - invalid_chunk[2] = STBI__BYTECAST(c.type >> 8); - invalid_chunk[3] = STBI__BYTECAST(c.type >> 0); - #endif - return stbi__err(invalid_chunk, "PNG not supported: unknown PNG chunk type"); - } - stbi__skip(s, c.length); - break; - } - // end of PNG chunk, read and skip CRC - stbi__get32be(s); - } -} - -static unsigned char *stbi__do_png(stbi__png *p, int *x, int *y, int *n, int req_comp) -{ - unsigned char *result=NULL; - if (req_comp < 0 || req_comp > 4) return stbi__errpuc("bad req_comp", "Internal error"); - if (stbi__parse_png_file(p, STBI__SCAN_load, req_comp)) { - result = p->out; - p->out = NULL; - if (req_comp && req_comp != p->s->img_out_n) { - result = stbi__convert_format(result, p->s->img_out_n, req_comp, p->s->img_x, p->s->img_y); - p->s->img_out_n = req_comp; - if (result == NULL) return result; - } - *x = p->s->img_x; - *y = p->s->img_y; - if (n) *n = p->s->img_out_n; - } - STBI_FREE(p->out); p->out = NULL; - STBI_FREE(p->expanded); p->expanded = NULL; - STBI_FREE(p->idata); p->idata = NULL; - - return result; -} - -static unsigned char *stbi__png_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - stbi__png p; - p.s = s; - return stbi__do_png(&p, x,y,comp,req_comp); -} - -static int stbi__png_test(stbi__context *s) -{ - int r; - r = stbi__check_png_header(s); - stbi__rewind(s); - return r; -} - -static int stbi__png_info_raw(stbi__png *p, int *x, int *y, int *comp) -{ - if (!stbi__parse_png_file(p, STBI__SCAN_header, 0)) { - stbi__rewind( p->s ); - return 0; - } - if (x) *x = p->s->img_x; - if (y) *y = p->s->img_y; - if (comp) *comp = p->s->img_n; - return 1; -} - -static int stbi__png_info(stbi__context *s, int *x, int *y, int *comp) -{ - stbi__png p; - p.s = s; - return stbi__png_info_raw(&p, x, y, comp); -} -#endif - -// Microsoft/Windows BMP image - -#ifndef STBI_NO_BMP -static int stbi__bmp_test_raw(stbi__context *s) -{ - int r; - int sz; - if (stbi__get8(s) != 'B') return 0; - if (stbi__get8(s) != 'M') return 0; - stbi__get32le(s); // discard filesize - stbi__get16le(s); // discard reserved - stbi__get16le(s); // discard reserved - stbi__get32le(s); // discard data offset - sz = stbi__get32le(s); - r = (sz == 12 || sz == 40 || sz == 56 || sz == 108 || sz == 124); - return r; -} - -static int stbi__bmp_test(stbi__context *s) -{ - int r = stbi__bmp_test_raw(s); - stbi__rewind(s); - return r; -} - - -// returns 0..31 for the highest set bit -static int stbi__high_bit(unsigned int z) -{ - int n=0; - if (z == 0) return -1; - if (z >= 0x10000) n += 16, z >>= 16; - if (z >= 0x00100) n += 8, z >>= 8; - if (z >= 0x00010) n += 4, z >>= 4; - if (z >= 0x00004) n += 2, z >>= 2; - if (z >= 0x00002) n += 1, z >>= 1; - return n; -} - -static int stbi__bitcount(unsigned int a) -{ - a = (a & 0x55555555) + ((a >> 1) & 0x55555555); // max 2 - a = (a & 0x33333333) + ((a >> 2) & 0x33333333); // max 4 - a = (a + (a >> 4)) & 0x0f0f0f0f; // max 8 per 4, now 8 bits - a = (a + (a >> 8)); // max 16 per 8 bits - a = (a + (a >> 16)); // max 32 per 8 bits - return a & 0xff; -} - -static int stbi__shiftsigned(int v, int shift, int bits) -{ - int result; - int z=0; - - if (shift < 0) v <<= -shift; - else v >>= shift; - result = v; - - z = bits; - while (z < 8) { - result += v >> z; - z += bits; - } - return result; -} - -static stbi_uc *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - stbi_uc *out; - unsigned int mr=0,mg=0,mb=0,ma=0, all_a=255; - stbi_uc pal[256][4]; - int psize=0,i,j,compress=0,width; - int bpp, flip_vertically, pad, target, offset, hsz; - if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') return stbi__errpuc("not BMP", "Corrupt BMP"); - stbi__get32le(s); // discard filesize - stbi__get16le(s); // discard reserved - stbi__get16le(s); // discard reserved - offset = stbi__get32le(s); - hsz = stbi__get32le(s); - if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) return stbi__errpuc("unknown BMP", "BMP type not supported: unknown"); - if (hsz == 12) { - s->img_x = stbi__get16le(s); - s->img_y = stbi__get16le(s); - } else { - s->img_x = stbi__get32le(s); - s->img_y = stbi__get32le(s); - } - if (stbi__get16le(s) != 1) return stbi__errpuc("bad BMP", "bad BMP"); - bpp = stbi__get16le(s); - if (bpp == 1) return stbi__errpuc("monochrome", "BMP type not supported: 1-bit"); - flip_vertically = ((int) s->img_y) > 0; - s->img_y = abs((int) s->img_y); - if (hsz == 12) { - if (bpp < 24) - psize = (offset - 14 - 24) / 3; - } else { - compress = stbi__get32le(s); - if (compress == 1 || compress == 2) return stbi__errpuc("BMP RLE", "BMP type not supported: RLE"); - stbi__get32le(s); // discard sizeof - stbi__get32le(s); // discard hres - stbi__get32le(s); // discard vres - stbi__get32le(s); // discard colorsused - stbi__get32le(s); // discard max important - if (hsz == 40 || hsz == 56) { - if (hsz == 56) { - stbi__get32le(s); - stbi__get32le(s); - stbi__get32le(s); - stbi__get32le(s); - } - if (bpp == 16 || bpp == 32) { - mr = mg = mb = 0; - if (compress == 0) { - if (bpp == 32) { - mr = 0xffu << 16; - mg = 0xffu << 8; - mb = 0xffu << 0; - ma = 0xffu << 24; - all_a = 0; // if all_a is 0 at end, then we loaded alpha channel but it was all 0 - } else { - mr = 31u << 10; - mg = 31u << 5; - mb = 31u << 0; - } - } else if (compress == 3) { - mr = stbi__get32le(s); - mg = stbi__get32le(s); - mb = stbi__get32le(s); - // not documented, but generated by photoshop and handled by mspaint - if (mr == mg && mg == mb) { - // ?!?!? - return stbi__errpuc("bad BMP", "bad BMP"); - } - } else - return stbi__errpuc("bad BMP", "bad BMP"); - } - } else { - STBI_ASSERT(hsz == 108 || hsz == 124); - mr = stbi__get32le(s); - mg = stbi__get32le(s); - mb = stbi__get32le(s); - ma = stbi__get32le(s); - stbi__get32le(s); // discard color space - for (i=0; i < 12; ++i) - stbi__get32le(s); // discard color space parameters - if (hsz == 124) { - stbi__get32le(s); // discard rendering intent - stbi__get32le(s); // discard offset of profile data - stbi__get32le(s); // discard size of profile data - stbi__get32le(s); // discard reserved - } - } - if (bpp < 16) - psize = (offset - 14 - hsz) >> 2; - } - s->img_n = ma ? 4 : 3; - if (req_comp && req_comp >= 3) // we can directly decode 3 or 4 - target = req_comp; - else - target = s->img_n; // if they want monochrome, we'll post-convert - out = (stbi_uc *) stbi__malloc(target * s->img_x * s->img_y); - if (!out) return stbi__errpuc("outofmem", "Out of memory"); - if (bpp < 16) { - int z=0; - if (psize == 0 || psize > 256) { STBI_FREE(out); return stbi__errpuc("invalid", "Corrupt BMP"); } - for (i=0; i < psize; ++i) { - pal[i][2] = stbi__get8(s); - pal[i][1] = stbi__get8(s); - pal[i][0] = stbi__get8(s); - if (hsz != 12) stbi__get8(s); - pal[i][3] = 255; - } - stbi__skip(s, offset - 14 - hsz - psize * (hsz == 12 ? 3 : 4)); - if (bpp == 4) width = (s->img_x + 1) >> 1; - else if (bpp == 8) width = s->img_x; - else { STBI_FREE(out); return stbi__errpuc("bad bpp", "Corrupt BMP"); } - pad = (-width)&3; - for (j=0; j < (int) s->img_y; ++j) { - for (i=0; i < (int) s->img_x; i += 2) { - int v=stbi__get8(s),v2=0; - if (bpp == 4) { - v2 = v & 15; - v >>= 4; - } - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) out[z++] = 255; - if (i+1 == (int) s->img_x) break; - v = (bpp == 8) ? stbi__get8(s) : v2; - out[z++] = pal[v][0]; - out[z++] = pal[v][1]; - out[z++] = pal[v][2]; - if (target == 4) out[z++] = 255; - } - stbi__skip(s, pad); - } - } else { - int rshift=0,gshift=0,bshift=0,ashift=0,rcount=0,gcount=0,bcount=0,acount=0; - int z = 0; - int easy=0; - stbi__skip(s, offset - 14 - hsz); - if (bpp == 24) width = 3 * s->img_x; - else if (bpp == 16) width = 2*s->img_x; - else /* bpp = 32 and pad = 0 */ width=0; - pad = (-width) & 3; - if (bpp == 24) { - easy = 1; - } else if (bpp == 32) { - if (mb == 0xff && mg == 0xff00 && mr == 0x00ff0000 && ma == 0xff000000) - easy = 2; - } - if (!easy) { - if (!mr || !mg || !mb) { STBI_FREE(out); return stbi__errpuc("bad masks", "Corrupt BMP"); } - // right shift amt to put high bit in position #7 - rshift = stbi__high_bit(mr)-7; rcount = stbi__bitcount(mr); - gshift = stbi__high_bit(mg)-7; gcount = stbi__bitcount(mg); - bshift = stbi__high_bit(mb)-7; bcount = stbi__bitcount(mb); - ashift = stbi__high_bit(ma)-7; acount = stbi__bitcount(ma); - } - for (j=0; j < (int) s->img_y; ++j) { - if (easy) { - for (i=0; i < (int) s->img_x; ++i) { - unsigned char a; - out[z+2] = stbi__get8(s); - out[z+1] = stbi__get8(s); - out[z+0] = stbi__get8(s); - z += 3; - a = (easy == 2 ? stbi__get8(s) : 255); - all_a |= a; - if (target == 4) out[z++] = a; - } - } else { - for (i=0; i < (int) s->img_x; ++i) { - stbi__uint32 v = (bpp == 16 ? (stbi__uint32) stbi__get16le(s) : stbi__get32le(s)); - int a; - out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mr, rshift, rcount)); - out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mg, gshift, gcount)); - out[z++] = STBI__BYTECAST(stbi__shiftsigned(v & mb, bshift, bcount)); - a = (ma ? stbi__shiftsigned(v & ma, ashift, acount) : 255); - all_a |= a; - if (target == 4) out[z++] = STBI__BYTECAST(a); - } - } - stbi__skip(s, pad); - } - } - - // if alpha channel is all 0s, replace with all 255s - if (target == 4 && all_a == 0) - for (i=4*s->img_x*s->img_y-1; i >= 0; i -= 4) - out[i] = 255; - - if (flip_vertically) { - stbi_uc t; - for (j=0; j < (int) s->img_y>>1; ++j) { - stbi_uc *p1 = out + j *s->img_x*target; - stbi_uc *p2 = out + (s->img_y-1-j)*s->img_x*target; - for (i=0; i < (int) s->img_x*target; ++i) { - t = p1[i], p1[i] = p2[i], p2[i] = t; - } - } - } - - if (req_comp && req_comp != target) { - out = stbi__convert_format(out, target, req_comp, s->img_x, s->img_y); - if (out == NULL) return out; // stbi__convert_format frees input on failure - } - - *x = s->img_x; - *y = s->img_y; - if (comp) *comp = s->img_n; - return out; -} -#endif - -// Targa Truevision - TGA -// by Jonathan Dummer -#ifndef STBI_NO_TGA -static int stbi__tga_info(stbi__context *s, int *x, int *y, int *comp) -{ - int tga_w, tga_h, tga_comp; - int sz; - stbi__get8(s); // discard Offset - sz = stbi__get8(s); // color type - if( sz > 1 ) { - stbi__rewind(s); - return 0; // only RGB or indexed allowed - } - sz = stbi__get8(s); // image type - // only RGB or grey allowed, +/- RLE - if ((sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11)) return 0; - stbi__skip(s,9); - tga_w = stbi__get16le(s); - if( tga_w < 1 ) { - stbi__rewind(s); - return 0; // test width - } - tga_h = stbi__get16le(s); - if( tga_h < 1 ) { - stbi__rewind(s); - return 0; // test height - } - sz = stbi__get8(s); // bits per pixel - // only RGB or RGBA or grey allowed - if ((sz != 8) && (sz != 16) && (sz != 24) && (sz != 32)) { - stbi__rewind(s); - return 0; - } - tga_comp = sz; - if (x) *x = tga_w; - if (y) *y = tga_h; - if (comp) *comp = tga_comp / 8; - return 1; // seems to have passed everything -} - -static int stbi__tga_test(stbi__context *s) -{ - int res; - int sz; - stbi__get8(s); // discard Offset - sz = stbi__get8(s); // color type - if ( sz > 1 ) return 0; // only RGB or indexed allowed - sz = stbi__get8(s); // image type - if ( (sz != 1) && (sz != 2) && (sz != 3) && (sz != 9) && (sz != 10) && (sz != 11) ) return 0; // only RGB or grey allowed, +/- RLE - stbi__get16be(s); // discard palette start - stbi__get16be(s); // discard palette length - stbi__get8(s); // discard bits per palette color entry - stbi__get16be(s); // discard x origin - stbi__get16be(s); // discard y origin - if ( stbi__get16be(s) < 1 ) return 0; // test width - if ( stbi__get16be(s) < 1 ) return 0; // test height - sz = stbi__get8(s); // bits per pixel - if ( (sz != 8) && (sz != 16) && (sz != 24) && (sz != 32) ) - res = 0; - else - res = 1; - stbi__rewind(s); - return res; -} - -static stbi_uc *stbi__tga_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - // read in the TGA header stuff - int tga_offset = stbi__get8(s); - int tga_indexed = stbi__get8(s); - int tga_image_type = stbi__get8(s); - int tga_is_RLE = 0; - int tga_palette_start = stbi__get16le(s); - int tga_palette_len = stbi__get16le(s); - int tga_palette_bits = stbi__get8(s); - int tga_x_origin = stbi__get16le(s); - int tga_y_origin = stbi__get16le(s); - int tga_width = stbi__get16le(s); - int tga_height = stbi__get16le(s); - int tga_bits_per_pixel = stbi__get8(s); - int tga_comp = tga_bits_per_pixel / 8; - int tga_inverted = stbi__get8(s); - // image data - unsigned char *tga_data; - unsigned char *tga_palette = NULL; - int i, j; - unsigned char raw_data[4]; - int RLE_count = 0; - int RLE_repeating = 0; - int read_next_pixel = 1; - - // do a tiny bit of precessing - if ( tga_image_type >= 8 ) - { - tga_image_type -= 8; - tga_is_RLE = 1; - } - /* int tga_alpha_bits = tga_inverted & 15; */ - tga_inverted = 1 - ((tga_inverted >> 5) & 1); - - // error check - if ( //(tga_indexed) || - (tga_width < 1) || (tga_height < 1) || - (tga_image_type < 1) || (tga_image_type > 3) || - ((tga_bits_per_pixel != 8) && (tga_bits_per_pixel != 16) && - (tga_bits_per_pixel != 24) && (tga_bits_per_pixel != 32)) - ) - { - return NULL; // we don't report this as a bad TGA because we don't even know if it's TGA - } - - // If I'm paletted, then I'll use the number of bits from the palette - if ( tga_indexed ) - { - tga_comp = tga_palette_bits / 8; - } - - // tga info - *x = tga_width; - *y = tga_height; - if (comp) *comp = tga_comp; - - tga_data = (unsigned char*)stbi__malloc( (size_t)tga_width * tga_height * tga_comp ); - if (!tga_data) return stbi__errpuc("outofmem", "Out of memory"); - - // skip to the data's starting position (offset usually = 0) - stbi__skip(s, tga_offset ); - - if ( !tga_indexed && !tga_is_RLE) { - for (i=0; i < tga_height; ++i) { - int row = tga_inverted ? tga_height -i - 1 : i; - stbi_uc *tga_row = tga_data + row*tga_width*tga_comp; - stbi__getn(s, tga_row, tga_width * tga_comp); - } - } else { - // do I need to load a palette? - if ( tga_indexed) - { - // any data to skip? (offset usually = 0) - stbi__skip(s, tga_palette_start ); - // load the palette - tga_palette = (unsigned char*)stbi__malloc( tga_palette_len * tga_palette_bits / 8 ); - if (!tga_palette) { - STBI_FREE(tga_data); - return stbi__errpuc("outofmem", "Out of memory"); - } - if (!stbi__getn(s, tga_palette, tga_palette_len * tga_palette_bits / 8 )) { - STBI_FREE(tga_data); - STBI_FREE(tga_palette); - return stbi__errpuc("bad palette", "Corrupt TGA"); - } - } - // load the data - for (i=0; i < tga_width * tga_height; ++i) - { - // if I'm in RLE mode, do I need to get a RLE stbi__pngchunk? - if ( tga_is_RLE ) - { - if ( RLE_count == 0 ) - { - // yep, get the next byte as a RLE command - int RLE_cmd = stbi__get8(s); - RLE_count = 1 + (RLE_cmd & 127); - RLE_repeating = RLE_cmd >> 7; - read_next_pixel = 1; - } else if ( !RLE_repeating ) - { - read_next_pixel = 1; - } - } else - { - read_next_pixel = 1; - } - // OK, if I need to read a pixel, do it now - if ( read_next_pixel ) - { - // load however much data we did have - if ( tga_indexed ) - { - // read in 1 byte, then perform the lookup - int pal_idx = stbi__get8(s); - if ( pal_idx >= tga_palette_len ) - { - // invalid index - pal_idx = 0; - } - pal_idx *= tga_bits_per_pixel / 8; - for (j = 0; j*8 < tga_bits_per_pixel; ++j) - { - raw_data[j] = tga_palette[pal_idx+j]; - } - } else - { - // read in the data raw - for (j = 0; j*8 < tga_bits_per_pixel; ++j) - { - raw_data[j] = stbi__get8(s); - } - } - // clear the reading flag for the next pixel - read_next_pixel = 0; - } // end of reading a pixel - - // copy data - for (j = 0; j < tga_comp; ++j) - tga_data[i*tga_comp+j] = raw_data[j]; - - // in case we're in RLE mode, keep counting down - --RLE_count; - } - // do I need to invert the image? - if ( tga_inverted ) - { - for (j = 0; j*2 < tga_height; ++j) - { - int index1 = j * tga_width * tga_comp; - int index2 = (tga_height - 1 - j) * tga_width * tga_comp; - for (i = tga_width * tga_comp; i > 0; --i) - { - unsigned char temp = tga_data[index1]; - tga_data[index1] = tga_data[index2]; - tga_data[index2] = temp; - ++index1; - ++index2; - } - } - } - // clear my palette, if I had one - if ( tga_palette != NULL ) - { - STBI_FREE( tga_palette ); - } - } - - // swap RGB - if (tga_comp >= 3) - { - unsigned char* tga_pixel = tga_data; - for (i=0; i < tga_width * tga_height; ++i) - { - unsigned char temp = tga_pixel[0]; - tga_pixel[0] = tga_pixel[2]; - tga_pixel[2] = temp; - tga_pixel += tga_comp; - } - } - - // convert to target component count - if (req_comp && req_comp != tga_comp) - tga_data = stbi__convert_format(tga_data, tga_comp, req_comp, tga_width, tga_height); - - // the things I do to get rid of an error message, and yet keep - // Microsoft's C compilers happy... [8^( - tga_palette_start = tga_palette_len = tga_palette_bits = - tga_x_origin = tga_y_origin = 0; - // OK, done - return tga_data; -} -#endif - -// ************************************************************************************************* -// Photoshop PSD loader -- PD by Thatcher Ulrich, integration by Nicolas Schulz, tweaked by STB - -#ifndef STBI_NO_PSD -static int stbi__psd_test(stbi__context *s) -{ - int r = (stbi__get32be(s) == 0x38425053); - stbi__rewind(s); - return r; -} - -static stbi_uc *stbi__psd_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - int pixelCount; - int channelCount, compression; - int channel, i, count, len; - int bitdepth; - int w,h; - stbi_uc *out; - - // Check identifier - if (stbi__get32be(s) != 0x38425053) // "8BPS" - return stbi__errpuc("not PSD", "Corrupt PSD image"); - - // Check file type version. - if (stbi__get16be(s) != 1) - return stbi__errpuc("wrong version", "Unsupported version of PSD image"); - - // Skip 6 reserved bytes. - stbi__skip(s, 6 ); - - // Read the number of channels (R, G, B, A, etc). - channelCount = stbi__get16be(s); - if (channelCount < 0 || channelCount > 16) - return stbi__errpuc("wrong channel count", "Unsupported number of channels in PSD image"); - - // Read the rows and columns of the image. - h = stbi__get32be(s); - w = stbi__get32be(s); - - // Make sure the depth is 8 bits. - bitdepth = stbi__get16be(s); - if (bitdepth != 8 && bitdepth != 16) - return stbi__errpuc("unsupported bit depth", "PSD bit depth is not 8 or 16 bit"); - - // Make sure the color mode is RGB. - // Valid options are: - // 0: Bitmap - // 1: Grayscale - // 2: Indexed color - // 3: RGB color - // 4: CMYK color - // 7: Multichannel - // 8: Duotone - // 9: Lab color - if (stbi__get16be(s) != 3) - return stbi__errpuc("wrong color format", "PSD is not in RGB color format"); - - // Skip the Mode Data. (It's the palette for indexed color; other info for other modes.) - stbi__skip(s,stbi__get32be(s) ); - - // Skip the image resources. (resolution, pen tool paths, etc) - stbi__skip(s, stbi__get32be(s) ); - - // Skip the reserved data. - stbi__skip(s, stbi__get32be(s) ); - - // Find out if the data is compressed. - // Known values: - // 0: no compression - // 1: RLE compressed - compression = stbi__get16be(s); - if (compression > 1) - return stbi__errpuc("bad compression", "PSD has an unknown compression format"); - - // Create the destination image. - out = (stbi_uc *) stbi__malloc(4 * w*h); - if (!out) return stbi__errpuc("outofmem", "Out of memory"); - pixelCount = w*h; - - // Initialize the data to zero. - //memset( out, 0, pixelCount * 4 ); - - // Finally, the image data. - if (compression) { - // RLE as used by .PSD and .TIFF - // Loop until you get the number of unpacked bytes you are expecting: - // Read the next source byte into n. - // If n is between 0 and 127 inclusive, copy the next n+1 bytes literally. - // Else if n is between -127 and -1 inclusive, copy the next byte -n+1 times. - // Else if n is 128, noop. - // Endloop - - // The RLE-compressed data is preceeded by a 2-byte data count for each row in the data, - // which we're going to just skip. - stbi__skip(s, h * channelCount * 2 ); - - // Read the RLE data by channel. - for (channel = 0; channel < 4; channel++) { - stbi_uc *p; - - p = out+channel; - if (channel >= channelCount) { - // Fill this channel with default data. - for (i = 0; i < pixelCount; i++, p += 4) - *p = (channel == 3 ? 255 : 0); - } else { - // Read the RLE data. - count = 0; - while (count < pixelCount) { - len = stbi__get8(s); - if (len == 128) { - // No-op. - } else if (len < 128) { - // Copy next len+1 bytes literally. - len++; - count += len; - while (len) { - *p = stbi__get8(s); - p += 4; - len--; - } - } else if (len > 128) { - stbi_uc val; - // Next -len+1 bytes in the dest are replicated from next source byte. - // (Interpret len as a negative 8-bit int.) - len ^= 0x0FF; - len += 2; - val = stbi__get8(s); - count += len; - while (len) { - *p = val; - p += 4; - len--; - } - } - } - } - } - - } else { - // We're at the raw image data. It's each channel in order (Red, Green, Blue, Alpha, ...) - // where each channel consists of an 8-bit value for each pixel in the image. - - // Read the data by channel. - for (channel = 0; channel < 4; channel++) { - stbi_uc *p; - - p = out + channel; - if (channel >= channelCount) { - // Fill this channel with default data. - stbi_uc val = channel == 3 ? 255 : 0; - for (i = 0; i < pixelCount; i++, p += 4) - *p = val; - } else { - // Read the data. - if (bitdepth == 16) { - for (i = 0; i < pixelCount; i++, p += 4) - *p = (stbi_uc) (stbi__get16be(s) >> 8); - } else { - for (i = 0; i < pixelCount; i++, p += 4) - *p = stbi__get8(s); - } - } - } - } - - if (req_comp && req_comp != 4) { - out = stbi__convert_format(out, 4, req_comp, w, h); - if (out == NULL) return out; // stbi__convert_format frees input on failure - } - - if (comp) *comp = 4; - *y = h; - *x = w; - - return out; -} -#endif - -// ************************************************************************************************* -// Softimage PIC loader -// by Tom Seddon -// -// See http://softimage.wiki.softimage.com/index.php/INFO:_PIC_file_format -// See http://ozviz.wasp.uwa.edu.au/~pbourke/dataformats/softimagepic/ - -#ifndef STBI_NO_PIC -static int stbi__pic_is4(stbi__context *s,const char *str) -{ - int i; - for (i=0; i<4; ++i) - if (stbi__get8(s) != (stbi_uc)str[i]) - return 0; - - return 1; -} - -static int stbi__pic_test_core(stbi__context *s) -{ - int i; - - if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) - return 0; - - for(i=0;i<84;++i) - stbi__get8(s); - - if (!stbi__pic_is4(s,"PICT")) - return 0; - - return 1; -} - -typedef struct -{ - stbi_uc size,type,channel; -} stbi__pic_packet; - -static stbi_uc *stbi__readval(stbi__context *s, int channel, stbi_uc *dest) -{ - int mask=0x80, i; - - for (i=0; i<4; ++i, mask>>=1) { - if (channel & mask) { - if (stbi__at_eof(s)) return stbi__errpuc("bad file","PIC file too short"); - dest[i]=stbi__get8(s); - } - } - - return dest; -} - -static void stbi__copyval(int channel,stbi_uc *dest,const stbi_uc *src) -{ - int mask=0x80,i; - - for (i=0;i<4; ++i, mask>>=1) - if (channel&mask) - dest[i]=src[i]; -} - -static stbi_uc *stbi__pic_load_core(stbi__context *s,int width,int height,int *comp, stbi_uc *result) -{ - int act_comp=0,num_packets=0,y,chained; - stbi__pic_packet packets[10]; - - // this will (should...) cater for even some bizarre stuff like having data - // for the same channel in multiple packets. - do { - stbi__pic_packet *packet; - - if (num_packets==sizeof(packets)/sizeof(packets[0])) - return stbi__errpuc("bad format","too many packets"); - - packet = &packets[num_packets++]; - - chained = stbi__get8(s); - packet->size = stbi__get8(s); - packet->type = stbi__get8(s); - packet->channel = stbi__get8(s); - - act_comp |= packet->channel; - - if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (reading packets)"); - if (packet->size != 8) return stbi__errpuc("bad format","packet isn't 8bpp"); - } while (chained); - - *comp = (act_comp & 0x10 ? 4 : 3); // has alpha channel? - - for(y=0; ytype) { - default: - return stbi__errpuc("bad format","packet has bad compression type"); - - case 0: {//uncompressed - int x; - - for(x=0;xchannel,dest)) - return 0; - break; - } - - case 1://Pure RLE - { - int left=width, i; - - while (left>0) { - stbi_uc count,value[4]; - - count=stbi__get8(s); - if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pure read count)"); - - if (count > left) - count = (stbi_uc) left; - - if (!stbi__readval(s,packet->channel,value)) return 0; - - for(i=0; ichannel,dest,value); - left -= count; - } - } - break; - - case 2: {//Mixed RLE - int left=width; - while (left>0) { - int count = stbi__get8(s), i; - if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (mixed read count)"); - - if (count >= 128) { // Repeated - stbi_uc value[4]; - - if (count==128) - count = stbi__get16be(s); - else - count -= 127; - if (count > left) - return stbi__errpuc("bad file","scanline overrun"); - - if (!stbi__readval(s,packet->channel,value)) - return 0; - - for(i=0;ichannel,dest,value); - } else { // Raw - ++count; - if (count>left) return stbi__errpuc("bad file","scanline overrun"); - - for(i=0;ichannel,dest)) - return 0; - } - left-=count; - } - break; - } - } - } - } - - return result; -} - -static stbi_uc *stbi__pic_load(stbi__context *s,int *px,int *py,int *comp,int req_comp) -{ - stbi_uc *result; - int i, x,y; - - for (i=0; i<92; ++i) - stbi__get8(s); - - x = stbi__get16be(s); - y = stbi__get16be(s); - if (stbi__at_eof(s)) return stbi__errpuc("bad file","file too short (pic header)"); - if ((1 << 28) / x < y) return stbi__errpuc("too large", "Image too large to decode"); - - stbi__get32be(s); //skip `ratio' - stbi__get16be(s); //skip `fields' - stbi__get16be(s); //skip `pad' - - // intermediate buffer is RGBA - result = (stbi_uc *) stbi__malloc(x*y*4); - memset(result, 0xff, x*y*4); - - if (!stbi__pic_load_core(s,x,y,comp, result)) { - STBI_FREE(result); - result=0; - } - *px = x; - *py = y; - if (req_comp == 0) req_comp = *comp; - result=stbi__convert_format(result,4,req_comp,x,y); - - return result; -} - -static int stbi__pic_test(stbi__context *s) -{ - int r = stbi__pic_test_core(s); - stbi__rewind(s); - return r; -} -#endif - -// ************************************************************************************************* -// GIF loader -- public domain by Jean-Marc Lienher -- simplified/shrunk by stb - -#ifndef STBI_NO_GIF -typedef struct -{ - stbi__int16 prefix; - stbi_uc first; - stbi_uc suffix; -} stbi__gif_lzw; - -typedef struct -{ - int w,h; - stbi_uc *out, *old_out; // output buffer (always 4 components) - int flags, bgindex, ratio, transparent, eflags, delay; - stbi_uc pal[256][4]; - stbi_uc lpal[256][4]; - stbi__gif_lzw codes[4096]; - stbi_uc *color_table; - int parse, step; - int lflags; - int start_x, start_y; - int max_x, max_y; - int cur_x, cur_y; - int line_size; -} stbi__gif; - -static int stbi__gif_test_raw(stbi__context *s) -{ - int sz; - if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') return 0; - sz = stbi__get8(s); - if (sz != '9' && sz != '7') return 0; - if (stbi__get8(s) != 'a') return 0; - return 1; -} - -static int stbi__gif_test(stbi__context *s) -{ - int r = stbi__gif_test_raw(s); - stbi__rewind(s); - return r; -} - -static void stbi__gif_parse_colortable(stbi__context *s, stbi_uc pal[256][4], int num_entries, int transp) -{ - int i; - for (i=0; i < num_entries; ++i) { - pal[i][2] = stbi__get8(s); - pal[i][1] = stbi__get8(s); - pal[i][0] = stbi__get8(s); - pal[i][3] = transp == i ? 0 : 255; - } -} - -static int stbi__gif_header(stbi__context *s, stbi__gif *g, int *comp, int is_info) -{ - stbi_uc version; - if (stbi__get8(s) != 'G' || stbi__get8(s) != 'I' || stbi__get8(s) != 'F' || stbi__get8(s) != '8') - return stbi__err("not GIF", "Corrupt GIF"); - - version = stbi__get8(s); - if (version != '7' && version != '9') return stbi__err("not GIF", "Corrupt GIF"); - if (stbi__get8(s) != 'a') return stbi__err("not GIF", "Corrupt GIF"); - - stbi__g_failure_reason = ""; - g->w = stbi__get16le(s); - g->h = stbi__get16le(s); - g->flags = stbi__get8(s); - g->bgindex = stbi__get8(s); - g->ratio = stbi__get8(s); - g->transparent = -1; - - if (comp != 0) *comp = 4; // can't actually tell whether it's 3 or 4 until we parse the comments - - if (is_info) return 1; - - if (g->flags & 0x80) - stbi__gif_parse_colortable(s,g->pal, 2 << (g->flags & 7), -1); - - return 1; -} - -static int stbi__gif_info_raw(stbi__context *s, int *x, int *y, int *comp) -{ - stbi__gif g; - if (!stbi__gif_header(s, &g, comp, 1)) { - stbi__rewind( s ); - return 0; - } - if (x) *x = g.w; - if (y) *y = g.h; - return 1; -} - -static void stbi__out_gif_code(stbi__gif *g, stbi__uint16 code) -{ - stbi_uc *p, *c; - - // recurse to decode the prefixes, since the linked-list is backwards, - // and working backwards through an interleaved image would be nasty - if (g->codes[code].prefix >= 0) - stbi__out_gif_code(g, g->codes[code].prefix); - - if (g->cur_y >= g->max_y) return; - - p = &g->out[g->cur_x + g->cur_y]; - c = &g->color_table[g->codes[code].suffix * 4]; - - if (c[3] >= 128) { - p[0] = c[2]; - p[1] = c[1]; - p[2] = c[0]; - p[3] = c[3]; - } - g->cur_x += 4; - - if (g->cur_x >= g->max_x) { - g->cur_x = g->start_x; - g->cur_y += g->step; - - while (g->cur_y >= g->max_y && g->parse > 0) { - g->step = (1 << g->parse) * g->line_size; - g->cur_y = g->start_y + (g->step >> 1); - --g->parse; - } - } -} - -static stbi_uc *stbi__process_gif_raster(stbi__context *s, stbi__gif *g) -{ - stbi_uc lzw_cs; - stbi__int32 len, init_code; - stbi__uint32 first; - stbi__int32 codesize, codemask, avail, oldcode, bits, valid_bits, clear; - stbi__gif_lzw *p; - - lzw_cs = stbi__get8(s); - if (lzw_cs > 12) return NULL; - clear = 1 << lzw_cs; - first = 1; - codesize = lzw_cs + 1; - codemask = (1 << codesize) - 1; - bits = 0; - valid_bits = 0; - for (init_code = 0; init_code < clear; init_code++) { - g->codes[init_code].prefix = -1; - g->codes[init_code].first = (stbi_uc) init_code; - g->codes[init_code].suffix = (stbi_uc) init_code; - } - - // support no starting clear code - avail = clear+2; - oldcode = -1; - - len = 0; - for(;;) { - if (valid_bits < codesize) { - if (len == 0) { - len = stbi__get8(s); // start new block - if (len == 0) - return g->out; - } - --len; - bits |= (stbi__int32) stbi__get8(s) << valid_bits; - valid_bits += 8; - } else { - stbi__int32 code = bits & codemask; - bits >>= codesize; - valid_bits -= codesize; - // @OPTIMIZE: is there some way we can accelerate the non-clear path? - if (code == clear) { // clear code - codesize = lzw_cs + 1; - codemask = (1 << codesize) - 1; - avail = clear + 2; - oldcode = -1; - first = 0; - } else if (code == clear + 1) { // end of stream code - stbi__skip(s, len); - while ((len = stbi__get8(s)) > 0) - stbi__skip(s,len); - return g->out; - } else if (code <= avail) { - if (first) return stbi__errpuc("no clear code", "Corrupt GIF"); - - if (oldcode >= 0) { - p = &g->codes[avail++]; - if (avail > 4096) return stbi__errpuc("too many codes", "Corrupt GIF"); - p->prefix = (stbi__int16) oldcode; - p->first = g->codes[oldcode].first; - p->suffix = (code == avail) ? p->first : g->codes[code].first; - } else if (code == avail) - return stbi__errpuc("illegal code in raster", "Corrupt GIF"); - - stbi__out_gif_code(g, (stbi__uint16) code); - - if ((avail & codemask) == 0 && avail <= 0x0FFF) { - codesize++; - codemask = (1 << codesize) - 1; - } - - oldcode = code; - } else { - return stbi__errpuc("illegal code in raster", "Corrupt GIF"); - } - } - } -} - -static void stbi__fill_gif_background(stbi__gif *g, int x0, int y0, int x1, int y1) -{ - int x, y; - stbi_uc *c = g->pal[g->bgindex]; - for (y = y0; y < y1; y += 4 * g->w) { - for (x = x0; x < x1; x += 4) { - stbi_uc *p = &g->out[y + x]; - p[0] = c[2]; - p[1] = c[1]; - p[2] = c[0]; - p[3] = 0; - } - } -} - -// this function is designed to support animated gifs, although stb_image doesn't support it -static stbi_uc *stbi__gif_load_next(stbi__context *s, stbi__gif *g, int *comp, int req_comp) -{ - int i; - stbi_uc *prev_out = 0; - - if (g->out == 0 && !stbi__gif_header(s, g, comp,0)) - return 0; // stbi__g_failure_reason set by stbi__gif_header - - prev_out = g->out; - g->out = (stbi_uc *) stbi__malloc(4 * g->w * g->h); - if (g->out == 0) return stbi__errpuc("outofmem", "Out of memory"); - - switch ((g->eflags & 0x1C) >> 2) { - case 0: // unspecified (also always used on 1st frame) - stbi__fill_gif_background(g, 0, 0, 4 * g->w, 4 * g->w * g->h); - break; - case 1: // do not dispose - if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); - g->old_out = prev_out; - break; - case 2: // dispose to background - if (prev_out) memcpy(g->out, prev_out, 4 * g->w * g->h); - stbi__fill_gif_background(g, g->start_x, g->start_y, g->max_x, g->max_y); - break; - case 3: // dispose to previous - if (g->old_out) { - for (i = g->start_y; i < g->max_y; i += 4 * g->w) - memcpy(&g->out[i + g->start_x], &g->old_out[i + g->start_x], g->max_x - g->start_x); - } - break; - } - - for (;;) { - switch (stbi__get8(s)) { - case 0x2C: /* Image Descriptor */ - { - int prev_trans = -1; - stbi__int32 x, y, w, h; - stbi_uc *o; - - x = stbi__get16le(s); - y = stbi__get16le(s); - w = stbi__get16le(s); - h = stbi__get16le(s); - if (((x + w) > (g->w)) || ((y + h) > (g->h))) - return stbi__errpuc("bad Image Descriptor", "Corrupt GIF"); - - g->line_size = g->w * 4; - g->start_x = x * 4; - g->start_y = y * g->line_size; - g->max_x = g->start_x + w * 4; - g->max_y = g->start_y + h * g->line_size; - g->cur_x = g->start_x; - g->cur_y = g->start_y; - - g->lflags = stbi__get8(s); - - if (g->lflags & 0x40) { - g->step = 8 * g->line_size; // first interlaced spacing - g->parse = 3; - } else { - g->step = g->line_size; - g->parse = 0; - } - - if (g->lflags & 0x80) { - stbi__gif_parse_colortable(s,g->lpal, 2 << (g->lflags & 7), g->eflags & 0x01 ? g->transparent : -1); - g->color_table = (stbi_uc *) g->lpal; - } else if (g->flags & 0x80) { - if (g->transparent >= 0 && (g->eflags & 0x01)) { - prev_trans = g->pal[g->transparent][3]; - g->pal[g->transparent][3] = 0; - } - g->color_table = (stbi_uc *) g->pal; - } else - return stbi__errpuc("missing color table", "Corrupt GIF"); - - o = stbi__process_gif_raster(s, g); - if (o == NULL) return NULL; - - if (prev_trans != -1) - g->pal[g->transparent][3] = (stbi_uc) prev_trans; - - return o; - } - - case 0x21: // Comment Extension. - { - int len; - if (stbi__get8(s) == 0xF9) { // Graphic Control Extension. - len = stbi__get8(s); - if (len == 4) { - g->eflags = stbi__get8(s); - g->delay = stbi__get16le(s); - g->transparent = stbi__get8(s); - } else { - stbi__skip(s, len); - break; - } - } - while ((len = stbi__get8(s)) != 0) - stbi__skip(s, len); - break; - } - - case 0x3B: // gif stream termination code - return (stbi_uc *) s; // using '1' causes warning on some compilers - - default: - return stbi__errpuc("unknown code", "Corrupt GIF"); - } - } - - STBI_NOTUSED(req_comp); -} - -static stbi_uc *stbi__gif_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - stbi_uc *u = 0; - stbi__gif g; - memset(&g, 0, sizeof(g)); - - u = stbi__gif_load_next(s, &g, comp, req_comp); - if (u == (stbi_uc *) s) u = 0; // end of animated gif marker - if (u) { - *x = g.w; - *y = g.h; - if (req_comp && req_comp != 4) - u = stbi__convert_format(u, 4, req_comp, g.w, g.h); - } - else if (g.out) - STBI_FREE(g.out); - - return u; -} - -static int stbi__gif_info(stbi__context *s, int *x, int *y, int *comp) -{ - return stbi__gif_info_raw(s,x,y,comp); -} -#endif - -// ************************************************************************************************* -// Radiance RGBE HDR loader -// originally by Nicolas Schulz -#ifndef STBI_NO_HDR -static int stbi__hdr_test_core(stbi__context *s) -{ - const char *signature = "#?RADIANCE\n"; - int i; - for (i=0; signature[i]; ++i) - if (stbi__get8(s) != signature[i]) - return 0; - return 1; -} - -static int stbi__hdr_test(stbi__context* s) -{ - int r = stbi__hdr_test_core(s); - stbi__rewind(s); - return r; -} - -#define STBI__HDR_BUFLEN 1024 -static char *stbi__hdr_gettoken(stbi__context *z, char *buffer) -{ - int len=0; - char c = '\0'; - - c = (char) stbi__get8(z); - - while (!stbi__at_eof(z) && c != '\n') { - buffer[len++] = c; - if (len == STBI__HDR_BUFLEN-1) { - // flush to end of line - while (!stbi__at_eof(z) && stbi__get8(z) != '\n') - ; - break; - } - c = (char) stbi__get8(z); - } - - buffer[len] = 0; - return buffer; -} - -static void stbi__hdr_convert(float *output, stbi_uc *input, int req_comp) -{ - if ( input[3] != 0 ) { - float f1; - // Exponent - f1 = (float) ldexp(1.0f, input[3] - (int)(128 + 8)); - if (req_comp <= 2) - output[0] = (input[0] + input[1] + input[2]) * f1 / 3; - else { - output[0] = input[0] * f1; - output[1] = input[1] * f1; - output[2] = input[2] * f1; - } - if (req_comp == 2) output[1] = 1; - if (req_comp == 4) output[3] = 1; - } else { - switch (req_comp) { - case 4: output[3] = 1; /* fallthrough */ - case 3: output[0] = output[1] = output[2] = 0; - break; - case 2: output[1] = 1; /* fallthrough */ - case 1: output[0] = 0; - break; - } - } -} - -static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - char buffer[STBI__HDR_BUFLEN]; - char *token; - int valid = 0; - int width, height; - stbi_uc *scanline; - float *hdr_data; - int len; - unsigned char count, value; - int i, j, k, c1,c2, z; - - - // Check identifier - if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) - return stbi__errpf("not HDR", "Corrupt HDR image"); - - // Parse header - for(;;) { - token = stbi__hdr_gettoken(s,buffer); - if (token[0] == 0) break; - if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; - } - - if (!valid) return stbi__errpf("unsupported format", "Unsupported HDR format"); - - // Parse width and height - // can't use sscanf() if we're not using stdio! - token = stbi__hdr_gettoken(s,buffer); - if (strncmp(token, "-Y ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); - token += 3; - height = (int) strtol(token, &token, 10); - while (*token == ' ') ++token; - if (strncmp(token, "+X ", 3)) return stbi__errpf("unsupported data layout", "Unsupported HDR format"); - token += 3; - width = (int) strtol(token, NULL, 10); - - *x = width; - *y = height; - - if (comp) *comp = 3; - if (req_comp == 0) req_comp = 3; - - // Read data - hdr_data = (float *) stbi__malloc(height * width * req_comp * sizeof(float)); - - // Load image data - // image data is stored as some number of sca - if ( width < 8 || width >= 32768) { - // Read flat data - for (j=0; j < height; ++j) { - for (i=0; i < width; ++i) { - stbi_uc rgbe[4]; - main_decode_loop: - stbi__getn(s, rgbe, 4); - stbi__hdr_convert(hdr_data + j * width * req_comp + i * req_comp, rgbe, req_comp); - } - } - } else { - // Read RLE-encoded data - scanline = NULL; - - for (j = 0; j < height; ++j) { - c1 = stbi__get8(s); - c2 = stbi__get8(s); - len = stbi__get8(s); - if (c1 != 2 || c2 != 2 || (len & 0x80)) { - // not run-length encoded, so we have to actually use THIS data as a decoded - // pixel (note this can't be a valid pixel--one of RGB must be >= 128) - stbi_uc rgbe[4]; - rgbe[0] = (stbi_uc) c1; - rgbe[1] = (stbi_uc) c2; - rgbe[2] = (stbi_uc) len; - rgbe[3] = (stbi_uc) stbi__get8(s); - stbi__hdr_convert(hdr_data, rgbe, req_comp); - i = 1; - j = 0; - STBI_FREE(scanline); - goto main_decode_loop; // yes, this makes no sense - } - len <<= 8; - len |= stbi__get8(s); - if (len != width) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("invalid decoded scanline length", "corrupt HDR"); } - if (scanline == NULL) scanline = (stbi_uc *) stbi__malloc(width * 4); - - for (k = 0; k < 4; ++k) { - i = 0; - while (i < width) { - count = stbi__get8(s); - if (count > 128) { - // Run - value = stbi__get8(s); - count -= 128; - for (z = 0; z < count; ++z) - scanline[i++ * 4 + k] = value; - } else { - // Dump - for (z = 0; z < count; ++z) - scanline[i++ * 4 + k] = stbi__get8(s); - } - } - } - for (i=0; i < width; ++i) - stbi__hdr_convert(hdr_data+(j*width + i)*req_comp, scanline + i*4, req_comp); - } - STBI_FREE(scanline); - } - - return hdr_data; -} - -static int stbi__hdr_info(stbi__context *s, int *x, int *y, int *comp) -{ - char buffer[STBI__HDR_BUFLEN]; - char *token; - int valid = 0; - - if (strcmp(stbi__hdr_gettoken(s,buffer), "#?RADIANCE") != 0) { - stbi__rewind( s ); - return 0; - } - - for(;;) { - token = stbi__hdr_gettoken(s,buffer); - if (token[0] == 0) break; - if (strcmp(token, "FORMAT=32-bit_rle_rgbe") == 0) valid = 1; - } - - if (!valid) { - stbi__rewind( s ); - return 0; - } - token = stbi__hdr_gettoken(s,buffer); - if (strncmp(token, "-Y ", 3)) { - stbi__rewind( s ); - return 0; - } - token += 3; - *y = (int) strtol(token, &token, 10); - while (*token == ' ') ++token; - if (strncmp(token, "+X ", 3)) { - stbi__rewind( s ); - return 0; - } - token += 3; - *x = (int) strtol(token, NULL, 10); - *comp = 3; - return 1; -} -#endif // STBI_NO_HDR - -#ifndef STBI_NO_BMP -static int stbi__bmp_info(stbi__context *s, int *x, int *y, int *comp) -{ - int hsz; - if (stbi__get8(s) != 'B' || stbi__get8(s) != 'M') { - stbi__rewind( s ); - return 0; - } - stbi__skip(s,12); - hsz = stbi__get32le(s); - if (hsz != 12 && hsz != 40 && hsz != 56 && hsz != 108 && hsz != 124) { - stbi__rewind( s ); - return 0; - } - if (hsz == 12) { - *x = stbi__get16le(s); - *y = stbi__get16le(s); - } else { - *x = stbi__get32le(s); - *y = stbi__get32le(s); - } - if (stbi__get16le(s) != 1) { - stbi__rewind( s ); - return 0; - } - *comp = stbi__get16le(s) / 8; - return 1; -} -#endif - -#ifndef STBI_NO_PSD -static int stbi__psd_info(stbi__context *s, int *x, int *y, int *comp) -{ - int channelCount; - if (stbi__get32be(s) != 0x38425053) { - stbi__rewind( s ); - return 0; - } - if (stbi__get16be(s) != 1) { - stbi__rewind( s ); - return 0; - } - stbi__skip(s, 6); - channelCount = stbi__get16be(s); - if (channelCount < 0 || channelCount > 16) { - stbi__rewind( s ); - return 0; - } - *y = stbi__get32be(s); - *x = stbi__get32be(s); - if (stbi__get16be(s) != 8) { - stbi__rewind( s ); - return 0; - } - if (stbi__get16be(s) != 3) { - stbi__rewind( s ); - return 0; - } - *comp = 4; - return 1; -} -#endif - -#ifndef STBI_NO_PIC -static int stbi__pic_info(stbi__context *s, int *x, int *y, int *comp) -{ - int act_comp=0,num_packets=0,chained; - stbi__pic_packet packets[10]; - - if (!stbi__pic_is4(s,"\x53\x80\xF6\x34")) { - stbi__rewind(s); - return 0; - } - - stbi__skip(s, 88); - - *x = stbi__get16be(s); - *y = stbi__get16be(s); - if (stbi__at_eof(s)) { - stbi__rewind( s); - return 0; - } - if ( (*x) != 0 && (1 << 28) / (*x) < (*y)) { - stbi__rewind( s ); - return 0; - } - - stbi__skip(s, 8); - - do { - stbi__pic_packet *packet; - - if (num_packets==sizeof(packets)/sizeof(packets[0])) - return 0; - - packet = &packets[num_packets++]; - chained = stbi__get8(s); - packet->size = stbi__get8(s); - packet->type = stbi__get8(s); - packet->channel = stbi__get8(s); - act_comp |= packet->channel; - - if (stbi__at_eof(s)) { - stbi__rewind( s ); - return 0; - } - if (packet->size != 8) { - stbi__rewind( s ); - return 0; - } - } while (chained); - - *comp = (act_comp & 0x10 ? 4 : 3); - - return 1; -} -#endif - -// ************************************************************************************************* -// Portable Gray Map and Portable Pixel Map loader -// by Ken Miller -// -// PGM: http://netpbm.sourceforge.net/doc/pgm.html -// PPM: http://netpbm.sourceforge.net/doc/ppm.html -// -// Known limitations: -// Does not support comments in the header section -// Does not support ASCII image data (formats P2 and P3) -// Does not support 16-bit-per-channel - -#ifndef STBI_NO_PNM - -static int stbi__pnm_test(stbi__context *s) -{ - char p, t; - p = (char) stbi__get8(s); - t = (char) stbi__get8(s); - if (p != 'P' || (t != '5' && t != '6')) { - stbi__rewind( s ); - return 0; - } - return 1; -} - -static stbi_uc *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req_comp) -{ - stbi_uc *out; - if (!stbi__pnm_info(s, (int *)&s->img_x, (int *)&s->img_y, (int *)&s->img_n)) - return 0; - *x = s->img_x; - *y = s->img_y; - *comp = s->img_n; - - out = (stbi_uc *) stbi__malloc(s->img_n * s->img_x * s->img_y); - if (!out) return stbi__errpuc("outofmem", "Out of memory"); - stbi__getn(s, out, s->img_n * s->img_x * s->img_y); - - if (req_comp && req_comp != s->img_n) { - out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y); - if (out == NULL) return out; // stbi__convert_format frees input on failure - } - return out; -} - -static int stbi__pnm_isspace(char c) -{ - return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r'; -} - -static void stbi__pnm_skip_whitespace(stbi__context *s, char *c) -{ - while (!stbi__at_eof(s) && stbi__pnm_isspace(*c)) - *c = (char) stbi__get8(s); -} - -static int stbi__pnm_isdigit(char c) -{ - return c >= '0' && c <= '9'; -} - -static int stbi__pnm_getinteger(stbi__context *s, char *c) -{ - int value = 0; - - while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) { - value = value*10 + (*c - '0'); - *c = (char) stbi__get8(s); - } - - return value; -} - -static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp) -{ - int maxv; - char c, p, t; - - stbi__rewind( s ); - - // Get identifier - p = (char) stbi__get8(s); - t = (char) stbi__get8(s); - if (p != 'P' || (t != '5' && t != '6')) { - stbi__rewind( s ); - return 0; - } - - *comp = (t == '6') ? 3 : 1; // '5' is 1-component .pgm; '6' is 3-component .ppm - - c = (char) stbi__get8(s); - stbi__pnm_skip_whitespace(s, &c); - - *x = stbi__pnm_getinteger(s, &c); // read width - stbi__pnm_skip_whitespace(s, &c); - - *y = stbi__pnm_getinteger(s, &c); // read height - stbi__pnm_skip_whitespace(s, &c); - - maxv = stbi__pnm_getinteger(s, &c); // read max value - - if (maxv > 255) - return stbi__err("max value > 255", "PPM image not 8-bit"); - else - return 1; -} -#endif - -static int stbi__info_main(stbi__context *s, int *x, int *y, int *comp) -{ - #ifndef STBI_NO_JPEG - if (stbi__jpeg_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_PNG - if (stbi__png_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_GIF - if (stbi__gif_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_BMP - if (stbi__bmp_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_PSD - if (stbi__psd_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_PIC - if (stbi__pic_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_PNM - if (stbi__pnm_info(s, x, y, comp)) return 1; - #endif - - #ifndef STBI_NO_HDR - if (stbi__hdr_info(s, x, y, comp)) return 1; - #endif - - // test tga last because it's a crappy test! - #ifndef STBI_NO_TGA - if (stbi__tga_info(s, x, y, comp)) - return 1; - #endif - return stbi__err("unknown image type", "Image not of any known type, or corrupt"); -} - -#ifndef STBI_NO_STDIO -STBIDEF int stbi_info(char const *filename, int *x, int *y, int *comp) -{ - FILE *f = stbi__fopen(filename, "rb"); - int result; - if (!f) return stbi__err("can't fopen", "Unable to open file"); - result = stbi_info_from_file(f, x, y, comp); - fclose(f); - return result; -} - -STBIDEF int stbi_info_from_file(FILE *f, int *x, int *y, int *comp) -{ - int r; - stbi__context s; - long pos = ftell(f); - stbi__start_file(&s, f); - r = stbi__info_main(&s,x,y,comp); - fseek(f,pos,SEEK_SET); - return r; -} -#endif // !STBI_NO_STDIO - -STBIDEF int stbi_info_from_memory(stbi_uc const *buffer, int len, int *x, int *y, int *comp) -{ - stbi__context s; - stbi__start_mem(&s,buffer,len); - return stbi__info_main(&s,x,y,comp); -} - -STBIDEF int stbi_info_from_callbacks(stbi_io_callbacks const *c, void *user, int *x, int *y, int *comp) -{ - stbi__context s; - stbi__start_callbacks(&s, (stbi_io_callbacks *) c, user); - return stbi__info_main(&s,x,y,comp); -} - -#endif // STB_IMAGE_IMPLEMENTATION - -/* - revision history: - 2.08 (2015-09-13) fix to 2.07 cleanup, reading RGB PSD as RGBA - 2.07 (2015-09-13) fix compiler warnings - partial animated GIF support - limited 16-bit PSD support - #ifdef unused functions - bug with < 92 byte PIC,PNM,HDR,TGA - 2.06 (2015-04-19) fix bug where PSD returns wrong '*comp' value - 2.05 (2015-04-19) fix bug in progressive JPEG handling, fix warning - 2.04 (2015-04-15) try to re-enable SIMD on MinGW 64-bit - 2.03 (2015-04-12) extra corruption checking (mmozeiko) - stbi_set_flip_vertically_on_load (nguillemot) - fix NEON support; fix mingw support - 2.02 (2015-01-19) fix incorrect assert, fix warning - 2.01 (2015-01-17) fix various warnings; suppress SIMD on gcc 32-bit without -msse2 - 2.00b (2014-12-25) fix STBI_MALLOC in progressive JPEG - 2.00 (2014-12-25) optimize JPG, including x86 SSE2 & NEON SIMD (ryg) - progressive JPEG (stb) - PGM/PPM support (Ken Miller) - STBI_MALLOC,STBI_REALLOC,STBI_FREE - GIF bugfix -- seemingly never worked - STBI_NO_*, STBI_ONLY_* - 1.48 (2014-12-14) fix incorrectly-named assert() - 1.47 (2014-12-14) 1/2/4-bit PNG support, both direct and paletted (Omar Cornut & stb) - optimize PNG (ryg) - fix bug in interlaced PNG with user-specified channel count (stb) - 1.46 (2014-08-26) - fix broken tRNS chunk (colorkey-style transparency) in non-paletted PNG - 1.45 (2014-08-16) - fix MSVC-ARM internal compiler error by wrapping malloc - 1.44 (2014-08-07) - various warning fixes from Ronny Chevalier - 1.43 (2014-07-15) - fix MSVC-only compiler problem in code changed in 1.42 - 1.42 (2014-07-09) - don't define _CRT_SECURE_NO_WARNINGS (affects user code) - fixes to stbi__cleanup_jpeg path - added STBI_ASSERT to avoid requiring assert.h - 1.41 (2014-06-25) - fix search&replace from 1.36 that messed up comments/error messages - 1.40 (2014-06-22) - fix gcc struct-initialization warning - 1.39 (2014-06-15) - fix to TGA optimization when req_comp != number of components in TGA; - fix to GIF loading because BMP wasn't rewinding (whoops, no GIFs in my test suite) - add support for BMP version 5 (more ignored fields) - 1.38 (2014-06-06) - suppress MSVC warnings on integer casts truncating values - fix accidental rename of 'skip' field of I/O - 1.37 (2014-06-04) - remove duplicate typedef - 1.36 (2014-06-03) - convert to header file single-file library - if de-iphone isn't set, load iphone images color-swapped instead of returning NULL - 1.35 (2014-05-27) - various warnings - fix broken STBI_SIMD path - fix bug where stbi_load_from_file no longer left file pointer in correct place - fix broken non-easy path for 32-bit BMP (possibly never used) - TGA optimization by Arseny Kapoulkine - 1.34 (unknown) - use STBI_NOTUSED in stbi__resample_row_generic(), fix one more leak in tga failure case - 1.33 (2011-07-14) - make stbi_is_hdr work in STBI_NO_HDR (as specified), minor compiler-friendly improvements - 1.32 (2011-07-13) - support for "info" function for all supported filetypes (SpartanJ) - 1.31 (2011-06-20) - a few more leak fixes, bug in PNG handling (SpartanJ) - 1.30 (2011-06-11) - added ability to load files via callbacks to accomidate custom input streams (Ben Wenger) - removed deprecated format-specific test/load functions - removed support for installable file formats (stbi_loader) -- would have been broken for IO callbacks anyway - error cases in bmp and tga give messages and don't leak (Raymond Barbiero, grisha) - fix inefficiency in decoding 32-bit BMP (David Woo) - 1.29 (2010-08-16) - various warning fixes from Aurelien Pocheville - 1.28 (2010-08-01) - fix bug in GIF palette transparency (SpartanJ) - 1.27 (2010-08-01) - cast-to-stbi_uc to fix warnings - 1.26 (2010-07-24) - fix bug in file buffering for PNG reported by SpartanJ - 1.25 (2010-07-17) - refix trans_data warning (Won Chun) - 1.24 (2010-07-12) - perf improvements reading from files on platforms with lock-heavy fgetc() - minor perf improvements for jpeg - deprecated type-specific functions so we'll get feedback if they're needed - attempt to fix trans_data warning (Won Chun) - 1.23 fixed bug in iPhone support - 1.22 (2010-07-10) - removed image *writing* support - stbi_info support from Jetro Lauha - GIF support from Jean-Marc Lienher - iPhone PNG-extensions from James Brown - warning-fixes from Nicolas Schulz and Janez Zemva (i.stbi__err. Janez (U+017D)emva) - 1.21 fix use of 'stbi_uc' in header (reported by jon blow) - 1.20 added support for Softimage PIC, by Tom Seddon - 1.19 bug in interlaced PNG corruption check (found by ryg) - 1.18 (2008-08-02) - fix a threading bug (local mutable static) - 1.17 support interlaced PNG - 1.16 major bugfix - stbi__convert_format converted one too many pixels - 1.15 initialize some fields for thread safety - 1.14 fix threadsafe conversion bug - header-file-only version (#define STBI_HEADER_FILE_ONLY before including) - 1.13 threadsafe - 1.12 const qualifiers in the API - 1.11 Support installable IDCT, colorspace conversion routines - 1.10 Fixes for 64-bit (don't use "unsigned long") - optimized upsampling by Fabian "ryg" Giesen - 1.09 Fix format-conversion for PSD code (bad global variables!) - 1.08 Thatcher Ulrich's PSD code integrated by Nicolas Schulz - 1.07 attempt to fix C++ warning/errors again - 1.06 attempt to fix C++ warning/errors again - 1.05 fix TGA loading to return correct *comp and use good luminance calc - 1.04 default float alpha is 1, not 255; use 'void *' for stbi_image_free - 1.03 bugfixes to STBI_NO_STDIO, STBI_NO_HDR - 1.02 support for (subset of) HDR files, float interface for preferred access to them - 1.01 fix bug: possible bug in handling right-side up bmps... not sure - fix bug: the stbi__bmp_load() and stbi__tga_load() functions didn't work at all - 1.00 interface to zlib that skips zlib header - 0.99 correct handling of alpha in palette - 0.98 TGA loader by lonesock; dynamically add loaders (untested) - 0.97 jpeg errors on too large a file; also catch another malloc failure - 0.96 fix detection of invalid v value - particleman@mollyrocket forum - 0.95 during header scan, seek to markers in case of padding - 0.94 STBI_NO_STDIO to disable stdio usage; rename all #defines the same - 0.93 handle jpegtran output; verbose errors - 0.92 read 4,8,16,24,32-bit BMP files of several formats - 0.91 output 24-bit Windows 3.0 BMP files - 0.90 fix a few more warnings; bump version number to approach 1.0 - 0.61 bugfixes due to Marc LeBlanc, Christopher Lloyd - 0.60 fix compiling as c++ - 0.59 fix warnings: merge Dave Moore's -Wall fixes - 0.58 fix bug: zlib uncompressed mode len/nlen was wrong endian - 0.57 fix bug: jpg last huffman symbol before marker was >9 bits but less than 16 available - 0.56 fix bug: zlib uncompressed mode len vs. nlen - 0.55 fix bug: restart_interval not initialized to 0 - 0.54 allow NULL for 'int *comp' - 0.53 fix bug in png 3->4; speedup png decoding - 0.52 png handles req_comp=3,4 directly; minor cleanup; jpeg comments - 0.51 obey req_comp requests, 1-component jpegs return as 1-component, - on 'test' only check type, not whether we support this variant - 0.50 (2006-11-19) - first released version -*/ diff --git a/deps/nuklear/extra_font/Cousine-Regular.ttf b/deps/nuklear/extra_font/Cousine-Regular.ttf deleted file mode 100644 index 70a0bf90..00000000 Binary files a/deps/nuklear/extra_font/Cousine-Regular.ttf and /dev/null differ diff --git a/deps/nuklear/extra_font/DroidSans.ttf b/deps/nuklear/extra_font/DroidSans.ttf deleted file mode 100644 index 767c63ad..00000000 Binary files a/deps/nuklear/extra_font/DroidSans.ttf and /dev/null differ diff --git a/deps/nuklear/extra_font/Karla-Regular.ttf b/deps/nuklear/extra_font/Karla-Regular.ttf deleted file mode 100644 index 81b3de6e..00000000 Binary files a/deps/nuklear/extra_font/Karla-Regular.ttf and /dev/null differ diff --git a/deps/nuklear/extra_font/ProggyClean.ttf b/deps/nuklear/extra_font/ProggyClean.ttf deleted file mode 100644 index 0270cdfe..00000000 Binary files a/deps/nuklear/extra_font/ProggyClean.ttf and /dev/null differ diff --git a/deps/nuklear/extra_font/ProggyTiny.ttf b/deps/nuklear/extra_font/ProggyTiny.ttf deleted file mode 100644 index 1c4312c3..00000000 Binary files a/deps/nuklear/extra_font/ProggyTiny.ttf and /dev/null differ diff --git a/deps/nuklear/extra_font/Raleway-Bold.ttf b/deps/nuklear/extra_font/Raleway-Bold.ttf deleted file mode 100644 index 7aa37f01..00000000 Binary files a/deps/nuklear/extra_font/Raleway-Bold.ttf and /dev/null differ diff --git a/deps/nuklear/extra_font/Roboto-Bold.ttf b/deps/nuklear/extra_font/Roboto-Bold.ttf deleted file mode 100644 index aaf374d2..00000000 Binary files a/deps/nuklear/extra_font/Roboto-Bold.ttf and /dev/null differ diff --git a/deps/nuklear/extra_font/Roboto-Light.ttf b/deps/nuklear/extra_font/Roboto-Light.ttf deleted file mode 100644 index 664e1b2f..00000000 Binary files a/deps/nuklear/extra_font/Roboto-Light.ttf and /dev/null differ diff --git a/deps/nuklear/extra_font/Roboto-Regular.ttf b/deps/nuklear/extra_font/Roboto-Regular.ttf deleted file mode 100644 index 3e6e2e76..00000000 Binary files a/deps/nuklear/extra_font/Roboto-Regular.ttf and /dev/null differ diff --git a/deps/nuklear/extra_font/kenvector_future.ttf b/deps/nuklear/extra_font/kenvector_future.ttf deleted file mode 100644 index 39ebdfaa..00000000 Binary files a/deps/nuklear/extra_font/kenvector_future.ttf and /dev/null differ diff --git a/deps/nuklear/extra_font/kenvector_future_thin.ttf b/deps/nuklear/extra_font/kenvector_future_thin.ttf deleted file mode 100644 index 9f4b4fa5..00000000 Binary files a/deps/nuklear/extra_font/kenvector_future_thin.ttf and /dev/null differ diff --git a/deps/nuklear/nuklear.h b/deps/nuklear/nuklear.h deleted file mode 100644 index 271ca942..00000000 --- a/deps/nuklear/nuklear.h +++ /dev/null @@ -1,22007 +0,0 @@ -/* - Nuklear - v1.20 - public domain - no warrenty implied; use at your own risk. - authored from 2015-2016 by Micha Mettke - -ABOUT: - This is a minimal state graphical user interface single header toolkit - written in ANSI C and licensed under public domain. - It was designed as a simple embeddable user interface for application and does - not have any dependencies, a default renderbackend or OS window and input handling - but instead provides a very modular library approach by using simple input state - for input and draw commands describing primitive shapes as output. - So instead of providing a layered library that tries to abstract over a number - of platform and render backends it only focuses on the actual UI. - -VALUES: - - Graphical user interface toolkit - - Single header library - - Written in C89 (a.k.a. ANSI C or ISO C90) - - Small codebase (~17kLOC) - - Focus on portability, efficiency and simplicity - - No dependencies (not even the standard library if not wanted) - - Fully skinnable and customizable - - Low memory footprint with total memory control if needed or wanted - - UTF-8 support - - No global or hidden state - - Customizable library modules (you can compile and use only what you need) - - Optional font baker and vertex buffer output - -USAGE: - This library is self contained in one single header file and can be used either - in header only mode or in implementation mode. The header only mode is used - by default when included and allows including this header in other headers - and does not contain the actual implementation. - - The implementation mode requires to define the preprocessor macro - NK_IMPLEMENTATION in *one* .c/.cpp file before #includeing this file, e.g.: - - #define NK_IMPLEMENTATION - #include "nuklear.h" - - Also optionally define the symbols listed in the section "OPTIONAL DEFINES" - below in header and implementation mode if you want to use additional functionality - or need more control over the library. - IMPORTANT: Every time you include "nuklear.h" you have to define the same flags. - This is very important not doing it either leads to compiler errors - or even worse stack corruptions. - -FEATURES: - - Absolutely no platform dependend code - - Memory management control ranging from/to - - Ease of use by allocating everything from standard library - - Control every byte of memory inside the library - - Font handling control ranging from/to - - Use your own font implementation for everything - - Use this libraries internal font baking and handling API - - Drawing output control ranging from/to - - Simple shapes for more high level APIs which already have drawing capabilities - - Hardware accessible anti-aliased vertex buffer output - - Customizable colors and properties ranging from/to - - Simple changes to color by filling a simple color table - - Complete control with ability to use skinning to decorate widgets - - Bendable UI library with widget ranging from/to - - Basic widgets like buttons, checkboxes, slider, ... - - Advanced widget like abstract comboboxes, contextual menus,... - - Compile time configuration to only compile what you need - - Subset which can be used if you do not want to link or use the standard library - - Can be easily modified to only update on user input instead of frame updates - -OPTIONAL DEFINES: - NK_PRIVATE - If defined declares all functions as static, so they can only be accessed - inside the file that contains the implementation - - NK_INCLUDE_FIXED_TYPES - If defined it will include header 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. - If used needs to be defined for implementation and header - - NK_INCLUDE_DEFAULT_ALLOCATOR - if defined it will include header and provide additional functions - to use this library without caring for memory allocation control and therefore - ease memory management. - Adds the standard library with malloc and free so don't define if you - don't want to link to the standard library - If used needs to be defined for implementation and header - - NK_INCLUDE_STANDARD_IO - if defined it will include header and provide - additional functions depending on file loading. - Adds the standard library with fopen, fclose,... so don't define this - if you don't want to link to the standard library - If used needs to be defined for implementation and header - - NK_INCLUDE_STANDARD_VARARGS - if defined it will include header and provide - additional functions depending on variable arguments - Adds the standard library with va_list and so don't define this if - you don't want to link to the standard library - If used needs to be defined for implementation and header - - 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,... - If used needs to be defined for implementation and header - - NK_INCLUDE_FONT_BAKING - Defining this adds the `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. - If used needs to be defined for implementation and header - - 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 - Enabling this adds ~12kb to global stack memory - If used needs to be defined for implementation and header - - 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. - If used needs to be defined for implementation and header - - NK_BUTTON_TRIGGER_ON_RELEASE - Different platforms require button clicks occuring 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. - If used it is only required to be defined for the implementation part - - 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. - - NK_ASSERT - If you don't define this, nuklear will use with assert(). - Adds the standard library so define to nothing of not wanted - If used needs to be defined for implementation and header - - 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. - If used needs to be defined for implementation and header - - NK_MAX_NUMBER_BUFFER - Maximum buffer size for the conversion buffer between float and string - Under normal circumstances this should be more than sufficient. - If used needs to be defined for implementation and header - - 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. - If used it is only required to be defined for the implementation part - - NK_MEMSET - You can define this to 'memset' or your own memset implementation - replacement. If not nuklear will use its own version. - If used it is only required to be defined for the implementation part - - NK_MEMCPY - You can define this to 'memcpy' or your own memcpy implementation - replacement. If not nuklear will use its own version. - If used it is only required to be defined for the implementation part - - NK_SQRT - You can define this to 'sqrt' or your own sqrt implementation - replacement. If not nuklear will use its own slow and not highly - accurate version. - If used it is only required to be defined for the implementation part - - NK_SIN - You can define this to 'sinf' or your own sine implementation - replacement. If not nuklear will use its own approximation implementation. - If used it is only required to be defined for the implementation part - - NK_COS - You can define this to 'cosf' or your own cosine implementation - replacement. If not nuklear will use its own approximation implementation. - If used it is only required to be defined for the implementation part - - 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!). - If used it is only required to be defined for the implementation part - - 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!). - If used it is only required to be defined for the implementation part - - 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. - If used it is only required to be defined for the implementation part - - NK_BYTE - NK_INT16 - NK_UINT16 - NK_INT32 - NK_UINT32 - NK_SIZE_TYPE - NK_POINTER_TYPE - If you compile without NK_USE_FIXED_TYPE then a number of standard types - will be selected and compile time validated. If they are incorrect you can - define the correct types by overloading these type defines. - -CREDITS: - Developed by Micha Mettke and every direct or indirect contributor. - - Embeds stb_texedit, stb_truetype and stb_rectpack by Sean Barret (public domain) - Embeds ProggyClean.ttf font by Tristan Grimmer (MIT license). - - Big thank you to Omar Cornut (ocornut@github) for his imgui library and - giving me the inspiration for this library, Casey Muratori for handmade hero - and his original immediate mode graphical user interface idea and Sean - Barret for his amazing single header libraries which restored my faith - in libraries and brought me to create some of my own. - -LICENSE: - This software is dual-licensed to the public domain and under the following - license: you are granted a perpetual, irrevocable license to copy, modify, - publish and distribute this file as you see fit. -*/ -#ifndef NK_NUKLEAR_H_ -#define NK_NUKLEAR_H_ - -#ifdef __cplusplus -extern "C" { -#endif -/* - * ============================================================== - * - * CONSTANTS - * - * =============================================================== - */ -#define NK_UNDEFINED (-1.0f) -#define NK_UTF_INVALID 0xFFFD /* internal invalid utf8 rune */ -#define NK_UTF_SIZE 4 /* describes the number of bytes a glyph consists of*/ -#ifndef NK_INPUT_MAX -#define NK_INPUT_MAX 16 -#endif -#ifndef NK_MAX_NUMBER_BUFFER -#define NK_MAX_NUMBER_BUFFER 64 -#endif -#ifndef NK_SCROLLBAR_HIDING_TIMEOUT -#define NK_SCROLLBAR_HIDING_TIMEOUT 4.0f -#endif - -/* - * ============================================================== - * - * HELPER - * - * =============================================================== - */ -#ifndef NK_API -#ifdef NK_PRIVATE -#define NK_API static -#else -#define NK_API extern -#endif -#endif - -#define NK_INTERN static -#define NK_STORAGE static -#define NK_GLOBAL static - -#define NK_FLAG(x) (1 << (x)) -#define NK_STRINGIFY(x) #x -#define NK_MACRO_STRINGIFY(x) NK_STRINGIFY(x) -#define NK_STRING_JOIN_IMMEDIATE(arg1, arg2) arg1 ## arg2 -#define NK_STRING_JOIN_DELAY(arg1, arg2) NK_STRING_JOIN_IMMEDIATE(arg1, arg2) -#define NK_STRING_JOIN(arg1, arg2) NK_STRING_JOIN_DELAY(arg1, arg2) - -#ifdef _MSC_VER -#define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__COUNTER__) -#else -#define NK_UNIQUE_NAME(name) NK_STRING_JOIN(name,__LINE__) -#endif - -#ifndef NK_STATIC_ASSERT -#define NK_STATIC_ASSERT(exp) typedef char NK_UNIQUE_NAME(_dummy_array)[(exp)?1:-1] -#endif - -#ifndef NK_FILE_LINE -#ifdef _MSC_VER -#define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__COUNTER__) -#else -#define NK_FILE_LINE __FILE__ ":" NK_MACRO_STRINGIFY(__LINE__) -#endif -#endif - -#define NK_MIN(a,b) ((a) < (b) ? (a) : (b)) -#define NK_MAX(a,b) ((a) < (b) ? (b) : (a)) -#define NK_CLAMP(i,v,x) (NK_MAX(NK_MIN(v,x), i)) - -/* - * =============================================================== - * - * BASIC - * - * =============================================================== - */ -#ifdef NK_INCLUDE_FIXED_TYPES - #include - #define NK_INT8 int8_t - #define NK_UINT8 uint8_t - #define NK_INT16 int16_t - #define NK_UINT16 uint16_t - #define NK_INT32 int32_t - #define NK_UINT32 uint32_t - #define NK_SIZE_TYPE uintptr_t - #define NK_POINTER_TYPE uintptr_t -#else - #ifndef NK_INT8 - #define NK_INT8 char - #endif - #ifndef NK_UINT8 - #define NK_UINT8 unsigned char - #endif - #ifndef NK_INT16 - #define NK_INT16 signed short - #endif - #ifndef NK_UINT16 - #define NK_UINT16 unsigned short - #endif - #ifndef NK_INT32 - #if defined(_MSC_VER) - #define NK_INT32 __int32 - #else - #define NK_INT32 signed int - #endif - #endif - #ifndef NK_UINT32 - #if defined(_MSC_VER) - #define NK_UINT32 unsigned __int32 - #else - #define NK_UINT32 unsigned int - #endif - #endif - #ifndef NK_SIZE_TYPE - #if (defined(__WIN32) || defined(WIN32)) && defined(_MSC_VER) - #define NK_SIZE_TYPE __int32 - #elif defined(__WIN64) && defined(_MSC_VER) - #define NK_SIZE_TYPE __int64 - #elif defined(__GNUC__) || defined(__clang__) - #if defined(__x86_64__) || defined(__ppc64__) - #define NK_SIZE_TYPE unsigned long - #else - #define NK_SIZE_TYPE unsigned int - #endif - #else - #define NK_SIZE_TYPE unsigned long - #endif - #endif - #ifndef NK_POINTER_TYPE - #if (defined(__WIN32) || defined(WIN32)) && defined(_MSC_VER) - #define NK_POINTER_TYPE unsigned __int32 - #elif defined(__WIN64) && defined(_MSC_VER) - #define NK_POINTER_TYPE unsigned __int64 - #elif defined(__GNUC__) || defined(__clang__) - #if defined(__x86_64__) || defined(__ppc64__) - #define NK_POINTER_TYPE unsigned long - #else - #define NK_POINTER_TYPE unsigned int - #endif - #else - #define NK_POINTER_TYPE unsigned long - #endif - #endif -#endif - -typedef NK_INT8 nk_char; -typedef NK_UINT8 nk_uchar; -typedef NK_UINT8 nk_byte; -typedef NK_INT16 nk_short; -typedef NK_UINT16 nk_ushort; -typedef NK_INT32 nk_int; -typedef NK_UINT32 nk_uint; -typedef NK_SIZE_TYPE nk_size; -typedef NK_POINTER_TYPE nk_ptr; - -typedef nk_uint nk_hash; -typedef nk_uint nk_flags; -typedef nk_uint nk_rune; - -/* Make sure correct type size: - * This will fire with a negative subscript error if the type sizes - * are set incorrectly by the compiler, and compile out if not */ -NK_STATIC_ASSERT(sizeof(nk_short) == 2); -NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); -NK_STATIC_ASSERT(sizeof(nk_uint) == 4); -NK_STATIC_ASSERT(sizeof(nk_int) == 4); -NK_STATIC_ASSERT(sizeof(nk_byte) == 1); -NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); -NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); -NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); -NK_STATIC_ASSERT(sizeof(nk_ptr) >= sizeof(void*)); - -/* ============================================================================ - * - * API - * - * =========================================================================== */ -struct nk_buffer; -struct nk_allocator; -struct nk_command_buffer; -struct nk_draw_command; -struct nk_convert_config; -struct nk_style_item; -struct nk_text_edit; -struct nk_draw_list; -struct nk_user_font; -struct nk_panel; -struct nk_context; -struct nk_draw_vertex_layout_element; -struct nk_style_button; -struct nk_style_toggle; -struct nk_style_selectable; -struct nk_style_slide; -struct nk_style_progress; -struct nk_style_scrollbar; -struct nk_style_edit; -struct nk_style_property; -struct nk_style_chart; -struct nk_style_combo; -struct nk_style_tab; -struct nk_style_window_header; -struct nk_style_window; - -enum {nk_false, nk_true}; -struct nk_color {nk_byte r,g,b,a;}; -struct nk_colorf {float r,g,b,a;}; -struct nk_vec2 {float x,y;}; -struct nk_vec2i {short x, y;}; -struct nk_rect {float x,y,w,h;}; -struct nk_recti {short x,y,w,h;}; -typedef char nk_glyph[NK_UTF_SIZE]; -typedef union {void *ptr; int id;} nk_handle; -struct nk_image {nk_handle handle;unsigned short w,h;unsigned short region[4];}; -struct nk_cursor {struct nk_image img; struct nk_vec2 size, offset;}; -struct nk_scroll {nk_uint x, y;}; - -enum nk_heading {NK_UP, NK_RIGHT, NK_DOWN, NK_LEFT}; -enum nk_button_behavior {NK_BUTTON_DEFAULT, NK_BUTTON_REPEATER}; -enum nk_modify {NK_FIXED = nk_false, NK_MODIFIABLE = nk_true}; -enum nk_orientation {NK_VERTICAL, NK_HORIZONTAL}; -enum nk_collapse_states {NK_MINIMIZED = nk_false, NK_MAXIMIZED = nk_true}; -enum nk_show_states {NK_HIDDEN = nk_false, NK_SHOWN = nk_true}; -enum nk_chart_type {NK_CHART_LINES, NK_CHART_COLUMN, NK_CHART_MAX}; -enum nk_chart_event {NK_CHART_HOVERING = 0x01, NK_CHART_CLICKED = 0x02}; -enum nk_color_format {NK_RGB, NK_RGBA}; -enum nk_popup_type {NK_POPUP_STATIC, NK_POPUP_DYNAMIC}; -enum nk_layout_format {NK_DYNAMIC, NK_STATIC}; -enum nk_tree_type {NK_TREE_NODE, NK_TREE_TAB}; -enum nk_anti_aliasing {NK_ANTI_ALIASING_OFF, NK_ANTI_ALIASING_ON}; - -typedef void*(*nk_plugin_alloc)(nk_handle, void *old, nk_size); -typedef void (*nk_plugin_free)(nk_handle, void *old); -typedef int(*nk_plugin_filter)(const struct nk_text_edit*, nk_rune unicode); -typedef void(*nk_plugin_paste)(nk_handle, struct nk_text_edit*); -typedef void(*nk_plugin_copy)(nk_handle, const char*, int len); - -struct nk_allocator { - nk_handle userdata; - nk_plugin_alloc alloc; - nk_plugin_free free; -}; - -struct nk_draw_null_texture { - nk_handle texture;/* texture handle to a texture with a white pixel */ - struct nk_vec2 uv; /* coordinates to a white pixel in the texture */ -}; -struct nk_convert_config { - float global_alpha; /* global alpha value */ - enum nk_anti_aliasing line_AA; /* line anti-aliasing flag can be turned off if you are tight on memory */ - enum nk_anti_aliasing shape_AA; /* shape anti-aliasing flag can be turned off if you are tight on memory */ - unsigned int circle_segment_count; /* number of segments used for circles: default to 22 */ - unsigned int arc_segment_count; /* number of segments used for arcs: default to 22 */ - unsigned int curve_segment_count; /* number of segments used for curves: default to 22 */ - struct nk_draw_null_texture null; /* handle to texture with a white pixel for shape drawing */ - const struct nk_draw_vertex_layout_element *vertex_layout; /* describes the vertex output format and packing */ - nk_size vertex_size; /* sizeof one vertex for vertex packing */ - nk_size vertex_alignment; /* vertex alignment: Can be optained by NK_ALIGNOF */ -}; - -struct nk_list_view { -/* public: */ - int begin, end, count; -/* private: */ - int total_height; - struct nk_context *ctx; - nk_uint *scroll_pointer; - nk_uint scroll_value; -}; - -enum nk_symbol_type { - NK_SYMBOL_NONE, - NK_SYMBOL_X, - NK_SYMBOL_UNDERSCORE, - NK_SYMBOL_CIRCLE_SOLID, - NK_SYMBOL_CIRCLE_OUTLINE, - NK_SYMBOL_RECT_SOLID, - NK_SYMBOL_RECT_OUTLINE, - NK_SYMBOL_TRIANGLE_UP, - NK_SYMBOL_TRIANGLE_DOWN, - NK_SYMBOL_TRIANGLE_LEFT, - NK_SYMBOL_TRIANGLE_RIGHT, - NK_SYMBOL_PLUS, - NK_SYMBOL_MINUS, - NK_SYMBOL_MAX -}; - -enum nk_keys { - NK_KEY_NONE, - NK_KEY_SHIFT, - NK_KEY_CTRL, - NK_KEY_DEL, - NK_KEY_ENTER, - NK_KEY_TAB, - NK_KEY_BACKSPACE, - NK_KEY_COPY, - NK_KEY_CUT, - NK_KEY_PASTE, - NK_KEY_UP, - NK_KEY_DOWN, - NK_KEY_LEFT, - NK_KEY_RIGHT, - - /* Shortcuts: text field */ - NK_KEY_TEXT_INSERT_MODE, - NK_KEY_TEXT_REPLACE_MODE, - NK_KEY_TEXT_RESET_MODE, - NK_KEY_TEXT_LINE_START, - NK_KEY_TEXT_LINE_END, - NK_KEY_TEXT_START, - NK_KEY_TEXT_END, - NK_KEY_TEXT_UNDO, - NK_KEY_TEXT_REDO, - NK_KEY_TEXT_WORD_LEFT, - NK_KEY_TEXT_WORD_RIGHT, - - /* Shortcuts: scrollbar */ - NK_KEY_SCROLL_START, - NK_KEY_SCROLL_END, - NK_KEY_SCROLL_DOWN, - NK_KEY_SCROLL_UP, - - NK_KEY_MAX -}; - -enum nk_buttons { - NK_BUTTON_LEFT, - NK_BUTTON_MIDDLE, - NK_BUTTON_RIGHT, - NK_BUTTON_MAX -}; - -enum nk_style_colors { - NK_COLOR_TEXT, - NK_COLOR_WINDOW, - NK_COLOR_HEADER, - NK_COLOR_BORDER, - NK_COLOR_BUTTON, - NK_COLOR_BUTTON_HOVER, - NK_COLOR_BUTTON_ACTIVE, - NK_COLOR_TOGGLE, - NK_COLOR_TOGGLE_HOVER, - NK_COLOR_TOGGLE_CURSOR, - NK_COLOR_SELECT, - NK_COLOR_SELECT_ACTIVE, - NK_COLOR_SLIDER, - NK_COLOR_SLIDER_CURSOR, - NK_COLOR_SLIDER_CURSOR_HOVER, - NK_COLOR_SLIDER_CURSOR_ACTIVE, - NK_COLOR_PROPERTY, - NK_COLOR_EDIT, - NK_COLOR_EDIT_CURSOR, - NK_COLOR_COMBO, - NK_COLOR_CHART, - NK_COLOR_CHART_COLOR, - NK_COLOR_CHART_COLOR_HIGHLIGHT, - NK_COLOR_SCROLLBAR, - NK_COLOR_SCROLLBAR_CURSOR, - NK_COLOR_SCROLLBAR_CURSOR_HOVER, - NK_COLOR_SCROLLBAR_CURSOR_ACTIVE, - NK_COLOR_TAB_HEADER, - NK_COLOR_COUNT -}; - -enum nk_style_cursor { - NK_CURSOR_ARROW, - NK_CURSOR_TEXT, - NK_CURSOR_MOVE, - NK_CURSOR_RESIZE_VERTICAL, - NK_CURSOR_RESIZE_HORIZONTAL, - NK_CURSOR_RESIZE_TOP_LEFT_DOWN_RIGHT, - NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT, - NK_CURSOR_COUNT -}; - -enum nk_widget_layout_states { - NK_WIDGET_INVALID, /* The widget cannot be seen and is completely out of view */ - NK_WIDGET_VALID, /* The widget is completely inside the window and can be updated and drawn */ - NK_WIDGET_ROM /* The widget is partially visible and cannot be updated */ -}; - -/* widget states */ -enum nk_widget_states { - NK_WIDGET_STATE_MODIFIED = NK_FLAG(1), - NK_WIDGET_STATE_INACTIVE = NK_FLAG(2), /* widget is neither active nor hovered */ - NK_WIDGET_STATE_ENTERED = NK_FLAG(3), /* widget has been hovered on the current frame */ - NK_WIDGET_STATE_HOVER = NK_FLAG(4), /* widget is being hovered */ - NK_WIDGET_STATE_ACTIVED = NK_FLAG(5),/* widget is currently activated */ - NK_WIDGET_STATE_LEFT = NK_FLAG(6), /* widget is from this frame on not hovered anymore */ - NK_WIDGET_STATE_HOVERED = NK_WIDGET_STATE_HOVER|NK_WIDGET_STATE_MODIFIED, /* widget is being hovered */ - NK_WIDGET_STATE_ACTIVE = NK_WIDGET_STATE_ACTIVED|NK_WIDGET_STATE_MODIFIED /* widget is currently activated */ -}; - -/* text alignment */ -enum nk_text_align { - NK_TEXT_ALIGN_LEFT = 0x01, - NK_TEXT_ALIGN_CENTERED = 0x02, - NK_TEXT_ALIGN_RIGHT = 0x04, - NK_TEXT_ALIGN_TOP = 0x08, - NK_TEXT_ALIGN_MIDDLE = 0x10, - NK_TEXT_ALIGN_BOTTOM = 0x20 -}; -enum nk_text_alignment { - NK_TEXT_LEFT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_LEFT, - NK_TEXT_CENTERED = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_CENTERED, - NK_TEXT_RIGHT = NK_TEXT_ALIGN_MIDDLE|NK_TEXT_ALIGN_RIGHT -}; - -/* edit flags */ -enum nk_edit_flags { - NK_EDIT_DEFAULT = 0, - NK_EDIT_READ_ONLY = NK_FLAG(0), - NK_EDIT_AUTO_SELECT = NK_FLAG(1), - NK_EDIT_SIG_ENTER = NK_FLAG(2), - NK_EDIT_ALLOW_TAB = NK_FLAG(3), - NK_EDIT_NO_CURSOR = NK_FLAG(4), - NK_EDIT_SELECTABLE = NK_FLAG(5), - NK_EDIT_CLIPBOARD = NK_FLAG(6), - NK_EDIT_CTRL_ENTER_NEWLINE = NK_FLAG(7), - NK_EDIT_NO_HORIZONTAL_SCROLL = NK_FLAG(8), - NK_EDIT_ALWAYS_INSERT_MODE = NK_FLAG(9), - NK_EDIT_MULTILINE = NK_FLAG(11), - NK_EDIT_GOTO_END_ON_ACTIVATE = NK_FLAG(12) -}; -enum nk_edit_types { - NK_EDIT_SIMPLE = NK_EDIT_ALWAYS_INSERT_MODE, - NK_EDIT_FIELD = NK_EDIT_SIMPLE|NK_EDIT_SELECTABLE|NK_EDIT_CLIPBOARD, - NK_EDIT_BOX = NK_EDIT_ALWAYS_INSERT_MODE| NK_EDIT_SELECTABLE| NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB|NK_EDIT_CLIPBOARD, - NK_EDIT_EDITOR = NK_EDIT_SELECTABLE|NK_EDIT_MULTILINE|NK_EDIT_ALLOW_TAB| NK_EDIT_CLIPBOARD -}; -enum nk_edit_events { - NK_EDIT_ACTIVE = NK_FLAG(0), /* edit widget is currently being modified */ - NK_EDIT_INACTIVE = NK_FLAG(1), /* edit widget is not active and is not being modified */ - NK_EDIT_ACTIVATED = NK_FLAG(2), /* edit widget went from state inactive to state active */ - NK_EDIT_DEACTIVATED = NK_FLAG(3), /* edit widget went from state active to state inactive */ - NK_EDIT_COMMITED = NK_FLAG(4) /* edit widget has received an enter and lost focus */ -}; -enum nk_panel_flags { - NK_WINDOW_BORDER = NK_FLAG(0), /* Draws a border around the window to visually separate the window from the background */ - NK_WINDOW_MOVABLE = NK_FLAG(1), /* The movable flag indicates that a window can be moved by user input or by dragging the window header */ - NK_WINDOW_SCALABLE = NK_FLAG(2), /* The scalable flag indicates that a window can be scaled by user input by dragging a scaler icon at the button of the window */ - NK_WINDOW_CLOSABLE = NK_FLAG(3), /* adds a closable icon into the header */ - NK_WINDOW_MINIMIZABLE = NK_FLAG(4), /* adds a minimize icon into the header */ - NK_WINDOW_NO_SCROLLBAR = NK_FLAG(5), /* Removes the scrollbar from the window */ - NK_WINDOW_TITLE = NK_FLAG(6), /* Forces a header at the top at the window showing the title */ - NK_WINDOW_SCROLL_AUTO_HIDE = NK_FLAG(7), /* Automatically hides the window scrollbar if no user interaction: also requires delta time in `nk_context` to be set each frame */ - NK_WINDOW_BACKGROUND = NK_FLAG(8) /* Always keep window in the background */ -}; - -/* context */ -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -NK_API int nk_init_default(struct nk_context*, const struct nk_user_font*); -#endif -NK_API int nk_init_fixed(struct nk_context*, void *memory, nk_size size, const struct nk_user_font*); -NK_API int nk_init(struct nk_context*, struct nk_allocator*, const struct nk_user_font*); -NK_API int nk_init_custom(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *pool, const struct nk_user_font*); -NK_API void nk_clear(struct nk_context*); -NK_API void nk_free(struct nk_context*); -#ifdef NK_INCLUDE_COMMAND_USERDATA -NK_API void nk_set_user_data(struct nk_context*, nk_handle handle); -#endif - -/* window */ -NK_API int nk_begin(struct nk_context*, const char *title, struct nk_rect bounds, nk_flags flags); -NK_API int nk_begin_titled(struct nk_context*, const char *name, const char *title, struct nk_rect bounds, nk_flags flags); -NK_API void nk_end(struct nk_context*); - -NK_API struct nk_window* nk_window_find(struct nk_context *ctx, const char *name); -NK_API struct nk_rect nk_window_get_bounds(const struct nk_context*); -NK_API struct nk_vec2 nk_window_get_position(const struct nk_context*); -NK_API struct nk_vec2 nk_window_get_size(const struct nk_context*); -NK_API float nk_window_get_width(const struct nk_context*); -NK_API float nk_window_get_height(const struct nk_context*); -NK_API struct nk_panel* nk_window_get_panel(struct nk_context*); -NK_API struct nk_rect nk_window_get_content_region(struct nk_context*); -NK_API struct nk_vec2 nk_window_get_content_region_min(struct nk_context*); -NK_API struct nk_vec2 nk_window_get_content_region_max(struct nk_context*); -NK_API struct nk_vec2 nk_window_get_content_region_size(struct nk_context*); -NK_API struct nk_command_buffer* nk_window_get_canvas(struct nk_context*); - -NK_API int nk_window_has_focus(const struct nk_context*); -NK_API int nk_window_is_collapsed(struct nk_context*, const char*); -NK_API int nk_window_is_closed(struct nk_context*, const char*); -NK_API int nk_window_is_hidden(struct nk_context*, const char*); -NK_API int nk_window_is_active(struct nk_context*, const char*); -NK_API int nk_window_is_hovered(struct nk_context*); -NK_API int nk_window_is_any_hovered(struct nk_context*); -NK_API int nk_item_is_any_active(struct nk_context*); - -NK_API void nk_window_set_bounds(struct nk_context*, struct nk_rect); -NK_API void nk_window_set_position(struct nk_context*, struct nk_vec2); -NK_API void nk_window_set_size(struct nk_context*, struct nk_vec2); -NK_API void nk_window_set_focus(struct nk_context*, const char *name); - -NK_API void nk_window_close(struct nk_context *ctx, const char *name); -NK_API void nk_window_collapse(struct nk_context*, const char *name, enum nk_collapse_states); -NK_API void nk_window_collapse_if(struct nk_context*, const char *name, enum nk_collapse_states, int cond); -NK_API void nk_window_show(struct nk_context*, const char *name, enum nk_show_states); -NK_API void nk_window_show_if(struct nk_context*, const char *name, enum nk_show_states, int cond); - -/* Layout */ -NK_API void nk_layout_row_dynamic(struct nk_context*, float height, int cols); -NK_API void nk_layout_row_static(struct nk_context*, float height, int item_width, int cols); - -NK_API void nk_layout_row_begin(struct nk_context*, enum nk_layout_format, float row_height, int cols); -NK_API void nk_layout_row_push(struct nk_context*, float value); -NK_API void nk_layout_row_end(struct nk_context*); -NK_API void nk_layout_row(struct nk_context*, enum nk_layout_format, float height, int cols, const float *ratio); - -NK_API void nk_layout_space_begin(struct nk_context*, enum nk_layout_format, float height, int widget_count); -NK_API void nk_layout_space_push(struct nk_context*, struct nk_rect); -NK_API void nk_layout_space_end(struct nk_context*); - -NK_API struct nk_rect nk_layout_space_bounds(struct nk_context*); -NK_API struct nk_vec2 nk_layout_space_to_screen(struct nk_context*, struct nk_vec2); -NK_API struct nk_vec2 nk_layout_space_to_local(struct nk_context*, struct nk_vec2); -NK_API struct nk_rect nk_layout_space_rect_to_screen(struct nk_context*, struct nk_rect); -NK_API struct nk_rect nk_layout_space_rect_to_local(struct nk_context*, struct nk_rect); -NK_API float nk_layout_ratio_from_pixel(struct nk_context*, float pixel_width); - -/* Layout: Group */ -NK_API int nk_group_begin(struct nk_context*, const char *title, nk_flags); -NK_API int nk_group_scrolled_offset_begin(struct nk_context*, nk_uint *x_offset, nk_uint *y_offset, const char*, nk_flags); -NK_API int nk_group_scrolled_begin(struct nk_context*, struct nk_scroll*, const char *title, nk_flags); -NK_API void nk_group_scrolled_end(struct nk_context*); -NK_API void nk_group_end(struct nk_context*); - -NK_API int nk_list_view_begin(struct nk_context*, struct nk_list_view *out, const char *id, nk_flags, int row_height, int row_count); -NK_API void nk_list_view_end(struct nk_list_view*); - -/* Layout: Tree */ -#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__) -#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) -NK_API int nk_tree_push_hashed(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); -#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__) -#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) -NK_API int nk_tree_image_push_hashed(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states initial_state, const char *hash, int len,int seed); -NK_API void nk_tree_pop(struct nk_context*); - -NK_API int nk_tree_state_push(struct nk_context*, enum nk_tree_type, const char *title, enum nk_collapse_states *state); -NK_API int nk_tree_state_image_push(struct nk_context*, enum nk_tree_type, struct nk_image, const char *title, enum nk_collapse_states *state); -NK_API void nk_tree_state_pop(struct nk_context*); - -/* Widgets */ -NK_API void nk_text(struct nk_context*, const char*, int, nk_flags); -NK_API void nk_text_colored(struct nk_context*, const char*, int, nk_flags, struct nk_color); -NK_API void nk_text_wrap(struct nk_context*, const char*, int); -NK_API void nk_text_wrap_colored(struct nk_context*, const char*, int, struct nk_color); - -NK_API void nk_label(struct nk_context*, const char*, nk_flags align); -NK_API void nk_label_colored(struct nk_context*, const char*, nk_flags align, struct nk_color); -NK_API void nk_label_wrap(struct nk_context*, const char*); -NK_API void nk_label_colored_wrap(struct nk_context*, const char*, struct nk_color); -NK_API void nk_image(struct nk_context*, struct nk_image); -#ifdef NK_INCLUDE_STANDARD_VARARGS -NK_API void nk_labelf(struct nk_context*, nk_flags, const char*, ...); -NK_API void nk_labelf_colored(struct nk_context*, nk_flags align, struct nk_color, const char*,...); -NK_API void nk_labelf_wrap(struct nk_context*, const char*,...); -NK_API void nk_labelf_colored_wrap(struct nk_context*, struct nk_color, const char*,...); - -NK_API void nk_value_bool(struct nk_context*, const char *prefix, int); -NK_API void nk_value_int(struct nk_context*, const char *prefix, int); -NK_API void nk_value_uint(struct nk_context*, const char *prefix, unsigned int); -NK_API void nk_value_float(struct nk_context*, const char *prefix, float); -NK_API void nk_value_color_byte(struct nk_context*, const char *prefix, struct nk_color); -NK_API void nk_value_color_float(struct nk_context*, const char *prefix, struct nk_color); -NK_API void nk_value_color_hex(struct nk_context*, const char *prefix, struct nk_color); -#endif - -/* Widgets: Buttons */ -NK_API void nk_button_set_behavior(struct nk_context*, enum nk_button_behavior); -NK_API int nk_button_push_behavior(struct nk_context*, enum nk_button_behavior); -NK_API int nk_button_pop_behavior(struct nk_context*); - -NK_API int nk_button_text(struct nk_context*, const char *title, int len); -NK_API int nk_button_label(struct nk_context*, const char *title); -NK_API int nk_button_color(struct nk_context*, struct nk_color); -NK_API int nk_button_symbol(struct nk_context*, enum nk_symbol_type); -NK_API int nk_button_image(struct nk_context*, struct nk_image img); -NK_API int nk_button_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags text_alignment); -NK_API int nk_button_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); -NK_API int nk_button_image_label(struct nk_context*, struct nk_image img, const char*, nk_flags text_alignment); -NK_API int nk_button_image_text(struct nk_context*, struct nk_image img, const char*, int, nk_flags alignment); - -NK_API int nk_button_text_styled(struct nk_context*, const struct nk_style_button*, const char *title, int len); -NK_API int nk_button_label_styled(struct nk_context*, const struct nk_style_button*, const char *title); -NK_API int nk_button_symbol_styled(struct nk_context*, const struct nk_style_button*, enum nk_symbol_type); -NK_API int nk_button_image_styled(struct nk_context*, const struct nk_style_button*, struct nk_image img); -NK_API int nk_button_symbol_label_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, nk_flags text_alignment); -NK_API int nk_button_symbol_text_styled(struct nk_context*,const struct nk_style_button*, enum nk_symbol_type, const char*, int, nk_flags alignment); -NK_API int nk_button_image_label_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, nk_flags text_alignment); -NK_API int nk_button_image_text_styled(struct nk_context*,const struct nk_style_button*, struct nk_image img, const char*, int, nk_flags alignment); - -/* Widgets: Checkbox */ -NK_API int nk_check_label(struct nk_context*, const char*, int active); -NK_API int nk_check_text(struct nk_context*, const char*, int,int active); -NK_API unsigned nk_check_flags_label(struct nk_context*, const char*, unsigned int flags, unsigned int value); -NK_API unsigned nk_check_flags_text(struct nk_context*, const char*, int, unsigned int flags, unsigned int value); -NK_API int nk_checkbox_label(struct nk_context*, const char*, int *active); -NK_API int nk_checkbox_text(struct nk_context*, const char*, int, int *active); -NK_API int nk_checkbox_flags_label(struct nk_context*, const char*, unsigned int *flags, unsigned int value); -NK_API int nk_checkbox_flags_text(struct nk_context*, const char*, int, unsigned int *flags, unsigned int value); - -/* Widgets: Radio */ -NK_API int nk_radio_label(struct nk_context*, const char*, int *active); -NK_API int nk_radio_text(struct nk_context*, const char*, int, int *active); -NK_API int nk_option_label(struct nk_context*, const char*, int active); -NK_API int nk_option_text(struct nk_context*, const char*, int, int active); - -/* Widgets: Selectable */ -NK_API int nk_selectable_label(struct nk_context*, const char*, nk_flags align, int *value); -NK_API int nk_selectable_text(struct nk_context*, const char*, int, nk_flags align, int *value); -NK_API int nk_selectable_image_label(struct nk_context*,struct nk_image, const char*, nk_flags align, int *value); -NK_API int nk_selectable_image_text(struct nk_context*,struct nk_image, const char*, int, nk_flags align, int *value); - -NK_API int nk_select_label(struct nk_context*, const char*, nk_flags align, int value); -NK_API int nk_select_text(struct nk_context*, const char*, int, nk_flags align, int value); -NK_API int nk_select_image_label(struct nk_context*, struct nk_image,const char*, nk_flags align, int value); -NK_API int nk_select_image_text(struct nk_context*, struct nk_image,const char*, int, nk_flags align, int value); - -/* Widgets: Slider */ -NK_API float nk_slide_float(struct nk_context*, float min, float val, float max, float step); -NK_API int nk_slide_int(struct nk_context*, int min, int val, int max, int step); -NK_API int nk_slider_float(struct nk_context*, float min, float *val, float max, float step); -NK_API int nk_slider_int(struct nk_context*, int min, int *val, int max, int step); - -/* Widgets: Progressbar */ -NK_API int nk_progress(struct nk_context*, nk_size *cur, nk_size max, int modifyable); -NK_API nk_size nk_prog(struct nk_context*, nk_size cur, nk_size max, int modifyable); - -/* Widgets: Color picker */ -NK_API struct nk_color nk_color_picker(struct nk_context*, struct nk_color, enum nk_color_format); -NK_API int nk_color_pick(struct nk_context*, struct nk_color*, enum nk_color_format); - -/* Widgets: Property */ -NK_API void nk_property_int(struct nk_context*, const char *name, int min, int *val, int max, int step, float inc_per_pixel); -NK_API void nk_property_float(struct nk_context*, const char *name, float min, float *val, float max, float step, float inc_per_pixel); -NK_API void nk_property_double(struct nk_context*, const char *name, double min, double *val, double max, double step, float inc_per_pixel); -NK_API int nk_propertyi(struct nk_context*, const char *name, int min, int val, int max, int step, float inc_per_pixel); -NK_API float nk_propertyf(struct nk_context*, const char *name, float min, float val, float max, float step, float inc_per_pixel); -NK_API double nk_propertyd(struct nk_context*, const char *name, double min, double val, double max, double step, float inc_per_pixel); - -/* Widgets: TextEdit */ -NK_API void nk_edit_focus(struct nk_context *ctx, nk_flags flags); -NK_API nk_flags nk_edit_string(struct nk_context*, nk_flags, char *buffer, int *len, int max, nk_plugin_filter); -NK_API nk_flags nk_edit_buffer(struct nk_context*, nk_flags, struct nk_text_edit*, nk_plugin_filter); -NK_API nk_flags nk_edit_string_zero_terminated(struct nk_context*, nk_flags, char *buffer, int max, nk_plugin_filter); - -/* Chart */ -NK_API int nk_chart_begin(struct nk_context*, enum nk_chart_type, int num, float min, float max); -NK_API int nk_chart_begin_colored(struct nk_context*, enum nk_chart_type, struct nk_color, struct nk_color active, int num, float min, float max); -NK_API void nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type, int count, float min_value, float max_value); -NK_API void nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type, struct nk_color, struct nk_color active, int count, float min_value, float max_value); -NK_API nk_flags nk_chart_push(struct nk_context*, float); -NK_API nk_flags nk_chart_push_slot(struct nk_context*, float, int); -NK_API void nk_chart_end(struct nk_context*); -NK_API void nk_plot(struct nk_context*, enum nk_chart_type, const float *values, int count, int offset); -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); - -/* Popups */ -NK_API int nk_popup_begin(struct nk_context*, enum nk_popup_type, const char*, nk_flags, struct nk_rect bounds); -NK_API void nk_popup_close(struct nk_context*); -NK_API void nk_popup_end(struct nk_context*); - -/* Combobox */ -NK_API int nk_combo(struct nk_context*, const char **items, int count, int selected, int item_height, struct nk_vec2 size); -NK_API int nk_combo_separator(struct nk_context*, const char *items_separated_by_separator, int separator, int selected, int count, int item_height, struct nk_vec2 size); -NK_API int nk_combo_string(struct nk_context*, const char *items_separated_by_zeros, int selected, int count, int item_height, struct nk_vec2 size); -NK_API int nk_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); -NK_API void nk_combobox(struct nk_context*, const char **items, int count, int *selected, int item_height, struct nk_vec2 size); -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); -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); -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); - -/* Combobox: abstract */ -NK_API int nk_combo_begin_text(struct nk_context*, const char *selected, int, struct nk_vec2 size); -NK_API int nk_combo_begin_label(struct nk_context*, const char *selected, struct nk_vec2 size); -NK_API int nk_combo_begin_color(struct nk_context*, struct nk_color color, struct nk_vec2 size); -NK_API int nk_combo_begin_symbol(struct nk_context*, enum nk_symbol_type, struct nk_vec2 size); -NK_API int nk_combo_begin_symbol_label(struct nk_context*, const char *selected, enum nk_symbol_type, struct nk_vec2 size); -NK_API int nk_combo_begin_symbol_text(struct nk_context*, const char *selected, int, enum nk_symbol_type, struct nk_vec2 size); -NK_API int nk_combo_begin_image(struct nk_context*, struct nk_image img, struct nk_vec2 size); -NK_API int nk_combo_begin_image_label(struct nk_context*, const char *selected, struct nk_image, struct nk_vec2 size); -NK_API int nk_combo_begin_image_text(struct nk_context*, const char *selected, int, struct nk_image, struct nk_vec2 size); -NK_API int nk_combo_item_label(struct nk_context*, const char*, nk_flags alignment); -NK_API int nk_combo_item_text(struct nk_context*, const char*,int, nk_flags alignment); -NK_API int nk_combo_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); -NK_API int nk_combo_item_image_text(struct nk_context*, struct nk_image, const char*, int,nk_flags alignment); -NK_API int nk_combo_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); -NK_API int nk_combo_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); -NK_API void nk_combo_close(struct nk_context*); -NK_API void nk_combo_end(struct nk_context*); - -/* Contextual */ -NK_API int nk_contextual_begin(struct nk_context*, nk_flags, struct nk_vec2, struct nk_rect trigger_bounds); -NK_API int nk_contextual_item_text(struct nk_context*, const char*, int,nk_flags align); -NK_API int nk_contextual_item_label(struct nk_context*, const char*, nk_flags align); -NK_API int nk_contextual_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); -NK_API int nk_contextual_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); -NK_API int nk_contextual_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); -NK_API int nk_contextual_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); -NK_API void nk_contextual_close(struct nk_context*); -NK_API void nk_contextual_end(struct nk_context*); - -/* Tooltip */ -NK_API void nk_tooltip(struct nk_context*, const char*); -NK_API int nk_tooltip_begin(struct nk_context*, float width); -NK_API void nk_tooltip_end(struct nk_context*); - -/* Menu */ -NK_API void nk_menubar_begin(struct nk_context*); -NK_API void nk_menubar_end(struct nk_context*); - -NK_API int nk_menu_begin_text(struct nk_context*, const char* title, int title_len, nk_flags align, struct nk_vec2 size); -NK_API int nk_menu_begin_label(struct nk_context*, const char*, nk_flags align, struct nk_vec2 size); -NK_API int nk_menu_begin_image(struct nk_context*, const char*, struct nk_image, struct nk_vec2 size); -NK_API int nk_menu_begin_image_text(struct nk_context*, const char*, int,nk_flags align,struct nk_image, struct nk_vec2 size); -NK_API int nk_menu_begin_image_label(struct nk_context*, const char*, nk_flags align,struct nk_image, struct nk_vec2 size); -NK_API int nk_menu_begin_symbol(struct nk_context*, const char*, enum nk_symbol_type, struct nk_vec2 size); -NK_API int nk_menu_begin_symbol_text(struct nk_context*, const char*, int,nk_flags align,enum nk_symbol_type, struct nk_vec2 size); -NK_API int nk_menu_begin_symbol_label(struct nk_context*, const char*, nk_flags align,enum nk_symbol_type, struct nk_vec2 size); -NK_API int nk_menu_item_text(struct nk_context*, const char*, int,nk_flags align); -NK_API int nk_menu_item_label(struct nk_context*, const char*, nk_flags alignment); -NK_API int nk_menu_item_image_label(struct nk_context*, struct nk_image, const char*, nk_flags alignment); -NK_API int nk_menu_item_image_text(struct nk_context*, struct nk_image, const char*, int len, nk_flags alignment); -NK_API int nk_menu_item_symbol_text(struct nk_context*, enum nk_symbol_type, const char*, int, nk_flags alignment); -NK_API int nk_menu_item_symbol_label(struct nk_context*, enum nk_symbol_type, const char*, nk_flags alignment); -NK_API void nk_menu_close(struct nk_context*); -NK_API void nk_menu_end(struct nk_context*); - -/* Drawing*/ -#define nk_foreach(c, ctx) for((c)=nk__begin(ctx); (c)!=0; (c)=nk__next(ctx, c)) -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT -NK_API void nk_convert(struct nk_context*, struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements, const struct nk_convert_config*); -#define nk_draw_foreach(cmd,ctx, b) for((cmd)=nk__draw_begin(ctx, b); (cmd)!=0; (cmd)=nk__draw_next(cmd, b, ctx)) -#define nk_draw_foreach_bounded(cmd,from,to) for((cmd)=(from); (cmd) && (to) && (cmd)>=to; --(cmd)) -NK_API const struct nk_draw_command* nk__draw_begin(const struct nk_context*, const struct nk_buffer*); -NK_API const struct nk_draw_command* nk__draw_end(const struct nk_context*, const struct nk_buffer*); -NK_API const struct nk_draw_command* nk__draw_next(const struct nk_draw_command*, const struct nk_buffer*, const struct nk_context*); -#endif - -/* User Input */ -NK_API void nk_input_begin(struct nk_context*); -NK_API void nk_input_motion(struct nk_context*, int x, int y); -NK_API void nk_input_key(struct nk_context*, enum nk_keys, int down); -NK_API void nk_input_button(struct nk_context*, enum nk_buttons, int x, int y, int down); -NK_API void nk_input_scroll(struct nk_context*, float y); -NK_API void nk_input_char(struct nk_context*, char); -NK_API void nk_input_glyph(struct nk_context*, const nk_glyph); -NK_API void nk_input_unicode(struct nk_context*, nk_rune); -NK_API void nk_input_end(struct nk_context*); - -/* Style */ -NK_API void nk_style_default(struct nk_context*); -NK_API void nk_style_from_table(struct nk_context*, const struct nk_color*); -NK_API void nk_style_load_cursor(struct nk_context*, enum nk_style_cursor, const struct nk_cursor*); -NK_API void nk_style_load_all_cursors(struct nk_context*, struct nk_cursor*); -NK_API const char* nk_style_get_color_by_name(enum nk_style_colors); -NK_API void nk_style_set_font(struct nk_context*, const struct nk_user_font*); -NK_API int nk_style_set_cursor(struct nk_context*, enum nk_style_cursor); -NK_API void nk_style_show_cursor(struct nk_context*); -NK_API void nk_style_hide_cursor(struct nk_context*); - -/* Style: stack */ -NK_API int nk_style_push_font(struct nk_context*, struct nk_user_font*); -NK_API int nk_style_push_float(struct nk_context*, float*, float); -NK_API int nk_style_push_vec2(struct nk_context*, struct nk_vec2*, struct nk_vec2); -NK_API int nk_style_push_style_item(struct nk_context*, struct nk_style_item*, struct nk_style_item); -NK_API int nk_style_push_flags(struct nk_context*, nk_flags*, nk_flags); -NK_API int nk_style_push_color(struct nk_context*, struct nk_color*, struct nk_color); - -NK_API int nk_style_pop_font(struct nk_context*); -NK_API int nk_style_pop_float(struct nk_context*); -NK_API int nk_style_pop_vec2(struct nk_context*); -NK_API int nk_style_pop_style_item(struct nk_context*); -NK_API int nk_style_pop_flags(struct nk_context*); -NK_API int nk_style_pop_color(struct nk_context*); - -/* Utilities */ -NK_API struct nk_rect nk_widget_bounds(struct nk_context*); -NK_API struct nk_vec2 nk_widget_position(struct nk_context*); -NK_API struct nk_vec2 nk_widget_size(struct nk_context*); -NK_API float nk_widget_width(struct nk_context*); -NK_API float nk_widget_height(struct nk_context*); -NK_API int nk_widget_is_hovered(struct nk_context*); -NK_API int nk_widget_is_mouse_clicked(struct nk_context*, enum nk_buttons); -NK_API int nk_widget_has_mouse_click_down(struct nk_context*, enum nk_buttons, int down); -NK_API void nk_spacing(struct nk_context*, int cols); - -/* base widget function */ -NK_API enum nk_widget_layout_states nk_widget(struct nk_rect*, const struct nk_context*); -NK_API enum nk_widget_layout_states nk_widget_fitting(struct nk_rect*, struct nk_context*, struct nk_vec2); - -/* color (conversion user --> nuklear) */ -NK_API struct nk_color nk_rgb(int r, int g, int b); -NK_API struct nk_color nk_rgb_iv(const int *rgb); -NK_API struct nk_color nk_rgb_bv(const nk_byte* rgb); -NK_API struct nk_color nk_rgb_f(float r, float g, float b); -NK_API struct nk_color nk_rgb_fv(const float *rgb); -NK_API struct nk_color nk_rgb_hex(const char *rgb); - -NK_API struct nk_color nk_rgba(int r, int g, int b, int a); -NK_API struct nk_color nk_rgba_u32(nk_uint); -NK_API struct nk_color nk_rgba_iv(const int *rgba); -NK_API struct nk_color nk_rgba_bv(const nk_byte *rgba); -NK_API struct nk_color nk_rgba_f(float r, float g, float b, float a); -NK_API struct nk_color nk_rgba_fv(const float *rgba); -NK_API struct nk_color nk_rgba_hex(const char *rgb); - -NK_API struct nk_color nk_hsv(int h, int s, int v); -NK_API struct nk_color nk_hsv_iv(const int *hsv); -NK_API struct nk_color nk_hsv_bv(const nk_byte *hsv); -NK_API struct nk_color nk_hsv_f(float h, float s, float v); -NK_API struct nk_color nk_hsv_fv(const float *hsv); - -NK_API struct nk_color nk_hsva(int h, int s, int v, int a); -NK_API struct nk_color nk_hsva_iv(const int *hsva); -NK_API struct nk_color nk_hsva_bv(const nk_byte *hsva); -NK_API struct nk_color nk_hsva_f(float h, float s, float v, float a); -NK_API struct nk_color nk_hsva_fv(const float *hsva); - -/* color (conversion nuklear --> user) */ -NK_API void nk_color_f(float *r, float *g, float *b, float *a, struct nk_color); -NK_API void nk_color_fv(float *rgba_out, struct nk_color); -NK_API void nk_color_d(double *r, double *g, double *b, double *a, struct nk_color); -NK_API void nk_color_dv(double *rgba_out, struct nk_color); - -NK_API nk_uint nk_color_u32(struct nk_color); -NK_API void nk_color_hex_rgba(char *output, struct nk_color); -NK_API void nk_color_hex_rgb(char *output, struct nk_color); - -NK_API void nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color); -NK_API void nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color); -NK_API void nk_color_hsv_iv(int *hsv_out, struct nk_color); -NK_API void nk_color_hsv_bv(nk_byte *hsv_out, struct nk_color); -NK_API void nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color); -NK_API void nk_color_hsv_fv(float *hsv_out, struct nk_color); - -NK_API void nk_color_hsva_i(int *h, int *s, int *v, int *a, struct nk_color); -NK_API void nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color); -NK_API void nk_color_hsva_iv(int *hsva_out, struct nk_color); -NK_API void nk_color_hsva_bv(nk_byte *hsva_out, struct nk_color); -NK_API void nk_color_hsva_f(float *out_h, float *out_s, float *out_v, float *out_a, struct nk_color); -NK_API void nk_color_hsva_fv(float *hsva_out, struct nk_color); - -/* image */ -NK_API nk_handle nk_handle_ptr(void*); -NK_API nk_handle nk_handle_id(int); -NK_API struct nk_image nk_image_handle(nk_handle); -NK_API struct nk_image nk_image_ptr(void*); -NK_API struct nk_image nk_image_id(int); -NK_API int nk_image_is_subimage(const struct nk_image* img); -NK_API struct nk_image nk_subimage_ptr(void*, unsigned short w, unsigned short h, struct nk_rect sub_region); -NK_API struct nk_image nk_subimage_id(int, unsigned short w, unsigned short h, struct nk_rect sub_region); -NK_API struct nk_image nk_subimage_handle(nk_handle, unsigned short w, unsigned short h, struct nk_rect sub_region); - -/* math */ -NK_API nk_hash nk_murmur_hash(const void *key, int len, nk_hash seed); -NK_API void nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, float pad_x, float pad_y, enum nk_heading); - -NK_API struct nk_vec2 nk_vec2(float x, float y); -NK_API struct nk_vec2 nk_vec2i(int x, int y); -NK_API struct nk_vec2 nk_vec2v(const float *xy); -NK_API struct nk_vec2 nk_vec2iv(const int *xy); - -NK_API struct nk_rect nk_get_null_rect(void); -NK_API struct nk_rect nk_rect(float x, float y, float w, float h); -NK_API struct nk_rect nk_recti(int x, int y, int w, int h); -NK_API struct nk_rect nk_recta(struct nk_vec2 pos, struct nk_vec2 size); -NK_API struct nk_rect nk_rectv(const float *xywh); -NK_API struct nk_rect nk_rectiv(const int *xywh); -NK_API struct nk_vec2 nk_rect_pos(struct nk_rect); -NK_API struct nk_vec2 nk_rect_size(struct nk_rect); - -/* string*/ -NK_API int nk_strlen(const char *str); -NK_API int nk_stricmp(const char *s1, const char *s2); -NK_API int nk_stricmpn(const char *s1, const char *s2, int n); -NK_API int nk_strtoi(const char *str, char **endptr); -NK_API float nk_strtof(const char *str, char **endptr); -NK_API double nk_strtod(const char *str, char **endptr); -NK_API int nk_strfilter(const char *text, const char *regexp); -NK_API int nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score); -NK_API int nk_strmatch_fuzzy_text(const char *txt, int txt_len, const char *pattern, int *out_score); - -/* UTF-8 */ -NK_API int nk_utf_decode(const char*, nk_rune*, int); -NK_API int nk_utf_encode(nk_rune, char*, int); -NK_API int nk_utf_len(const char*, int byte_len); -NK_API const char* nk_utf_at(const char *buffer, int length, int index, nk_rune *unicode, int *len); - -/* =============================================================== - * - * FONT - * - * ===============================================================*/ -/* Font handling in this library was designed to be quite customizable and lets - you decide what you want to use and what you want to provide. There are three - different ways to use the font atlas. The first two will use your font - handling scheme and only requires essential data to run nuklear. The next - slightly more advanced features is font handling with vertex buffer output. - Finally the most complex API wise is using nuklears font baking API. - - 1.) Using your own implementation without vertex buffer output - -------------------------------------------------------------- - So first up the easiest way to do font handling is by just providing a - `nk_user_font` struct which only requires the height in pixel of the used - font and a callback to calculate the width of a string. This way of handling - fonts is best fitted for using the normal draw shape command API where you - do all the text drawing yourself and the library does not require any kind - of deeper knowledge about which font handling mechanism you use. - IMPORTANT: the `nk_user_font` pointer provided to nuklear has to persist - over the complete life time! I know this sucks but it is currently the only - way to switch between fonts. - - float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) - { - your_font_type *type = handle.ptr; - float text_width = ...; - return text_width; - } - - struct nk_user_font font; - font.userdata.ptr = &your_font_class_or_struct; - font.height = your_font_height; - font.width = your_text_width_calculation; - - struct nk_context ctx; - nk_init_default(&ctx, &font); - - 2.) Using your own implementation with vertex buffer output - -------------------------------------------------------------- - While the first approach works fine if you don't want to use the optional - vertex buffer output it is not enough if you do. To get font handling working - for these cases you have to provide two additional parameters inside the - `nk_user_font`. First a texture atlas handle used to draw text as subimages - of a bigger font atlas texture and a callback to query a character's glyph - information (offset, size, ...). So it is still possible to provide your own - font and use the vertex buffer output. - - float your_text_width_calculation(nk_handle handle, float height, const char *text, int len) - { - your_font_type *type = handle.ptr; - float text_width = ...; - return text_width; - } - void query_your_font_glyph(nk_handle handle, float font_height, struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) - { - your_font_type *type = handle.ptr; - glyph.width = ...; - glyph.height = ...; - glyph.xadvance = ...; - glyph.uv[0].x = ...; - glyph.uv[0].y = ...; - glyph.uv[1].x = ...; - glyph.uv[1].y = ...; - glyph.offset.x = ...; - glyph.offset.y = ...; - } - - struct nk_user_font font; - font.userdata.ptr = &your_font_class_or_struct; - font.height = your_font_height; - font.width = your_text_width_calculation; - font.query = query_your_font_glyph; - font.texture.id = your_font_texture; - - struct nk_context ctx; - nk_init_default(&ctx, &font); - - 3.) Nuklear font baker - ------------------------------------ - The final approach if you do not have a font handling functionality or don't - want to use it in this library is by using the optional font baker. - The font baker API's can be used to create a font plus font atlas texture - and can be used with or without the vertex buffer output. - - It still uses the `nk_user_font` struct and the two different approaches - previously stated still work. The font baker is not located inside - `nk_context` like all other systems since it can be understood as more of - an extension to nuklear and does not really depend on any `nk_context` state. - - Font baker need to be initialized first by one of the nk_font_atlas_init_xxx - functions. If you don't care about memory just call the default version - `nk_font_atlas_init_default` which will allocate all memory from the standard library. - If you want to control memory allocation but you don't care if the allocated - memory is temporary and therefore can be freed directly after the baking process - is over or permanent you can call `nk_font_atlas_init`. - - After successfull intializing the font baker you can add Truetype(.ttf) fonts from - different sources like memory or from file by calling one of the `nk_font_atlas_add_xxx`. - functions. Adding font will permanently store each font, font config and ttf memory block(!) - inside the font atlas and allows to reuse the font atlas. If you don't want to reuse - the font baker by for example adding additional fonts you can call - `nk_font_atlas_cleanup` after the baking process is over (after calling nk_font_atlas_end). - - As soon as you added all fonts you wanted you can now start the baking process - for every selected glyphes to image by calling `nk_font_atlas_bake`. - The baking process returns image memory, width and height which can be used to - either create your own image object or upload it to any graphics library. - No matter which case you finally have to call `nk_font_atlas_end` which - will free all temporary memory including the font atlas image so make sure - you created our texture beforehand. `nk_font_atlas_end` requires a handle - to your font texture or object and optionally fills a `struct nk_draw_null_texture` - which can be used for the optional vertex output. If you don't want it just - set the argument to `NULL`. - - At this point you are done and if you don't want to reuse the font atlas you - can call `nk_font_atlas_cleanup` to free all truetype blobs and configuration - memory. Finally if you don't use the font atlas and any of it's fonts anymore - you need to call `nk_font_atlas_clear` to free all memory still being used. - - struct nk_font_atlas atlas; - nk_font_atlas_init_default(&atlas); - nk_font_atlas_begin(&atlas); - nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, 0); - nk_font *font2 = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font2.ttf", 16, 0); - void* img = nk_font_atlas_bake(&atlas, &img_width, &img_height, NK_FONT_ATLAS_RGBA32, 0); - nk_font_atlas_end(&atlas, nk_handle_id(texture), 0); - - struct nk_context ctx; - nk_init_default(&ctx, &font->handle); - while (1) { - - } - nk_font_atlas_clear(&atlas); - - The font baker API is probably the most complex API inside this library and - I would suggest reading some of my examples `example/` to get a grip on how - to use the font atlas. There are a number of details I left out. For example - how to merge fonts, configure a font with `nk_font_config` to use other languages, - use another texture coodinate format and a lot more: - - struct nk_font_config cfg = nk_font_config(font_pixel_height); - cfg.merge_mode = nk_false or nk_true; - cfg.range = nk_font_korean_glyph_ranges(); - cfg.coord_type = NK_COORD_PIXEL; - nk_font *font = nk_font_atlas_add_from_file(&atlas, "Path/To/Your/TTF_Font.ttf", 13, &cfg); - -*/ -struct nk_user_font_glyph; -typedef float(*nk_text_width_f)(nk_handle, float h, const char*, int len); -typedef void(*nk_query_font_glyph_f)(nk_handle handle, float font_height, - struct nk_user_font_glyph *glyph, - nk_rune codepoint, nk_rune next_codepoint); - -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT -struct nk_user_font_glyph { - struct nk_vec2 uv[2]; - /* texture coordinates */ - struct nk_vec2 offset; - /* offset between top left and glyph */ - float width, height; - /* size of the glyph */ - float xadvance; - /* offset to the next glyph */ -}; -#endif - -struct nk_user_font { - nk_handle userdata; - /* user provided font handle */ - float height; - /* max height of the font */ - nk_text_width_f width; - /* font string width in pixel callback */ -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT - nk_query_font_glyph_f query; - /* font glyph callback to query drawing info */ - nk_handle texture; - /* texture handle to the used font atlas or texture */ -#endif -}; - -#ifdef NK_INCLUDE_FONT_BAKING -enum nk_font_coord_type { - NK_COORD_UV, /* texture coordinates inside font glyphs are clamped between 0-1 */ - NK_COORD_PIXEL /* texture coordinates inside font glyphs are in absolute pixel */ -}; - -struct nk_baked_font { - float height; - /* height of the font */ - float ascent, descent; - /* font glyphs ascent and descent */ - nk_rune glyph_offset; - /* glyph array offset inside the font glyph baking output array */ - nk_rune glyph_count; - /* number of glyphs of this font inside the glyph baking array output */ - const nk_rune *ranges; - /* font codepoint ranges as pairs of (from/to) and 0 as last element */ -}; - -struct nk_font_config { - struct nk_font_config *next; - /* NOTE: only used internally */ - void *ttf_blob; - /* pointer to loaded TTF file memory block. - * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ - nk_size ttf_size; - /* size of the loaded TTF file memory block - * NOTE: not needed for nk_font_atlas_add_from_memory and nk_font_atlas_add_from_file. */ - - unsigned char ttf_data_owned_by_atlas; - /* used inside font atlas: default to: 0*/ - unsigned char merge_mode; - /* merges this font into the last font */ - unsigned char pixel_snap; - /* align every character to pixel boundary (if true set oversample (1,1)) */ - unsigned char oversample_v, oversample_h; - /* rasterize at hight quality for sub-pixel position */ - unsigned char padding[3]; - - float size; - /* baked pixel height of the font */ - enum nk_font_coord_type coord_type; - /* texture coordinate format with either pixel or UV coordinates */ - struct nk_vec2 spacing; - /* extra pixel spacing between glyphs */ - const nk_rune *range; - /* list of unicode ranges (2 values per range, zero terminated) */ - struct nk_baked_font *font; - /* font to setup in the baking process: NOTE: not needed for font atlas */ - nk_rune fallback_glyph; - /* fallback glyph to use if a given rune is not found */ -}; - -struct nk_font_glyph { - nk_rune codepoint; - float xadvance; - float x0, y0, x1, y1, w, h; - float u0, v0, u1, v1; -}; - -struct nk_font { - struct nk_font *next; - struct nk_user_font handle; - struct nk_baked_font info; - float scale; - struct nk_font_glyph *glyphs; - const struct nk_font_glyph *fallback; - nk_rune fallback_codepoint; - nk_handle texture; - struct nk_font_config *config; -}; - -enum nk_font_atlas_format { - NK_FONT_ATLAS_ALPHA8, - NK_FONT_ATLAS_RGBA32 -}; - -struct nk_font_atlas { - void *pixel; - int tex_width; - int tex_height; - - struct nk_allocator permanent; - struct nk_allocator temporary; - - struct nk_recti custom; - struct nk_cursor cursors[NK_CURSOR_COUNT]; - - int glyph_count; - struct nk_font_glyph *glyphs; - struct nk_font *default_font; - struct nk_font *fonts; - struct nk_font_config *config; - int font_num; -}; - -/* some language glyph codepoint ranges */ -NK_API const nk_rune *nk_font_default_glyph_ranges(void); -NK_API const nk_rune *nk_font_chinese_glyph_ranges(void); -NK_API const nk_rune *nk_font_cyrillic_glyph_ranges(void); -NK_API const nk_rune *nk_font_korean_glyph_ranges(void); - -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -NK_API void nk_font_atlas_init_default(struct nk_font_atlas*); -#endif -NK_API void nk_font_atlas_init(struct nk_font_atlas*, struct nk_allocator*); -NK_API void nk_font_atlas_init_custom(struct nk_font_atlas*, struct nk_allocator *persistent, struct nk_allocator *transient); -NK_API void nk_font_atlas_begin(struct nk_font_atlas*); -NK_API struct nk_font_config nk_font_config(float pixel_height); -NK_API struct nk_font *nk_font_atlas_add(struct nk_font_atlas*, const struct nk_font_config*); -#ifdef NK_INCLUDE_DEFAULT_FONT -NK_API struct nk_font* nk_font_atlas_add_default(struct nk_font_atlas*, float height, const struct nk_font_config*); -#endif -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); -#ifdef NK_INCLUDE_STANDARD_IO -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*); -#endif -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*); -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); -NK_API const void* nk_font_atlas_bake(struct nk_font_atlas*, int *width, int *height, enum nk_font_atlas_format); -NK_API void nk_font_atlas_end(struct nk_font_atlas*, nk_handle tex, struct nk_draw_null_texture*); -NK_API const struct nk_font_glyph* nk_font_find_glyph(struct nk_font*, nk_rune unicode); -NK_API void nk_font_atlas_cleanup(struct nk_font_atlas *atlas); -NK_API void nk_font_atlas_clear(struct nk_font_atlas*); - -#endif - -/* ============================================================== - * - * MEMORY BUFFER - * - * ===============================================================*/ -/* A basic (double)-buffer with linear allocation and resetting as only - freeing policy. The buffer's main purpose is to control all memory management - inside the GUI toolkit and still leave memory control as much as possible in - the hand of the user while also making sure the library is easy to use if - not as much control is needed. - In general all memory inside this library can be provided from the user in - three different ways. - - The first way and the one providing most control is by just passing a fixed - size memory block. In this case all control lies in the hand of the user - since he can exactly control where the memory comes from and how much memory - the library should consume. Of course using the fixed size API removes the - ability to automatically resize a buffer if not enough memory is provided so - you have to take over the resizing. While being a fixed sized buffer sounds - quite limiting, it is very effective in this library since the actual memory - consumption is quite stable and has a fixed upper bound for a lot of cases. - - If you don't want to think about how much memory the library should allocate - at all time or have a very dynamic UI with unpredictable memory consumption - habits but still want control over memory allocation you can use the dynamic - allocator based API. The allocator consists of two callbacks for allocating - and freeing memory and optional userdata so you can plugin your own allocator. - - The final and easiest way can be used by defining - NK_INCLUDE_DEFAULT_ALLOCATOR which uses the standard library memory - allocation functions malloc and free and takes over complete control over - memory in this library. -*/ -struct nk_memory_status { - void *memory; - unsigned int type; - nk_size size; - nk_size allocated; - nk_size needed; - nk_size calls; -}; - -enum nk_allocation_type { - NK_BUFFER_FIXED, - NK_BUFFER_DYNAMIC -}; - -enum nk_buffer_allocation_type { - NK_BUFFER_FRONT, - NK_BUFFER_BACK, - NK_BUFFER_MAX -}; - -struct nk_buffer_marker { - int active; - nk_size offset; -}; - -struct nk_memory {void *ptr;nk_size size;}; -struct nk_buffer { - struct nk_buffer_marker marker[NK_BUFFER_MAX]; - /* buffer marker to free a buffer to a certain offset */ - struct nk_allocator pool; - /* allocator callback for dynamic buffers */ - enum nk_allocation_type type; - /* memory management type */ - struct nk_memory memory; - /* memory and size of the current memory block */ - float grow_factor; - /* growing factor for dynamic memory management */ - nk_size allocated; - /* total amount of memory allocated */ - nk_size needed; - /* totally consumed memory given that enough memory is present */ - nk_size calls; - /* number of allocation calls */ - nk_size size; - /* current size of the buffer */ -}; - -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -NK_API void nk_buffer_init_default(struct nk_buffer*); -#endif -NK_API void nk_buffer_init(struct nk_buffer*, const struct nk_allocator*, nk_size size); -NK_API void nk_buffer_init_fixed(struct nk_buffer*, void *memory, nk_size size); -NK_API void nk_buffer_info(struct nk_memory_status*, struct nk_buffer*); -NK_API void nk_buffer_push(struct nk_buffer*, enum nk_buffer_allocation_type type, const void *memory, nk_size size, nk_size align); -NK_API void nk_buffer_mark(struct nk_buffer*, enum nk_buffer_allocation_type type); -NK_API void nk_buffer_reset(struct nk_buffer*, enum nk_buffer_allocation_type type); -NK_API void nk_buffer_clear(struct nk_buffer*); -NK_API void nk_buffer_free(struct nk_buffer*); -NK_API void *nk_buffer_memory(struct nk_buffer*); -NK_API const void *nk_buffer_memory_const(const struct nk_buffer*); -NK_API nk_size nk_buffer_total(struct nk_buffer*); - -/* ============================================================== - * - * STRING - * - * ===============================================================*/ -/* Basic string buffer which is only used in context with the text editor - * to manage and manipulate dynamic or fixed size string content. This is _NOT_ - * the default string handling method. The only instance you should have any contact - * with this API is if you interact with an `nk_text_edit` object inside one of the - * copy and paste functions and even there only for more advanced cases. */ -struct nk_str { - struct nk_buffer buffer; - int len; /* in codepoints/runes/glyphs */ -}; - -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -NK_API void nk_str_init_default(struct nk_str*); -#endif -NK_API void nk_str_init(struct nk_str*, const struct nk_allocator*, nk_size size); -NK_API void nk_str_init_fixed(struct nk_str*, void *memory, nk_size size); -NK_API void nk_str_clear(struct nk_str*); -NK_API void nk_str_free(struct nk_str*); - -NK_API int nk_str_append_text_char(struct nk_str*, const char*, int); -NK_API int nk_str_append_str_char(struct nk_str*, const char*); -NK_API int nk_str_append_text_utf8(struct nk_str*, const char*, int); -NK_API int nk_str_append_str_utf8(struct nk_str*, const char*); -NK_API int nk_str_append_text_runes(struct nk_str*, const nk_rune*, int); -NK_API int nk_str_append_str_runes(struct nk_str*, const nk_rune*); - -NK_API int nk_str_insert_at_char(struct nk_str*, int pos, const char*, int); -NK_API int nk_str_insert_at_rune(struct nk_str*, int pos, const char*, int); - -NK_API int nk_str_insert_text_char(struct nk_str*, int pos, const char*, int); -NK_API int nk_str_insert_str_char(struct nk_str*, int pos, const char*); -NK_API int nk_str_insert_text_utf8(struct nk_str*, int pos, const char*, int); -NK_API int nk_str_insert_str_utf8(struct nk_str*, int pos, const char*); -NK_API int nk_str_insert_text_runes(struct nk_str*, int pos, const nk_rune*, int); -NK_API int nk_str_insert_str_runes(struct nk_str*, int pos, const nk_rune*); - -NK_API void nk_str_remove_chars(struct nk_str*, int len); -NK_API void nk_str_remove_runes(struct nk_str *str, int len); -NK_API void nk_str_delete_chars(struct nk_str*, int pos, int len); -NK_API void nk_str_delete_runes(struct nk_str*, int pos, int len); - -NK_API char *nk_str_at_char(struct nk_str*, int pos); -NK_API char *nk_str_at_rune(struct nk_str*, int pos, nk_rune *unicode, int *len); -NK_API nk_rune nk_str_rune_at(const struct nk_str*, int pos); -NK_API const char *nk_str_at_char_const(const struct nk_str*, int pos); -NK_API const char *nk_str_at_const(const struct nk_str*, int pos, nk_rune *unicode, int *len); - -NK_API char *nk_str_get(struct nk_str*); -NK_API const char *nk_str_get_const(const struct nk_str*); -NK_API int nk_str_len(struct nk_str*); -NK_API int nk_str_len_char(struct nk_str*); - -/*=============================================================== - * - * TEXT EDITOR - * - * ===============================================================*/ -/* Editing text in this library is handled by either `nk_edit_string` or - * `nk_edit_buffer`. But like almost everything in this library there are multiple - * ways of doing it and a balance between control and ease of use with memory - * as well as functionality controlled by flags. - * - * This library generally allows three different levels of memory control: - * First of is the most basic way of just providing a simple char array with - * string length. This method is probably the easiest way of handling simple - * user text input. Main upside is complete control over memory while the biggest - * downside in comparsion with the other two approaches is missing undo/redo. - * - * For UIs that require undo/redo the second way was created. It is based on - * a fixed size nk_text_edit struct, which has an internal undo/redo stack. - * This is mainly useful if you want something more like a text editor but don't want - * to have a dynamically growing buffer. - * - * The final way is using a dynamically growing nk_text_edit struct, which - * has both a default version if you don't care where memory comes from and an - * allocator version if you do. While the text editor is quite powerful for its - * complexity I would not recommend editing gigabytes of data with it. - * It is rather designed for uses cases which make sense for a GUI library not for - * an full blown text editor. - */ -#ifndef NK_TEXTEDIT_UNDOSTATECOUNT -#define NK_TEXTEDIT_UNDOSTATECOUNT 99 -#endif - -#ifndef NK_TEXTEDIT_UNDOCHARCOUNT -#define NK_TEXTEDIT_UNDOCHARCOUNT 999 -#endif - -struct nk_text_edit; -struct nk_clipboard { - nk_handle userdata; - nk_plugin_paste paste; - nk_plugin_copy copy; -}; - -struct nk_text_undo_record { - int where; - short insert_length; - short delete_length; - short char_storage; -}; - -struct nk_text_undo_state { - struct nk_text_undo_record undo_rec[NK_TEXTEDIT_UNDOSTATECOUNT]; - nk_rune undo_char[NK_TEXTEDIT_UNDOCHARCOUNT]; - short undo_point; - short redo_point; - short undo_char_point; - short redo_char_point; -}; - -enum nk_text_edit_type { - NK_TEXT_EDIT_SINGLE_LINE, - NK_TEXT_EDIT_MULTI_LINE -}; - -enum nk_text_edit_mode { - NK_TEXT_EDIT_MODE_VIEW, - NK_TEXT_EDIT_MODE_INSERT, - NK_TEXT_EDIT_MODE_REPLACE -}; - -struct nk_text_edit { - struct nk_clipboard clip; - struct nk_str string; - nk_plugin_filter filter; - struct nk_vec2 scrollbar; - - int cursor; - int select_start; - int select_end; - unsigned char mode; - unsigned char cursor_at_end_of_line; - unsigned char initialized; - unsigned char has_preferred_x; - unsigned char single_line; - unsigned char active; - unsigned char padding1; - float preferred_x; - struct nk_text_undo_state undo; -}; - -/* filter function */ -NK_API int nk_filter_default(const struct nk_text_edit*, nk_rune unicode); -NK_API int nk_filter_ascii(const struct nk_text_edit*, nk_rune unicode); -NK_API int nk_filter_float(const struct nk_text_edit*, nk_rune unicode); -NK_API int nk_filter_decimal(const struct nk_text_edit*, nk_rune unicode); -NK_API int nk_filter_hex(const struct nk_text_edit*, nk_rune unicode); -NK_API int nk_filter_oct(const struct nk_text_edit*, nk_rune unicode); -NK_API int nk_filter_binary(const struct nk_text_edit*, nk_rune unicode); - -/* text editor */ -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -NK_API void nk_textedit_init_default(struct nk_text_edit*); -#endif -NK_API void nk_textedit_init(struct nk_text_edit*, struct nk_allocator*, nk_size size); -NK_API void nk_textedit_init_fixed(struct nk_text_edit*, void *memory, nk_size size); -NK_API void nk_textedit_free(struct nk_text_edit*); -NK_API void nk_textedit_text(struct nk_text_edit*, const char*, int total_len); -NK_API void nk_textedit_delete(struct nk_text_edit*, int where, int len); -NK_API void nk_textedit_delete_selection(struct nk_text_edit*); -NK_API void nk_textedit_select_all(struct nk_text_edit*); -NK_API int nk_textedit_cut(struct nk_text_edit*); -NK_API int nk_textedit_paste(struct nk_text_edit*, char const*, int len); -NK_API void nk_textedit_undo(struct nk_text_edit*); -NK_API void nk_textedit_redo(struct nk_text_edit*); - -/* =============================================================== - * - * DRAWING - * - * ===============================================================*/ -/* This library was designed to be render backend agnostic so it does - not draw anything to screen. Instead all drawn shapes, widgets - are made of, are buffered into memory and make up a command queue. - Each frame therefore fills the command buffer with draw commands - that then need to be executed by the user and his own render backend. - After that the command buffer needs to be cleared and a new frame can be - started. It is probably important to note that the command buffer is the main - drawing API and the optional vertex buffer API only takes this format and - converts it into a hardware accessible format. - - To use the command queue to draw your own widgets you can access the - command buffer of each window by calling `nk_window_get_canvas` after - previously having called `nk_begin`: - - void draw_red_rectangle_widget(struct nk_context *ctx) - { - struct nk_command_buffer *canvas; - struct nk_input *input = &ctx->input; - canvas = nk_window_get_canvas(ctx); - - struct nk_rect space; - enum nk_widget_layout_states state; - state = nk_widget(&space, ctx); - if (!state) return; - - if (state != NK_WIDGET_ROM) - update_your_widget_by_user_input(...); - nk_fill_rect(canvas, space, 0, nk_rgb(255,0,0)); - } - - if (nk_begin(...)) { - nk_layout_row_dynamic(ctx, 25, 1); - draw_red_rectangle_widget(ctx); - } - nk_end(..) - - Important to know if you want to create your own widgets is the `nk_widget` - call. It allocates space on the panel reserved for this widget to be used, - but also returns the state of the widget space. If your widget is not seen and does - not have to be updated it is '0' and you can just return. If it only has - to be drawn the state will be `NK_WIDGET_ROM` otherwise you can do both - update and draw your widget. The reason for seperating is to only draw and - update what is actually neccessary which is crucial for performance. -*/ -enum nk_command_type { - NK_COMMAND_NOP, - NK_COMMAND_SCISSOR, - NK_COMMAND_LINE, - NK_COMMAND_CURVE, - NK_COMMAND_RECT, - NK_COMMAND_RECT_FILLED, - NK_COMMAND_RECT_MULTI_COLOR, - NK_COMMAND_CIRCLE, - NK_COMMAND_CIRCLE_FILLED, - NK_COMMAND_ARC, - NK_COMMAND_ARC_FILLED, - NK_COMMAND_TRIANGLE, - NK_COMMAND_TRIANGLE_FILLED, - NK_COMMAND_POLYGON, - NK_COMMAND_POLYGON_FILLED, - NK_COMMAND_POLYLINE, - NK_COMMAND_TEXT, - NK_COMMAND_IMAGE -}; - -/* command base and header of every command inside the buffer */ -struct nk_command { - enum nk_command_type type; - nk_size next; -#ifdef NK_INCLUDE_COMMAND_USERDATA - nk_handle userdata; -#endif -}; - -struct nk_command_scissor { - struct nk_command header; - short x, y; - unsigned short w, h; -}; - -struct nk_command_line { - struct nk_command header; - unsigned short line_thickness; - struct nk_vec2i begin; - struct nk_vec2i end; - struct nk_color color; -}; - -struct nk_command_curve { - struct nk_command header; - unsigned short line_thickness; - struct nk_vec2i begin; - struct nk_vec2i end; - struct nk_vec2i ctrl[2]; - struct nk_color color; -}; - -struct nk_command_rect { - struct nk_command header; - unsigned short rounding; - unsigned short line_thickness; - short x, y; - unsigned short w, h; - struct nk_color color; -}; - -struct nk_command_rect_filled { - struct nk_command header; - unsigned short rounding; - short x, y; - unsigned short w, h; - struct nk_color color; -}; - -struct nk_command_rect_multi_color { - struct nk_command header; - short x, y; - unsigned short w, h; - struct nk_color left; - struct nk_color top; - struct nk_color bottom; - struct nk_color right; -}; - -struct nk_command_triangle { - struct nk_command header; - unsigned short line_thickness; - struct nk_vec2i a; - struct nk_vec2i b; - struct nk_vec2i c; - struct nk_color color; -}; - -struct nk_command_triangle_filled { - struct nk_command header; - struct nk_vec2i a; - struct nk_vec2i b; - struct nk_vec2i c; - struct nk_color color; -}; - -struct nk_command_circle { - struct nk_command header; - short x, y; - unsigned short line_thickness; - unsigned short w, h; - struct nk_color color; -}; - -struct nk_command_circle_filled { - struct nk_command header; - short x, y; - unsigned short w, h; - struct nk_color color; -}; - -struct nk_command_arc { - struct nk_command header; - short cx, cy; - unsigned short r; - unsigned short line_thickness; - float a[2]; - struct nk_color color; -}; - -struct nk_command_arc_filled { - struct nk_command header; - short cx, cy; - unsigned short r; - float a[2]; - struct nk_color color; -}; - -struct nk_command_polygon { - struct nk_command header; - struct nk_color color; - unsigned short line_thickness; - unsigned short point_count; - struct nk_vec2i points[1]; -}; - -struct nk_command_polygon_filled { - struct nk_command header; - struct nk_color color; - unsigned short point_count; - struct nk_vec2i points[1]; -}; - -struct nk_command_polyline { - struct nk_command header; - struct nk_color color; - unsigned short line_thickness; - unsigned short point_count; - struct nk_vec2i points[1]; -}; - -struct nk_command_image { - struct nk_command header; - short x, y; - unsigned short w, h; - struct nk_image img; - struct nk_color col; -}; - -struct nk_command_text { - struct nk_command header; - const struct nk_user_font *font; - struct nk_color background; - struct nk_color foreground; - short x, y; - unsigned short w, h; - float height; - int length; - char string[1]; -}; - -enum nk_command_clipping { - NK_CLIPPING_OFF = nk_false, - NK_CLIPPING_ON = nk_true -}; - -struct nk_command_buffer { - struct nk_buffer *base; - struct nk_rect clip; - int use_clipping; - nk_handle userdata; - nk_size begin, end, last; -}; - -/* shape outlines */ -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); -NK_API void nk_stroke_curve(struct nk_command_buffer*, float, float, float, float, float, float, float, float, float line_thickness, struct nk_color); -NK_API void nk_stroke_rect(struct nk_command_buffer*, struct nk_rect, float rounding, float line_thickness, struct nk_color); -NK_API void nk_stroke_circle(struct nk_command_buffer*, struct nk_rect, float line_thickness, struct nk_color); -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); -NK_API void nk_stroke_triangle(struct nk_command_buffer*, float, float, float, float, float, float, float line_thichness, struct nk_color); -NK_API void nk_stroke_polyline(struct nk_command_buffer*, float *points, int point_count, float line_thickness, struct nk_color col); -NK_API void nk_stroke_polygon(struct nk_command_buffer*, float*, int point_count, float line_thickness, struct nk_color); - -/* filled shades */ -NK_API void nk_fill_rect(struct nk_command_buffer*, struct nk_rect, float rounding, struct nk_color); -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); -NK_API void nk_fill_circle(struct nk_command_buffer*, struct nk_rect, struct nk_color); -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); -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); -NK_API void nk_fill_polygon(struct nk_command_buffer*, float*, int point_count, struct nk_color); - -/* misc */ -NK_API void nk_push_scissor(struct nk_command_buffer*, struct nk_rect); -NK_API void nk_draw_image(struct nk_command_buffer*, struct nk_rect, const struct nk_image*, struct nk_color); -NK_API void nk_draw_text(struct nk_command_buffer*, struct nk_rect, const char *text, int len, const struct nk_user_font*, struct nk_color, struct nk_color); -NK_API const struct nk_command* nk__next(struct nk_context*, const struct nk_command*); -NK_API const struct nk_command* nk__begin(struct nk_context*); - -/* =============================================================== - * - * INPUT - * - * ===============================================================*/ -struct nk_mouse_button { - int down; - unsigned int clicked; - struct nk_vec2 clicked_pos; -}; -struct nk_mouse { - struct nk_mouse_button buttons[NK_BUTTON_MAX]; - struct nk_vec2 pos; - struct nk_vec2 prev; - struct nk_vec2 delta; - float scroll_delta; - unsigned char grab; - unsigned char grabbed; - unsigned char ungrab; -}; - -struct nk_key { - int down; - unsigned int clicked; -}; -struct nk_keyboard { - struct nk_key keys[NK_KEY_MAX]; - char text[NK_INPUT_MAX]; - int text_len; -}; - -struct nk_input { - struct nk_keyboard keyboard; - struct nk_mouse mouse; -}; - -NK_API int nk_input_has_mouse_click(const struct nk_input*, enum nk_buttons); -NK_API int nk_input_has_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); -NK_API int nk_input_has_mouse_click_down_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect, int down); -NK_API int nk_input_is_mouse_click_in_rect(const struct nk_input*, enum nk_buttons, struct nk_rect); -NK_API int nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, struct nk_rect b, int down); -NK_API int nk_input_any_mouse_click_in_rect(const struct nk_input*, struct nk_rect); -NK_API int nk_input_is_mouse_prev_hovering_rect(const struct nk_input*, struct nk_rect); -NK_API int nk_input_is_mouse_hovering_rect(const struct nk_input*, struct nk_rect); -NK_API int nk_input_mouse_clicked(const struct nk_input*, enum nk_buttons, struct nk_rect); -NK_API int nk_input_is_mouse_down(const struct nk_input*, enum nk_buttons); -NK_API int nk_input_is_mouse_pressed(const struct nk_input*, enum nk_buttons); -NK_API int nk_input_is_mouse_released(const struct nk_input*, enum nk_buttons); -NK_API int nk_input_is_key_pressed(const struct nk_input*, enum nk_keys); -NK_API int nk_input_is_key_released(const struct nk_input*, enum nk_keys); -NK_API int nk_input_is_key_down(const struct nk_input*, enum nk_keys); - -/* =============================================================== - * - * DRAW LIST - * - * ===============================================================*/ -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT -/* The optional vertex buffer draw list provides a 2D drawing context - with antialiasing functionality which takes basic filled or outlined shapes - or a path and outputs vertexes, elements and draw commands. - The actual draw list API is not required to be used directly while using this - library since converting the default library draw command output is done by - just calling `nk_convert` but I decided to still make this library accessible - since it can be useful. - - The draw list is based on a path buffering and polygon and polyline - rendering API which allows a lot of ways to draw 2D content to screen. - In fact it is probably more powerful than needed but allows even more crazy - things than this library provides by default. -*/ -typedef nk_ushort nk_draw_index; -enum nk_draw_list_stroke { - NK_STROKE_OPEN = nk_false, - /* build up path has no connection back to the beginning */ - NK_STROKE_CLOSED = nk_true - /* build up path has a connection back to the beginning */ -}; - -enum nk_draw_vertex_layout_attribute { - NK_VERTEX_POSITION, - NK_VERTEX_COLOR, - NK_VERTEX_TEXCOORD, - NK_VERTEX_ATTRIBUTE_COUNT -}; - -enum nk_draw_vertex_layout_format { - NK_FORMAT_SCHAR, - NK_FORMAT_SSHORT, - NK_FORMAT_SINT, - NK_FORMAT_UCHAR, - NK_FORMAT_USHORT, - NK_FORMAT_UINT, - NK_FORMAT_FLOAT, - NK_FORMAT_DOUBLE, - -NK_FORMAT_COLOR_BEGIN, - NK_FORMAT_R8G8B8 = NK_FORMAT_COLOR_BEGIN, - NK_FORMAT_R16G15B16, - NK_FORMAT_R32G32B32, - - NK_FORMAT_R8G8B8A8, - NK_FORMAT_R16G15B16A16, - NK_FORMAT_R32G32B32A32, - NK_FORMAT_R32G32B32A32_FLOAT, - NK_FORMAT_R32G32B32A32_DOUBLE, - - NK_FORMAT_RGB32, - NK_FORMAT_RGBA32, -NK_FORMAT_COLOR_END = NK_FORMAT_RGBA32, - NK_FORMAT_COUNT -}; - -#define NK_VERTEX_LAYOUT_END NK_VERTEX_ATTRIBUTE_COUNT,NK_FORMAT_COUNT,0 -struct nk_draw_vertex_layout_element { - enum nk_draw_vertex_layout_attribute attribute; - enum nk_draw_vertex_layout_format format; - nk_size offset; -}; - -struct nk_draw_command { - unsigned int elem_count; - /* number of elements in the current draw batch */ - struct nk_rect clip_rect; - /* current screen clipping rectangle */ - nk_handle texture; - /* current texture to set */ -#ifdef NK_INCLUDE_COMMAND_USERDATA - nk_handle userdata; -#endif -}; - -struct nk_draw_list { - struct nk_rect clip_rect; - struct nk_vec2 circle_vtx[12]; - struct nk_convert_config config; - - struct nk_buffer *buffer; - struct nk_buffer *vertices; - struct nk_buffer *elements; - - unsigned int element_count; - unsigned int vertex_count; - unsigned int cmd_count; - nk_size cmd_offset; - - unsigned int path_count; - unsigned int path_offset; - -#ifdef NK_INCLUDE_COMMAND_USERDATA - nk_handle userdata; -#endif -}; - -/* draw list */ -NK_API void nk_draw_list_init(struct nk_draw_list*); -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); -NK_API void nk_draw_list_clear(struct nk_draw_list*); - -/* drawing */ -#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)) -NK_API const struct nk_draw_command* nk__draw_list_begin(const struct nk_draw_list*, const struct nk_buffer*); -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*); -NK_API const struct nk_draw_command* nk__draw_list_end(const struct nk_draw_list*, const struct nk_buffer*); -NK_API void nk_draw_list_clear(struct nk_draw_list *list); - -/* path */ -NK_API void nk_draw_list_path_clear(struct nk_draw_list*); -NK_API void nk_draw_list_path_line_to(struct nk_draw_list*, struct nk_vec2 pos); -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); -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); -NK_API void nk_draw_list_path_rect_to(struct nk_draw_list*, struct nk_vec2 a, struct nk_vec2 b, float rounding); -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); -NK_API void nk_draw_list_path_fill(struct nk_draw_list*, struct nk_color); -NK_API void nk_draw_list_path_stroke(struct nk_draw_list*, struct nk_color, enum nk_draw_list_stroke closed, float thickness); - -/* stroke */ -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); -NK_API void nk_draw_list_stroke_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding, float thickness); -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); -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); -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); -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); - -/* fill */ -NK_API void nk_draw_list_fill_rect(struct nk_draw_list*, struct nk_rect rect, struct nk_color, float rounding); -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); -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); -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); -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); - -/* misc */ -NK_API void nk_draw_list_add_image(struct nk_draw_list*, struct nk_image texture, struct nk_rect rect, struct nk_color); -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); -#ifdef NK_INCLUDE_COMMAND_USERDATA -NK_API void nk_draw_list_push_userdata(struct nk_draw_list*, nk_handle userdata); -#endif - -#endif - -/* =============================================================== - * - * GUI - * - * ===============================================================*/ -enum nk_style_item_type { - NK_STYLE_ITEM_COLOR, - NK_STYLE_ITEM_IMAGE -}; - -union nk_style_item_data { - struct nk_image image; - struct nk_color color; -}; - -struct nk_style_item { - enum nk_style_item_type type; - union nk_style_item_data data; -}; - -struct nk_style_text { - struct nk_color color; - struct nk_vec2 padding; -}; - -struct nk_style_button { - /* background */ - struct nk_style_item normal; - struct nk_style_item hover; - struct nk_style_item active; - struct nk_color border_color; - - /* text */ - struct nk_color text_background; - struct nk_color text_normal; - struct nk_color text_hover; - struct nk_color text_active; - nk_flags text_alignment; - - /* properties */ - float border; - float rounding; - struct nk_vec2 padding; - struct nk_vec2 image_padding; - struct nk_vec2 touch_padding; - - /* optional user callbacks */ - nk_handle userdata; - void(*draw_begin)(struct nk_command_buffer*, nk_handle userdata); - void(*draw_end)(struct nk_command_buffer*, nk_handle userdata); -}; - -struct nk_style_toggle { - /* background */ - struct nk_style_item normal; - struct nk_style_item hover; - struct nk_style_item active; - struct nk_color border_color; - - /* cursor */ - struct nk_style_item cursor_normal; - struct nk_style_item cursor_hover; - - /* text */ - struct nk_color text_normal; - struct nk_color text_hover; - struct nk_color text_active; - struct nk_color text_background; - nk_flags text_alignment; - - /* properties */ - struct nk_vec2 padding; - struct nk_vec2 touch_padding; - float spacing; - float border; - - /* optional user callbacks */ - nk_handle userdata; - void(*draw_begin)(struct nk_command_buffer*, nk_handle); - void(*draw_end)(struct nk_command_buffer*, nk_handle); -}; - -struct nk_style_selectable { - /* background (inactive) */ - struct nk_style_item normal; - struct nk_style_item hover; - struct nk_style_item pressed; - - /* background (active) */ - struct nk_style_item normal_active; - struct nk_style_item hover_active; - struct nk_style_item pressed_active; - - /* text color (inactive) */ - struct nk_color text_normal; - struct nk_color text_hover; - struct nk_color text_pressed; - - /* text color (active) */ - struct nk_color text_normal_active; - struct nk_color text_hover_active; - struct nk_color text_pressed_active; - struct nk_color text_background; - nk_flags text_alignment; - - /* properties */ - float rounding; - struct nk_vec2 padding; - struct nk_vec2 touch_padding; - struct nk_vec2 image_padding; - - /* optional user callbacks */ - nk_handle userdata; - void(*draw_begin)(struct nk_command_buffer*, nk_handle); - void(*draw_end)(struct nk_command_buffer*, nk_handle); -}; - -struct nk_style_slider { - /* background */ - struct nk_style_item normal; - struct nk_style_item hover; - struct nk_style_item active; - struct nk_color border_color; - - /* background bar */ - struct nk_color bar_normal; - struct nk_color bar_hover; - struct nk_color bar_active; - struct nk_color bar_filled; - - /* cursor */ - struct nk_style_item cursor_normal; - struct nk_style_item cursor_hover; - struct nk_style_item cursor_active; - - /* properties */ - float border; - float rounding; - float bar_height; - struct nk_vec2 padding; - struct nk_vec2 spacing; - struct nk_vec2 cursor_size; - - /* optional buttons */ - int show_buttons; - struct nk_style_button inc_button; - struct nk_style_button dec_button; - enum nk_symbol_type inc_symbol; - enum nk_symbol_type dec_symbol; - - /* optional user callbacks */ - nk_handle userdata; - void(*draw_begin)(struct nk_command_buffer*, nk_handle); - void(*draw_end)(struct nk_command_buffer*, nk_handle); -}; - -struct nk_style_progress { - /* background */ - struct nk_style_item normal; - struct nk_style_item hover; - struct nk_style_item active; - struct nk_color border_color; - - /* cursor */ - struct nk_style_item cursor_normal; - struct nk_style_item cursor_hover; - struct nk_style_item cursor_active; - struct nk_color cursor_border_color; - - /* properties */ - float rounding; - float border; - float cursor_border; - float cursor_rounding; - struct nk_vec2 padding; - - /* optional user callbacks */ - nk_handle userdata; - void(*draw_begin)(struct nk_command_buffer*, nk_handle); - void(*draw_end)(struct nk_command_buffer*, nk_handle); -}; - -struct nk_style_scrollbar { - /* background */ - struct nk_style_item normal; - struct nk_style_item hover; - struct nk_style_item active; - struct nk_color border_color; - - /* cursor */ - struct nk_style_item cursor_normal; - struct nk_style_item cursor_hover; - struct nk_style_item cursor_active; - struct nk_color cursor_border_color; - - /* properties */ - float border; - float rounding; - float border_cursor; - float rounding_cursor; - struct nk_vec2 padding; - - /* optional buttons */ - int show_buttons; - struct nk_style_button inc_button; - struct nk_style_button dec_button; - enum nk_symbol_type inc_symbol; - enum nk_symbol_type dec_symbol; - - /* optional user callbacks */ - nk_handle userdata; - void(*draw_begin)(struct nk_command_buffer*, nk_handle); - void(*draw_end)(struct nk_command_buffer*, nk_handle); -}; - -struct nk_style_edit { - /* background */ - struct nk_style_item normal; - struct nk_style_item hover; - struct nk_style_item active; - struct nk_color border_color; - struct nk_style_scrollbar scrollbar; - - /* cursor */ - struct nk_color cursor_normal; - struct nk_color cursor_hover; - struct nk_color cursor_text_normal; - struct nk_color cursor_text_hover; - - /* text (unselected) */ - struct nk_color text_normal; - struct nk_color text_hover; - struct nk_color text_active; - - /* text (selected) */ - struct nk_color selected_normal; - struct nk_color selected_hover; - struct nk_color selected_text_normal; - struct nk_color selected_text_hover; - - /* properties */ - float border; - float rounding; - float cursor_size; - struct nk_vec2 scrollbar_size; - struct nk_vec2 padding; - float row_padding; -}; - -struct nk_style_property { - /* background */ - struct nk_style_item normal; - struct nk_style_item hover; - struct nk_style_item active; - struct nk_color border_color; - - /* text */ - struct nk_color label_normal; - struct nk_color label_hover; - struct nk_color label_active; - - /* symbols */ - enum nk_symbol_type sym_left; - enum nk_symbol_type sym_right; - - /* properties */ - float border; - float rounding; - struct nk_vec2 padding; - - struct nk_style_edit edit; - struct nk_style_button inc_button; - struct nk_style_button dec_button; - - /* optional user callbacks */ - nk_handle userdata; - void(*draw_begin)(struct nk_command_buffer*, nk_handle); - void(*draw_end)(struct nk_command_buffer*, nk_handle); -}; - -struct nk_style_chart { - /* colors */ - struct nk_style_item background; - struct nk_color border_color; - struct nk_color selected_color; - struct nk_color color; - - /* properties */ - float border; - float rounding; - struct nk_vec2 padding; -}; - -struct nk_style_combo { - /* background */ - struct nk_style_item normal; - struct nk_style_item hover; - struct nk_style_item active; - struct nk_color border_color; - - /* label */ - struct nk_color label_normal; - struct nk_color label_hover; - struct nk_color label_active; - - /* symbol */ - struct nk_color symbol_normal; - struct nk_color symbol_hover; - struct nk_color symbol_active; - - /* button */ - struct nk_style_button button; - enum nk_symbol_type sym_normal; - enum nk_symbol_type sym_hover; - enum nk_symbol_type sym_active; - - /* properties */ - float border; - float rounding; - struct nk_vec2 content_padding; - struct nk_vec2 button_padding; - struct nk_vec2 spacing; -}; - -struct nk_style_tab { - /* background */ - struct nk_style_item background; - struct nk_color border_color; - struct nk_color text; - - /* button */ - struct nk_style_button tab_maximize_button; - struct nk_style_button tab_minimize_button; - struct nk_style_button node_maximize_button; - struct nk_style_button node_minimize_button; - enum nk_symbol_type sym_minimize; - enum nk_symbol_type sym_maximize; - - /* properties */ - float border; - float rounding; - float indent; - struct nk_vec2 padding; - struct nk_vec2 spacing; -}; - -enum nk_style_header_align { - NK_HEADER_LEFT, - NK_HEADER_RIGHT -}; -struct nk_style_window_header { - /* background */ - struct nk_style_item normal; - struct nk_style_item hover; - struct nk_style_item active; - - /* button */ - struct nk_style_button close_button; - struct nk_style_button minimize_button; - enum nk_symbol_type close_symbol; - enum nk_symbol_type minimize_symbol; - enum nk_symbol_type maximize_symbol; - - /* title */ - struct nk_color label_normal; - struct nk_color label_hover; - struct nk_color label_active; - - /* properties */ - enum nk_style_header_align align; - struct nk_vec2 padding; - struct nk_vec2 label_padding; - struct nk_vec2 spacing; -}; - -struct nk_style_window { - struct nk_style_window_header header; - struct nk_style_item fixed_background; - struct nk_color background; - - struct nk_color border_color; - struct nk_color popup_border_color; - struct nk_color combo_border_color; - struct nk_color contextual_border_color; - struct nk_color menu_border_color; - struct nk_color group_border_color; - struct nk_color tooltip_border_color; - struct nk_style_item scaler; - - float border; - float combo_border; - float contextual_border; - float menu_border; - float group_border; - float tooltip_border; - float popup_border; - - float rounding; - struct nk_vec2 spacing; - struct nk_vec2 scrollbar_size; - struct nk_vec2 min_size; - - struct nk_vec2 padding; - struct nk_vec2 group_padding; - struct nk_vec2 popup_padding; - struct nk_vec2 combo_padding; - struct nk_vec2 contextual_padding; - struct nk_vec2 menu_padding; - struct nk_vec2 tooltip_padding; -}; - -struct nk_style { - const struct nk_user_font *font; - const struct nk_cursor *cursors[NK_CURSOR_COUNT]; - const struct nk_cursor *cursor_active; - struct nk_cursor *cursor_last; - int cursor_visible; - - struct nk_style_text text; - struct nk_style_button button; - struct nk_style_button contextual_button; - struct nk_style_button menu_button; - struct nk_style_toggle option; - struct nk_style_toggle checkbox; - struct nk_style_selectable selectable; - struct nk_style_slider slider; - struct nk_style_progress progress; - struct nk_style_property property; - struct nk_style_edit edit; - struct nk_style_chart chart; - struct nk_style_scrollbar scrollh; - struct nk_style_scrollbar scrollv; - struct nk_style_tab tab; - struct nk_style_combo combo; - struct nk_style_window window; -}; - -NK_API struct nk_style_item nk_style_item_image(struct nk_image img); -NK_API struct nk_style_item nk_style_item_color(struct nk_color); -NK_API struct nk_style_item nk_style_item_hide(void); - -/*============================================================== - * PANEL - * =============================================================*/ -#ifndef NK_CHART_MAX_SLOT -#define NK_CHART_MAX_SLOT 4 -#endif - -enum nk_panel_type { - NK_PANEL_WINDOW = NK_FLAG(0), - NK_PANEL_GROUP = NK_FLAG(1), - NK_PANEL_POPUP = NK_FLAG(2), - NK_PANEL_CONTEXTUAL = NK_FLAG(4), - NK_PANEL_COMBO = NK_FLAG(5), - NK_PANEL_MENU = NK_FLAG(6), - NK_PANEL_TOOLTIP = NK_FLAG(7) -}; -enum nk_panel_set { - NK_PANEL_SET_NONBLOCK = NK_PANEL_CONTEXTUAL|NK_PANEL_COMBO|NK_PANEL_MENU|NK_PANEL_TOOLTIP, - NK_PANEL_SET_POPUP = NK_PANEL_SET_NONBLOCK|NK_PANEL_POPUP, - NK_PANEL_SET_SUB = NK_PANEL_SET_POPUP|NK_PANEL_GROUP -}; - -struct nk_chart_slot { - enum nk_chart_type type; - struct nk_color color; - struct nk_color highlight; - float min, max, range; - int count; - struct nk_vec2 last; - int index; -}; - -struct nk_chart { - int slot; - float x, y, w, h; - struct nk_chart_slot slots[NK_CHART_MAX_SLOT]; -}; - -struct nk_row_layout { - int type; - int index; - float height; - int columns; - const float *ratio; - float item_width; - float item_height; - float item_offset; - float filled; - struct nk_rect item; - int tree_depth; -}; - -struct nk_popup_buffer { - nk_size begin; - nk_size parent; - nk_size last; - nk_size end; - int active; -}; - -struct nk_menu_state { - float x, y, w, h; - struct nk_scroll offset; -}; - -struct nk_panel { - enum nk_panel_type type; - nk_flags flags; - struct nk_rect bounds; - nk_uint *offset_x; - nk_uint *offset_y; - float at_x, at_y, max_x; - float footer_height; - float header_height; - float border; - unsigned int has_scrolling; - struct nk_rect clip; - struct nk_menu_state menu; - struct nk_row_layout row; - struct nk_chart chart; - struct nk_popup_buffer popup_buffer; - struct nk_command_buffer *buffer; - struct nk_panel *parent; -}; - -/*============================================================== - * WINDOW - * =============================================================*/ -#ifndef NK_WINDOW_MAX_NAME -#define NK_WINDOW_MAX_NAME 64 -#endif - -struct nk_table; -enum nk_window_flags { - NK_WINDOW_PRIVATE = NK_FLAG(10), - NK_WINDOW_DYNAMIC = NK_WINDOW_PRIVATE, - /* special window type growing up in height while being filled to a certain maximum height */ - NK_WINDOW_ROM = NK_FLAG(11), - /* sets the window into a read only mode and does not allow input changes */ - NK_WINDOW_HIDDEN = NK_FLAG(12), - /* Hides the window and stops any window interaction and drawing */ - NK_WINDOW_CLOSED = NK_FLAG(13), - /* Directly closes and frees the window at the end of the frame */ - NK_WINDOW_MINIMIZED = NK_FLAG(14), - /* marks the window as minimized */ - NK_WINDOW_REMOVE_ROM = NK_FLAG(15) - /* Removes the read only mode at the end of the window */ -}; - -struct nk_popup_state { - struct nk_window *win; - enum nk_panel_type type; - nk_hash name; - int active; - unsigned combo_count; - unsigned con_count, con_old; - unsigned active_con; - struct nk_rect header; -}; - -struct nk_edit_state { - nk_hash name; - unsigned int seq; - unsigned int old; - int active, prev; - int cursor; - int sel_start; - int sel_end; - struct nk_scroll scrollbar; - unsigned char mode; - unsigned char single_line; -}; - -struct nk_property_state { - int active, prev; - char buffer[NK_MAX_NUMBER_BUFFER]; - int length; - int cursor; - nk_hash name; - unsigned int seq; - unsigned int old; - int state; -}; - -struct nk_window { - unsigned int seq; - nk_hash name; - char name_string[NK_WINDOW_MAX_NAME]; - nk_flags flags; - - struct nk_rect bounds; - struct nk_scroll scrollbar; - struct nk_command_buffer buffer; - struct nk_panel *layout; - float scrollbar_hiding_timer; - - /* persistent widget state */ - struct nk_property_state property; - struct nk_popup_state popup; - struct nk_edit_state edit; - unsigned int scrolled; - - struct nk_table *tables; - unsigned short table_count; - unsigned short table_size; - - /* window list hooks */ - struct nk_window *next; - struct nk_window *prev; - struct nk_window *parent; -}; - -/*============================================================== - * STACK - * =============================================================*/ -/* The style modifier stack can be used to temporarily change a - * property inside `nk_style`. For example if you want a special - * red button you can temporarily push the old button color onto a stack - * draw the button with a red color and then you just pop the old color - * back from the stack: - * - * nk_style_push_style_item(ctx, &ctx->style.button.normal, nk_style_item_color(nk_rgb(255,0,0))); - * nk_style_push_style_item(ctx, &ctx->style.button.hover, nk_style_item_color(nk_rgb(255,0,0))); - * nk_style_push_style_item(ctx, &ctx->style.button.active, nk_style_item_color(nk_rgb(255,0,0))); - * nk_style_push_vec2(ctx, &cx->style.button.padding, nk_vec2(2,2)); - * - * nk_button(...); - * - * nk_style_pop_style_item(ctx); - * nk_style_pop_style_item(ctx); - * nk_style_pop_style_item(ctx); - * nk_style_pop_vec2(ctx); - * - * Nuklear has a stack for style_items, float properties, vector properties, - * flags, colors, fonts and for button_behavior. Each has it's own fixed size stack - * which can be changed at compile time. - */ -#ifndef NK_BUTTON_BEHAVIOR_STACK_SIZE -#define NK_BUTTON_BEHAVIOR_STACK_SIZE 8 -#endif - -#ifndef NK_FONT_STACK_SIZE -#define NK_FONT_STACK_SIZE 8 -#endif - -#ifndef NK_STYLE_ITEM_STACK_SIZE -#define NK_STYLE_ITEM_STACK_SIZE 16 -#endif - -#ifndef NK_FLOAT_STACK_SIZE -#define NK_FLOAT_STACK_SIZE 32 -#endif - -#ifndef NK_VECTOR_STACK_SIZE -#define NK_VECTOR_STACK_SIZE 16 -#endif - -#ifndef NK_FLAGS_STACK_SIZE -#define NK_FLAGS_STACK_SIZE 32 -#endif - -#ifndef NK_COLOR_STACK_SIZE -#define NK_COLOR_STACK_SIZE 32 -#endif - -#define NK_CONFIGURATION_STACK_TYPE(prefix, name, type)\ - struct nk_config_stack_##name##_element {\ - prefix##_##type *address;\ - prefix##_##type old_value;\ - } -#define NK_CONFIG_STACK(type,size)\ - struct nk_config_stack_##type {\ - int head;\ - struct nk_config_stack_##type##_element elements[size];\ - } - -#define nk_float float -NK_CONFIGURATION_STACK_TYPE(struct nk, style_item, style_item); -NK_CONFIGURATION_STACK_TYPE(nk ,float, float); -NK_CONFIGURATION_STACK_TYPE(struct nk, vec2, vec2); -NK_CONFIGURATION_STACK_TYPE(nk ,flags, flags); -NK_CONFIGURATION_STACK_TYPE(struct nk, color, color); -NK_CONFIGURATION_STACK_TYPE(const struct nk, user_font, user_font*); -NK_CONFIGURATION_STACK_TYPE(enum nk, button_behavior, button_behavior); - -NK_CONFIG_STACK(style_item, NK_STYLE_ITEM_STACK_SIZE); -NK_CONFIG_STACK(float, NK_FLOAT_STACK_SIZE); -NK_CONFIG_STACK(vec2, NK_VECTOR_STACK_SIZE); -NK_CONFIG_STACK(flags, NK_FLAGS_STACK_SIZE); -NK_CONFIG_STACK(color, NK_COLOR_STACK_SIZE); -NK_CONFIG_STACK(user_font, NK_FONT_STACK_SIZE); -NK_CONFIG_STACK(button_behavior, NK_BUTTON_BEHAVIOR_STACK_SIZE); - -struct nk_configuration_stacks { - struct nk_config_stack_style_item style_items; - struct nk_config_stack_float floats; - struct nk_config_stack_vec2 vectors; - struct nk_config_stack_flags flags; - struct nk_config_stack_color colors; - struct nk_config_stack_user_font fonts; - struct nk_config_stack_button_behavior button_behaviors; -}; - -/*============================================================== - * CONTEXT - * =============================================================*/ -#define NK_VALUE_PAGE_CAPACITY \ - ((NK_MAX(sizeof(struct nk_window),sizeof(struct nk_panel)) / sizeof(nk_uint)) / 2) - -struct nk_table { - unsigned int seq; - nk_hash keys[NK_VALUE_PAGE_CAPACITY]; - nk_uint values[NK_VALUE_PAGE_CAPACITY]; - struct nk_table *next, *prev; -}; - -union nk_page_data { - struct nk_table tbl; - struct nk_panel pan; - struct nk_window win; -}; - -struct nk_page_element { - union nk_page_data data; - struct nk_page_element *next; - struct nk_page_element *prev; -}; - -struct nk_page { - unsigned int size; - struct nk_page *next; - struct nk_page_element win[1]; -}; - -struct nk_pool { - struct nk_allocator alloc; - enum nk_allocation_type type; - unsigned int page_count; - struct nk_page *pages; - struct nk_page_element *freelist; - unsigned capacity; - nk_size size; - nk_size cap; -}; - -struct nk_context { -/* public: can be accessed freely */ - struct nk_input input; - struct nk_style style; - struct nk_buffer memory; - struct nk_clipboard clip; - nk_flags last_widget_state; - enum nk_button_behavior button_behavior; - struct nk_configuration_stacks stacks; - float delta_time_seconds; - -/* private: - should only be accessed if you - know what you are doing */ -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT - struct nk_draw_list draw_list; -#endif -#ifdef NK_INCLUDE_COMMAND_USERDATA - nk_handle userdata; -#endif - /* text editor objects are quite big because of an internal - * undo/redo stack. Therefore it does not make sense to have one for - * each window for temporary use cases, so I only provide *one* instance - * for all windows. This works because the content is cleared anyway */ - struct nk_text_edit text_edit; - /* draw buffer used for overlay drawing operation like cursor */ - struct nk_command_buffer overlay; - - /* windows */ - int build; - int use_pool; - struct nk_pool pool; - struct nk_window *begin; - struct nk_window *end; - struct nk_window *active; - struct nk_window *current; - struct nk_page_element *freelist; - unsigned int count; - unsigned int seq; -}; - -/* ============================================================== - * MATH - * =============================================================== */ -#define NK_PI 3.141592654f -#define NK_UTF_INVALID 0xFFFD -#define NK_MAX_FLOAT_PRECISION 2 - -#define NK_UNUSED(x) ((void)(x)) -#define NK_SATURATE(x) (NK_MAX(0, NK_MIN(1.0f, x))) -#define NK_LEN(a) (sizeof(a)/sizeof(a)[0]) -#define NK_ABS(a) (((a) < 0) ? -(a) : (a)) -#define NK_BETWEEN(x, a, b) ((a) <= (x) && (x) <= (b)) -#define NK_INBOX(px, py, x, y, w, h)\ - (NK_BETWEEN(px,x,x+w) && NK_BETWEEN(py,y,y+h)) -#define NK_INTERSECT(x0, y0, w0, h0, x1, y1, w1, h1) \ - (!(((x1 > (x0 + w0)) || ((x1 + w1) < x0) || (y1 > (y0 + h0)) || (y1 + h1) < y0))) -#define NK_CONTAINS(x, y, w, h, bx, by, bw, bh)\ - (NK_INBOX(x,y, bx, by, bw, bh) && NK_INBOX(x+w,y+h, bx, by, bw, bh)) - -#define nk_vec2_sub(a, b) nk_vec2((a).x - (b).x, (a).y - (b).y) -#define nk_vec2_add(a, b) nk_vec2((a).x + (b).x, (a).y + (b).y) -#define nk_vec2_len_sqr(a) ((a).x*(a).x+(a).y*(a).y) -#define nk_vec2_muls(a, t) nk_vec2((a).x * (t), (a).y * (t)) - -#define nk_ptr_add(t, p, i) ((t*)((void*)((nk_byte*)(p) + (i)))) -#define nk_ptr_add_const(t, p, i) ((const t*)((const void*)((const nk_byte*)(p) + (i)))) -#define nk_zero_struct(s) nk_zero(&s, sizeof(s)) - -/* ============================================================== - * ALIGNMENT - * =============================================================== */ -/* Pointer to Integer type conversion for pointer alignment */ -#if defined(__PTRDIFF_TYPE__) /* This case should work for GCC*/ -# define NK_UINT_TO_PTR(x) ((void*)(__PTRDIFF_TYPE__)(x)) -# define NK_PTR_TO_UINT(x) ((nk_size)(__PTRDIFF_TYPE__)(x)) -#elif !defined(__GNUC__) /* works for compilers other than LLVM */ -# define NK_UINT_TO_PTR(x) ((void*)&((char*)0)[x]) -# define NK_PTR_TO_UINT(x) ((nk_size)(((char*)x)-(char*)0)) -#elif defined(NK_USE_FIXED_TYPES) /* used if we have */ -# define NK_UINT_TO_PTR(x) ((void*)(uintptr_t)(x)) -# define NK_PTR_TO_UINT(x) ((uintptr_t)(x)) -#else /* generates warning but works */ -# define NK_UINT_TO_PTR(x) ((void*)(x)) -# define NK_PTR_TO_UINT(x) ((nk_size)(x)) -#endif - -#define NK_ALIGN_PTR(x, mask)\ - (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x) + (mask-1)) & ~(mask-1)))) -#define NK_ALIGN_PTR_BACK(x, mask)\ - (NK_UINT_TO_PTR((NK_PTR_TO_UINT((nk_byte*)(x)) & ~(mask-1)))) - -#define NK_OFFSETOF(st,m) ((nk_ptr)&(((st*)0)->m)) -#define NK_CONTAINER_OF(ptr,type,member)\ - (type*)((void*)((char*)(1 ? (ptr): &((type*)0)->member) - NK_OFFSETOF(type, member))) - -#ifdef __cplusplus -} -#endif - -#ifdef __cplusplus -template struct nk_alignof; -template struct nk_helper{enum {value = size_diff};}; -template struct nk_helper{enum {value = nk_alignof::value};}; -template struct nk_alignof{struct Big {T x; char c;}; enum { - diff = sizeof(Big) - sizeof(T), value = nk_helper::value};}; -#define NK_ALIGNOF(t) (nk_alignof::value); -#elif defined(_MSC_VER) -#define NK_ALIGNOF(t) (__alignof(t)) -#else -#define NK_ALIGNOF(t) ((char*)(&((struct {char c; t _h;}*)0)->_h) - (char*)0) -#endif - -#endif /* NK_H_ */ -/* - * ============================================================== - * - * IMPLEMENTATION - * - * =============================================================== - */ -#ifdef NK_IMPLEMENTATION - -#ifndef NK_POOL_DEFAULT_CAPACITY -#define NK_POOL_DEFAULT_CAPACITY 16 -#endif - -#ifndef NK_DEFAULT_COMMAND_BUFFER_SIZE -#define NK_DEFAULT_COMMAND_BUFFER_SIZE (4*1024) -#endif - -#ifndef NK_BUFFER_DEFAULT_INITIAL_SIZE -#define NK_BUFFER_DEFAULT_INITIAL_SIZE (4*1024) -#endif - -/* standard library headers */ -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -#include /* malloc, free */ -#endif -#ifdef NK_INCLUDE_STANDARD_IO -#include /* fopen, fclose,... */ -#endif -#ifdef NK_INCLUDE_STANDARD_VARARGS -#include /* valist, va_start, va_end, ... */ -#endif -#ifndef NK_ASSERT -#include -#define NK_ASSERT(expr) assert(expr) -#endif - -#ifndef NK_MEMSET -#define NK_MEMSET nk_memset -#endif -#ifndef NK_MEMCPY -#define NK_MEMCPY nk_memcopy -#endif -#ifndef NK_SQRT -#define NK_SQRT nk_sqrt -#endif -#ifndef NK_SIN -#define NK_SIN nk_sin -#endif -#ifndef NK_COS -#define NK_COS nk_cos -#endif -#ifndef NK_STRTOD -#define NK_STRTOD nk_strtod -#endif -#ifndef NK_DTOA -#define NK_DTOA nk_dtoa -#endif - -#define NK_DEFAULT (-1) - -#ifndef NK_VSNPRINTF -/* If your compiler does support `vsnprintf` I would highly recommend - * defining this to vsnprintf instead since `vsprintf` is basically - * unbelievable unsafe and should *NEVER* be used. But I have to support - * it since C89 only provides this unsafe version. */ - #if (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) ||\ - (defined(__cplusplus) && (__cplusplus >= 201103L)) || \ - (defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L)) ||\ - (defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) ||\ - defined(_ISOC99_SOURCE) || defined(_BSD_SOURCE) - #define NK_VSNPRINTF(s,n,f,a) vsnprintf(s,n,f,a) - #else - #define NK_VSNPRINTF(s,n,f,a) vsprintf(s,f,a) - #endif -#endif - -#define NK_SCHAR_MIN (-127) -#define NK_SCHAR_MAX 127 -#define NK_UCHAR_MIN 0 -#define NK_UCHAR_MAX 256 -#define NK_SSHORT_MIN (-32767) -#define NK_SSHORT_MAX 32767 -#define NK_USHORT_MIN 0 -#define NK_USHORT_MAX 65535 -#define NK_SINT_MIN (-2147483647) -#define NK_SINT_MAX 2147483647 -#define NK_UINT_MIN 0 -#define NK_UINT_MAX 4294967295 - -/* Make sure correct type size: - * This will fire with a negative subscript error if the type sizes - * are set incorrectly by the compiler, and compile out if not */ -NK_STATIC_ASSERT(sizeof(nk_size) >= sizeof(void*)); -NK_STATIC_ASSERT(sizeof(nk_ptr) == sizeof(void*)); -NK_STATIC_ASSERT(sizeof(nk_flags) >= 4); -NK_STATIC_ASSERT(sizeof(nk_rune) >= 4); -NK_STATIC_ASSERT(sizeof(nk_ushort) == 2); -NK_STATIC_ASSERT(sizeof(nk_short) == 2); -NK_STATIC_ASSERT(sizeof(nk_uint) == 4); -NK_STATIC_ASSERT(sizeof(nk_int) == 4); -NK_STATIC_ASSERT(sizeof(nk_byte) == 1); - -NK_GLOBAL const struct nk_rect nk_null_rect = {-8192.0f, -8192.0f, 16384, 16384}; -#define NK_FLOAT_PRECISION 0.00000000000001 - -NK_GLOBAL const struct nk_color nk_red = {255,0,0,255}; -NK_GLOBAL const struct nk_color nk_green = {0,255,0,255}; -NK_GLOBAL const struct nk_color nk_blue = {0,0,255,255}; -NK_GLOBAL const struct nk_color nk_white = {255,255,255,255}; -NK_GLOBAL const struct nk_color nk_black = {0,0,0,255}; -NK_GLOBAL const struct nk_color nk_yellow = {255,255,0,255}; - -/* - * ============================================================== - * - * MATH - * - * =============================================================== - */ -/* Since nuklear is supposed to work on all systems providing floating point - math without any dependencies I also had to implement my own math functions - for sqrt, sin and cos. Since the actual highly accurate implementations for - the standard library functions are quite complex and I do not need high - precision for my use cases I use approximations. - - Sqrt - ---- - For square root nuklear uses the famous fast inverse square root: - https://en.wikipedia.org/wiki/Fast_inverse_square_root with - slightly tweaked magic constant. While on todays hardware it is - probably not faster it is still fast and accurate enough for - nuklear's use cases. IMPORTANT: this requires float format IEEE 754 - - Sine/Cosine - ----------- - All constants inside both function are generated Remez's minimax - approximations for value range 0...2*PI. The reason why I decided to - approximate exactly that range is that nuklear only needs sine and - cosine to generate circles which only requires that exact range. - In addition I used Remez instead of Taylor for additional precision: - www.lolengine.net/blog/2011/12/21/better-function-approximatations. - - The tool I used to generate constants for both sine and cosine - (it can actually approximate a lot more functions) can be - found here: www.lolengine.net/wiki/oss/lolremez -*/ -NK_INTERN float -nk_inv_sqrt(float number) -{ - float x2; - const float threehalfs = 1.5f; - union {nk_uint i; float f;} conv = {0}; - conv.f = number; - x2 = number * 0.5f; - conv.i = 0x5f375A84 - (conv.i >> 1); - conv.f = conv.f * (threehalfs - (x2 * conv.f * conv.f)); - return conv.f; -} - -NK_INTERN float -nk_sqrt(float x) -{ - return x * nk_inv_sqrt(x); -} - -NK_INTERN float -nk_sin(float x) -{ - NK_STORAGE const float a0 = +1.91059300966915117e-31f; - NK_STORAGE const float a1 = +1.00086760103908896f; - NK_STORAGE const float a2 = -1.21276126894734565e-2f; - NK_STORAGE const float a3 = -1.38078780785773762e-1f; - NK_STORAGE const float a4 = -2.67353392911981221e-2f; - NK_STORAGE const float a5 = +2.08026600266304389e-2f; - NK_STORAGE const float a6 = -3.03996055049204407e-3f; - NK_STORAGE const float a7 = +1.38235642404333740e-4f; - return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7)))))); -} - -NK_INTERN float -nk_cos(float x) -{ - NK_STORAGE const float a0 = +1.00238601909309722f; - NK_STORAGE const float a1 = -3.81919947353040024e-2f; - NK_STORAGE const float a2 = -3.94382342128062756e-1f; - NK_STORAGE const float a3 = -1.18134036025221444e-1f; - NK_STORAGE const float a4 = +1.07123798512170878e-1f; - NK_STORAGE const float a5 = -1.86637164165180873e-2f; - NK_STORAGE const float a6 = +9.90140908664079833e-4f; - NK_STORAGE const float a7 = -5.23022132118824778e-14f; - return a0 + x*(a1 + x*(a2 + x*(a3 + x*(a4 + x*(a5 + x*(a6 + x*a7)))))); -} - -NK_INTERN nk_uint -nk_round_up_pow2(nk_uint v) -{ - v--; - v |= v >> 1; - v |= v >> 2; - v |= v >> 4; - v |= v >> 8; - v |= v >> 16; - v++; - return v; -} - -NK_API struct nk_rect -nk_get_null_rect(void) -{ - return nk_null_rect; -} - -NK_API struct nk_rect -nk_rect(float x, float y, float w, float h) -{ - struct nk_rect r; - r.x = x; r.y = y; - r.w = w; r.h = h; - return r; -} - -NK_API struct nk_rect -nk_recti(int x, int y, int w, int h) -{ - struct nk_rect r; - r.x = (float)x; - r.y = (float)y; - r.w = (float)w; - r.h = (float)h; - return r; -} - -NK_API struct nk_rect -nk_recta(struct nk_vec2 pos, struct nk_vec2 size) -{ - return nk_rect(pos.x, pos.y, size.x, size.y); -} - -NK_API struct nk_rect -nk_rectv(const float *r) -{ - return nk_rect(r[0], r[1], r[2], r[3]); -} - -NK_API struct nk_rect -nk_rectiv(const int *r) -{ - return nk_recti(r[0], r[1], r[2], r[3]); -} - -NK_API struct nk_vec2 -nk_rect_pos(struct nk_rect r) -{ - struct nk_vec2 ret; - ret.x = r.x; ret.y = r.y; - return ret; -} - -NK_API struct nk_vec2 -nk_rect_size(struct nk_rect r) -{ - struct nk_vec2 ret; - ret.x = r.w; ret.y = r.h; - return ret; -} - -NK_INTERN struct nk_rect -nk_shrink_rect(struct nk_rect r, float amount) -{ - struct nk_rect res; - r.w = NK_MAX(r.w, 2 * amount); - r.h = NK_MAX(r.h, 2 * amount); - res.x = r.x + amount; - res.y = r.y + amount; - res.w = r.w - 2 * amount; - res.h = r.h - 2 * amount; - return res; -} - -NK_INTERN struct nk_rect -nk_pad_rect(struct nk_rect r, struct nk_vec2 pad) -{ - r.w = NK_MAX(r.w, 2 * pad.x); - r.h = NK_MAX(r.h, 2 * pad.y); - r.x += pad.x; r.y += pad.y; - r.w -= 2 * pad.x; - r.h -= 2 * pad.y; - return r; -} - -NK_API struct nk_vec2 -nk_vec2(float x, float y) -{ - struct nk_vec2 ret; - ret.x = x; ret.y = y; - return ret; -} - -NK_API struct nk_vec2 -nk_vec2i(int x, int y) -{ - struct nk_vec2 ret; - ret.x = (float)x; - ret.y = (float)y; - return ret; -} - -NK_API struct nk_vec2 -nk_vec2v(const float *v) -{ - return nk_vec2(v[0], v[1]); -} - -NK_API struct nk_vec2 -nk_vec2iv(const int *v) -{ - return nk_vec2i(v[0], v[1]); -} - -/* - * ============================================================== - * - * UTIL - * - * =============================================================== - */ -NK_INTERN int nk_str_match_here(const char *regexp, const char *text); -NK_INTERN int nk_str_match_star(int c, const char *regexp, const char *text); -NK_INTERN int nk_is_lower(int c) {return (c >= 'a' && c <= 'z') || (c >= 0xE0 && c <= 0xFF);} -NK_INTERN int nk_is_upper(int c){return (c >= 'A' && c <= 'Z') || (c >= 0xC0 && c <= 0xDF);} -NK_INTERN int nk_to_upper(int c) {return (c >= 'a' && c <= 'z') ? (c - ('a' - 'A')) : c;} -NK_INTERN int nk_to_lower(int c) {return (c >= 'A' && c <= 'Z') ? (c - ('a' + 'A')) : c;} - -NK_INTERN void* -nk_memcopy(void *dst0, const void *src0, nk_size length) -{ - nk_ptr t; - char *dst = (char*)dst0; - const char *src = (const char*)src0; - if (length == 0 || dst == src) - goto done; - - #define nk_word int - #define nk_wsize sizeof(nk_word) - #define nk_wmask (nk_wsize-1) - #define NK_TLOOP(s) if (t) NK_TLOOP1(s) - #define NK_TLOOP1(s) do { s; } while (--t) - - if (dst < src) { - t = (nk_ptr)src; /* only need low bits */ - if ((t | (nk_ptr)dst) & nk_wmask) { - if ((t ^ (nk_ptr)dst) & nk_wmask || length < nk_wsize) - t = length; - else - t = nk_wsize - (t & nk_wmask); - length -= t; - NK_TLOOP1(*dst++ = *src++); - } - t = length / nk_wsize; - NK_TLOOP(*(nk_word*)(void*)dst = *(const nk_word*)(const void*)src; - src += nk_wsize; dst += nk_wsize); - t = length & nk_wmask; - NK_TLOOP(*dst++ = *src++); - } else { - src += length; - dst += length; - t = (nk_ptr)src; - if ((t | (nk_ptr)dst) & nk_wmask) { - if ((t ^ (nk_ptr)dst) & nk_wmask || length <= nk_wsize) - t = length; - else - t &= nk_wmask; - length -= t; - NK_TLOOP1(*--dst = *--src); - } - t = length / nk_wsize; - NK_TLOOP(src -= nk_wsize; dst -= nk_wsize; - *(nk_word*)(void*)dst = *(const nk_word*)(const void*)src); - t = length & nk_wmask; - NK_TLOOP(*--dst = *--src); - } - #undef nk_word - #undef nk_wsize - #undef nk_wmask - #undef NK_TLOOP - #undef NK_TLOOP1 -done: - return (dst0); -} - -NK_INTERN void -nk_memset(void *ptr, int c0, nk_size size) -{ - #define nk_word unsigned - #define nk_wsize sizeof(nk_word) - #define nk_wmask (nk_wsize - 1) - nk_byte *dst = (nk_byte*)ptr; - unsigned c = 0; - nk_size t = 0; - - if ((c = (nk_byte)c0) != 0) { - c = (c << 8) | c; /* at least 16-bits */ - if (sizeof(unsigned int) > 2) - c = (c << 16) | c; /* at least 32-bits*/ - } - - /* too small of a word count */ - dst = (nk_byte*)ptr; - if (size < 3 * nk_wsize) { - while (size--) *dst++ = (nk_byte)c0; - return; - } - - /* align destination */ - if ((t = NK_PTR_TO_UINT(dst) & nk_wmask) != 0) { - t = nk_wsize -t; - size -= t; - do { - *dst++ = (nk_byte)c0; - } while (--t != 0); - } - - /* fill word */ - t = size / nk_wsize; - do { - *(nk_word*)((void*)dst) = c; - dst += nk_wsize; - } while (--t != 0); - - /* fill trailing bytes */ - t = (size & nk_wmask); - if (t != 0) { - do { - *dst++ = (nk_byte)c0; - } while (--t != 0); - } - - #undef nk_word - #undef nk_wsize - #undef nk_wmask -} - -NK_INTERN void -nk_zero(void *ptr, nk_size size) -{ - NK_ASSERT(ptr); - NK_MEMSET(ptr, 0, size); -} - -NK_API int -nk_strlen(const char *str) -{ - int siz = 0; - NK_ASSERT(str); - while (str && *str++ != '\0') siz++; - return siz; -} - -NK_API int -nk_strtoi(const char *str, char **endptr) -{ - int neg = 1; - const char *p = str; - int value = 0; - - NK_ASSERT(str); - if (!str) return 0; - - /* skip whitespace */ - while (*p == ' ') p++; - if (*p == '-') { - neg = -1; - p++; - } - while (*p && *p >= '0' && *p <= '9') { - value = value * 10 + (int) (*p - '0'); - p++; - } - if (endptr) - *endptr = (char*)p; - return neg*value; -} - -NK_API double -nk_strtod(const char *str, char **endptr) -{ - double m; - double neg = 1.0; - const char *p = str; - double value = 0; - double number = 0; - - NK_ASSERT(str); - if (!str) return 0; - - /* skip whitespace */ - while (*p == ' ') p++; - if (*p == '-') { - neg = -1.0; - p++; - } - - while (*p && *p != '.' && *p != 'e') { - value = value * 10.0 + (double) (*p - '0'); - p++; - } - - if (*p == '.') { - p++; - for(m = 0.1; *p && *p != 'e'; p++ ) { - value = value + (double) (*p - '0') * m; - m *= 0.1; - } - } - if (*p == 'e') { - int i, pow, div; - p++; - if (*p == '-') { - div = nk_true; - p++; - } else if (*p == '+') { - div = nk_false; - p++; - } else div = nk_false; - - for (pow = 0; *p; p++) - pow = pow * 10 + (int) (*p - '0'); - - for (m = 1.0, i = 0; i < pow; i++) - m *= 10.0; - - if (div) - value /= m; - else value *= m; - } - number = value * neg; - if (endptr) - *endptr = (char*)p; - return number; -} - -NK_API float -nk_strtof(const char *str, char **endptr) -{ - float float_value; - double double_value; - double_value = NK_STRTOD(str, endptr); - float_value = (float)double_value; - return float_value; -} - -NK_API int -nk_stricmp(const char *s1, const char *s2) -{ - nk_int c1,c2,d; - do { - c1 = *s1++; - c2 = *s2++; - d = c1 - c2; - while (d) { - if (c1 <= 'Z' && c1 >= 'A') { - d += ('a' - 'A'); - if (!d) break; - } - if (c2 <= 'Z' && c2 >= 'A') { - d -= ('a' - 'A'); - if (!d) break; - } - return ((d >= 0) << 1) - 1; - } - } while (c1); - return 0; -} - -NK_API int -nk_stricmpn(const char *s1, const char *s2, int n) -{ - int c1,c2,d; - NK_ASSERT(n >= 0); - do { - c1 = *s1++; - c2 = *s2++; - if (!n--) return 0; - - d = c1 - c2; - while (d) { - if (c1 <= 'Z' && c1 >= 'A') { - d += ('a' - 'A'); - if (!d) break; - } - if (c2 <= 'Z' && c2 >= 'A') { - d -= ('a' - 'A'); - if (!d) break; - } - return ((d >= 0) << 1) - 1; - } - } while (c1); - return 0; -} - -NK_INTERN int -nk_str_match_here(const char *regexp, const char *text) -{ - if (regexp[0] == '\0') - return 1; - if (regexp[1] == '*') - return nk_str_match_star(regexp[0], regexp+2, text); - if (regexp[0] == '$' && regexp[1] == '\0') - return *text == '\0'; - if (*text!='\0' && (regexp[0]=='.' || regexp[0]==*text)) - return nk_str_match_here(regexp+1, text+1); - return 0; -} - -NK_INTERN int -nk_str_match_star(int c, const char *regexp, const char *text) -{ - do {/* a '* matches zero or more instances */ - if (nk_str_match_here(regexp, text)) - return 1; - } while (*text != '\0' && (*text++ == c || c == '.')); - return 0; -} - -NK_API int -nk_strfilter(const char *text, const char *regexp) -{ - /* - c matches any literal character c - . matches any single character - ^ matches the beginning of the input string - $ matches the end of the input string - * matches zero or more occurrences of the previous character*/ - if (regexp[0] == '^') - return nk_str_match_here(regexp+1, text); - do { /* must look even if string is empty */ - if (nk_str_match_here(regexp, text)) - return 1; - } while (*text++ != '\0'); - return 0; -} - -NK_API int -nk_strmatch_fuzzy_text(const char *str, int str_len, - const char *pattern, int *out_score) -{ - /* Returns true if each character in pattern is found sequentially within str - * if found then outScore is also set. Score value has no intrinsic meaning. - * Range varies with pattern. Can only compare scores with same search pattern. */ - - /* ------- scores --------- */ - /* bonus for adjacent matches */ - #define NK_ADJACENCY_BONUS 5 - /* bonus if match occurs after a separator */ - #define NK_SEPARATOR_BONUS 10 - /* bonus if match is uppercase and prev is lower */ - #define NK_CAMEL_BONUS 10 - /* penalty applied for every letter in str before the first match */ - #define NK_LEADING_LETTER_PENALTY (-3) - /* maximum penalty for leading letters */ - #define NK_MAX_LEADING_LETTER_PENALTY (-9) - /* penalty for every letter that doesn't matter */ - #define NK_UNMATCHED_LETTER_PENALTY (-1) - - /* loop variables */ - int score = 0; - char const * pattern_iter = pattern; - int str_iter = 0; - int prev_matched = nk_false; - int prev_lower = nk_false; - /* true so if first letter match gets separator bonus*/ - int prev_separator = nk_true; - - /* use "best" matched letter if multiple string letters match the pattern */ - char const * best_letter = 0; - int best_letter_score = 0; - - /* loop over strings */ - NK_ASSERT(str); - NK_ASSERT(pattern); - if (!str || !str_len || !pattern) return 0; - while (str_iter < str_len) - { - const char pattern_letter = *pattern_iter; - const char str_letter = str[str_iter]; - - int next_match = *pattern_iter != '\0' && - nk_to_lower(pattern_letter) == nk_to_lower(str_letter); - int rematch = best_letter && nk_to_lower(*best_letter) == nk_to_lower(str_letter); - - int advanced = next_match && best_letter; - int pattern_repeat = best_letter && *pattern_iter != '\0'; - pattern_repeat = pattern_repeat && - nk_to_lower(*best_letter) == nk_to_lower(pattern_letter); - - if (advanced || pattern_repeat) { - score += best_letter_score; - best_letter = 0; - best_letter_score = 0; - } - - if (next_match || rematch) - { - int new_score = 0; - /* Apply penalty for each letter before the first pattern match */ - if (pattern_iter == pattern) { - int count = (int)(&str[str_iter] - str); - int penalty = NK_LEADING_LETTER_PENALTY * count; - if (penalty < NK_MAX_LEADING_LETTER_PENALTY) - penalty = NK_MAX_LEADING_LETTER_PENALTY; - - score += penalty; - } - - /* apply bonus for consecutive bonuses */ - if (prev_matched) - new_score += NK_ADJACENCY_BONUS; - - /* apply bonus for matches after a separator */ - if (prev_separator) - new_score += NK_SEPARATOR_BONUS; - - /* apply bonus across camel case boundaries */ - if (prev_lower && nk_is_upper(str_letter)) - new_score += NK_CAMEL_BONUS; - - /* update pattern iter IFF the next pattern letter was matched */ - if (next_match) - ++pattern_iter; - - /* update best letter in str which may be for a "next" letter or a rematch */ - if (new_score >= best_letter_score) { - /* apply penalty for now skipped letter */ - if (best_letter != 0) - score += NK_UNMATCHED_LETTER_PENALTY; - - best_letter = &str[str_iter]; - best_letter_score = new_score; - } - prev_matched = nk_true; - } else { - score += NK_UNMATCHED_LETTER_PENALTY; - prev_matched = nk_false; - } - - /* separators should be more easily defined */ - prev_lower = nk_is_lower(str_letter) != 0; - prev_separator = str_letter == '_' || str_letter == ' '; - - ++str_iter; - } - - /* apply score for last match */ - if (best_letter) - score += best_letter_score; - - /* did not match full pattern */ - if (*pattern_iter != '\0') - return nk_false; - - if (out_score) - *out_score = score; - return nk_true; -} - -NK_API int -nk_strmatch_fuzzy_string(char const *str, char const *pattern, int *out_score) -{return nk_strmatch_fuzzy_text(str, nk_strlen(str), pattern, out_score);} - -NK_INTERN int -nk_string_float_limit(char *string, int prec) -{ - int dot = 0; - char *c = string; - while (*c) { - if (*c == '.') { - dot = 1; - c++; - continue; - } - if (dot == (prec+1)) { - *c = 0; - break; - } - if (dot > 0) dot++; - c++; - } - return (int)(c - string); -} - -NK_INTERN double -nk_pow(double x, int n) -{ - /* check the sign of n */ - double r = 1; - int plus = n >= 0; - n = (plus) ? n : -n; - while (n > 0) { - if ((n & 1) == 1) - r *= x; - n /= 2; - x *= x; - } - return plus ? r : 1.0 / r; -} - -NK_INTERN int -nk_ifloord(double x) -{ - x = (double)((int)x - ((x < 0.0) ? 1 : 0)); - return (int)x; -} - -NK_INTERN int -nk_ifloorf(float x) -{ - x = (float)((int)x - ((x < 0.0f) ? 1 : 0)); - return (int)x; -} - -NK_INTERN int -nk_iceilf(float x) -{ - if (x >= 0) { - int i = (int)x; - return i; - } else { - int t = (int)x; - float r = x - (float)t; - return (r > 0.0f) ? t+1: t; - } -} - -NK_INTERN int -nk_log10(double n) -{ - int neg; - int ret; - int exp = 0; - - neg = (n < 0) ? 1 : 0; - ret = (neg) ? (int)-n : (int)n; - while ((ret / 10) > 0) { - ret /= 10; - exp++; - } - if (neg) exp = -exp; - return exp; -} - -NK_INTERN void -nk_strrev_ascii(char *s) -{ - int len = nk_strlen(s); - int end = len / 2; - int i = 0; - char t; - for (; i < end; ++i) { - t = s[i]; - s[i] = s[len - 1 - i]; - s[len -1 - i] = t; - } -} - -NK_INTERN char* -nk_itoa(char *s, long n) -{ - long i = 0; - if (n == 0) { - s[i++] = '0'; - s[i] = 0; - return s; - } - if (n < 0) { - s[i++] = '-'; - n = -n; - } - while (n > 0) { - s[i++] = (char)('0' + (n % 10)); - n /= 10; - } - s[i] = 0; - if (s[0] == '-') - ++s; - - nk_strrev_ascii(s); - return s; -} - -NK_INTERN char* -nk_dtoa(char *s, double n) -{ - int useExp = 0; - int digit = 0, m = 0, m1 = 0; - char *c = s; - int neg = 0; - - NK_ASSERT(s); - if (!s) return 0; - - if (n == 0.0) { - s[0] = '0'; s[1] = '\0'; - return s; - } - - neg = (n < 0); - if (neg) n = -n; - - /* calculate magnitude */ - m = nk_log10(n); - useExp = (m >= 14 || (neg && m >= 9) || m <= -9); - if (neg) *(c++) = '-'; - - /* set up for scientific notation */ - if (useExp) { - if (m < 0) - m -= 1; - n = n / (double)nk_pow(10.0, m); - m1 = m; - m = 0; - } - if (m < 1.0) { - m = 0; - } - - /* convert the number */ - while (n > NK_FLOAT_PRECISION || m >= 0) { - double weight = nk_pow(10.0, m); - if (weight > 0) { - double t = (double)n / weight; - digit = nk_ifloord(t); - n -= ((double)digit * weight); - *(c++) = (char)('0' + (char)digit); - } - if (m == 0 && n > 0) - *(c++) = '.'; - m--; - } - - if (useExp) { - /* convert the exponent */ - int i, j; - *(c++) = 'e'; - if (m1 > 0) { - *(c++) = '+'; - } else { - *(c++) = '-'; - m1 = -m1; - } - m = 0; - while (m1 > 0) { - *(c++) = (char)('0' + (char)(m1 % 10)); - m1 /= 10; - m++; - } - c -= m; - for (i = 0, j = m-1; i= buf_size) break; - iter++; - - /* flag arguments */ - while (*iter) { - if (*iter == '-') flag |= NK_ARG_FLAG_LEFT; - else if (*iter == '+') flag |= NK_ARG_FLAG_PLUS; - else if (*iter == ' ') flag |= NK_ARG_FLAG_SPACE; - else if (*iter == '#') flag |= NK_ARG_FLAG_NUM; - else if (*iter == '0') flag |= NK_ARG_FLAG_ZERO; - else break; - iter++; - } - - /* width argument */ - width = NK_DEFAULT; - if (*iter >= '1' && *iter <= '9') { - char *end; - width = nk_strtoi(iter, &end); - if (end == iter) - width = -1; - else iter = end; - } else if (*iter == '*') { - width = va_arg(args, int); - iter++; - } - - /* precision argument */ - precision = NK_DEFAULT; - if (*iter == '.') { - iter++; - if (*iter == '*') { - precision = va_arg(args, int); - iter++; - } else { - char *end; - precision = nk_strtoi(iter, &end); - if (end == iter) - precision = -1; - else iter = end; - } - } - - /* length modifier */ - if (*iter == 'h') { - if (*(iter+1) == 'h') { - arg_type = NK_ARG_TYPE_CHAR; - iter++; - } else arg_type = NK_ARG_TYPE_SHORT; - iter++; - } else if (*iter == 'l') { - arg_type = NK_ARG_TYPE_LONG; - iter++; - } else arg_type = NK_ARG_TYPE_DEFAULT; - - /* specifier */ - if (*iter == '%') { - NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); - NK_ASSERT(precision == NK_DEFAULT); - NK_ASSERT(width == NK_DEFAULT); - if (len < buf_size) - buf[len++] = '%'; - } else if (*iter == 's') { - /* string */ - const char *str = va_arg(args, const char*); - NK_ASSERT(str != buf && "buffer and argument are not allowed to overlap!"); - NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); - NK_ASSERT(precision == NK_DEFAULT); - NK_ASSERT(width == NK_DEFAULT); - if (str == buf) return -1; - while (str && *str && len < buf_size) - buf[len++] = *str++; - } else if (*iter == 'n') { - /* current length callback */ - signed int *n = va_arg(args, int*); - NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); - NK_ASSERT(precision == NK_DEFAULT); - NK_ASSERT(width == NK_DEFAULT); - if (n) *n = len; - } else if (*iter == 'c' || *iter == 'i' || *iter == 'd') { - /* signed integer */ - long value = 0; - const char *num_iter; - int num_len, num_print, padding; - int cur_precision = NK_MAX(precision, 1); - int cur_width = NK_MAX(width, 0); - - /* retrieve correct value type */ - if (arg_type == NK_ARG_TYPE_CHAR) - value = (signed char)va_arg(args, int); - else if (arg_type == NK_ARG_TYPE_SHORT) - value = (signed short)va_arg(args, int); - else if (arg_type == NK_ARG_TYPE_LONG) - value = va_arg(args, signed long); - else if (*iter == 'c') - value = (unsigned char)va_arg(args, int); - else value = va_arg(args, signed int); - - /* convert number to string */ - nk_itoa(number_buffer, value); - num_len = nk_strlen(number_buffer); - padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); - if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) - padding = NK_MAX(padding-1, 0); - - /* fill left padding up to a total of `width` characters */ - if (!(flag & NK_ARG_FLAG_LEFT)) { - while (padding-- > 0 && (len < buf_size)) { - if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) - buf[len++] = '0'; - else buf[len++] = ' '; - } - } - - /* copy string value representation into buffer */ - if ((flag & NK_ARG_FLAG_PLUS) && value >= 0 && len < buf_size) - buf[len++] = '+'; - else if ((flag & NK_ARG_FLAG_SPACE) && value >= 0 && len < buf_size) - buf[len++] = ' '; - - /* fill up to precision number of digits with '0' */ - num_print = NK_MAX(cur_precision, num_len); - while (precision && (num_print > num_len) && (len < buf_size)) { - buf[len++] = '0'; - num_print--; - } - - /* copy string value representation into buffer */ - num_iter = number_buffer; - while (precision && *num_iter && len < buf_size) - buf[len++] = *num_iter++; - - /* fill right padding up to width characters */ - if (flag & NK_ARG_FLAG_LEFT) { - while ((padding-- > 0) && (len < buf_size)) - buf[len++] = ' '; - } - } else if (*iter == 'o' || *iter == 'x' || *iter == 'X' || *iter == 'u') { - /* unsigned integer */ - unsigned long value = 0; - int num_len = 0, num_print, padding = 0; - int cur_precision = NK_MAX(precision, 1); - int cur_width = NK_MAX(width, 0); - unsigned int base = (*iter == 'o') ? 8: (*iter == 'u')? 10: 16; - - /* print oct/hex/dec value */ - const char *upper_output_format = "0123456789ABCDEF"; - const char *lower_output_format = "0123456789abcdef"; - const char *output_format = (*iter == 'x') ? - lower_output_format: upper_output_format; - - /* retrieve correct value type */ - if (arg_type == NK_ARG_TYPE_CHAR) - value = (unsigned char)va_arg(args, int); - else if (arg_type == NK_ARG_TYPE_SHORT) - value = (unsigned short)va_arg(args, int); - else if (arg_type == NK_ARG_TYPE_LONG) - value = va_arg(args, unsigned long); - else value = va_arg(args, unsigned int); - - do { - /* convert decimal number into hex/oct number */ - int digit = output_format[value % base]; - if (num_len < NK_MAX_NUMBER_BUFFER) - number_buffer[num_len++] = (char)digit; - value /= base; - } while (value > 0); - - num_print = NK_MAX(cur_precision, num_len); - padding = NK_MAX(cur_width - NK_MAX(cur_precision, num_len), 0); - if (flag & NK_ARG_FLAG_NUM) - padding = NK_MAX(padding-1, 0); - - /* fill left padding up to a total of `width` characters */ - if (!(flag & NK_ARG_FLAG_LEFT)) { - while ((padding-- > 0) && (len < buf_size)) { - if ((flag & NK_ARG_FLAG_ZERO) && (precision == NK_DEFAULT)) - buf[len++] = '0'; - else buf[len++] = ' '; - } - } - - /* fill up to precision number of digits */ - if (num_print && (flag & NK_ARG_FLAG_NUM)) { - if ((*iter == 'o') && (len < buf_size)) { - buf[len++] = '0'; - } else if ((*iter == 'x') && ((len+1) < buf_size)) { - buf[len++] = '0'; - buf[len++] = 'x'; - } else if ((*iter == 'X') && ((len+1) < buf_size)) { - buf[len++] = '0'; - buf[len++] = 'X'; - } - } - while (precision && (num_print > num_len) && (len < buf_size)) { - buf[len++] = '0'; - num_print--; - } - - /* reverse number direction */ - while (num_len > 0) { - if (precision && (len < buf_size)) - buf[len++] = number_buffer[num_len-1]; - num_len--; - } - - /* fill right padding up to width characters */ - if (flag & NK_ARG_FLAG_LEFT) { - while ((padding-- > 0) && (len < buf_size)) - buf[len++] = ' '; - } - } else if (*iter == 'f') { - /* floating point */ - const char *num_iter; - int cur_precision = (precision < 0) ? 6: precision; - int prefix, cur_width = NK_MAX(width, 0); - double value = va_arg(args, double); - int num_len = 0, frac_len = 0, dot = 0; - int padding = 0; - - NK_ASSERT(arg_type == NK_ARG_TYPE_DEFAULT); - NK_DTOA(number_buffer, value); - num_len = nk_strlen(number_buffer); - - /* calculate padding */ - num_iter = number_buffer; - while (*num_iter && *num_iter != '.') - num_iter++; - - prefix = (*num_iter == '.')?(int)(num_iter - number_buffer)+1:0; - padding = NK_MAX(cur_width - (prefix + NK_MIN(cur_precision, num_len - prefix)) , 0); - if ((flag & NK_ARG_FLAG_PLUS) || (flag & NK_ARG_FLAG_SPACE)) - padding = NK_MAX(padding-1, 0); - - /* fill left padding up to a total of `width` characters */ - if (!(flag & NK_ARG_FLAG_LEFT)) { - while (padding-- > 0 && (len < buf_size)) { - if (flag & NK_ARG_FLAG_ZERO) - buf[len++] = '0'; - else buf[len++] = ' '; - } - } - - /* copy string value representation into buffer */ - num_iter = number_buffer; - if ((flag & NK_ARG_FLAG_PLUS) && (value >= 0) && (len < buf_size)) - buf[len++] = '+'; - else if ((flag & NK_ARG_FLAG_SPACE) && (value >= 0) && (len < buf_size)) - buf[len++] = ' '; - while (*num_iter) { - if (dot) frac_len++; - if (len < buf_size) - buf[len++] = *num_iter; - if (*num_iter == '.') dot = 1; - if (frac_len >= cur_precision) break; - num_iter++; - } - - /* fill number up to precision */ - while (frac_len < cur_precision) { - if (!dot && len < buf_size) { - buf[len++] = '.'; - dot = 1; - } - if (len < buf_size) - buf[len++] = '0'; - frac_len++; - } - - /* fill right padding up to width characters */ - if (flag & NK_ARG_FLAG_LEFT) { - while ((padding-- > 0) && (len < buf_size)) - buf[len++] = ' '; - } - } else { - /* Specifier not supported: g,G,e,E,p,z */ - NK_ASSERT(0 && "specifier is not supported!"); - return result; - } - } - buf[(len >= buf_size)?(buf_size-1):len] = 0; - result = (len >= buf_size)?-1:len; - return result; -} - -NK_INTERN int -nk_strfmt(char *buf, int buf_size, const char *fmt, va_list args) -{ - int result = -1; - NK_ASSERT(buf); - NK_ASSERT(buf_size); - if (!buf || !buf_size || !fmt) return 0; -#ifdef NK_INCLUDE_STANDARD_IO - result = NK_VSNPRINTF(buf, (nk_size)buf_size, fmt, args); - result = (result >= buf_size) ? -1: result; - buf[buf_size-1] = 0; -#else - result = nk_vsnprintf(buf, buf_size, fmt, args); -#endif - return result; -} -#endif - -NK_API nk_hash -nk_murmur_hash(const void * key, int len, nk_hash seed) -{ - /* 32-Bit MurmurHash3: https://code.google.com/p/smhasher/wiki/MurmurHash3*/ - #define NK_ROTL(x,r) ((x) << (r) | ((x) >> (32 - r))) - union {const nk_uint *i; const nk_byte *b;} conv = {0}; - const nk_byte *data = (const nk_byte*)key; - const int nblocks = len/4; - nk_uint h1 = seed; - const nk_uint c1 = 0xcc9e2d51; - const nk_uint c2 = 0x1b873593; - const nk_byte *tail; - const nk_uint *blocks; - nk_uint k1; - int i; - - /* body */ - if (!key) return 0; - conv.b = (data + nblocks*4); - blocks = (const nk_uint*)conv.i; - for (i = -nblocks; i; ++i) { - k1 = blocks[i]; - k1 *= c1; - k1 = NK_ROTL(k1,15); - k1 *= c2; - - h1 ^= k1; - h1 = NK_ROTL(h1,13); - h1 = h1*5+0xe6546b64; - } - - /* tail */ - tail = (const nk_byte*)(data + nblocks*4); - k1 = 0; - switch (len & 3) { - case 3: k1 ^= (nk_uint)(tail[2] << 16); - case 2: k1 ^= (nk_uint)(tail[1] << 8u); - case 1: k1 ^= tail[0]; - k1 *= c1; - k1 = NK_ROTL(k1,15); - k1 *= c2; - h1 ^= k1; - default: break; - } - - /* finalization */ - h1 ^= (nk_uint)len; - /* fmix32 */ - h1 ^= h1 >> 16; - h1 *= 0x85ebca6b; - h1 ^= h1 >> 13; - h1 *= 0xc2b2ae35; - h1 ^= h1 >> 16; - - #undef NK_ROTL - return h1; -} - -#ifdef NK_INCLUDE_STANDARD_IO -NK_INTERN char* -nk_file_load(const char* path, nk_size* siz, struct nk_allocator *alloc) -{ - char *buf; - FILE *fd; - long ret; - - NK_ASSERT(path); - NK_ASSERT(siz); - NK_ASSERT(alloc); - if (!path || !siz || !alloc) - return 0; - - fd = fopen(path, "rb"); - if (!fd) return 0; - fseek(fd, 0, SEEK_END); - ret = ftell(fd); - if (ret < 0) { - fclose(fd); - return 0; - } - *siz = (nk_size)ret; - fseek(fd, 0, SEEK_SET); - buf = (char*)alloc->alloc(alloc->userdata,0, *siz); - NK_ASSERT(buf); - if (!buf) { - fclose(fd); - return 0; - } - *siz = (nk_size)fread(buf, *siz, 1, fd); - fclose(fd); - return buf; -} -#endif - -/* - * ============================================================== - * - * COLOR - * - * =============================================================== - */ -NK_INTERN int -nk_parse_hex(const char *p, int length) -{ - int i = 0; - int len = 0; - while (len < length) { - i <<= 4; - if (p[len] >= 'a' && p[len] <= 'f') - i += ((p[len] - 'a') + 10); - else if (p[len] >= 'A' && p[len] <= 'F') - i += ((p[len] - 'A') + 10); - else i += (p[len] - '0'); - len++; - } - return i; -} - -NK_API struct nk_color -nk_rgba(int r, int g, int b, int a) -{ - struct nk_color ret; - ret.r = (nk_byte)NK_CLAMP(0, r, 255); - ret.g = (nk_byte)NK_CLAMP(0, g, 255); - ret.b = (nk_byte)NK_CLAMP(0, b, 255); - ret.a = (nk_byte)NK_CLAMP(0, a, 255); - return ret; -} - -NK_API struct nk_color -nk_rgb_hex(const char *rgb) -{ - struct nk_color col; - const char *c = rgb; - if (*c == '#') c++; - col.r = (nk_byte)nk_parse_hex(c, 2); - col.g = (nk_byte)nk_parse_hex(c+2, 2); - col.b = (nk_byte)nk_parse_hex(c+4, 2); - col.a = 255; - return col; -} - -NK_API struct nk_color -nk_rgba_hex(const char *rgb) -{ - struct nk_color col; - const char *c = rgb; - if (*c == '#') c++; - col.r = (nk_byte)nk_parse_hex(c, 2); - col.g = (nk_byte)nk_parse_hex(c+2, 2); - col.b = (nk_byte)nk_parse_hex(c+4, 2); - col.a = (nk_byte)nk_parse_hex(c+6, 2); - return col; -} - -NK_API void -nk_color_hex_rgba(char *output, struct nk_color col) -{ - #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) - output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); - output[1] = (char)NK_TO_HEX((col.r & 0x0F)); - output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); - output[3] = (char)NK_TO_HEX((col.g & 0x0F)); - output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); - output[5] = (char)NK_TO_HEX((col.b & 0x0F)); - output[6] = (char)NK_TO_HEX((col.a & 0xF0) >> 4); - output[7] = (char)NK_TO_HEX((col.a & 0x0F)); - output[8] = '\0'; - #undef NK_TO_HEX -} - -NK_API void -nk_color_hex_rgb(char *output, struct nk_color col) -{ - #define NK_TO_HEX(i) ((i) <= 9 ? '0' + (i): 'A' - 10 + (i)) - output[0] = (char)NK_TO_HEX((col.r & 0xF0) >> 4); - output[1] = (char)NK_TO_HEX((col.r & 0x0F)); - output[2] = (char)NK_TO_HEX((col.g & 0xF0) >> 4); - output[3] = (char)NK_TO_HEX((col.g & 0x0F)); - output[4] = (char)NK_TO_HEX((col.b & 0xF0) >> 4); - output[5] = (char)NK_TO_HEX((col.b & 0x0F)); - output[6] = '\0'; - #undef NK_TO_HEX -} - -NK_API struct nk_color -nk_rgba_iv(const int *c) -{ - return nk_rgba(c[0], c[1], c[2], c[3]); -} - -NK_API struct nk_color -nk_rgba_bv(const nk_byte *c) -{ - return nk_rgba(c[0], c[1], c[2], c[3]); -} - -NK_API struct nk_color -nk_rgb(int r, int g, int b) -{ - struct nk_color ret; - ret.r = (nk_byte)NK_CLAMP(0, r, 255); - ret.g = (nk_byte)NK_CLAMP(0, g, 255); - ret.b = (nk_byte)NK_CLAMP(0, b, 255); - ret.a = (nk_byte)255; - return ret; -} - -NK_API struct nk_color -nk_rgb_iv(const int *c) -{ - return nk_rgb(c[0], c[1], c[2]); -} - -NK_API struct nk_color -nk_rgb_bv(const nk_byte* c) -{ - return nk_rgb(c[0], c[1], c[2]); -} - -NK_API struct nk_color -nk_rgba_u32(nk_uint in) -{ - struct nk_color ret; - ret.r = (in & 0xFF); - ret.g = ((in >> 8) & 0xFF); - ret.b = ((in >> 16) & 0xFF); - ret.a = (nk_byte)((in >> 24) & 0xFF); - return ret; -} - -NK_API struct nk_color -nk_rgba_f(float r, float g, float b, float a) -{ - struct nk_color ret; - ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); - ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); - ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); - ret.a = (nk_byte)(NK_SATURATE(a) * 255.0f); - return ret; -} - -NK_API struct nk_color -nk_rgba_fv(const float *c) -{ - return nk_rgba_f(c[0], c[1], c[2], c[3]); -} - -NK_API struct nk_color -nk_rgb_f(float r, float g, float b) -{ - struct nk_color ret; - ret.r = (nk_byte)(NK_SATURATE(r) * 255.0f); - ret.g = (nk_byte)(NK_SATURATE(g) * 255.0f); - ret.b = (nk_byte)(NK_SATURATE(b) * 255.0f); - ret.a = 255; - return ret; -} - -NK_API struct nk_color -nk_rgb_fv(const float *c) -{ - return nk_rgb_f(c[0], c[1], c[2]); -} - -NK_API struct nk_color -nk_hsv(int h, int s, int v) -{ - return nk_hsva(h, s, v, 255); -} - -NK_API struct nk_color -nk_hsv_iv(const int *c) -{ - return nk_hsv(c[0], c[1], c[2]); -} - -NK_API struct nk_color -nk_hsv_bv(const nk_byte *c) -{ - return nk_hsv(c[0], c[1], c[2]); -} - -NK_API struct nk_color -nk_hsv_f(float h, float s, float v) -{ - return nk_hsva_f(h, s, v, 1.0f); -} - -NK_API struct nk_color -nk_hsv_fv(const float *c) -{ - return nk_hsv_f(c[0], c[1], c[2]); -} - -NK_API struct nk_color -nk_hsva(int h, int s, int v, int a) -{ - float hf = ((float)NK_CLAMP(0, h, 255)) / 255.0f; - float sf = ((float)NK_CLAMP(0, s, 255)) / 255.0f; - float vf = ((float)NK_CLAMP(0, v, 255)) / 255.0f; - float af = ((float)NK_CLAMP(0, a, 255)) / 255.0f; - return nk_hsva_f(hf, sf, vf, af); -} - -NK_API struct nk_color -nk_hsva_iv(const int *c) -{ - return nk_hsva(c[0], c[1], c[2], c[3]); -} - -NK_API struct nk_color -nk_hsva_bv(const nk_byte *c) -{ - return nk_hsva(c[0], c[1], c[2], c[3]); -} - -NK_API struct nk_color -nk_hsva_f(float h, float s, float v, float a) -{ - struct nk_colorf out = {0,0,0,0}; - float p, q, t, f; - int i; - - if (s <= 0.0f) { - out.r = v; out.g = v; out.b = v; - return nk_rgb_f(out.r, out.g, out.b); - } - - h = h / (60.0f/360.0f); - i = (int)h; - f = h - (float)i; - p = v * (1.0f - s); - q = v * (1.0f - (s * f)); - t = v * (1.0f - s * (1.0f - f)); - - switch (i) { - case 0: default: out.r = v; out.g = t; out.b = p; break; - case 1: out.r = q; out.g = v; out.b = p; break; - case 2: out.r = p; out.g = v; out.b = t; break; - case 3: out.r = p; out.g = q; out.b = v; break; - case 4: out.r = t; out.g = p; out.b = v; break; - case 5: out.r = v; out.g = p; out.b = q; break; - } - return nk_rgba_f(out.r, out.g, out.b, a); -} - -NK_API struct nk_color -nk_hsva_fv(const float *c) -{ - return nk_hsva_f(c[0], c[1], c[2], c[3]); -} - -NK_API nk_uint -nk_color_u32(struct nk_color in) -{ - nk_uint out = (nk_uint)in.r; - out |= ((nk_uint)in.g << 8); - out |= ((nk_uint)in.b << 16); - out |= ((nk_uint)in.a << 24); - return out; -} - -NK_API void -nk_color_f(float *r, float *g, float *b, float *a, struct nk_color in) -{ - NK_STORAGE const float s = 1.0f/255.0f; - *r = (float)in.r * s; - *g = (float)in.g * s; - *b = (float)in.b * s; - *a = (float)in.a * s; -} - -NK_API void -nk_color_fv(float *c, struct nk_color in) -{ - nk_color_f(&c[0], &c[1], &c[2], &c[3], in); -} - -NK_API void -nk_color_d(double *r, double *g, double *b, double *a, struct nk_color in) -{ - NK_STORAGE const double s = 1.0/255.0; - *r = (double)in.r * s; - *g = (double)in.g * s; - *b = (double)in.b * s; - *a = (double)in.a * s; -} - -NK_API void -nk_color_dv(double *c, struct nk_color in) -{ - nk_color_d(&c[0], &c[1], &c[2], &c[3], in); -} - -NK_API void -nk_color_hsv_f(float *out_h, float *out_s, float *out_v, struct nk_color in) -{ - float a; - nk_color_hsva_f(out_h, out_s, out_v, &a, in); -} - -NK_API void -nk_color_hsv_fv(float *out, struct nk_color in) -{ - float a; - nk_color_hsva_f(&out[0], &out[1], &out[2], &a, in); -} - -NK_API void -nk_color_hsva_f(float *out_h, float *out_s, - float *out_v, float *out_a, struct nk_color in) -{ - float chroma; - float K = 0.0f; - float r,g,b,a; - - nk_color_f(&r,&g,&b,&a, in); - if (g < b) { - const float t = g; g = b; b = t; - K = -1.f; - } - if (r < g) { - const float t = r; r = g; g = t; - K = -2.f/6.0f - K; - } - chroma = r - ((g < b) ? g: b); - *out_h = NK_ABS(K + (g - b)/(6.0f * chroma + 1e-20f)); - *out_s = chroma / (r + 1e-20f); - *out_v = r; - *out_a = (float)in.a / 255.0f; -} - -NK_API void -nk_color_hsva_fv(float *out, struct nk_color in) -{ - nk_color_hsva_f(&out[0], &out[1], &out[2], &out[3], in); -} - -NK_API void -nk_color_hsva_i(int *out_h, int *out_s, int *out_v, - int *out_a, struct nk_color in) -{ - float h,s,v,a; - nk_color_hsva_f(&h, &s, &v, &a, in); - *out_h = (nk_byte)(h * 255.0f); - *out_s = (nk_byte)(s * 255.0f); - *out_v = (nk_byte)(v * 255.0f); - *out_a = (nk_byte)(a * 255.0f); -} - -NK_API void -nk_color_hsva_iv(int *out, struct nk_color in) -{ - nk_color_hsva_i(&out[0], &out[1], &out[2], &out[3], in); -} - -NK_API void -nk_color_hsva_bv(nk_byte *out, struct nk_color in) -{ - int tmp[4]; - nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); - out[0] = (nk_byte)tmp[0]; - out[1] = (nk_byte)tmp[1]; - out[2] = (nk_byte)tmp[2]; - out[3] = (nk_byte)tmp[3]; -} - -NK_API void -nk_color_hsva_b(nk_byte *h, nk_byte *s, nk_byte *v, nk_byte *a, struct nk_color in) -{ - int tmp[4]; - nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); - *h = (nk_byte)tmp[0]; - *s = (nk_byte)tmp[1]; - *v = (nk_byte)tmp[2]; - *a = (nk_byte)tmp[3]; -} - -NK_API void -nk_color_hsv_i(int *out_h, int *out_s, int *out_v, struct nk_color in) -{ - int a; - nk_color_hsva_i(out_h, out_s, out_v, &a, in); -} - -NK_API void -nk_color_hsv_b(nk_byte *out_h, nk_byte *out_s, nk_byte *out_v, struct nk_color in) -{ - int tmp[4]; - nk_color_hsva_i(&tmp[0], &tmp[1], &tmp[2], &tmp[3], in); - *out_h = (nk_byte)tmp[0]; - *out_s = (nk_byte)tmp[1]; - *out_v = (nk_byte)tmp[2]; -} - -NK_API void -nk_color_hsv_iv(int *out, struct nk_color in) -{ - nk_color_hsv_i(&out[0], &out[1], &out[2], in); -} - -NK_API void -nk_color_hsv_bv(nk_byte *out, struct nk_color in) -{ - int tmp[4]; - nk_color_hsv_i(&tmp[0], &tmp[1], &tmp[2], in); - out[0] = (nk_byte)tmp[0]; - out[1] = (nk_byte)tmp[1]; - out[2] = (nk_byte)tmp[2]; -} -/* - * ============================================================== - * - * IMAGE - * - * =============================================================== - */ -NK_API nk_handle -nk_handle_ptr(void *ptr) -{ - nk_handle handle = {0}; - handle.ptr = ptr; - return handle; -} - -NK_API nk_handle -nk_handle_id(int id) -{ - nk_handle handle; - nk_zero_struct(handle); - handle.id = id; - return handle; -} - -NK_API struct nk_image -nk_subimage_ptr(void *ptr, unsigned short w, unsigned short h, struct nk_rect r) -{ - struct nk_image s; - nk_zero(&s, sizeof(s)); - s.handle.ptr = ptr; - s.w = w; s.h = h; - s.region[0] = (unsigned short)r.x; - s.region[1] = (unsigned short)r.y; - s.region[2] = (unsigned short)r.w; - s.region[3] = (unsigned short)r.h; - return s; -} - -NK_API struct nk_image -nk_subimage_id(int id, unsigned short w, unsigned short h, struct nk_rect r) -{ - struct nk_image s; - nk_zero(&s, sizeof(s)); - s.handle.id = id; - s.w = w; s.h = h; - s.region[0] = (unsigned short)r.x; - s.region[1] = (unsigned short)r.y; - s.region[2] = (unsigned short)r.w; - s.region[3] = (unsigned short)r.h; - return s; -} - -NK_API struct nk_image -nk_subimage_handle(nk_handle handle, unsigned short w, unsigned short h, - struct nk_rect r) -{ - struct nk_image s; - nk_zero(&s, sizeof(s)); - s.handle = handle; - s.w = w; s.h = h; - s.region[0] = (unsigned short)r.x; - s.region[1] = (unsigned short)r.y; - s.region[2] = (unsigned short)r.w; - s.region[3] = (unsigned short)r.h; - return s; -} - -NK_API struct nk_image -nk_image_handle(nk_handle handle) -{ - struct nk_image s; - nk_zero(&s, sizeof(s)); - s.handle = handle; - s.w = 0; s.h = 0; - s.region[0] = 0; - s.region[1] = 0; - s.region[2] = 0; - s.region[3] = 0; - return s; -} - -NK_API struct nk_image -nk_image_ptr(void *ptr) -{ - struct nk_image s; - nk_zero(&s, sizeof(s)); - NK_ASSERT(ptr); - s.handle.ptr = ptr; - s.w = 0; s.h = 0; - s.region[0] = 0; - s.region[1] = 0; - s.region[2] = 0; - s.region[3] = 0; - return s; -} - -NK_API struct nk_image -nk_image_id(int id) -{ - struct nk_image s; - nk_zero(&s, sizeof(s)); - s.handle.id = id; - s.w = 0; s.h = 0; - s.region[0] = 0; - s.region[1] = 0; - s.region[2] = 0; - s.region[3] = 0; - return s; -} - -NK_API int -nk_image_is_subimage(const struct nk_image* img) -{ - NK_ASSERT(img); - return !(img->w == 0 && img->h == 0); -} - -NK_INTERN void -nk_unify(struct nk_rect *clip, const struct nk_rect *a, float x0, float y0, - float x1, float y1) -{ - NK_ASSERT(a); - NK_ASSERT(clip); - clip->x = NK_MAX(a->x, x0); - clip->y = NK_MAX(a->y, y0); - clip->w = NK_MIN(a->x + a->w, x1) - clip->x; - clip->h = NK_MIN(a->y + a->h, y1) - clip->y; - clip->w = NK_MAX(0, clip->w); - clip->h = NK_MAX(0, clip->h); -} - -NK_API void -nk_triangle_from_direction(struct nk_vec2 *result, struct nk_rect r, - float pad_x, float pad_y, enum nk_heading direction) -{ - float w_half, h_half; - NK_ASSERT(result); - - r.w = NK_MAX(2 * pad_x, r.w); - r.h = NK_MAX(2 * pad_y, r.h); - r.w = r.w - 2 * pad_x; - r.h = r.h - 2 * pad_y; - - r.x = r.x + pad_x; - r.y = r.y + pad_y; - - w_half = r.w / 2.0f; - h_half = r.h / 2.0f; - - if (direction == NK_UP) { - result[0] = nk_vec2(r.x + w_half, r.y); - result[1] = nk_vec2(r.x + r.w, r.y + r.h); - result[2] = nk_vec2(r.x, r.y + r.h); - } else if (direction == NK_RIGHT) { - result[0] = nk_vec2(r.x, r.y); - result[1] = nk_vec2(r.x + r.w, r.y + h_half); - result[2] = nk_vec2(r.x, r.y + r.h); - } else if (direction == NK_DOWN) { - result[0] = nk_vec2(r.x, r.y); - result[1] = nk_vec2(r.x + r.w, r.y); - result[2] = nk_vec2(r.x + w_half, r.y + r.h); - } else { - result[0] = nk_vec2(r.x, r.y + h_half); - result[1] = nk_vec2(r.x + r.w, r.y); - result[2] = nk_vec2(r.x + r.w, r.y + r.h); - } -} - -NK_INTERN 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) -{ - int i = 0; - int glyph_len = 0; - float last_width = 0; - nk_rune unicode = 0; - float width = 0; - int len = 0; - int g = 0; - float s; - - int sep_len = 0; - int sep_g = 0; - float sep_width = 0; - sep_count = NK_MAX(sep_count,0); - - glyph_len = nk_utf_decode(text, &unicode, text_len); - while (glyph_len && (width < space) && (len < text_len)) { - len += glyph_len; - s = font->width(font->userdata, font->height, text, len); - for (i = 0; i < sep_count; ++i) { - if (unicode != sep_list[i]) continue; - sep_width = last_width = width; - sep_g = g+1; - sep_len = len; - break; - } - if (i == NK_MAX(sep_count,0)){ - last_width = sep_width = width; - sep_g = g+1; - } - width = s; - glyph_len = nk_utf_decode(&text[len], &unicode, text_len - len); - g++; - } - if (len >= text_len) { - *glyphs = g; - *text_width = last_width; - return len; - } else { - *glyphs = sep_g; - *text_width = sep_width; - return (!sep_len) ? len: sep_len; - } -} - -enum {NK_DO_NOT_STOP_ON_NEW_LINE, NK_STOP_ON_NEW_LINE}; -NK_INTERN 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) -{ - float line_height = row_height; - struct nk_vec2 text_size = nk_vec2(0,0); - float line_width = 0.0f; - - float glyph_width; - int glyph_len = 0; - nk_rune unicode = 0; - int text_len = 0; - if (!begin || byte_len <= 0 || !font) - return nk_vec2(0,row_height); - - glyph_len = nk_utf_decode(begin, &unicode, byte_len); - if (!glyph_len) return text_size; - glyph_width = font->width(font->userdata, font->height, begin, glyph_len); - - *glyphs = 0; - while ((text_len < byte_len) && glyph_len) { - if (unicode == '\n') { - text_size.x = NK_MAX(text_size.x, line_width); - text_size.y += line_height; - line_width = 0; - *glyphs+=1; - if (op == NK_STOP_ON_NEW_LINE) - break; - - text_len++; - glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); - continue; - } - - if (unicode == '\r') { - text_len++; - *glyphs+=1; - glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); - continue; - } - - *glyphs = *glyphs + 1; - text_len += glyph_len; - line_width += (float)glyph_width; - glyph_len = nk_utf_decode(begin + text_len, &unicode, byte_len-text_len); - glyph_width = font->width(font->userdata, font->height, begin+text_len, glyph_len); - continue; - } - - if (text_size.x < line_width) - text_size.x = line_width; - if (out_offset) - *out_offset = nk_vec2(line_width, text_size.y + line_height); - if (line_width > 0 || text_size.y == 0.0f) - text_size.y += line_height; - if (remaining) - *remaining = begin+text_len; - return text_size; -} - -/* ============================================================== - * - * UTF-8 - * - * ===============================================================*/ -NK_GLOBAL const nk_byte nk_utfbyte[NK_UTF_SIZE+1] = {0x80, 0, 0xC0, 0xE0, 0xF0}; -NK_GLOBAL const nk_byte nk_utfmask[NK_UTF_SIZE+1] = {0xC0, 0x80, 0xE0, 0xF0, 0xF8}; -NK_GLOBAL const nk_uint nk_utfmin[NK_UTF_SIZE+1] = {0, 0, 0x80, 0x800, 0x10000}; -NK_GLOBAL const nk_uint nk_utfmax[NK_UTF_SIZE+1] = {0x10FFFF, 0x7F, 0x7FF, 0xFFFF, 0x10FFFF}; - -NK_INTERN int -nk_utf_validate(nk_rune *u, int i) -{ - NK_ASSERT(u); - if (!u) return 0; - if (!NK_BETWEEN(*u, nk_utfmin[i], nk_utfmax[i]) || - NK_BETWEEN(*u, 0xD800, 0xDFFF)) - *u = NK_UTF_INVALID; - for (i = 1; *u > nk_utfmax[i]; ++i); - return i; -} - -NK_INTERN nk_rune -nk_utf_decode_byte(char c, int *i) -{ - NK_ASSERT(i); - if (!i) return 0; - for(*i = 0; *i < (int)NK_LEN(nk_utfmask); ++(*i)) { - if (((nk_byte)c & nk_utfmask[*i]) == nk_utfbyte[*i]) - return (nk_byte)(c & ~nk_utfmask[*i]); - } - return 0; -} - -NK_API int -nk_utf_decode(const char *c, nk_rune *u, int clen) -{ - int i, j, len, type=0; - nk_rune udecoded; - - NK_ASSERT(c); - NK_ASSERT(u); - - if (!c || !u) return 0; - if (!clen) return 0; - *u = NK_UTF_INVALID; - - udecoded = nk_utf_decode_byte(c[0], &len); - if (!NK_BETWEEN(len, 1, NK_UTF_SIZE)) - return 1; - - for (i = 1, j = 1; i < clen && j < len; ++i, ++j) { - udecoded = (udecoded << 6) | nk_utf_decode_byte(c[i], &type); - if (type != 0) - return j; - } - if (j < len) - return 0; - *u = udecoded; - nk_utf_validate(u, len); - return len; -} - -NK_INTERN char -nk_utf_encode_byte(nk_rune u, int i) -{ - return (char)((nk_utfbyte[i]) | ((nk_byte)u & ~nk_utfmask[i])); -} - -NK_API int -nk_utf_encode(nk_rune u, char *c, int clen) -{ - int len, i; - len = nk_utf_validate(&u, 0); - if (clen < len || !len || len > NK_UTF_SIZE) - return 0; - - for (i = len - 1; i != 0; --i) { - c[i] = nk_utf_encode_byte(u, 0); - u >>= 6; - } - c[0] = nk_utf_encode_byte(u, len); - return len; -} - -NK_API int -nk_utf_len(const char *str, int len) -{ - const char *text; - int glyphs = 0; - int text_len; - int glyph_len; - int src_len = 0; - nk_rune unicode; - - NK_ASSERT(str); - if (!str || !len) return 0; - - text = str; - text_len = len; - glyph_len = nk_utf_decode(text, &unicode, text_len); - while (glyph_len && src_len < len) { - glyphs++; - src_len = src_len + glyph_len; - glyph_len = nk_utf_decode(text + src_len, &unicode, text_len - src_len); - } - return glyphs; -} - -NK_API const char* -nk_utf_at(const char *buffer, int length, int index, - nk_rune *unicode, int *len) -{ - int i = 0; - int src_len = 0; - int glyph_len = 0; - const char *text; - int text_len; - - NK_ASSERT(buffer); - NK_ASSERT(unicode); - NK_ASSERT(len); - - if (!buffer || !unicode || !len) return 0; - if (index < 0) { - *unicode = NK_UTF_INVALID; - *len = 0; - return 0; - } - - text = buffer; - text_len = length; - glyph_len = nk_utf_decode(text, unicode, text_len); - while (glyph_len) { - if (i == index) { - *len = glyph_len; - break; - } - - i++; - src_len = src_len + glyph_len; - glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); - } - if (i != index) return 0; - return buffer + src_len; -} - -/* ============================================================== - * - * BUFFER - * - * ===============================================================*/ -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -NK_INTERN void* nk_malloc(nk_handle unused, void *old,nk_size size) -{NK_UNUSED(unused); NK_UNUSED(old); return malloc(size);} -NK_INTERN void nk_mfree(nk_handle unused, void *ptr) -{NK_UNUSED(unused); free(ptr);} - -NK_API void -nk_buffer_init_default(struct nk_buffer *buffer) -{ - struct nk_allocator alloc; - alloc.userdata.ptr = 0; - alloc.alloc = nk_malloc; - alloc.free = nk_mfree; - nk_buffer_init(buffer, &alloc, NK_BUFFER_DEFAULT_INITIAL_SIZE); -} -#endif - -NK_API void -nk_buffer_init(struct nk_buffer *b, const struct nk_allocator *a, - nk_size initial_size) -{ - NK_ASSERT(b); - NK_ASSERT(a); - NK_ASSERT(initial_size); - if (!b || !a || !initial_size) return; - - nk_zero(b, sizeof(*b)); - b->type = NK_BUFFER_DYNAMIC; - b->memory.ptr = a->alloc(a->userdata,0, initial_size); - b->memory.size = initial_size; - b->size = initial_size; - b->grow_factor = 2.0f; - b->pool = *a; -} - -NK_API void -nk_buffer_init_fixed(struct nk_buffer *b, void *m, nk_size size) -{ - NK_ASSERT(b); - NK_ASSERT(m); - NK_ASSERT(size); - if (!b || !m || !size) return; - - nk_zero(b, sizeof(*b)); - b->type = NK_BUFFER_FIXED; - b->memory.ptr = m; - b->memory.size = size; - b->size = size; -} - -NK_INTERN void* -nk_buffer_align(void *unaligned, nk_size align, nk_size *alignment, - enum nk_buffer_allocation_type type) -{ - void *memory = 0; - switch (type) { - default: - case NK_BUFFER_MAX: - case NK_BUFFER_FRONT: - if (align) { - memory = NK_ALIGN_PTR(unaligned, align); - *alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); - } else { - memory = unaligned; - *alignment = 0; - } - break; - case NK_BUFFER_BACK: - if (align) { - memory = NK_ALIGN_PTR_BACK(unaligned, align); - *alignment = (nk_size)((nk_byte*)unaligned - (nk_byte*)memory); - } else { - memory = unaligned; - *alignment = 0; - } - break; - } - return memory; -} - -NK_INTERN void* -nk_buffer_realloc(struct nk_buffer *b, nk_size capacity, nk_size *size) -{ - void *temp; - nk_size buffer_size; - - NK_ASSERT(b); - NK_ASSERT(size); - if (!b || !size || !b->pool.alloc || !b->pool.free) - return 0; - - buffer_size = b->memory.size; - temp = b->pool.alloc(b->pool.userdata, b->memory.ptr, capacity); - NK_ASSERT(temp); - if (!temp) return 0; - - *size = capacity; - if (temp != b->memory.ptr) { - NK_MEMCPY(temp, b->memory.ptr, buffer_size); - b->pool.free(b->pool.userdata, b->memory.ptr); - } - - if (b->size == buffer_size) { - /* no back buffer so just set correct size */ - b->size = capacity; - return temp; - } else { - /* copy back buffer to the end of the new buffer */ - void *dst, *src; - nk_size back_size; - back_size = buffer_size - b->size; - dst = nk_ptr_add(void, temp, capacity - back_size); - src = nk_ptr_add(void, temp, b->size); - NK_MEMCPY(dst, src, back_size); - b->size = capacity - back_size; - } - return temp; -} - -NK_INTERN void* -nk_buffer_alloc(struct nk_buffer *b, enum nk_buffer_allocation_type type, - nk_size size, nk_size align) -{ - int full; - nk_size alignment; - void *unaligned; - void *memory; - - NK_ASSERT(b); - NK_ASSERT(size); - if (!b || !size) return 0; - b->needed += size; - - /* calculate total size with needed alignment + size */ - if (type == NK_BUFFER_FRONT) - unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); - else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); - memory = nk_buffer_align(unaligned, align, &alignment, type); - - /* check if buffer has enough memory*/ - if (type == NK_BUFFER_FRONT) - full = ((b->allocated + size + alignment) > b->size); - else full = ((b->size - (size + alignment)) <= b->allocated); - - if (full) { - nk_size capacity; - NK_ASSERT(b->type == NK_BUFFER_DYNAMIC); - NK_ASSERT(b->pool.alloc && b->pool.free); - if (b->type != NK_BUFFER_DYNAMIC || !b->pool.alloc || !b->pool.free) - return 0; - - /* buffer is full so allocate bigger buffer if dynamic */ - capacity = (nk_size)((float)b->memory.size * b->grow_factor); - capacity = NK_MAX(capacity, nk_round_up_pow2((nk_uint)(b->allocated + size))); - b->memory.ptr = nk_buffer_realloc(b, capacity, &b->memory.size); - if (!b->memory.ptr) return 0; - - /* align newly allocated pointer */ - if (type == NK_BUFFER_FRONT) - unaligned = nk_ptr_add(void, b->memory.ptr, b->allocated); - else unaligned = nk_ptr_add(void, b->memory.ptr, b->size - size); - memory = nk_buffer_align(unaligned, align, &alignment, type); - } - - if (type == NK_BUFFER_FRONT) - b->allocated += size + alignment; - else b->size -= (size + alignment); - b->needed += alignment; - b->calls++; - return memory; -} - -NK_API void -nk_buffer_push(struct nk_buffer *b, enum nk_buffer_allocation_type type, - const void *memory, nk_size size, nk_size align) -{ - void *mem = nk_buffer_alloc(b, type, size, align); - if (!mem) return; - NK_MEMCPY(mem, memory, size); -} - -NK_API void -nk_buffer_mark(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) -{ - NK_ASSERT(buffer); - if (!buffer) return; - buffer->marker[type].active = nk_true; - if (type == NK_BUFFER_BACK) - buffer->marker[type].offset = buffer->size; - else buffer->marker[type].offset = buffer->allocated; -} - -NK_API void -nk_buffer_reset(struct nk_buffer *buffer, enum nk_buffer_allocation_type type) -{ - NK_ASSERT(buffer); - if (!buffer) return; - if (type == NK_BUFFER_BACK) { - /* reset back buffer either back to marker or empty */ - buffer->needed -= (buffer->memory.size - buffer->marker[type].offset); - if (buffer->marker[type].active) - buffer->size = buffer->marker[type].offset; - else buffer->size = buffer->memory.size; - buffer->marker[type].active = nk_false; - } else { - /* reset front buffer either back to back marker or empty */ - buffer->needed -= (buffer->allocated - buffer->marker[type].offset); - if (buffer->marker[type].active) - buffer->allocated = buffer->marker[type].offset; - else buffer->allocated = 0; - buffer->marker[type].active = nk_false; - } -} - -NK_API void -nk_buffer_clear(struct nk_buffer *b) -{ - NK_ASSERT(b); - if (!b) return; - b->allocated = 0; - b->size = b->memory.size; - b->calls = 0; - b->needed = 0; -} - -NK_API void -nk_buffer_free(struct nk_buffer *b) -{ - NK_ASSERT(b); - if (!b || !b->memory.ptr) return; - if (b->type == NK_BUFFER_FIXED) return; - if (!b->pool.free) return; - NK_ASSERT(b->pool.free); - b->pool.free(b->pool.userdata, b->memory.ptr); -} - -NK_API void -nk_buffer_info(struct nk_memory_status *s, struct nk_buffer *b) -{ - NK_ASSERT(b); - NK_ASSERT(s); - if (!s || !b) return; - s->allocated = b->allocated; - s->size = b->memory.size; - s->needed = b->needed; - s->memory = b->memory.ptr; - s->calls = b->calls; -} - -NK_API void* -nk_buffer_memory(struct nk_buffer *buffer) -{ - NK_ASSERT(buffer); - if (!buffer) return 0; - return buffer->memory.ptr; -} - -NK_API const void* -nk_buffer_memory_const(const struct nk_buffer *buffer) -{ - NK_ASSERT(buffer); - if (!buffer) return 0; - return buffer->memory.ptr; -} - -NK_API nk_size -nk_buffer_total(struct nk_buffer *buffer) -{ - NK_ASSERT(buffer); - if (!buffer) return 0; - return buffer->memory.size; -} - -/* - * ============================================================== - * - * STRING - * - * =============================================================== - */ -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -NK_API void -nk_str_init_default(struct nk_str *str) -{ - struct nk_allocator alloc; - alloc.userdata.ptr = 0; - alloc.alloc = nk_malloc; - alloc.free = nk_mfree; - nk_buffer_init(&str->buffer, &alloc, 32); - str->len = 0; -} -#endif - -NK_API void -nk_str_init(struct nk_str *str, const struct nk_allocator *alloc, nk_size size) -{ - nk_buffer_init(&str->buffer, alloc, size); - str->len = 0; -} - -NK_API void -nk_str_init_fixed(struct nk_str *str, void *memory, nk_size size) -{ - nk_buffer_init_fixed(&str->buffer, memory, size); - str->len = 0; -} - -NK_API int -nk_str_append_text_char(struct nk_str *s, const char *str, int len) -{ - char *mem; - NK_ASSERT(s); - NK_ASSERT(str); - if (!s || !str || !len) return 0; - mem = (char*)nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); - if (!mem) return 0; - NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); - s->len += nk_utf_len(str, len); - return len; -} - -NK_API int -nk_str_append_str_char(struct nk_str *s, const char *str) -{ - return nk_str_append_text_char(s, str, nk_strlen(str)); -} - -NK_API int -nk_str_append_text_utf8(struct nk_str *str, const char *text, int len) -{ - int i = 0; - int byte_len = 0; - nk_rune unicode; - if (!str || !text || !len) return 0; - for (i = 0; i < len; ++i) - byte_len += nk_utf_decode(text+byte_len, &unicode, 4); - nk_str_append_text_char(str, text, byte_len); - return len; -} - -NK_API int -nk_str_append_str_utf8(struct nk_str *str, const char *text) -{ - int runes = 0; - int byte_len = 0; - int num_runes = 0; - int glyph_len = 0; - nk_rune unicode; - if (!str || !text) return 0; - - glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); - while (unicode != '\0' && glyph_len) { - glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); - byte_len += glyph_len; - num_runes++; - } - nk_str_append_text_char(str, text, byte_len); - return runes; -} - -NK_API int -nk_str_append_text_runes(struct nk_str *str, const nk_rune *text, int len) -{ - int i = 0; - int byte_len = 0; - nk_glyph glyph; - - NK_ASSERT(str); - if (!str || !text || !len) return 0; - for (i = 0; i < len; ++i) { - byte_len = nk_utf_encode(text[i], glyph, NK_UTF_SIZE); - if (!byte_len) break; - nk_str_append_text_char(str, glyph, byte_len); - } - return len; -} - -NK_API int -nk_str_append_str_runes(struct nk_str *str, const nk_rune *runes) -{ - int i = 0; - nk_glyph glyph; - int byte_len; - NK_ASSERT(str); - if (!str || !runes) return 0; - while (runes[i] != '\0') { - byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); - nk_str_append_text_char(str, glyph, byte_len); - i++; - } - return i; -} - -NK_API int -nk_str_insert_at_char(struct nk_str *s, int pos, const char *str, int len) -{ - int i; - void *mem; - char *src; - char *dst; - - int copylen; - NK_ASSERT(s); - NK_ASSERT(str); - NK_ASSERT(len >= 0); - if (!s || !str || !len || (nk_size)pos > s->buffer.allocated) return 0; - if ((s->buffer.allocated + (nk_size)len >= s->buffer.memory.size) && - (s->buffer.type == NK_BUFFER_FIXED)) return 0; - - copylen = (int)s->buffer.allocated - pos; - if (!copylen) { - nk_str_append_text_char(s, str, len); - return 1; - } - mem = nk_buffer_alloc(&s->buffer, NK_BUFFER_FRONT, (nk_size)len * sizeof(char), 0); - if (!mem) return 0; - - /* memmove */ - NK_ASSERT(((int)pos + (int)len + ((int)copylen - 1)) >= 0); - NK_ASSERT(((int)pos + ((int)copylen - 1)) >= 0); - dst = nk_ptr_add(char, s->buffer.memory.ptr, pos + len + (copylen - 1)); - src = nk_ptr_add(char, s->buffer.memory.ptr, pos + (copylen-1)); - for (i = 0; i < copylen; ++i) *dst-- = *src--; - mem = nk_ptr_add(void, s->buffer.memory.ptr, pos); - NK_MEMCPY(mem, str, (nk_size)len * sizeof(char)); - s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); - return 1; -} - -NK_API int -nk_str_insert_at_rune(struct nk_str *str, int pos, const char *cstr, int len) -{ - int glyph_len; - nk_rune unicode; - const char *begin; - const char *buffer; - - NK_ASSERT(str); - NK_ASSERT(cstr); - NK_ASSERT(len); - if (!str || !cstr || !len) return 0; - begin = nk_str_at_rune(str, pos, &unicode, &glyph_len); - if (!str->len) - return nk_str_append_text_char(str, cstr, len); - buffer = nk_str_get_const(str); - if (!begin) return 0; - return nk_str_insert_at_char(str, (int)(begin - buffer), cstr, len); -} - -NK_API int -nk_str_insert_text_char(struct nk_str *str, int pos, const char *text, int len) -{ - return nk_str_insert_text_utf8(str, pos, text, len); -} - -NK_API int -nk_str_insert_str_char(struct nk_str *str, int pos, const char *text) -{ - return nk_str_insert_text_utf8(str, pos, text, nk_strlen(text)); -} - -NK_API int -nk_str_insert_text_utf8(struct nk_str *str, int pos, const char *text, int len) -{ - int i = 0; - int byte_len = 0; - nk_rune unicode; - - NK_ASSERT(str); - NK_ASSERT(text); - if (!str || !text || !len) return 0; - for (i = 0; i < len; ++i) - byte_len += nk_utf_decode(text+byte_len, &unicode, 4); - nk_str_insert_at_rune(str, pos, text, byte_len); - return len; -} - -NK_API int -nk_str_insert_str_utf8(struct nk_str *str, int pos, const char *text) -{ - int runes = 0; - int byte_len = 0; - int num_runes = 0; - int glyph_len = 0; - nk_rune unicode; - if (!str || !text) return 0; - - glyph_len = byte_len = nk_utf_decode(text+byte_len, &unicode, 4); - while (unicode != '\0' && glyph_len) { - glyph_len = nk_utf_decode(text+byte_len, &unicode, 4); - byte_len += glyph_len; - num_runes++; - } - nk_str_insert_at_rune(str, pos, text, byte_len); - return runes; -} - -NK_API int -nk_str_insert_text_runes(struct nk_str *str, int pos, const nk_rune *runes, int len) -{ - int i = 0; - int byte_len = 0; - nk_glyph glyph; - - NK_ASSERT(str); - if (!str || !runes || !len) return 0; - for (i = 0; i < len; ++i) { - byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); - if (!byte_len) break; - nk_str_insert_at_rune(str, pos+i, glyph, byte_len); - } - return len; -} - -NK_API int -nk_str_insert_str_runes(struct nk_str *str, int pos, const nk_rune *runes) -{ - int i = 0; - nk_glyph glyph; - int byte_len; - NK_ASSERT(str); - if (!str || !runes) return 0; - while (runes[i] != '\0') { - byte_len = nk_utf_encode(runes[i], glyph, NK_UTF_SIZE); - nk_str_insert_at_rune(str, pos+i, glyph, byte_len); - i++; - } - return i; -} - -NK_API void -nk_str_remove_chars(struct nk_str *s, int len) -{ - NK_ASSERT(s); - NK_ASSERT(len >= 0); - if (!s || len < 0 || (nk_size)len > s->buffer.allocated) return; - NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); - s->buffer.allocated -= (nk_size)len; - s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); -} - -NK_API void -nk_str_remove_runes(struct nk_str *str, int len) -{ - int index; - const char *begin; - const char *end; - nk_rune unicode; - - NK_ASSERT(str); - NK_ASSERT(len >= 0); - if (!str || len < 0) return; - if (len >= str->len) { - str->len = 0; - return; - } - - index = str->len - len; - begin = nk_str_at_rune(str, index, &unicode, &len); - end = (const char*)str->buffer.memory.ptr + str->buffer.allocated; - nk_str_remove_chars(str, (int)(end-begin)+1); -} - -NK_API void -nk_str_delete_chars(struct nk_str *s, int pos, int len) -{ - NK_ASSERT(s); - if (!s || !len || (nk_size)pos > s->buffer.allocated || - (nk_size)(pos + len) > s->buffer.allocated) return; - - if ((nk_size)(pos + len) < s->buffer.allocated) { - /* memmove */ - char *dst = nk_ptr_add(char, s->buffer.memory.ptr, pos); - char *src = nk_ptr_add(char, s->buffer.memory.ptr, pos + len); - NK_MEMCPY(dst, src, s->buffer.allocated - (nk_size)(pos + len)); - NK_ASSERT(((int)s->buffer.allocated - (int)len) >= 0); - s->buffer.allocated -= (nk_size)len; - } else nk_str_remove_chars(s, len); - s->len = nk_utf_len((char *)s->buffer.memory.ptr, (int)s->buffer.allocated); -} - -NK_API void -nk_str_delete_runes(struct nk_str *s, int pos, int len) -{ - char *temp; - nk_rune unicode; - char *begin; - char *end; - int unused; - - NK_ASSERT(s); - NK_ASSERT(s->len >= pos + len); - if (s->len < pos + len) - len = NK_CLAMP(0, (s->len - pos), s->len); - if (!len) return; - - temp = (char *)s->buffer.memory.ptr; - begin = nk_str_at_rune(s, pos, &unicode, &unused); - if (!begin) return; - s->buffer.memory.ptr = begin; - end = nk_str_at_rune(s, len, &unicode, &unused); - s->buffer.memory.ptr = temp; - if (!end) return; - nk_str_delete_chars(s, (int)(begin - temp), (int)(end - begin)); -} - -NK_API char* -nk_str_at_char(struct nk_str *s, int pos) -{ - NK_ASSERT(s); - if (!s || pos > (int)s->buffer.allocated) return 0; - return nk_ptr_add(char, s->buffer.memory.ptr, pos); -} - -NK_API char* -nk_str_at_rune(struct nk_str *str, int pos, nk_rune *unicode, int *len) -{ - int i = 0; - int src_len = 0; - int glyph_len = 0; - char *text; - int text_len; - - NK_ASSERT(str); - NK_ASSERT(unicode); - NK_ASSERT(len); - - if (!str || !unicode || !len) return 0; - if (pos < 0) { - *unicode = 0; - *len = 0; - return 0; - } - - text = (char*)str->buffer.memory.ptr; - text_len = (int)str->buffer.allocated; - glyph_len = nk_utf_decode(text, unicode, text_len); - while (glyph_len) { - if (i == pos) { - *len = glyph_len; - break; - } - - i++; - src_len = src_len + glyph_len; - glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); - } - if (i != pos) return 0; - return text + src_len; -} - -NK_API const char* -nk_str_at_char_const(const struct nk_str *s, int pos) -{ - NK_ASSERT(s); - if (!s || pos > (int)s->buffer.allocated) return 0; - return nk_ptr_add(char, s->buffer.memory.ptr, pos); -} - -NK_API const char* -nk_str_at_const(const struct nk_str *str, int pos, nk_rune *unicode, int *len) -{ - int i = 0; - int src_len = 0; - int glyph_len = 0; - char *text; - int text_len; - - NK_ASSERT(str); - NK_ASSERT(unicode); - NK_ASSERT(len); - - if (!str || !unicode || !len) return 0; - if (pos < 0) { - *unicode = 0; - *len = 0; - return 0; - } - - text = (char*)str->buffer.memory.ptr; - text_len = (int)str->buffer.allocated; - glyph_len = nk_utf_decode(text, unicode, text_len); - while (glyph_len) { - if (i == pos) { - *len = glyph_len; - break; - } - - i++; - src_len = src_len + glyph_len; - glyph_len = nk_utf_decode(text + src_len, unicode, text_len - src_len); - } - if (i != pos) return 0; - return text + src_len; -} - -NK_API nk_rune -nk_str_rune_at(const struct nk_str *str, int pos) -{ - int len; - nk_rune unicode = 0; - nk_str_at_const(str, pos, &unicode, &len); - return unicode; -} - -NK_API char* -nk_str_get(struct nk_str *s) -{ - NK_ASSERT(s); - if (!s || !s->len || !s->buffer.allocated) return 0; - return (char*)s->buffer.memory.ptr; -} - -NK_API const char* -nk_str_get_const(const struct nk_str *s) -{ - NK_ASSERT(s); - if (!s || !s->len || !s->buffer.allocated) return 0; - return (const char*)s->buffer.memory.ptr; -} - -NK_API int -nk_str_len(struct nk_str *s) -{ - NK_ASSERT(s); - if (!s || !s->len || !s->buffer.allocated) return 0; - return s->len; -} - -NK_API int -nk_str_len_char(struct nk_str *s) -{ - NK_ASSERT(s); - if (!s || !s->len || !s->buffer.allocated) return 0; - return (int)s->buffer.allocated; -} - -NK_API void -nk_str_clear(struct nk_str *str) -{ - NK_ASSERT(str); - nk_buffer_clear(&str->buffer); - str->len = 0; -} - -NK_API void -nk_str_free(struct nk_str *str) -{ - NK_ASSERT(str); - nk_buffer_free(&str->buffer); - str->len = 0; -} - -/* - * ============================================================== - * - * Command buffer - * - * =============================================================== -*/ -NK_INTERN void -nk_command_buffer_init(struct nk_command_buffer *cmdbuf, - struct nk_buffer *buffer, enum nk_command_clipping clip) -{ - NK_ASSERT(cmdbuf); - NK_ASSERT(buffer); - if (!cmdbuf || !buffer) return; - cmdbuf->base = buffer; - cmdbuf->use_clipping = clip; - cmdbuf->begin = buffer->allocated; - cmdbuf->end = buffer->allocated; - cmdbuf->last = buffer->allocated; -} - -NK_INTERN void -nk_command_buffer_reset(struct nk_command_buffer *buffer) -{ - NK_ASSERT(buffer); - if (!buffer) return; - buffer->begin = 0; - buffer->end = 0; - buffer->last = 0; - buffer->clip = nk_null_rect; -#ifdef NK_INCLUDE_COMMAND_USERDATA - buffer->userdata.ptr = 0; -#endif -} - -NK_INTERN void* -nk_command_buffer_push(struct nk_command_buffer* b, - enum nk_command_type t, nk_size size) -{ - NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_command); - struct nk_command *cmd; - nk_size alignment; - void *unaligned; - void *memory; - - NK_ASSERT(b); - NK_ASSERT(b->base); - if (!b) return 0; - cmd = (struct nk_command*)nk_buffer_alloc(b->base,NK_BUFFER_FRONT,size,align); - if (!cmd) return 0; - - /* make sure the offset to the next command is aligned */ - b->last = (nk_size)((nk_byte*)cmd - (nk_byte*)b->base->memory.ptr); - unaligned = (nk_byte*)cmd + size; - memory = NK_ALIGN_PTR(unaligned, align); - alignment = (nk_size)((nk_byte*)memory - (nk_byte*)unaligned); -#ifdef NK_ZERO_COMMAND_MEMORY - NK_MEMSET(cmd, 0, size + alignment); -#endif - - cmd->type = t; - cmd->next = b->base->allocated + alignment; -#ifdef NK_INCLUDE_COMMAND_USERDATA - cmd->userdata = b->userdata; -#endif - b->end = cmd->next; - return cmd; -} - -NK_API void -nk_push_scissor(struct nk_command_buffer *b, struct nk_rect r) -{ - struct nk_command_scissor *cmd; - NK_ASSERT(b); - if (!b) return; - - b->clip.x = r.x; - b->clip.y = r.y; - b->clip.w = r.w; - b->clip.h = r.h; - cmd = (struct nk_command_scissor*) - nk_command_buffer_push(b, NK_COMMAND_SCISSOR, sizeof(*cmd)); - - if (!cmd) return; - cmd->x = (short)r.x; - cmd->y = (short)r.y; - cmd->w = (unsigned short)NK_MAX(0, r.w); - cmd->h = (unsigned short)NK_MAX(0, r.h); -} - -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 c) -{ - struct nk_command_line *cmd; - NK_ASSERT(b); - if (!b) return; - cmd = (struct nk_command_line*) - nk_command_buffer_push(b, NK_COMMAND_LINE, sizeof(*cmd)); - if (!cmd) return; - cmd->line_thickness = (unsigned short)line_thickness; - cmd->begin.x = (short)x0; - cmd->begin.y = (short)y0; - cmd->end.x = (short)x1; - cmd->end.y = (short)y1; - cmd->color = c; -} - -NK_API void -nk_stroke_curve(struct nk_command_buffer *b, float ax, float ay, - float ctrl0x, float ctrl0y, float ctrl1x, float ctrl1y, - float bx, float by, float line_thickness, struct nk_color col) -{ - struct nk_command_curve *cmd; - NK_ASSERT(b); - if (!b || col.a == 0) return; - - cmd = (struct nk_command_curve*) - nk_command_buffer_push(b, NK_COMMAND_CURVE, sizeof(*cmd)); - if (!cmd) return; - cmd->line_thickness = (unsigned short)line_thickness; - cmd->begin.x = (short)ax; - cmd->begin.y = (short)ay; - cmd->ctrl[0].x = (short)ctrl0x; - cmd->ctrl[0].y = (short)ctrl0y; - cmd->ctrl[1].x = (short)ctrl1x; - cmd->ctrl[1].y = (short)ctrl1y; - cmd->end.x = (short)bx; - cmd->end.y = (short)by; - cmd->color = col; -} - -NK_API void -nk_stroke_rect(struct nk_command_buffer *b, struct nk_rect rect, - float rounding, float line_thickness, struct nk_color c) -{ - struct nk_command_rect *cmd; - NK_ASSERT(b); - if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return; - if (b->use_clipping) { - const struct nk_rect *clip = &b->clip; - if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, - clip->x, clip->y, clip->w, clip->h)) return; - } - - cmd = (struct nk_command_rect*) - nk_command_buffer_push(b, NK_COMMAND_RECT, sizeof(*cmd)); - if (!cmd) return; - cmd->rounding = (unsigned short)rounding; - cmd->line_thickness = (unsigned short)line_thickness; - cmd->x = (short)rect.x; - cmd->y = (short)rect.y; - cmd->w = (unsigned short)NK_MAX(0, rect.w); - cmd->h = (unsigned short)NK_MAX(0, rect.h); - cmd->color = c; -} - -NK_API void -nk_fill_rect(struct nk_command_buffer *b, struct nk_rect rect, - float rounding, struct nk_color c) -{ - struct nk_command_rect_filled *cmd; - NK_ASSERT(b); - if (!b || c.a == 0 || rect.w == 0 || rect.h == 0) return; - if (b->use_clipping) { - const struct nk_rect *clip = &b->clip; - if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, - clip->x, clip->y, clip->w, clip->h)) return; - } - - cmd = (struct nk_command_rect_filled*) - nk_command_buffer_push(b, NK_COMMAND_RECT_FILLED, sizeof(*cmd)); - if (!cmd) return; - cmd->rounding = (unsigned short)rounding; - cmd->x = (short)rect.x; - cmd->y = (short)rect.y; - cmd->w = (unsigned short)NK_MAX(0, rect.w); - cmd->h = (unsigned short)NK_MAX(0, rect.h); - cmd->color = c; -} - -NK_API void -nk_fill_rect_multi_color(struct nk_command_buffer *b, struct nk_rect rect, - struct nk_color left, struct nk_color top, struct nk_color right, - struct nk_color bottom) -{ - struct nk_command_rect_multi_color *cmd; - NK_ASSERT(b); - if (!b || rect.w == 0 || rect.h == 0) return; - if (b->use_clipping) { - const struct nk_rect *clip = &b->clip; - if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, - clip->x, clip->y, clip->w, clip->h)) return; - } - - cmd = (struct nk_command_rect_multi_color*) - nk_command_buffer_push(b, NK_COMMAND_RECT_MULTI_COLOR, sizeof(*cmd)); - if (!cmd) return; - cmd->x = (short)rect.x; - cmd->y = (short)rect.y; - cmd->w = (unsigned short)NK_MAX(0, rect.w); - cmd->h = (unsigned short)NK_MAX(0, rect.h); - cmd->left = left; - cmd->top = top; - cmd->right = right; - cmd->bottom = bottom; -} - -NK_API void -nk_stroke_circle(struct nk_command_buffer *b, struct nk_rect r, - float line_thickness, struct nk_color c) -{ - struct nk_command_circle *cmd; - if (!b || r.w == 0 || r.h == 0) return; - if (b->use_clipping) { - const struct nk_rect *clip = &b->clip; - if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) - return; - } - - cmd = (struct nk_command_circle*) - nk_command_buffer_push(b, NK_COMMAND_CIRCLE, sizeof(*cmd)); - if (!cmd) return; - cmd->line_thickness = (unsigned short)line_thickness; - cmd->x = (short)r.x; - cmd->y = (short)r.y; - cmd->w = (unsigned short)NK_MAX(r.w, 0); - cmd->h = (unsigned short)NK_MAX(r.h, 0); - cmd->color = c; -} - -NK_API void -nk_fill_circle(struct nk_command_buffer *b, struct nk_rect r, struct nk_color c) -{ - struct nk_command_circle_filled *cmd; - NK_ASSERT(b); - if (!b || c.a == 0 || r.w == 0 || r.h == 0) return; - if (b->use_clipping) { - const struct nk_rect *clip = &b->clip; - if (!NK_INTERSECT(r.x, r.y, r.w, r.h, clip->x, clip->y, clip->w, clip->h)) - return; - } - - cmd = (struct nk_command_circle_filled*) - nk_command_buffer_push(b, NK_COMMAND_CIRCLE_FILLED, sizeof(*cmd)); - if (!cmd) return; - cmd->x = (short)r.x; - cmd->y = (short)r.y; - cmd->w = (unsigned short)NK_MAX(r.w, 0); - cmd->h = (unsigned short)NK_MAX(r.h, 0); - cmd->color = c; -} - -NK_API void -nk_stroke_arc(struct nk_command_buffer *b, float cx, float cy, float radius, - float a_min, float a_max, float line_thickness, struct nk_color c) -{ - struct nk_command_arc *cmd; - if (!b || c.a == 0) return; - cmd = (struct nk_command_arc*) - nk_command_buffer_push(b, NK_COMMAND_ARC, sizeof(*cmd)); - if (!cmd) return; - cmd->line_thickness = (unsigned short)line_thickness; - cmd->cx = (short)cx; - cmd->cy = (short)cy; - cmd->r = (unsigned short)radius; - cmd->a[0] = a_min; - cmd->a[1] = a_max; - cmd->color = c; -} - -NK_API void -nk_fill_arc(struct nk_command_buffer *b, float cx, float cy, float radius, - float a_min, float a_max, struct nk_color c) -{ - struct nk_command_arc_filled *cmd; - NK_ASSERT(b); - if (!b || c.a == 0) return; - cmd = (struct nk_command_arc_filled*) - nk_command_buffer_push(b, NK_COMMAND_ARC_FILLED, sizeof(*cmd)); - if (!cmd) return; - cmd->cx = (short)cx; - cmd->cy = (short)cy; - cmd->r = (unsigned short)radius; - cmd->a[0] = a_min; - cmd->a[1] = a_max; - cmd->color = c; -} - -NK_API void -nk_stroke_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, - float y1, float x2, float y2, float line_thickness, struct nk_color c) -{ - struct nk_command_triangle *cmd; - NK_ASSERT(b); - if (!b || c.a == 0) return; - if (b->use_clipping) { - const struct nk_rect *clip = &b->clip; - if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && - !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && - !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) - return; - } - - cmd = (struct nk_command_triangle*) - nk_command_buffer_push(b, NK_COMMAND_TRIANGLE, sizeof(*cmd)); - if (!cmd) return; - cmd->line_thickness = (unsigned short)line_thickness; - cmd->a.x = (short)x0; - cmd->a.y = (short)y0; - cmd->b.x = (short)x1; - cmd->b.y = (short)y1; - cmd->c.x = (short)x2; - cmd->c.y = (short)y2; - cmd->color = c; -} - -NK_API void -nk_fill_triangle(struct nk_command_buffer *b, float x0, float y0, float x1, - float y1, float x2, float y2, struct nk_color c) -{ - struct nk_command_triangle_filled *cmd; - NK_ASSERT(b); - if (!b || c.a == 0) return; - if (!b) return; - if (b->use_clipping) { - const struct nk_rect *clip = &b->clip; - if (!NK_INBOX(x0, y0, clip->x, clip->y, clip->w, clip->h) && - !NK_INBOX(x1, y1, clip->x, clip->y, clip->w, clip->h) && - !NK_INBOX(x2, y2, clip->x, clip->y, clip->w, clip->h)) - return; - } - - cmd = (struct nk_command_triangle_filled*) - nk_command_buffer_push(b, NK_COMMAND_TRIANGLE_FILLED, sizeof(*cmd)); - if (!cmd) return; - cmd->a.x = (short)x0; - cmd->a.y = (short)y0; - cmd->b.x = (short)x1; - cmd->b.y = (short)y1; - cmd->c.x = (short)x2; - cmd->c.y = (short)y2; - cmd->color = c; -} - -NK_API void -nk_stroke_polygon(struct nk_command_buffer *b, float *points, int point_count, - float line_thickness, struct nk_color col) -{ - int i; - nk_size size = 0; - struct nk_command_polygon *cmd; - - NK_ASSERT(b); - if (!b || col.a == 0) return; - size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; - cmd = (struct nk_command_polygon*) nk_command_buffer_push(b, NK_COMMAND_POLYGON, size); - if (!cmd) return; - cmd->color = col; - cmd->line_thickness = (unsigned short)line_thickness; - cmd->point_count = (unsigned short)point_count; - for (i = 0; i < point_count; ++i) { - cmd->points[i].x = (short)points[i*2]; - cmd->points[i].y = (short)points[i*2+1]; - } -} - -NK_API void -nk_fill_polygon(struct nk_command_buffer *b, float *points, int point_count, - struct nk_color col) -{ - int i; - nk_size size = 0; - struct nk_command_polygon_filled *cmd; - - NK_ASSERT(b); - if (!b || col.a == 0) return; - size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; - cmd = (struct nk_command_polygon_filled*) - nk_command_buffer_push(b, NK_COMMAND_POLYGON_FILLED, size); - if (!cmd) return; - cmd->color = col; - cmd->point_count = (unsigned short)point_count; - for (i = 0; i < point_count; ++i) { - cmd->points[i].x = (short)points[i*2+0]; - cmd->points[i].y = (short)points[i*2+1]; - } -} - -NK_API void -nk_stroke_polyline(struct nk_command_buffer *b, float *points, int point_count, - float line_thickness, struct nk_color col) -{ - int i; - nk_size size = 0; - struct nk_command_polyline *cmd; - - NK_ASSERT(b); - if (!b || col.a == 0) return; - size = sizeof(*cmd) + sizeof(short) * 2 * (nk_size)point_count; - cmd = (struct nk_command_polyline*) nk_command_buffer_push(b, NK_COMMAND_POLYLINE, size); - if (!cmd) return; - cmd->color = col; - cmd->point_count = (unsigned short)point_count; - cmd->line_thickness = (unsigned short)line_thickness; - for (i = 0; i < point_count; ++i) { - cmd->points[i].x = (short)points[i*2]; - cmd->points[i].y = (short)points[i*2+1]; - } -} - -NK_API void -nk_draw_image(struct nk_command_buffer *b, struct nk_rect r, - const struct nk_image *img, struct nk_color col) -{ - struct nk_command_image *cmd; - NK_ASSERT(b); - if (!b) return; - if (b->use_clipping) { - const struct nk_rect *c = &b->clip; - 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)) - return; - } - - cmd = (struct nk_command_image*) - nk_command_buffer_push(b, NK_COMMAND_IMAGE, sizeof(*cmd)); - if (!cmd) return; - cmd->x = (short)r.x; - cmd->y = (short)r.y; - cmd->w = (unsigned short)NK_MAX(0, r.w); - cmd->h = (unsigned short)NK_MAX(0, r.h); - cmd->img = *img; - cmd->col = col; -} - -NK_API void -nk_draw_text(struct nk_command_buffer *b, struct nk_rect r, - const char *string, int length, const struct nk_user_font *font, - struct nk_color bg, struct nk_color fg) -{ - float text_width = 0; - struct nk_command_text *cmd; - - NK_ASSERT(b); - NK_ASSERT(font); - if (!b || !string || !length || (bg.a == 0 && fg.a == 0)) return; - if (b->use_clipping) { - const struct nk_rect *c = &b->clip; - 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)) - return; - } - - /* make sure text fits inside bounds */ - text_width = font->width(font->userdata, font->height, string, length); - if (text_width > r.w){ - int glyphs = 0; - float txt_width = (float)text_width; - length = nk_text_clamp(font, string, length, r.w, &glyphs, &txt_width, 0,0); - } - - if (!length) return; - cmd = (struct nk_command_text*) - nk_command_buffer_push(b, NK_COMMAND_TEXT, sizeof(*cmd) + (nk_size)(length + 1)); - if (!cmd) return; - cmd->x = (short)r.x; - cmd->y = (short)r.y; - cmd->w = (unsigned short)r.w; - cmd->h = (unsigned short)r.h; - cmd->background = bg; - cmd->foreground = fg; - cmd->font = font; - cmd->length = length; - cmd->height = font->height; - NK_MEMCPY(cmd->string, string, (nk_size)length); - cmd->string[length] = '\0'; -} - -/* ============================================================== - * - * DRAW LIST - * - * ===============================================================*/ -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT -NK_API void -nk_draw_list_init(struct nk_draw_list *list) -{ - nk_size i = 0; - NK_ASSERT(list); - if (!list) return; - nk_zero(list, sizeof(*list)); - for (i = 0; i < NK_LEN(list->circle_vtx); ++i) { - const float a = ((float)i / (float)NK_LEN(list->circle_vtx)) * 2 * NK_PI; - list->circle_vtx[i].x = (float)NK_COS(a); - list->circle_vtx[i].y = (float)NK_SIN(a); - } -} - -NK_API void -nk_draw_list_setup(struct nk_draw_list *canvas, const struct nk_convert_config *config, - struct nk_buffer *cmds, struct nk_buffer *vertices, struct nk_buffer *elements) -{ - NK_ASSERT(canvas); - NK_ASSERT(config); - NK_ASSERT(cmds); - NK_ASSERT(vertices); - NK_ASSERT(elements); - if (!canvas || !config || !cmds || !vertices || !elements) - return; - - canvas->buffer = cmds; - canvas->config = *config; - canvas->elements = elements; - canvas->vertices = vertices; - canvas->clip_rect = nk_null_rect; -} - -NK_API const struct nk_draw_command* -nk__draw_list_begin(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) -{ - nk_byte *memory; - nk_size offset; - const struct nk_draw_command *cmd; - - NK_ASSERT(buffer); - if (!buffer || !buffer->size || !canvas->cmd_count) - return 0; - - memory = (nk_byte*)buffer->memory.ptr; - offset = buffer->memory.size - canvas->cmd_offset; - cmd = nk_ptr_add(const struct nk_draw_command, memory, offset); - return cmd; -} - -NK_API const struct nk_draw_command* -nk__draw_list_end(const struct nk_draw_list *canvas, const struct nk_buffer *buffer) -{ - nk_size size; - nk_size offset; - nk_byte *memory; - const struct nk_draw_command *end; - - NK_ASSERT(buffer); - NK_ASSERT(canvas); - if (!buffer || !canvas) - return 0; - - memory = (nk_byte*)buffer->memory.ptr; - size = buffer->memory.size; - offset = size - canvas->cmd_offset; - end = nk_ptr_add(const struct nk_draw_command, memory, offset); - end -= (canvas->cmd_count-1); - return end; -} - -NK_API const struct nk_draw_command* -nk__draw_list_next(const struct nk_draw_command *cmd, - const struct nk_buffer *buffer, const struct nk_draw_list *canvas) -{ - const struct nk_draw_command *end; - NK_ASSERT(buffer); - NK_ASSERT(canvas); - if (!cmd || !buffer || !canvas) - return 0; - - end = nk__draw_list_end(canvas, buffer); - if (cmd <= end) return 0; - return (cmd-1); -} - -NK_API void -nk_draw_list_clear(struct nk_draw_list *list) -{ - NK_ASSERT(list); - if (!list) return; - if (list->buffer) - nk_buffer_clear(list->buffer); - if (list->vertices) - nk_buffer_clear(list->vertices); - if (list->elements) - nk_buffer_clear(list->elements); - - list->element_count = 0; - list->vertex_count = 0; - list->cmd_offset = 0; - list->cmd_count = 0; - list->path_count = 0; - list->vertices = 0; - list->elements = 0; - list->clip_rect = nk_null_rect; -} - -NK_INTERN struct nk_vec2* -nk_draw_list_alloc_path(struct nk_draw_list *list, int count) -{ - struct nk_vec2 *points; - NK_STORAGE const nk_size point_align = NK_ALIGNOF(struct nk_vec2); - NK_STORAGE const nk_size point_size = sizeof(struct nk_vec2); - points = (struct nk_vec2*) - nk_buffer_alloc(list->buffer, NK_BUFFER_FRONT, - point_size * (nk_size)count, point_align); - - if (!points) return 0; - if (!list->path_offset) { - void *memory = nk_buffer_memory(list->buffer); - list->path_offset = (unsigned int)((nk_byte*)points - (nk_byte*)memory); - } - list->path_count += (unsigned int)count; - return points; -} - -NK_INTERN struct nk_vec2 -nk_draw_list_path_last(struct nk_draw_list *list) -{ - void *memory; - struct nk_vec2 *point; - NK_ASSERT(list->path_count); - memory = nk_buffer_memory(list->buffer); - point = nk_ptr_add(struct nk_vec2, memory, list->path_offset); - point += (list->path_count-1); - return *point; -} - -NK_INTERN struct nk_draw_command* -nk_draw_list_push_command(struct nk_draw_list *list, struct nk_rect clip, - nk_handle texture) -{ - NK_STORAGE const nk_size cmd_align = NK_ALIGNOF(struct nk_draw_command); - NK_STORAGE const nk_size cmd_size = sizeof(struct nk_draw_command); - struct nk_draw_command *cmd; - - NK_ASSERT(list); - cmd = (struct nk_draw_command*) - nk_buffer_alloc(list->buffer, NK_BUFFER_BACK, cmd_size, cmd_align); - - if (!cmd) return 0; - if (!list->cmd_count) { - nk_byte *memory = (nk_byte*)nk_buffer_memory(list->buffer); - nk_size total = nk_buffer_total(list->buffer); - memory = nk_ptr_add(nk_byte, memory, total); - list->cmd_offset = (nk_size)(memory - (nk_byte*)cmd); - } - - cmd->elem_count = 0; - cmd->clip_rect = clip; - cmd->texture = texture; -#ifdef NK_INCLUDE_COMMAND_USERDATA - cmd->userdata = list->userdata; -#endif - - list->cmd_count++; - list->clip_rect = clip; - return cmd; -} - -NK_INTERN struct nk_draw_command* -nk_draw_list_command_last(struct nk_draw_list *list) -{ - void *memory; - nk_size size; - struct nk_draw_command *cmd; - NK_ASSERT(list->cmd_count); - - memory = nk_buffer_memory(list->buffer); - size = nk_buffer_total(list->buffer); - cmd = nk_ptr_add(struct nk_draw_command, memory, size - list->cmd_offset); - return (cmd - (list->cmd_count-1)); -} - -NK_INTERN void -nk_draw_list_add_clip(struct nk_draw_list *list, struct nk_rect rect) -{ - NK_ASSERT(list); - if (!list) return; - if (!list->cmd_count) { - nk_draw_list_push_command(list, rect, list->config.null.texture); - } else { - struct nk_draw_command *prev = nk_draw_list_command_last(list); - if (prev->elem_count == 0) - prev->clip_rect = rect; - nk_draw_list_push_command(list, rect, prev->texture); - } -} - -NK_INTERN void -nk_draw_list_push_image(struct nk_draw_list *list, nk_handle texture) -{ - NK_ASSERT(list); - if (!list) return; - if (!list->cmd_count) { - nk_draw_list_push_command(list, nk_null_rect, texture); - } else { - struct nk_draw_command *prev = nk_draw_list_command_last(list); - if (prev->elem_count == 0) - prev->texture = texture; - else if (prev->texture.id != texture.id) - nk_draw_list_push_command(list, prev->clip_rect, texture); - } -} - -#ifdef NK_INCLUDE_COMMAND_USERDATA -NK_API void -nk_draw_list_push_userdata(struct nk_draw_list *list, nk_handle userdata) -{ - list->userdata = userdata; -} -#endif - -NK_INTERN void* -nk_draw_list_alloc_vertices(struct nk_draw_list *list, nk_size count) -{ - void *vtx; - NK_ASSERT(list); - if (!list) return 0; - vtx = nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, - list->config.vertex_size*count, list->config.vertex_alignment); - if (!vtx) return 0; - list->vertex_count += (unsigned int)count; - return vtx; -} - -NK_INTERN nk_draw_index* -nk_draw_list_alloc_elements(struct nk_draw_list *list, nk_size count) -{ - nk_draw_index *ids; - struct nk_draw_command *cmd; - NK_STORAGE const nk_size elem_align = NK_ALIGNOF(nk_draw_index); - NK_STORAGE const nk_size elem_size = sizeof(nk_draw_index); - NK_ASSERT(list); - if (!list) return 0; - - ids = (nk_draw_index*) - nk_buffer_alloc(list->elements, NK_BUFFER_FRONT, elem_size*count, elem_align); - if (!ids) return 0; - cmd = nk_draw_list_command_last(list); - list->element_count += (unsigned int)count; - cmd->elem_count += (unsigned int)count; - return ids; -} - -static int -nk_draw_vertex_layout_element_is_end_of_layout( - const struct nk_draw_vertex_layout_element *element) -{ - return (element->attribute == NK_VERTEX_ATTRIBUTE_COUNT || - element->format == NK_FORMAT_COUNT); -} - -static void -nk_draw_vertex_color(void *attribute, const float *values, - enum nk_draw_vertex_layout_format format) -{ - /* if this triggers you tried to provide a value format for a color */ - NK_ASSERT(format >= NK_FORMAT_COLOR_BEGIN); - NK_ASSERT(format <= NK_FORMAT_COLOR_END); - if (format < NK_FORMAT_COLOR_BEGIN || format > NK_FORMAT_COLOR_END) return; - - switch (format) { - default: NK_ASSERT(0 && "Invalid vertex layout color format"); break; - case NK_FORMAT_R8G8B8A8: - case NK_FORMAT_R8G8B8: { - struct nk_color col = nk_rgba_fv(values); - NK_MEMCPY(attribute, &col.r, sizeof(col)); - } break; - case NK_FORMAT_R16G15B16: { - nk_ushort col[3]; - col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX); - col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX); - col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX); - NK_MEMCPY(attribute, col, sizeof(col)); - } break; - case NK_FORMAT_R16G15B16A16: { - nk_ushort col[4]; - col[0] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[0] * NK_USHORT_MAX, NK_USHORT_MAX); - col[1] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[1] * NK_USHORT_MAX, NK_USHORT_MAX); - col[2] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[2] * NK_USHORT_MAX, NK_USHORT_MAX); - col[3] = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[3] * NK_USHORT_MAX, NK_USHORT_MAX); - NK_MEMCPY(attribute, col, sizeof(col)); - } break; - case NK_FORMAT_R32G32B32: { - nk_uint col[3]; - col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX); - col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX); - col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX); - NK_MEMCPY(attribute, col, sizeof(col)); - } break; - case NK_FORMAT_R32G32B32A32: { - nk_uint col[4]; - col[0] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[0] * NK_UINT_MAX, NK_UINT_MAX); - col[1] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[1] * NK_UINT_MAX, NK_UINT_MAX); - col[2] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[2] * NK_UINT_MAX, NK_UINT_MAX); - col[3] = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[3] * NK_UINT_MAX, NK_UINT_MAX); - NK_MEMCPY(attribute, col, sizeof(col)); - } break; - case NK_FORMAT_R32G32B32A32_FLOAT: - NK_MEMCPY(attribute, values, sizeof(float)*4); - break; - case NK_FORMAT_R32G32B32A32_DOUBLE: { - double col[4]; - col[0] = (double)NK_SATURATE(values[0]); - col[1] = (double)NK_SATURATE(values[1]); - col[2] = (double)NK_SATURATE(values[2]); - col[3] = (double)NK_SATURATE(values[3]); - NK_MEMCPY(attribute, col, sizeof(col)); - } break; - case NK_FORMAT_RGB32: - case NK_FORMAT_RGBA32: { - struct nk_color col = nk_rgba_fv(values); - nk_uint color = nk_color_u32(col); - NK_MEMCPY(attribute, &color, sizeof(color)); - } break; - } -} - -static void -nk_draw_vertex_element(void *dst, const float *values, int value_count, - enum nk_draw_vertex_layout_format format) -{ - int value_index; - void *attribute = dst; - /* if this triggers you tried to provide a color format for a value */ - NK_ASSERT(format < NK_FORMAT_COLOR_BEGIN); - if (format >= NK_FORMAT_COLOR_BEGIN && format <= NK_FORMAT_COLOR_END) return; - for (value_index = 0; value_index < value_count; ++value_index) { - switch (format) { - default: NK_ASSERT(0 && "invalid vertex layout format"); break; - case NK_FORMAT_SCHAR: { - char value = (char)NK_CLAMP(NK_SCHAR_MIN, values[value_index], NK_SCHAR_MAX); - NK_MEMCPY(attribute, &value, sizeof(value)); - attribute = (void*)((char*)attribute + sizeof(char)); - } break; - case NK_FORMAT_SSHORT: { - nk_short value = (nk_short)NK_CLAMP(NK_SSHORT_MIN, values[value_index], NK_SSHORT_MAX); - NK_MEMCPY(attribute, &value, sizeof(value)); - attribute = (void*)((char*)attribute + sizeof(value)); - } break; - case NK_FORMAT_SINT: { - nk_int value = (nk_int)NK_CLAMP(NK_SINT_MIN, values[value_index], NK_SINT_MAX); - NK_MEMCPY(attribute, &value, sizeof(value)); - attribute = (void*)((char*)attribute + sizeof(nk_int)); - } break; - case NK_FORMAT_UCHAR: { - unsigned char value = (unsigned char)NK_CLAMP(NK_UCHAR_MIN, values[value_index], NK_UCHAR_MAX); - NK_MEMCPY(attribute, &value, sizeof(value)); - attribute = (void*)((char*)attribute + sizeof(unsigned char)); - } break; - case NK_FORMAT_USHORT: { - nk_ushort value = (nk_ushort)NK_CLAMP(NK_USHORT_MIN, values[value_index], NK_USHORT_MAX); - NK_MEMCPY(attribute, &value, sizeof(value)); - attribute = (void*)((char*)attribute + sizeof(value)); - } break; - case NK_FORMAT_UINT: { - nk_uint value = (nk_uint)NK_CLAMP(NK_UINT_MIN, values[value_index], NK_UINT_MAX); - NK_MEMCPY(attribute, &value, sizeof(value)); - attribute = (void*)((char*)attribute + sizeof(nk_uint)); - } break; - case NK_FORMAT_FLOAT: - NK_MEMCPY(attribute, &values[value_index], sizeof(values[value_index])); - attribute = (void*)((char*)attribute + sizeof(float)); - break; - case NK_FORMAT_DOUBLE: { - double value = (double)values[value_index]; - NK_MEMCPY(attribute, &value, sizeof(value)); - attribute = (void*)((char*)attribute + sizeof(double)); - } break; - } - } -} - -NK_INTERN void* -nk_draw_vertex(void *dst, const struct nk_convert_config *config, - struct nk_vec2 pos, struct nk_vec2 uv, struct nk_colorf color) -{ - void *result = (void*)((char*)dst + config->vertex_size); - const struct nk_draw_vertex_layout_element *elem_iter = config->vertex_layout; - while (!nk_draw_vertex_layout_element_is_end_of_layout(elem_iter)) { - void *address = (void*)((char*)dst + elem_iter->offset); - switch (elem_iter->attribute) { - case NK_VERTEX_ATTRIBUTE_COUNT: - default: NK_ASSERT(0 && "wrong element attribute"); - case NK_VERTEX_POSITION: nk_draw_vertex_element(address, &pos.x, 2, elem_iter->format); break; - case NK_VERTEX_TEXCOORD: nk_draw_vertex_element(address, &uv.x, 2, elem_iter->format); break; - case NK_VERTEX_COLOR: nk_draw_vertex_color(address, &color.r, elem_iter->format); break; - } - elem_iter++; - } - return result; -} - -NK_API void -nk_draw_list_stroke_poly_line(struct nk_draw_list *list, const struct nk_vec2 *points, - const unsigned int points_count, struct nk_color color, enum nk_draw_list_stroke closed, - float thickness, enum nk_anti_aliasing aliasing) -{ - nk_size count; - int thick_line; - struct nk_colorf col; - struct nk_colorf col_trans; - NK_ASSERT(list); - if (!list || points_count < 2) return; - - color.a = (nk_byte)((float)color.a * list->config.global_alpha); - count = points_count; - if (!closed) count = points_count-1; - thick_line = thickness > 1.0f; - -#ifdef NK_INCLUDE_COMMAND_USERDATA - nk_draw_list_push_userdata(list, list->userdata); -#endif - - color.a = (nk_byte)((float)color.a * list->config.global_alpha); - nk_color_fv(&col.r, color); - col_trans = col; - col_trans.a = 0; - - if (aliasing == NK_ANTI_ALIASING_ON) { - /* ANTI-ALIASED STROKE */ - const float AA_SIZE = 1.0f; - NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); - NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); - - /* allocate vertices and elements */ - nk_size i1 = 0; - nk_size vertex_offset; - nk_size index = list->vertex_count; - - const nk_size idx_count = (thick_line) ? (count * 18) : (count * 12); - const nk_size vtx_count = (thick_line) ? (points_count * 4): (points_count *3); - - void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); - nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); - - nk_size size; - struct nk_vec2 *normals, *temp; - NK_ASSERT(vtx && ids); - if (!vtx || !ids) return; - - /* temporary allocate normals + points */ - vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); - nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); - size = pnt_size * ((thick_line) ? 5 : 3) * points_count; - normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); - NK_ASSERT(normals); - if (!normals) return; - temp = normals + points_count; - - /* make sure vertex pointer is still correct */ - vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); - - /* calculate normals */ - for (i1 = 0; i1 < count; ++i1) { - const nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); - struct nk_vec2 diff = nk_vec2_sub(points[i2], points[i1]); - float len; - - /* vec2 inverted length */ - len = nk_vec2_len_sqr(diff); - if (len != 0.0f) - len = nk_inv_sqrt(len); - else len = 1.0f; - - diff = nk_vec2_muls(diff, len); - normals[i1].x = diff.y; - normals[i1].y = -diff.x; - } - - if (!closed) - normals[points_count-1] = normals[points_count-2]; - - if (!thick_line) { - nk_size idx1, i; - if (!closed) { - struct nk_vec2 d; - temp[0] = nk_vec2_add(points[0], nk_vec2_muls(normals[0], AA_SIZE)); - temp[1] = nk_vec2_sub(points[0], nk_vec2_muls(normals[0], AA_SIZE)); - d = nk_vec2_muls(normals[points_count-1], AA_SIZE); - temp[(points_count-1) * 2 + 0] = nk_vec2_add(points[points_count-1], d); - temp[(points_count-1) * 2 + 1] = nk_vec2_sub(points[points_count-1], d); - } - - /* fill elements */ - idx1 = index; - for (i1 = 0; i1 < count; i1++) { - struct nk_vec2 dm; - float dmr2; - nk_size i2 = ((i1 + 1) == points_count) ? 0 : (i1 + 1); - nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 3); - - /* average normals */ - dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); - dmr2 = dm.x * dm.x + dm.y* dm.y; - if (dmr2 > 0.000001f) { - float scale = 1.0f/dmr2; - scale = NK_MIN(100.0f, scale); - dm = nk_vec2_muls(dm, scale); - } - - dm = nk_vec2_muls(dm, AA_SIZE); - temp[i2*2+0] = nk_vec2_add(points[i2], dm); - temp[i2*2+1] = nk_vec2_sub(points[i2], dm); - - ids[0] = (nk_draw_index)(idx2 + 0); ids[1] = (nk_draw_index)(idx1+0); - ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); - ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+0); - ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); - ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); - ids[10]= (nk_draw_index)(idx2 + 0); ids[11]= (nk_draw_index)(idx2+1); - ids += 12; - idx1 = idx2; - } - - /* fill vertices */ - for (i = 0; i < points_count; ++i) { - const struct nk_vec2 uv = list->config.null.uv; - vtx = nk_draw_vertex(vtx, &list->config, points[i], uv, col); - vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+0], uv, col_trans); - vtx = nk_draw_vertex(vtx, &list->config, temp[i*2+1], uv, col_trans); - } - } else { - nk_size idx1, i; - const float half_inner_thickness = (thickness - AA_SIZE) * 0.5f; - if (!closed) { - struct nk_vec2 d1 = nk_vec2_muls(normals[0], half_inner_thickness + AA_SIZE); - struct nk_vec2 d2 = nk_vec2_muls(normals[0], half_inner_thickness); - - temp[0] = nk_vec2_add(points[0], d1); - temp[1] = nk_vec2_add(points[0], d2); - temp[2] = nk_vec2_sub(points[0], d2); - temp[3] = nk_vec2_sub(points[0], d1); - - d1 = nk_vec2_muls(normals[points_count-1], half_inner_thickness + AA_SIZE); - d2 = nk_vec2_muls(normals[points_count-1], half_inner_thickness); - - temp[(points_count-1)*4+0] = nk_vec2_add(points[points_count-1], d1); - temp[(points_count-1)*4+1] = nk_vec2_add(points[points_count-1], d2); - temp[(points_count-1)*4+2] = nk_vec2_sub(points[points_count-1], d2); - temp[(points_count-1)*4+3] = nk_vec2_sub(points[points_count-1], d1); - } - - /* add all elements */ - idx1 = index; - for (i1 = 0; i1 < count; ++i1) { - struct nk_vec2 dm_out, dm_in; - const nk_size i2 = ((i1+1) == points_count) ? 0: (i1 + 1); - nk_size idx2 = ((i1+1) == points_count) ? index: (idx1 + 4); - - /* average normals */ - struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(normals[i1], normals[i2]), 0.5f); - float dmr2 = dm.x * dm.x + dm.y* dm.y; - if (dmr2 > 0.000001f) { - float scale = 1.0f/dmr2; - scale = NK_MIN(100.0f, scale); - dm = nk_vec2_muls(dm, scale); - } - - dm_out = nk_vec2_muls(dm, ((half_inner_thickness) + AA_SIZE)); - dm_in = nk_vec2_muls(dm, half_inner_thickness); - temp[i2*4+0] = nk_vec2_add(points[i2], dm_out); - temp[i2*4+1] = nk_vec2_add(points[i2], dm_in); - temp[i2*4+2] = nk_vec2_sub(points[i2], dm_in); - temp[i2*4+3] = nk_vec2_sub(points[i2], dm_out); - - /* add indexes */ - ids[0] = (nk_draw_index)(idx2 + 1); ids[1] = (nk_draw_index)(idx1+1); - ids[2] = (nk_draw_index)(idx1 + 2); ids[3] = (nk_draw_index)(idx1+2); - ids[4] = (nk_draw_index)(idx2 + 2); ids[5] = (nk_draw_index)(idx2+1); - ids[6] = (nk_draw_index)(idx2 + 1); ids[7] = (nk_draw_index)(idx1+1); - ids[8] = (nk_draw_index)(idx1 + 0); ids[9] = (nk_draw_index)(idx1+0); - ids[10]= (nk_draw_index)(idx2 + 0); ids[11] = (nk_draw_index)(idx2+1); - ids[12]= (nk_draw_index)(idx2 + 2); ids[13] = (nk_draw_index)(idx1+2); - ids[14]= (nk_draw_index)(idx1 + 3); ids[15] = (nk_draw_index)(idx1+3); - ids[16]= (nk_draw_index)(idx2 + 3); ids[17] = (nk_draw_index)(idx2+2); - ids += 18; - idx1 = idx2; - } - - /* add vertices */ - for (i = 0; i < points_count; ++i) { - const struct nk_vec2 uv = list->config.null.uv; - vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+0], uv, col_trans); - vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+1], uv, col); - vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+2], uv, col); - vtx = nk_draw_vertex(vtx, &list->config, temp[i*4+3], uv, col_trans); - } - } - /* free temporary normals + points */ - nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); - } else { - /* NON ANTI-ALIASED STROKE */ - nk_size i1 = 0; - nk_size idx = list->vertex_count; - const nk_size idx_count = count * 6; - const nk_size vtx_count = count * 4; - void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); - nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); - if (!vtx || !ids) return; - - for (i1 = 0; i1 < count; ++i1) { - float dx, dy; - const struct nk_vec2 uv = list->config.null.uv; - const nk_size i2 = ((i1+1) == points_count) ? 0 : i1 + 1; - const struct nk_vec2 p1 = points[i1]; - const struct nk_vec2 p2 = points[i2]; - struct nk_vec2 diff = nk_vec2_sub(p2, p1); - float len; - - /* vec2 inverted length */ - len = nk_vec2_len_sqr(diff); - if (len != 0.0f) - len = nk_inv_sqrt(len); - else len = 1.0f; - diff = nk_vec2_muls(diff, len); - - /* add vertices */ - dx = diff.x * (thickness * 0.5f); - dy = diff.y * (thickness * 0.5f); - - vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x + dy, p1.y - dx), uv, col); - vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x + dy, p2.y - dx), uv, col); - vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p2.x - dy, p2.y + dx), uv, col); - vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(p1.x - dy, p1.y + dx), uv, col); - - ids[0] = (nk_draw_index)(idx+0); ids[1] = (nk_draw_index)(idx+1); - ids[2] = (nk_draw_index)(idx+2); ids[3] = (nk_draw_index)(idx+0); - ids[4] = (nk_draw_index)(idx+2); ids[5] = (nk_draw_index)(idx+3); - - ids += 6; - idx += 4; - } - } -} - -NK_API void -nk_draw_list_fill_poly_convex(struct nk_draw_list *list, - const struct nk_vec2 *points, const unsigned int points_count, - struct nk_color color, enum nk_anti_aliasing aliasing) -{ - struct nk_colorf col; - struct nk_colorf col_trans; - - NK_STORAGE const nk_size pnt_align = NK_ALIGNOF(struct nk_vec2); - NK_STORAGE const nk_size pnt_size = sizeof(struct nk_vec2); - NK_ASSERT(list); - if (!list || points_count < 3) return; - -#ifdef NK_INCLUDE_COMMAND_USERDATA - nk_draw_list_push_userdata(list, list->userdata); -#endif - - color.a = (nk_byte)((float)color.a * list->config.global_alpha); - nk_color_fv(&col.r, color); - col_trans = col; - col_trans.a = 0; - - if (aliasing == NK_ANTI_ALIASING_ON) { - nk_size i = 0; - nk_size i0 = 0; - nk_size i1 = 0; - - const float AA_SIZE = 1.0f; - nk_size vertex_offset = 0; - nk_size index = list->vertex_count; - - const nk_size idx_count = (points_count-2)*3 + points_count*6; - const nk_size vtx_count = (points_count*2); - - void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); - nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); - - nk_size size = 0; - struct nk_vec2 *normals = 0; - unsigned int vtx_inner_idx = (unsigned int)(index + 0); - unsigned int vtx_outer_idx = (unsigned int)(index + 1); - if (!vtx || !ids) return; - - /* temporary allocate normals */ - vertex_offset = (nk_size)((nk_byte*)vtx - (nk_byte*)list->vertices->memory.ptr); - nk_buffer_mark(list->vertices, NK_BUFFER_FRONT); - size = pnt_size * points_count; - normals = (struct nk_vec2*) nk_buffer_alloc(list->vertices, NK_BUFFER_FRONT, size, pnt_align); - NK_ASSERT(normals); - if (!normals) return; - vtx = (void*)((nk_byte*)list->vertices->memory.ptr + vertex_offset); - - /* add elements */ - for (i = 2; i < points_count; i++) { - ids[0] = (nk_draw_index)(vtx_inner_idx); - ids[1] = (nk_draw_index)(vtx_inner_idx + ((i-1) << 1)); - ids[2] = (nk_draw_index)(vtx_inner_idx + (i << 1)); - ids += 3; - } - - /* compute normals */ - for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { - struct nk_vec2 p0 = points[i0]; - struct nk_vec2 p1 = points[i1]; - struct nk_vec2 diff = nk_vec2_sub(p1, p0); - - /* vec2 inverted length */ - float len = nk_vec2_len_sqr(diff); - if (len != 0.0f) - len = nk_inv_sqrt(len); - else len = 1.0f; - diff = nk_vec2_muls(diff, len); - - normals[i0].x = diff.y; - normals[i0].y = -diff.x; - } - - /* add vertices + indexes */ - for (i0 = points_count-1, i1 = 0; i1 < points_count; i0 = i1++) { - const struct nk_vec2 uv = list->config.null.uv; - struct nk_vec2 n0 = normals[i0]; - struct nk_vec2 n1 = normals[i1]; - struct nk_vec2 dm = nk_vec2_muls(nk_vec2_add(n0, n1), 0.5f); - float dmr2 = dm.x*dm.x + dm.y*dm.y; - if (dmr2 > 0.000001f) { - float scale = 1.0f / dmr2; - scale = NK_MIN(scale, 100.0f); - dm = nk_vec2_muls(dm, scale); - } - dm = nk_vec2_muls(dm, AA_SIZE * 0.5f); - - /* add vertices */ - vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_sub(points[i1], dm), uv, col); - vtx = nk_draw_vertex(vtx, &list->config, nk_vec2_add(points[i1], dm), uv, col_trans); - - /* add indexes */ - ids[0] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); - ids[1] = (nk_draw_index)(vtx_inner_idx+(i0<<1)); - ids[2] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); - ids[3] = (nk_draw_index)(vtx_outer_idx+(i0<<1)); - ids[4] = (nk_draw_index)(vtx_outer_idx+(i1<<1)); - ids[5] = (nk_draw_index)(vtx_inner_idx+(i1<<1)); - ids += 6; - } - /* free temporary normals + points */ - nk_buffer_reset(list->vertices, NK_BUFFER_FRONT); - } else { - nk_size i = 0; - nk_size index = list->vertex_count; - const nk_size idx_count = (points_count-2)*3; - const nk_size vtx_count = points_count; - void *vtx = nk_draw_list_alloc_vertices(list, vtx_count); - nk_draw_index *ids = nk_draw_list_alloc_elements(list, idx_count); - - if (!vtx || !ids) return; - for (i = 0; i < vtx_count; ++i) - vtx = nk_draw_vertex(vtx, &list->config, points[i], list->config.null.uv, col); - for (i = 2; i < points_count; ++i) { - ids[0] = (nk_draw_index)index; - ids[1] = (nk_draw_index)(index+ i - 1); - ids[2] = (nk_draw_index)(index+i); - ids += 3; - } - } -} - -NK_API void -nk_draw_list_path_clear(struct nk_draw_list *list) -{ - NK_ASSERT(list); - if (!list) return; - nk_buffer_reset(list->buffer, NK_BUFFER_FRONT); - list->path_count = 0; - list->path_offset = 0; -} - -NK_API void -nk_draw_list_path_line_to(struct nk_draw_list *list, struct nk_vec2 pos) -{ - struct nk_vec2 *points = 0; - struct nk_draw_command *cmd = 0; - NK_ASSERT(list); - if (!list) return; - if (!list->cmd_count) - nk_draw_list_add_clip(list, nk_null_rect); - - cmd = nk_draw_list_command_last(list); - if (cmd && cmd->texture.ptr != list->config.null.texture.ptr) - nk_draw_list_push_image(list, list->config.null.texture); - - points = nk_draw_list_alloc_path(list, 1); - if (!points) return; - points[0] = pos; -} - -NK_API void -nk_draw_list_path_arc_to_fast(struct nk_draw_list *list, struct nk_vec2 center, - float radius, int a_min, int a_max) -{ - int a = 0; - NK_ASSERT(list); - if (!list) return; - if (a_min <= a_max) { - for (a = a_min; a <= a_max; a++) { - const struct nk_vec2 c = list->circle_vtx[(nk_size)a % NK_LEN(list->circle_vtx)]; - const float x = center.x + c.x * radius; - const float y = center.y + c.y * radius; - nk_draw_list_path_line_to(list, nk_vec2(x, y)); - } - } -} - -NK_API void -nk_draw_list_path_arc_to(struct nk_draw_list *list, struct nk_vec2 center, - float radius, float a_min, float a_max, unsigned int segments) -{ - unsigned int i = 0; - NK_ASSERT(list); - if (!list) return; - if (radius == 0.0f) return; - for (i = 0; i <= segments; ++i) { - const float a = a_min + ((float)i / ((float)segments) * (a_max - a_min)); - const float x = center.x + (float)NK_COS(a) * radius; - const float y = center.y + (float)NK_SIN(a) * radius; - nk_draw_list_path_line_to(list, nk_vec2(x, y)); - } -} - -NK_API void -nk_draw_list_path_rect_to(struct nk_draw_list *list, struct nk_vec2 a, - struct nk_vec2 b, float rounding) -{ - float r; - NK_ASSERT(list); - if (!list) return; - r = rounding; - r = NK_MIN(r, ((b.x-a.x) < 0) ? -(b.x-a.x): (b.x-a.x)); - r = NK_MIN(r, ((b.y-a.y) < 0) ? -(b.y-a.y): (b.y-a.y)); - - if (r == 0.0f) { - nk_draw_list_path_line_to(list, a); - nk_draw_list_path_line_to(list, nk_vec2(b.x,a.y)); - nk_draw_list_path_line_to(list, b); - nk_draw_list_path_line_to(list, nk_vec2(a.x,b.y)); - } else { - nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, a.y + r), r, 6, 9); - nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, a.y + r), r, 9, 12); - nk_draw_list_path_arc_to_fast(list, nk_vec2(b.x - r, b.y - r), r, 0, 3); - nk_draw_list_path_arc_to_fast(list, nk_vec2(a.x + r, b.y - r), r, 3, 6); - } -} - -NK_API void -nk_draw_list_path_curve_to(struct nk_draw_list *list, struct nk_vec2 p2, - struct nk_vec2 p3, struct nk_vec2 p4, unsigned int num_segments) -{ - float t_step; - unsigned int i_step; - struct nk_vec2 p1; - - NK_ASSERT(list); - NK_ASSERT(list->path_count); - if (!list || !list->path_count) return; - num_segments = NK_MAX(num_segments, 1); - - p1 = nk_draw_list_path_last(list); - t_step = 1.0f/(float)num_segments; - for (i_step = 1; i_step <= num_segments; ++i_step) { - float t = t_step * (float)i_step; - float u = 1.0f - t; - float w1 = u*u*u; - float w2 = 3*u*u*t; - float w3 = 3*u*t*t; - float w4 = t * t *t; - float x = w1 * p1.x + w2 * p2.x + w3 * p3.x + w4 * p4.x; - float y = w1 * p1.y + w2 * p2.y + w3 * p3.y + w4 * p4.y; - nk_draw_list_path_line_to(list, nk_vec2(x,y)); - } -} - -NK_API void -nk_draw_list_path_fill(struct nk_draw_list *list, struct nk_color color) -{ - struct nk_vec2 *points; - NK_ASSERT(list); - if (!list) return; - points = (struct nk_vec2*)nk_buffer_memory(list->buffer); - nk_draw_list_fill_poly_convex(list, points, list->path_count, color, list->config.shape_AA); - nk_draw_list_path_clear(list); -} - -NK_API void -nk_draw_list_path_stroke(struct nk_draw_list *list, struct nk_color color, - enum nk_draw_list_stroke closed, float thickness) -{ - struct nk_vec2 *points; - NK_ASSERT(list); - if (!list) return; - points = (struct nk_vec2*)nk_buffer_memory(list->buffer); - nk_draw_list_stroke_poly_line(list, points, list->path_count, color, - closed, thickness, list->config.line_AA); - nk_draw_list_path_clear(list); -} - -NK_API void -nk_draw_list_stroke_line(struct nk_draw_list *list, struct nk_vec2 a, - struct nk_vec2 b, struct nk_color col, float thickness) -{ - NK_ASSERT(list); - if (!list || !col.a) return; - nk_draw_list_path_line_to(list, nk_vec2_add(a, nk_vec2(0.5f, 0.5f))); - nk_draw_list_path_line_to(list, nk_vec2_add(b, nk_vec2(0.5f, 0.5f))); - nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); -} - -NK_API void -nk_draw_list_fill_rect(struct nk_draw_list *list, struct nk_rect rect, - struct nk_color col, float rounding) -{ - NK_ASSERT(list); - if (!list || !col.a) return; - nk_draw_list_path_rect_to(list, nk_vec2(rect.x + 0.5f, rect.y + 0.5f), - nk_vec2(rect.x + rect.w + 0.5f, rect.y + rect.h + 0.5f), rounding); - nk_draw_list_path_fill(list, col); -} - -NK_API void -nk_draw_list_stroke_rect(struct nk_draw_list *list, struct nk_rect rect, - struct nk_color col, float rounding, float thickness) -{ - NK_ASSERT(list); - if (!list || !col.a) return; - nk_draw_list_path_rect_to(list, nk_vec2(rect.x + 0.5f, rect.y + 0.5f), - nk_vec2(rect.x + rect.w + 0.5f, rect.y + rect.h + 0.5f), rounding); - nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); -} - -NK_API void -nk_draw_list_fill_rect_multi_color(struct nk_draw_list *list, struct nk_rect rect, - struct nk_color left, struct nk_color top, struct nk_color right, - struct nk_color bottom) -{ - void *vtx; - struct nk_colorf col_left, col_top; - struct nk_colorf col_right, col_bottom; - nk_draw_index *idx; - nk_draw_index index; - - nk_color_fv(&col_left.r, left); - nk_color_fv(&col_right.r, right); - nk_color_fv(&col_top.r, top); - nk_color_fv(&col_bottom.r, bottom); - - NK_ASSERT(list); - if (!list) return; - - nk_draw_list_push_image(list, list->config.null.texture); - index = (nk_draw_index)list->vertex_count; - vtx = nk_draw_list_alloc_vertices(list, 4); - idx = nk_draw_list_alloc_elements(list, 6); - if (!vtx || !idx) return; - - idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); - idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); - idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); - - vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y), list->config.null.uv, col_left); - vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y), list->config.null.uv, col_top); - vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x + rect.w, rect.y + rect.h), list->config.null.uv, col_right); - vtx = nk_draw_vertex(vtx, &list->config, nk_vec2(rect.x, rect.y + rect.h), list->config.null.uv, col_bottom); -} - -NK_API void -nk_draw_list_fill_triangle(struct nk_draw_list *list, struct nk_vec2 a, - struct nk_vec2 b, struct nk_vec2 c, struct nk_color col) -{ - NK_ASSERT(list); - if (!list || !col.a) return; - nk_draw_list_path_line_to(list, a); - nk_draw_list_path_line_to(list, b); - nk_draw_list_path_line_to(list, c); - nk_draw_list_path_fill(list, col); -} - -NK_API void -nk_draw_list_stroke_triangle(struct nk_draw_list *list, struct nk_vec2 a, - struct nk_vec2 b, struct nk_vec2 c, struct nk_color col, float thickness) -{ - NK_ASSERT(list); - if (!list || !col.a) return; - nk_draw_list_path_line_to(list, a); - nk_draw_list_path_line_to(list, b); - nk_draw_list_path_line_to(list, c); - nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); -} - -NK_API void -nk_draw_list_fill_circle(struct nk_draw_list *list, struct nk_vec2 center, - float radius, struct nk_color col, unsigned int segs) -{ - float a_max; - NK_ASSERT(list); - if (!list || !col.a) return; - a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; - nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); - nk_draw_list_path_fill(list, col); -} - -NK_API void -nk_draw_list_stroke_circle(struct nk_draw_list *list, struct nk_vec2 center, - float radius, struct nk_color col, unsigned int segs, float thickness) -{ - float a_max; - NK_ASSERT(list); - if (!list || !col.a) return; - a_max = NK_PI * 2.0f * ((float)segs - 1.0f) / (float)segs; - nk_draw_list_path_arc_to(list, center, radius, 0.0f, a_max, segs); - nk_draw_list_path_stroke(list, col, NK_STROKE_CLOSED, thickness); -} - -NK_API void -nk_draw_list_stroke_curve(struct nk_draw_list *list, struct nk_vec2 p0, - struct nk_vec2 cp0, struct nk_vec2 cp1, struct nk_vec2 p1, - struct nk_color col, unsigned int segments, float thickness) -{ - NK_ASSERT(list); - if (!list || !col.a) return; - nk_draw_list_path_line_to(list, p0); - nk_draw_list_path_curve_to(list, cp0, cp1, p1, segments); - nk_draw_list_path_stroke(list, col, NK_STROKE_OPEN, thickness); -} - -NK_INTERN void -nk_draw_list_push_rect_uv(struct nk_draw_list *list, struct nk_vec2 a, - struct nk_vec2 c, struct nk_vec2 uva, struct nk_vec2 uvc, - struct nk_color color) -{ - void *vtx; - struct nk_vec2 uvb; - struct nk_vec2 uvd; - struct nk_vec2 b; - struct nk_vec2 d; - - struct nk_colorf col; - nk_draw_index *idx; - nk_draw_index index; - NK_ASSERT(list); - if (!list) return; - - nk_color_fv(&col.r, color); - uvb = nk_vec2(uvc.x, uva.y); - uvd = nk_vec2(uva.x, uvc.y); - b = nk_vec2(c.x, a.y); - d = nk_vec2(a.x, c.y); - - index = (nk_draw_index)list->vertex_count; - vtx = nk_draw_list_alloc_vertices(list, 4); - idx = nk_draw_list_alloc_elements(list, 6); - if (!vtx || !idx) return; - - idx[0] = (nk_draw_index)(index+0); idx[1] = (nk_draw_index)(index+1); - idx[2] = (nk_draw_index)(index+2); idx[3] = (nk_draw_index)(index+0); - idx[4] = (nk_draw_index)(index+2); idx[5] = (nk_draw_index)(index+3); - - vtx = nk_draw_vertex(vtx, &list->config, a, uva, col); - vtx = nk_draw_vertex(vtx, &list->config, b, uvb, col); - vtx = nk_draw_vertex(vtx, &list->config, c, uvc, col); - vtx = nk_draw_vertex(vtx, &list->config, d, uvd, col); -} - -NK_API void -nk_draw_list_add_image(struct nk_draw_list *list, struct nk_image texture, - struct nk_rect rect, struct nk_color color) -{ - NK_ASSERT(list); - if (!list) return; - /* push new command with given texture */ - nk_draw_list_push_image(list, texture.handle); - if (nk_image_is_subimage(&texture)) { - /* add region inside of the texture */ - struct nk_vec2 uv[2]; - uv[0].x = (float)texture.region[0]/(float)texture.w; - uv[0].y = (float)texture.region[1]/(float)texture.h; - uv[1].x = (float)(texture.region[0] + texture.region[2])/(float)texture.w; - uv[1].y = (float)(texture.region[1] + texture.region[3])/(float)texture.h; - nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), - nk_vec2(rect.x + rect.w, rect.y + rect.h), uv[0], uv[1], color); - } else nk_draw_list_push_rect_uv(list, nk_vec2(rect.x, rect.y), - nk_vec2(rect.x + rect.w, rect.y + rect.h), - nk_vec2(0.0f, 0.0f), nk_vec2(1.0f, 1.0f),color); -} - -NK_API void -nk_draw_list_add_text(struct nk_draw_list *list, const struct nk_user_font *font, - struct nk_rect rect, const char *text, int len, float font_height, - struct nk_color fg) -{ - float x = 0; - int text_len = 0; - nk_rune unicode = 0; - nk_rune next = 0; - int glyph_len = 0; - int next_glyph_len = 0; - struct nk_user_font_glyph g; - - NK_ASSERT(list); - if (!list || !len || !text) return; - if (!NK_INTERSECT(rect.x, rect.y, rect.w, rect.h, - list->clip_rect.x, list->clip_rect.y, list->clip_rect.w, list->clip_rect.h)) return; - - nk_draw_list_push_image(list, font->texture); - x = rect.x; - glyph_len = nk_utf_decode(text, &unicode, len); - if (!glyph_len) return; - - /* draw every glyph image */ - fg.a = (nk_byte)((float)fg.a * list->config.global_alpha); - while (text_len < len && glyph_len) { - float gx, gy, gh, gw; - float char_width = 0; - if (unicode == NK_UTF_INVALID) break; - - /* query currently drawn glyph information */ - next_glyph_len = nk_utf_decode(text + text_len + glyph_len, &next, (int)len - text_len); - font->query(font->userdata, font_height, &g, unicode, - (next == NK_UTF_INVALID) ? '\0' : next); - - /* calculate and draw glyph drawing rectangle and image */ - gx = x + g.offset.x; - gy = rect.y + g.offset.y; - gw = g.width; gh = g.height; - char_width = g.xadvance; - nk_draw_list_push_rect_uv(list, nk_vec2(gx,gy), nk_vec2(gx + gw, gy+ gh), - g.uv[0], g.uv[1], fg); - - /* offset next glyph */ - text_len += glyph_len; - x += char_width; - glyph_len = next_glyph_len; - unicode = next; - } -} - -NK_API void -nk_convert(struct nk_context *ctx, struct nk_buffer *cmds, - struct nk_buffer *vertices, struct nk_buffer *elements, - const struct nk_convert_config *config) -{ - const struct nk_command *cmd; - NK_ASSERT(ctx); - NK_ASSERT(cmds); - NK_ASSERT(vertices); - NK_ASSERT(elements); - NK_ASSERT(config); - NK_ASSERT(config->vertex_layout); - NK_ASSERT(config->vertex_size); - if (!ctx || !cmds || !vertices || !elements || !config || !config->vertex_layout) - return; - - nk_draw_list_setup(&ctx->draw_list, config, cmds, vertices, elements); - nk_foreach(cmd, ctx) - { -#ifdef NK_INCLUDE_COMMAND_USERDATA - ctx->draw_list.userdata = cmd->userdata; -#endif - switch (cmd->type) { - case NK_COMMAND_NOP: break; - case NK_COMMAND_SCISSOR: { - const struct nk_command_scissor *s = (const struct nk_command_scissor*)cmd; - nk_draw_list_add_clip(&ctx->draw_list, nk_rect(s->x, s->y, s->w, s->h)); - } break; - case NK_COMMAND_LINE: { - const struct nk_command_line *l = (const struct nk_command_line*)cmd; - nk_draw_list_stroke_line(&ctx->draw_list, nk_vec2(l->begin.x, l->begin.y), - nk_vec2(l->end.x, l->end.y), l->color, l->line_thickness); - } break; - case NK_COMMAND_CURVE: { - const struct nk_command_curve *q = (const struct nk_command_curve*)cmd; - nk_draw_list_stroke_curve(&ctx->draw_list, nk_vec2(q->begin.x, q->begin.y), - nk_vec2(q->ctrl[0].x, q->ctrl[0].y), nk_vec2(q->ctrl[1].x, - q->ctrl[1].y), nk_vec2(q->end.x, q->end.y), q->color, - config->curve_segment_count, q->line_thickness); - } break; - case NK_COMMAND_RECT: { - const struct nk_command_rect *r = (const struct nk_command_rect*)cmd; - nk_draw_list_stroke_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), - r->color, (float)r->rounding, r->line_thickness); - } break; - case NK_COMMAND_RECT_FILLED: { - const struct nk_command_rect_filled *r = (const struct nk_command_rect_filled*)cmd; - nk_draw_list_fill_rect(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), - r->color, (float)r->rounding); - } break; - case NK_COMMAND_RECT_MULTI_COLOR: { - const struct nk_command_rect_multi_color *r = (const struct nk_command_rect_multi_color*)cmd; - nk_draw_list_fill_rect_multi_color(&ctx->draw_list, nk_rect(r->x, r->y, r->w, r->h), - r->left, r->top, r->right, r->bottom); - } break; - case NK_COMMAND_CIRCLE: { - const struct nk_command_circle *c = (const struct nk_command_circle*)cmd; - nk_draw_list_stroke_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, - (float)c->y + (float)c->h/2), (float)c->w/2, c->color, - config->circle_segment_count, c->line_thickness); - } break; - case NK_COMMAND_CIRCLE_FILLED: { - const struct nk_command_circle_filled *c = (const struct nk_command_circle_filled *)cmd; - nk_draw_list_fill_circle(&ctx->draw_list, nk_vec2((float)c->x + (float)c->w/2, - (float)c->y + (float)c->h/2), (float)c->w/2, c->color, - config->circle_segment_count); - } break; - case NK_COMMAND_ARC: { - const struct nk_command_arc *c = (const struct nk_command_arc*)cmd; - nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); - nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, - c->a[0], c->a[1], config->arc_segment_count); - nk_draw_list_path_stroke(&ctx->draw_list, c->color, NK_STROKE_CLOSED, c->line_thickness); - } break; - case NK_COMMAND_ARC_FILLED: { - const struct nk_command_arc_filled *c = (const struct nk_command_arc_filled*)cmd; - nk_draw_list_path_line_to(&ctx->draw_list, nk_vec2(c->cx, c->cy)); - nk_draw_list_path_arc_to(&ctx->draw_list, nk_vec2(c->cx, c->cy), c->r, - c->a[0], c->a[1], config->arc_segment_count); - nk_draw_list_path_fill(&ctx->draw_list, c->color); - } break; - case NK_COMMAND_TRIANGLE: { - const struct nk_command_triangle *t = (const struct nk_command_triangle*)cmd; - nk_draw_list_stroke_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), - nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color, - t->line_thickness); - } break; - case NK_COMMAND_TRIANGLE_FILLED: { - const struct nk_command_triangle_filled *t = (const struct nk_command_triangle_filled*)cmd; - nk_draw_list_fill_triangle(&ctx->draw_list, nk_vec2(t->a.x, t->a.y), - nk_vec2(t->b.x, t->b.y), nk_vec2(t->c.x, t->c.y), t->color); - } break; - case NK_COMMAND_POLYGON: { - int i; - const struct nk_command_polygon*p = (const struct nk_command_polygon*)cmd; - for (i = 0; i < p->point_count; ++i) { - struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); - nk_draw_list_path_line_to(&ctx->draw_list, pnt); - } - nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_CLOSED, p->line_thickness); - } break; - case NK_COMMAND_POLYGON_FILLED: { - int i; - const struct nk_command_polygon_filled *p = (const struct nk_command_polygon_filled*)cmd; - for (i = 0; i < p->point_count; ++i) { - struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); - nk_draw_list_path_line_to(&ctx->draw_list, pnt); - } - nk_draw_list_path_fill(&ctx->draw_list, p->color); - } break; - case NK_COMMAND_POLYLINE: { - int i; - const struct nk_command_polyline *p = (const struct nk_command_polyline*)cmd; - for (i = 0; i < p->point_count; ++i) { - struct nk_vec2 pnt = nk_vec2((float)p->points[i].x, (float)p->points[i].y); - nk_draw_list_path_line_to(&ctx->draw_list, pnt); - } - nk_draw_list_path_stroke(&ctx->draw_list, p->color, NK_STROKE_OPEN, p->line_thickness); - } break; - case NK_COMMAND_TEXT: { - const struct nk_command_text *t = (const struct nk_command_text*)cmd; - nk_draw_list_add_text(&ctx->draw_list, t->font, nk_rect(t->x, t->y, t->w, t->h), - t->string, t->length, t->height, t->foreground); - } break; - case NK_COMMAND_IMAGE: { - const struct nk_command_image *i = (const struct nk_command_image*)cmd; - nk_draw_list_add_image(&ctx->draw_list, i->img, nk_rect(i->x, i->y, i->w, i->h), i->col); - } break; - default: break; - } - } -} - -NK_API const struct nk_draw_command* -nk__draw_begin(const struct nk_context *ctx, - const struct nk_buffer *buffer) -{return nk__draw_list_begin(&ctx->draw_list, buffer);} - -NK_API const struct nk_draw_command* -nk__draw_end(const struct nk_context *ctx, const struct nk_buffer *buffer) -{return nk__draw_list_end(&ctx->draw_list, buffer);} - -NK_API const struct nk_draw_command* -nk__draw_next(const struct nk_draw_command *cmd, - const struct nk_buffer *buffer, const struct nk_context *ctx) -{return nk__draw_list_next(cmd, buffer, &ctx->draw_list);} - -#endif - -/* - * ============================================================== - * - * FONT HANDLING - * - * =============================================================== - */ -#ifdef NK_INCLUDE_FONT_BAKING -/* ------------------------------------------------------------- - * - * RECT PACK - * - * --------------------------------------------------------------*/ -/* stb_rect_pack.h - v0.05 - public domain - rectangle packing */ -/* Sean Barrett 2014 */ -#define NK_RP__MAXVAL 0xffff -typedef unsigned short nk_rp_coord; - -struct nk_rp_rect { - /* reserved for your use: */ - int id; - /* input: */ - nk_rp_coord w, h; - /* output: */ - nk_rp_coord x, y; - int was_packed; - /* non-zero if valid packing */ -}; /* 16 bytes, nominally */ - -struct nk_rp_node { - nk_rp_coord x,y; - struct nk_rp_node *next; -}; - -struct nk_rp_context { - int width; - int height; - int align; - int init_mode; - int heuristic; - int num_nodes; - struct nk_rp_node *active_head; - struct nk_rp_node *free_head; - struct nk_rp_node extra[2]; - /* we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' */ -}; - -struct nk_rp__findresult { - int x,y; - struct nk_rp_node **prev_link; -}; - -enum NK_RP_HEURISTIC { - NK_RP_HEURISTIC_Skyline_default=0, - NK_RP_HEURISTIC_Skyline_BL_sortHeight = NK_RP_HEURISTIC_Skyline_default, - NK_RP_HEURISTIC_Skyline_BF_sortHeight -}; -enum NK_RP_INIT_STATE{NK_RP__INIT_skyline = 1}; - -NK_INTERN void -nk_rp_setup_allow_out_of_mem(struct nk_rp_context *context, int allow_out_of_mem) -{ - if (allow_out_of_mem) - /* if it's ok to run out of memory, then don't bother aligning them; */ - /* this gives better packing, but may fail due to OOM (even though */ - /* the rectangles easily fit). @TODO a smarter approach would be to only */ - /* quantize once we've hit OOM, then we could get rid of this parameter. */ - context->align = 1; - else { - /* if it's not ok to run out of memory, then quantize the widths */ - /* so that num_nodes is always enough nodes. */ - /* */ - /* I.e. num_nodes * align >= width */ - /* align >= width / num_nodes */ - /* align = ceil(width/num_nodes) */ - context->align = (context->width + context->num_nodes-1) / context->num_nodes; - } -} - -NK_INTERN void -nk_rp_init_target(struct nk_rp_context *context, int width, int height, - struct nk_rp_node *nodes, int num_nodes) -{ - int i; -#ifndef STBRP_LARGE_RECTS - NK_ASSERT(width <= 0xffff && height <= 0xffff); -#endif - - for (i=0; i < num_nodes-1; ++i) - nodes[i].next = &nodes[i+1]; - nodes[i].next = 0; - context->init_mode = NK_RP__INIT_skyline; - context->heuristic = NK_RP_HEURISTIC_Skyline_default; - context->free_head = &nodes[0]; - context->active_head = &context->extra[0]; - context->width = width; - context->height = height; - context->num_nodes = num_nodes; - nk_rp_setup_allow_out_of_mem(context, 0); - - /* node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) */ - context->extra[0].x = 0; - context->extra[0].y = 0; - context->extra[0].next = &context->extra[1]; - context->extra[1].x = (nk_rp_coord) width; - context->extra[1].y = 65535; - context->extra[1].next = 0; -} - -/* find minimum y position if it starts at x1 */ -NK_INTERN int -nk_rp__skyline_find_min_y(struct nk_rp_context *c, struct nk_rp_node *first, - int x0, int width, int *pwaste) -{ - struct nk_rp_node *node = first; - int x1 = x0 + width; - int min_y, visited_width, waste_area; - NK_ASSERT(first->x <= x0); - NK_UNUSED(c); - - NK_ASSERT(node->next->x > x0); - /* we ended up handling this in the caller for efficiency */ - NK_ASSERT(node->x <= x0); - - min_y = 0; - waste_area = 0; - visited_width = 0; - while (node->x < x1) - { - if (node->y > min_y) { - /* raise min_y higher. */ - /* we've accounted for all waste up to min_y, */ - /* but we'll now add more waste for everything we've visited */ - waste_area += visited_width * (node->y - min_y); - min_y = node->y; - /* the first time through, visited_width might be reduced */ - if (node->x < x0) - visited_width += node->next->x - x0; - else - visited_width += node->next->x - node->x; - } else { - /* add waste area */ - int under_width = node->next->x - node->x; - if (under_width + visited_width > width) - under_width = width - visited_width; - waste_area += under_width * (min_y - node->y); - visited_width += under_width; - } - node = node->next; - } - *pwaste = waste_area; - return min_y; -} - -NK_INTERN struct nk_rp__findresult -nk_rp__skyline_find_best_pos(struct nk_rp_context *c, int width, int height) -{ - int best_waste = (1<<30), best_x, best_y = (1 << 30); - struct nk_rp__findresult fr; - struct nk_rp_node **prev, *node, *tail, **best = 0; - - /* align to multiple of c->align */ - width = (width + c->align - 1); - width -= width % c->align; - NK_ASSERT(width % c->align == 0); - - node = c->active_head; - prev = &c->active_head; - while (node->x + width <= c->width) { - int y,waste; - y = nk_rp__skyline_find_min_y(c, node, node->x, width, &waste); - /* actually just want to test BL */ - if (c->heuristic == NK_RP_HEURISTIC_Skyline_BL_sortHeight) { - /* bottom left */ - if (y < best_y) { - best_y = y; - best = prev; - } - } else { - /* best-fit */ - if (y + height <= c->height) { - /* can only use it if it first vertically */ - if (y < best_y || (y == best_y && waste < best_waste)) { - best_y = y; - best_waste = waste; - best = prev; - } - } - } - prev = &node->next; - node = node->next; - } - best_x = (best == 0) ? 0 : (*best)->x; - - /* if doing best-fit (BF), we also have to try aligning right edge to each node position */ - /* */ - /* e.g, if fitting */ - /* */ - /* ____________________ */ - /* |____________________| */ - /* */ - /* into */ - /* */ - /* | | */ - /* | ____________| */ - /* |____________| */ - /* */ - /* then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned */ - /* */ - /* This makes BF take about 2x the time */ - if (c->heuristic == NK_RP_HEURISTIC_Skyline_BF_sortHeight) - { - tail = c->active_head; - node = c->active_head; - prev = &c->active_head; - /* find first node that's admissible */ - while (tail->x < width) - tail = tail->next; - while (tail) - { - int xpos = tail->x - width; - int y,waste; - NK_ASSERT(xpos >= 0); - /* find the left position that matches this */ - while (node->next->x <= xpos) { - prev = &node->next; - node = node->next; - } - NK_ASSERT(node->next->x > xpos && node->x <= xpos); - y = nk_rp__skyline_find_min_y(c, node, xpos, width, &waste); - if (y + height < c->height) { - if (y <= best_y) { - if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { - best_x = xpos; - NK_ASSERT(y <= best_y); - best_y = y; - best_waste = waste; - best = prev; - } - } - } - tail = tail->next; - } - } - fr.prev_link = best; - fr.x = best_x; - fr.y = best_y; - return fr; -} - -NK_INTERN struct nk_rp__findresult -nk_rp__skyline_pack_rectangle(struct nk_rp_context *context, int width, int height) -{ - /* find best position according to heuristic */ - struct nk_rp__findresult res = nk_rp__skyline_find_best_pos(context, width, height); - struct nk_rp_node *node, *cur; - - /* bail if: */ - /* 1. it failed */ - /* 2. the best node doesn't fit (we don't always check this) */ - /* 3. we're out of memory */ - if (res.prev_link == 0 || res.y + height > context->height || context->free_head == 0) { - res.prev_link = 0; - return res; - } - - /* on success, create new node */ - node = context->free_head; - node->x = (nk_rp_coord) res.x; - node->y = (nk_rp_coord) (res.y + height); - - context->free_head = node->next; - - /* insert the new node into the right starting point, and */ - /* let 'cur' point to the remaining nodes needing to be */ - /* stitched back in */ - cur = *res.prev_link; - if (cur->x < res.x) { - /* preserve the existing one, so start testing with the next one */ - struct nk_rp_node *next = cur->next; - cur->next = node; - cur = next; - } else { - *res.prev_link = node; - } - - /* from here, traverse cur and free the nodes, until we get to one */ - /* that shouldn't be freed */ - while (cur->next && cur->next->x <= res.x + width) { - struct nk_rp_node *next = cur->next; - /* move the current node to the free list */ - cur->next = context->free_head; - context->free_head = cur; - cur = next; - } - /* stitch the list back in */ - node->next = cur; - - if (cur->x < res.x + width) - cur->x = (nk_rp_coord) (res.x + width); - return res; -} - -NK_INTERN int -nk_rect_height_compare(const void *a, const void *b) -{ - const struct nk_rp_rect *p = (const struct nk_rp_rect *) a; - const struct nk_rp_rect *q = (const struct nk_rp_rect *) b; - if (p->h > q->h) - return -1; - if (p->h < q->h) - return 1; - return (p->w > q->w) ? -1 : (p->w < q->w); -} - -NK_INTERN int -nk_rect_original_order(const void *a, const void *b) -{ - const struct nk_rp_rect *p = (const struct nk_rp_rect *) a; - const struct nk_rp_rect *q = (const struct nk_rp_rect *) b; - return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); -} - -static void -nk_rp_qsort(struct nk_rp_rect *array, unsigned int len, int(*cmp)(const void*,const void*)) -{ - /* iterative quick sort */ - #define NK_MAX_SORT_STACK 64 - unsigned right, left = 0, stack[NK_MAX_SORT_STACK], pos = 0; - unsigned seed = len/2 * 69069+1; - for (;;) { - for (; left+1 < len; len++) { - struct nk_rp_rect pivot, tmp; - if (pos == NK_MAX_SORT_STACK) len = stack[pos = 0]; - pivot = array[left+seed%(len-left)]; - seed = seed * 69069 + 1; - stack[pos++] = len; - for (right = left-1;;) { - while (cmp(&array[++right], &pivot) < 0); - while (cmp(&pivot, &array[--len]) < 0); - if (right >= len) break; - tmp = array[right]; - array[right] = array[len]; - array[len] = tmp; - } - } - if (pos == 0) break; - left = len; - len = stack[--pos]; - } - #undef NK_MAX_SORT_STACK -} - -NK_INTERN void -nk_rp_pack_rects(struct nk_rp_context *context, struct nk_rp_rect *rects, int num_rects) -{ - int i; - /* we use the 'was_packed' field internally to allow sorting/unsorting */ - for (i=0; i < num_rects; ++i) { - rects[i].was_packed = i; - } - - /* sort according to heuristic */ - nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_height_compare); - - for (i=0; i < num_rects; ++i) { - struct nk_rp__findresult fr = nk_rp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); - if (fr.prev_link) { - rects[i].x = (nk_rp_coord) fr.x; - rects[i].y = (nk_rp_coord) fr.y; - } else { - rects[i].x = rects[i].y = NK_RP__MAXVAL; - } - } - - /* unsort */ - nk_rp_qsort(rects, (unsigned)num_rects, nk_rect_original_order); - - /* set was_packed flags */ - for (i=0; i < num_rects; ++i) - rects[i].was_packed = !(rects[i].x == NK_RP__MAXVAL && rects[i].y == NK_RP__MAXVAL); -} - -/* - * ============================================================== - * - * TRUETYPE - * - * =============================================================== - */ -/* stb_truetype.h - v1.07 - public domain */ -#define NK_TT_MAX_OVERSAMPLE 8 -#define NK_TT__OVER_MASK (NK_TT_MAX_OVERSAMPLE-1) - -struct nk_tt_bakedchar { - unsigned short x0,y0,x1,y1; - /* coordinates of bbox in bitmap */ - float xoff,yoff,xadvance; -}; - -struct nk_tt_aligned_quad{ - float x0,y0,s0,t0; /* top-left */ - float x1,y1,s1,t1; /* bottom-right */ -}; - -struct nk_tt_packedchar { - unsigned short x0,y0,x1,y1; - /* coordinates of bbox in bitmap */ - float xoff,yoff,xadvance; - float xoff2,yoff2; -}; - -struct nk_tt_pack_range { - float font_size; - int first_unicode_codepoint_in_range; - /* if non-zero, then the chars are continuous, and this is the first codepoint */ - int *array_of_unicode_codepoints; - /* if non-zero, then this is an array of unicode codepoints */ - int num_chars; - struct nk_tt_packedchar *chardata_for_range; /* output */ - unsigned char h_oversample, v_oversample; - /* don't set these, they're used internally */ -}; - -struct nk_tt_pack_context { - void *pack_info; - int width; - int height; - int stride_in_bytes; - int padding; - unsigned int h_oversample, v_oversample; - unsigned char *pixels; - void *nodes; -}; - -struct nk_tt_fontinfo { - const unsigned char* data; /* pointer to .ttf file */ - int fontstart;/* offset of start of font */ - int numGlyphs;/* number of glyphs, needed for range checking */ - int loca,head,glyf,hhea,hmtx,kern; /* table locations as offset from start of .ttf */ - int index_map; /* a cmap mapping for our chosen character encoding */ - int indexToLocFormat; /* format needed to map from glyph index to glyph */ -}; - -enum { - NK_TT_vmove=1, - NK_TT_vline, - NK_TT_vcurve -}; - -struct nk_tt_vertex { - short x,y,cx,cy; - unsigned char type,padding; -}; - -struct nk_tt__bitmap{ - int w,h,stride; - unsigned char *pixels; -}; - -struct nk_tt__hheap_chunk { - struct nk_tt__hheap_chunk *next; -}; -struct nk_tt__hheap { - struct nk_allocator alloc; - struct nk_tt__hheap_chunk *head; - void *first_free; - int num_remaining_in_head_chunk; -}; - -struct nk_tt__edge { - float x0,y0, x1,y1; - int invert; -}; - -struct nk_tt__active_edge { - struct nk_tt__active_edge *next; - float fx,fdx,fdy; - float direction; - float sy; - float ey; -}; -struct nk_tt__point {float x,y;}; - -#define NK_TT_MACSTYLE_DONTCARE 0 -#define NK_TT_MACSTYLE_BOLD 1 -#define NK_TT_MACSTYLE_ITALIC 2 -#define NK_TT_MACSTYLE_UNDERSCORE 4 -#define NK_TT_MACSTYLE_NONE 8 -/* <= not same as 0, this makes us check the bitfield is 0 */ - -enum { /* platformID */ - NK_TT_PLATFORM_ID_UNICODE =0, - NK_TT_PLATFORM_ID_MAC =1, - NK_TT_PLATFORM_ID_ISO =2, - NK_TT_PLATFORM_ID_MICROSOFT =3 -}; - -enum { /* encodingID for NK_TT_PLATFORM_ID_UNICODE */ - NK_TT_UNICODE_EID_UNICODE_1_0 =0, - NK_TT_UNICODE_EID_UNICODE_1_1 =1, - NK_TT_UNICODE_EID_ISO_10646 =2, - NK_TT_UNICODE_EID_UNICODE_2_0_BMP=3, - NK_TT_UNICODE_EID_UNICODE_2_0_FULL=4 -}; - -enum { /* encodingID for NK_TT_PLATFORM_ID_MICROSOFT */ - NK_TT_MS_EID_SYMBOL =0, - NK_TT_MS_EID_UNICODE_BMP =1, - NK_TT_MS_EID_SHIFTJIS =2, - NK_TT_MS_EID_UNICODE_FULL =10 -}; - -enum { /* encodingID for NK_TT_PLATFORM_ID_MAC; same as Script Manager codes */ - NK_TT_MAC_EID_ROMAN =0, NK_TT_MAC_EID_ARABIC =4, - NK_TT_MAC_EID_JAPANESE =1, NK_TT_MAC_EID_HEBREW =5, - NK_TT_MAC_EID_CHINESE_TRAD =2, NK_TT_MAC_EID_GREEK =6, - NK_TT_MAC_EID_KOREAN =3, NK_TT_MAC_EID_RUSSIAN =7 -}; - -enum { /* languageID for NK_TT_PLATFORM_ID_MICROSOFT; same as LCID... */ - /* problematic because there are e.g. 16 english LCIDs and 16 arabic LCIDs */ - NK_TT_MS_LANG_ENGLISH =0x0409, NK_TT_MS_LANG_ITALIAN =0x0410, - NK_TT_MS_LANG_CHINESE =0x0804, NK_TT_MS_LANG_JAPANESE =0x0411, - NK_TT_MS_LANG_DUTCH =0x0413, NK_TT_MS_LANG_KOREAN =0x0412, - NK_TT_MS_LANG_FRENCH =0x040c, NK_TT_MS_LANG_RUSSIAN =0x0419, - NK_TT_MS_LANG_GERMAN =0x0407, NK_TT_MS_LANG_SPANISH =0x0409, - NK_TT_MS_LANG_HEBREW =0x040d, NK_TT_MS_LANG_SWEDISH =0x041D -}; - -enum { /* languageID for NK_TT_PLATFORM_ID_MAC */ - NK_TT_MAC_LANG_ENGLISH =0 , NK_TT_MAC_LANG_JAPANESE =11, - NK_TT_MAC_LANG_ARABIC =12, NK_TT_MAC_LANG_KOREAN =23, - NK_TT_MAC_LANG_DUTCH =4 , NK_TT_MAC_LANG_RUSSIAN =32, - NK_TT_MAC_LANG_FRENCH =1 , NK_TT_MAC_LANG_SPANISH =6 , - NK_TT_MAC_LANG_GERMAN =2 , NK_TT_MAC_LANG_SWEDISH =5 , - NK_TT_MAC_LANG_HEBREW =10, NK_TT_MAC_LANG_CHINESE_SIMPLIFIED =33, - NK_TT_MAC_LANG_ITALIAN =3 , NK_TT_MAC_LANG_CHINESE_TRAD =19 -}; - -#define nk_ttBYTE(p) (* (const nk_byte *) (p)) -#define nk_ttCHAR(p) (* (const char *) (p)) - -#if defined(NK_BIGENDIAN) && !defined(NK_ALLOW_UNALIGNED_TRUETYPE) - #define nk_ttUSHORT(p) (* (nk_ushort *) (p)) - #define nk_ttSHORT(p) (* (nk_short *) (p)) - #define nk_ttULONG(p) (* (nk_uint *) (p)) - #define nk_ttLONG(p) (* (nk_int *) (p)) -#else - static nk_ushort nk_ttUSHORT(const nk_byte *p) { return (nk_ushort)(p[0]*256 + p[1]); } - static nk_short nk_ttSHORT(const nk_byte *p) { return (nk_short)(p[0]*256 + p[1]); } - static nk_uint nk_ttULONG(const nk_byte *p) { return (nk_uint)((p[0]<<24) + (p[1]<<16) + (p[2]<<8) + p[3]); } -#endif - -#define nk_tt_tag4(p,c0,c1,c2,c3)\ - ((p)[0] == (c0) && (p)[1] == (c1) && (p)[2] == (c2) && (p)[3] == (c3)) -#define nk_tt_tag(p,str) nk_tt_tag4(p,str[0],str[1],str[2],str[3]) - -NK_INTERN int nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc, - int glyph_index, struct nk_tt_vertex **pvertices); - -NK_INTERN nk_uint -nk_tt__find_table(const nk_byte *data, nk_uint fontstart, const char *tag) -{ - /* @OPTIMIZE: binary search */ - nk_int num_tables = nk_ttUSHORT(data+fontstart+4); - nk_uint tabledir = fontstart + 12; - nk_int i; - for (i = 0; i < num_tables; ++i) { - nk_uint loc = tabledir + (nk_uint)(16*i); - if (nk_tt_tag(data+loc+0, tag)) - return nk_ttULONG(data+loc+8); - } - return 0; -} - -NK_INTERN int -nk_tt_InitFont(struct nk_tt_fontinfo *info, const unsigned char *data2, int fontstart) -{ - nk_uint cmap, t; - nk_int i,numTables; - const nk_byte *data = (const nk_byte *) data2; - - info->data = data; - info->fontstart = fontstart; - - cmap = nk_tt__find_table(data, (nk_uint)fontstart, "cmap"); /* required */ - info->loca = (int)nk_tt__find_table(data, (nk_uint)fontstart, "loca"); /* required */ - info->head = (int)nk_tt__find_table(data, (nk_uint)fontstart, "head"); /* required */ - info->glyf = (int)nk_tt__find_table(data, (nk_uint)fontstart, "glyf"); /* required */ - info->hhea = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hhea"); /* required */ - info->hmtx = (int)nk_tt__find_table(data, (nk_uint)fontstart, "hmtx"); /* required */ - info->kern = (int)nk_tt__find_table(data, (nk_uint)fontstart, "kern"); /* not required */ - if (!cmap || !info->loca || !info->head || !info->glyf || !info->hhea || !info->hmtx) - return 0; - - t = nk_tt__find_table(data, (nk_uint)fontstart, "maxp"); - if (t) info->numGlyphs = nk_ttUSHORT(data+t+4); - else info->numGlyphs = 0xffff; - - /* find a cmap encoding table we understand *now* to avoid searching */ - /* later. (todo: could make this installable) */ - /* the same regardless of glyph. */ - numTables = nk_ttUSHORT(data + cmap + 2); - info->index_map = 0; - for (i=0; i < numTables; ++i) - { - nk_uint encoding_record = cmap + 4 + 8 * (nk_uint)i; - /* find an encoding we understand: */ - switch(nk_ttUSHORT(data+encoding_record)) { - case NK_TT_PLATFORM_ID_MICROSOFT: - switch (nk_ttUSHORT(data+encoding_record+2)) { - case NK_TT_MS_EID_UNICODE_BMP: - case NK_TT_MS_EID_UNICODE_FULL: - /* MS/Unicode */ - info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4)); - break; - default: break; - } break; - case NK_TT_PLATFORM_ID_UNICODE: - /* Mac/iOS has these */ - /* all the encodingIDs are unicode, so we don't bother to check it */ - info->index_map = (int)(cmap + nk_ttULONG(data+encoding_record+4)); - break; - default: break; - } - } - if (info->index_map == 0) - return 0; - info->indexToLocFormat = nk_ttUSHORT(data+info->head + 50); - return 1; -} - -NK_INTERN int -nk_tt_FindGlyphIndex(const struct nk_tt_fontinfo *info, int unicode_codepoint) -{ - const nk_byte *data = info->data; - nk_uint index_map = (nk_uint)info->index_map; - - nk_ushort format = nk_ttUSHORT(data + index_map + 0); - if (format == 0) { /* apple byte encoding */ - nk_int bytes = nk_ttUSHORT(data + index_map + 2); - if (unicode_codepoint < bytes-6) - return nk_ttBYTE(data + index_map + 6 + unicode_codepoint); - return 0; - } else if (format == 6) { - nk_uint first = nk_ttUSHORT(data + index_map + 6); - nk_uint count = nk_ttUSHORT(data + index_map + 8); - if ((nk_uint) unicode_codepoint >= first && (nk_uint) unicode_codepoint < first+count) - return nk_ttUSHORT(data + index_map + 10 + (unicode_codepoint - (int)first)*2); - return 0; - } else if (format == 2) { - NK_ASSERT(0); /* @TODO: high-byte mapping for japanese/chinese/korean */ - return 0; - } else if (format == 4) { /* standard mapping for windows fonts: binary search collection of ranges */ - nk_ushort segcount = nk_ttUSHORT(data+index_map+6) >> 1; - nk_ushort searchRange = nk_ttUSHORT(data+index_map+8) >> 1; - nk_ushort entrySelector = nk_ttUSHORT(data+index_map+10); - nk_ushort rangeShift = nk_ttUSHORT(data+index_map+12) >> 1; - - /* do a binary search of the segments */ - nk_uint endCount = index_map + 14; - nk_uint search = endCount; - - if (unicode_codepoint > 0xffff) - return 0; - - /* they lie from endCount .. endCount + segCount */ - /* but searchRange is the nearest power of two, so... */ - if (unicode_codepoint >= nk_ttUSHORT(data + search + rangeShift*2)) - search += (nk_uint)(rangeShift*2); - - /* now decrement to bias correctly to find smallest */ - search -= 2; - while (entrySelector) { - nk_ushort end; - searchRange >>= 1; - end = nk_ttUSHORT(data + search + searchRange*2); - if (unicode_codepoint > end) - search += (nk_uint)(searchRange*2); - --entrySelector; - } - search += 2; - - { - nk_ushort offset, start; - nk_ushort item = (nk_ushort) ((search - endCount) >> 1); - - NK_ASSERT(unicode_codepoint <= nk_ttUSHORT(data + endCount + 2*item)); - start = nk_ttUSHORT(data + index_map + 14 + segcount*2 + 2 + 2*item); - if (unicode_codepoint < start) - return 0; - - offset = nk_ttUSHORT(data + index_map + 14 + segcount*6 + 2 + 2*item); - if (offset == 0) - return (nk_ushort) (unicode_codepoint + nk_ttSHORT(data + index_map + 14 + segcount*4 + 2 + 2*item)); - - return nk_ttUSHORT(data + offset + (unicode_codepoint-start)*2 + index_map + 14 + segcount*6 + 2 + 2*item); - } - } else if (format == 12 || format == 13) { - nk_uint ngroups = nk_ttULONG(data+index_map+12); - nk_int low,high; - low = 0; high = (nk_int)ngroups; - /* Binary search the right group. */ - while (low < high) { - nk_int mid = low + ((high-low) >> 1); /* rounds down, so low <= mid < high */ - nk_uint start_char = nk_ttULONG(data+index_map+16+mid*12); - nk_uint end_char = nk_ttULONG(data+index_map+16+mid*12+4); - if ((nk_uint) unicode_codepoint < start_char) - high = mid; - else if ((nk_uint) unicode_codepoint > end_char) - low = mid+1; - else { - nk_uint start_glyph = nk_ttULONG(data+index_map+16+mid*12+8); - if (format == 12) - return (int)start_glyph + (int)unicode_codepoint - (int)start_char; - else /* format == 13 */ - return (int)start_glyph; - } - } - return 0; /* not found */ - } - /* @TODO */ - NK_ASSERT(0); - return 0; -} - -NK_INTERN void -nk_tt_setvertex(struct nk_tt_vertex *v, nk_byte type, nk_int x, nk_int y, nk_int cx, nk_int cy) -{ - v->type = type; - v->x = (nk_short) x; - v->y = (nk_short) y; - v->cx = (nk_short) cx; - v->cy = (nk_short) cy; -} - -NK_INTERN int -nk_tt__GetGlyfOffset(const struct nk_tt_fontinfo *info, int glyph_index) -{ - int g1,g2; - if (glyph_index >= info->numGlyphs) return -1; /* glyph index out of range */ - if (info->indexToLocFormat >= 2) return -1; /* unknown index->glyph map format */ - - if (info->indexToLocFormat == 0) { - g1 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2) * 2; - g2 = info->glyf + nk_ttUSHORT(info->data + info->loca + glyph_index * 2 + 2) * 2; - } else { - g1 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4); - g2 = info->glyf + (int)nk_ttULONG (info->data + info->loca + glyph_index * 4 + 4); - } - return g1==g2 ? -1 : g1; /* if length is 0, return -1 */ -} - -NK_INTERN int -nk_tt_GetGlyphBox(const struct nk_tt_fontinfo *info, int glyph_index, - int *x0, int *y0, int *x1, int *y1) -{ - int g = nk_tt__GetGlyfOffset(info, glyph_index); - if (g < 0) return 0; - - if (x0) *x0 = nk_ttSHORT(info->data + g + 2); - if (y0) *y0 = nk_ttSHORT(info->data + g + 4); - if (x1) *x1 = nk_ttSHORT(info->data + g + 6); - if (y1) *y1 = nk_ttSHORT(info->data + g + 8); - return 1; -} - -NK_INTERN int -stbtt__close_shape(struct nk_tt_vertex *vertices, int num_vertices, int was_off, - int start_off, nk_int sx, nk_int sy, nk_int scx, nk_int scy, nk_int cx, nk_int cy) -{ - if (start_off) { - if (was_off) - nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+scx)>>1, (cy+scy)>>1, cx,cy); - nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, sx,sy,scx,scy); - } else { - if (was_off) - nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve,sx,sy,cx,cy); - else - nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline,sx,sy,0,0); - } - return num_vertices; -} - -NK_INTERN int -nk_tt_GetGlyphShape(const struct nk_tt_fontinfo *info, struct nk_allocator *alloc, - int glyph_index, struct nk_tt_vertex **pvertices) -{ - nk_short numberOfContours; - const nk_byte *endPtsOfContours; - const nk_byte *data = info->data; - struct nk_tt_vertex *vertices=0; - int num_vertices=0; - int g = nk_tt__GetGlyfOffset(info, glyph_index); - *pvertices = 0; - - if (g < 0) return 0; - numberOfContours = nk_ttSHORT(data + g); - if (numberOfContours > 0) { - nk_byte flags=0,flagcount; - nk_int ins, i,j=0,m,n, next_move, was_off=0, off, start_off=0; - nk_int x,y,cx,cy,sx,sy, scx,scy; - const nk_byte *points; - endPtsOfContours = (data + g + 10); - ins = nk_ttUSHORT(data + g + 10 + numberOfContours * 2); - points = data + g + 10 + numberOfContours * 2 + 2 + ins; - - n = 1+nk_ttUSHORT(endPtsOfContours + numberOfContours*2-2); - m = n + 2*numberOfContours; /* a loose bound on how many vertices we might need */ - vertices = (struct nk_tt_vertex *)alloc->alloc(alloc->userdata, 0, (nk_size)m * sizeof(vertices[0])); - if (vertices == 0) - return 0; - - next_move = 0; - flagcount=0; - - /* in first pass, we load uninterpreted data into the allocated array */ - /* above, shifted to the end of the array so we won't overwrite it when */ - /* we create our final data starting from the front */ - off = m - n; /* starting offset for uninterpreted data, regardless of how m ends up being calculated */ - - /* first load flags */ - for (i=0; i < n; ++i) { - if (flagcount == 0) { - flags = *points++; - if (flags & 8) - flagcount = *points++; - } else --flagcount; - vertices[off+i].type = flags; - } - - /* now load x coordinates */ - x=0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - if (flags & 2) { - nk_short dx = *points++; - x += (flags & 16) ? dx : -dx; /* ??? */ - } else { - if (!(flags & 16)) { - x = x + (nk_short) (points[0]*256 + points[1]); - points += 2; - } - } - vertices[off+i].x = (nk_short) x; - } - - /* now load y coordinates */ - y=0; - for (i=0; i < n; ++i) { - flags = vertices[off+i].type; - if (flags & 4) { - nk_short dy = *points++; - y += (flags & 32) ? dy : -dy; /* ??? */ - } else { - if (!(flags & 32)) { - y = y + (nk_short) (points[0]*256 + points[1]); - points += 2; - } - } - vertices[off+i].y = (nk_short) y; - } - - /* now convert them to our format */ - num_vertices=0; - sx = sy = cx = cy = scx = scy = 0; - for (i=0; i < n; ++i) - { - flags = vertices[off+i].type; - x = (nk_short) vertices[off+i].x; - y = (nk_short) vertices[off+i].y; - - if (next_move == i) { - if (i != 0) - num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - - /* now start the new one */ - start_off = !(flags & 1); - if (start_off) { - /* if we start off with an off-curve point, then when we need to find a point on the curve */ - /* where we can start, and we need to save some state for when we wraparound. */ - scx = x; - scy = y; - if (!(vertices[off+i+1].type & 1)) { - /* next point is also a curve point, so interpolate an on-point curve */ - sx = (x + (nk_int) vertices[off+i+1].x) >> 1; - sy = (y + (nk_int) vertices[off+i+1].y) >> 1; - } else { - /* otherwise just use the next point as our start point */ - sx = (nk_int) vertices[off+i+1].x; - sy = (nk_int) vertices[off+i+1].y; - ++i; /* we're using point i+1 as the starting point, so skip it */ - } - } else { - sx = x; - sy = y; - } - nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vmove,sx,sy,0,0); - was_off = 0; - next_move = 1 + nk_ttUSHORT(endPtsOfContours+j*2); - ++j; - } else { - if (!(flags & 1)) - { /* if it's a curve */ - if (was_off) /* two off-curve control points in a row means interpolate an on-curve midpoint */ - nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, (cx+x)>>1, (cy+y)>>1, cx, cy); - cx = x; - cy = y; - was_off = 1; - } else { - if (was_off) - nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vcurve, x,y, cx, cy); - else nk_tt_setvertex(&vertices[num_vertices++], NK_TT_vline, x,y,0,0); - was_off = 0; - } - } - } - num_vertices = stbtt__close_shape(vertices, num_vertices, was_off, start_off, sx,sy,scx,scy,cx,cy); - } else if (numberOfContours == -1) { - /* Compound shapes. */ - int more = 1; - const nk_byte *comp = data + g + 10; - num_vertices = 0; - vertices = 0; - - while (more) - { - nk_ushort flags, gidx; - int comp_num_verts = 0, i; - struct nk_tt_vertex *comp_verts = 0, *tmp = 0; - float mtx[6] = {1,0,0,1,0,0}, m, n; - - flags = (nk_ushort)nk_ttSHORT(comp); comp+=2; - gidx = (nk_ushort)nk_ttSHORT(comp); comp+=2; - - if (flags & 2) { /* XY values */ - if (flags & 1) { /* shorts */ - mtx[4] = nk_ttSHORT(comp); comp+=2; - mtx[5] = nk_ttSHORT(comp); comp+=2; - } else { - mtx[4] = nk_ttCHAR(comp); comp+=1; - mtx[5] = nk_ttCHAR(comp); comp+=1; - } - } else { - /* @TODO handle matching point */ - NK_ASSERT(0); - } - if (flags & (1<<3)) { /* WE_HAVE_A_SCALE */ - mtx[0] = mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - } else if (flags & (1<<6)) { /* WE_HAVE_AN_X_AND_YSCALE */ - mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = mtx[2] = 0; - mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; - } else if (flags & (1<<7)) { /* WE_HAVE_A_TWO_BY_TWO */ - mtx[0] = nk_ttSHORT(comp)/16384.0f; comp+=2; - mtx[1] = nk_ttSHORT(comp)/16384.0f; comp+=2; - mtx[2] = nk_ttSHORT(comp)/16384.0f; comp+=2; - mtx[3] = nk_ttSHORT(comp)/16384.0f; comp+=2; - } - - /* Find transformation scales. */ - m = (float) NK_SQRT(mtx[0]*mtx[0] + mtx[1]*mtx[1]); - n = (float) NK_SQRT(mtx[2]*mtx[2] + mtx[3]*mtx[3]); - - /* Get indexed glyph. */ - comp_num_verts = nk_tt_GetGlyphShape(info, alloc, gidx, &comp_verts); - if (comp_num_verts > 0) - { - /* Transform vertices. */ - for (i = 0; i < comp_num_verts; ++i) { - struct nk_tt_vertex* v = &comp_verts[i]; - short x,y; - x=v->x; y=v->y; - v->x = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->y = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - x=v->cx; y=v->cy; - v->cx = (short)(m * (mtx[0]*x + mtx[2]*y + mtx[4])); - v->cy = (short)(n * (mtx[1]*x + mtx[3]*y + mtx[5])); - } - /* Append vertices. */ - tmp = (struct nk_tt_vertex*)alloc->alloc(alloc->userdata, 0, - (nk_size)(num_vertices+comp_num_verts)*sizeof(struct nk_tt_vertex)); - if (!tmp) { - if (vertices) alloc->free(alloc->userdata, vertices); - if (comp_verts) alloc->free(alloc->userdata, comp_verts); - return 0; - } - if (num_vertices > 0) NK_MEMCPY(tmp, vertices, (nk_size)num_vertices*sizeof(struct nk_tt_vertex)); - NK_MEMCPY(tmp+num_vertices, comp_verts, (nk_size)comp_num_verts*sizeof(struct nk_tt_vertex)); - if (vertices) alloc->free(alloc->userdata,vertices); - vertices = tmp; - alloc->free(alloc->userdata,comp_verts); - num_vertices += comp_num_verts; - } - /* More components ? */ - more = flags & (1<<5); - } - } else if (numberOfContours < 0) { - /* @TODO other compound variations? */ - NK_ASSERT(0); - } else { - /* numberOfCounters == 0, do nothing */ - } - *pvertices = vertices; - return num_vertices; -} - -NK_INTERN void -nk_tt_GetGlyphHMetrics(const struct nk_tt_fontinfo *info, int glyph_index, - int *advanceWidth, int *leftSideBearing) -{ - nk_ushort numOfLongHorMetrics = nk_ttUSHORT(info->data+info->hhea + 34); - if (glyph_index < numOfLongHorMetrics) { - if (advanceWidth) - *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index); - if (leftSideBearing) - *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*glyph_index + 2); - } else { - if (advanceWidth) - *advanceWidth = nk_ttSHORT(info->data + info->hmtx + 4*(numOfLongHorMetrics-1)); - if (leftSideBearing) - *leftSideBearing = nk_ttSHORT(info->data + info->hmtx + 4*numOfLongHorMetrics + 2*(glyph_index - numOfLongHorMetrics)); - } -} - -NK_INTERN void -nk_tt_GetFontVMetrics(const struct nk_tt_fontinfo *info, - int *ascent, int *descent, int *lineGap) -{ - if (ascent ) *ascent = nk_ttSHORT(info->data+info->hhea + 4); - if (descent) *descent = nk_ttSHORT(info->data+info->hhea + 6); - if (lineGap) *lineGap = nk_ttSHORT(info->data+info->hhea + 8); -} - -NK_INTERN float -nk_tt_ScaleForPixelHeight(const struct nk_tt_fontinfo *info, float height) -{ - int fheight = nk_ttSHORT(info->data + info->hhea + 4) - nk_ttSHORT(info->data + info->hhea + 6); - return (float) height / (float)fheight; -} - -NK_INTERN float -nk_tt_ScaleForMappingEmToPixels(const struct nk_tt_fontinfo *info, float pixels) -{ - int unitsPerEm = nk_ttUSHORT(info->data + info->head + 18); - return pixels / (float)unitsPerEm; -} - -/*------------------------------------------------------------- - * antialiasing software rasterizer - * --------------------------------------------------------------*/ -NK_INTERN void -nk_tt_GetGlyphBitmapBoxSubpixel(const struct nk_tt_fontinfo *font, - int glyph, float scale_x, float scale_y,float shift_x, float shift_y, - int *ix0, int *iy0, int *ix1, int *iy1) -{ - int x0,y0,x1,y1; - if (!nk_tt_GetGlyphBox(font, glyph, &x0,&y0,&x1,&y1)) { - /* e.g. space character */ - if (ix0) *ix0 = 0; - if (iy0) *iy0 = 0; - if (ix1) *ix1 = 0; - if (iy1) *iy1 = 0; - } else { - /* move to integral bboxes (treating pixels as little squares, what pixels get touched)? */ - if (ix0) *ix0 = nk_ifloorf((float)x0 * scale_x + shift_x); - if (iy0) *iy0 = nk_ifloorf((float)-y1 * scale_y + shift_y); - if (ix1) *ix1 = nk_iceilf ((float)x1 * scale_x + shift_x); - if (iy1) *iy1 = nk_iceilf ((float)-y0 * scale_y + shift_y); - } -} - -NK_INTERN void -nk_tt_GetGlyphBitmapBox(const struct nk_tt_fontinfo *font, int glyph, - float scale_x, float scale_y, int *ix0, int *iy0, int *ix1, int *iy1) -{ - nk_tt_GetGlyphBitmapBoxSubpixel(font, glyph, scale_x, scale_y,0.0f,0.0f, ix0, iy0, ix1, iy1); -} - -/*------------------------------------------------------------- - * Rasterizer - * --------------------------------------------------------------*/ -NK_INTERN void* -nk_tt__hheap_alloc(struct nk_tt__hheap *hh, nk_size size) -{ - if (hh->first_free) { - void *p = hh->first_free; - hh->first_free = * (void **) p; - return p; - } else { - if (hh->num_remaining_in_head_chunk == 0) { - int count = (size < 32 ? 2000 : size < 128 ? 800 : 100); - struct nk_tt__hheap_chunk *c = (struct nk_tt__hheap_chunk *) - hh->alloc.alloc(hh->alloc.userdata, 0, - sizeof(struct nk_tt__hheap_chunk) + size * (nk_size)count); - if (c == 0) return 0; - c->next = hh->head; - hh->head = c; - hh->num_remaining_in_head_chunk = count; - } - --hh->num_remaining_in_head_chunk; - return (char *) (hh->head) + size * (nk_size)hh->num_remaining_in_head_chunk; - } -} - -NK_INTERN void -nk_tt__hheap_free(struct nk_tt__hheap *hh, void *p) -{ - *(void **) p = hh->first_free; - hh->first_free = p; -} - -NK_INTERN void -nk_tt__hheap_cleanup(struct nk_tt__hheap *hh) -{ - struct nk_tt__hheap_chunk *c = hh->head; - while (c) { - struct nk_tt__hheap_chunk *n = c->next; - hh->alloc.free(hh->alloc.userdata, c); - c = n; - } -} - -NK_INTERN struct nk_tt__active_edge* -nk_tt__new_active(struct nk_tt__hheap *hh, struct nk_tt__edge *e, - int off_x, float start_point) -{ - struct nk_tt__active_edge *z = (struct nk_tt__active_edge *) - nk_tt__hheap_alloc(hh, sizeof(*z)); - float dxdy = (e->x1 - e->x0) / (e->y1 - e->y0); - /*STBTT_assert(e->y0 <= start_point); */ - if (!z) return z; - z->fdx = dxdy; - z->fdy = (dxdy != 0) ? (1/dxdy): 0; - z->fx = e->x0 + dxdy * (start_point - e->y0); - z->fx -= (float)off_x; - z->direction = e->invert ? 1.0f : -1.0f; - z->sy = e->y0; - z->ey = e->y1; - z->next = 0; - return z; -} - -NK_INTERN void -nk_tt__handle_clipped_edge(float *scanline, int x, struct nk_tt__active_edge *e, - float x0, float y0, float x1, float y1) -{ - if (y0 == y1) return; - NK_ASSERT(y0 < y1); - NK_ASSERT(e->sy <= e->ey); - if (y0 > e->ey) return; - if (y1 < e->sy) return; - if (y0 < e->sy) { - x0 += (x1-x0) * (e->sy - y0) / (y1-y0); - y0 = e->sy; - } - if (y1 > e->ey) { - x1 += (x1-x0) * (e->ey - y1) / (y1-y0); - y1 = e->ey; - } - - if (x0 == x) NK_ASSERT(x1 <= x+1); - else if (x0 == x+1) NK_ASSERT(x1 >= x); - else if (x0 <= x) NK_ASSERT(x1 <= x); - else if (x0 >= x+1) NK_ASSERT(x1 >= x+1); - else NK_ASSERT(x1 >= x && x1 <= x+1); - - if (x0 <= x && x1 <= x) - scanline[x] += e->direction * (y1-y0); - else if (x0 >= x+1 && x1 >= x+1); - else { - NK_ASSERT(x0 >= x && x0 <= x+1 && x1 >= x && x1 <= x+1); - /* coverage = 1 - average x position */ - scanline[x] += (float)e->direction * (float)(y1-y0) * (1.0f-((x0-(float)x)+(x1-(float)x))/2.0f); - } -} - -NK_INTERN void -nk_tt__fill_active_edges_new(float *scanline, float *scanline_fill, int len, - struct nk_tt__active_edge *e, float y_top) -{ - float y_bottom = y_top+1; - while (e) - { - /* brute force every pixel */ - /* compute intersection points with top & bottom */ - NK_ASSERT(e->ey >= y_top); - if (e->fdx == 0) { - float x0 = e->fx; - if (x0 < len) { - if (x0 >= 0) { - nk_tt__handle_clipped_edge(scanline,(int) x0,e, x0,y_top, x0,y_bottom); - nk_tt__handle_clipped_edge(scanline_fill-1,(int) x0+1,e, x0,y_top, x0,y_bottom); - } else { - nk_tt__handle_clipped_edge(scanline_fill-1,0,e, x0,y_top, x0,y_bottom); - } - } - } else { - float x0 = e->fx; - float dx = e->fdx; - float xb = x0 + dx; - float x_top, x_bottom; - float y0,y1; - float dy = e->fdy; - NK_ASSERT(e->sy <= y_bottom && e->ey >= y_top); - - /* compute endpoints of line segment clipped to this scanline (if the */ - /* line segment starts on this scanline. x0 is the intersection of the */ - /* line with y_top, but that may be off the line segment. */ - if (e->sy > y_top) { - x_top = x0 + dx * (e->sy - y_top); - y0 = e->sy; - } else { - x_top = x0; - y0 = y_top; - } - - if (e->ey < y_bottom) { - x_bottom = x0 + dx * (e->ey - y_top); - y1 = e->ey; - } else { - x_bottom = xb; - y1 = y_bottom; - } - - if (x_top >= 0 && x_bottom >= 0 && x_top < len && x_bottom < len) - { - /* from here on, we don't have to range check x values */ - if ((int) x_top == (int) x_bottom) { - float height; - /* simple case, only spans one pixel */ - int x = (int) x_top; - height = y1 - y0; - NK_ASSERT(x >= 0 && x < len); - scanline[x] += e->direction * (1.0f-(((float)x_top - (float)x) + ((float)x_bottom-(float)x))/2.0f) * (float)height; - scanline_fill[x] += e->direction * (float)height; /* everything right of this pixel is filled */ - } else { - int x,x1,x2; - float y_crossing, step, sign, area; - /* covers 2+ pixels */ - if (x_top > x_bottom) - { - /* flip scanline vertically; signed area is the same */ - float t; - y0 = y_bottom - (y0 - y_top); - y1 = y_bottom - (y1 - y_top); - t = y0; y0 = y1; y1 = t; - t = x_bottom; x_bottom = x_top; x_top = t; - dx = -dx; - dy = -dy; - t = x0; x0 = xb; xb = t; - } - - x1 = (int) x_top; - x2 = (int) x_bottom; - /* compute intersection with y axis at x1+1 */ - y_crossing = ((float)x1+1 - (float)x0) * (float)dy + (float)y_top; - - sign = e->direction; - /* area of the rectangle covered from y0..y_crossing */ - area = sign * (y_crossing-y0); - /* area of the triangle (x_top,y0), (x+1,y0), (x+1,y_crossing) */ - scanline[x1] += area * (1.0f-((float)((float)x_top - (float)x1)+(float)(x1+1-x1))/2.0f); - - step = sign * dy; - for (x = x1+1; x < x2; ++x) { - scanline[x] += area + step/2; - area += step; - } - y_crossing += (float)dy * (float)(x2 - (x1+1)); - - scanline[x2] += area + sign * (1.0f-((float)(x2-x2)+((float)x_bottom-(float)x2))/2.0f) * (y1-y_crossing); - scanline_fill[x2] += sign * (y1-y0); - } - } - else - { - /* if edge goes outside of box we're drawing, we require */ - /* clipping logic. since this does not match the intended use */ - /* of this library, we use a different, very slow brute */ - /* force implementation */ - int x; - for (x=0; x < len; ++x) - { - /* cases: */ - /* */ - /* there can be up to two intersections with the pixel. any intersection */ - /* with left or right edges can be handled by splitting into two (or three) */ - /* regions. intersections with top & bottom do not necessitate case-wise logic. */ - /* */ - /* the old way of doing this found the intersections with the left & right edges, */ - /* then used some simple logic to produce up to three segments in sorted order */ - /* from top-to-bottom. however, this had a problem: if an x edge was epsilon */ - /* across the x border, then the corresponding y position might not be distinct */ - /* from the other y segment, and it might ignored as an empty segment. to avoid */ - /* that, we need to explicitly produce segments based on x positions. */ - - /* rename variables to clear pairs */ - float ya = y_top; - float x1 = (float) (x); - float x2 = (float) (x+1); - float x3 = xb; - float y3 = y_bottom; - float yb,y2; - - yb = ((float)x - x0) / dx + y_top; - y2 = ((float)x+1 - x0) / dx + y_top; - - if (x0 < x1 && x3 > x2) { /* three segments descending down-right */ - nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); - nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x2,y2); - nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else if (x3 < x1 && x0 > x2) { /* three segments descending down-left */ - nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); - nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x1,yb); - nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); - } else if (x0 < x1 && x3 > x1) { /* two segments across x, down-right */ - nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); - nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); - } else if (x3 < x1 && x0 > x1) { /* two segments across x, down-left */ - nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x1,yb); - nk_tt__handle_clipped_edge(scanline,x,e, x1,yb, x3,y3); - } else if (x0 < x2 && x3 > x2) { /* two segments across x+1, down-right */ - nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); - nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else if (x3 < x2 && x0 > x2) { /* two segments across x+1, down-left */ - nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x2,y2); - nk_tt__handle_clipped_edge(scanline,x,e, x2,y2, x3,y3); - } else { /* one segment */ - nk_tt__handle_clipped_edge(scanline,x,e, x0,ya, x3,y3); - } - } - } - } - e = e->next; - } -} - -/* directly AA rasterize edges w/o supersampling */ -NK_INTERN void -nk_tt__rasterize_sorted_edges(struct nk_tt__bitmap *result, struct nk_tt__edge *e, - int n, int vsubsample, int off_x, int off_y, struct nk_allocator *alloc) -{ - struct nk_tt__hheap hh; - struct nk_tt__active_edge *active = 0; - int y,j=0, i; - float scanline_data[129], *scanline, *scanline2; - - NK_UNUSED(vsubsample); - nk_zero_struct(hh); - hh.alloc = *alloc; - - if (result->w > 64) - scanline = (float *) alloc->alloc(alloc->userdata,0, (nk_size)(result->w*2+1) * sizeof(float)); - else scanline = scanline_data; - - scanline2 = scanline + result->w; - y = off_y; - e[n].y0 = (float) (off_y + result->h) + 1; - - while (j < result->h) - { - /* find center of pixel for this scanline */ - float scan_y_top = (float)y + 0.0f; - float scan_y_bottom = (float)y + 1.0f; - struct nk_tt__active_edge **step = &active; - - NK_MEMSET(scanline , 0, (nk_size)result->w*sizeof(scanline[0])); - NK_MEMSET(scanline2, 0, (nk_size)(result->w+1)*sizeof(scanline[0])); - - /* update all active edges; */ - /* remove all active edges that terminate before the top of this scanline */ - while (*step) { - struct nk_tt__active_edge * z = *step; - if (z->ey <= scan_y_top) { - *step = z->next; /* delete from list */ - NK_ASSERT(z->direction); - z->direction = 0; - nk_tt__hheap_free(&hh, z); - } else { - step = &((*step)->next); /* advance through list */ - } - } - - /* insert all edges that start before the bottom of this scanline */ - while (e->y0 <= scan_y_bottom) { - if (e->y0 != e->y1) { - struct nk_tt__active_edge *z = nk_tt__new_active(&hh, e, off_x, scan_y_top); - if (z != 0) { - NK_ASSERT(z->ey >= scan_y_top); - /* insert at front */ - z->next = active; - active = z; - } - } - ++e; - } - - /* now process all active edges */ - if (active) - nk_tt__fill_active_edges_new(scanline, scanline2+1, result->w, active, scan_y_top); - - { - float sum = 0; - for (i=0; i < result->w; ++i) { - float k; - int m; - sum += scanline2[i]; - k = scanline[i] + sum; - k = (float) NK_ABS(k) * 255.0f + 0.5f; - m = (int) k; - if (m > 255) m = 255; - result->pixels[j*result->stride + i] = (unsigned char) m; - } - } - /* advance all the edges */ - step = &active; - while (*step) { - struct nk_tt__active_edge *z = *step; - z->fx += z->fdx; /* advance to position for current scanline */ - step = &((*step)->next); /* advance through list */ - } - ++y; - ++j; - } - nk_tt__hheap_cleanup(&hh); - if (scanline != scanline_data) - alloc->free(alloc->userdata, scanline); -} - -#define NK_TT__COMPARE(a,b) ((a)->y0 < (b)->y0) -NK_INTERN void -nk_tt__sort_edges_ins_sort(struct nk_tt__edge *p, int n) -{ - int i,j; - for (i=1; i < n; ++i) { - struct nk_tt__edge t = p[i], *a = &t; - j = i; - while (j > 0) { - struct nk_tt__edge *b = &p[j-1]; - int c = NK_TT__COMPARE(a,b); - if (!c) break; - p[j] = p[j-1]; - --j; - } - if (i != j) - p[j] = t; - } -} - -NK_INTERN void -nk_tt__sort_edges_quicksort(struct nk_tt__edge *p, int n) -{ - /* threshold for transitioning to insertion sort */ - while (n > 12) { - struct nk_tt__edge t; - int c01,c12,c,m,i,j; - - /* compute median of three */ - m = n >> 1; - c01 = NK_TT__COMPARE(&p[0],&p[m]); - c12 = NK_TT__COMPARE(&p[m],&p[n-1]); - - /* if 0 >= mid >= end, or 0 < mid < end, then use mid */ - if (c01 != c12) { - /* otherwise, we'll need to swap something else to middle */ - int z; - c = NK_TT__COMPARE(&p[0],&p[n-1]); - /* 0>mid && midn => n; 0 0 */ - /* 0n: 0>n => 0; 0 n */ - z = (c == c12) ? 0 : n-1; - t = p[z]; - p[z] = p[m]; - p[m] = t; - } - - /* now p[m] is the median-of-three */ - /* swap it to the beginning so it won't move around */ - t = p[0]; - p[0] = p[m]; - p[m] = t; - - /* partition loop */ - i=1; - j=n-1; - for(;;) { - /* handling of equality is crucial here */ - /* for sentinels & efficiency with duplicates */ - for (;;++i) { - if (!NK_TT__COMPARE(&p[i], &p[0])) break; - } - for (;;--j) { - if (!NK_TT__COMPARE(&p[0], &p[j])) break; - } - - /* make sure we haven't crossed */ - if (i >= j) break; - t = p[i]; - p[i] = p[j]; - p[j] = t; - - ++i; - --j; - - } - - /* recurse on smaller side, iterate on larger */ - if (j < (n-i)) { - nk_tt__sort_edges_quicksort(p,j); - p = p+i; - n = n-i; - } else { - nk_tt__sort_edges_quicksort(p+i, n-i); - n = j; - } - } -} - -NK_INTERN void -nk_tt__sort_edges(struct nk_tt__edge *p, int n) -{ - nk_tt__sort_edges_quicksort(p, n); - nk_tt__sort_edges_ins_sort(p, n); -} - -NK_INTERN void -nk_tt__rasterize(struct nk_tt__bitmap *result, struct nk_tt__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, - struct nk_allocator *alloc) -{ - float y_scale_inv = invert ? -scale_y : scale_y; - struct nk_tt__edge *e; - int n,i,j,k,m; - int vsubsample = 1; - /* vsubsample should divide 255 evenly; otherwise we won't reach full opacity */ - - /* now we have to blow out the windings into explicit edge lists */ - n = 0; - for (i=0; i < windings; ++i) - n += wcount[i]; - - e = (struct nk_tt__edge*) - alloc->alloc(alloc->userdata, 0,(sizeof(*e) * (nk_size)(n+1))); - if (e == 0) return; - n = 0; - - m=0; - for (i=0; i < windings; ++i) - { - struct nk_tt__point *p = pts + m; - m += wcount[i]; - j = wcount[i]-1; - for (k=0; k < wcount[i]; j=k++) { - int a=k,b=j; - /* skip the edge if horizontal */ - if (p[j].y == p[k].y) - continue; - - /* add edge from j to k to the list */ - e[n].invert = 0; - if (invert ? p[j].y > p[k].y : p[j].y < p[k].y) { - e[n].invert = 1; - a=j,b=k; - } - e[n].x0 = p[a].x * scale_x + shift_x; - e[n].y0 = (p[a].y * y_scale_inv + shift_y) * (float)vsubsample; - e[n].x1 = p[b].x * scale_x + shift_x; - e[n].y1 = (p[b].y * y_scale_inv + shift_y) * (float)vsubsample; - ++n; - } - } - - /* now sort the edges by their highest point (should snap to integer, and then by x) */ - /*STBTT_sort(e, n, sizeof(e[0]), stbtt__edge_compare); */ - nk_tt__sort_edges(e, n); - /* now, traverse the scanlines and find the intersections on each scanline, use xor winding rule */ - nk_tt__rasterize_sorted_edges(result, e, n, vsubsample, off_x, off_y, alloc); - alloc->free(alloc->userdata, e); -} - -NK_INTERN void -nk_tt__add_point(struct nk_tt__point *points, int n, float x, float y) -{ - if (!points) return; /* during first pass, it's unallocated */ - points[n].x = x; - points[n].y = y; -} - -NK_INTERN int -nk_tt__tesselate_curve(struct nk_tt__point *points, int *num_points, - float x0, float y0, float x1, float y1, float x2, float y2, - float objspace_flatness_squared, int n) -{ - /* tesselate until threshold p is happy... - * @TODO warped to compensate for non-linear stretching */ - /* midpoint */ - float mx = (x0 + 2*x1 + x2)/4; - float my = (y0 + 2*y1 + y2)/4; - /* versus directly drawn line */ - float dx = (x0+x2)/2 - mx; - float dy = (y0+y2)/2 - my; - if (n > 16) /* 65536 segments on one curve better be enough! */ - return 1; - - /* half-pixel error allowed... need to be smaller if AA */ - if (dx*dx+dy*dy > objspace_flatness_squared) { - nk_tt__tesselate_curve(points, num_points, x0,y0, - (x0+x1)/2.0f,(y0+y1)/2.0f, mx,my, objspace_flatness_squared,n+1); - nk_tt__tesselate_curve(points, num_points, mx,my, - (x1+x2)/2.0f,(y1+y2)/2.0f, x2,y2, objspace_flatness_squared,n+1); - } else { - nk_tt__add_point(points, *num_points,x2,y2); - *num_points = *num_points+1; - } - return 1; -} - -/* returns number of contours */ -NK_INTERN struct nk_tt__point* -nk_tt_FlattenCurves(struct nk_tt_vertex *vertices, int num_verts, - float objspace_flatness, int **contour_lengths, int *num_contours, - struct nk_allocator *alloc) -{ - struct nk_tt__point *points=0; - int num_points=0; - float objspace_flatness_squared = objspace_flatness * objspace_flatness; - int i; - int n=0; - int start=0; - int pass; - - /* count how many "moves" there are to get the contour count */ - for (i=0; i < num_verts; ++i) - if (vertices[i].type == NK_TT_vmove) ++n; - - *num_contours = n; - if (n == 0) return 0; - - *contour_lengths = (int *) - alloc->alloc(alloc->userdata,0, (sizeof(**contour_lengths) * (nk_size)n)); - if (*contour_lengths == 0) { - *num_contours = 0; - return 0; - } - - /* make two passes through the points so we don't need to realloc */ - for (pass=0; pass < 2; ++pass) - { - float x=0,y=0; - if (pass == 1) { - points = (struct nk_tt__point *) - alloc->alloc(alloc->userdata,0, (nk_size)num_points * sizeof(points[0])); - if (points == 0) goto error; - } - num_points = 0; - n= -1; - - for (i=0; i < num_verts; ++i) - { - switch (vertices[i].type) { - case NK_TT_vmove: - /* start the next contour */ - if (n >= 0) - (*contour_lengths)[n] = num_points - start; - ++n; - start = num_points; - - x = vertices[i].x, y = vertices[i].y; - nk_tt__add_point(points, num_points++, x,y); - break; - case NK_TT_vline: - x = vertices[i].x, y = vertices[i].y; - nk_tt__add_point(points, num_points++, x, y); - break; - case NK_TT_vcurve: - nk_tt__tesselate_curve(points, &num_points, x,y, - vertices[i].cx, vertices[i].cy, - vertices[i].x, vertices[i].y, - objspace_flatness_squared, 0); - x = vertices[i].x, y = vertices[i].y; - break; - default: break; - } - } - (*contour_lengths)[n] = num_points - start; - } - return points; - -error: - alloc->free(alloc->userdata, points); - alloc->free(alloc->userdata, *contour_lengths); - *contour_lengths = 0; - *num_contours = 0; - return 0; -} - -NK_INTERN void -nk_tt_Rasterize(struct nk_tt__bitmap *result, float flatness_in_pixels, - struct nk_tt_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, struct nk_allocator *alloc) -{ - float scale = scale_x > scale_y ? scale_y : scale_x; - int winding_count, *winding_lengths; - struct nk_tt__point *windings = nk_tt_FlattenCurves(vertices, num_verts, - flatness_in_pixels / scale, &winding_lengths, &winding_count, alloc); - - NK_ASSERT(alloc); - if (windings) { - nk_tt__rasterize(result, windings, winding_lengths, winding_count, - scale_x, scale_y, shift_x, shift_y, x_off, y_off, invert, alloc); - alloc->free(alloc->userdata, winding_lengths); - alloc->free(alloc->userdata, windings); - } -} - -NK_INTERN void -nk_tt_MakeGlyphBitmapSubpixel(const struct nk_tt_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, struct nk_allocator *alloc) -{ - int ix0,iy0; - struct nk_tt_vertex *vertices; - int num_verts = nk_tt_GetGlyphShape(info, alloc, glyph, &vertices); - struct nk_tt__bitmap gbm; - - nk_tt_GetGlyphBitmapBoxSubpixel(info, glyph, scale_x, scale_y, shift_x, - shift_y, &ix0,&iy0,0,0); - gbm.pixels = output; - gbm.w = out_w; - gbm.h = out_h; - gbm.stride = out_stride; - - if (gbm.w && gbm.h) - nk_tt_Rasterize(&gbm, 0.35f, vertices, num_verts, scale_x, scale_y, - shift_x, shift_y, ix0,iy0, 1, alloc); - alloc->free(alloc->userdata, vertices); -} - -/*------------------------------------------------------------- - * Bitmap baking - * --------------------------------------------------------------*/ -NK_INTERN int -nk_tt_PackBegin(struct nk_tt_pack_context *spc, unsigned char *pixels, - int pw, int ph, int stride_in_bytes, int padding, struct nk_allocator *alloc) -{ - int num_nodes = pw - padding; - struct nk_rp_context *context = (struct nk_rp_context *) - alloc->alloc(alloc->userdata,0, sizeof(*context)); - struct nk_rp_node *nodes = (struct nk_rp_node*) - alloc->alloc(alloc->userdata,0, (sizeof(*nodes ) * (nk_size)num_nodes)); - - if (context == 0 || nodes == 0) { - if (context != 0) alloc->free(alloc->userdata, context); - if (nodes != 0) alloc->free(alloc->userdata, nodes); - return 0; - } - - spc->width = pw; - spc->height = ph; - spc->pixels = pixels; - spc->pack_info = context; - spc->nodes = nodes; - spc->padding = padding; - spc->stride_in_bytes = (stride_in_bytes != 0) ? stride_in_bytes : pw; - spc->h_oversample = 1; - spc->v_oversample = 1; - - nk_rp_init_target(context, pw-padding, ph-padding, nodes, num_nodes); - if (pixels) - NK_MEMSET(pixels, 0, (nk_size)(pw*ph)); /* background of 0 around pixels */ - return 1; -} - -NK_INTERN void -nk_tt_PackEnd(struct nk_tt_pack_context *spc, struct nk_allocator *alloc) -{ - alloc->free(alloc->userdata, spc->nodes); - alloc->free(alloc->userdata, spc->pack_info); -} - -NK_INTERN void -nk_tt_PackSetOversampling(struct nk_tt_pack_context *spc, - unsigned int h_oversample, unsigned int v_oversample) -{ - NK_ASSERT(h_oversample <= NK_TT_MAX_OVERSAMPLE); - NK_ASSERT(v_oversample <= NK_TT_MAX_OVERSAMPLE); - if (h_oversample <= NK_TT_MAX_OVERSAMPLE) - spc->h_oversample = h_oversample; - if (v_oversample <= NK_TT_MAX_OVERSAMPLE) - spc->v_oversample = v_oversample; -} - -NK_INTERN void -nk_tt__h_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, - int kernel_width) -{ - unsigned char buffer[NK_TT_MAX_OVERSAMPLE]; - int safe_w = w - kernel_width; - int j; - - for (j=0; j < h; ++j) - { - int i; - unsigned int total; - NK_MEMSET(buffer, 0, (nk_size)kernel_width); - - total = 0; - - /* make kernel_width a constant in common cases so compiler can optimize out the divide */ - switch (kernel_width) { - case 2: - for (i=0; i <= safe_w; ++i) { - total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); - buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 2); - } - break; - case 3: - for (i=0; i <= safe_w; ++i) { - total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); - buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 3); - } - break; - case 4: - for (i=0; i <= safe_w; ++i) { - total += (unsigned int)pixels[i] - buffer[i & NK_TT__OVER_MASK]; - buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 4); - } - break; - case 5: - for (i=0; i <= safe_w; ++i) { - total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); - buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / 5); - } - break; - default: - for (i=0; i <= safe_w; ++i) { - total += (unsigned int)(pixels[i] - buffer[i & NK_TT__OVER_MASK]); - buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i]; - pixels[i] = (unsigned char) (total / (unsigned int)kernel_width); - } - break; - } - - for (; i < w; ++i) { - NK_ASSERT(pixels[i] == 0); - total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]); - pixels[i] = (unsigned char) (total / (unsigned int)kernel_width); - } - pixels += stride_in_bytes; - } -} - -NK_INTERN void -nk_tt__v_prefilter(unsigned char *pixels, int w, int h, int stride_in_bytes, - int kernel_width) -{ - unsigned char buffer[NK_TT_MAX_OVERSAMPLE]; - int safe_h = h - kernel_width; - int j; - - for (j=0; j < w; ++j) - { - int i; - unsigned int total; - NK_MEMSET(buffer, 0, (nk_size)kernel_width); - - total = 0; - - /* make kernel_width a constant in common cases so compiler can optimize out the divide */ - switch (kernel_width) { - case 2: - for (i=0; i <= safe_h; ++i) { - total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); - buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 2); - } - break; - case 3: - for (i=0; i <= safe_h; ++i) { - total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); - buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 3); - } - break; - case 4: - for (i=0; i <= safe_h; ++i) { - total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); - buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 4); - } - break; - case 5: - for (i=0; i <= safe_h; ++i) { - total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); - buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / 5); - } - break; - default: - for (i=0; i <= safe_h; ++i) { - total += (unsigned int)(pixels[i*stride_in_bytes] - buffer[i & NK_TT__OVER_MASK]); - buffer[(i+kernel_width) & NK_TT__OVER_MASK] = pixels[i*stride_in_bytes]; - pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width); - } - break; - } - - for (; i < h; ++i) { - NK_ASSERT(pixels[i*stride_in_bytes] == 0); - total -= (unsigned int)(buffer[i & NK_TT__OVER_MASK]); - pixels[i*stride_in_bytes] = (unsigned char) (total / (unsigned int)kernel_width); - } - pixels += 1; - } -} - -NK_INTERN float -nk_tt__oversample_shift(int oversample) -{ - if (!oversample) - return 0.0f; - - /* The prefilter is a box filter of width "oversample", */ - /* which shifts phase by (oversample - 1)/2 pixels in */ - /* oversampled space. We want to shift in the opposite */ - /* direction to counter this. */ - return (float)-(oversample - 1) / (2.0f * (float)oversample); -} - -/* rects array must be big enough to accommodate all characters in the given ranges */ -NK_INTERN int -nk_tt_PackFontRangesGatherRects(struct nk_tt_pack_context *spc, - struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges, - int num_ranges, struct nk_rp_rect *rects) -{ - int i,j,k; - k = 0; - - for (i=0; i < num_ranges; ++i) { - float fh = ranges[i].font_size; - float scale = (fh > 0) ? nk_tt_ScaleForPixelHeight(info, fh): - nk_tt_ScaleForMappingEmToPixels(info, -fh); - ranges[i].h_oversample = (unsigned char) spc->h_oversample; - ranges[i].v_oversample = (unsigned char) spc->v_oversample; - for (j=0; j < ranges[i].num_chars; ++j) { - int x0,y0,x1,y1; - int codepoint = ranges[i].first_unicode_codepoint_in_range ? - ranges[i].first_unicode_codepoint_in_range + j : - ranges[i].array_of_unicode_codepoints[j]; - - int glyph = nk_tt_FindGlyphIndex(info, codepoint); - nk_tt_GetGlyphBitmapBoxSubpixel(info,glyph, scale * (float)spc->h_oversample, - scale * (float)spc->v_oversample, 0,0, &x0,&y0,&x1,&y1); - rects[k].w = (nk_rp_coord) (x1-x0 + spc->padding + (int)spc->h_oversample-1); - rects[k].h = (nk_rp_coord) (y1-y0 + spc->padding + (int)spc->v_oversample-1); - ++k; - } - } - return k; -} - -NK_INTERN int -nk_tt_PackFontRangesRenderIntoRects(struct nk_tt_pack_context *spc, - struct nk_tt_fontinfo *info, struct nk_tt_pack_range *ranges, - int num_ranges, struct nk_rp_rect *rects, struct nk_allocator *alloc) -{ - int i,j,k, return_value = 1; - /* save current values */ - int old_h_over = (int)spc->h_oversample; - int old_v_over = (int)spc->v_oversample; - /* rects array must be big enough to accommodate all characters in the given ranges */ - - k = 0; - for (i=0; i < num_ranges; ++i) - { - float fh = ranges[i].font_size; - float recip_h,recip_v,sub_x,sub_y; - float scale = fh > 0 ? nk_tt_ScaleForPixelHeight(info, fh): - nk_tt_ScaleForMappingEmToPixels(info, -fh); - - spc->h_oversample = ranges[i].h_oversample; - spc->v_oversample = ranges[i].v_oversample; - - recip_h = 1.0f / (float)spc->h_oversample; - recip_v = 1.0f / (float)spc->v_oversample; - - sub_x = nk_tt__oversample_shift((int)spc->h_oversample); - sub_y = nk_tt__oversample_shift((int)spc->v_oversample); - - for (j=0; j < ranges[i].num_chars; ++j) - { - struct nk_rp_rect *r = &rects[k]; - if (r->was_packed) - { - struct nk_tt_packedchar *bc = &ranges[i].chardata_for_range[j]; - int advance, lsb, x0,y0,x1,y1; - int codepoint = ranges[i].first_unicode_codepoint_in_range ? - ranges[i].first_unicode_codepoint_in_range + j : - ranges[i].array_of_unicode_codepoints[j]; - int glyph = nk_tt_FindGlyphIndex(info, codepoint); - nk_rp_coord pad = (nk_rp_coord) spc->padding; - - /* pad on left and top */ - r->x = (nk_rp_coord)((int)r->x + (int)pad); - r->y = (nk_rp_coord)((int)r->y + (int)pad); - r->w = (nk_rp_coord)((int)r->w - (int)pad); - r->h = (nk_rp_coord)((int)r->h - (int)pad); - - nk_tt_GetGlyphHMetrics(info, glyph, &advance, &lsb); - nk_tt_GetGlyphBitmapBox(info, glyph, scale * (float)spc->h_oversample, - (scale * (float)spc->v_oversample), &x0,&y0,&x1,&y1); - nk_tt_MakeGlyphBitmapSubpixel(info, spc->pixels + r->x + r->y*spc->stride_in_bytes, - (int)(r->w - spc->h_oversample+1), (int)(r->h - spc->v_oversample+1), - spc->stride_in_bytes, scale * (float)spc->h_oversample, - scale * (float)spc->v_oversample, 0,0, glyph, alloc); - - if (spc->h_oversample > 1) - nk_tt__h_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, (int)spc->h_oversample); - - if (spc->v_oversample > 1) - nk_tt__v_prefilter(spc->pixels + r->x + r->y*spc->stride_in_bytes, - r->w, r->h, spc->stride_in_bytes, (int)spc->v_oversample); - - bc->x0 = (nk_ushort) r->x; - bc->y0 = (nk_ushort) r->y; - bc->x1 = (nk_ushort) (r->x + r->w); - bc->y1 = (nk_ushort) (r->y + r->h); - bc->xadvance = scale * (float)advance; - bc->xoff = (float) x0 * recip_h + sub_x; - bc->yoff = (float) y0 * recip_v + sub_y; - bc->xoff2 = ((float)x0 + r->w) * recip_h + sub_x; - bc->yoff2 = ((float)y0 + r->h) * recip_v + sub_y; - } else { - return_value = 0; /* if any fail, report failure */ - } - ++k; - } - } - /* restore original values */ - spc->h_oversample = (unsigned int)old_h_over; - spc->v_oversample = (unsigned int)old_v_over; - return return_value; -} - -NK_INTERN void -nk_tt_GetPackedQuad(struct nk_tt_packedchar *chardata, int pw, int ph, - int char_index, float *xpos, float *ypos, struct nk_tt_aligned_quad *q, - int align_to_integer) -{ - float ipw = 1.0f / (float)pw, iph = 1.0f / (float)ph; - struct nk_tt_packedchar *b = (struct nk_tt_packedchar*)(chardata + char_index); - if (align_to_integer) { - int tx = nk_ifloorf((*xpos + b->xoff) + 0.5f); - int ty = nk_ifloorf((*ypos + b->yoff) + 0.5f); - - float x = (float)tx; - float y = (float)ty; - - q->x0 = x; - q->y0 = y; - q->x1 = x + b->xoff2 - b->xoff; - q->y1 = y + b->yoff2 - b->yoff; - } else { - q->x0 = *xpos + b->xoff; - q->y0 = *ypos + b->yoff; - q->x1 = *xpos + b->xoff2; - q->y1 = *ypos + b->yoff2; - } - q->s0 = b->x0 * ipw; - q->t0 = b->y0 * iph; - q->s1 = b->x1 * ipw; - q->t1 = b->y1 * iph; - *xpos += b->xadvance; -} - -/* ------------------------------------------------------------- - * - * FONT BAKING - * - * --------------------------------------------------------------*/ -struct nk_font_bake_data { - struct nk_tt_fontinfo info; - struct nk_rp_rect *rects; - struct nk_tt_pack_range *ranges; - nk_rune range_count; -}; - -struct nk_font_baker { - struct nk_allocator alloc; - struct nk_tt_pack_context spc; - struct nk_font_bake_data *build; - struct nk_tt_packedchar *packed_chars; - struct nk_rp_rect *rects; - struct nk_tt_pack_range *ranges; -}; - -NK_GLOBAL const nk_size nk_rect_align = NK_ALIGNOF(struct nk_rp_rect); -NK_GLOBAL const nk_size nk_range_align = NK_ALIGNOF(struct nk_tt_pack_range); -NK_GLOBAL const nk_size nk_char_align = NK_ALIGNOF(struct nk_tt_packedchar); -NK_GLOBAL const nk_size nk_build_align = NK_ALIGNOF(struct nk_font_bake_data); -NK_GLOBAL const nk_size nk_baker_align = NK_ALIGNOF(struct nk_font_baker); - -NK_INTERN int -nk_range_count(const nk_rune *range) -{ - const nk_rune *iter = range; - NK_ASSERT(range); - if (!range) return 0; - while (*(iter++) != 0); - return (iter == range) ? 0 : (int)((iter - range)/2); -} - -NK_INTERN int -nk_range_glyph_count(const nk_rune *range, int count) -{ - int i = 0; - int total_glyphs = 0; - for (i = 0; i < count; ++i) { - int diff; - nk_rune f = range[(i*2)+0]; - nk_rune t = range[(i*2)+1]; - NK_ASSERT(t >= f); - diff = (int)((t - f) + 1); - total_glyphs += diff; - } - return total_glyphs; -} - -NK_API const nk_rune* -nk_font_default_glyph_ranges(void) -{ - NK_STORAGE const nk_rune ranges[] = {0x0020, 0x00FF, 0}; - return ranges; -} - -NK_API const nk_rune* -nk_font_chinese_glyph_ranges(void) -{ - NK_STORAGE const nk_rune ranges[] = { - 0x0020, 0x00FF, - 0x3000, 0x30FF, - 0x31F0, 0x31FF, - 0xFF00, 0xFFEF, - 0x4e00, 0x9FAF, - 0 - }; - return ranges; -} - -NK_API const nk_rune* -nk_font_cyrillic_glyph_ranges(void) -{ - NK_STORAGE const nk_rune ranges[] = { - 0x0020, 0x00FF, - 0x0400, 0x052F, - 0x2DE0, 0x2DFF, - 0xA640, 0xA69F, - 0 - }; - return ranges; -} - -NK_API const nk_rune* -nk_font_korean_glyph_ranges(void) -{ - NK_STORAGE const nk_rune ranges[] = { - 0x0020, 0x00FF, - 0x3131, 0x3163, - 0xAC00, 0xD79D, - 0 - }; - return ranges; -} - -NK_INTERN void -nk_font_baker_memory(nk_size *temp, int *glyph_count, - struct nk_font_config *config_list, int count) -{ - int range_count = 0; - int total_range_count = 0; - struct nk_font_config *iter; - - NK_ASSERT(config_list); - NK_ASSERT(glyph_count); - if (!config_list) { - *temp = 0; - *glyph_count = 0; - return; - } - - *glyph_count = 0; - if (!config_list->range) - config_list->range = nk_font_default_glyph_ranges(); - for (iter = config_list; iter; iter = iter->next) { - range_count = nk_range_count(iter->range); - total_range_count += range_count; - *glyph_count += nk_range_glyph_count(iter->range, range_count); - } - - *temp = (nk_size)*glyph_count * sizeof(struct nk_rp_rect); - *temp += (nk_size)total_range_count * sizeof(struct nk_tt_pack_range); - *temp += (nk_size)*glyph_count * sizeof(struct nk_tt_packedchar); - *temp += (nk_size)count * sizeof(struct nk_font_bake_data); - *temp += sizeof(struct nk_font_baker); - *temp += nk_rect_align + nk_range_align + nk_char_align; - *temp += nk_build_align + nk_baker_align; -} - -NK_INTERN struct nk_font_baker* -nk_font_baker(void *memory, int glyph_count, int count, struct nk_allocator *alloc) -{ - struct nk_font_baker *baker; - if (!memory) return 0; - /* setup baker inside a memory block */ - baker = (struct nk_font_baker*)NK_ALIGN_PTR(memory, nk_baker_align); - baker->build = (struct nk_font_bake_data*)NK_ALIGN_PTR((baker + 1), nk_build_align); - baker->packed_chars = (struct nk_tt_packedchar*)NK_ALIGN_PTR((baker->build + count), nk_char_align); - baker->rects = (struct nk_rp_rect*)NK_ALIGN_PTR((baker->packed_chars + glyph_count), nk_rect_align); - baker->ranges = (struct nk_tt_pack_range*)NK_ALIGN_PTR((baker->rects + glyph_count), nk_range_align); - baker->alloc = *alloc; - return baker; -} - -NK_INTERN int -nk_font_bake_pack(struct nk_font_baker *baker, - nk_size *image_memory, int *width, int *height, struct nk_recti *custom, - const struct nk_font_config *config_list, int count, - struct nk_allocator *alloc) -{ - NK_STORAGE const nk_size max_height = 1024 * 32; - const struct nk_font_config *config_iter; - int total_glyph_count = 0; - int total_range_count = 0; - int range_count = 0; - int i = 0; - - NK_ASSERT(image_memory); - NK_ASSERT(width); - NK_ASSERT(height); - NK_ASSERT(config_list); - NK_ASSERT(count); - NK_ASSERT(alloc); - - if (!image_memory || !width || !height || !config_list || !count) return nk_false; - for (config_iter = config_list; config_iter; config_iter = config_iter->next) { - range_count = nk_range_count(config_iter->range); - total_range_count += range_count; - total_glyph_count += nk_range_glyph_count(config_iter->range, range_count); - } - - /* setup font baker from temporary memory */ - for (config_iter = config_list; config_iter; config_iter = config_iter->next) { - const struct nk_font_config *cfg = config_iter; - if (!nk_tt_InitFont(&baker->build[i++].info, (const unsigned char*)cfg->ttf_blob, 0)) - return nk_false; - } - - *height = 0; - *width = (total_glyph_count > 1000) ? 1024 : 512; - nk_tt_PackBegin(&baker->spc, 0, (int)*width, (int)max_height, 0, 1, alloc); - { - int input_i = 0; - int range_n = 0; - int rect_n = 0; - int char_n = 0; - - /* pack custom user data first so it will be in the upper left corner*/ - if (custom) { - struct nk_rp_rect custom_space; - nk_zero(&custom_space, sizeof(custom_space)); - custom_space.w = (nk_rp_coord)((custom->w * 2) + 1); - custom_space.h = (nk_rp_coord)(custom->h + 1); - - nk_tt_PackSetOversampling(&baker->spc, 1, 1); - nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, &custom_space, 1); - *height = NK_MAX(*height, (int)(custom_space.y + custom_space.h)); - - custom->x = (short)custom_space.x; - custom->y = (short)custom_space.y; - custom->w = (short)custom_space.w; - custom->h = (short)custom_space.h; - } - - /* first font pass: pack all glyphs */ - for (input_i = 0, config_iter = config_list; input_i < count && config_iter; - input_i++, config_iter = config_iter->next) - { - int n = 0; - int glyph_count; - const nk_rune *in_range; - const struct nk_font_config *cfg = config_iter; - struct nk_font_bake_data *tmp = &baker->build[input_i]; - - /* count glyphs + ranges in current font */ - glyph_count = 0; range_count = 0; - for (in_range = cfg->range; in_range[0] && in_range[1]; in_range += 2) { - glyph_count += (int)(in_range[1] - in_range[0]) + 1; - range_count++; - } - - /* setup ranges */ - tmp->ranges = baker->ranges + range_n; - tmp->range_count = (nk_rune)range_count; - range_n += range_count; - for (i = 0; i < range_count; ++i) { - in_range = &cfg->range[i * 2]; - tmp->ranges[i].font_size = cfg->size; - tmp->ranges[i].first_unicode_codepoint_in_range = (int)in_range[0]; - tmp->ranges[i].num_chars = (int)(in_range[1]- in_range[0]) + 1; - tmp->ranges[i].chardata_for_range = baker->packed_chars + char_n; - char_n += tmp->ranges[i].num_chars; - } - - /* pack */ - tmp->rects = baker->rects + rect_n; - rect_n += glyph_count; - nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); - n = nk_tt_PackFontRangesGatherRects(&baker->spc, &tmp->info, - tmp->ranges, (int)tmp->range_count, tmp->rects); - nk_rp_pack_rects((struct nk_rp_context*)baker->spc.pack_info, tmp->rects, (int)n); - - /* texture height */ - for (i = 0; i < n; ++i) { - if (tmp->rects[i].was_packed) - *height = NK_MAX(*height, tmp->rects[i].y + tmp->rects[i].h); - } - } - NK_ASSERT(rect_n == total_glyph_count); - NK_ASSERT(char_n == total_glyph_count); - NK_ASSERT(range_n == total_range_count); - } - *height = (int)nk_round_up_pow2((nk_uint)*height); - *image_memory = (nk_size)(*width) * (nk_size)(*height); - return nk_true; -} - -NK_INTERN void -nk_font_bake(struct nk_font_baker *baker, void *image_memory, int width, int height, - struct nk_font_glyph *glyphs, int glyphs_count, - const struct nk_font_config *config_list, int font_count) -{ - int input_i = 0; - nk_rune glyph_n = 0; - const struct nk_font_config *config_iter; - - NK_ASSERT(image_memory); - NK_ASSERT(width); - NK_ASSERT(height); - NK_ASSERT(config_list); - NK_ASSERT(baker); - NK_ASSERT(font_count); - NK_ASSERT(glyphs_count); - if (!image_memory || !width || !height || !config_list || - !font_count || !glyphs || !glyphs_count) - return; - - /* second font pass: render glyphs */ - nk_zero(image_memory, (nk_size)((nk_size)width * (nk_size)height)); - baker->spc.pixels = (unsigned char*)image_memory; - baker->spc.height = (int)height; - for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; - ++input_i, config_iter = config_iter->next) - { - const struct nk_font_config *cfg = config_iter; - struct nk_font_bake_data *tmp = &baker->build[input_i]; - nk_tt_PackSetOversampling(&baker->spc, cfg->oversample_h, cfg->oversample_v); - nk_tt_PackFontRangesRenderIntoRects(&baker->spc, &tmp->info, tmp->ranges, - (int)tmp->range_count, tmp->rects, &baker->alloc); - } - nk_tt_PackEnd(&baker->spc, &baker->alloc); - - /* third pass: setup font and glyphs */ - for (input_i = 0, config_iter = config_list; input_i < font_count && config_iter; - ++input_i, config_iter = config_iter->next) - { - nk_size i = 0; - int char_idx = 0; - nk_rune glyph_count = 0; - const struct nk_font_config *cfg = config_iter; - struct nk_font_bake_data *tmp = &baker->build[input_i]; - struct nk_baked_font *dst_font = cfg->font; - - float font_scale = nk_tt_ScaleForPixelHeight(&tmp->info, cfg->size); - int unscaled_ascent, unscaled_descent, unscaled_line_gap; - nk_tt_GetFontVMetrics(&tmp->info, &unscaled_ascent, &unscaled_descent, - &unscaled_line_gap); - - /* fill baked font */ - if (!cfg->merge_mode) { - dst_font->ranges = cfg->range; - dst_font->height = cfg->size; - dst_font->ascent = ((float)unscaled_ascent * font_scale); - dst_font->descent = ((float)unscaled_descent * font_scale); - dst_font->glyph_offset = glyph_n; - } - - /* fill own baked font glyph array */ - for (i = 0; i < tmp->range_count; ++i) - { - struct nk_tt_pack_range *range = &tmp->ranges[i]; - for (char_idx = 0; char_idx < range->num_chars; char_idx++) - { - nk_rune codepoint = 0; - float dummy_x = 0, dummy_y = 0; - struct nk_tt_aligned_quad q; - struct nk_font_glyph *glyph; - - /* query glyph bounds from stb_truetype */ - const struct nk_tt_packedchar *pc = &range->chardata_for_range[char_idx]; - if (!pc->x0 && !pc->x1 && !pc->y0 && !pc->y1) continue; - codepoint = (nk_rune)(range->first_unicode_codepoint_in_range + char_idx); - nk_tt_GetPackedQuad(range->chardata_for_range, (int)width, - (int)height, char_idx, &dummy_x, &dummy_y, &q, 0); - - /* fill own glyph type with data */ - glyph = &glyphs[dst_font->glyph_offset + (unsigned int)glyph_count]; - glyph->codepoint = codepoint; - glyph->x0 = q.x0; glyph->y0 = q.y0; - glyph->x1 = q.x1; glyph->y1 = q.y1; - glyph->y0 += (dst_font->ascent + 0.5f); - glyph->y1 += (dst_font->ascent + 0.5f); - glyph->w = glyph->x1 - glyph->x0 + 0.5f; - glyph->h = glyph->y1 - glyph->y0; - - if (cfg->coord_type == NK_COORD_PIXEL) { - glyph->u0 = q.s0 * (float)width; - glyph->v0 = q.t0 * (float)height; - glyph->u1 = q.s1 * (float)width; - glyph->v1 = q.t1 * (float)height; - } else { - glyph->u0 = q.s0; - glyph->v0 = q.t0; - glyph->u1 = q.s1; - glyph->v1 = q.t1; - } - glyph->xadvance = (pc->xadvance + cfg->spacing.x); - if (cfg->pixel_snap) - glyph->xadvance = (float)(int)(glyph->xadvance + 0.5f); - glyph_count++; - } - } - dst_font->glyph_count = glyph_count; - glyph_n += dst_font->glyph_count; - } -} - -NK_INTERN void -nk_font_bake_custom_data(void *img_memory, int img_width, int img_height, - struct nk_recti img_dst, const char *texture_data_mask, int tex_width, - int tex_height, char white, char black) -{ - nk_byte *pixels; - int y = 0; - int x = 0; - int n = 0; - - NK_ASSERT(img_memory); - NK_ASSERT(img_width); - NK_ASSERT(img_height); - NK_ASSERT(texture_data_mask); - NK_UNUSED(tex_height); - if (!img_memory || !img_width || !img_height || !texture_data_mask) - return; - - pixels = (nk_byte*)img_memory; - for (y = 0, n = 0; y < tex_height; ++y) { - for (x = 0; x < tex_width; ++x, ++n) { - const int off0 = ((img_dst.x + x) + (img_dst.y + y) * img_width); - const int off1 = off0 + 1 + tex_width; - pixels[off0] = (texture_data_mask[n] == white) ? 0xFF : 0x00; - pixels[off1] = (texture_data_mask[n] == black) ? 0xFF : 0x00; - } - } -} - -NK_INTERN void -nk_font_bake_convert(void *out_memory, int img_width, int img_height, - const void *in_memory) -{ - int n = 0; - nk_rune *dst; - const nk_byte *src; - - NK_ASSERT(out_memory); - NK_ASSERT(in_memory); - NK_ASSERT(img_width); - NK_ASSERT(img_height); - if (!out_memory || !in_memory || !img_height || !img_width) return; - - dst = (nk_rune*)out_memory; - src = (const nk_byte*)in_memory; - for (n = (int)(img_width * img_height); n > 0; n--) - *dst++ = ((nk_rune)(*src++) << 24) | 0x00FFFFFF; -} - -/* ------------------------------------------------------------- - * - * FONT - * - * --------------------------------------------------------------*/ -NK_INTERN float -nk_font_text_width(nk_handle handle, float height, const char *text, int len) -{ - nk_rune unicode; - int text_len = 0; - float text_width = 0; - int glyph_len = 0; - float scale = 0; - - struct nk_font *font = (struct nk_font*)handle.ptr; - NK_ASSERT(font); - NK_ASSERT(font->glyphs); - if (!font || !text || !len) - return 0; - - scale = height/font->info.height; - glyph_len = text_len = nk_utf_decode(text, &unicode, (int)len); - if (!glyph_len) return 0; - while (text_len <= (int)len && glyph_len) { - const struct nk_font_glyph *g; - if (unicode == NK_UTF_INVALID) break; - - /* query currently drawn glyph information */ - g = nk_font_find_glyph(font, unicode); - text_width += g->xadvance * scale; - - /* offset next glyph */ - glyph_len = nk_utf_decode(text + text_len, &unicode, (int)len - text_len); - text_len += glyph_len; - } - return text_width; -} - -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT -NK_INTERN void -nk_font_query_font_glyph(nk_handle handle, float height, - struct nk_user_font_glyph *glyph, nk_rune codepoint, nk_rune next_codepoint) -{ - float scale; - const struct nk_font_glyph *g; - struct nk_font *font; - - NK_ASSERT(glyph); - NK_UNUSED(next_codepoint); - - font = (struct nk_font*)handle.ptr; - NK_ASSERT(font); - NK_ASSERT(font->glyphs); - if (!font || !glyph) - return; - - scale = height/font->info.height; - g = nk_font_find_glyph(font, codepoint); - glyph->width = (g->x1 - g->x0) * scale; - glyph->height = (g->y1 - g->y0) * scale; - glyph->offset = nk_vec2(g->x0 * scale, g->y0 * scale); - glyph->xadvance = (g->xadvance * scale); - glyph->uv[0] = nk_vec2(g->u0, g->v0); - glyph->uv[1] = nk_vec2(g->u1, g->v1); -} -#endif - -NK_API const struct nk_font_glyph* -nk_font_find_glyph(struct nk_font *font, nk_rune unicode) -{ - int i = 0; - int count; - int total_glyphs = 0; - const struct nk_font_glyph *glyph = 0; - - NK_ASSERT(font); - NK_ASSERT(font->glyphs); - NK_ASSERT(font->info.ranges); - if (!font || !font->glyphs) return 0; - - glyph = font->fallback; - count = nk_range_count(font->info.ranges); - for (i = 0; i < count; ++i) { - int diff; - nk_rune f = font->info.ranges[(i*2)+0]; - nk_rune t = font->info.ranges[(i*2)+1]; - diff = (int)((t - f) + 1); - if (unicode >= f && unicode <= t) - return &font->glyphs[((nk_rune)total_glyphs + (unicode - f))]; - total_glyphs += diff; - } - return glyph; -} - -NK_INTERN void -nk_font_init(struct nk_font *font, float pixel_height, - nk_rune fallback_codepoint, struct nk_font_glyph *glyphs, - const struct nk_baked_font *baked_font, nk_handle atlas) -{ - struct nk_baked_font baked; - NK_ASSERT(font); - NK_ASSERT(glyphs); - NK_ASSERT(baked_font); - if (!font || !glyphs || !baked_font) - return; - - baked = *baked_font; - font->info = baked; - font->scale = (float)pixel_height / (float)font->info.height; - font->glyphs = &glyphs[baked_font->glyph_offset]; - font->texture = atlas; - font->fallback_codepoint = fallback_codepoint; - font->fallback = nk_font_find_glyph(font, fallback_codepoint); - - font->handle.height = font->info.height * font->scale; - font->handle.width = nk_font_text_width; - font->handle.userdata.ptr = font; -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT - font->handle.query = nk_font_query_font_glyph; - font->handle.texture = font->texture; -#endif -} - -/* --------------------------------------------------------------------------- - * - * DEFAULT FONT - * - * ProggyClean.ttf - * Copyright (c) 2004, 2005 Tristan Grimmer - * MIT license (see License.txt in http://www.upperbounds.net/download/ProggyClean.ttf.zip) - * Download and more information at http://upperbounds.net - *-----------------------------------------------------------------------------*/ -#ifdef NK_INCLUDE_DEFAULT_FONT - - #ifdef __clang__ -#pragma clang diagnostic push - -#pragma clang diagnostic ignored "-Woverlength-strings" -#elif defined(__GNUC__) || defined(__GNUG__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Woverlength-strings" -#endif - -NK_GLOBAL const char nk_proggy_clean_ttf_compressed_data_base85[11980+1] = - "7])#######hV0qs'/###[),##/l:$#Q6>##5[n42>c-TH`->>#/e>11NNV=Bv(*:.F?uu#(gRU.o0XGH`$vhLG1hxt9?W`#,5LsCp#-i>.r$<$6pD>Lb';9Crc6tgXmKVeU2cD4Eo3R/" - "2*>]b(MC;$jPfY.;h^`IWM9Qo#t'X#(v#Y9w0#1D$CIf;W'#pWUPXOuxXuU(H9M(1=Ke$$'5F%)]0^#0X@U.a$FBjVQTSDgEKnIS7EM9>ZY9w0#L;>>#Mx&4Mvt//L[MkA#W@lK.N'[0#7RL_&#w+F%HtG9M#XL`N&.,GM4Pg;--VsM.M0rJfLH2eTM`*oJMHRC`N" - "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&VZ>1i%h1S9u5o@YaaW$e+bROPOpxTO7Stwi1::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." - "x]Ip.PH^'/aqUO/$1WxLoW0[iLAw=4h(9.`G" - "CRUxHPeR`5Mjol(dUWxZa(>STrPkrJiWx`5U7F#.g*jrohGg`cg:lSTvEY/EV_7H4Q9[Z%cnv;JQYZ5q.l7Zeas:HOIZOB?Ggv:[7MI2k).'2($5FNP&EQ(,)" - "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#" - "'/###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" - "_3YlQC7(p7q)&](`6_c)$/*JL(L-^(]$wIM`dPtOdGA,U3:w2M-0+WomX2u7lqM2iEumMTcsF?-aT=Z-97UEnXglEn1K-bnEO`gu" - "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/" - "/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[Ket`e;)f#Km8&+DC$I46>#Kr]]u-[=99tts1.qb#q72g1WJO81q+eN'03'eM>&1XxY-caEnO" - "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-XTt,%OVU4)S1+R-#dg0/Nn?Ku1^0f$B*P:Rowwm-`0PKjYDDM'3]d39VZHEl4,.j']Pk-M.h^&:0FACm$maq-&sgw0t7/6(^xtk%" - "LuH88Fj-ekm>GA#_>568x6(OFRl-IZp`&b,_P'$MhLbxfc$mj`,O;&%W2m`Zh:/)Uetw:aJ%]K9h:TcF]u_-Sj9,VK3M.*'&0D[Ca]J9gp8,kAW]" - "%(?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" - "Hg*`+RLgv>=4U8guD$I%D:W>-r5V*%j*W:Kvej.Lp$'?;++O'>()jLR-^u68PHm8ZFWe+ej8h:9r6L*0//c&iH&R8pRbA#Kjm%upV1g:" - "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&VBpqB>0ie&jhZ[?iLR@@_AvA-iQC(=ksRZRVp7`.=+NpBC%rh&3]R:8XDmE5^V8O(x<-+k?'(^](H.aREZSi,#1:[IXaZFOm<-ui#qUq2$##Ri;u75OK#(RtaW-K-F`S+cF]uN`-KMQ%rP/Xri.LRcB##=YL3BgM/3M" - "D?@f&1'BW-)Ju#bmmWCMkk&#TR`C,5d>g)F;t,4:@_l8G/5h4vUd%&%950:VXD'QdWoY-F$BtUwmfe$YqL'8(PWX(" - "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" - "bIu)'Z,*[>br5fX^:FPAWr-m2KgLQ_nN6'8uTGT5g)uLv:873UpTLgH+#FgpH'_o1780Ph8KmxQJ8#H72L4@768@Tm&Q" - "h4CB/5OvmA&,Q&QbUoi$a_%3M01H)4x7I^&KQVgtFnV+;[Pc>[m4k//,]1?#`VY[Jr*3&&slRfLiVZJ:]?=K3Sw=[$=uRB?3xk48@aege0jT6'N#(q%.O=?2S]u*(m<-" - "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" - "sZ88+dKQ)W6>J%CL`.d*(B`-n8D9oK-XV1q['-5k'cAZ69e;D_?$ZPP&s^+7])$*$#@QYi9,5P r+$%CE=68>K8r0=dSC%%(@p7" - ".m7jilQ02'0-VWAgTlGW'b)Tq7VT9q^*^$$.:&N@@" - "$&)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*" - "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" - "@-W$U%VEQ/,,>>#)D#%8cY#YZ?=,`Wdxu/ae&#" - "w6)R89tI#6@s'(6Bf7a&?S=^ZI_kS&ai`&=tE72L_D,;^R)7[$so8lKN%5/$(vdfq7+ebA#" - "u1p]ovUKW&Y%q]'>$1@-[xfn$7ZTp7mM,G,Ko7a&Gu%G[RMxJs[0MM%wci.LFDK)(%:_i2B5CsR8&9Z&#=mPEnm0f`<&c)QL5uJ#%u%lJj+D-r;BoFDoS97h5g)E#o:&S4weDF,9^Hoe`h*L+_a*NrLW-1pG_&2UdB8" - "6e%B/:=>)N4xeW.*wft-;$'58-ESqr#U`'6AQ]m&6/`Z>#S?YY#Vc;r7U2&326d=w&H####?TZ`*4?&.MK?LP8Vxg>$[QXc%QJv92.(Db*B)gb*BM9dM*hJMAo*c&#" - "b0v=Pjer]$gG&JXDf->'StvU7505l9$AFvgYRI^&<^b68?j#q9QX4SM'RO#&sL1IM.rJfLUAj221]d##DW=m83u5;'bYx,*Sl0hL(W;;$doB&O/TQ:(Z^xBdLjLV#*8U_72Lh+2Q8Cj0i:6hp&$C/:p(HK>T8Y[gHQ4`4)'$Ab(Nof%V'8hL&#SfD07&6D@M.*J:;$-rv29'M]8qMv-tLp,'886iaC=Hb*YJoKJ,(j%K=H`K.v9HggqBIiZu'QvBT.#=)0ukruV&.)3=(^1`o*Pj4<-#MJ+gLq9-##@HuZPN0]u:h7.T..G:;$/Usj(T7`Q8tT72LnYl<-qx8;-HV7Q-&Xdx%1a,hC=0u+HlsV>nuIQL-5" - "_>@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%" - "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;" - "^V'9;jY@;)br#q^YQpx:X#Te$Z^'=-=bGhLf:D6&bNwZ9-ZD#n^9HhLMr5G;']d&6'wYmTFmLq9wI>P(9mI[>kC-ekLC/R&CH+s'B;K-M6$EB%is00:" - "+A4[7xks.LrNk0&E)wILYF@2L'0Nb$+pv<(2.768/FrY&h$^3i&@+G%JT'<-,v`3;_)I9M^AE]CN?Cl2AZg+%4iTpT3$U4O]GKx'm9)b@p7YsvK3w^YR-" - "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*" - "hU%<-SRF`Tt:542R_VV$p@[p8DV[A,?1839FWdFTi1O*H&#(AL8[_P%.M>v^-))qOT*F5Cq0`Ye%+$B6i:7@0IXSsDiWP,##P`%/L-" - "S(qw%sf/@%#B6;/U7K]uZbi^Oc^2n%t<)'mEVE''n`WnJra$^TKvX5B>;_aSEK',(hwa0:i4G?.Bci.(X[?b*($,=-n<.Q%`(X=?+@Am*Js0&=3bh8K]mL69=Lb,OcZV/);TTm8VI;?%OtJ<(b4mq7M6:u?KRdFl*:xP?Yb.5)%w_I?7uk5JC+FS(m#i'k.'a0i)9<7b'fs'59hq$*5Uhv##pi^8+hIEBF`nvo`;'l0.^S1<-wUK2/Coh58KKhLj" - "M=SO*rfO`+qC`W-On.=AJ56>>i2@2LH6A:&5q`?9I3@@'04&p2/LVa*T-4<-i3;M9UvZd+N7>b*eIwg:CC)c<>nO&#$(>.Z-I&J(Q0Hd5Q%7Co-b`-cP)hI;*_F]u`Rb[.j8_Q/<&>uu+VsH$sM9TA%?)(vmJ80),P7E>)tjD%2L=-t#fK[%`v=Q8WlA2);Sa" - ">gXm8YB`1d@K#n]76-a$U,mF%Ul:#/'xoFM9QX-$.QN'>" - "[%$Z$uF6pA6Ki2O5:8w*vP1<-1`[G,)-m#>0`P&#eb#.3i)rtB61(o'$?X3B2Qft^ae_5tKL9MUe9b*sLEQ95C&`=G?@Mj=wh*'3E>=-<)Gt*Iw)'QG:`@I" - "wOf7&]1i'S01B+Ev/Nac#9S;=;YQpg_6U`*kVY39xK,[/6Aj7:'1Bm-_1EYfa1+o&o4hp7KN_Q(OlIo@S%;jVdn0'1h19w,WQhLI)3S#f$2(eb,jr*b;3Vw]*7NH%$c4Vs,eD9>XW8?N]o+(*pgC%/72LV-uW%iewS8W6m2rtCpo'RS1R84=@paTKt)>=%&1[)*vp'u+x,VrwN;&]kuO9JDbg=pO$J*.jVe;u'm0dr9l,<*wMK*Oe=g8lV_KEBFkO'oU]^=[-792#ok,)" - "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" - "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" - "iDDG)g,r%+?,$@?uou5tSe2aN_AQU*'IAO" - "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(#" - ";u.T%fAr%4tJ8&><1=GHZ_+m9/#H1F^R#SC#*N=BA9(D?v[UiFY>>^8p,KKF.W]L29uLkLlu/+4T" - "w$)F./^n3+rlo+DB;5sIYGNk+i1t-69Jg--0pao7Sm#K)pdHW&;LuDNH@H>#/X-TI(;P>#,Gc>#0Su>#4`1?#8lC?#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" - "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#" - "/QHC#3^ZC#7jmC#;v)D#?,)4kMYD4lVu`4m`:&5niUA5@(A5BA1]PBB:xlBCC=2CDLXMCEUtiCf&0g2'tN?PGT4CPGT4CPGT4CPGT4CPGT4CPGT4CPGT4CP" - "GT4CPGT4CPGT4CPGT4CPGT4CPGT4CP-qekC`.9kEg^+F$kwViFJTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5KTB&5o,^<-28ZI'O?;xp" - "O?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xpO?;xp;7q-#lLYI:xvD=#"; -#endif /* NK_INCLUDE_DEFAULT_FONT */ - -#define NK_CURSOR_DATA_W 90 -#define NK_CURSOR_DATA_H 27 -NK_GLOBAL const char nk_custom_cursor_data[NK_CURSOR_DATA_W * NK_CURSOR_DATA_H + 1] = -{ - "..- -XXXXXXX- X - X -XXXXXXX - XXXXXXX" - "..- -X.....X- X.X - X.X -X.....X - X.....X" - "--- -XXX.XXX- X...X - X...X -X....X - X....X" - "X - X.X - X.....X - X.....X -X...X - X...X" - "XX - X.X -X.......X- X.......X -X..X.X - X.X..X" - "X.X - X.X -XXXX.XXXX- XXXX.XXXX -X.X X.X - X.X X.X" - "X..X - X.X - X.X - X.X -XX X.X - X.X XX" - "X...X - X.X - X.X - XX X.X XX - X.X - X.X " - "X....X - X.X - X.X - X.X X.X X.X - X.X - X.X " - "X.....X - X.X - X.X - X..X X.X X..X - X.X - X.X " - "X......X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X XX-XX X.X " - "X.......X - X.X - X.X -X.....................X- X.X X.X-X.X X.X " - "X........X - X.X - X.X - X...XXXXXX.XXXXXX...X - X.X..X-X..X.X " - "X.........X -XXX.XXX- X.X - X..X X.X X..X - X...X-X...X " - "X..........X-X.....X- X.X - X.X X.X X.X - X....X-X....X " - "X......XXXXX-XXXXXXX- X.X - XX X.X XX - X.....X-X.....X " - "X...X..X --------- X.X - X.X - XXXXXXX-XXXXXXX " - "X..X X..X - -XXXX.XXXX- XXXX.XXXX ------------------------------------" - "X.X X..X - -X.......X- X.......X - XX XX - " - "XX X..X - - X.....X - X.....X - X.X X.X - " - " X..X - X...X - X...X - X..X X..X - " - " XX - X.X - X.X - X...XXXXXXXXXXXXX...X - " - "------------ - X - X -X.....................X- " - " ----------------------------------- X...XXXXXXXXXXXXX...X - " - " - X..X X..X - " - " - X.X X.X - " - " - XX XX - " -}; - -#ifdef __clang__ -#pragma clang diagnostic pop -#elif defined(__GNUC__) || defined(__GNUG__) -#pragma GCC diagnostic pop -#endif - -NK_INTERN unsigned int -nk_decompress_length(unsigned char *input) -{ - return (unsigned int)((input[8] << 24) + (input[9] << 16) + (input[10] << 8) + input[11]); -} - -NK_GLOBAL unsigned char *nk__barrier; -NK_GLOBAL unsigned char *nk__barrier2; -NK_GLOBAL unsigned char *nk__barrier3; -NK_GLOBAL unsigned char *nk__barrier4; -NK_GLOBAL unsigned char *nk__dout; - -NK_INTERN void -nk__match(unsigned char *data, unsigned int length) -{ - /* INVERSE of memmove... write each byte before copying the next...*/ - NK_ASSERT (nk__dout + length <= nk__barrier); - if (nk__dout + length > nk__barrier) { nk__dout += length; return; } - if (data < nk__barrier4) { nk__dout = nk__barrier+1; return; } - while (length--) *nk__dout++ = *data++; -} - -NK_INTERN void -nk__lit(unsigned char *data, unsigned int length) -{ - NK_ASSERT (nk__dout + length <= nk__barrier); - if (nk__dout + length > nk__barrier) { nk__dout += length; return; } - if (data < nk__barrier2) { nk__dout = nk__barrier+1; return; } - NK_MEMCPY(nk__dout, data, length); - nk__dout += length; -} - -#define nk__in2(x) ((i[x] << 8) + i[(x)+1]) -#define nk__in3(x) ((i[x] << 16) + nk__in2((x)+1)) -#define nk__in4(x) ((i[x] << 24) + nk__in3((x)+1)) - -NK_INTERN unsigned char* -nk_decompress_token(unsigned char *i) -{ - if (*i >= 0x20) { /* use fewer if's for cases that expand small */ - if (*i >= 0x80) nk__match(nk__dout-i[1]-1, (unsigned int)i[0] - 0x80 + 1), i += 2; - else if (*i >= 0x40) nk__match(nk__dout-(nk__in2(0) - 0x4000 + 1), (unsigned int)i[2]+1), i += 3; - else /* *i >= 0x20 */ nk__lit(i+1, (unsigned int)i[0] - 0x20 + 1), i += 1 + (i[0] - 0x20 + 1); - } else { /* more ifs for cases that expand large, since overhead is amortized */ - if (*i >= 0x18) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x180000 + 1), (unsigned int)i[3]+1), i += 4; - else if (*i >= 0x10) nk__match(nk__dout-(unsigned int)(nk__in3(0) - 0x100000 + 1), (unsigned int)nk__in2(3)+1), i += 5; - else if (*i >= 0x08) nk__lit(i+2, (unsigned int)nk__in2(0) - 0x0800 + 1), i += 2 + (nk__in2(0) - 0x0800 + 1); - else if (*i == 0x07) nk__lit(i+3, (unsigned int)nk__in2(1) + 1), i += 3 + (nk__in2(1) + 1); - else if (*i == 0x06) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), i[4]+1u), i += 5; - else if (*i == 0x04) nk__match(nk__dout-(unsigned int)(nk__in3(1)+1), (unsigned int)nk__in2(4)+1u), i += 6; - } - return i; -} - -NK_INTERN unsigned int -nk_adler32(unsigned int adler32, unsigned char *buffer, unsigned int buflen) -{ - const unsigned long ADLER_MOD = 65521; - unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; - unsigned long blocklen, i; - - blocklen = buflen % 5552; - while (buflen) { - for (i=0; i + 7 < blocklen; i += 8) { - s1 += buffer[0]; s2 += s1; - s1 += buffer[1]; s2 += s1; - s1 += buffer[2]; s2 += s1; - s1 += buffer[3]; s2 += s1; - s1 += buffer[4]; s2 += s1; - s1 += buffer[5]; s2 += s1; - s1 += buffer[6]; s2 += s1; - s1 += buffer[7]; s2 += s1; - buffer += 8; - } - for (; i < blocklen; ++i) { - s1 += *buffer++; s2 += s1; - } - - s1 %= ADLER_MOD; s2 %= ADLER_MOD; - buflen -= (unsigned int)blocklen; - blocklen = 5552; - } - return (unsigned int)(s2 << 16) + (unsigned int)s1; -} - -NK_INTERN unsigned int -nk_decompress(unsigned char *output, unsigned char *i, unsigned int length) -{ - unsigned int olen; - if (nk__in4(0) != 0x57bC0000) return 0; - if (nk__in4(4) != 0) return 0; /* error! stream is > 4GB */ - olen = nk_decompress_length(i); - nk__barrier2 = i; - nk__barrier3 = i+length; - nk__barrier = output + olen; - nk__barrier4 = output; - i += 16; - - nk__dout = output; - for (;;) { - unsigned char *old_i = i; - i = nk_decompress_token(i); - if (i == old_i) { - if (*i == 0x05 && i[1] == 0xfa) { - NK_ASSERT(nk__dout == output + olen); - if (nk__dout != output + olen) return 0; - if (nk_adler32(1, output, olen) != (unsigned int) nk__in4(2)) - return 0; - return olen; - } else { - NK_ASSERT(0); /* NOTREACHED */ - return 0; - } - } - NK_ASSERT(nk__dout <= output + olen); - if (nk__dout > output + olen) - return 0; - } -} - -NK_INTERN unsigned int -nk_decode_85_byte(char c) -{ return (unsigned int)((c >= '\\') ? c-36 : c-35); } - -NK_INTERN void -nk_decode_85(unsigned char* dst, const unsigned char* src) -{ - while (*src) - { - unsigned int tmp = - nk_decode_85_byte((char)src[0]) + - 85 * (nk_decode_85_byte((char)src[1]) + - 85 * (nk_decode_85_byte((char)src[2]) + - 85 * (nk_decode_85_byte((char)src[3]) + - 85 * nk_decode_85_byte((char)src[4])))); - - /* we can't assume little-endianess. */ - dst[0] = (unsigned char)((tmp >> 0) & 0xFF); - dst[1] = (unsigned char)((tmp >> 8) & 0xFF); - dst[2] = (unsigned char)((tmp >> 16) & 0xFF); - dst[3] = (unsigned char)((tmp >> 24) & 0xFF); - - src += 5; - dst += 4; - } -} - -/* ------------------------------------------------------------- - * - * FONT ATLAS - * - * --------------------------------------------------------------*/ -NK_API struct nk_font_config -nk_font_config(float pixel_height) -{ - struct nk_font_config cfg; - nk_zero_struct(cfg); - cfg.ttf_blob = 0; - cfg.ttf_size = 0; - cfg.ttf_data_owned_by_atlas = 0; - cfg.size = pixel_height; - cfg.oversample_h = 3; - cfg.oversample_v = 1; - cfg.pixel_snap = 0; - cfg.coord_type = NK_COORD_UV; - cfg.spacing = nk_vec2(0,0); - cfg.range = nk_font_default_glyph_ranges(); - cfg.merge_mode = 0; - cfg.fallback_glyph = '?'; - cfg.font = 0; - return cfg; -} - -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -NK_API void -nk_font_atlas_init_default(struct nk_font_atlas *atlas) -{ - NK_ASSERT(atlas); - if (!atlas) return; - nk_zero_struct(*atlas); - atlas->temporary.userdata.ptr = 0; - atlas->temporary.alloc = nk_malloc; - atlas->temporary.free = nk_mfree; - atlas->permanent.userdata.ptr = 0; - atlas->permanent.alloc = nk_malloc; - atlas->permanent.free = nk_mfree; -} -#endif - -NK_API void -nk_font_atlas_init(struct nk_font_atlas *atlas, struct nk_allocator *alloc) -{ - NK_ASSERT(atlas); - NK_ASSERT(alloc); - if (!atlas || !alloc) return; - nk_zero_struct(*atlas); - atlas->permanent = *alloc; - atlas->temporary = *alloc; -} - -NK_API void -nk_font_atlas_init_custom(struct nk_font_atlas *atlas, - struct nk_allocator *permanent, struct nk_allocator *temporary) -{ - NK_ASSERT(atlas); - NK_ASSERT(permanent); - NK_ASSERT(temporary); - if (!atlas || !permanent || !temporary) return; - nk_zero_struct(*atlas); - atlas->permanent = *permanent; - atlas->temporary = *temporary; -} - -NK_API void -nk_font_atlas_begin(struct nk_font_atlas *atlas) -{ - NK_ASSERT(atlas); - NK_ASSERT(atlas->temporary.alloc && atlas->temporary.free); - NK_ASSERT(atlas->permanent.alloc && atlas->permanent.free); - if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free || - !atlas->temporary.alloc || !atlas->temporary.free) return; - if (atlas->glyphs) { - atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); - atlas->glyphs = 0; - } - if (atlas->pixel) { - atlas->permanent.free(atlas->permanent.userdata, atlas->pixel); - atlas->pixel = 0; - } -} - -NK_API struct nk_font* -nk_font_atlas_add(struct nk_font_atlas *atlas, const struct nk_font_config *config) -{ - struct nk_font *font = 0; - struct nk_font_config *cfg; - - NK_ASSERT(atlas); - NK_ASSERT(atlas->permanent.alloc); - NK_ASSERT(atlas->permanent.free); - NK_ASSERT(atlas->temporary.alloc); - NK_ASSERT(atlas->temporary.free); - - NK_ASSERT(config); - NK_ASSERT(config->ttf_blob); - NK_ASSERT(config->ttf_size); - NK_ASSERT(config->size > 0.0f); - - if (!atlas || !config || !config->ttf_blob || !config->ttf_size || config->size <= 0.0f|| - !atlas->permanent.alloc || !atlas->permanent.free || - !atlas->temporary.alloc || !atlas->temporary.free) - return 0; - - /* allocate and insert font config into list */ - cfg = (struct nk_font_config*) - atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font_config)); - NK_MEMCPY(cfg, config, sizeof(*config)); - if (!atlas->config) { - atlas->config = cfg; - cfg->next = 0; - } else { - cfg->next = atlas->config; - atlas->config = cfg; - } - - /* allocate new font */ - if (!config->merge_mode) { - font = (struct nk_font*) - atlas->permanent.alloc(atlas->permanent.userdata,0, sizeof(struct nk_font)); - NK_ASSERT(font); - if (!font) return 0; - font->config = cfg; - } else { - NK_ASSERT(atlas->font_num); - font = atlas->fonts; - font->config = cfg; - } - - /* insert font into list */ - if (!config->merge_mode) { - if (!atlas->fonts) { - atlas->fonts = font; - font->next = 0; - } else { - font->next = atlas->fonts; - atlas->fonts = font; - } - cfg->font = &font->info; - } - - /* create own copy of .TTF font blob */ - if (!config->ttf_data_owned_by_atlas) { - cfg->ttf_blob = atlas->permanent.alloc(atlas->permanent.userdata,0, cfg->ttf_size); - NK_ASSERT(cfg->ttf_blob); - if (!cfg->ttf_blob) { - atlas->font_num++; - return 0; - } - NK_MEMCPY(cfg->ttf_blob, config->ttf_blob, cfg->ttf_size); - cfg->ttf_data_owned_by_atlas = 1; - } - atlas->font_num++; - return font; -} - -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) -{ - struct nk_font_config cfg; - NK_ASSERT(memory); - NK_ASSERT(size); - - NK_ASSERT(atlas); - NK_ASSERT(atlas->temporary.alloc); - NK_ASSERT(atlas->temporary.free); - NK_ASSERT(atlas->permanent.alloc); - NK_ASSERT(atlas->permanent.free); - if (!atlas || !atlas->temporary.alloc || !atlas->temporary.free || !memory || !size || - !atlas->permanent.alloc || !atlas->permanent.free) - return 0; - - cfg = (config) ? *config: nk_font_config(height); - cfg.ttf_blob = memory; - cfg.ttf_size = size; - cfg.size = height; - cfg.ttf_data_owned_by_atlas = 0; - return nk_font_atlas_add(atlas, &cfg); -} - -#ifdef NK_INCLUDE_STANDARD_IO -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 *config) -{ - nk_size size; - char *memory; - struct nk_font_config cfg; - - NK_ASSERT(atlas); - NK_ASSERT(atlas->temporary.alloc); - NK_ASSERT(atlas->temporary.free); - NK_ASSERT(atlas->permanent.alloc); - NK_ASSERT(atlas->permanent.free); - - if (!atlas || !file_path) return 0; - memory = nk_file_load(file_path, &size, &atlas->permanent); - if (!memory) return 0; - - cfg = (config) ? *config: nk_font_config(height); - cfg.ttf_blob = memory; - cfg.ttf_size = size; - cfg.size = height; - cfg.ttf_data_owned_by_atlas = 1; - return nk_font_atlas_add(atlas, &cfg); -} -#endif - -NK_API struct nk_font* -nk_font_atlas_add_compressed(struct nk_font_atlas *atlas, - void *compressed_data, nk_size compressed_size, float height, - const struct nk_font_config *config) -{ - unsigned int decompressed_size; - void *decompressed_data; - struct nk_font_config cfg; - - NK_ASSERT(atlas); - NK_ASSERT(atlas->temporary.alloc); - NK_ASSERT(atlas->temporary.free); - NK_ASSERT(atlas->permanent.alloc); - NK_ASSERT(atlas->permanent.free); - - NK_ASSERT(compressed_data); - NK_ASSERT(compressed_size); - if (!atlas || !compressed_data || !atlas->temporary.alloc || !atlas->temporary.free || - !atlas->permanent.alloc || !atlas->permanent.free) - return 0; - - decompressed_size = nk_decompress_length((unsigned char*)compressed_data); - decompressed_data = atlas->permanent.alloc(atlas->permanent.userdata,0,decompressed_size); - NK_ASSERT(decompressed_data); - if (!decompressed_data) return 0; - nk_decompress((unsigned char*)decompressed_data, (unsigned char*)compressed_data, - (unsigned int)compressed_size); - - cfg = (config) ? *config: nk_font_config(height); - cfg.ttf_blob = decompressed_data; - cfg.ttf_size = decompressed_size; - cfg.size = height; - cfg.ttf_data_owned_by_atlas = 1; - return nk_font_atlas_add(atlas, &cfg); -} - -NK_API struct nk_font* -nk_font_atlas_add_compressed_base85(struct nk_font_atlas *atlas, - const char *data_base85, float height, const struct nk_font_config *config) -{ - int compressed_size; - void *compressed_data; - struct nk_font *font; - - NK_ASSERT(atlas); - NK_ASSERT(atlas->temporary.alloc); - NK_ASSERT(atlas->temporary.free); - NK_ASSERT(atlas->permanent.alloc); - NK_ASSERT(atlas->permanent.free); - - NK_ASSERT(data_base85); - if (!atlas || !data_base85 || !atlas->temporary.alloc || !atlas->temporary.free || - !atlas->permanent.alloc || !atlas->permanent.free) - return 0; - - compressed_size = (((int)nk_strlen(data_base85) + 4) / 5) * 4; - compressed_data = atlas->temporary.alloc(atlas->temporary.userdata,0, (nk_size)compressed_size); - NK_ASSERT(compressed_data); - if (!compressed_data) return 0; - nk_decode_85((unsigned char*)compressed_data, (const unsigned char*)data_base85); - font = nk_font_atlas_add_compressed(atlas, compressed_data, - (nk_size)compressed_size, height, config); - atlas->temporary.free(atlas->temporary.userdata, compressed_data); - return font; -} - -#ifdef NK_INCLUDE_DEFAULT_FONT -NK_API struct nk_font* -nk_font_atlas_add_default(struct nk_font_atlas *atlas, - float pixel_height, const struct nk_font_config *config) -{ - NK_ASSERT(atlas); - NK_ASSERT(atlas->temporary.alloc); - NK_ASSERT(atlas->temporary.free); - NK_ASSERT(atlas->permanent.alloc); - NK_ASSERT(atlas->permanent.free); - return nk_font_atlas_add_compressed_base85(atlas, - nk_proggy_clean_ttf_compressed_data_base85, pixel_height, config); -} -#endif - -NK_API const void* -nk_font_atlas_bake(struct nk_font_atlas *atlas, int *width, int *height, - enum nk_font_atlas_format fmt) -{ - int i = 0; - void *tmp = 0; - nk_size tmp_size, img_size; - struct nk_font *font_iter; - struct nk_font_baker *baker; - - NK_ASSERT(atlas); - NK_ASSERT(atlas->temporary.alloc); - NK_ASSERT(atlas->temporary.free); - NK_ASSERT(atlas->permanent.alloc); - NK_ASSERT(atlas->permanent.free); - - NK_ASSERT(width); - NK_ASSERT(height); - if (!atlas || !width || !height || - !atlas->temporary.alloc || !atlas->temporary.free || - !atlas->permanent.alloc || !atlas->permanent.free) - return 0; - -#ifdef NK_INCLUDE_DEFAULT_FONT - /* no font added so just use default font */ - if (!atlas->font_num) - atlas->default_font = nk_font_atlas_add_default(atlas, 13.0f, 0); -#endif - NK_ASSERT(atlas->font_num); - if (!atlas->font_num) return 0; - - /* allocate temporary baker memory required for the baking process */ - nk_font_baker_memory(&tmp_size, &atlas->glyph_count, atlas->config, atlas->font_num); - tmp = atlas->temporary.alloc(atlas->temporary.userdata,0, tmp_size); - NK_ASSERT(tmp); - if (!tmp) goto failed; - - /* allocate glyph memory for all fonts */ - baker = nk_font_baker(tmp, atlas->glyph_count, atlas->font_num, &atlas->temporary); - atlas->glyphs = (struct nk_font_glyph*)atlas->permanent.alloc( - atlas->permanent.userdata,0, sizeof(struct nk_font_glyph)*(nk_size)atlas->glyph_count); - NK_ASSERT(atlas->glyphs); - if (!atlas->glyphs) - goto failed; - - /* pack all glyphs into a tight fit space */ - atlas->custom.w = (NK_CURSOR_DATA_W*2)+1; - atlas->custom.h = NK_CURSOR_DATA_H + 1; - if (!nk_font_bake_pack(baker, &img_size, width, height, &atlas->custom, - atlas->config, atlas->font_num, &atlas->temporary)) - goto failed; - - /* allocate memory for the baked image font atlas */ - atlas->pixel = atlas->temporary.alloc(atlas->temporary.userdata,0, img_size); - NK_ASSERT(atlas->pixel); - if (!atlas->pixel) - goto failed; - - /* bake glyphs and custom white pixel into image */ - nk_font_bake(baker, atlas->pixel, *width, *height, - atlas->glyphs, atlas->glyph_count, atlas->config, atlas->font_num); - nk_font_bake_custom_data(atlas->pixel, *width, *height, atlas->custom, - nk_custom_cursor_data, NK_CURSOR_DATA_W, NK_CURSOR_DATA_H, '.', 'X'); - - if (fmt == NK_FONT_ATLAS_RGBA32) { - /* convert alpha8 image into rgba32 image */ - void *img_rgba = atlas->temporary.alloc(atlas->temporary.userdata,0, - (nk_size)(*width * *height * 4)); - NK_ASSERT(img_rgba); - if (!img_rgba) goto failed; - nk_font_bake_convert(img_rgba, *width, *height, atlas->pixel); - atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); - atlas->pixel = img_rgba; - } - atlas->tex_width = *width; - atlas->tex_height = *height; - - /* initialize each font */ - for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { - struct nk_font *font = font_iter; - struct nk_font_config *config = font->config; - nk_font_init(font, config->size, config->fallback_glyph, atlas->glyphs, - config->font, nk_handle_ptr(0)); - } - - /* initialize each cursor */ - {NK_STORAGE const struct nk_vec2 nk_cursor_data[NK_CURSOR_COUNT][3] = { - /* Pos ----- Size ------- Offset --*/ - {{ 0, 3}, {12,19}, { 0, 0}}, - {{13, 0}, { 7,16}, { 4, 8}}, - {{31, 0}, {23,23}, {11,11}}, - {{21, 0}, { 9, 23}, { 5,11}}, - {{55,18}, {23, 9}, {11, 5}}, - {{73, 0}, {17,17}, { 9, 9}}, - {{55, 0}, {17,17}, { 9, 9}} - }; - for (i = 0; i < NK_CURSOR_COUNT; ++i) { - struct nk_cursor *cursor = &atlas->cursors[i]; - cursor->img.w = (unsigned short)*width; - cursor->img.h = (unsigned short)*height; - cursor->img.region[0] = (unsigned short)(atlas->custom.x + nk_cursor_data[i][0].x); - cursor->img.region[1] = (unsigned short)(atlas->custom.y + nk_cursor_data[i][0].y); - cursor->img.region[2] = (unsigned short)nk_cursor_data[i][1].x; - cursor->img.region[3] = (unsigned short)nk_cursor_data[i][1].y; - cursor->size = nk_cursor_data[i][1]; - cursor->offset = nk_cursor_data[i][2]; - }} - /* free temporary memory */ - atlas->temporary.free(atlas->temporary.userdata, tmp); - return atlas->pixel; - -failed: - /* error so cleanup all memory */ - if (tmp) atlas->temporary.free(atlas->temporary.userdata, tmp); - if (atlas->glyphs) { - atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); - atlas->glyphs = 0; - } - if (atlas->pixel) { - atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); - atlas->pixel = 0; - } - return 0; -} - -NK_API void -nk_font_atlas_end(struct nk_font_atlas *atlas, nk_handle texture, - struct nk_draw_null_texture *null) -{ - int i = 0; - struct nk_font *font_iter; - NK_ASSERT(atlas); - if (!atlas) { - if (!null) return; - null->texture = texture; - null->uv = nk_vec2(0.5f,0.5f); - } - if (null) { - null->texture = texture; - null->uv.x = (atlas->custom.x + 0.5f)/(float)atlas->tex_width; - null->uv.y = (atlas->custom.y + 0.5f)/(float)atlas->tex_height; - } - for (font_iter = atlas->fonts; font_iter; font_iter = font_iter->next) { - font_iter->texture = texture; -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT - font_iter->handle.texture = texture; -#endif - } - for (i = 0; i < NK_CURSOR_COUNT; ++i) - atlas->cursors[i].img.handle = texture; - - atlas->temporary.free(atlas->temporary.userdata, atlas->pixel); - atlas->pixel = 0; - atlas->tex_width = 0; - atlas->tex_height = 0; - atlas->custom.x = 0; - atlas->custom.y = 0; - atlas->custom.w = 0; - atlas->custom.h = 0; -} - -NK_API void -nk_font_atlas_cleanup(struct nk_font_atlas *atlas) -{ - NK_ASSERT(atlas); - NK_ASSERT(atlas->temporary.alloc); - NK_ASSERT(atlas->temporary.free); - NK_ASSERT(atlas->permanent.alloc); - NK_ASSERT(atlas->permanent.free); - - if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; - if (atlas->config) { - struct nk_font_config *iter, *next; - for (iter = atlas->config; iter; iter = next) { - next = iter->next; - atlas->permanent.free(atlas->permanent.userdata, iter->ttf_blob); - atlas->permanent.free(atlas->permanent.userdata, iter); - } - } -} - -NK_API void -nk_font_atlas_clear(struct nk_font_atlas *atlas) -{ - NK_ASSERT(atlas); - NK_ASSERT(atlas->temporary.alloc); - NK_ASSERT(atlas->temporary.free); - NK_ASSERT(atlas->permanent.alloc); - NK_ASSERT(atlas->permanent.free); - if (!atlas || !atlas->permanent.alloc || !atlas->permanent.free) return; - - nk_font_atlas_cleanup(atlas); - if (atlas->fonts) { - struct nk_font *iter, *next; - for (iter = atlas->fonts; iter; iter = next) { - next = iter->next; - atlas->permanent.free(atlas->permanent.userdata, iter); - } - atlas->fonts = 0; - } - if (atlas->glyphs) - atlas->permanent.free(atlas->permanent.userdata, atlas->glyphs); - nk_zero_struct(*atlas); -} -#endif -/* ============================================================== - * - * INPUT - * - * ===============================================================*/ -NK_API void -nk_input_begin(struct nk_context *ctx) -{ - int i; - struct nk_input *in; - NK_ASSERT(ctx); - if (!ctx) return; - in = &ctx->input; - for (i = 0; i < NK_BUTTON_MAX; ++i) - in->mouse.buttons[i].clicked = 0; - - in->keyboard.text_len = 0; - in->mouse.scroll_delta = 0; - in->mouse.prev.x = in->mouse.pos.x; - in->mouse.prev.y = in->mouse.pos.y; - in->mouse.delta.x = 0; - in->mouse.delta.y = 0; - for (i = 0; i < NK_KEY_MAX; i++) - in->keyboard.keys[i].clicked = 0; -} - -NK_API void -nk_input_end(struct nk_context *ctx) -{ - struct nk_input *in; - NK_ASSERT(ctx); - if (!ctx) return; - in = &ctx->input; - if (in->mouse.grab) - in->mouse.grab = 0; - if (in->mouse.ungrab) { - in->mouse.grabbed = 0; - in->mouse.ungrab = 0; - in->mouse.grab = 0; - } -} - -NK_API void -nk_input_motion(struct nk_context *ctx, int x, int y) -{ - struct nk_input *in; - NK_ASSERT(ctx); - if (!ctx) return; - in = &ctx->input; - in->mouse.pos.x = (float)x; - in->mouse.pos.y = (float)y; - in->mouse.delta.x = in->mouse.pos.x - in->mouse.prev.x; - in->mouse.delta.y = in->mouse.pos.y - in->mouse.prev.y; -} - -NK_API void -nk_input_key(struct nk_context *ctx, enum nk_keys key, int down) -{ - struct nk_input *in; - NK_ASSERT(ctx); - if (!ctx) return; - in = &ctx->input; - in->keyboard.keys[key].down = down; - in->keyboard.keys[key].clicked++; -} - -NK_API void -nk_input_button(struct nk_context *ctx, enum nk_buttons id, int x, int y, int down) -{ - struct nk_mouse_button *btn; - struct nk_input *in; - NK_ASSERT(ctx); - if (!ctx) return; - in = &ctx->input; - if (in->mouse.buttons[id].down == down) return; - - btn = &in->mouse.buttons[id]; - btn->clicked_pos.x = (float)x; - btn->clicked_pos.y = (float)y; - btn->down = down; - btn->clicked++; -} - -NK_API void -nk_input_scroll(struct nk_context *ctx, float y) -{ - NK_ASSERT(ctx); - if (!ctx) return; - ctx->input.mouse.scroll_delta += y; -} - -NK_API void -nk_input_glyph(struct nk_context *ctx, const nk_glyph glyph) -{ - int len = 0; - nk_rune unicode; - struct nk_input *in; - - NK_ASSERT(ctx); - if (!ctx) return; - in = &ctx->input; - - len = nk_utf_decode(glyph, &unicode, NK_UTF_SIZE); - if (len && ((in->keyboard.text_len + len) < NK_INPUT_MAX)) { - nk_utf_encode(unicode, &in->keyboard.text[in->keyboard.text_len], - NK_INPUT_MAX - in->keyboard.text_len); - in->keyboard.text_len += len; - } -} - -NK_API void -nk_input_char(struct nk_context *ctx, char c) -{ - nk_glyph glyph; - NK_ASSERT(ctx); - if (!ctx) return; - glyph[0] = c; - nk_input_glyph(ctx, glyph); -} - -NK_API void -nk_input_unicode(struct nk_context *ctx, nk_rune unicode) -{ - nk_glyph rune; - NK_ASSERT(ctx); - if (!ctx) return; - nk_utf_encode(unicode, rune, NK_UTF_SIZE); - nk_input_glyph(ctx, rune); -} - -NK_API int -nk_input_has_mouse_click(const struct nk_input *i, enum nk_buttons id) -{ - const struct nk_mouse_button *btn; - if (!i) return nk_false; - btn = &i->mouse.buttons[id]; - return (btn->clicked && btn->down == nk_false) ? nk_true : nk_false; -} - -NK_API int -nk_input_has_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, - struct nk_rect b) -{ - const struct nk_mouse_button *btn; - if (!i) return nk_false; - btn = &i->mouse.buttons[id]; - if (!NK_INBOX(btn->clicked_pos.x,btn->clicked_pos.y,b.x,b.y,b.w,b.h)) - return nk_false; - return nk_true; -} - -NK_API int -nk_input_has_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, - struct nk_rect b, int down) -{ - const struct nk_mouse_button *btn; - if (!i) return nk_false; - btn = &i->mouse.buttons[id]; - return nk_input_has_mouse_click_in_rect(i, id, b) && (btn->down == down); -} - -NK_API int -nk_input_is_mouse_click_in_rect(const struct nk_input *i, enum nk_buttons id, - struct nk_rect b) -{ - const struct nk_mouse_button *btn; - if (!i) return nk_false; - btn = &i->mouse.buttons[id]; - return (nk_input_has_mouse_click_down_in_rect(i, id, b, nk_false) && - btn->clicked) ? nk_true : nk_false; -} - -NK_API int -nk_input_is_mouse_click_down_in_rect(const struct nk_input *i, enum nk_buttons id, - struct nk_rect b, int down) -{ - const struct nk_mouse_button *btn; - if (!i) return nk_false; - btn = &i->mouse.buttons[id]; - return (nk_input_has_mouse_click_down_in_rect(i, id, b, down) && - btn->clicked) ? nk_true : nk_false; -} - -NK_API int -nk_input_any_mouse_click_in_rect(const struct nk_input *in, struct nk_rect b) -{ - int i, down = 0; - for (i = 0; i < NK_BUTTON_MAX; ++i) - down = down || nk_input_is_mouse_click_in_rect(in, (enum nk_buttons)i, b); - return down; -} - -NK_API int -nk_input_is_mouse_hovering_rect(const struct nk_input *i, struct nk_rect rect) -{ - if (!i) return nk_false; - return NK_INBOX(i->mouse.pos.x, i->mouse.pos.y, rect.x, rect.y, rect.w, rect.h); -} - -NK_API int -nk_input_is_mouse_prev_hovering_rect(const struct nk_input *i, struct nk_rect rect) -{ - if (!i) return nk_false; - return NK_INBOX(i->mouse.prev.x, i->mouse.prev.y, rect.x, rect.y, rect.w, rect.h); -} - -NK_API int -nk_input_mouse_clicked(const struct nk_input *i, enum nk_buttons id, struct nk_rect rect) -{ - if (!i) return nk_false; - if (!nk_input_is_mouse_hovering_rect(i, rect)) return nk_false; - return nk_input_is_mouse_click_in_rect(i, id, rect); -} - -NK_API int -nk_input_is_mouse_down(const struct nk_input *i, enum nk_buttons id) -{ - if (!i) return nk_false; - return i->mouse.buttons[id].down; -} - -NK_API int -nk_input_is_mouse_pressed(const struct nk_input *i, enum nk_buttons id) -{ - const struct nk_mouse_button *b; - if (!i) return nk_false; - b = &i->mouse.buttons[id]; - if (b->down && b->clicked) - return nk_true; - return nk_false; -} - -NK_API int -nk_input_is_mouse_released(const struct nk_input *i, enum nk_buttons id) -{ - if (!i) return nk_false; - return (!i->mouse.buttons[id].down && i->mouse.buttons[id].clicked); -} - -NK_API int -nk_input_is_key_pressed(const struct nk_input *i, enum nk_keys key) -{ - const struct nk_key *k; - if (!i) return nk_false; - k = &i->keyboard.keys[key]; - if ((k->down && k->clicked) || (!k->down && k->clicked >= 2)) - return nk_true; - return nk_false; -} - -NK_API int -nk_input_is_key_released(const struct nk_input *i, enum nk_keys key) -{ - const struct nk_key *k; - if (!i) return nk_false; - k = &i->keyboard.keys[key]; - if ((!k->down && k->clicked) || (k->down && k->clicked >= 2)) - return nk_true; - return nk_false; -} - -NK_API int -nk_input_is_key_down(const struct nk_input *i, enum nk_keys key) -{ - const struct nk_key *k; - if (!i) return nk_false; - k = &i->keyboard.keys[key]; - if (k->down) return nk_true; - return nk_false; -} - -/* - * ============================================================== - * - * TEXT EDITOR - * - * =============================================================== - */ -/* stb_textedit.h - v1.8 - public domain - Sean Barrett */ -struct nk_text_find { - float x,y; /* position of n'th character */ - float height; /* height of line */ - int first_char, length; /* first char of row, and length */ - int prev_first; /*_ first char of previous row */ -}; - -struct nk_text_edit_row { - float x0,x1; - /* starting x location, end x location (allows for align=right, etc) */ - float baseline_y_delta; - /* position of baseline relative to previous row's baseline*/ - float ymin,ymax; - /* height of row above and below baseline */ - int num_chars; -}; - -/* forward declarations */ -NK_INTERN void nk_textedit_makeundo_delete(struct nk_text_edit*, int, int); -NK_INTERN void nk_textedit_makeundo_insert(struct nk_text_edit*, int, int); -NK_INTERN void nk_textedit_makeundo_replace(struct nk_text_edit*, int, int, int); -#define NK_TEXT_HAS_SELECTION(s) ((s)->select_start != (s)->select_end) - -NK_INTERN float -nk_textedit_get_width(const struct nk_text_edit *edit, int line_start, int char_id, - const struct nk_user_font *font) -{ - int len = 0; - nk_rune unicode = 0; - const char *str = nk_str_at_const(&edit->string, line_start + char_id, &unicode, &len); - return font->width(font->userdata, font->height, str, len); -} - -NK_INTERN void -nk_textedit_layout_row(struct nk_text_edit_row *r, struct nk_text_edit *edit, - int line_start_id, float row_height, const struct nk_user_font *font) -{ - int l; - int glyphs = 0; - nk_rune unicode; - const char *remaining; - int len = nk_str_len_char(&edit->string); - const char *end = nk_str_get_const(&edit->string) + len; - const char *text = nk_str_at_const(&edit->string, line_start_id, &unicode, &l); - const struct nk_vec2 size = nk_text_calculate_text_bounds(font, - text, (int)(end - text), row_height, &remaining, 0, &glyphs, NK_STOP_ON_NEW_LINE); - - r->x0 = 0.0f; - r->x1 = size.x; - r->baseline_y_delta = size.y; - r->ymin = 0.0f; - r->ymax = size.y; - r->num_chars = glyphs; -} - -NK_INTERN int -nk_textedit_locate_coord(struct nk_text_edit *edit, float x, float y, - const struct nk_user_font *font, float row_height) -{ - struct nk_text_edit_row r; - int n = edit->string.len; - float base_y = 0, prev_x; - int i=0, k; - - r.x0 = r.x1 = 0; - r.ymin = r.ymax = 0; - r.num_chars = 0; - - /* search rows to find one that straddles 'y' */ - while (i < n) { - nk_textedit_layout_row(&r, edit, i, row_height, font); - if (r.num_chars <= 0) - return n; - - if (i==0 && y < base_y + r.ymin) - return 0; - - if (y < base_y + r.ymax) - break; - - i += r.num_chars; - base_y += r.baseline_y_delta; - } - - /* below all text, return 'after' last character */ - if (i >= n) - return n; - - /* check if it's before the beginning of the line */ - if (x < r.x0) - return i; - - /* check if it's before the end of the line */ - if (x < r.x1) { - /* search characters in row for one that straddles 'x' */ - k = i; - prev_x = r.x0; - for (i=0; i < r.num_chars; ++i) { - float w = nk_textedit_get_width(edit, k, i, font); - if (x < prev_x+w) { - if (x < prev_x+w/2) - return k+i; - else return k+i+1; - } - prev_x += w; - } - /* shouldn't happen, but if it does, fall through to end-of-line case */ - } - - /* if the last character is a newline, return that. - * otherwise return 'after' the last character */ - if (nk_str_rune_at(&edit->string, i+r.num_chars-1) == '\n') - return i+r.num_chars-1; - else return i+r.num_chars; -} - -NK_INTERN void -nk_textedit_click(struct nk_text_edit *state, float x, float y, - const struct nk_user_font *font, float row_height) -{ - /* API click: on mouse down, move the cursor to the clicked location, - * and reset the selection */ - state->cursor = nk_textedit_locate_coord(state, x, y, font, row_height); - state->select_start = state->cursor; - state->select_end = state->cursor; - state->has_preferred_x = 0; -} - -NK_INTERN void -nk_textedit_drag(struct nk_text_edit *state, float x, float y, - const struct nk_user_font *font, float row_height) -{ - /* API drag: on mouse drag, move the cursor and selection endpoint - * to the clicked location */ - int p = nk_textedit_locate_coord(state, x, y, font, row_height); - if (state->select_start == state->select_end) - state->select_start = state->cursor; - state->cursor = state->select_end = p; -} - -NK_INTERN void -nk_textedit_find_charpos(struct nk_text_find *find, struct nk_text_edit *state, - int n, int single_line, const struct nk_user_font *font, float row_height) -{ - /* find the x/y location of a character, and remember info about the previous - * row in case we get a move-up event (for page up, we'll have to rescan) */ - struct nk_text_edit_row r; - int prev_start = 0; - int z = state->string.len; - int i=0, first; - - nk_zero_struct(r); - if (n == z) { - /* if it's at the end, then find the last line -- simpler than trying to - explicitly handle this case in the regular code */ - nk_textedit_layout_row(&r, state, 0, row_height, font); - if (single_line) { - find->first_char = 0; - find->length = z; - } else { - while (i < z) { - prev_start = i; - i += r.num_chars; - nk_textedit_layout_row(&r, state, i, row_height, font); - } - - find->first_char = i; - find->length = r.num_chars; - } - find->x = r.x1; - find->y = r.ymin; - find->height = r.ymax - r.ymin; - find->prev_first = prev_start; - return; - } - - /* search rows to find the one that straddles character n */ - find->y = 0; - - for(;;) { - nk_textedit_layout_row(&r, state, i, row_height, font); - if (n < i + r.num_chars) break; - prev_start = i; - i += r.num_chars; - find->y += r.baseline_y_delta; - } - - find->first_char = first = i; - find->length = r.num_chars; - find->height = r.ymax - r.ymin; - find->prev_first = prev_start; - - /* now scan to find xpos */ - find->x = r.x0; - for (i=0; first+i < n; ++i) - find->x += nk_textedit_get_width(state, first, i, font); -} - -NK_INTERN void -nk_textedit_clamp(struct nk_text_edit *state) -{ - /* make the selection/cursor state valid if client altered the string */ - int n = state->string.len; - if (NK_TEXT_HAS_SELECTION(state)) { - if (state->select_start > n) state->select_start = n; - if (state->select_end > n) state->select_end = n; - /* if clamping forced them to be equal, move the cursor to match */ - if (state->select_start == state->select_end) - state->cursor = state->select_start; - } - if (state->cursor > n) state->cursor = n; -} - -NK_API void -nk_textedit_delete(struct nk_text_edit *state, int where, int len) -{ - /* delete characters while updating undo */ - nk_textedit_makeundo_delete(state, where, len); - nk_str_delete_runes(&state->string, where, len); - state->has_preferred_x = 0; -} - -NK_API void -nk_textedit_delete_selection(struct nk_text_edit *state) -{ - /* delete the section */ - nk_textedit_clamp(state); - if (NK_TEXT_HAS_SELECTION(state)) { - if (state->select_start < state->select_end) { - nk_textedit_delete(state, state->select_start, - state->select_end - state->select_start); - state->select_end = state->cursor = state->select_start; - } else { - nk_textedit_delete(state, state->select_end, - state->select_start - state->select_end); - state->select_start = state->cursor = state->select_end; - } - state->has_preferred_x = 0; - } -} - -NK_INTERN void -nk_textedit_sortselection(struct nk_text_edit *state) -{ - /* canonicalize the selection so start <= end */ - if (state->select_end < state->select_start) { - int temp = state->select_end; - state->select_end = state->select_start; - state->select_start = temp; - } -} - -NK_INTERN void -nk_textedit_move_to_first(struct nk_text_edit *state) -{ - /* move cursor to first character of selection */ - if (NK_TEXT_HAS_SELECTION(state)) { - nk_textedit_sortselection(state); - state->cursor = state->select_start; - state->select_end = state->select_start; - state->has_preferred_x = 0; - } -} - -NK_INTERN void -nk_textedit_move_to_last(struct nk_text_edit *state) -{ - /* move cursor to last character of selection */ - if (NK_TEXT_HAS_SELECTION(state)) { - nk_textedit_sortselection(state); - nk_textedit_clamp(state); - state->cursor = state->select_end; - state->select_start = state->select_end; - state->has_preferred_x = 0; - } -} - -NK_INTERN int -nk_is_word_boundary( struct nk_text_edit *state, int idx) -{ - int len; - nk_rune c; - if (idx <= 0) return 1; - if (!nk_str_at_rune(&state->string, idx, &c, &len)) return 1; - return (c == ' ' || c == '\t' ||c == 0x3000 || c == ',' || c == ';' || - c == '(' || c == ')' || c == '{' || c == '}' || c == '[' || c == ']' || - c == '|'); -} - -NK_INTERN int -nk_textedit_move_to_word_previous(struct nk_text_edit *state) -{ - int c = state->cursor - 1; - while( c >= 0 && !nk_is_word_boundary(state, c)) - --c; - - if( c < 0 ) - c = 0; - - return c; -} - -NK_INTERN int -nk_textedit_move_to_word_next(struct nk_text_edit *state) -{ - const int len = state->string.len; - int c = state->cursor+1; - while( c < len && !nk_is_word_boundary(state, c)) - ++c; - - if( c > len ) - c = len; - - return c; -} - -NK_INTERN void -nk_textedit_prep_selection_at_cursor(struct nk_text_edit *state) -{ - /* update selection and cursor to match each other */ - if (!NK_TEXT_HAS_SELECTION(state)) - state->select_start = state->select_end = state->cursor; - else state->cursor = state->select_end; -} - -NK_API int -nk_textedit_cut(struct nk_text_edit *state) -{ - /* API cut: delete selection */ - if (state->mode == NK_TEXT_EDIT_MODE_VIEW) - return 0; - if (NK_TEXT_HAS_SELECTION(state)) { - nk_textedit_delete_selection(state); /* implicitly clamps */ - state->has_preferred_x = 0; - return 1; - } - return 0; -} - -NK_API int -nk_textedit_paste(struct nk_text_edit *state, char const *ctext, int len) -{ - /* API paste: replace existing selection with passed-in text */ - int glyphs; - const char *text = (const char *) ctext; - if (state->mode == NK_TEXT_EDIT_MODE_VIEW) return 0; - - /* if there's a selection, the paste should delete it */ - nk_textedit_clamp(state); - nk_textedit_delete_selection(state); - - /* try to insert the characters */ - glyphs = nk_utf_len(ctext, len); - if (nk_str_insert_text_char(&state->string, state->cursor, text, len)) { - nk_textedit_makeundo_insert(state, state->cursor, glyphs); - state->cursor += len; - state->has_preferred_x = 0; - return 1; - } - /* remove the undo since we didn't actually insert the characters */ - if (state->undo.undo_point) - --state->undo.undo_point; - return 0; -} - -NK_API void -nk_textedit_text(struct nk_text_edit *state, const char *text, int total_len) -{ - nk_rune unicode; - int glyph_len; - int text_len = 0; - - NK_ASSERT(state); - NK_ASSERT(text); - if (!text || !total_len || state->mode == NK_TEXT_EDIT_MODE_VIEW) return; - - glyph_len = nk_utf_decode(text, &unicode, total_len); - if (!glyph_len) return; - while ((text_len < total_len) && glyph_len) - { - /* don't insert a backward delete, just process the event */ - if (unicode == 127) - break; - - /* can't add newline in single-line mode */ - if (unicode == '\n' && state->single_line) - break; - - /* filter incoming text */ - if (state->filter && !state->filter(state, unicode)) { - glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len); - text_len += glyph_len; - continue; - } - - if (!NK_TEXT_HAS_SELECTION(state) && - state->cursor < state->string.len) - { - if (state->mode == NK_TEXT_EDIT_MODE_REPLACE) { - nk_textedit_makeundo_replace(state, state->cursor, 1, 1); - nk_str_delete_runes(&state->string, state->cursor, 1); - } - if (nk_str_insert_text_utf8(&state->string, state->cursor, - text+text_len, 1)) - { - ++state->cursor; - state->has_preferred_x = 0; - } - } else { - nk_textedit_delete_selection(state); /* implicitly clamps */ - if (nk_str_insert_text_utf8(&state->string, state->cursor, - text+text_len, 1)) - { - nk_textedit_makeundo_insert(state, state->cursor, 1); - ++state->cursor; - state->has_preferred_x = 0; - } - } - glyph_len = nk_utf_decode(text + text_len, &unicode, total_len-text_len); - text_len += glyph_len; - } -} - -NK_INTERN 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) -{ -retry: - switch (key) - { - case NK_KEY_NONE: - case NK_KEY_CTRL: - case NK_KEY_ENTER: - case NK_KEY_SHIFT: - case NK_KEY_TAB: - case NK_KEY_COPY: - case NK_KEY_CUT: - case NK_KEY_PASTE: - case NK_KEY_MAX: - default: break; - case NK_KEY_TEXT_UNDO: - nk_textedit_undo(state); - state->has_preferred_x = 0; - break; - - case NK_KEY_TEXT_REDO: - nk_textedit_redo(state); - state->has_preferred_x = 0; - break; - - case NK_KEY_TEXT_INSERT_MODE: - if (state->mode == NK_TEXT_EDIT_MODE_VIEW) - state->mode = NK_TEXT_EDIT_MODE_INSERT; - break; - case NK_KEY_TEXT_REPLACE_MODE: - if (state->mode == NK_TEXT_EDIT_MODE_VIEW) - state->mode = NK_TEXT_EDIT_MODE_REPLACE; - break; - case NK_KEY_TEXT_RESET_MODE: - if (state->mode == NK_TEXT_EDIT_MODE_INSERT || - state->mode == NK_TEXT_EDIT_MODE_REPLACE) - state->mode = NK_TEXT_EDIT_MODE_VIEW; - break; - - case NK_KEY_LEFT: - if (shift_mod) { - nk_textedit_clamp(state); - nk_textedit_prep_selection_at_cursor(state); - /* move selection left */ - if (state->select_end > 0) - --state->select_end; - state->cursor = state->select_end; - state->has_preferred_x = 0; - } else { - /* if currently there's a selection, - * move cursor to start of selection */ - if (NK_TEXT_HAS_SELECTION(state)) - nk_textedit_move_to_first(state); - else if (state->cursor > 0) - --state->cursor; - state->has_preferred_x = 0; - } break; - - case NK_KEY_RIGHT: - if (shift_mod) { - nk_textedit_prep_selection_at_cursor(state); - /* move selection right */ - ++state->select_end; - nk_textedit_clamp(state); - state->cursor = state->select_end; - state->has_preferred_x = 0; - } else { - /* if currently there's a selection, - * move cursor to end of selection */ - if (NK_TEXT_HAS_SELECTION(state)) - nk_textedit_move_to_last(state); - else ++state->cursor; - nk_textedit_clamp(state); - state->has_preferred_x = 0; - } break; - - case NK_KEY_TEXT_WORD_LEFT: - if (shift_mod) { - if( !NK_TEXT_HAS_SELECTION( state ) ) - nk_textedit_prep_selection_at_cursor(state); - state->cursor = nk_textedit_move_to_word_previous(state); - state->select_end = state->cursor; - nk_textedit_clamp(state ); - } else { - if (NK_TEXT_HAS_SELECTION(state)) - nk_textedit_move_to_first(state); - else { - state->cursor = nk_textedit_move_to_word_previous(state); - nk_textedit_clamp(state ); - } - } break; - - case NK_KEY_TEXT_WORD_RIGHT: - if (shift_mod) { - if( !NK_TEXT_HAS_SELECTION( state ) ) - nk_textedit_prep_selection_at_cursor(state); - state->cursor = nk_textedit_move_to_word_next(state); - state->select_end = state->cursor; - nk_textedit_clamp(state); - } else { - if (NK_TEXT_HAS_SELECTION(state)) - nk_textedit_move_to_last(state); - else { - state->cursor = nk_textedit_move_to_word_next(state); - nk_textedit_clamp(state ); - } - } break; - - case NK_KEY_DOWN: { - struct nk_text_find find; - struct nk_text_edit_row row; - int i, sel = shift_mod; - - if (state->single_line) { - /* on windows, up&down in single-line behave like left&right */ - key = NK_KEY_RIGHT; - goto retry; - } - - if (sel) - nk_textedit_prep_selection_at_cursor(state); - else if (NK_TEXT_HAS_SELECTION(state)) - nk_textedit_move_to_last(state); - - /* compute current position of cursor point */ - nk_textedit_clamp(state); - nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, - font, row_height); - - /* now find character position down a row */ - if (find.length) - { - float x; - float goal_x = state->has_preferred_x ? state->preferred_x : find.x; - int start = find.first_char + find.length; - - state->cursor = start; - nk_textedit_layout_row(&row, state, state->cursor, row_height, font); - x = row.x0; - - for (i=0; i < row.num_chars && x < row.x1; ++i) { - float dx = nk_textedit_get_width(state, start, i, font); - x += dx; - if (x > goal_x) - break; - ++state->cursor; - } - nk_textedit_clamp(state); - - state->has_preferred_x = 1; - state->preferred_x = goal_x; - if (sel) - state->select_end = state->cursor; - } - } break; - - case NK_KEY_UP: { - struct nk_text_find find; - struct nk_text_edit_row row; - int i, sel = shift_mod; - - if (state->single_line) { - /* on windows, up&down become left&right */ - key = NK_KEY_LEFT; - goto retry; - } - - if (sel) - nk_textedit_prep_selection_at_cursor(state); - else if (NK_TEXT_HAS_SELECTION(state)) - nk_textedit_move_to_first(state); - - /* compute current position of cursor point */ - nk_textedit_clamp(state); - nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, - font, row_height); - - /* can only go up if there's a previous row */ - if (find.prev_first != find.first_char) { - /* now find character position up a row */ - float x; - float goal_x = state->has_preferred_x ? state->preferred_x : find.x; - - state->cursor = find.prev_first; - nk_textedit_layout_row(&row, state, state->cursor, row_height, font); - x = row.x0; - - for (i=0; i < row.num_chars && x < row.x1; ++i) { - float dx = nk_textedit_get_width(state, find.prev_first, i, font); - x += dx; - if (x > goal_x) - break; - ++state->cursor; - } - nk_textedit_clamp(state); - - state->has_preferred_x = 1; - state->preferred_x = goal_x; - if (sel) state->select_end = state->cursor; - } - } break; - - case NK_KEY_DEL: - if (state->mode == NK_TEXT_EDIT_MODE_VIEW) - break; - if (NK_TEXT_HAS_SELECTION(state)) - nk_textedit_delete_selection(state); - else { - int n = state->string.len; - if (state->cursor < n) - nk_textedit_delete(state, state->cursor, 1); - } - state->has_preferred_x = 0; - break; - - case NK_KEY_BACKSPACE: - if (state->mode == NK_TEXT_EDIT_MODE_VIEW) - break; - if (NK_TEXT_HAS_SELECTION(state)) - nk_textedit_delete_selection(state); - else { - nk_textedit_clamp(state); - if (state->cursor > 0) { - nk_textedit_delete(state, state->cursor-1, 1); - --state->cursor; - } - } - state->has_preferred_x = 0; - break; - - case NK_KEY_TEXT_START: - if (shift_mod) { - nk_textedit_prep_selection_at_cursor(state); - state->cursor = state->select_end = 0; - state->has_preferred_x = 0; - } else { - state->cursor = state->select_start = state->select_end = 0; - state->has_preferred_x = 0; - } - break; - - case NK_KEY_TEXT_END: - if (shift_mod) { - nk_textedit_prep_selection_at_cursor(state); - state->cursor = state->select_end = state->string.len; - state->has_preferred_x = 0; - } else { - state->cursor = state->string.len; - state->select_start = state->select_end = 0; - state->has_preferred_x = 0; - } - break; - - case NK_KEY_TEXT_LINE_START: { - if (shift_mod) { - struct nk_text_find find; - nk_textedit_clamp(state); - nk_textedit_prep_selection_at_cursor(state); - if (state->string.len && state->cursor == state->string.len) - --state->cursor; - nk_textedit_find_charpos(&find, state,state->cursor, state->single_line, - font, row_height); - state->cursor = state->select_end = find.first_char; - state->has_preferred_x = 0; - } else { - struct nk_text_find find; - if (state->string.len && state->cursor == state->string.len) - --state->cursor; - nk_textedit_clamp(state); - nk_textedit_move_to_first(state); - nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, - font, row_height); - state->cursor = find.first_char; - state->has_preferred_x = 0; - } - } break; - - case NK_KEY_TEXT_LINE_END: { - if (shift_mod) { - struct nk_text_find find; - nk_textedit_clamp(state); - nk_textedit_prep_selection_at_cursor(state); - nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, - font, row_height); - state->has_preferred_x = 0; - state->cursor = find.first_char + find.length; - if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') - --state->cursor; - state->select_end = state->cursor; - } else { - struct nk_text_find find; - nk_textedit_clamp(state); - nk_textedit_move_to_first(state); - nk_textedit_find_charpos(&find, state, state->cursor, state->single_line, - font, row_height); - - state->has_preferred_x = 0; - state->cursor = find.first_char + find.length; - if (find.length > 0 && nk_str_rune_at(&state->string, state->cursor-1) == '\n') - --state->cursor; - }} break; - } -} - -NK_INTERN void -nk_textedit_flush_redo(struct nk_text_undo_state *state) -{ - state->redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; - state->redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; -} - -NK_INTERN void -nk_textedit_discard_undo(struct nk_text_undo_state *state) -{ - /* discard the oldest entry in the undo list */ - if (state->undo_point > 0) { - /* if the 0th undo state has characters, clean those up */ - if (state->undo_rec[0].char_storage >= 0) { - int n = state->undo_rec[0].insert_length, i; - /* delete n characters from all other records */ - state->undo_char_point = (short)(state->undo_char_point - n); - NK_MEMCPY(state->undo_char, state->undo_char + n, - (nk_size)state->undo_char_point*sizeof(nk_rune)); - for (i=0; i < state->undo_point; ++i) { - if (state->undo_rec[i].char_storage >= 0) - state->undo_rec[i].char_storage = (short) - (state->undo_rec[i].char_storage - n); - } - } - --state->undo_point; - NK_MEMCPY(state->undo_rec, state->undo_rec+1, - (nk_size)((nk_size)state->undo_point * sizeof(state->undo_rec[0]))); - } -} - -NK_INTERN void -nk_textedit_discard_redo(struct nk_text_undo_state *state) -{ -/* discard the oldest entry in the redo list--it's bad if this - ever happens, but because undo & redo have to store the actual - characters in different cases, the redo character buffer can - fill up even though the undo buffer didn't */ - nk_size num; - int k = NK_TEXTEDIT_UNDOSTATECOUNT-1; - if (state->redo_point <= k) { - /* if the k'th undo state has characters, clean those up */ - if (state->undo_rec[k].char_storage >= 0) { - int n = state->undo_rec[k].insert_length, i; - /* delete n characters from all other records */ - state->redo_char_point = (short)(state->redo_char_point + n); - num = (nk_size)(NK_TEXTEDIT_UNDOCHARCOUNT - state->redo_char_point); - NK_MEMCPY(state->undo_char + state->redo_char_point, - state->undo_char + state->redo_char_point-n, num * sizeof(char)); - for (i = state->redo_point; i < k; ++i) { - if (state->undo_rec[i].char_storage >= 0) { - state->undo_rec[i].char_storage = (short) - (state->undo_rec[i].char_storage + n); - } - } - } - ++state->redo_point; - num = (nk_size)(NK_TEXTEDIT_UNDOSTATECOUNT - state->redo_point); - if (num) NK_MEMCPY(state->undo_rec + state->redo_point-1, - state->undo_rec + state->redo_point, num * sizeof(state->undo_rec[0])); - } -} - -NK_INTERN struct nk_text_undo_record* -nk_textedit_create_undo_record(struct nk_text_undo_state *state, int numchars) -{ - /* any time we create a new undo record, we discard redo*/ - nk_textedit_flush_redo(state); - - /* if we have no free records, we have to make room, - * by sliding the existing records down */ - if (state->undo_point == NK_TEXTEDIT_UNDOSTATECOUNT) - nk_textedit_discard_undo(state); - - /* if the characters to store won't possibly fit in the buffer, - * we can't undo */ - if (numchars > NK_TEXTEDIT_UNDOCHARCOUNT) { - state->undo_point = 0; - state->undo_char_point = 0; - return 0; - } - - /* if we don't have enough free characters in the buffer, - * we have to make room */ - while (state->undo_char_point + numchars > NK_TEXTEDIT_UNDOCHARCOUNT) - nk_textedit_discard_undo(state); - return &state->undo_rec[state->undo_point++]; -} - -NK_INTERN nk_rune* -nk_textedit_createundo(struct nk_text_undo_state *state, int pos, - int insert_len, int delete_len) -{ - struct nk_text_undo_record *r = nk_textedit_create_undo_record(state, insert_len); - if (r == 0) - return 0; - - r->where = pos; - r->insert_length = (short) insert_len; - r->delete_length = (short) delete_len; - - if (insert_len == 0) { - r->char_storage = -1; - return 0; - } else { - r->char_storage = state->undo_char_point; - state->undo_char_point = (short)(state->undo_char_point + insert_len); - return &state->undo_char[r->char_storage]; - } -} - -NK_API void -nk_textedit_undo(struct nk_text_edit *state) -{ - struct nk_text_undo_state *s = &state->undo; - struct nk_text_undo_record u, *r; - if (s->undo_point == 0) - return; - - /* we need to do two things: apply the undo record, and create a redo record */ - u = s->undo_rec[s->undo_point-1]; - r = &s->undo_rec[s->redo_point-1]; - r->char_storage = -1; - - r->insert_length = u.delete_length; - r->delete_length = u.insert_length; - r->where = u.where; - - if (u.delete_length) - { - /* if the undo record says to delete characters, then the redo record will - need to re-insert the characters that get deleted, so we need to store - them. - there are three cases: - - there's enough room to store the characters - - characters stored for *redoing* don't leave room for redo - - characters stored for *undoing* don't leave room for redo - if the last is true, we have to bail */ - if (s->undo_char_point + u.delete_length >= NK_TEXTEDIT_UNDOCHARCOUNT) { - /* the undo records take up too much character space; there's no space - * to store the redo characters */ - r->insert_length = 0; - } else { - int i; - /* there's definitely room to store the characters eventually */ - while (s->undo_char_point + u.delete_length > s->redo_char_point) { - /* there's currently not enough room, so discard a redo record */ - nk_textedit_discard_redo(s); - /* should never happen: */ - if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) - return; - } - - r = &s->undo_rec[s->redo_point-1]; - r->char_storage = (short)(s->redo_char_point - u.delete_length); - s->redo_char_point = (short)(s->redo_char_point - u.delete_length); - - /* now save the characters */ - for (i=0; i < u.delete_length; ++i) - s->undo_char[r->char_storage + i] = - nk_str_rune_at(&state->string, u.where + i); - } - /* now we can carry out the deletion */ - nk_str_delete_runes(&state->string, u.where, u.delete_length); - } - - /* check type of recorded action: */ - if (u.insert_length) { - /* easy case: was a deletion, so we need to insert n characters */ - nk_str_insert_text_runes(&state->string, u.where, - &s->undo_char[u.char_storage], u.insert_length); - s->undo_char_point = (short)(s->undo_char_point - u.insert_length); - } - state->cursor = (short)(u.where + u.insert_length); - - s->undo_point--; - s->redo_point--; -} - -NK_API void -nk_textedit_redo(struct nk_text_edit *state) -{ - struct nk_text_undo_state *s = &state->undo; - struct nk_text_undo_record *u, r; - if (s->redo_point == NK_TEXTEDIT_UNDOSTATECOUNT) - return; - - /* we need to do two things: apply the redo record, and create an undo record */ - u = &s->undo_rec[s->undo_point]; - r = s->undo_rec[s->redo_point]; - - /* we KNOW there must be room for the undo record, because the redo record - was derived from an undo record */ - u->delete_length = r.insert_length; - u->insert_length = r.delete_length; - u->where = r.where; - u->char_storage = -1; - - if (r.delete_length) { - /* the redo record requires us to delete characters, so the undo record - needs to store the characters */ - if (s->undo_char_point + u->insert_length > s->redo_char_point) { - u->insert_length = 0; - u->delete_length = 0; - } else { - int i; - u->char_storage = s->undo_char_point; - s->undo_char_point = (short)(s->undo_char_point + u->insert_length); - - /* now save the characters */ - for (i=0; i < u->insert_length; ++i) { - s->undo_char[u->char_storage + i] = - nk_str_rune_at(&state->string, u->where + i); - } - } - nk_str_delete_runes(&state->string, r.where, r.delete_length); - } - - if (r.insert_length) { - /* easy case: need to insert n characters */ - nk_str_insert_text_runes(&state->string, r.where, - &s->undo_char[r.char_storage], r.insert_length); - } - state->cursor = r.where + r.insert_length; - - s->undo_point++; - s->redo_point++; -} - -NK_INTERN void -nk_textedit_makeundo_insert(struct nk_text_edit *state, int where, int length) -{ - nk_textedit_createundo(&state->undo, where, 0, length); -} - -NK_INTERN void -nk_textedit_makeundo_delete(struct nk_text_edit *state, int where, int length) -{ - int i; - nk_rune *p = nk_textedit_createundo(&state->undo, where, length, 0); - if (p) { - for (i=0; i < length; ++i) - p[i] = nk_str_rune_at(&state->string, where+i); - } -} - -NK_INTERN void -nk_textedit_makeundo_replace(struct nk_text_edit *state, int where, - int old_length, int new_length) -{ - int i; - nk_rune *p = nk_textedit_createundo(&state->undo, where, old_length, new_length); - if (p) { - for (i=0; i < old_length; ++i) - p[i] = nk_str_rune_at(&state->string, where+i); - } -} - -NK_INTERN void -nk_textedit_clear_state(struct nk_text_edit *state, enum nk_text_edit_type type, - nk_plugin_filter filter) -{ - /* reset the state to default */ - state->undo.undo_point = 0; - state->undo.undo_char_point = 0; - state->undo.redo_point = NK_TEXTEDIT_UNDOSTATECOUNT; - state->undo.redo_char_point = NK_TEXTEDIT_UNDOCHARCOUNT; - state->select_end = state->select_start = 0; - state->cursor = 0; - state->has_preferred_x = 0; - state->preferred_x = 0; - state->cursor_at_end_of_line = 0; - state->initialized = 1; - state->single_line = (unsigned char)(type == NK_TEXT_EDIT_SINGLE_LINE); - state->mode = NK_TEXT_EDIT_MODE_VIEW; - state->filter = filter; - state->scrollbar = nk_vec2(0,0); -} - -NK_API void -nk_textedit_init_fixed(struct nk_text_edit *state, void *memory, nk_size size) -{ - NK_ASSERT(state); - NK_ASSERT(memory); - if (!state || !memory || !size) return; - nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); - nk_str_init_fixed(&state->string, memory, size); -} - -NK_API void -nk_textedit_init(struct nk_text_edit *state, struct nk_allocator *alloc, nk_size size) -{ - NK_ASSERT(state); - NK_ASSERT(alloc); - if (!state || !alloc) return; - nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); - nk_str_init(&state->string, alloc, size); -} - -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -NK_API void -nk_textedit_init_default(struct nk_text_edit *state) -{ - NK_ASSERT(state); - if (!state) return; - nk_textedit_clear_state(state, NK_TEXT_EDIT_SINGLE_LINE, 0); - nk_str_init_default(&state->string); -} -#endif - -NK_API void -nk_textedit_select_all(struct nk_text_edit *state) -{ - NK_ASSERT(state); - state->select_start = 0; - state->select_end = state->string.len; -} - -NK_API void -nk_textedit_free(struct nk_text_edit *state) -{ - NK_ASSERT(state); - if (!state) return; - nk_str_free(&state->string); -} - -/* =============================================================== - * - * TEXT WIDGET - * - * ===============================================================*/ -#define nk_widget_state_reset(s)\ - if ((*(s)) & NK_WIDGET_STATE_MODIFIED)\ - (*(s)) = NK_WIDGET_STATE_INACTIVE|NK_WIDGET_STATE_MODIFIED;\ - else (*(s)) = NK_WIDGET_STATE_INACTIVE; - -struct nk_text { - struct nk_vec2 padding; - struct nk_color background; - struct nk_color text; -}; - -NK_INTERN 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) -{ - struct nk_rect label; - float text_width; - - NK_ASSERT(o); - NK_ASSERT(t); - if (!o || !t) return; - - b.h = NK_MAX(b.h, 2 * t->padding.y); - label.x = 0; label.w = 0; - label.y = b.y + t->padding.y; - label.h = NK_MIN(f->height, b.h - 2 * t->padding.y); - - text_width = f->width(f->userdata, f->height, (const char*)string, len); - text_width += (2.0f * t->padding.x); - - /* align in x-axis */ - if (a & NK_TEXT_ALIGN_LEFT) { - label.x = b.x + t->padding.x; - label.w = NK_MAX(0, b.w - 2 * t->padding.x); - } else if (a & NK_TEXT_ALIGN_CENTERED) { - label.w = NK_MAX(1, 2 * t->padding.x + (float)text_width); - label.x = (b.x + t->padding.x + ((b.w - 2 * t->padding.x) - label.w) / 2); - label.x = NK_MAX(b.x + t->padding.x, label.x); - label.w = NK_MIN(b.x + b.w, label.x + label.w); - if (label.w >= label.x) label.w -= label.x; - } else if (a & NK_TEXT_ALIGN_RIGHT) { - label.x = NK_MAX(b.x + t->padding.x, (b.x + b.w) - (2 * t->padding.x + (float)text_width)); - label.w = (float)text_width + 2 * t->padding.x; - } else return; - - /* align in y-axis */ - if (a & NK_TEXT_ALIGN_MIDDLE) { - label.y = b.y + b.h/2.0f - (float)f->height/2.0f; - label.h = NK_MAX(b.h/2.0f, b.h - (b.h/2.0f + f->height/2.0f)); - } else if (a & NK_TEXT_ALIGN_BOTTOM) { - label.y = b.y + b.h - f->height; - label.h = f->height; - } - nk_draw_text(o, label, (const char*)string, - len, f, t->background, t->text); -} - -NK_INTERN 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) -{ - float width; - int glyphs = 0; - int fitting = 0; - int done = 0; - struct nk_rect line; - struct nk_text text; - NK_INTERN nk_rune seperator[] = {' '}; - - NK_ASSERT(o); - NK_ASSERT(t); - if (!o || !t) return; - - text.padding = nk_vec2(0,0); - text.background = t->background; - text.text = t->text; - - b.w = NK_MAX(b.w, 2 * t->padding.x); - b.h = NK_MAX(b.h, 2 * t->padding.y); - b.h = b.h - 2 * t->padding.y; - - line.x = b.x + t->padding.x; - line.y = b.y + t->padding.y; - line.w = b.w - 2 * t->padding.x; - line.h = 2 * t->padding.y + f->height; - - fitting = nk_text_clamp(f, string, len, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); - while (done < len) { - if (!fitting || line.y + line.h >= (b.y + b.h)) break; - nk_widget_text(o, line, &string[done], fitting, &text, NK_TEXT_LEFT, f); - done += fitting; - line.y += f->height + 2 * t->padding.y; - fitting = nk_text_clamp(f, &string[done], len - done, line.w, &glyphs, &width, seperator,NK_LEN(seperator)); - } -} - -/* =============================================================== - * - * BUTTON - * - * ===============================================================*/ -NK_INTERN 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) -{ - switch (type) { - case NK_SYMBOL_X: - case NK_SYMBOL_UNDERSCORE: - case NK_SYMBOL_PLUS: - case NK_SYMBOL_MINUS: { - /* single character text symbol */ - const char *X = (type == NK_SYMBOL_X) ? "x": - (type == NK_SYMBOL_UNDERSCORE) ? "_": - (type == NK_SYMBOL_PLUS) ? "+": "-"; - struct nk_text text; - text.padding = nk_vec2(0,0); - text.background = background; - text.text = foreground; - nk_widget_text(out, content, X, 1, &text, NK_TEXT_CENTERED, font); - } break; - case NK_SYMBOL_CIRCLE_SOLID: - case NK_SYMBOL_CIRCLE_OUTLINE: - case NK_SYMBOL_RECT_SOLID: - case NK_SYMBOL_RECT_OUTLINE: { - /* simple empty/filled shapes */ - if (type == NK_SYMBOL_RECT_SOLID || type == NK_SYMBOL_RECT_OUTLINE) { - nk_fill_rect(out, content, 0, foreground); - if (type == NK_SYMBOL_RECT_OUTLINE) - nk_fill_rect(out, nk_shrink_rect(content, border_width), 0, background); - } else { - nk_fill_circle(out, content, foreground); - if (type == NK_SYMBOL_CIRCLE_OUTLINE) - nk_fill_circle(out, nk_shrink_rect(content, 1), background); - } - } break; - case NK_SYMBOL_TRIANGLE_UP: - case NK_SYMBOL_TRIANGLE_DOWN: - case NK_SYMBOL_TRIANGLE_LEFT: - case NK_SYMBOL_TRIANGLE_RIGHT: { - enum nk_heading heading; - struct nk_vec2 points[3]; - heading = (type == NK_SYMBOL_TRIANGLE_RIGHT) ? NK_RIGHT : - (type == NK_SYMBOL_TRIANGLE_LEFT) ? NK_LEFT: - (type == NK_SYMBOL_TRIANGLE_UP) ? NK_UP: NK_DOWN; - nk_triangle_from_direction(points, content, 0, 0, heading); - nk_fill_triangle(out, points[0].x, points[0].y, points[1].x, points[1].y, - points[2].x, points[2].y, foreground); - } break; - default: - case NK_SYMBOL_NONE: - case NK_SYMBOL_MAX: break; - } -} - -NK_INTERN int -nk_button_behavior(nk_flags *state, struct nk_rect r, - const struct nk_input *i, enum nk_button_behavior behavior) -{ - int ret = 0; - nk_widget_state_reset(state); - if (!i) return 0; - if (nk_input_is_mouse_hovering_rect(i, r)) { - *state = NK_WIDGET_STATE_HOVERED; - if (nk_input_is_mouse_down(i, NK_BUTTON_LEFT)) - *state = NK_WIDGET_STATE_ACTIVE; - if (nk_input_has_mouse_click_in_rect(i, NK_BUTTON_LEFT, r)) { - ret = (behavior != NK_BUTTON_DEFAULT) ? - nk_input_is_mouse_down(i, NK_BUTTON_LEFT): -#ifdef NK_BUTTON_TRIGGER_ON_RELEASE - nk_input_is_mouse_released(i, NK_BUTTON_LEFT); -#else - nk_input_is_mouse_pressed(i, NK_BUTTON_LEFT); -#endif - } - } - if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(i, r)) - *state |= NK_WIDGET_STATE_ENTERED; - else if (nk_input_is_mouse_prev_hovering_rect(i, r)) - *state |= NK_WIDGET_STATE_LEFT; - return ret; -} - -NK_INTERN 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) -{ - const struct nk_style_item *background; - if (state & NK_WIDGET_STATE_HOVER) - background = &style->hover; - else if (state & NK_WIDGET_STATE_ACTIVED) - background = &style->active; - else background = &style->normal; - - if (background->type == NK_STYLE_ITEM_IMAGE) { - nk_draw_image(out, *bounds, &background->data.image, nk_white); - } else { - nk_fill_rect(out, *bounds, style->rounding, background->data.color); - nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); - } - return background; -} - -NK_INTERN int -nk_do_button(nk_flags *state, struct nk_command_buffer *out, struct nk_rect r, - const struct nk_style_button *style, const struct nk_input *in, - enum nk_button_behavior behavior, struct nk_rect *content) -{ - struct nk_rect bounds; - NK_ASSERT(style); - NK_ASSERT(state); - NK_ASSERT(out); - if (!out || !style) - return nk_false; - - /* calculate button content space */ - content->x = r.x + style->padding.x + style->border + style->rounding; - content->y = r.y + style->padding.y + style->border + style->rounding; - content->w = r.w - (2 * style->padding.x + style->border + style->rounding*2); - content->h = r.h - (2 * style->padding.y + style->border + style->rounding*2); - - /* execute button behavior */ - bounds.x = r.x - style->touch_padding.x; - bounds.y = r.y - style->touch_padding.y; - bounds.w = r.w + 2 * style->touch_padding.x; - bounds.h = r.h + 2 * style->touch_padding.y; - return nk_button_behavior(state, bounds, in, behavior); -} - -NK_INTERN 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) -{ - struct nk_text text; - const struct nk_style_item *background; - background = nk_draw_button(out, bounds, state, style); - - /* select correct colors/images */ - if (background->type == NK_STYLE_ITEM_COLOR) - text.background = background->data.color; - else text.background = style->text_background; - if (state & NK_WIDGET_STATE_HOVER) - text.text = style->text_hover; - else if (state & NK_WIDGET_STATE_ACTIVED) - text.text = style->text_active; - else text.text = style->text_normal; - - text.padding = nk_vec2(0,0); - nk_widget_text(out, *content, txt, len, &text, text_alignment, font); -} - -NK_INTERN int -nk_do_button_text(nk_flags *state, - struct nk_command_buffer *out, struct nk_rect bounds, - const char *string, int len, nk_flags align, enum nk_button_behavior behavior, - const struct nk_style_button *style, const struct nk_input *in, - const struct nk_user_font *font) -{ - struct nk_rect content; - int ret = nk_false; - - NK_ASSERT(state); - NK_ASSERT(style); - NK_ASSERT(out); - NK_ASSERT(string); - NK_ASSERT(font); - if (!out || !style || !font || !string) - return nk_false; - - ret = nk_do_button(state, out, bounds, style, in, behavior, &content); - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_button_text(out, &bounds, &content, *state, style, string, len, align, font); - if (style->draw_end) style->draw_end(out, style->userdata); - return ret; -} - -NK_INTERN 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) -{ - struct nk_color sym, bg; - const struct nk_style_item *background; - - /* select correct colors/images */ - background = nk_draw_button(out, bounds, state, style); - if (background->type == NK_STYLE_ITEM_COLOR) - bg = background->data.color; - else bg = style->text_background; - - if (state & NK_WIDGET_STATE_HOVER) - sym = style->text_hover; - else if (state & NK_WIDGET_STATE_ACTIVED) - sym = style->text_active; - else sym = style->text_normal; - nk_draw_symbol(out, type, *content, bg, sym, 1, font); -} - -NK_INTERN int -nk_do_button_symbol(nk_flags *state, - struct nk_command_buffer *out, struct nk_rect bounds, - enum nk_symbol_type symbol, enum nk_button_behavior behavior, - const struct nk_style_button *style, const struct nk_input *in, - const struct nk_user_font *font) -{ - int ret; - struct nk_rect content; - - NK_ASSERT(state); - NK_ASSERT(style); - NK_ASSERT(font); - NK_ASSERT(out); - if (!out || !style || !font || !state) - return nk_false; - - ret = nk_do_button(state, out, bounds, style, in, behavior, &content); - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_button_symbol(out, &bounds, &content, *state, style, symbol, font); - if (style->draw_end) style->draw_end(out, style->userdata); - return ret; -} - -NK_INTERN 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) -{ - nk_draw_button(out, bounds, state, style); - nk_draw_image(out, *content, img, nk_white); -} - -NK_INTERN int -nk_do_button_image(nk_flags *state, - struct nk_command_buffer *out, struct nk_rect bounds, - struct nk_image img, enum nk_button_behavior b, - const struct nk_style_button *style, const struct nk_input *in) -{ - int ret; - struct nk_rect content; - - NK_ASSERT(state); - NK_ASSERT(style); - NK_ASSERT(out); - if (!out || !style || !state) - return nk_false; - - ret = nk_do_button(state, out, bounds, style, in, b, &content); - content.x += style->image_padding.x; - content.y += style->image_padding.y; - content.w -= 2 * style->image_padding.x; - content.h -= 2 * style->image_padding.y; - - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_button_image(out, &bounds, &content, *state, style, &img); - if (style->draw_end) style->draw_end(out, style->userdata); - return ret; -} - -NK_INTERN 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) -{ - struct nk_color sym; - struct nk_text text; - const struct nk_style_item *background; - - /* select correct background colors/images */ - background = nk_draw_button(out, bounds, state, style); - if (background->type == NK_STYLE_ITEM_COLOR) - text.background = background->data.color; - else text.background = style->text_background; - - /* select correct text colors */ - if (state & NK_WIDGET_STATE_HOVER) { - sym = style->text_hover; - text.text = style->text_hover; - } else if (state & NK_WIDGET_STATE_ACTIVED) { - sym = style->text_active; - text.text = style->text_active; - } else { - sym = style->text_normal; - text.text = style->text_normal; - } - - text.padding = nk_vec2(0,0); - nk_draw_symbol(out, type, *symbol, style->text_background, sym, 0, font); - nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); -} - -NK_INTERN int -nk_do_button_text_symbol(nk_flags *state, - struct nk_command_buffer *out, struct nk_rect bounds, - enum nk_symbol_type symbol, const char *str, int len, nk_flags align, - enum nk_button_behavior behavior, const struct nk_style_button *style, - const struct nk_user_font *font, const struct nk_input *in) -{ - int ret; - struct nk_rect tri = {0,0,0,0}; - struct nk_rect content; - - NK_ASSERT(style); - NK_ASSERT(out); - NK_ASSERT(font); - if (!out || !style || !font) - return nk_false; - - ret = nk_do_button(state, out, bounds, style, in, behavior, &content); - tri.y = content.y + (content.h/2) - font->height/2; - tri.w = font->height; tri.h = font->height; - if (align & NK_TEXT_ALIGN_LEFT) { - tri.x = (content.x + content.w) - (2 * style->padding.x + tri.w); - tri.x = NK_MAX(tri.x, 0); - } else tri.x = content.x + 2 * style->padding.x; - - /* draw button */ - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_button_text_symbol(out, &bounds, &content, &tri, - *state, style, str, len, symbol, font); - if (style->draw_end) style->draw_end(out, style->userdata); - return ret; -} - -NK_INTERN 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) -{ - struct nk_text text; - const struct nk_style_item *background; - background = nk_draw_button(out, bounds, state, style); - - /* select correct colors */ - if (background->type == NK_STYLE_ITEM_COLOR) - text.background = background->data.color; - else text.background = style->text_background; - if (state & NK_WIDGET_STATE_HOVER) - text.text = style->text_hover; - else if (state & NK_WIDGET_STATE_ACTIVED) - text.text = style->text_active; - else text.text = style->text_normal; - - text.padding = nk_vec2(0,0); - nk_widget_text(out, *label, str, len, &text, NK_TEXT_CENTERED, font); - nk_draw_image(out, *image, img, nk_white); -} - -NK_INTERN int -nk_do_button_text_image(nk_flags *state, - struct nk_command_buffer *out, struct nk_rect bounds, - struct nk_image img, const char* str, int len, nk_flags align, - enum nk_button_behavior behavior, const struct nk_style_button *style, - const struct nk_user_font *font, const struct nk_input *in) -{ - int ret; - struct nk_rect icon; - struct nk_rect content; - - NK_ASSERT(style); - NK_ASSERT(state); - NK_ASSERT(font); - NK_ASSERT(out); - if (!out || !font || !style || !str) - return nk_false; - - ret = nk_do_button(state, out, bounds, style, in, behavior, &content); - icon.y = bounds.y + style->padding.y; - icon.w = icon.h = bounds.h - 2 * style->padding.y; - if (align & NK_TEXT_ALIGN_LEFT) { - icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); - icon.x = NK_MAX(icon.x, 0); - } else icon.x = bounds.x + 2 * style->padding.x; - - icon.x += style->image_padding.x; - icon.y += style->image_padding.y; - icon.w -= 2 * style->image_padding.x; - icon.h -= 2 * style->image_padding.y; - - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_button_text_image(out, &bounds, &content, &icon, *state, style, str, len, font, &img); - if (style->draw_end) style->draw_end(out, style->userdata); - return ret; -} - -/* =============================================================== - * - * TOGGLE - * - * ===============================================================*/ -enum nk_toggle_type { - NK_TOGGLE_CHECK, - NK_TOGGLE_OPTION -}; - -NK_INTERN int -nk_toggle_behavior(const struct nk_input *in, struct nk_rect select, - nk_flags *state, int active) -{ - nk_widget_state_reset(state); - if (nk_button_behavior(state, select, in, NK_BUTTON_DEFAULT)) { - *state = NK_WIDGET_STATE_ACTIVE; - active = !active; - } - if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, select)) - *state |= NK_WIDGET_STATE_ENTERED; - else if (nk_input_is_mouse_prev_hovering_rect(in, select)) - *state |= NK_WIDGET_STATE_LEFT; - return active; -} - -NK_INTERN void -nk_draw_checkbox(struct nk_command_buffer *out, - nk_flags state, const struct nk_style_toggle *style, int active, - const struct nk_rect *label, const struct nk_rect *selector, - const struct nk_rect *cursors, const char *string, int len, - const struct nk_user_font *font) -{ - const struct nk_style_item *background; - const struct nk_style_item *cursor; - struct nk_text text; - - /* select correct colors/images */ - if (state & NK_WIDGET_STATE_HOVER) { - background = &style->hover; - cursor = &style->cursor_hover; - text.text = style->text_hover; - } else if (state & NK_WIDGET_STATE_ACTIVED) { - background = &style->hover; - cursor = &style->cursor_hover; - text.text = style->text_active; - } else { - background = &style->normal; - cursor = &style->cursor_normal; - text.text = style->text_normal; - } - - /* draw background and cursor */ - if (background->type == NK_STYLE_ITEM_COLOR) { - nk_fill_rect(out, *selector, 0, style->border_color); - nk_fill_rect(out, nk_shrink_rect(*selector, style->border), 0, background->data.color); - } else nk_draw_image(out, *selector, &background->data.image, nk_white); - if (active) { - if (cursor->type == NK_STYLE_ITEM_IMAGE) - nk_draw_image(out, *cursors, &cursor->data.image, nk_white); - else nk_fill_rect(out, *cursors, 0, cursor->data.color); - } - - text.padding.x = 0; - text.padding.y = 0; - text.background = style->text_background; - nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); -} - -NK_INTERN void -nk_draw_option(struct nk_command_buffer *out, - nk_flags state, const struct nk_style_toggle *style, int active, - const struct nk_rect *label, const struct nk_rect *selector, - const struct nk_rect *cursors, const char *string, int len, - const struct nk_user_font *font) -{ - const struct nk_style_item *background; - const struct nk_style_item *cursor; - struct nk_text text; - - /* select correct colors/images */ - if (state & NK_WIDGET_STATE_HOVER) { - background = &style->hover; - cursor = &style->cursor_hover; - text.text = style->text_hover; - } else if (state & NK_WIDGET_STATE_ACTIVED) { - background = &style->hover; - cursor = &style->cursor_hover; - text.text = style->text_active; - } else { - background = &style->normal; - cursor = &style->cursor_normal; - text.text = style->text_normal; - } - - /* draw background and cursor */ - if (background->type == NK_STYLE_ITEM_COLOR) { - nk_fill_circle(out, *selector, style->border_color); - nk_fill_circle(out, nk_shrink_rect(*selector, style->border), background->data.color); - } else nk_draw_image(out, *selector, &background->data.image, nk_white); - if (active) { - if (cursor->type == NK_STYLE_ITEM_IMAGE) - nk_draw_image(out, *cursors, &cursor->data.image, nk_white); - else nk_fill_circle(out, *cursors, cursor->data.color); - } - - text.padding.x = 0; - text.padding.y = 0; - text.background = style->text_background; - nk_widget_text(out, *label, string, len, &text, NK_TEXT_LEFT, font); -} - -NK_INTERN int -nk_do_toggle(nk_flags *state, - struct nk_command_buffer *out, struct nk_rect r, - int *active, const char *str, int len, enum nk_toggle_type type, - const struct nk_style_toggle *style, const struct nk_input *in, - const struct nk_user_font *font) -{ - int was_active; - struct nk_rect bounds; - struct nk_rect select; - struct nk_rect cursor; - struct nk_rect label; - - NK_ASSERT(style); - NK_ASSERT(out); - NK_ASSERT(font); - if (!out || !style || !font || !active) - return 0; - - r.w = NK_MAX(r.w, font->height + 2 * style->padding.x); - r.h = NK_MAX(r.h, font->height + 2 * style->padding.y); - - /* add additional touch padding for touch screen devices */ - bounds.x = r.x - style->touch_padding.x; - bounds.y = r.y - style->touch_padding.y; - bounds.w = r.w + 2 * style->touch_padding.x; - bounds.h = r.h + 2 * style->touch_padding.y; - - /* calculate the selector space */ - select.w = font->height; - select.h = select.w; - select.y = r.y + r.h/2.0f - select.h/2.0f; - select.x = r.x; - - /* calculate the bounds of the cursor inside the selector */ - cursor.x = select.x + style->padding.x + style->border; - cursor.y = select.y + style->padding.y + style->border; - cursor.w = select.w - (2 * style->padding.x + 2 * style->border); - cursor.h = select.h - (2 * style->padding.y + 2 * style->border); - - /* label behind the selector */ - label.x = select.x + select.w + style->spacing; - label.y = select.y; - label.w = NK_MAX(r.x + r.w, label.x) - label.x; - label.h = select.w; - - /* update selector */ - was_active = *active; - *active = nk_toggle_behavior(in, bounds, state, *active); - - /* draw selector */ - if (style->draw_begin) - style->draw_begin(out, style->userdata); - if (type == NK_TOGGLE_CHECK) { - nk_draw_checkbox(out, *state, style, *active, &label, &select, &cursor, str, len, font); - } else { - nk_draw_option(out, *state, style, *active, &label, &select, &cursor, str, len, font); - } - if (style->draw_end) - style->draw_end(out, style->userdata); - return (was_active != *active); -} - -/* =============================================================== - * - * SELECTABLE - * - * ===============================================================*/ -NK_INTERN void -nk_draw_selectable(struct nk_command_buffer *out, - nk_flags state, const struct nk_style_selectable *style, int active, - const struct nk_rect *bounds, const struct nk_rect *icon, const struct nk_image *img, - const char *string, int len, nk_flags align, const struct nk_user_font *font) -{ - const struct nk_style_item *background; - struct nk_text text; - text.padding = style->padding; - - /* select correct colors/images */ - if (!active) { - if (state & NK_WIDGET_STATE_ACTIVED) { - background = &style->pressed; - text.text = style->text_pressed; - } else if (state & NK_WIDGET_STATE_HOVER) { - background = &style->hover; - text.text = style->text_hover; - } else { - background = &style->normal; - text.text = style->text_normal; - } - } else { - if (state & NK_WIDGET_STATE_ACTIVED) { - background = &style->pressed_active; - text.text = style->text_pressed_active; - } else if (state & NK_WIDGET_STATE_HOVER) { - background = &style->hover_active; - text.text = style->text_hover_active; - } else { - background = &style->normal_active; - text.text = style->text_normal_active; - } - } - - - /* draw selectable background and text */ - if (background->type == NK_STYLE_ITEM_IMAGE) { - nk_draw_image(out, *bounds, &background->data.image, nk_white); - text.background = nk_rgba(0,0,0,0); - } else { - nk_fill_rect(out, *bounds, style->rounding, background->data.color); - text.background = background->data.color; - } - if (img && icon) nk_draw_image(out, *icon, img, nk_white); - nk_widget_text(out, *bounds, string, len, &text, align, font); -} - -NK_INTERN int -nk_do_selectable(nk_flags *state, struct nk_command_buffer *out, - struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, - const struct nk_style_selectable *style, const struct nk_input *in, - const struct nk_user_font *font) -{ - int old_value; - struct nk_rect touch; - - NK_ASSERT(state); - NK_ASSERT(out); - NK_ASSERT(str); - NK_ASSERT(len); - NK_ASSERT(value); - NK_ASSERT(style); - NK_ASSERT(font); - - if (!state || !out || !str || !len || !value || !style || !font) return 0; - old_value = *value; - - /* remove padding */ - touch.x = bounds.x - style->touch_padding.x; - touch.y = bounds.y - style->touch_padding.y; - touch.w = bounds.w + style->touch_padding.x * 2; - touch.h = bounds.h + style->touch_padding.y * 2; - - /* update button */ - if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) - *value = !(*value); - - /* draw selectable */ - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_selectable(out, *state, style, *value, &bounds, 0,0, str, len, align, font); - if (style->draw_end) style->draw_end(out, style->userdata); - return old_value != *value; -} - -NK_INTERN int -nk_do_selectable_image(nk_flags *state, struct nk_command_buffer *out, - struct nk_rect bounds, const char *str, int len, nk_flags align, int *value, - const struct nk_image *img, const struct nk_style_selectable *style, - const struct nk_input *in, const struct nk_user_font *font) -{ - int old_value; - struct nk_rect touch; - struct nk_rect icon; - - NK_ASSERT(state); - NK_ASSERT(out); - NK_ASSERT(str); - NK_ASSERT(len); - NK_ASSERT(value); - NK_ASSERT(style); - NK_ASSERT(font); - - if (!state || !out || !str || !len || !value || !style || !font) return 0; - old_value = *value; - - /* toggle behavior */ - touch.x = bounds.x - style->touch_padding.x; - touch.y = bounds.y - style->touch_padding.y; - touch.w = bounds.w + style->touch_padding.x * 2; - touch.h = bounds.h + style->touch_padding.y * 2; - if (nk_button_behavior(state, touch, in, NK_BUTTON_DEFAULT)) - *value = !(*value); - - icon.y = bounds.y + style->padding.y; - icon.w = icon.h = bounds.h - 2 * style->padding.y; - if (align & NK_TEXT_ALIGN_LEFT) { - icon.x = (bounds.x + bounds.w) - (2 * style->padding.x + icon.w); - icon.x = NK_MAX(icon.x, 0); - } else icon.x = bounds.x + 2 * style->padding.x; - - icon.x += style->image_padding.x; - icon.y += style->image_padding.y; - icon.w -= 2 * style->image_padding.x; - icon.h -= 2 * style->image_padding.y; - - /* draw selectable */ - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_selectable(out, *state, style, *value, &bounds, &icon, img, str, len, align, font); - if (style->draw_end) style->draw_end(out, style->userdata); - return old_value != *value; -} - - -/* =============================================================== - * - * SLIDER - * - * ===============================================================*/ -NK_INTERN float -nk_slider_behavior(nk_flags *state, struct nk_rect *logical_cursor, - struct nk_rect *visual_cursor, struct nk_input *in, - const struct nk_style_slider *style, struct nk_rect bounds, - float slider_min, float slider_max, float slider_value, - float slider_step, float slider_steps) -{ - int left_mouse_down; - int left_mouse_click_in_cursor; - - /* check if visual cursor is being dragged */ - nk_widget_state_reset(state); - left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; - left_mouse_click_in_cursor = in && nk_input_has_mouse_click_down_in_rect(in, - NK_BUTTON_LEFT, *visual_cursor, nk_true); - - if (left_mouse_down && left_mouse_click_in_cursor) - { - float ratio = 0; - const float d = in->mouse.pos.x - (visual_cursor->x + visual_cursor->w / 2.0f); - const float pxstep = (bounds.w - (2 * style->padding.x)) / slider_steps; - - /* only update value if the next slider step is reached */ - *state = NK_WIDGET_STATE_ACTIVE; - if (NK_ABS(d) >= pxstep) { - const float steps = (float)((int)(NK_ABS(d) / pxstep)); - slider_value += (d > 0) ? (slider_step*steps) : -(slider_step*steps); - slider_value = NK_CLAMP(slider_min, slider_value, slider_max); - ratio = (slider_value - slider_min)/slider_step; - logical_cursor->x = bounds.x + (logical_cursor->w * ratio); - in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = logical_cursor->x + logical_cursor->w/2.0f; - } - } - - /* slider widget state */ - if (nk_input_is_mouse_hovering_rect(in, bounds)) - *state = NK_WIDGET_STATE_HOVERED; - if (*state & NK_WIDGET_STATE_HOVER && - !nk_input_is_mouse_prev_hovering_rect(in, bounds)) - *state |= NK_WIDGET_STATE_ENTERED; - else if (nk_input_is_mouse_prev_hovering_rect(in, bounds)) - *state |= NK_WIDGET_STATE_LEFT; - return slider_value; -} - -NK_INTERN 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) -{ - struct nk_rect fill; - struct nk_rect bar; - const struct nk_style_item *background; - - /* select correct slider images/colors */ - struct nk_color bar_color; - const struct nk_style_item *cursor; - - NK_UNUSED(min); - NK_UNUSED(max); - NK_UNUSED(value); - - if (state & NK_WIDGET_STATE_ACTIVED) { - background = &style->active; - bar_color = style->bar_active; - cursor = &style->cursor_active; - } else if (state & NK_WIDGET_STATE_HOVER) { - background = &style->hover; - bar_color = style->bar_hover; - cursor = &style->cursor_hover; - } else { - background = &style->normal; - bar_color = style->bar_normal; - cursor = &style->cursor_normal; - } - - /* calculate slider background bar */ - bar.x = bounds->x; - bar.y = (visual_cursor->y + visual_cursor->h/2) - bounds->h/12; - bar.w = bounds->w; - bar.h = bounds->h/6; - - /* filled background bar style */ - fill.w = (visual_cursor->x + (visual_cursor->w/2.0f)) - bar.x; - fill.x = bar.x; - fill.y = bar.y; - fill.h = bar.h; - - /* draw background */ - if (background->type == NK_STYLE_ITEM_IMAGE) { - nk_draw_image(out, *bounds, &background->data.image, nk_white); - } else { - nk_fill_rect(out, *bounds, style->rounding, background->data.color); - nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); - } - - /* draw slider bar */ - nk_fill_rect(out, bar, style->rounding, bar_color); - nk_fill_rect(out, fill, style->rounding, style->bar_filled); - - /* draw cursor */ - if (cursor->type == NK_STYLE_ITEM_IMAGE) - nk_draw_image(out, *visual_cursor, &cursor->data.image, nk_white); - else nk_fill_circle(out, *visual_cursor, cursor->data.color); -} - -NK_INTERN 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) -{ - float slider_range; - float slider_min; - float slider_max; - float slider_value; - float slider_steps; - float cursor_offset; - - struct nk_rect visual_cursor; - struct nk_rect logical_cursor; - - NK_ASSERT(style); - NK_ASSERT(out); - if (!out || !style) - return 0; - - /* remove padding from slider bounds */ - bounds.x = bounds.x + style->padding.x; - bounds.y = bounds.y + style->padding.y; - bounds.h = NK_MAX(bounds.h, 2*style->padding.y); - bounds.w = NK_MAX(bounds.w, 2*style->padding.x + style->cursor_size.x); - bounds.w -= 2 * style->padding.x; - bounds.h -= 2 * style->padding.y; - - /* optional buttons */ - if (style->show_buttons) { - nk_flags ws; - struct nk_rect button; - button.y = bounds.y; - button.w = bounds.h; - button.h = bounds.h; - - /* decrement button */ - button.x = bounds.x; - if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, NK_BUTTON_DEFAULT, - &style->dec_button, in, font)) - val -= step; - - /* increment button */ - button.x = (bounds.x + bounds.w) - button.w; - if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, NK_BUTTON_DEFAULT, - &style->inc_button, in, font)) - val += step; - - bounds.x = bounds.x + button.w + style->spacing.x; - bounds.w = bounds.w - (2*button.w + 2*style->spacing.x); - } - - /* make sure the provided values are correct */ - slider_max = NK_MAX(min, max); - slider_min = NK_MIN(min, max); - slider_value = NK_CLAMP(slider_min, val, slider_max); - slider_range = slider_max - slider_min; - slider_steps = slider_range / step; - cursor_offset = (slider_value - slider_min) / step; - - /* remove one cursor size to support visual cursor */ - bounds.x += style->cursor_size.x*0.5f; - bounds.w -= style->cursor_size.x; - - /* calculate cursor - Basically you have two cursors. One for visual representation and interaction - and one for updating the actual cursor value. */ - logical_cursor.h = bounds.h; - logical_cursor.w = bounds.w / slider_steps; - logical_cursor.x = bounds.x + (logical_cursor.w * cursor_offset); - logical_cursor.y = bounds.y; - - visual_cursor.h = style->cursor_size.y; - visual_cursor.w = style->cursor_size.x; - visual_cursor.y = (bounds.y + bounds.h*0.5f) - visual_cursor.h*0.5f; - visual_cursor.x = (logical_cursor.x + logical_cursor.w*0.5f) - visual_cursor.w*0.5f; - - slider_value = nk_slider_behavior(state, &logical_cursor, &visual_cursor, - in, style, bounds, slider_min, slider_max, slider_value, step, slider_steps); - visual_cursor.x = logical_cursor.x - visual_cursor.w*0.5f; - - /* draw slider */ - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_slider(out, *state, style, &bounds, &visual_cursor, slider_min, slider_value, slider_max); - if (style->draw_end) style->draw_end(out, style->userdata); - return slider_value; -} - -/* =============================================================== - * - * PROGRESSBAR - * - * ===============================================================*/ -NK_INTERN nk_size -nk_progress_behavior(nk_flags *state, const struct nk_input *in, - struct nk_rect r, nk_size max, nk_size value, int modifiable) -{ - nk_widget_state_reset(state); - if (in && modifiable && nk_input_is_mouse_hovering_rect(in, r)) { - int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; - int left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, - NK_BUTTON_LEFT, r, nk_true); - - if (left_mouse_down && left_mouse_click_in_cursor) { - float ratio = NK_MAX(0, (float)(in->mouse.pos.x - r.x)) / (float)r.w; - value = (nk_size)NK_MAX(0,((float)max * ratio)); - *state = NK_WIDGET_STATE_ACTIVE; - } else *state = NK_WIDGET_STATE_HOVERED; - } - - /* set progressbar widget state */ - if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, r)) - *state |= NK_WIDGET_STATE_ENTERED; - else if (nk_input_is_mouse_prev_hovering_rect(in, r)) - *state |= NK_WIDGET_STATE_LEFT; - - if (!max) return value; - value = NK_MIN(value, max); - return value; -} - -NK_INTERN 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) -{ - const struct nk_style_item *background; - const struct nk_style_item *cursor; - - NK_UNUSED(max); - NK_UNUSED(value); - - /* select correct colors/images to draw */ - if (state & NK_WIDGET_STATE_ACTIVED) { - background = &style->active; - cursor = &style->cursor_active; - } else if (state & NK_WIDGET_STATE_HOVER){ - background = &style->hover; - cursor = &style->cursor_hover; - } else { - background = &style->normal; - cursor = &style->cursor_normal; - } - - /* draw background */ - if (background->type == NK_STYLE_ITEM_COLOR) { - nk_fill_rect(out, *bounds, style->rounding, background->data.color); - nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); - } else nk_draw_image(out, *bounds, &background->data.image, nk_white); - - /* draw cursor */ - if (background->type == NK_STYLE_ITEM_COLOR) { - nk_fill_rect(out, *scursor, style->rounding, cursor->data.color); - nk_stroke_rect(out, *scursor, style->rounding, style->border, style->border_color); - } else nk_draw_image(out, *scursor, &cursor->data.image, nk_white); -} - -NK_INTERN nk_size -nk_do_progress(nk_flags *state, - struct nk_command_buffer *out, struct nk_rect bounds, - nk_size value, nk_size max, int modifiable, - const struct nk_style_progress *style, const struct nk_input *in) -{ - float prog_scale; - nk_size prog_value; - struct nk_rect cursor; - - NK_ASSERT(style); - NK_ASSERT(out); - if (!out || !style) return 0; - - /* calculate progressbar cursor */ - cursor.w = NK_MAX(bounds.w, 2 * style->padding.x + 2 * style->border); - cursor.h = NK_MAX(bounds.h, 2 * style->padding.y + 2 * style->border); - cursor = nk_pad_rect(bounds, nk_vec2(style->padding.x + style->border, style->padding.y + style->border)); - prog_scale = (float)value / (float)max; - cursor.w = (bounds.w - 2) * prog_scale; - - /* update progressbar */ - prog_value = NK_MIN(value, max); - prog_value = nk_progress_behavior(state, in, bounds, max, prog_value, modifiable); - - /* draw progressbar */ - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_progress(out, *state, style, &bounds, &cursor, value, max); - if (style->draw_end) style->draw_end(out, style->userdata); - return prog_value; -} - -/* =============================================================== - * - * SCROLLBAR - * - * ===============================================================*/ -NK_INTERN 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) -{ - nk_flags ws; - int left_mouse_down; - int left_mouse_click_in_cursor; - - nk_widget_state_reset(state); - if (!in) return scroll_offset; - - left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; - left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, - NK_BUTTON_LEFT, *cursor, nk_true); - if (nk_input_is_mouse_hovering_rect(in, *scroll)) - *state = NK_WIDGET_STATE_HOVERED; - - if (left_mouse_down && left_mouse_click_in_cursor) { - /* update cursor by mouse dragging */ - float pixel, delta; - *state = NK_WIDGET_STATE_ACTIVE; - if (o == NK_VERTICAL) { - float cursor_y; - pixel = in->mouse.delta.y; - delta = (pixel / scroll->h) * target; - scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->h); - cursor_y = scroll->y + ((scroll_offset/target) * scroll->h); - in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = cursor_y + cursor->h/2.0f; - } else { - float cursor_x; - pixel = in->mouse.delta.x; - delta = (pixel / scroll->w) * target; - scroll_offset = NK_CLAMP(0, scroll_offset + delta, target - scroll->w); - cursor_x = scroll->x + ((scroll_offset/target) * scroll->w); - in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = cursor_x + cursor->w/2.0f; - } - } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_UP) && o == NK_VERTICAL && has_scrolling)|| - nk_button_behavior(&ws, *empty0, in, NK_BUTTON_DEFAULT)) { - /* scroll page up by click on empty space or shortcut */ - if (o == NK_VERTICAL) - scroll_offset = NK_MAX(0, scroll_offset - scroll->h); - else scroll_offset = NK_MAX(0, scroll_offset - scroll->w); - } else if ((nk_input_is_key_pressed(in, NK_KEY_SCROLL_DOWN) && o == NK_VERTICAL && has_scrolling) || - nk_button_behavior(&ws, *empty1, in, NK_BUTTON_DEFAULT)) { - /* scroll page down by click on empty space or shortcut */ - if (o == NK_VERTICAL) - scroll_offset = NK_MIN(scroll_offset + scroll->h, target - scroll->h); - else scroll_offset = NK_MIN(scroll_offset + scroll->w, target - scroll->w); - } else if (has_scrolling) { - if ((in->mouse.scroll_delta<0 || (in->mouse.scroll_delta>0))) { - /* update cursor by mouse scrolling */ - scroll_offset = scroll_offset + scroll_step * (-in->mouse.scroll_delta); - if (o == NK_VERTICAL) - scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->h); - else scroll_offset = NK_CLAMP(0, scroll_offset, target - scroll->w); - } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_START)) { - /* update cursor to the beginning */ - if (o == NK_VERTICAL) scroll_offset = 0; - } else if (nk_input_is_key_pressed(in, NK_KEY_SCROLL_END)) { - /* update cursor to the end */ - if (o == NK_VERTICAL) scroll_offset = target - scroll->h; - } - } - if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *scroll)) - *state |= NK_WIDGET_STATE_ENTERED; - else if (nk_input_is_mouse_prev_hovering_rect(in, *scroll)) - *state |= NK_WIDGET_STATE_LEFT; - return scroll_offset; -} - -NK_INTERN 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) -{ - const struct nk_style_item *background; - const struct nk_style_item *cursor; - - /* select correct colors/images to draw */ - if (state & NK_WIDGET_STATE_ACTIVED) { - background = &style->active; - cursor = &style->cursor_active; - } else if (state & NK_WIDGET_STATE_HOVER) { - background = &style->hover; - cursor = &style->cursor_hover; - } else { - background = &style->normal; - cursor = &style->cursor_normal; - } - - /* draw background */ - if (background->type == NK_STYLE_ITEM_COLOR) { - nk_fill_rect(out, *bounds, style->rounding, background->data.color); - nk_stroke_rect(out, *bounds, style->rounding, style->border, style->border_color); - } else { - nk_draw_image(out, *bounds, &background->data.image, nk_white); - } - - /* draw cursor */ - if (background->type == NK_STYLE_ITEM_COLOR) { - nk_fill_rect(out, *scroll, style->rounding_cursor, cursor->data.color); - nk_stroke_rect(out, *scroll, style->rounding_cursor, style->border_cursor, style->cursor_border_color); - } else nk_draw_image(out, *scroll, &cursor->data.image, nk_white); -} - -NK_INTERN 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) -{ - struct nk_rect empty_north; - struct nk_rect empty_south; - struct nk_rect cursor; - - float scroll_step; - float scroll_offset; - float scroll_off; - float scroll_ratio; - - NK_ASSERT(out); - NK_ASSERT(style); - NK_ASSERT(state); - if (!out || !style) return 0; - - scroll.w = NK_MAX(scroll.w, 1); - scroll.h = NK_MAX(scroll.h, 2 * scroll.w); - if (target <= scroll.h) return 0; - - /* optional scrollbar buttons */ - if (style->show_buttons) { - nk_flags ws; - float scroll_h; - struct nk_rect button; - - button.x = scroll.x; - button.w = scroll.w; - button.h = scroll.w; - - scroll_h = scroll.h - 2 * button.h; - scroll_step = NK_MIN(step, button_pixel_inc); - - /* decrement button */ - button.y = scroll.y; - if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, - NK_BUTTON_REPEATER, &style->dec_button, in, font)) - offset = offset - scroll_step; - - /* increment button */ - button.y = scroll.y + scroll.h - button.h; - if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, - NK_BUTTON_REPEATER, &style->inc_button, in, font)) - offset = offset + scroll_step; - - scroll.y = scroll.y + button.h; - scroll.h = scroll_h; - } - - /* calculate scrollbar constants */ - scroll_step = NK_MIN(step, scroll.h); - scroll_offset = NK_CLAMP(0, offset, target - scroll.h); - scroll_ratio = scroll.h / target; - scroll_off = scroll_offset / target; - - /* calculate scrollbar cursor bounds */ - cursor.h = (scroll_ratio * scroll.h) - (2*style->border + 2*style->padding.y); - cursor.y = scroll.y + (scroll_off * scroll.h) + style->border + style->padding.y; - cursor.w = scroll.w - (2 * style->border + 2 * style->padding.x); - cursor.x = scroll.x + style->border + style->padding.x; - - /* calculate empty space around cursor */ - empty_north.x = scroll.x; - empty_north.y = scroll.y; - empty_north.w = scroll.w; - empty_north.h = cursor.y - scroll.y; - - empty_south.x = scroll.x; - empty_south.y = cursor.y + cursor.h; - empty_south.w = scroll.w; - empty_south.h = (scroll.y + scroll.h) - (cursor.y + cursor.h); - - /* update scrollbar */ - scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, - &empty_north, &empty_south, scroll_offset, target, scroll_step, NK_VERTICAL); - scroll_off = scroll_offset / target; - cursor.y = scroll.y + (scroll_off * scroll.h) + style->border_cursor + style->padding.y; - - /* draw scrollbar */ - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_scrollbar(out, *state, style, &scroll, &cursor); - if (style->draw_end) style->draw_end(out, style->userdata); - return scroll_offset; -} - -NK_INTERN 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) -{ - struct nk_rect cursor; - struct nk_rect empty_west; - struct nk_rect empty_east; - - float scroll_step; - float scroll_offset; - float scroll_off; - float scroll_ratio; - - NK_ASSERT(out); - NK_ASSERT(style); - if (!out || !style) return 0; - - /* scrollbar background */ - scroll.h = NK_MAX(scroll.h, 1); - scroll.w = NK_MAX(scroll.w, 2 * scroll.h); - if (target <= scroll.w) return 0; - - /* optional scrollbar buttons */ - if (style->show_buttons) { - nk_flags ws; - float scroll_w; - struct nk_rect button; - button.y = scroll.y; - button.w = scroll.h; - button.h = scroll.h; - - scroll_w = scroll.w - 2 * button.w; - scroll_step = NK_MIN(step, button_pixel_inc); - - /* decrement button */ - button.x = scroll.x; - if (nk_do_button_symbol(&ws, out, button, style->dec_symbol, - NK_BUTTON_REPEATER, &style->dec_button, in, font)) - offset = offset - scroll_step; - - /* increment button */ - button.x = scroll.x + scroll.w - button.w; - if (nk_do_button_symbol(&ws, out, button, style->inc_symbol, - NK_BUTTON_REPEATER, &style->inc_button, in, font)) - offset = offset + scroll_step; - - scroll.x = scroll.x + button.w; - scroll.w = scroll_w; - } - - /* calculate scrollbar constants */ - scroll_step = NK_MIN(step, scroll.w); - scroll_offset = NK_CLAMP(0, offset, target - scroll.w); - scroll_ratio = scroll.w / target; - scroll_off = scroll_offset / target; - - /* calculate cursor bounds */ - cursor.w = (scroll_ratio * scroll.w) - (2*style->border + 2*style->padding.x); - cursor.x = scroll.x + (scroll_off * scroll.w) + style->border + style->padding.x; - cursor.h = scroll.h - (2 * style->border + 2 * style->padding.y); - cursor.y = scroll.y + style->border + style->padding.y; - - /* calculate empty space around cursor */ - empty_west.x = scroll.x; - empty_west.y = scroll.y; - empty_west.w = cursor.x - scroll.x; - empty_west.h = scroll.h; - - empty_east.x = cursor.x + cursor.w; - empty_east.y = scroll.y; - empty_east.w = (scroll.x + scroll.w) - (cursor.x + cursor.w); - empty_east.h = scroll.h; - - /* update scrollbar */ - scroll_offset = nk_scrollbar_behavior(state, in, has_scrolling, &scroll, &cursor, - &empty_west, &empty_east, scroll_offset, target, scroll_step, NK_HORIZONTAL); - scroll_off = scroll_offset / target; - cursor.x = scroll.x + (scroll_off * scroll.w); - - /* draw scrollbar */ - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_scrollbar(out, *state, style, &scroll, &cursor); - if (style->draw_end) style->draw_end(out, style->userdata); - return scroll_offset; -} - -/* =============================================================== - * - * FILTER - * - * ===============================================================*/ -NK_API int nk_filter_default(const struct nk_text_edit *box, nk_rune unicode) -{(void)unicode;NK_UNUSED(box);return nk_true;} - -NK_API int -nk_filter_ascii(const struct nk_text_edit *box, nk_rune unicode) -{ - NK_UNUSED(box); - if (unicode > 128) return nk_false; - else return nk_true; -} - -NK_API int -nk_filter_float(const struct nk_text_edit *box, nk_rune unicode) -{ - NK_UNUSED(box); - if ((unicode < '0' || unicode > '9') && unicode != '.' && unicode != '-') - return nk_false; - else return nk_true; -} - -NK_API int -nk_filter_decimal(const struct nk_text_edit *box, nk_rune unicode) -{ - NK_UNUSED(box); - if ((unicode < '0' || unicode > '9') && unicode != '-') - return nk_false; - else return nk_true; -} - -NK_API int -nk_filter_hex(const struct nk_text_edit *box, nk_rune unicode) -{ - NK_UNUSED(box); - if ((unicode < '0' || unicode > '9') && - (unicode < 'a' || unicode > 'f') && - (unicode < 'A' || unicode > 'F')) - return nk_false; - else return nk_true; -} - -NK_API int -nk_filter_oct(const struct nk_text_edit *box, nk_rune unicode) -{ - NK_UNUSED(box); - if (unicode < '0' || unicode > '7') - return nk_false; - else return nk_true; -} - -NK_API int -nk_filter_binary(const struct nk_text_edit *box, nk_rune unicode) -{ - NK_UNUSED(box); - if (unicode != '0' && unicode != '1') - return nk_false; - else return nk_true; -} - -/* =============================================================== - * - * EDIT - * - * ===============================================================*/ -NK_INTERN void -nk_edit_draw_text(struct nk_command_buffer *out, - const struct nk_style_edit *style, float pos_x, float pos_y, - float x_offset, const char *text, int byte_len, float row_height, - const struct nk_user_font *font, struct nk_color background, - struct nk_color foreground, int is_selected) -{ - NK_ASSERT(out); - NK_ASSERT(font); - NK_ASSERT(style); - if (!text || !byte_len || !out || !style) return; - - {int glyph_len = 0; - nk_rune unicode = 0; - int text_len = 0; - float line_width = 0; - float glyph_width; - const char *line = text; - float line_offset = 0; - int line_count = 0; - - struct nk_text txt; - txt.padding = nk_vec2(0,0); - txt.background = background; - txt.text = foreground; - - glyph_len = nk_utf_decode(text+text_len, &unicode, byte_len-text_len); - if (!glyph_len) return; - while ((text_len < byte_len) && glyph_len) - { - if (unicode == '\n') { - /* new line sepeator so draw previous line */ - struct nk_rect label; - label.y = pos_y + line_offset; - label.h = row_height; - label.w = line_width; - label.x = pos_x; - if (!line_count) - label.x += x_offset; - - if (is_selected) /* selection needs to draw different background color */ - nk_fill_rect(out, label, 0, background); - nk_widget_text(out, label, line, (int)((text + text_len) - line), - &txt, NK_TEXT_CENTERED, font); - - text_len++; - line_count++; - line_width = 0; - line = text + text_len; - line_offset += row_height; - glyph_len = nk_utf_decode(text + text_len, &unicode, (int)(byte_len-text_len)); - continue; - } - if (unicode == '\r') { - text_len++; - glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); - continue; - } - glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); - line_width += (float)glyph_width; - text_len += glyph_len; - glyph_len = nk_utf_decode(text + text_len, &unicode, byte_len-text_len); - continue; - } - if (line_width > 0) { - /* draw last line */ - struct nk_rect label; - label.y = pos_y + line_offset; - label.h = row_height; - label.w = line_width; - label.x = pos_x; - if (!line_count) - label.x += x_offset; - - if (is_selected) - nk_fill_rect(out, label, 0, background); - nk_widget_text(out, label, line, (int)((text + text_len) - line), - &txt, NK_TEXT_LEFT, font); - }} -} - -NK_INTERN 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) -{ - struct nk_rect area; - nk_flags ret = 0; - float row_height; - char prev_state = 0; - char is_hovered = 0; - char select_all = 0; - char cursor_follow = 0; - struct nk_rect old_clip; - struct nk_rect clip; - - NK_ASSERT(state); - NK_ASSERT(out); - NK_ASSERT(style); - if (!state || !out || !style) - return ret; - - /* visible text area calculation */ - area.x = bounds.x + style->padding.x + style->border; - area.y = bounds.y + style->padding.y + style->border; - area.w = bounds.w - (2.0f * style->padding.x + 2 * style->border); - area.h = bounds.h - (2.0f * style->padding.y + 2 * style->border); - if (flags & NK_EDIT_MULTILINE) - area.w = NK_MAX(0, area.w - style->scrollbar_size.x); - row_height = (flags & NK_EDIT_MULTILINE)? font->height + style->row_padding: area.h; - - /* calculate clipping rectangle */ - old_clip = out->clip; - nk_unify(&clip, &old_clip, area.x, area.y, area.x + area.w, area.y + area.h); - - /* update edit state */ - prev_state = (char)edit->active; - is_hovered = (char)nk_input_is_mouse_hovering_rect(in, bounds); - if (in && in->mouse.buttons[NK_BUTTON_LEFT].clicked && in->mouse.buttons[NK_BUTTON_LEFT].down) { - edit->active = NK_INBOX(in->mouse.pos.x, in->mouse.pos.y, - bounds.x, bounds.y, bounds.w, bounds.h); - } - - /* (de)activate text editor */ - if (!prev_state && edit->active) { - const enum nk_text_edit_type type = (flags & NK_EDIT_MULTILINE) ? - NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE; - nk_textedit_clear_state(edit, type, filter); - if (flags & NK_EDIT_ALWAYS_INSERT_MODE) - edit->mode = NK_TEXT_EDIT_MODE_INSERT; - if (flags & NK_EDIT_AUTO_SELECT) - select_all = nk_true; - if (flags & NK_EDIT_GOTO_END_ON_ACTIVATE) { - edit->cursor = edit->string.len; - in = 0; - } - } else if (!edit->active) edit->mode = NK_TEXT_EDIT_MODE_VIEW; - if (flags & NK_EDIT_READ_ONLY) - edit->mode = NK_TEXT_EDIT_MODE_VIEW; - - ret = (edit->active) ? NK_EDIT_ACTIVE: NK_EDIT_INACTIVE; - if (prev_state != edit->active) - ret |= (edit->active) ? NK_EDIT_ACTIVATED: NK_EDIT_DEACTIVATED; - - /* handle user input */ - if (edit->active && in) - { - int shift_mod = in->keyboard.keys[NK_KEY_SHIFT].down; - const float mouse_x = (in->mouse.pos.x - area.x) + edit->scrollbar.x; - const float mouse_y = (in->mouse.pos.y - area.y) + edit->scrollbar.y; - - /* mouse click handler */ - is_hovered = (char)nk_input_is_mouse_hovering_rect(in, area); - if (select_all) { - nk_textedit_select_all(edit); - } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && - in->mouse.buttons[NK_BUTTON_LEFT].clicked) { - nk_textedit_click(edit, mouse_x, mouse_y, font, row_height); - } else if (is_hovered && in->mouse.buttons[NK_BUTTON_LEFT].down && - (in->mouse.delta.x != 0.0f || in->mouse.delta.y != 0.0f)) { - nk_textedit_drag(edit, mouse_x, mouse_y, font, row_height); - cursor_follow = nk_true; - } else if (is_hovered && in->mouse.buttons[NK_BUTTON_RIGHT].clicked && - in->mouse.buttons[NK_BUTTON_RIGHT].down) { - nk_textedit_key(edit, NK_KEY_TEXT_WORD_LEFT, nk_false, font, row_height); - nk_textedit_key(edit, NK_KEY_TEXT_WORD_RIGHT, nk_true, font, row_height); - cursor_follow = nk_true; - } - - {int i; /* keyboard input */ - int old_mode = edit->mode; - for (i = 0; i < NK_KEY_MAX; ++i) { - if (i == NK_KEY_ENTER || i == NK_KEY_TAB) continue; /* special case */ - if (nk_input_is_key_pressed(in, (enum nk_keys)i)) { - nk_textedit_key(edit, (enum nk_keys)i, shift_mod, font, row_height); - cursor_follow = nk_true; - } - } - if (old_mode != edit->mode) { - in->keyboard.text_len = 0; - }} - - /* text input */ - edit->filter = filter; - if (in->keyboard.text_len) { - nk_textedit_text(edit, in->keyboard.text, in->keyboard.text_len); - cursor_follow = nk_true; - in->keyboard.text_len = 0; - } - - /* enter key handler */ - if (nk_input_is_key_pressed(in, NK_KEY_ENTER)) { - cursor_follow = nk_true; - if (flags & NK_EDIT_CTRL_ENTER_NEWLINE && shift_mod) - nk_textedit_text(edit, "\n", 1); - else if (flags & NK_EDIT_SIG_ENTER) - ret |= NK_EDIT_COMMITED; - else nk_textedit_text(edit, "\n", 1); - } - - /* cut & copy handler */ - {int copy= nk_input_is_key_pressed(in, NK_KEY_COPY); - int cut = nk_input_is_key_pressed(in, NK_KEY_CUT); - if ((copy || cut) && (flags & NK_EDIT_CLIPBOARD)) - { - int glyph_len; - nk_rune unicode; - const char *text; - int b = edit->select_start; - int e = edit->select_end; - - int begin = NK_MIN(b, e); - int end = NK_MAX(b, e); - text = nk_str_at_const(&edit->string, begin, &unicode, &glyph_len); - if (edit->clip.copy) - edit->clip.copy(edit->clip.userdata, text, end - begin); - if (cut && !(flags & NK_EDIT_READ_ONLY)){ - nk_textedit_cut(edit); - cursor_follow = nk_true; - } - }} - - /* paste handler */ - {int paste = nk_input_is_key_pressed(in, NK_KEY_PASTE); - if (paste && (flags & NK_EDIT_CLIPBOARD) && edit->clip.paste) { - edit->clip.paste(edit->clip.userdata, edit); - cursor_follow = nk_true; - }} - - /* tab handler */ - {int tab = nk_input_is_key_pressed(in, NK_KEY_TAB); - if (tab && (flags & NK_EDIT_ALLOW_TAB)) { - nk_textedit_text(edit, " ", 4); - cursor_follow = nk_true; - }} - } - - /* set widget state */ - if (edit->active) - *state = NK_WIDGET_STATE_ACTIVE; - else nk_widget_state_reset(state); - - if (is_hovered) - *state |= NK_WIDGET_STATE_HOVERED; - - /* DRAW EDIT */ - {const char *text = nk_str_get_const(&edit->string); - int len = nk_str_len_char(&edit->string); - - {/* select background colors/images */ - const struct nk_style_item *background; - if (*state & NK_WIDGET_STATE_ACTIVED) - background = &style->active; - else if (*state & NK_WIDGET_STATE_HOVER) - background = &style->hover; - else background = &style->normal; - - /* draw background frame */ - if (background->type == NK_STYLE_ITEM_COLOR) { - nk_stroke_rect(out, bounds, style->rounding, style->border, style->border_color); - nk_fill_rect(out, bounds, style->rounding, background->data.color); - } else nk_draw_image(out, bounds, &background->data.image, nk_white);} - - area.w = NK_MAX(0, area.w - style->cursor_size); - if (edit->active) - { - int total_lines = 1; - struct nk_vec2 text_size = nk_vec2(0,0); - - /* text pointer positions */ - const char *cursor_ptr = 0; - const char *select_begin_ptr = 0; - const char *select_end_ptr = 0; - - /* 2D pixel positions */ - struct nk_vec2 cursor_pos = nk_vec2(0,0); - struct nk_vec2 selection_offset_start = nk_vec2(0,0); - struct nk_vec2 selection_offset_end = nk_vec2(0,0); - - int selection_begin = NK_MIN(edit->select_start, edit->select_end); - int selection_end = NK_MAX(edit->select_start, edit->select_end); - - /* calculate total line count + total space + cursor/selection position */ - float line_width = 0.0f; - if (text && len) - { - /* utf8 encoding */ - float glyph_width; - int glyph_len = 0; - nk_rune unicode = 0; - int text_len = 0; - int glyphs = 0; - int row_begin = 0; - - glyph_len = nk_utf_decode(text, &unicode, len); - glyph_width = font->width(font->userdata, font->height, text, glyph_len); - line_width = 0; - - /* iterate all lines */ - while ((text_len < len) && glyph_len) - { - /* set cursor 2D position and line */ - if (!cursor_ptr && glyphs == edit->cursor) - { - int glyph_offset; - struct nk_vec2 out_offset; - struct nk_vec2 row_size; - const char *remaining; - - /* calculate 2d position */ - cursor_pos.y = (float)(total_lines-1) * row_height; - row_size = nk_text_calculate_text_bounds(font, text+row_begin, - text_len-row_begin, row_height, &remaining, - &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); - cursor_pos.x = row_size.x; - cursor_ptr = text + text_len; - } - - /* set start selection 2D position and line */ - if (!select_begin_ptr && edit->select_start != edit->select_end && - glyphs == selection_begin) - { - int glyph_offset; - struct nk_vec2 out_offset; - struct nk_vec2 row_size; - const char *remaining; - - /* calculate 2d position */ - selection_offset_start.y = (float)(NK_MAX(total_lines-1,0)) * row_height; - row_size = nk_text_calculate_text_bounds(font, text+row_begin, - text_len-row_begin, row_height, &remaining, - &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); - selection_offset_start.x = row_size.x; - select_begin_ptr = text + text_len; - } - - /* set end selection 2D position and line */ - if (!select_end_ptr && edit->select_start != edit->select_end && - glyphs == selection_end) - { - int glyph_offset; - struct nk_vec2 out_offset; - struct nk_vec2 row_size; - const char *remaining; - - /* calculate 2d position */ - selection_offset_end.y = (float)(total_lines-1) * row_height; - row_size = nk_text_calculate_text_bounds(font, text+row_begin, - text_len-row_begin, row_height, &remaining, - &out_offset, &glyph_offset, NK_STOP_ON_NEW_LINE); - selection_offset_end.x = row_size.x; - select_end_ptr = text + text_len; - } - if (unicode == '\n') { - text_size.x = NK_MAX(text_size.x, line_width); - total_lines++; - line_width = 0; - text_len++; - glyphs++; - row_begin = text_len; - glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); - glyph_width = font->width(font->userdata, font->height, text+text_len, glyph_len); - continue; - } - - glyphs++; - text_len += glyph_len; - line_width += (float)glyph_width; - - glyph_len = nk_utf_decode(text + text_len, &unicode, len-text_len); - glyph_width = font->width(font->userdata, font->height, - text+text_len, glyph_len); - continue; - } - text_size.y = (float)total_lines * row_height; - - /* handle case when cursor is at end of text buffer */ - if (!cursor_ptr && edit->cursor == edit->string.len) { - cursor_pos.x = line_width; - cursor_pos.y = text_size.y - row_height; - } - } - { - /* scrollbar */ - if (cursor_follow) - { - /* update scrollbar to follow cursor */ - if (!(flags & NK_EDIT_NO_HORIZONTAL_SCROLL)) { - /* horizontal scroll */ - const float scroll_increment = area.w * 0.25f; - if (cursor_pos.x < edit->scrollbar.x) - edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x - scroll_increment); - if (cursor_pos.x >= edit->scrollbar.x + area.w) - edit->scrollbar.x = (float)(int)NK_MAX(0.0f, cursor_pos.x); - } else edit->scrollbar.x = 0; - - if (flags & NK_EDIT_MULTILINE) { - /* vertical scroll */ - if (cursor_pos.y < edit->scrollbar.y) - edit->scrollbar.y = NK_MAX(0.0f, cursor_pos.y - row_height); - if (cursor_pos.y >= edit->scrollbar.y + area.h) - edit->scrollbar.y = edit->scrollbar.y + row_height; - } else edit->scrollbar.y = 0; - } - - /* scrollbar widget */ - if (flags & NK_EDIT_MULTILINE) - { - nk_flags ws; - struct nk_rect scroll; - float scroll_target; - float scroll_offset; - float scroll_step; - float scroll_inc; - - scroll = area; - scroll.x = (bounds.x + bounds.w - style->border) - style->scrollbar_size.x; - scroll.w = style->scrollbar_size.x; - - scroll_offset = edit->scrollbar.y; - scroll_step = scroll.h * 0.10f; - scroll_inc = scroll.h * 0.01f; - scroll_target = text_size.y; - edit->scrollbar.y = nk_do_scrollbarv(&ws, out, scroll, 0, - scroll_offset, scroll_target, scroll_step, scroll_inc, - &style->scrollbar, in, font); - } - } - - /* draw text */ - {struct nk_color background_color; - struct nk_color text_color; - struct nk_color sel_background_color; - struct nk_color sel_text_color; - struct nk_color cursor_color; - struct nk_color cursor_text_color; - const struct nk_style_item *background; - nk_push_scissor(out, clip); - - /* select correct colors to draw */ - if (*state & NK_WIDGET_STATE_ACTIVED) { - background = &style->active; - text_color = style->text_active; - sel_text_color = style->selected_text_hover; - sel_background_color = style->selected_hover; - cursor_color = style->cursor_hover; - cursor_text_color = style->cursor_text_hover; - } else if (*state & NK_WIDGET_STATE_HOVER) { - background = &style->hover; - text_color = style->text_hover; - sel_text_color = style->selected_text_hover; - sel_background_color = style->selected_hover; - cursor_text_color = style->cursor_text_hover; - cursor_color = style->cursor_hover; - } else { - background = &style->normal; - text_color = style->text_normal; - sel_text_color = style->selected_text_normal; - sel_background_color = style->selected_normal; - cursor_color = style->cursor_normal; - cursor_text_color = style->cursor_text_normal; - } - if (background->type == NK_STYLE_ITEM_IMAGE) - background_color = nk_rgba(0,0,0,0); - else background_color = background->data.color; - - - if (edit->select_start == edit->select_end) { - /* no selection so just draw the complete text */ - const char *begin = nk_str_get_const(&edit->string); - int l = nk_str_len_char(&edit->string); - nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, - area.y - edit->scrollbar.y, 0, begin, l, row_height, font, - background_color, text_color, nk_false); - } else { - /* edit has selection so draw 1-3 text chunks */ - if (edit->select_start != edit->select_end && selection_begin > 0){ - /* draw unselected text before selection */ - const char *begin = nk_str_get_const(&edit->string); - NK_ASSERT(select_begin_ptr); - nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, - area.y - edit->scrollbar.y, 0, begin, (int)(select_begin_ptr - begin), - row_height, font, background_color, text_color, nk_false); - } - if (edit->select_start != edit->select_end) { - /* draw selected text */ - NK_ASSERT(select_begin_ptr); - if (!select_end_ptr) { - const char *begin = nk_str_get_const(&edit->string); - select_end_ptr = begin + nk_str_len_char(&edit->string); - } - nk_edit_draw_text(out, style, - area.x - edit->scrollbar.x, - area.y + selection_offset_start.y - edit->scrollbar.y, - selection_offset_start.x, - select_begin_ptr, (int)(select_end_ptr - select_begin_ptr), - row_height, font, sel_background_color, sel_text_color, nk_true); - } - if ((edit->select_start != edit->select_end && - selection_end < edit->string.len)) - { - /* draw unselected text after selected text */ - const char *begin = select_end_ptr; - const char *end = nk_str_get_const(&edit->string) + - nk_str_len_char(&edit->string); - NK_ASSERT(select_end_ptr); - nk_edit_draw_text(out, style, - area.x - edit->scrollbar.x, - area.y + selection_offset_end.y - edit->scrollbar.y, - selection_offset_end.x, - begin, (int)(end - begin), row_height, font, - background_color, text_color, nk_true); - } - } - - /* cursor */ - if (edit->select_start == edit->select_end) - { - if (edit->cursor >= nk_str_len(&edit->string) || - (cursor_ptr && *cursor_ptr == '\n')) { - /* draw cursor at end of line */ - struct nk_rect cursor; - cursor.w = style->cursor_size; - cursor.h = font->height; - cursor.x = area.x + cursor_pos.x - edit->scrollbar.x; - cursor.y = area.y + cursor_pos.y + row_height/2.0f - cursor.h/2.0f; - cursor.y -= edit->scrollbar.y; - nk_fill_rect(out, cursor, 0, cursor_color); - } else { - /* draw cursor inside text */ - int glyph_len; - struct nk_rect label; - struct nk_text txt; - - nk_rune unicode; - NK_ASSERT(cursor_ptr); - glyph_len = nk_utf_decode(cursor_ptr, &unicode, 4); - - label.x = area.x + cursor_pos.x - edit->scrollbar.x; - label.y = area.y + cursor_pos.y - edit->scrollbar.y; - label.w = font->width(font->userdata, font->height, cursor_ptr, glyph_len); - label.h = row_height; - - txt.padding = nk_vec2(0,0); - txt.background = cursor_color;; - txt.text = cursor_text_color; - nk_fill_rect(out, label, 0, cursor_color); - nk_widget_text(out, label, cursor_ptr, glyph_len, &txt, NK_TEXT_LEFT, font); - } - }} - } else { - /* not active so just draw text */ - int l = nk_str_len_char(&edit->string); - const char *begin = nk_str_get_const(&edit->string); - - const struct nk_style_item *background; - struct nk_color background_color; - struct nk_color text_color; - nk_push_scissor(out, clip); - if (*state & NK_WIDGET_STATE_ACTIVED) { - background = &style->active; - text_color = style->text_active; - } else if (*state & NK_WIDGET_STATE_HOVER) { - background = &style->hover; - text_color = style->text_hover; - } else { - background = &style->normal; - text_color = style->text_normal; - } - if (background->type == NK_STYLE_ITEM_IMAGE) - background_color = nk_rgba(0,0,0,0); - else background_color = background->data.color; - nk_edit_draw_text(out, style, area.x - edit->scrollbar.x, - area.y - edit->scrollbar.y, 0, begin, l, row_height, font, - background_color, text_color, nk_false); - } - nk_push_scissor(out, old_clip);} - return ret; -} - -/* =============================================================== - * - * PROPERTY - * - * ===============================================================*/ -enum nk_property_status { - NK_PROPERTY_DEFAULT, - NK_PROPERTY_EDIT, - NK_PROPERTY_DRAG -}; -enum nk_property_filter { - NK_FILTER_INT, - NK_FILTER_FLOAT -}; -enum nk_property_kind { - NK_PROPERTY_INT, - NK_PROPERTY_FLOAT, - NK_PROPERTY_DOUBLE -}; -union nk_property { - int i; - float f; - double d; -}; -struct nk_property_variant { - enum nk_property_kind kind; - union nk_property value; - union nk_property min_value; - union nk_property max_value; - union nk_property step; -}; - -NK_INTERN 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) -{ - int left_mouse_down = in && in->mouse.buttons[NK_BUTTON_LEFT].down; - int left_mouse_click_in_cursor = in && - nk_input_has_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, drag, nk_true); - - nk_widget_state_reset(state); - if (nk_input_is_mouse_hovering_rect(in, drag)) - *state = NK_WIDGET_STATE_HOVERED; - - if (left_mouse_down && left_mouse_click_in_cursor) { - float delta, pixels; - pixels = in->mouse.delta.x; - delta = pixels * inc_per_pixel; - switch (variant->kind) { - default: break; - case NK_PROPERTY_INT: - variant->value.i = variant->value.i + (int)delta; - variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); - break; - case NK_PROPERTY_FLOAT: - variant->value.f = variant->value.f + (float)delta; - variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); - break; - case NK_PROPERTY_DOUBLE: - variant->value.d = variant->value.d + (double)delta; - variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); - break; - } - *state = NK_WIDGET_STATE_ACTIVE; - } - if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, drag)) - *state |= NK_WIDGET_STATE_ENTERED; - else if (nk_input_is_mouse_prev_hovering_rect(in, drag)) - *state |= NK_WIDGET_STATE_LEFT; -} - -NK_INTERN 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) -{ - if (in && *state == NK_PROPERTY_DEFAULT) { - if (nk_button_behavior(ws, edit, in, NK_BUTTON_DEFAULT)) - *state = NK_PROPERTY_EDIT; - else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, label, nk_true)) - *state = NK_PROPERTY_DRAG; - else if (nk_input_is_mouse_click_down_in_rect(in, NK_BUTTON_LEFT, empty, nk_true)) - *state = NK_PROPERTY_DRAG; - } - if (*state == NK_PROPERTY_DRAG) { - nk_drag_behavior(ws, in, property, variant, inc_per_pixel); - if (!(*ws & NK_WIDGET_STATE_ACTIVED)) *state = NK_PROPERTY_DEFAULT; - } -} - -NK_INTERN 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) -{ - struct nk_text text; - const struct nk_style_item *background; - - /* select correct background and text color */ - if (state & NK_WIDGET_STATE_ACTIVED) { - background = &style->active; - text.text = style->label_active; - } else if (state & NK_WIDGET_STATE_HOVER) { - background = &style->hover; - text.text = style->label_hover; - } else { - background = &style->normal; - text.text = style->label_normal; - } - - /* draw background */ - if (background->type == NK_STYLE_ITEM_IMAGE) { - nk_draw_image(out, *bounds, &background->data.image, nk_white); - text.background = nk_rgba(0,0,0,0); - } else { - text.background = background->data.color; - nk_fill_rect(out, *bounds, style->rounding, background->data.color); - nk_stroke_rect(out, *bounds, style->rounding, style->border, background->data.color); - } - - /* draw label */ - text.padding = nk_vec2(0,0); - nk_widget_text(out, *label, name, len, &text, NK_TEXT_CENTERED, font); -} - -NK_INTERN 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, 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) -{ - const nk_plugin_filter filters[] = { - nk_filter_decimal, - nk_filter_float - }; - int active, old; - int num_len, name_len; - char string[NK_MAX_NUMBER_BUFFER]; - float size; - - char *dst = 0; - int *length; - - struct nk_rect left; - struct nk_rect right; - struct nk_rect label; - struct nk_rect edit; - struct nk_rect empty; - - /* left decrement button */ - left.h = font->height/2; - left.w = left.h; - left.x = property.x + style->border + style->padding.x; - left.y = property.y + style->border + property.h/2.0f - left.h/2; - - /* text label */ - name_len = nk_strlen(name); - size = font->width(font->userdata, font->height, name, name_len); - label.x = left.x + left.w + style->padding.x; - label.w = (float)size + 2 * style->padding.x; - label.y = property.y + style->border + style->padding.y; - label.h = property.h - (2 * style->border + 2 * style->padding.y); - - /* right increment button */ - right.y = left.y; - right.w = left.w; - right.h = left.h; - right.x = property.x + property.w - (right.w + style->padding.x); - - /* edit */ - if (*state == NK_PROPERTY_EDIT) { - size = font->width(font->userdata, font->height, buffer, *len); - size += style->edit.cursor_size; - length = len; - dst = buffer; - } else { - switch (variant->kind) { - default: break; - case NK_PROPERTY_INT: - nk_itoa(string, variant->value.i); - num_len = nk_strlen(string); - break; - case NK_PROPERTY_FLOAT: - nk_dtoa(string, (double)variant->value.f); - num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); - break; - case NK_PROPERTY_DOUBLE: - nk_dtoa(string, variant->value.d); - num_len = nk_string_float_limit(string, NK_MAX_FLOAT_PRECISION); - break; - } - size = font->width(font->userdata, font->height, string, num_len); - dst = string; - length = &num_len; - } - - edit.w = (float)size + 2 * style->padding.x; - edit.w = NK_MIN(edit.w, right.x - (label.x + label.w)); - edit.x = right.x - (edit.w + style->padding.x); - edit.y = property.y + style->border; - edit.h = property.h - (2 * style->border); - - /* empty left space activator */ - empty.w = edit.x - (label.x + label.w); - empty.x = label.x + label.w; - empty.y = property.y; - empty.h = property.h; - - /* update property */ - old = (*state == NK_PROPERTY_EDIT); - nk_property_behavior(ws, in, property, label, edit, empty, state, variant, inc_per_pixel); - - /* draw property */ - if (style->draw_begin) style->draw_begin(out, style->userdata); - nk_draw_property(out, style, &property, &label, *ws, name, name_len, font); - if (style->draw_end) style->draw_end(out, style->userdata); - - /* execute right button */ - if (nk_do_button_symbol(ws, out, left, style->sym_left, NK_BUTTON_DEFAULT, &style->dec_button, in, font)) { - switch (variant->kind) { - default: break; - case NK_PROPERTY_INT: - variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i - variant->step.i, variant->max_value.i); break; - case NK_PROPERTY_FLOAT: - variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f - variant->step.f, variant->max_value.f); break; - case NK_PROPERTY_DOUBLE: - variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d - variant->step.d, variant->max_value.d); break; - } - } - - /* execute left button */ - if (nk_do_button_symbol(ws, out, right, style->sym_right, NK_BUTTON_DEFAULT, &style->inc_button, in, font)) { - switch (variant->kind) { - default: break; - case NK_PROPERTY_INT: - variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i + variant->step.i, variant->max_value.i); break; - case NK_PROPERTY_FLOAT: - variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f + variant->step.f, variant->max_value.f); break; - case NK_PROPERTY_DOUBLE: - variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d + variant->step.d, variant->max_value.d); break; - } - } - - active = (*state == NK_PROPERTY_EDIT); - if (old != NK_PROPERTY_EDIT && active) { - /* property has been activated so setup buffer */ - NK_MEMCPY(buffer, dst, (nk_size)*length); - *cursor = nk_utf_len(buffer, *length); - *len = *length; - length = len; - dst = buffer; - } - - /* execute and run text edit field */ - nk_textedit_clear_state(text_edit, NK_TEXT_EDIT_SINGLE_LINE, filters[filter]); - text_edit->active = (unsigned char)active; - text_edit->string.len = *length; - text_edit->cursor = NK_CLAMP(0, *cursor, *length); - text_edit->string.buffer.allocated = (nk_size)*length; - text_edit->string.buffer.memory.size = NK_MAX_NUMBER_BUFFER; - text_edit->string.buffer.memory.ptr = dst; - text_edit->string.buffer.size = NK_MAX_NUMBER_BUFFER; - text_edit->mode = NK_TEXT_EDIT_MODE_INSERT; - nk_do_edit(ws, out, edit, NK_EDIT_ALWAYS_INSERT_MODE, filters[filter], - text_edit, &style->edit, (*state == NK_PROPERTY_EDIT) ? in: 0, font); - - *length = text_edit->string.len; - active = text_edit->active; - *cursor = text_edit->cursor; - - if (active && nk_input_is_key_pressed(in, NK_KEY_ENTER)) - active = !active; - - if (old && !active) { - /* property is now not active so convert edit text to value*/ - *state = NK_PROPERTY_DEFAULT; - buffer[*len] = '\0'; - switch (variant->kind) { - default: break; - case NK_PROPERTY_INT: - variant->value.i = nk_strtoi(buffer, 0); - variant->value.i = NK_CLAMP(variant->min_value.i, variant->value.i, variant->max_value.i); - break; - case NK_PROPERTY_FLOAT: - nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); - variant->value.f = nk_strtof(buffer, 0); - variant->value.f = NK_CLAMP(variant->min_value.f, variant->value.f, variant->max_value.f); - break; - case NK_PROPERTY_DOUBLE: - nk_string_float_limit(buffer, NK_MAX_FLOAT_PRECISION); - variant->value.d = nk_strtod(buffer, 0); - variant->value.d = NK_CLAMP(variant->min_value.d, variant->value.d, variant->max_value.d); - break; - } - } -} -/* =============================================================== - * - * COLOR PICKER - * - * ===============================================================*/ -NK_INTERN int -nk_color_picker_behavior(nk_flags *state, - const struct nk_rect *bounds, const struct nk_rect *matrix, - const struct nk_rect *hue_bar, const struct nk_rect *alpha_bar, - struct nk_color *color, const struct nk_input *in) -{ - float hsva[4]; - int value_changed = 0; - int hsv_changed = 0; - - NK_ASSERT(state); - NK_ASSERT(matrix); - NK_ASSERT(hue_bar); - NK_ASSERT(color); - - /* color matrix */ - nk_color_hsva_fv(hsva, *color); - if (nk_button_behavior(state, *matrix, in, NK_BUTTON_REPEATER)) { - hsva[1] = NK_SATURATE((in->mouse.pos.x - matrix->x) / (matrix->w-1)); - hsva[2] = 1.0f - NK_SATURATE((in->mouse.pos.y - matrix->y) / (matrix->h-1)); - value_changed = hsv_changed = 1; - } - - /* hue bar */ - if (nk_button_behavior(state, *hue_bar, in, NK_BUTTON_REPEATER)) { - hsva[0] = NK_SATURATE((in->mouse.pos.y - hue_bar->y) / (hue_bar->h-1)); - value_changed = hsv_changed = 1; - } - - /* alpha bar */ - if (alpha_bar) { - if (nk_button_behavior(state, *alpha_bar, in, NK_BUTTON_REPEATER)) { - hsva[3] = 1.0f - NK_SATURATE((in->mouse.pos.y - alpha_bar->y) / (alpha_bar->h-1)); - value_changed = 1; - } - } - nk_widget_state_reset(state); - if (hsv_changed) { - *color = nk_hsva_fv(hsva); - *state = NK_WIDGET_STATE_ACTIVE; - } - if (value_changed) { - color->a = (nk_byte)(hsva[3] * 255.0f); - *state = NK_WIDGET_STATE_ACTIVE; - } - - /* set color picker widget state */ - if (nk_input_is_mouse_hovering_rect(in, *bounds)) - *state = NK_WIDGET_STATE_HOVERED; - if (*state & NK_WIDGET_STATE_HOVER && !nk_input_is_mouse_prev_hovering_rect(in, *bounds)) - *state |= NK_WIDGET_STATE_ENTERED; - else if (nk_input_is_mouse_prev_hovering_rect(in, *bounds)) - *state |= NK_WIDGET_STATE_LEFT; - return value_changed; -} - -NK_INTERN 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_color color) -{ - NK_STORAGE const struct nk_color black = {0,0,0,255}; - NK_STORAGE const struct nk_color white = {255, 255, 255, 255}; - NK_STORAGE const struct nk_color black_trans = {0,0,0,0}; - - const float crosshair_size = 7.0f; - struct nk_color temp; - float hsva[4]; - float line_y; - int i; - - NK_ASSERT(o); - NK_ASSERT(matrix); - NK_ASSERT(hue_bar); - - /* draw hue bar */ - nk_color_hsv_fv(hsva, color); - for (i = 0; i < 6; ++i) { - NK_GLOBAL const struct nk_color hue_colors[] = { - {255, 0, 0, 255}, - {255,255,0,255}, - {0,255,0,255}, - {0, 255,255,255}, - {0,0,255,255}, - {255, 0, 255, 255}, - {255, 0, 0, 255} - }; - nk_fill_rect_multi_color(o, - nk_rect(hue_bar->x, hue_bar->y + (float)i * (hue_bar->h/6.0f) + 0.5f, - hue_bar->w, (hue_bar->h/6.0f) + 0.5f), hue_colors[i], hue_colors[i], - hue_colors[i+1], hue_colors[i+1]); - } - line_y = (float)(int)(hue_bar->y + hsva[0] * matrix->h + 0.5f); - nk_stroke_line(o, hue_bar->x-1, line_y, hue_bar->x + hue_bar->w + 2, - line_y, 1, nk_rgb(255,255,255)); - - /* draw alpha bar */ - if (alpha_bar) { - float alpha = NK_SATURATE((float)color.a/255.0f); - line_y = (float)(int)(alpha_bar->y + (1.0f - alpha) * matrix->h + 0.5f); - - nk_fill_rect_multi_color(o, *alpha_bar, white, white, black, black); - nk_stroke_line(o, alpha_bar->x-1, line_y, alpha_bar->x + alpha_bar->w + 2, - line_y, 1, nk_rgb(255,255,255)); - } - - /* draw color matrix */ - temp = nk_hsv_f(hsva[0], 1.0f, 1.0f); - nk_fill_rect_multi_color(o, *matrix, white, temp, temp, white); - nk_fill_rect_multi_color(o, *matrix, black_trans, black_trans, black, black); - - /* draw cross-hair */ - {struct nk_vec2 p; float S = hsva[1]; float V = hsva[2]; - p.x = (float)(int)(matrix->x + S * matrix->w); - p.y = (float)(int)(matrix->y + (1.0f - V) * matrix->h); - nk_stroke_line(o, p.x - crosshair_size, p.y, p.x-2, p.y, 1.0f, white); - nk_stroke_line(o, p.x + crosshair_size + 1, p.y, p.x+3, p.y, 1.0f, white); - nk_stroke_line(o, p.x, p.y + crosshair_size + 1, p.x, p.y+3, 1.0f, white); - nk_stroke_line(o, p.x, p.y - crosshair_size, p.x, p.y-2, 1.0f, white);} -} - -NK_INTERN int -nk_do_color_picker(nk_flags *state, - struct nk_command_buffer *out, struct nk_color *color, - enum nk_color_format fmt, struct nk_rect bounds, - struct nk_vec2 padding, const struct nk_input *in, - const struct nk_user_font *font) -{ - int ret = 0; - struct nk_rect matrix; - struct nk_rect hue_bar; - struct nk_rect alpha_bar; - float bar_w; - - NK_ASSERT(out); - NK_ASSERT(color); - NK_ASSERT(state); - NK_ASSERT(font); - if (!out || !color || !state || !font) - return ret; - - bar_w = font->height; - bounds.x += padding.x; - bounds.y += padding.x; - bounds.w -= 2 * padding.x; - bounds.h -= 2 * padding.y; - - matrix.x = bounds.x; - matrix.y = bounds.y; - matrix.h = bounds.h; - matrix.w = bounds.w - (3 * padding.x + 2 * bar_w); - - hue_bar.w = bar_w; - hue_bar.y = bounds.y; - hue_bar.h = matrix.h; - hue_bar.x = matrix.x + matrix.w + padding.x; - - alpha_bar.x = hue_bar.x + hue_bar.w + padding.x; - alpha_bar.y = bounds.y; - alpha_bar.w = bar_w; - alpha_bar.h = matrix.h; - - ret = nk_color_picker_behavior(state, &bounds, &matrix, &hue_bar, - (fmt == NK_RGBA) ? &alpha_bar:0, color, in); - nk_draw_color_picker(out, &matrix, &hue_bar, (fmt == NK_RGBA) ? &alpha_bar:0, *color); - return ret; -} - -/* ============================================================== - * - * STYLE - * - * ===============================================================*/ -NK_API void nk_style_default(struct nk_context *ctx){nk_style_from_table(ctx, 0);} -#define NK_COLOR_MAP(NK_COLOR)\ - NK_COLOR(NK_COLOR_TEXT, 175,175,175,255) \ - NK_COLOR(NK_COLOR_WINDOW, 45, 45, 45, 255) \ - NK_COLOR(NK_COLOR_HEADER, 40, 40, 40, 255) \ - NK_COLOR(NK_COLOR_BORDER, 65, 65, 65, 255) \ - NK_COLOR(NK_COLOR_BUTTON, 50, 50, 50, 255) \ - NK_COLOR(NK_COLOR_BUTTON_HOVER, 40, 40, 40, 255) \ - NK_COLOR(NK_COLOR_BUTTON_ACTIVE, 35, 35, 35, 255) \ - NK_COLOR(NK_COLOR_TOGGLE, 100,100,100,255) \ - NK_COLOR(NK_COLOR_TOGGLE_HOVER, 120,120,120,255) \ - NK_COLOR(NK_COLOR_TOGGLE_CURSOR, 45, 45, 45, 255) \ - NK_COLOR(NK_COLOR_SELECT, 45, 45, 45, 255) \ - NK_COLOR(NK_COLOR_SELECT_ACTIVE, 35, 35, 35,255) \ - NK_COLOR(NK_COLOR_SLIDER, 38, 38, 38, 255) \ - NK_COLOR(NK_COLOR_SLIDER_CURSOR, 100,100,100,255) \ - NK_COLOR(NK_COLOR_SLIDER_CURSOR_HOVER, 120,120,120,255) \ - NK_COLOR(NK_COLOR_SLIDER_CURSOR_ACTIVE, 150,150,150,255) \ - NK_COLOR(NK_COLOR_PROPERTY, 38, 38, 38, 255) \ - NK_COLOR(NK_COLOR_EDIT, 38, 38, 38, 255) \ - NK_COLOR(NK_COLOR_EDIT_CURSOR, 175,175,175,255) \ - NK_COLOR(NK_COLOR_COMBO, 45, 45, 45, 255) \ - NK_COLOR(NK_COLOR_CHART, 120,120,120,255) \ - NK_COLOR(NK_COLOR_CHART_COLOR, 45, 45, 45, 255) \ - NK_COLOR(NK_COLOR_CHART_COLOR_HIGHLIGHT,255, 0, 0, 255) \ - NK_COLOR(NK_COLOR_SCROLLBAR, 40, 40, 40, 255) \ - NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR, 100,100,100,255) \ - NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_HOVER,120,120,120,255) \ - NK_COLOR(NK_COLOR_SCROLLBAR_CURSOR_ACTIVE,150,150,150,255) \ - NK_COLOR(NK_COLOR_TAB_HEADER, 40, 40, 40,255) - -NK_GLOBAL const struct nk_color -nk_default_color_style[NK_COLOR_COUNT] = { -#define NK_COLOR(a,b,c,d,e) {b,c,d,e}, - NK_COLOR_MAP(NK_COLOR) -#undef NK_COLOR -}; - -NK_GLOBAL const char *nk_color_names[NK_COLOR_COUNT] = { -#define NK_COLOR(a,b,c,d,e) #a, - NK_COLOR_MAP(NK_COLOR) -#undef NK_COLOR -}; - -NK_API const char *nk_style_get_color_by_name(enum nk_style_colors c) -{return nk_color_names[c];} - -NK_API struct nk_style_item nk_style_item_image(struct nk_image img) -{struct nk_style_item i; i.type = NK_STYLE_ITEM_IMAGE; i.data.image = img; return i;} - -NK_API struct nk_style_item nk_style_item_color(struct nk_color col) -{struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = col; return i;} - -NK_API struct nk_style_item nk_style_item_hide(void) -{struct nk_style_item i; i.type = NK_STYLE_ITEM_COLOR; i.data.color = nk_rgba(0,0,0,0); return i;} - -NK_API void -nk_style_from_table(struct nk_context *ctx, const struct nk_color *table) -{ - struct nk_style *style; - struct nk_style_text *text; - struct nk_style_button *button; - struct nk_style_toggle *toggle; - struct nk_style_selectable *select; - struct nk_style_slider *slider; - struct nk_style_progress *prog; - struct nk_style_scrollbar *scroll; - struct nk_style_edit *edit; - struct nk_style_property *property; - struct nk_style_combo *combo; - struct nk_style_chart *chart; - struct nk_style_tab *tab; - struct nk_style_window *win; - - NK_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - table = (!table) ? nk_default_color_style: table; - - /* default text */ - text = &style->text; - text->color = table[NK_COLOR_TEXT]; - text->padding = nk_vec2(0,0); - - /* default button */ - button = &style->button; - nk_zero_struct(*button); - button->normal = nk_style_item_color(table[NK_COLOR_BUTTON]); - button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); - button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); - button->border_color = table[NK_COLOR_BORDER]; - button->text_background = table[NK_COLOR_BUTTON]; - button->text_normal = table[NK_COLOR_TEXT]; - button->text_hover = table[NK_COLOR_TEXT]; - button->text_active = table[NK_COLOR_TEXT]; - button->padding = nk_vec2(2.0f,2.0f); - button->image_padding = nk_vec2(0.0f,0.0f); - button->touch_padding = nk_vec2(0.0f, 0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 1.0f; - button->rounding = 4.0f; - button->draw_begin = 0; - button->draw_end = 0; - - /* contextual button */ - button = &style->contextual_button; - nk_zero_struct(*button); - button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); - button->hover = nk_style_item_color(table[NK_COLOR_BUTTON_HOVER]); - button->active = nk_style_item_color(table[NK_COLOR_BUTTON_ACTIVE]); - button->border_color = table[NK_COLOR_WINDOW]; - button->text_background = table[NK_COLOR_WINDOW]; - button->text_normal = table[NK_COLOR_TEXT]; - button->text_hover = table[NK_COLOR_TEXT]; - button->text_active = table[NK_COLOR_TEXT]; - button->padding = nk_vec2(2.0f,2.0f); - button->touch_padding = nk_vec2(0.0f,0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 0.0f; - button->rounding = 0.0f; - button->draw_begin = 0; - button->draw_end = 0; - - /* menu button */ - button = &style->menu_button; - nk_zero_struct(*button); - button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); - button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); - button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); - button->border_color = table[NK_COLOR_WINDOW]; - button->text_background = table[NK_COLOR_WINDOW]; - button->text_normal = table[NK_COLOR_TEXT]; - button->text_hover = table[NK_COLOR_TEXT]; - button->text_active = table[NK_COLOR_TEXT]; - button->padding = nk_vec2(2.0f,2.0f); - button->touch_padding = nk_vec2(0.0f,0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 0.0f; - button->rounding = 1.0f; - button->draw_begin = 0; - button->draw_end = 0; - - /* checkbox toggle */ - toggle = &style->checkbox; - nk_zero_struct(*toggle); - toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); - toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); - toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); - toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); - toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); - toggle->userdata = nk_handle_ptr(0); - toggle->text_background = table[NK_COLOR_WINDOW]; - toggle->text_normal = table[NK_COLOR_TEXT]; - toggle->text_hover = table[NK_COLOR_TEXT]; - toggle->text_active = table[NK_COLOR_TEXT]; - toggle->padding = nk_vec2(2.0f, 2.0f); - toggle->touch_padding = nk_vec2(0,0); - toggle->border_color = nk_rgba(0,0,0,0); - toggle->border = 0.0f; - toggle->spacing = 4; - - /* option toggle */ - toggle = &style->option; - nk_zero_struct(*toggle); - toggle->normal = nk_style_item_color(table[NK_COLOR_TOGGLE]); - toggle->hover = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); - toggle->active = nk_style_item_color(table[NK_COLOR_TOGGLE_HOVER]); - toggle->cursor_normal = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); - toggle->cursor_hover = nk_style_item_color(table[NK_COLOR_TOGGLE_CURSOR]); - toggle->userdata = nk_handle_ptr(0); - toggle->text_background = table[NK_COLOR_WINDOW]; - toggle->text_normal = table[NK_COLOR_TEXT]; - toggle->text_hover = table[NK_COLOR_TEXT]; - toggle->text_active = table[NK_COLOR_TEXT]; - toggle->padding = nk_vec2(3.0f, 3.0f); - toggle->touch_padding = nk_vec2(0,0); - toggle->border_color = nk_rgba(0,0,0,0); - toggle->border = 0.0f; - toggle->spacing = 4; - - /* selectable */ - select = &style->selectable; - nk_zero_struct(*select); - select->normal = nk_style_item_color(table[NK_COLOR_SELECT]); - select->hover = nk_style_item_color(table[NK_COLOR_SELECT]); - select->pressed = nk_style_item_color(table[NK_COLOR_SELECT]); - select->normal_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); - select->hover_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); - select->pressed_active = nk_style_item_color(table[NK_COLOR_SELECT_ACTIVE]); - select->text_normal = table[NK_COLOR_TEXT]; - select->text_hover = table[NK_COLOR_TEXT]; - select->text_pressed = table[NK_COLOR_TEXT]; - select->text_normal_active = table[NK_COLOR_TEXT]; - select->text_hover_active = table[NK_COLOR_TEXT]; - select->text_pressed_active = table[NK_COLOR_TEXT]; - select->padding = nk_vec2(2.0f,2.0f); - select->touch_padding = nk_vec2(0,0); - select->userdata = nk_handle_ptr(0); - select->rounding = 0.0f; - select->draw_begin = 0; - select->draw_end = 0; - - /* slider */ - slider = &style->slider; - nk_zero_struct(*slider); - slider->normal = nk_style_item_hide(); - slider->hover = nk_style_item_hide(); - slider->active = nk_style_item_hide(); - slider->bar_normal = table[NK_COLOR_SLIDER]; - slider->bar_hover = table[NK_COLOR_SLIDER]; - slider->bar_active = table[NK_COLOR_SLIDER]; - slider->bar_filled = table[NK_COLOR_SLIDER_CURSOR]; - slider->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); - slider->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); - slider->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); - slider->inc_symbol = NK_SYMBOL_TRIANGLE_RIGHT; - slider->dec_symbol = NK_SYMBOL_TRIANGLE_LEFT; - slider->cursor_size = nk_vec2(16,16); - slider->padding = nk_vec2(2,2); - slider->spacing = nk_vec2(2,2); - slider->userdata = nk_handle_ptr(0); - slider->show_buttons = nk_false; - slider->bar_height = 8; - slider->rounding = 0; - slider->draw_begin = 0; - slider->draw_end = 0; - - /* slider buttons */ - button = &style->slider.inc_button; - button->normal = nk_style_item_color(nk_rgb(40,40,40)); - button->hover = nk_style_item_color(nk_rgb(42,42,42)); - button->active = nk_style_item_color(nk_rgb(44,44,44)); - button->border_color = nk_rgb(65,65,65); - button->text_background = nk_rgb(40,40,40); - button->text_normal = nk_rgb(175,175,175); - button->text_hover = nk_rgb(175,175,175); - button->text_active = nk_rgb(175,175,175); - button->padding = nk_vec2(8.0f,8.0f); - button->touch_padding = nk_vec2(0.0f,0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 1.0f; - button->rounding = 0.0f; - button->draw_begin = 0; - button->draw_end = 0; - style->slider.dec_button = style->slider.inc_button; - - /* progressbar */ - prog = &style->progress; - nk_zero_struct(*prog); - prog->normal = nk_style_item_color(table[NK_COLOR_SLIDER]); - prog->hover = nk_style_item_color(table[NK_COLOR_SLIDER]); - prog->active = nk_style_item_color(table[NK_COLOR_SLIDER]); - prog->cursor_normal = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR]); - prog->cursor_hover = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_HOVER]); - prog->cursor_active = nk_style_item_color(table[NK_COLOR_SLIDER_CURSOR_ACTIVE]); - prog->border_color = nk_rgba(0,0,0,0); - prog->cursor_border_color = nk_rgba(0,0,0,0); - prog->userdata = nk_handle_ptr(0); - prog->padding = nk_vec2(4,4); - prog->rounding = 0; - prog->border = 0; - prog->cursor_rounding = 0; - prog->cursor_border = 0; - prog->draw_begin = 0; - prog->draw_end = 0; - - /* scrollbars */ - scroll = &style->scrollh; - nk_zero_struct(*scroll); - scroll->normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); - scroll->hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); - scroll->active = nk_style_item_color(table[NK_COLOR_SCROLLBAR]); - scroll->cursor_normal = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR]); - scroll->cursor_hover = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_HOVER]); - scroll->cursor_active = nk_style_item_color(table[NK_COLOR_SCROLLBAR_CURSOR_ACTIVE]); - scroll->dec_symbol = NK_SYMBOL_CIRCLE_SOLID; - scroll->inc_symbol = NK_SYMBOL_CIRCLE_SOLID; - scroll->userdata = nk_handle_ptr(0); - scroll->border_color = table[NK_COLOR_SCROLLBAR]; - scroll->cursor_border_color = table[NK_COLOR_SCROLLBAR]; - scroll->padding = nk_vec2(0,0); - scroll->show_buttons = nk_false; - scroll->border = 0; - scroll->rounding = 0; - scroll->border_cursor = 0; - scroll->rounding_cursor = 0; - scroll->draw_begin = 0; - scroll->draw_end = 0; - style->scrollv = style->scrollh; - - /* scrollbars buttons */ - button = &style->scrollh.inc_button; - button->normal = nk_style_item_color(nk_rgb(40,40,40)); - button->hover = nk_style_item_color(nk_rgb(42,42,42)); - button->active = nk_style_item_color(nk_rgb(44,44,44)); - button->border_color = nk_rgb(65,65,65); - button->text_background = nk_rgb(40,40,40); - button->text_normal = nk_rgb(175,175,175); - button->text_hover = nk_rgb(175,175,175); - button->text_active = nk_rgb(175,175,175); - button->padding = nk_vec2(4.0f,4.0f); - button->touch_padding = nk_vec2(0.0f,0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 1.0f; - button->rounding = 0.0f; - button->draw_begin = 0; - button->draw_end = 0; - style->scrollh.dec_button = style->scrollh.inc_button; - style->scrollv.inc_button = style->scrollh.inc_button; - style->scrollv.dec_button = style->scrollh.inc_button; - - /* edit */ - edit = &style->edit; - nk_zero_struct(*edit); - edit->normal = nk_style_item_color(table[NK_COLOR_EDIT]); - edit->hover = nk_style_item_color(table[NK_COLOR_EDIT]); - edit->active = nk_style_item_color(table[NK_COLOR_EDIT]); - edit->cursor_normal = table[NK_COLOR_TEXT]; - edit->cursor_hover = table[NK_COLOR_TEXT]; - edit->cursor_text_normal= table[NK_COLOR_EDIT]; - edit->cursor_text_hover = table[NK_COLOR_EDIT]; - edit->border_color = table[NK_COLOR_BORDER]; - edit->text_normal = table[NK_COLOR_TEXT]; - edit->text_hover = table[NK_COLOR_TEXT]; - edit->text_active = table[NK_COLOR_TEXT]; - edit->selected_normal = table[NK_COLOR_TEXT]; - edit->selected_hover = table[NK_COLOR_TEXT]; - edit->selected_text_normal = table[NK_COLOR_EDIT]; - edit->selected_text_hover = table[NK_COLOR_EDIT]; - edit->scrollbar_size = nk_vec2(10,10); - edit->scrollbar = style->scrollv; - edit->padding = nk_vec2(4,4); - edit->row_padding = 2; - edit->cursor_size = 4; - edit->border = 1; - edit->rounding = 0; - - /* property */ - property = &style->property; - nk_zero_struct(*property); - property->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); - property->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); - property->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); - property->border_color = table[NK_COLOR_BORDER]; - property->label_normal = table[NK_COLOR_TEXT]; - property->label_hover = table[NK_COLOR_TEXT]; - property->label_active = table[NK_COLOR_TEXT]; - property->sym_left = NK_SYMBOL_TRIANGLE_LEFT; - property->sym_right = NK_SYMBOL_TRIANGLE_RIGHT; - property->userdata = nk_handle_ptr(0); - property->padding = nk_vec2(4,4); - property->border = 1; - property->rounding = 10; - property->draw_begin = 0; - property->draw_end = 0; - - /* property buttons */ - button = &style->property.dec_button; - nk_zero_struct(*button); - button->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); - button->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); - button->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); - button->border_color = nk_rgba(0,0,0,0); - button->text_background = table[NK_COLOR_PROPERTY]; - button->text_normal = table[NK_COLOR_TEXT]; - button->text_hover = table[NK_COLOR_TEXT]; - button->text_active = table[NK_COLOR_TEXT]; - button->padding = nk_vec2(0.0f,0.0f); - button->touch_padding = nk_vec2(0.0f,0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 0.0f; - button->rounding = 0.0f; - button->draw_begin = 0; - button->draw_end = 0; - style->property.inc_button = style->property.dec_button; - - /* property edit */ - edit = &style->property.edit; - nk_zero_struct(*edit); - edit->normal = nk_style_item_color(table[NK_COLOR_PROPERTY]); - edit->hover = nk_style_item_color(table[NK_COLOR_PROPERTY]); - edit->active = nk_style_item_color(table[NK_COLOR_PROPERTY]); - edit->border_color = nk_rgba(0,0,0,0); - edit->cursor_normal = table[NK_COLOR_TEXT]; - edit->cursor_hover = table[NK_COLOR_TEXT]; - edit->cursor_text_normal= table[NK_COLOR_EDIT]; - edit->cursor_text_hover = table[NK_COLOR_EDIT]; - edit->text_normal = table[NK_COLOR_TEXT]; - edit->text_hover = table[NK_COLOR_TEXT]; - edit->text_active = table[NK_COLOR_TEXT]; - edit->selected_normal = table[NK_COLOR_TEXT]; - edit->selected_hover = table[NK_COLOR_TEXT]; - edit->selected_text_normal = table[NK_COLOR_EDIT]; - edit->selected_text_hover = table[NK_COLOR_EDIT]; - edit->padding = nk_vec2(0,0); - edit->cursor_size = 8; - edit->border = 0; - edit->rounding = 0; - - /* chart */ - chart = &style->chart; - nk_zero_struct(*chart); - chart->background = nk_style_item_color(table[NK_COLOR_CHART]); - chart->border_color = table[NK_COLOR_BORDER]; - chart->selected_color = table[NK_COLOR_CHART_COLOR_HIGHLIGHT]; - chart->color = table[NK_COLOR_CHART_COLOR]; - chart->padding = nk_vec2(4,4); - chart->border = 0; - chart->rounding = 0; - - /* combo */ - combo = &style->combo; - combo->normal = nk_style_item_color(table[NK_COLOR_COMBO]); - combo->hover = nk_style_item_color(table[NK_COLOR_COMBO]); - combo->active = nk_style_item_color(table[NK_COLOR_COMBO]); - combo->border_color = table[NK_COLOR_BORDER]; - combo->label_normal = table[NK_COLOR_TEXT]; - combo->label_hover = table[NK_COLOR_TEXT]; - combo->label_active = table[NK_COLOR_TEXT]; - combo->sym_normal = NK_SYMBOL_TRIANGLE_DOWN; - combo->sym_hover = NK_SYMBOL_TRIANGLE_DOWN; - combo->sym_active = NK_SYMBOL_TRIANGLE_DOWN; - combo->content_padding = nk_vec2(4,4); - combo->button_padding = nk_vec2(0,4); - combo->spacing = nk_vec2(4,0); - combo->border = 1; - combo->rounding = 0; - - /* combo button */ - button = &style->combo.button; - nk_zero_struct(*button); - button->normal = nk_style_item_color(table[NK_COLOR_COMBO]); - button->hover = nk_style_item_color(table[NK_COLOR_COMBO]); - button->active = nk_style_item_color(table[NK_COLOR_COMBO]); - button->border_color = nk_rgba(0,0,0,0); - button->text_background = table[NK_COLOR_COMBO]; - button->text_normal = table[NK_COLOR_TEXT]; - button->text_hover = table[NK_COLOR_TEXT]; - button->text_active = table[NK_COLOR_TEXT]; - button->padding = nk_vec2(2.0f,2.0f); - button->touch_padding = nk_vec2(0.0f,0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 0.0f; - button->rounding = 0.0f; - button->draw_begin = 0; - button->draw_end = 0; - - /* tab */ - tab = &style->tab; - tab->background = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); - tab->border_color = table[NK_COLOR_BORDER]; - tab->text = table[NK_COLOR_TEXT]; - tab->sym_minimize = NK_SYMBOL_TRIANGLE_RIGHT; - tab->sym_maximize = NK_SYMBOL_TRIANGLE_DOWN; - tab->padding = nk_vec2(4,4); - tab->spacing = nk_vec2(4,4); - tab->indent = 10.0f; - tab->border = 1; - tab->rounding = 0; - - /* tab button */ - button = &style->tab.tab_minimize_button; - nk_zero_struct(*button); - button->normal = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); - button->hover = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); - button->active = nk_style_item_color(table[NK_COLOR_TAB_HEADER]); - button->border_color = nk_rgba(0,0,0,0); - button->text_background = table[NK_COLOR_TAB_HEADER]; - button->text_normal = table[NK_COLOR_TEXT]; - button->text_hover = table[NK_COLOR_TEXT]; - button->text_active = table[NK_COLOR_TEXT]; - button->padding = nk_vec2(2.0f,2.0f); - button->touch_padding = nk_vec2(0.0f,0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 0.0f; - button->rounding = 0.0f; - button->draw_begin = 0; - button->draw_end = 0; - style->tab.tab_maximize_button =*button; - - /* node button */ - button = &style->tab.node_minimize_button; - nk_zero_struct(*button); - button->normal = nk_style_item_color(table[NK_COLOR_WINDOW]); - button->hover = nk_style_item_color(table[NK_COLOR_WINDOW]); - button->active = nk_style_item_color(table[NK_COLOR_WINDOW]); - button->border_color = nk_rgba(0,0,0,0); - button->text_background = table[NK_COLOR_TAB_HEADER]; - button->text_normal = table[NK_COLOR_TEXT]; - button->text_hover = table[NK_COLOR_TEXT]; - button->text_active = table[NK_COLOR_TEXT]; - button->padding = nk_vec2(2.0f,2.0f); - button->touch_padding = nk_vec2(0.0f,0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 0.0f; - button->rounding = 0.0f; - button->draw_begin = 0; - button->draw_end = 0; - style->tab.node_maximize_button =*button; - - /* window header */ - win = &style->window; - win->header.align = NK_HEADER_RIGHT; - win->header.close_symbol = NK_SYMBOL_X; - win->header.minimize_symbol = NK_SYMBOL_MINUS; - win->header.maximize_symbol = NK_SYMBOL_PLUS; - win->header.normal = nk_style_item_color(table[NK_COLOR_HEADER]); - win->header.hover = nk_style_item_color(table[NK_COLOR_HEADER]); - win->header.active = nk_style_item_color(table[NK_COLOR_HEADER]); - win->header.label_normal = table[NK_COLOR_TEXT]; - win->header.label_hover = table[NK_COLOR_TEXT]; - win->header.label_active = table[NK_COLOR_TEXT]; - win->header.label_padding = nk_vec2(4,4); - win->header.padding = nk_vec2(4,4); - win->header.spacing = nk_vec2(0,0); - - /* window header close button */ - button = &style->window.header.close_button; - nk_zero_struct(*button); - button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); - button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); - button->active = nk_style_item_color(table[NK_COLOR_HEADER]); - button->border_color = nk_rgba(0,0,0,0); - button->text_background = table[NK_COLOR_HEADER]; - button->text_normal = table[NK_COLOR_TEXT]; - button->text_hover = table[NK_COLOR_TEXT]; - button->text_active = table[NK_COLOR_TEXT]; - button->padding = nk_vec2(0.0f,0.0f); - button->touch_padding = nk_vec2(0.0f,0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 0.0f; - button->rounding = 0.0f; - button->draw_begin = 0; - button->draw_end = 0; - - /* window header minimize button */ - button = &style->window.header.minimize_button; - nk_zero_struct(*button); - button->normal = nk_style_item_color(table[NK_COLOR_HEADER]); - button->hover = nk_style_item_color(table[NK_COLOR_HEADER]); - button->active = nk_style_item_color(table[NK_COLOR_HEADER]); - button->border_color = nk_rgba(0,0,0,0); - button->text_background = table[NK_COLOR_HEADER]; - button->text_normal = table[NK_COLOR_TEXT]; - button->text_hover = table[NK_COLOR_TEXT]; - button->text_active = table[NK_COLOR_TEXT]; - button->padding = nk_vec2(0.0f,0.0f); - button->touch_padding = nk_vec2(0.0f,0.0f); - button->userdata = nk_handle_ptr(0); - button->text_alignment = NK_TEXT_CENTERED; - button->border = 0.0f; - button->rounding = 0.0f; - button->draw_begin = 0; - button->draw_end = 0; - - /* window */ - win->background = table[NK_COLOR_WINDOW]; - win->fixed_background = nk_style_item_color(table[NK_COLOR_WINDOW]); - win->border_color = table[NK_COLOR_BORDER]; - win->popup_border_color = table[NK_COLOR_BORDER]; - win->combo_border_color = table[NK_COLOR_BORDER]; - win->contextual_border_color = table[NK_COLOR_BORDER]; - win->menu_border_color = table[NK_COLOR_BORDER]; - win->group_border_color = table[NK_COLOR_BORDER]; - win->tooltip_border_color = table[NK_COLOR_BORDER]; - win->scaler = nk_style_item_color(table[NK_COLOR_TEXT]); - - win->rounding = 0.0f; - win->spacing = nk_vec2(4,4); - win->scrollbar_size = nk_vec2(10,10); - win->min_size = nk_vec2(64,64); - - win->combo_border = 1.0f; - win->contextual_border = 1.0f; - win->menu_border = 1.0f; - win->group_border = 1.0f; - win->tooltip_border = 1.0f; - win->popup_border = 1.0f; - win->border = 2.0f; - - win->padding = nk_vec2(4,4); - win->group_padding = nk_vec2(4,4); - win->popup_padding = nk_vec2(4,4); - win->combo_padding = nk_vec2(4,4); - win->contextual_padding = nk_vec2(4,4); - win->menu_padding = nk_vec2(4,4); - win->tooltip_padding = nk_vec2(4,4); -} - -NK_API void -nk_style_set_font(struct nk_context *ctx, const struct nk_user_font *font) -{ - struct nk_style *style; - NK_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - style->font = font; - ctx->stacks.fonts.head = 0; -} - -NK_API int -nk_style_push_font(struct nk_context *ctx, struct nk_user_font *font) -{ - struct nk_config_stack_user_font *font_stack; - struct nk_config_stack_user_font_element *element; - - NK_ASSERT(ctx); - if (!ctx) return 0; - - font_stack = &ctx->stacks.fonts; - NK_ASSERT(font_stack->head < (int)NK_LEN(font_stack->elements)); - if (font_stack->head >= (int)NK_LEN(font_stack->elements)) - return 0; - - element = &font_stack->elements[font_stack->head++]; - element->address = &ctx->style.font; - element->old_value = ctx->style.font; - ctx->style.font = font; - return 1; -} - -NK_API int -nk_style_pop_font(struct nk_context *ctx) -{ - struct nk_config_stack_user_font *font_stack; - struct nk_config_stack_user_font_element *element; - - NK_ASSERT(ctx); - if (!ctx) return 0; - - font_stack = &ctx->stacks.fonts; - NK_ASSERT(font_stack->head > 0); - if (font_stack->head < 1) - return 0; - - element = &font_stack->elements[--font_stack->head]; - *element->address = element->old_value; - return 1; -} - -#define NK_STYLE_PUSH_IMPLEMENATION(prefix, type, stack) \ -nk_style_push_##type(struct nk_context *ctx, prefix##_##type *address, prefix##_##type value)\ -{\ - struct nk_config_stack_##type * type_stack;\ - struct nk_config_stack_##type##_element *element;\ - NK_ASSERT(ctx);\ - if (!ctx) return 0;\ - type_stack = &ctx->stacks.stack;\ - NK_ASSERT(type_stack->head < (int)NK_LEN(type_stack->elements));\ - if (type_stack->head >= (int)NK_LEN(type_stack->elements))\ - return 0;\ - element = &type_stack->elements[type_stack->head++];\ - element->address = address;\ - element->old_value = *address;\ - *address = value;\ - return 1;\ -} - -#define NK_STYLE_POP_IMPLEMENATION(type, stack) \ -nk_style_pop_##type(struct nk_context *ctx)\ -{\ - struct nk_config_stack_##type *type_stack;\ - struct nk_config_stack_##type##_element *element;\ - NK_ASSERT(ctx);\ - if (!ctx) return 0;\ - type_stack = &ctx->stacks.stack;\ - NK_ASSERT(type_stack->head > 0);\ - if (type_stack->head < 1)\ - return 0;\ - element = &type_stack->elements[--type_stack->head];\ - *element->address = element->old_value;\ - return 1;\ -} - -NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, style_item, style_items) -NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,float, floats) -NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk, vec2, vectors) -NK_API int NK_STYLE_PUSH_IMPLEMENATION(nk,flags, flags) -NK_API int NK_STYLE_PUSH_IMPLEMENATION(struct nk,color, colors) - -NK_API int NK_STYLE_POP_IMPLEMENATION(style_item, style_items) -NK_API int NK_STYLE_POP_IMPLEMENATION(float,floats) -NK_API int NK_STYLE_POP_IMPLEMENATION(vec2, vectors) -NK_API int NK_STYLE_POP_IMPLEMENATION(flags,flags) -NK_API int NK_STYLE_POP_IMPLEMENATION(color,colors) - -NK_API int -nk_style_set_cursor(struct nk_context *ctx, enum nk_style_cursor c) -{ - struct nk_style *style; - NK_ASSERT(ctx); - if (!ctx) return 0; - style = &ctx->style; - if (style->cursors[c]) { - style->cursor_active = style->cursors[c]; - return 1; - } - return 0; -} - -NK_API void -nk_style_show_cursor(struct nk_context *ctx) -{ - ctx->style.cursor_visible = nk_true; -} - -NK_API void -nk_style_hide_cursor(struct nk_context *ctx) -{ - ctx->style.cursor_visible = nk_false; -} - -NK_API void -nk_style_load_cursor(struct nk_context *ctx, enum nk_style_cursor cursor, - const struct nk_cursor *c) -{ - struct nk_style *style; - NK_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - style->cursors[cursor] = c; -} - -NK_API void -nk_style_load_all_cursors(struct nk_context *ctx, struct nk_cursor *cursors) -{ - int i = 0; - struct nk_style *style; - NK_ASSERT(ctx); - if (!ctx) return; - style = &ctx->style; - for (i = 0; i < NK_CURSOR_COUNT; ++i) - style->cursors[i] = &cursors[i]; - style->cursor_visible = nk_true; -} - -/* =============================================================== - * - * POOL - * - * ===============================================================*/ -NK_INTERN void -nk_pool_init(struct nk_pool *pool, struct nk_allocator *alloc, - unsigned int capacity) -{ - nk_zero(pool, sizeof(*pool)); - pool->alloc = *alloc; - pool->capacity = capacity; - pool->type = NK_BUFFER_DYNAMIC; - pool->pages = 0; -} - -NK_INTERN void -nk_pool_free(struct nk_pool *pool) -{ - struct nk_page *next; - struct nk_page *iter = pool->pages; - if (!pool) return; - if (pool->type == NK_BUFFER_FIXED) return; - while (iter) { - next = iter->next; - pool->alloc.free(pool->alloc.userdata, iter); - iter = next; - } -} - -NK_INTERN void -nk_pool_init_fixed(struct nk_pool *pool, void *memory, nk_size size) -{ - nk_zero(pool, sizeof(*pool)); - NK_ASSERT(size >= sizeof(struct nk_page)); - if (size < sizeof(struct nk_page)) return; - pool->capacity = (unsigned)(size - sizeof(struct nk_page)) / sizeof(struct nk_page_element); - pool->pages = (struct nk_page*)memory; - pool->type = NK_BUFFER_FIXED; - pool->size = size; -} - -NK_INTERN struct nk_page_element* -nk_pool_alloc(struct nk_pool *pool) -{ - if (!pool->pages || pool->pages->size >= pool->capacity) { - /* allocate new page */ - struct nk_page *page; - if (pool->type == NK_BUFFER_FIXED) { - if (!pool->pages) { - NK_ASSERT(pool->pages); - return 0; - } - NK_ASSERT(pool->pages->size < pool->capacity); - return 0; - } else { - nk_size size = sizeof(struct nk_page); - size += NK_POOL_DEFAULT_CAPACITY * sizeof(union nk_page_data); - page = (struct nk_page*)pool->alloc.alloc(pool->alloc.userdata,0, size); - page->next = pool->pages; - pool->pages = page; - page->size = 0; - } - } - return &pool->pages->win[pool->pages->size++]; -} - -/* =============================================================== - * - * CONTEXT - * - * ===============================================================*/ -NK_INTERN void* nk_create_window(struct nk_context *ctx); -NK_INTERN void nk_remove_window(struct nk_context*, struct nk_window*); -NK_INTERN void nk_free_window(struct nk_context *ctx, struct nk_window *win); -NK_INTERN void nk_free_table(struct nk_context *ctx, struct nk_table *tbl); -NK_INTERN void nk_remove_table(struct nk_window *win, struct nk_table *tbl); -NK_INTERN void* nk_create_panel(struct nk_context *ctx); -NK_INTERN void nk_free_panel(struct nk_context*, struct nk_panel *pan); - -NK_INTERN void -nk_setup(struct nk_context *ctx, const struct nk_user_font *font) -{ - NK_ASSERT(ctx); - if (!ctx) return; - nk_zero_struct(*ctx); - nk_style_default(ctx); - ctx->seq = 1; - if (font) ctx->style.font = font; -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT - nk_draw_list_init(&ctx->draw_list); -#endif -} - -#ifdef NK_INCLUDE_DEFAULT_ALLOCATOR -NK_API int -nk_init_default(struct nk_context *ctx, const struct nk_user_font *font) -{ - struct nk_allocator alloc; - alloc.userdata.ptr = 0; - alloc.alloc = nk_malloc; - alloc.free = nk_mfree; - return nk_init(ctx, &alloc, font); -} -#endif - -NK_API int -nk_init_fixed(struct nk_context *ctx, void *memory, nk_size size, - const struct nk_user_font *font) -{ - NK_ASSERT(memory); - if (!memory) return 0; - nk_setup(ctx, font); - nk_buffer_init_fixed(&ctx->memory, memory, size); - ctx->use_pool = nk_false; - return 1; -} - -NK_API int -nk_init_custom(struct nk_context *ctx, struct nk_buffer *cmds, - struct nk_buffer *pool, const struct nk_user_font *font) -{ - NK_ASSERT(cmds); - NK_ASSERT(pool); - if (!cmds || !pool) return 0; - - nk_setup(ctx, font); - ctx->memory = *cmds; - if (pool->type == NK_BUFFER_FIXED) { - /* take memory from buffer and alloc fixed pool */ - nk_pool_init_fixed(&ctx->pool, pool->memory.ptr, pool->memory.size); - } else { - /* create dynamic pool from buffer allocator */ - struct nk_allocator *alloc = &pool->pool; - nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); - } - ctx->use_pool = nk_true; - return 1; -} - -NK_API int -nk_init(struct nk_context *ctx, struct nk_allocator *alloc, - const struct nk_user_font *font) -{ - NK_ASSERT(alloc); - if (!alloc) return 0; - nk_setup(ctx, font); - nk_buffer_init(&ctx->memory, alloc, NK_DEFAULT_COMMAND_BUFFER_SIZE); - nk_pool_init(&ctx->pool, alloc, NK_POOL_DEFAULT_CAPACITY); - ctx->use_pool = nk_true; - return 1; -} - -#ifdef NK_INCLUDE_COMMAND_USERDATA -NK_API void -nk_set_user_data(struct nk_context *ctx, nk_handle handle) -{ - if (!ctx) return; - ctx->userdata = handle; - if (ctx->current) - ctx->current->buffer.userdata = handle; -} -#endif - -NK_API void -nk_free(struct nk_context *ctx) -{ - NK_ASSERT(ctx); - if (!ctx) return; - nk_buffer_free(&ctx->memory); - if (ctx->use_pool) - nk_pool_free(&ctx->pool); - - nk_zero(&ctx->input, sizeof(ctx->input)); - nk_zero(&ctx->style, sizeof(ctx->style)); - nk_zero(&ctx->memory, sizeof(ctx->memory)); - - ctx->seq = 0; - ctx->build = 0; - ctx->begin = 0; - ctx->end = 0; - ctx->active = 0; - ctx->current = 0; - ctx->freelist = 0; - ctx->count = 0; -} - -NK_API void -nk_clear(struct nk_context *ctx) -{ - struct nk_window *iter; - struct nk_window *next; - NK_ASSERT(ctx); - - if (!ctx) return; - if (ctx->use_pool) - nk_buffer_clear(&ctx->memory); - else nk_buffer_reset(&ctx->memory, NK_BUFFER_FRONT); - - ctx->build = 0; - ctx->memory.calls = 0; - ctx->last_widget_state = 0; - ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; - NK_MEMSET(&ctx->overlay, 0, sizeof(ctx->overlay)); -#ifdef NK_INCLUDE_VERTEX_BUFFER_OUTPUT - nk_draw_list_clear(&ctx->draw_list); -#endif - - /* garbage collector */ - iter = ctx->begin; - while (iter) { - /* make sure minimized windows do not get removed */ - if ((iter->flags & NK_WINDOW_MINIMIZED) && - !(iter->flags & NK_WINDOW_CLOSED)) { - iter = iter->next; - continue; - } - - /* free unused popup windows */ - if (iter->popup.win && iter->popup.win->seq != ctx->seq) { - nk_free_window(ctx, iter->popup.win); - iter->popup.win = 0; - } - - /* remove unused window state tables */ - {struct nk_table *n, *it = iter->tables; - while (it) { - n = it->next; - if (it->seq != ctx->seq) { - nk_remove_table(iter, it); - nk_zero(it, sizeof(union nk_page_data)); - nk_free_table(ctx, it); - if (it == iter->tables) - iter->tables = n; - } - it = n; - }} - - /* window itself is not used anymore so free */ - if (iter->seq != ctx->seq || iter->flags & NK_WINDOW_CLOSED) { - next = iter->next; - nk_remove_window(ctx, iter); - nk_free_window(ctx, iter); - iter = next; - } else iter = iter->next; - } - ctx->seq++; -} - -/* ---------------------------------------------------------------- - * - * BUFFERING - * - * ---------------------------------------------------------------*/ -NK_INTERN void -nk_start_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) -{ - NK_ASSERT(ctx); - NK_ASSERT(buffer); - if (!ctx || !buffer) return; - buffer->begin = ctx->memory.allocated; - buffer->end = buffer->begin; - buffer->last = buffer->begin; - buffer->clip = nk_null_rect; -} - -NK_INTERN void -nk_start(struct nk_context *ctx, struct nk_window *win) -{ - NK_ASSERT(ctx); - NK_ASSERT(win); - nk_start_buffer(ctx, &win->buffer); -} - -NK_INTERN void -nk_start_popup(struct nk_context *ctx, struct nk_window *win) -{ - struct nk_popup_buffer *buf; - struct nk_panel *iter; - NK_ASSERT(ctx); - NK_ASSERT(win); - if (!ctx || !win) return; - - /* make sure to use the correct popup buffer*/ - iter = win->layout; - while (iter->parent) - iter = iter->parent; - - /* save buffer fill state for popup */ - buf = &iter->popup_buffer; - buf->begin = win->buffer.end; - buf->end = win->buffer.end; - buf->parent = win->buffer.last; - buf->last = buf->begin; - buf->active = nk_true; -} - -NK_INTERN void -nk_finish_popup(struct nk_context *ctx, struct nk_window *win) -{ - struct nk_popup_buffer *buf; - struct nk_panel *iter; - NK_ASSERT(ctx); - NK_ASSERT(win); - if (!ctx || !win) return; - - /* make sure to use the correct popup buffer*/ - iter = win->layout; - while (iter->parent) - iter = iter->parent; - - buf = &iter->popup_buffer; - buf->last = win->buffer.last; - buf->end = win->buffer.end; -} - -NK_INTERN void -nk_finish_buffer(struct nk_context *ctx, struct nk_command_buffer *buffer) -{ - NK_ASSERT(ctx); - NK_ASSERT(buffer); - if (!ctx || !buffer) return; - buffer->end = ctx->memory.allocated; -} - -NK_INTERN void -nk_finish(struct nk_context *ctx, struct nk_window *win) -{ - struct nk_popup_buffer *buf; - struct nk_command *parent_last; - struct nk_command *sublast; - struct nk_command *last; - void *memory; - - NK_ASSERT(ctx); - NK_ASSERT(win); - if (!ctx || !win) return; - nk_finish_buffer(ctx, &win->buffer); - if (!win->layout->popup_buffer.active) return; - - /* from here on is for popup window buffer handling */ - /*--------------------------------------------------*/ - buf = &win->layout->popup_buffer; - memory = ctx->memory.memory.ptr; - - /* redirect the sub-window buffer to the end of the window command buffer */ - parent_last = nk_ptr_add(struct nk_command, memory, buf->parent); - sublast = nk_ptr_add(struct nk_command, memory, buf->last); - last = nk_ptr_add(struct nk_command, memory, win->buffer.last); - - parent_last->next = buf->end; - sublast->next = last->next; - last->next = buf->begin; - win->buffer.last = buf->last; - win->buffer.end = buf->end; - buf->active = nk_false; -} - -NK_INTERN void -nk_build(struct nk_context *ctx) -{ - struct nk_window *iter; - struct nk_window *next; - struct nk_command *cmd; - nk_byte *buffer; - - /* draw cursor overlay */ - if (!ctx->style.cursor_active) - ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_ARROW]; - if (ctx->style.cursor_active && !ctx->input.mouse.grabbed && ctx->style.cursor_visible) { - struct nk_rect mouse_bounds; - const struct nk_cursor *cursor = ctx->style.cursor_active; - nk_command_buffer_init(&ctx->overlay, &ctx->memory, NK_CLIPPING_OFF); - nk_start_buffer(ctx, &ctx->overlay); - - mouse_bounds.x = ctx->input.mouse.pos.x - cursor->offset.x; - mouse_bounds.y = ctx->input.mouse.pos.y - cursor->offset.y; - mouse_bounds.w = cursor->size.x; - mouse_bounds.h = cursor->size.y; - - nk_draw_image(&ctx->overlay, mouse_bounds, &cursor->img, nk_white); - nk_finish_buffer(ctx, &ctx->overlay); - } - - /* build one big draw command list out of all buffers */ - iter = ctx->begin; - buffer = (nk_byte*)ctx->memory.memory.ptr; - while (iter != 0) { - next = iter->next; - if (iter->buffer.last == iter->buffer.begin || (iter->flags & NK_WINDOW_HIDDEN)) { - iter = next; - continue; - } - cmd = nk_ptr_add(struct nk_command, buffer, iter->buffer.last); - while (next && ((next->buffer.last == next->buffer.begin) || - (next->flags & NK_WINDOW_HIDDEN))) - next = next->next; /* skip empty command buffers */ - - if (next) { - cmd->next = next->buffer.begin; - } else { - if (ctx->overlay.end != ctx->overlay.begin) - cmd->next = ctx->overlay.begin; - else cmd->next = ctx->memory.allocated; - } - iter = next; - } -} - -NK_API const struct nk_command* -nk__begin(struct nk_context *ctx) -{ - struct nk_window *iter; - nk_byte *buffer; - NK_ASSERT(ctx); - if (!ctx) return 0; - if (!ctx->count) return 0; - - buffer = (nk_byte*)ctx->memory.memory.ptr; - if (!ctx->build) { - nk_build(ctx); - ctx->build = nk_true; - } - - iter = ctx->begin; - while (iter && ((iter->buffer.begin == iter->buffer.end) || (iter->flags & NK_WINDOW_HIDDEN))) - iter = iter->next; - if (!iter) return 0; - return nk_ptr_add_const(struct nk_command, buffer, iter->buffer.begin); -} - -NK_API const struct nk_command* -nk__next(struct nk_context *ctx, const struct nk_command *cmd) -{ - nk_byte *buffer; - const struct nk_command *next; - NK_ASSERT(ctx); - if (!ctx || !cmd || !ctx->count) return 0; - if (cmd->next >= ctx->memory.allocated) return 0; - buffer = (nk_byte*)ctx->memory.memory.ptr; - next = nk_ptr_add_const(struct nk_command, buffer, cmd->next); - return next; -} - -/* ---------------------------------------------------------------- - * - * PANEL - * - * ---------------------------------------------------------------*/ -static int -nk_panel_has_header(nk_flags flags, const char *title) -{ - /* window header state */ - int active = 0; - active = (flags & (NK_WINDOW_CLOSABLE|NK_WINDOW_MINIMIZABLE)); - active = active || (flags & NK_WINDOW_TITLE); - active = active && !(flags & NK_WINDOW_HIDDEN) && title; - return active; -} - -NK_INTERN struct nk_vec2 -nk_panel_get_padding(const struct nk_style *style, enum nk_panel_type type) -{ - switch (type) { - default: - case NK_PANEL_WINDOW: return style->window.padding; - case NK_PANEL_GROUP: return style->window.group_padding; - case NK_PANEL_POPUP: return style->window.popup_padding; - case NK_PANEL_CONTEXTUAL: return style->window.contextual_padding; - case NK_PANEL_COMBO: return style->window.combo_padding; - case NK_PANEL_MENU: return style->window.menu_padding; - case NK_PANEL_TOOLTIP: return style->window.menu_padding; - } -} - -NK_INTERN float -nk_panel_get_border(const struct nk_style *style, nk_flags flags, - enum nk_panel_type type) -{ - if (flags & NK_WINDOW_BORDER) { - switch (type) { - default: - case NK_PANEL_WINDOW: return style->window.border; - case NK_PANEL_GROUP: return style->window.group_border; - case NK_PANEL_POPUP: return style->window.popup_border; - case NK_PANEL_CONTEXTUAL: return style->window.contextual_border; - case NK_PANEL_COMBO: return style->window.combo_border; - case NK_PANEL_MENU: return style->window.menu_border; - case NK_PANEL_TOOLTIP: return style->window.menu_border; - }} else return 0; -} - -NK_INTERN struct nk_color -nk_panel_get_border_color(const struct nk_style *style, enum nk_panel_type type) -{ - switch (type) { - default: - case NK_PANEL_WINDOW: return style->window.border_color; - case NK_PANEL_GROUP: return style->window.group_border_color; - case NK_PANEL_POPUP: return style->window.popup_border_color; - case NK_PANEL_CONTEXTUAL: return style->window.contextual_border_color; - case NK_PANEL_COMBO: return style->window.combo_border_color; - case NK_PANEL_MENU: return style->window.menu_border_color; - case NK_PANEL_TOOLTIP: return style->window.menu_border_color; - } -} - -NK_INTERN int -nk_panel_is_sub(enum nk_panel_type type) -{ - return (type & NK_PANEL_SET_SUB)?1:0; -} - -NK_INTERN int -nk_panel_is_nonblock(enum nk_panel_type type) -{ - return (type & NK_PANEL_SET_NONBLOCK)?1:0; -} - -NK_INTERN int -nk_panel_begin(struct nk_context *ctx, const char *title, enum nk_panel_type panel_type) -{ - struct nk_input *in; - struct nk_window *win; - struct nk_panel *layout; - struct nk_command_buffer *out; - const struct nk_style *style; - const struct nk_user_font *font; - - struct nk_vec2 scrollbar_size; - struct nk_vec2 panel_padding; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) return 0; - nk_zero(ctx->current->layout, sizeof(*ctx->current->layout)); - if (ctx->current->flags & NK_WINDOW_HIDDEN) - return 0; - - /* pull state into local stack */ - style = &ctx->style; - font = style->font; - in = &ctx->input; - win = ctx->current; - layout = win->layout; - out = &win->buffer; -#ifdef NK_INCLUDE_COMMAND_USERDATA - win->buffer.userdata = ctx->userdata; -#endif - - /* pull style configuration into local stack */ - scrollbar_size = style->window.scrollbar_size; - panel_padding = nk_panel_get_padding(style, panel_type); - - /* window movement */ - if ((win->flags & NK_WINDOW_MOVABLE) && !(win->flags & NK_WINDOW_ROM)) { - int left_mouse_down; - int left_mouse_click_in_cursor; - - /* calculate draggable window space */ - struct nk_rect header; - header.x = win->bounds.x; - header.y = win->bounds.y; - header.w = win->bounds.w; - if (nk_panel_has_header(win->flags, title)) { - header.h = font->height + 2.0f * style->window.header.padding.y; - header.h += 2.0f * style->window.header.label_padding.y; - } else header.h = panel_padding.y; - - /* window movement by dragging */ - left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; - left_mouse_click_in_cursor = nk_input_has_mouse_click_down_in_rect(in, - NK_BUTTON_LEFT, header, nk_true); - if (left_mouse_down && left_mouse_click_in_cursor) { - win->bounds.x = win->bounds.x + in->mouse.delta.x; - win->bounds.y = win->bounds.y + in->mouse.delta.y; - in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x += in->mouse.delta.x; - in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y += in->mouse.delta.y; - ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_MOVE]; - } - } - - /* setup panel */ - layout->type = panel_type; - layout->flags = win->flags; - layout->bounds = win->bounds; - layout->bounds.x += panel_padding.x; - layout->bounds.w -= 2*panel_padding.x; - if (win->flags & NK_WINDOW_BORDER) { - layout->border = nk_panel_get_border(style, win->flags, panel_type); - layout->bounds = nk_shrink_rect(layout->bounds, layout->border); - } else layout->border = 0; - layout->at_y = layout->bounds.y; - layout->at_x = layout->bounds.x; - layout->max_x = 0; - layout->header_height = 0; - layout->footer_height = 0; - layout->row.index = 0; - layout->row.columns = 0; - layout->row.ratio = 0; - layout->row.item_width = 0; - layout->row.tree_depth = 0; - layout->row.height = panel_padding.y; - layout->has_scrolling = nk_true; - if (!(win->flags & NK_WINDOW_NO_SCROLLBAR)) - layout->bounds.w -= scrollbar_size.x; - if (!nk_panel_is_nonblock(panel_type)) { - layout->footer_height = 0; - if (!(win->flags & NK_WINDOW_NO_SCROLLBAR) || win->flags & NK_WINDOW_SCALABLE) - layout->footer_height = scrollbar_size.y; - layout->bounds.h -= layout->footer_height; - } - - /* panel header */ - if (nk_panel_has_header(win->flags, title)) - { - struct nk_text text; - struct nk_rect header; - const struct nk_style_item *background = 0; - - /* calculate header bounds */ - header.x = win->bounds.x; - header.y = win->bounds.y; - header.w = win->bounds.w; - header.h = font->height + 2.0f * style->window.header.padding.y; - header.h += (2.0f * style->window.header.label_padding.y); - - /* shrink panel by header */ - layout->header_height = header.h; - layout->bounds.y += header.h; - layout->bounds.h -= header.h; - layout->at_y += header.h; - - /* select correct header background and text color */ - if (ctx->active == win) { - background = &style->window.header.active; - text.text = style->window.header.label_active; - } else if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) { - background = &style->window.header.hover; - text.text = style->window.header.label_hover; - } else { - background = &style->window.header.normal; - text.text = style->window.header.label_normal; - } - - /* draw header background */ - header.h += 1.0f; - if (background->type == NK_STYLE_ITEM_IMAGE) { - text.background = nk_rgba(0,0,0,0); - nk_draw_image(&win->buffer, header, &background->data.image, nk_white); - } else { - text.background = background->data.color; - nk_fill_rect(out, header, 0, background->data.color); - } - - /* window close button */ - {struct nk_rect button; - button.y = header.y + style->window.header.padding.y; - button.h = header.h - 2 * style->window.header.padding.y; - button.w = button.h; - if (win->flags & NK_WINDOW_CLOSABLE) { - nk_flags ws = 0; - if (style->window.header.align == NK_HEADER_RIGHT) { - button.x = (header.w + header.x) - (button.w + style->window.header.padding.x); - header.w -= button.w + style->window.header.spacing.x + style->window.header.padding.x; - } else { - button.x = header.x + style->window.header.padding.x; - header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; - } - - if (nk_do_button_symbol(&ws, &win->buffer, button, - style->window.header.close_symbol, NK_BUTTON_DEFAULT, - &style->window.header.close_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) - { - layout->flags |= NK_WINDOW_HIDDEN; - layout->flags |= NK_WINDOW_CLOSED; - layout->flags &= (nk_flags)~NK_WINDOW_MINIMIZED; - } - } - - /* window minimize button */ - if (win->flags & NK_WINDOW_MINIMIZABLE) { - nk_flags ws = 0; - if (style->window.header.align == NK_HEADER_RIGHT) { - button.x = (header.w + header.x) - button.w; - if (!(win->flags & NK_WINDOW_CLOSABLE)) { - button.x -= style->window.header.padding.x; - header.w -= style->window.header.padding.x; - } - header.w -= button.w + style->window.header.spacing.x; - } else { - button.x = header.x; - header.x += button.w + style->window.header.spacing.x + style->window.header.padding.x; - } - if (nk_do_button_symbol(&ws, &win->buffer, button, (layout->flags & NK_WINDOW_MINIMIZED)? - style->window.header.maximize_symbol: style->window.header.minimize_symbol, - NK_BUTTON_DEFAULT, &style->window.header.minimize_button, in, style->font) && !(win->flags & NK_WINDOW_ROM)) - layout->flags = (layout->flags & NK_WINDOW_MINIMIZED) ? - layout->flags & (nk_flags)~NK_WINDOW_MINIMIZED: - layout->flags | NK_WINDOW_MINIMIZED; - }} - - {/* window header title */ - int text_len = nk_strlen(title); - struct nk_rect label = {0,0,0,0}; - float t = font->width(font->userdata, font->height, title, text_len); - text.padding = nk_vec2(0,0); - - label.x = header.x + style->window.header.padding.x; - label.x += style->window.header.label_padding.x; - label.y = header.y + style->window.header.label_padding.y; - label.h = font->height + 2 * style->window.header.label_padding.y; - label.w = t + 2 * style->window.header.spacing.x; - nk_widget_text(out, label,(const char*)title, text_len, &text, NK_TEXT_LEFT, font);} - } - - /* draw window background */ - if (!(layout->flags & NK_WINDOW_MINIMIZED) && !(layout->flags & NK_WINDOW_DYNAMIC)) { - struct nk_rect body; - body.x = win->bounds.x; - body.w = win->bounds.w; - body.y = (win->bounds.y + layout->header_height); - body.h = (win->bounds.h - layout->header_height); - if (style->window.fixed_background.type == NK_STYLE_ITEM_IMAGE) - nk_draw_image(out, body, &style->window.fixed_background.data.image, nk_white); - else nk_fill_rect(out, body, 0, style->window.fixed_background.data.color); - } - - /* set clipping rectangle */ - {struct nk_rect clip; - layout->clip = layout->bounds; - nk_unify(&clip, &win->buffer.clip, layout->clip.x, layout->clip.y, - layout->clip.x + layout->clip.w, layout->clip.y + layout->clip.h); - nk_push_scissor(out, clip); - layout->clip = clip;} - return !(layout->flags & NK_WINDOW_HIDDEN) && !(layout->flags & NK_WINDOW_MINIMIZED); -} - -NK_INTERN void -nk_panel_end(struct nk_context *ctx) -{ - struct nk_input *in; - struct nk_window *window; - struct nk_panel *layout; - const struct nk_style *style; - struct nk_command_buffer *out; - - struct nk_vec2 scrollbar_size; - struct nk_vec2 panel_padding; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - window = ctx->current; - layout = window->layout; - style = &ctx->style; - out = &window->buffer; - in = (layout->flags & NK_WINDOW_ROM) ? 0 :&ctx->input; - if (!nk_panel_is_sub(layout->type)) - nk_push_scissor(out, nk_null_rect); - - /* cache configuration data */ - scrollbar_size = style->window.scrollbar_size; - panel_padding = nk_panel_get_padding(style, layout->type); - - /* update the current cursor Y-position to point over the last added widget */ - layout->at_y += layout->row.height; - - /* dynamic panels */ - if (layout->flags & NK_WINDOW_DYNAMIC && !(layout->flags & NK_WINDOW_MINIMIZED)) - { - /* update panel height to fit dynamic growth */ - struct nk_rect empty_space; - if (layout->at_y < (layout->bounds.y + layout->bounds.h)) - layout->bounds.h = layout->at_y - layout->bounds.y; - - /* fill top empty space */ - empty_space.x = window->bounds.x; - empty_space.y = layout->bounds.y; - empty_space.h = panel_padding.y; - empty_space.w = window->bounds.w; - nk_fill_rect(out, empty_space, 0, style->window.background); - - /* fill left empty space */ - empty_space.x = window->bounds.x; - empty_space.y = layout->bounds.y; - empty_space.w = panel_padding.x + layout->border; - empty_space.h = layout->bounds.h; - nk_fill_rect(out, empty_space, 0, style->window.background); - - /* fill right empty space */ - empty_space.x = layout->bounds.x + layout->bounds.w - layout->border; - empty_space.y = layout->bounds.y; - empty_space.w = panel_padding.x + layout->border; - empty_space.h = layout->bounds.h; - if (*layout->offset_y == 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) - empty_space.w += scrollbar_size.x; - nk_fill_rect(out, empty_space, 0, style->window.background); - - /* fill bottom empty space */ - if (*layout->offset_x != 0 && !(layout->flags & NK_WINDOW_NO_SCROLLBAR)) { - empty_space.x = window->bounds.x; - empty_space.y = layout->bounds.y + layout->bounds.h; - empty_space.w = window->bounds.w; - empty_space.h = scrollbar_size.y; - nk_fill_rect(out, empty_space, 0, style->window.background); - } - } - - /* scrollbars */ - if (!(layout->flags & NK_WINDOW_NO_SCROLLBAR) && - !(layout->flags & NK_WINDOW_MINIMIZED) && - window->scrollbar_hiding_timer < NK_SCROLLBAR_HIDING_TIMEOUT) - { - struct nk_rect scroll; - int scroll_has_scrolling; - float scroll_target; - float scroll_offset; - float scroll_step; - float scroll_inc; - { - /* vertical scrollbar */ - nk_flags state = 0; - scroll.x = layout->bounds.x + layout->bounds.w + panel_padding.x; - scroll.y = layout->bounds.y; - scroll.w = scrollbar_size.x; - scroll.h = layout->bounds.h; - - scroll_offset = (float)*layout->offset_y; - scroll_step = scroll.h * 0.10f; - scroll_inc = scroll.h * 0.01f; - scroll_target = (float)(int)(layout->at_y - scroll.y); - - /* scrolling by mouse wheel */ - if (nk_panel_is_sub(layout->type)) - { - /* sub-window scrollbar wheel scrolling */ - struct nk_window *root_window = window; - struct nk_panel *root_panel = window->layout; - while (root_panel->parent) - root_panel = root_panel->parent; - while (root_window->parent) - root_window = root_window->parent; - - /* only allow scrolling if parent window is active */ - scroll_has_scrolling = 0; - if ((root_window == ctx->active) && layout->has_scrolling) { - /* and panel is being hovered and inside clip rect*/ - if (nk_input_is_mouse_hovering_rect(in, layout->bounds) && - NK_INTERSECT(layout->bounds.x, layout->bounds.y, layout->bounds.w, layout->bounds.h, - root_panel->clip.x, root_panel->clip.y, root_panel->clip.w, root_panel->clip.h)) - { - /* deactivate all parent scrolling */ - root_panel = window->layout; - while (root_panel->parent) { - root_panel->has_scrolling = nk_false; - root_panel = root_panel->parent; - } - root_panel->has_scrolling = nk_false; - scroll_has_scrolling = nk_true; - } - } - } else if (!nk_panel_is_sub(layout->type)) { - /* window scrollbar wheel scrolling */ - scroll_has_scrolling = (window == ctx->active) && layout->has_scrolling; - if (in && in->mouse.scroll_delta > 0 && scroll_has_scrolling) - window->scrolled = nk_true; - else window->scrolled = nk_false; - } else scroll_has_scrolling = nk_false; - - /* execute scrollbar */ - scroll_offset = nk_do_scrollbarv(&state, out, scroll, scroll_has_scrolling, - scroll_offset, scroll_target, scroll_step, scroll_inc, - &ctx->style.scrollv, in, style->font); - *layout->offset_y = (nk_uint)scroll_offset; - if (in && scroll_has_scrolling) - in->mouse.scroll_delta = 0; - } - { - /* horizontal scrollbar */ - nk_flags state = 0; - scroll.x = layout->bounds.x; - scroll.y = layout->bounds.y + layout->bounds.h; - scroll.w = layout->bounds.w; - scroll.h = scrollbar_size.y; - - scroll_offset = (float)*layout->offset_x; - scroll_target = (float)(int)(layout->max_x - scroll.x); - scroll_step = layout->max_x * 0.05f; - scroll_inc = layout->max_x * 0.005f; - scroll_has_scrolling = nk_false; - scroll_offset = nk_do_scrollbarh(&state, out, scroll, scroll_has_scrolling, - scroll_offset, scroll_target, scroll_step, scroll_inc, - &ctx->style.scrollh, in, style->font); - *layout->offset_x = (nk_uint)scroll_offset; - } - } - - /* hide scroll if no user input */ - if (window->flags & NK_WINDOW_SCROLL_AUTO_HIDE) { - int has_input = ctx->input.mouse.delta.x != 0 || ctx->input.mouse.delta.y != 0 || ctx->input.mouse.scroll_delta != 0; - int is_window_hovered = nk_window_is_hovered(ctx); - int any_item_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); - if ((!has_input && is_window_hovered) || (!is_window_hovered && !any_item_active)) - window->scrollbar_hiding_timer += ctx->delta_time_seconds; - else window->scrollbar_hiding_timer = 0; - } else window->scrollbar_hiding_timer = 0; - - /* window border */ - if (layout->flags & NK_WINDOW_BORDER) - { - struct nk_color border_color = nk_panel_get_border_color(style, layout->type); - const float padding_y = (layout->flags & NK_WINDOW_MINIMIZED) ? - style->window.border + window->bounds.y + layout->header_height: - (layout->flags & NK_WINDOW_DYNAMIC)? - layout->bounds.y + layout->bounds.h + layout->footer_height: - window->bounds.y + window->bounds.h; - - /* draw border top */ - nk_stroke_line(out,window->bounds.x,window->bounds.y, - window->bounds.x + window->bounds.w, window->bounds.y, - layout->border, border_color); - - /* draw bottom border */ - nk_stroke_line(out, window->bounds.x, padding_y, - window->bounds.x + window->bounds.w, padding_y, layout->border, border_color); - - /* draw left border */ - nk_stroke_line(out, window->bounds.x + layout->border*0.5f, - window->bounds.y, window->bounds.x + layout->border*0.5f, - padding_y, layout->border, border_color); - - /* draw right border */ - nk_stroke_line(out, window->bounds.x + window->bounds.w - layout->border*0.5f, - window->bounds.y, window->bounds.x + window->bounds.w - layout->border*0.5f, - padding_y, layout->border, border_color); - } - - /* scaler */ - if ((layout->flags & NK_WINDOW_SCALABLE) && in && !(layout->flags & NK_WINDOW_MINIMIZED)) - { - /* calculate scaler bounds */ - struct nk_rect scaler; - scaler.w = scrollbar_size.x; - scaler.h = scrollbar_size.y; - scaler.y = layout->bounds.y + layout->bounds.h; - scaler.x = layout->bounds.x + layout->bounds.w + panel_padding.x; - if (layout->flags & NK_WINDOW_NO_SCROLLBAR) - scaler.x -= scaler.w; - - /* draw scaler */ - {const struct nk_style_item *item = &style->window.scaler; - if (item->type == NK_STYLE_ITEM_IMAGE) - nk_draw_image(out, scaler, &item->data.image, nk_white); - else nk_fill_triangle(out, scaler.x + scaler.w, scaler.y, scaler.x + scaler.w, - scaler.y + scaler.h, scaler.x, scaler.y + scaler.h, item->data.color); - } - - /* do window scaling */ - if (!(window->flags & NK_WINDOW_ROM)) { - struct nk_vec2 window_size = style->window.min_size; - int left_mouse_down = in->mouse.buttons[NK_BUTTON_LEFT].down; - int left_mouse_click_in_scaler = nk_input_has_mouse_click_down_in_rect(in, - NK_BUTTON_LEFT, scaler, nk_true); - - if (nk_input_is_mouse_down(in, NK_BUTTON_LEFT) && left_mouse_down && left_mouse_click_in_scaler) { - window->bounds.w = NK_MAX(window_size.x, window->bounds.w + in->mouse.delta.x); - /* dragging in y-direction is only possible if static window */ - if (!(layout->flags & NK_WINDOW_DYNAMIC)) - window->bounds.h = NK_MAX(window_size.y, window->bounds.h + in->mouse.delta.y); - ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_RESIZE_TOP_RIGHT_DOWN_LEFT]; - in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.x = scaler.x + in->mouse.delta.x + scaler.w/2.0f; - in->mouse.buttons[NK_BUTTON_LEFT].clicked_pos.y = scaler.y + in->mouse.delta.y + scaler.h/2.0f; - } - } - } - - if (!nk_panel_is_sub(layout->type)) { - /* window is hidden so clear command buffer */ - if (layout->flags & NK_WINDOW_HIDDEN) - nk_command_buffer_reset(&window->buffer); - /* window is visible and not tab */ - else nk_finish(ctx, window); - } - - /* NK_WINDOW_REMOVE_ROM flag was set so remove NK_WINDOW_ROM */ - if (layout->flags & NK_WINDOW_REMOVE_ROM) { - layout->flags &= ~(nk_flags)NK_WINDOW_ROM; - layout->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; - } - window->flags = layout->flags; - - /* property garbage collector */ - if (window->property.active && window->property.old != window->property.seq && - window->property.active == window->property.prev) { - nk_zero(&window->property, sizeof(window->property)); - } else { - window->property.old = window->property.seq; - window->property.prev = window->property.active; - window->property.seq = 0; - } - - /* edit garbage collector */ - if (window->edit.active && window->edit.old != window->edit.seq && - window->edit.active == window->edit.prev) { - nk_zero(&window->edit, sizeof(window->edit)); - } else { - window->edit.old = window->edit.seq; - window->edit.prev = window->edit.active; - window->edit.seq = 0; - } - - /* contextual garbage collector */ - if (window->popup.active_con && window->popup.con_old != window->popup.con_count) { - window->popup.con_count = 0; - window->popup.con_old = 0; - window->popup.active_con = 0; - } else { - window->popup.con_old = window->popup.con_count; - window->popup.con_count = 0; - } - window->popup.combo_count = 0; - - /* helper to make sure you have a 'nk_tree_push' * for every 'nk_tree_pop' */ - NK_ASSERT(!layout->row.tree_depth); -} - -/* ---------------------------------------------------------------- - * - * PAGE ELEMENT - * - * ---------------------------------------------------------------*/ -NK_INTERN struct nk_page_element* -nk_create_page_element(struct nk_context *ctx) -{ - struct nk_page_element *elem; - if (ctx->freelist) { - /* unlink page element from free list */ - elem = ctx->freelist; - ctx->freelist = elem->next; - } else if (ctx->use_pool) { - /* allocate page element from memory pool */ - elem = nk_pool_alloc(&ctx->pool); - NK_ASSERT(elem); - if (!elem) return 0; - } else { - /* allocate new page element from the back of the fixed size memory buffer */ - NK_STORAGE const nk_size size = sizeof(struct nk_page_element); - NK_STORAGE const nk_size align = NK_ALIGNOF(struct nk_page_element); - elem = (struct nk_page_element*)nk_buffer_alloc(&ctx->memory, NK_BUFFER_BACK, size, align); - NK_ASSERT(elem); - if (!elem) return 0; - } - nk_zero_struct(*elem); - elem->next = 0; - elem->prev = 0; - return elem; -} - -NK_INTERN void -nk_link_page_element_into_freelist(struct nk_context *ctx, - struct nk_page_element *elem) -{ - /* link table into freelist */ - if (!ctx->freelist) { - ctx->freelist = elem; - } else { - elem->next = ctx->freelist; - ctx->freelist = elem; - } -} - -NK_INTERN void -nk_free_page_element(struct nk_context *ctx, struct nk_page_element *elem) -{ - /* we have a pool so just add to free list */ - if (ctx->use_pool) { - nk_link_page_element_into_freelist(ctx, elem); - return; - } - - /* if possible remove last element from back of fixed memory buffer */ - {void *elem_end = (void*)(elem + 1); - void *buffer_end = (nk_byte*)ctx->memory.memory.ptr + ctx->memory.size; - if (elem_end == buffer_end) - ctx->memory.size -= sizeof(struct nk_page_element); - else nk_link_page_element_into_freelist(ctx, elem);} -} - -/* ---------------------------------------------------------------- - * - * PANEL - * - * ---------------------------------------------------------------*/ -NK_INTERN void* -nk_create_panel(struct nk_context *ctx) -{ - struct nk_page_element *elem; - elem = nk_create_page_element(ctx); - if (!elem) return 0; - nk_zero_struct(*elem); - return &elem->data.pan; -} - -NK_INTERN void -nk_free_panel(struct nk_context *ctx, struct nk_panel *pan) -{ - union nk_page_data *pd = NK_CONTAINER_OF(pan, union nk_page_data, pan); - struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); - nk_free_page_element(ctx, pe); -} - -/* ---------------------------------------------------------------- - * - * TABLES - * - * ---------------------------------------------------------------*/ -NK_INTERN struct nk_table* -nk_create_table(struct nk_context *ctx) -{ - struct nk_page_element *elem; - elem = nk_create_page_element(ctx); - if (!elem) return 0; - nk_zero_struct(*elem); - return &elem->data.tbl; -} - -NK_INTERN void -nk_free_table(struct nk_context *ctx, struct nk_table *tbl) -{ - union nk_page_data *pd = NK_CONTAINER_OF(tbl, union nk_page_data, tbl); - struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); - nk_free_page_element(ctx, pe); -} - -NK_INTERN void -nk_push_table(struct nk_window *win, struct nk_table *tbl) -{ - if (!win->tables) { - win->tables = tbl; - tbl->next = 0; - tbl->prev = 0; - win->table_count = 1; - win->table_size = 0; - return; - } - win->tables->prev = tbl; - tbl->next = win->tables; - tbl->prev = 0; - win->tables = tbl; - win->table_count++; - win->table_size = 0; -} - -NK_INTERN void -nk_remove_table(struct nk_window *win, struct nk_table *tbl) -{ - if (win->tables == tbl) - win->tables = tbl->next; - if (tbl->next) - tbl->next->prev = tbl->prev; - if (tbl->prev) - tbl->prev->next = tbl->next; - tbl->next = 0; - tbl->prev = 0; -} - -NK_INTERN nk_uint* -nk_add_value(struct nk_context *ctx, struct nk_window *win, - nk_hash name, nk_uint value) -{ - NK_ASSERT(ctx); - NK_ASSERT(win); - if (!win || !ctx) return 0; - if (!win->tables || win->table_size >= NK_VALUE_PAGE_CAPACITY) { - struct nk_table *tbl = nk_create_table(ctx); - NK_ASSERT(tbl); - if (!tbl) return 0; - nk_push_table(win, tbl); - } - win->tables->seq = win->seq; - win->tables->keys[win->table_size] = name; - win->tables->values[win->table_size] = value; - return &win->tables->values[win->table_size++]; -} - -NK_INTERN nk_uint* -nk_find_value(struct nk_window *win, nk_hash name) -{ - nk_ushort size = win->table_size; - struct nk_table *iter = win->tables; - while (iter) { - nk_ushort i = 0; - for (i = 0; i < size; ++i) { - if (iter->keys[i] == name) { - iter->seq = win->seq; - return &iter->values[i]; - } - } - size = NK_VALUE_PAGE_CAPACITY; - iter = iter->next; - } - return 0; -} - -/* ---------------------------------------------------------------- - * - * WINDOW - * - * ---------------------------------------------------------------*/ -NK_INTERN void* -nk_create_window(struct nk_context *ctx) -{ - struct nk_page_element *elem; - elem = nk_create_page_element(ctx); - if (!elem) return 0; - elem->data.win.seq = ctx->seq; - return &elem->data.win; -} - -NK_INTERN void -nk_free_window(struct nk_context *ctx, struct nk_window *win) -{ - /* unlink windows from list */ - struct nk_table *n, *it = win->tables; - if (win->popup.win) { - nk_free_window(ctx, win->popup.win); - win->popup.win = 0; - } - win->next = 0; - win->prev = 0; - - while (it) { - /*free window state tables */ - n = it->next; - nk_remove_table(win, it); - nk_free_table(ctx, it); - if (it == win->tables) - win->tables = n; - it = n; - } - - /* link windows into freelist */ - {union nk_page_data *pd = NK_CONTAINER_OF(win, union nk_page_data, win); - struct nk_page_element *pe = NK_CONTAINER_OF(pd, struct nk_page_element, data); - nk_free_page_element(ctx, pe);} -} - -NK_INTERN struct nk_window* -nk_find_window(struct nk_context *ctx, nk_hash hash, const char *name) -{ - struct nk_window *iter; - iter = ctx->begin; - while (iter) { - NK_ASSERT(iter != iter->next); - if (iter->name == hash) { - int max_len = nk_strlen(iter->name_string); - if (!nk_stricmpn(iter->name_string, name, max_len)) - return iter; - } - iter = iter->next; - } - return 0; -} - -enum nk_window_insert_location { - NK_INSERT_BACK, /* inserts window into the back of list (front of screen) */ - NK_INSERT_FRONT /* inserts window into the front of list (back of screen) */ -}; -NK_INTERN void -nk_insert_window(struct nk_context *ctx, struct nk_window *win, - enum nk_window_insert_location loc) -{ - const struct nk_window *iter; - NK_ASSERT(ctx); - NK_ASSERT(win); - if (!win || !ctx) return; - - iter = ctx->begin; - while (iter) { - NK_ASSERT(iter != iter->next); - NK_ASSERT(iter != win); - if (iter == win) return; - iter = iter->next; - } - - if (!ctx->begin) { - win->next = 0; - win->prev = 0; - ctx->begin = win; - ctx->end = win; - ctx->count = 1; - return; - } - if (loc == NK_INSERT_BACK) { - struct nk_window *end; - end = ctx->end; - end->flags |= NK_WINDOW_ROM; - end->next = win; - win->prev = ctx->end; - win->next = 0; - ctx->end = win; - ctx->active = ctx->end; - ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; - } else { - ctx->end->flags |= NK_WINDOW_ROM; - ctx->begin->prev = win; - win->next = ctx->begin; - win->prev = 0; - ctx->begin = win; - ctx->begin->flags &= ~(nk_flags)NK_WINDOW_ROM; - } - ctx->count++; -} - -NK_INTERN void -nk_remove_window(struct nk_context *ctx, struct nk_window *win) -{ - if (win == ctx->begin || win == ctx->end) { - if (win == ctx->begin) { - ctx->begin = win->next; - if (win->next) - win->next->prev = 0; - } - if (win == ctx->end) { - ctx->end = win->prev; - if (win->prev) - win->prev->next = 0; - } - } else { - if (win->next) - win->next->prev = win->prev; - if (win->prev) - win->prev->next = win->next; - } - if (win == ctx->active || !ctx->active) { - ctx->active = ctx->end; - if (ctx->end) - ctx->end->flags &= ~(nk_flags)NK_WINDOW_ROM; - } - win->next = 0; - win->prev = 0; - ctx->count--; -} - -NK_API int -nk_begin(struct nk_context *ctx, const char *title, - struct nk_rect bounds, nk_flags flags) -{ - return nk_begin_titled(ctx, title, title, bounds, flags); -} - -NK_API int -nk_begin_titled(struct nk_context *ctx, const char *name, const char *title, - struct nk_rect bounds, nk_flags flags) -{ - struct nk_window *win; - struct nk_style *style; - nk_hash title_hash; - int title_len; - int ret = 0; - - NK_ASSERT(ctx); - NK_ASSERT(name); - NK_ASSERT(title); - NK_ASSERT(ctx->style.font && ctx->style.font->width && "if this triggers you forgot to add a font"); - NK_ASSERT(!ctx->current && "if this triggers you missed a `nk_end` call"); - if (!ctx || ctx->current || !title || !name) - return 0; - - /* find or create window */ - style = &ctx->style; - title_len = (int)nk_strlen(name); - title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); - win = nk_find_window(ctx, title_hash, name); - if (!win) { - /* create new window */ - nk_size name_length = (nk_size)nk_strlen(name); - win = (struct nk_window*)nk_create_window(ctx); - NK_ASSERT(win); - if (!win) return 0; - - if (flags & NK_WINDOW_BACKGROUND) - nk_insert_window(ctx, win, NK_INSERT_FRONT); - else nk_insert_window(ctx, win, NK_INSERT_BACK); - nk_command_buffer_init(&win->buffer, &ctx->memory, NK_CLIPPING_ON); - - win->flags = flags; - win->bounds = bounds; - win->name = title_hash; - name_length = NK_MIN(name_length, NK_WINDOW_MAX_NAME-1); - NK_MEMCPY(win->name_string, name, name_length); - win->name_string[name_length] = 0; - win->popup.win = 0; - if (!ctx->active) - ctx->active = win; - } else { - /* update window */ - win->flags &= ~(nk_flags)(NK_WINDOW_PRIVATE-1); - win->flags |= flags; - if (!(win->flags & (NK_WINDOW_MOVABLE | NK_WINDOW_SCALABLE))) - win->bounds = bounds; - /* If this assert triggers you either: - * - * I.) Have more than one window with the same name or - * II.) You forgot to actually draw the window. - * More specific you did not call `nk_clear` (nk_clear will be - * automatically called for you if you are using one of the - * provided demo backends). */ - NK_ASSERT(win->seq != ctx->seq); - win->seq = ctx->seq; - if (!ctx->active) - ctx->active = win; - } - if (win->flags & NK_WINDOW_HIDDEN) { - ctx->current = win; - return 0; - } - - /* window overlapping */ - if (!(win->flags & NK_WINDOW_HIDDEN)) - { - int inpanel, ishovered; - const struct nk_window *iter = win; - float h = ctx->style.font->height + 2.0f * style->window.header.padding.y + - (2.0f * style->window.header.label_padding.y); - struct nk_rect win_bounds = (!(win->flags & NK_WINDOW_MINIMIZED))? - win->bounds: nk_rect(win->bounds.x, win->bounds.y, win->bounds.w, h); - - /* activate window if hovered and no other window is overlapping this window */ - nk_start(ctx, win); - inpanel = nk_input_has_mouse_click_down_in_rect(&ctx->input, NK_BUTTON_LEFT, win_bounds, nk_true); - inpanel = inpanel && ctx->input.mouse.buttons[NK_BUTTON_LEFT].clicked; - ishovered = nk_input_is_mouse_hovering_rect(&ctx->input, win_bounds); - if ((win != ctx->active) && ishovered && !ctx->input.mouse.buttons[NK_BUTTON_LEFT].down) { - iter = win->next; - while (iter) { - struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? - iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); - if (NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, - iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && - (!(iter->flags & NK_WINDOW_HIDDEN) || !(iter->flags & NK_WINDOW_BACKGROUND))) - break; - - if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && - NK_INTERSECT(win->bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, - iter->popup.win->bounds.x, iter->popup.win->bounds.y, - iter->popup.win->bounds.w, iter->popup.win->bounds.h)) - break; - iter = iter->next; - } - } - - /* activate window if clicked */ - if (iter && inpanel && (win != ctx->end) && !(iter->flags & NK_WINDOW_BACKGROUND)) { - iter = win->next; - while (iter) { - /* try to find a panel with higher priority in the same position */ - struct nk_rect iter_bounds = (!(iter->flags & NK_WINDOW_MINIMIZED))? - iter->bounds: nk_rect(iter->bounds.x, iter->bounds.y, iter->bounds.w, h); - if (NK_INBOX(ctx->input.mouse.pos.x, ctx->input.mouse.pos.y, - iter_bounds.x, iter_bounds.y, iter_bounds.w, iter_bounds.h) && - !(iter->flags & NK_WINDOW_HIDDEN)) - break; - if (iter->popup.win && iter->popup.active && !(iter->flags & NK_WINDOW_HIDDEN) && - NK_INTERSECT(win_bounds.x, win_bounds.y, win_bounds.w, win_bounds.h, - iter->popup.win->bounds.x, iter->popup.win->bounds.y, - iter->popup.win->bounds.w, iter->popup.win->bounds.h)) - break; - iter = iter->next; - } - } - - if (!iter && ctx->end != win) { - if (!(win->flags & NK_WINDOW_BACKGROUND)) { - /* current window is active in that position so transfer to top - * at the highest priority in stack */ - nk_remove_window(ctx, win); - nk_insert_window(ctx, win, NK_INSERT_BACK); - } - win->flags &= ~(nk_flags)NK_WINDOW_ROM; - ctx->active = win; - } - if (ctx->end != win && !(win->flags & NK_WINDOW_BACKGROUND)) - win->flags |= NK_WINDOW_ROM; - } - - win->layout = (struct nk_panel*)nk_create_panel(ctx); - ctx->current = win; - ret = nk_panel_begin(ctx, title, NK_PANEL_WINDOW); - win->layout->offset_x = &win->scrollbar.x; - win->layout->offset_y = &win->scrollbar.y; - return ret; -} - -NK_API void -nk_end(struct nk_context *ctx) -{ - struct nk_panel *layout; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current && "if this triggers you forgot to call `nk_begin`"); - NK_ASSERT(ctx->current->layout); - - layout = ctx->current->layout; - if (!ctx || !ctx->current) return; - if (layout->type == NK_PANEL_WINDOW && (ctx->current->flags & NK_WINDOW_HIDDEN)) { - ctx->current = 0; - return; - } - nk_panel_end(ctx); - nk_free_panel(ctx, ctx->current->layout); - ctx->current = 0; -} - -NK_API struct nk_rect -nk_window_get_bounds(const struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return nk_rect(0,0,0,0); - return ctx->current->bounds; -} - -NK_API struct nk_vec2 -nk_window_get_position(const struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return nk_vec2(0,0); - return nk_vec2(ctx->current->bounds.x, ctx->current->bounds.y); -} - -NK_API struct nk_vec2 -nk_window_get_size(const struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return nk_vec2(0,0); - return nk_vec2(ctx->current->bounds.w, ctx->current->bounds.h); -} - -NK_API float -nk_window_get_width(const struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return 0; - return ctx->current->bounds.w; -} - -NK_API float -nk_window_get_height(const struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return 0; - return ctx->current->bounds.h; -} - -NK_API struct nk_rect -nk_window_get_content_region(struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return nk_rect(0,0,0,0); - return ctx->current->layout->clip; -} - -NK_API struct nk_vec2 -nk_window_get_content_region_min(struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current) return nk_vec2(0,0); - return nk_vec2(ctx->current->layout->clip.x, ctx->current->layout->clip.y); -} - -NK_API struct nk_vec2 -nk_window_get_content_region_max(struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current) return nk_vec2(0,0); - return nk_vec2(ctx->current->layout->clip.x + ctx->current->layout->clip.w, - ctx->current->layout->clip.y + ctx->current->layout->clip.h); -} - -NK_API struct nk_vec2 -nk_window_get_content_region_size(struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current) return nk_vec2(0,0); - return nk_vec2(ctx->current->layout->clip.w, ctx->current->layout->clip.h); -} - -NK_API struct nk_command_buffer* -nk_window_get_canvas(struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current) return 0; - return &ctx->current->buffer; -} - -NK_API struct nk_panel* -nk_window_get_panel(struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return 0; - return ctx->current->layout; -} - -NK_API int -nk_window_has_focus(const struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current) return 0; - return ctx->current == ctx->active; -} - -NK_API int -nk_window_is_hovered(struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return 0; - return nk_input_is_mouse_hovering_rect(&ctx->input, ctx->current->bounds); -} - -NK_API int -nk_window_is_any_hovered(struct nk_context *ctx) -{ - struct nk_window *iter; - NK_ASSERT(ctx); - if (!ctx) return 0; - iter = ctx->begin; - while (iter) { - /* check if window is being hovered */ - if (iter->flags & NK_WINDOW_MINIMIZED) { - struct nk_rect header = iter->bounds; - header.h = ctx->style.font->height + 2 * ctx->style.window.header.padding.y; - if (nk_input_is_mouse_hovering_rect(&ctx->input, header)) - return 1; - } else if (nk_input_is_mouse_hovering_rect(&ctx->input, iter->bounds)) { - return 1; - } - /* check if window popup is being hovered */ - if (iter->popup.active && iter->popup.win && nk_input_is_mouse_hovering_rect(&ctx->input, iter->popup.win->bounds)) - return 1; - iter = iter->next; - } - return 0; -} - -NK_API int -nk_item_is_any_active(struct nk_context *ctx) -{ - int any_hovered = nk_window_is_any_hovered(ctx); - int any_active = (ctx->last_widget_state & NK_WIDGET_STATE_MODIFIED); - return any_hovered || any_active; -} - -NK_API int -nk_window_is_collapsed(struct nk_context *ctx, const char *name) -{ - int title_len; - nk_hash title_hash; - struct nk_window *win; - NK_ASSERT(ctx); - if (!ctx) return 0; - - title_len = (int)nk_strlen(name); - title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); - win = nk_find_window(ctx, title_hash, name); - if (!win) return 0; - return win->flags & NK_WINDOW_MINIMIZED; -} - -NK_API int -nk_window_is_closed(struct nk_context *ctx, const char *name) -{ - int title_len; - nk_hash title_hash; - struct nk_window *win; - NK_ASSERT(ctx); - if (!ctx) return 1; - - title_len = (int)nk_strlen(name); - title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); - win = nk_find_window(ctx, title_hash, name); - if (!win) return 1; - return (win->flags & NK_WINDOW_CLOSED); -} - -NK_API int -nk_window_is_hidden(struct nk_context *ctx, const char *name) -{ - int title_len; - nk_hash title_hash; - struct nk_window *win; - NK_ASSERT(ctx); - if (!ctx) return 1; - - title_len = (int)nk_strlen(name); - title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); - win = nk_find_window(ctx, title_hash, name); - if (!win) return 1; - return (win->flags & NK_WINDOW_HIDDEN); -} - -NK_API int -nk_window_is_active(struct nk_context *ctx, const char *name) -{ - int title_len; - nk_hash title_hash; - struct nk_window *win; - NK_ASSERT(ctx); - if (!ctx) return 0; - - title_len = (int)nk_strlen(name); - title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); - win = nk_find_window(ctx, title_hash, name); - if (!win) return 0; - return win == ctx->active; -} - -NK_API struct nk_window* -nk_window_find(struct nk_context *ctx, const char *name) -{ - int title_len; - nk_hash title_hash; - title_len = (int)nk_strlen(name); - title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); - return nk_find_window(ctx, title_hash, name); -} - -NK_API void -nk_window_close(struct nk_context *ctx, const char *name) -{ - struct nk_window *win; - NK_ASSERT(ctx); - if (!ctx) return; - win = nk_window_find(ctx, name); - if (!win) return; - NK_ASSERT(ctx->current != win && "You cannot close a currently active window"); - if (ctx->current == win) return; - win->flags |= NK_WINDOW_HIDDEN; - win->flags |= NK_WINDOW_CLOSED; -} - -NK_API void -nk_window_set_bounds(struct nk_context *ctx, struct nk_rect bounds) -{ - NK_ASSERT(ctx); NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return; - ctx->current->bounds = bounds; -} - -NK_API void -nk_window_set_position(struct nk_context *ctx, struct nk_vec2 pos) -{ - NK_ASSERT(ctx); NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return; - ctx->current->bounds.x = pos.x; - ctx->current->bounds.y = pos.y; -} - -NK_API void -nk_window_set_size(struct nk_context *ctx, struct nk_vec2 size) -{ - NK_ASSERT(ctx); NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return; - ctx->current->bounds.w = size.x; - ctx->current->bounds.h = size.y; -} - -NK_API void -nk_window_collapse(struct nk_context *ctx, const char *name, - enum nk_collapse_states c) -{ - int title_len; - nk_hash title_hash; - struct nk_window *win; - NK_ASSERT(ctx); - if (!ctx) return; - - title_len = (int)nk_strlen(name); - title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); - win = nk_find_window(ctx, title_hash, name); - if (!win) return; - if (c == NK_MINIMIZED) - win->flags |= NK_WINDOW_MINIMIZED; - else win->flags &= ~(nk_flags)NK_WINDOW_MINIMIZED; -} - -NK_API void -nk_window_collapse_if(struct nk_context *ctx, const char *name, - enum nk_collapse_states c, int cond) -{ - NK_ASSERT(ctx); - if (!ctx || !cond) return; - nk_window_collapse(ctx, name, c); -} - -NK_API void -nk_window_show(struct nk_context *ctx, const char *name, enum nk_show_states s) -{ - int title_len; - nk_hash title_hash; - struct nk_window *win; - NK_ASSERT(ctx); - if (!ctx) return; - - title_len = (int)nk_strlen(name); - title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); - win = nk_find_window(ctx, title_hash, name); - if (!win) return; - if (s == NK_HIDDEN) - win->flags |= NK_WINDOW_HIDDEN; - else win->flags &= ~(nk_flags)NK_WINDOW_HIDDEN; -} - -NK_API void -nk_window_show_if(struct nk_context *ctx, const char *name, - enum nk_show_states s, int cond) -{ - NK_ASSERT(ctx); - if (!ctx || !cond) return; - nk_window_show(ctx, name, s); -} - -NK_API void -nk_window_set_focus(struct nk_context *ctx, const char *name) -{ - int title_len; - nk_hash title_hash; - struct nk_window *win; - NK_ASSERT(ctx); - if (!ctx) return; - - title_len = (int)nk_strlen(name); - title_hash = nk_murmur_hash(name, (int)title_len, NK_WINDOW_TITLE); - win = nk_find_window(ctx, title_hash, name); - if (win && ctx->end != win) { - nk_remove_window(ctx, win); - nk_insert_window(ctx, win, NK_INSERT_BACK); - } - ctx->active = win; -} - -/*---------------------------------------------------------------- - * - * MENUBAR - * - * --------------------------------------------------------------*/ -NK_API void -nk_menubar_begin(struct nk_context *ctx) -{ - struct nk_panel *layout; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - layout = ctx->current->layout; - NK_ASSERT(layout->at_y == layout->bounds.y); - /* if this assert triggers you allocated space between nk_begin and nk_menubar_begin. - If you want a menubar the first nuklear function after `nk_begin` has to be a - `nk_menubar_begin` call. Inside the menubar you then have to allocate space for - widgets (also supports multiple rows). - Example: - if (nk_begin(...)) { - nk_menubar_begin(...); - nk_layout_xxxx(...); - nk_button(...); - nk_layout_xxxx(...); - nk_button(...); - nk_menubar_end(...); - } - nk_end(...); - */ - if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) - return; - - layout->menu.x = layout->at_x; - layout->menu.y = layout->at_y + layout->row.height; - layout->menu.w = layout->bounds.w; - layout->menu.offset.x = *layout->offset_x; - layout->menu.offset.y = *layout->offset_y; - *layout->offset_y = 0; -} - -NK_API void -nk_menubar_end(struct nk_context *ctx) -{ - struct nk_window *win; - struct nk_panel *layout; - struct nk_command_buffer *out; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - out = &win->buffer; - layout = win->layout; - if (layout->flags & NK_WINDOW_HIDDEN || layout->flags & NK_WINDOW_MINIMIZED) - return; - - layout->menu.h = layout->at_y - layout->menu.y; - layout->bounds.y += layout->menu.h + ctx->style.window.spacing.y + layout->row.height; - layout->bounds.h -= layout->menu.h + ctx->style.window.spacing.y + layout->row.height; - - *layout->offset_x = layout->menu.offset.x; - *layout->offset_y = layout->menu.offset.y; - layout->at_y = layout->bounds.y - layout->row.height; - - layout->clip.y = layout->bounds.y; - layout->clip.h = layout->bounds.h; - nk_push_scissor(out, layout->clip); -} -/* ------------------------------------------------------------- - * - * LAYOUT - * - * --------------------------------------------------------------*/ -#define NK_LAYOUT_DYNAMIC_FIXED 0 -#define NK_LAYOUT_DYNAMIC_ROW 1 -#define NK_LAYOUT_DYNAMIC_FREE 2 -#define NK_LAYOUT_DYNAMIC 3 -#define NK_LAYOUT_STATIC_FIXED 4 -#define NK_LAYOUT_STATIC_ROW 5 -#define NK_LAYOUT_STATIC_FREE 6 -#define NK_LAYOUT_STATIC 7 - -NK_INTERN void -nk_panel_layout(const struct nk_context *ctx, struct nk_window *win, - float height, int cols) -{ - struct nk_panel *layout; - const struct nk_style *style; - struct nk_command_buffer *out; - - struct nk_vec2 item_spacing; - struct nk_color color; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - /* prefetch some configuration data */ - layout = win->layout; - style = &ctx->style; - out = &win->buffer; - color = style->window.background; - item_spacing = style->window.spacing; - - /* if one of these triggers you forgot to add an `if` condition around either - a window, group, popup, combobox or contextual menu `begin` and `end` block. - Example: - if (nk_begin(...) {...} nk_end(...); or - if (nk_group_begin(...) { nk_group_end(...);} */ - NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); - NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); - NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); - - /* update the current row and set the current row layout */ - layout->row.index = 0; - layout->at_y += layout->row.height; - layout->row.columns = cols; - layout->row.height = height + item_spacing.y; - layout->row.item_offset = 0; - if (layout->flags & NK_WINDOW_DYNAMIC) { - /* draw background for dynamic panels */ - struct nk_rect background; - background.x = win->bounds.x; - background.w = win->bounds.w; - background.y = layout->at_y - 1.0f; - background.h = layout->row.height + 1.0f; - nk_fill_rect(out, background, 0, color); - } -} - -NK_INTERN void -nk_row_layout(struct nk_context *ctx, enum nk_layout_format fmt, - float height, int cols, int width) -{ - /* update the current row and set the current row layout */ - struct nk_window *win; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - nk_panel_layout(ctx, win, height, cols); - if (fmt == NK_DYNAMIC) - win->layout->row.type = NK_LAYOUT_DYNAMIC_FIXED; - else win->layout->row.type = NK_LAYOUT_STATIC_FIXED; - - win->layout->row.ratio = 0; - win->layout->row.filled = 0; - win->layout->row.item_offset = 0; - win->layout->row.item_width = (float)width; -} - -NK_API float -nk_layout_ratio_from_pixel(struct nk_context *ctx, float pixel_width) -{ - struct nk_window *win; - NK_ASSERT(ctx); - NK_ASSERT(pixel_width); - if (!ctx || !ctx->current || !ctx->current->layout) return 0; - win = ctx->current; - return NK_CLAMP(0.0f, pixel_width/win->bounds.x, 1.0f); -} - -NK_API void -nk_layout_row_dynamic(struct nk_context *ctx, float height, int cols) -{ - nk_row_layout(ctx, NK_DYNAMIC, height, cols, 0); -} - -NK_API void -nk_layout_row_static(struct nk_context *ctx, float height, int item_width, int cols) -{ - nk_row_layout(ctx, NK_STATIC, height, cols, item_width); -} - -NK_API void -nk_layout_row_begin(struct nk_context *ctx, enum nk_layout_format fmt, - float row_height, int cols) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - layout = win->layout; - nk_panel_layout(ctx, win, row_height, cols); - if (fmt == NK_DYNAMIC) - layout->row.type = NK_LAYOUT_DYNAMIC_ROW; - else layout->row.type = NK_LAYOUT_STATIC_ROW; - - layout->row.ratio = 0; - layout->row.filled = 0; - layout->row.item_width = 0; - layout->row.item_offset = 0; - layout->row.columns = cols; -} - -NK_API void -nk_layout_row_push(struct nk_context *ctx, float ratio_or_width) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - layout = win->layout; - if (layout->row.type == NK_LAYOUT_DYNAMIC_ROW) { - float ratio = ratio_or_width; - if ((ratio + layout->row.filled) > 1.0f) return; - if (ratio > 0.0f) - layout->row.item_width = NK_SATURATE(ratio); - else layout->row.item_width = 1.0f - layout->row.filled; - } else layout->row.item_width = ratio_or_width; -} - -NK_API void -nk_layout_row_end(struct nk_context *ctx) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - layout = win->layout; - layout->row.item_width = 0; - layout->row.item_offset = 0; -} - -NK_API void -nk_layout_row(struct nk_context *ctx, enum nk_layout_format fmt, - float height, int cols, const float *ratio) -{ - int i; - int n_undef = 0; - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - layout = win->layout; - nk_panel_layout(ctx, win, height, cols); - if (fmt == NK_DYNAMIC) { - /* calculate width of undefined widget ratios */ - float r = 0; - layout->row.ratio = ratio; - for (i = 0; i < cols; ++i) { - if (ratio[i] < 0.0f) - n_undef++; - else r += ratio[i]; - } - r = NK_SATURATE(1.0f - r); - layout->row.type = NK_LAYOUT_DYNAMIC; - layout->row.item_width = (r > 0 && n_undef > 0) ? (r / (float)n_undef):0; - } else { - layout->row.ratio = ratio; - layout->row.type = NK_LAYOUT_STATIC; - layout->row.item_width = 0; - layout->row.item_offset = 0; - } - layout->row.item_offset = 0; - layout->row.filled = 0; -} - -NK_API void -nk_layout_space_begin(struct nk_context *ctx, enum nk_layout_format fmt, - float height, int widget_count) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - layout = win->layout; - nk_panel_layout(ctx, win, height, widget_count); - if (fmt == NK_STATIC) - layout->row.type = NK_LAYOUT_STATIC_FREE; - else layout->row.type = NK_LAYOUT_DYNAMIC_FREE; - - layout->row.ratio = 0; - layout->row.filled = 0; - layout->row.item_width = 0; - layout->row.item_offset = 0; -} - -NK_API void -nk_layout_space_end(struct nk_context *ctx) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - layout = win->layout; - layout->row.item_width = 0; - layout->row.item_height = 0; - layout->row.item_offset = 0; - nk_zero(&layout->row.item, sizeof(layout->row.item)); -} - -NK_API void -nk_layout_space_push(struct nk_context *ctx, struct nk_rect rect) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - layout = win->layout; - layout->row.item = rect; -} - -NK_API struct nk_rect -nk_layout_space_bounds(struct nk_context *ctx) -{ - struct nk_rect ret; - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - win = ctx->current; - layout = win->layout; - - ret.x = layout->clip.x; - ret.y = layout->clip.y; - ret.w = layout->clip.w; - ret.h = layout->row.height; - return ret; -} - -NK_API struct nk_vec2 -nk_layout_space_to_screen(struct nk_context *ctx, struct nk_vec2 ret) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - win = ctx->current; - layout = win->layout; - - ret.x += layout->at_x - *layout->offset_x; - ret.y += layout->at_y - *layout->offset_y; - return ret; -} - -NK_API struct nk_vec2 -nk_layout_space_to_local(struct nk_context *ctx, struct nk_vec2 ret) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - win = ctx->current; - layout = win->layout; - - ret.x += -layout->at_x + *layout->offset_x; - ret.y += -layout->at_y + *layout->offset_y; - return ret; -} - -NK_API struct nk_rect -nk_layout_space_rect_to_screen(struct nk_context *ctx, struct nk_rect ret) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - win = ctx->current; - layout = win->layout; - - ret.x += layout->at_x - *layout->offset_x; - ret.y += layout->at_y - *layout->offset_y; - return ret; -} - -NK_API struct nk_rect -nk_layout_space_rect_to_local(struct nk_context *ctx, struct nk_rect ret) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - win = ctx->current; - layout = win->layout; - - ret.x += -layout->at_x + *layout->offset_x; - ret.y += -layout->at_y + *layout->offset_y; - return ret; -} - -NK_INTERN void -nk_panel_alloc_row(const struct nk_context *ctx, struct nk_window *win) -{ - struct nk_panel *layout = win->layout; - struct nk_vec2 spacing = ctx->style.window.spacing; - const float row_height = layout->row.height - spacing.y; - nk_panel_layout(ctx, win, row_height, layout->row.columns); -} - -NK_INTERN void -nk_layout_widget_space(struct nk_rect *bounds, const struct nk_context *ctx, - struct nk_window *win, int modify) -{ - struct nk_panel *layout; - const struct nk_style *style; - - float item_offset = 0; - float item_width = 0; - float item_spacing = 0; - - float panel_padding; - float panel_spacing; - float panel_space; - - struct nk_vec2 spacing; - struct nk_vec2 padding; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - style = &ctx->style; - layout = win->layout; - NK_ASSERT(bounds); - - /* cache some configuration data */ - spacing = ctx->style.window.spacing; - padding = nk_panel_get_padding(style, layout->type); - - /* calculate the usable panel space */ - panel_padding = 2 * padding.x; - panel_spacing = (float)(layout->row.columns - 1) * spacing.x; - panel_space = layout->bounds.w - panel_padding - panel_spacing; - - /* calculate the width of one item inside the current layout space */ - switch (layout->row.type) { - case NK_LAYOUT_DYNAMIC_FIXED: { - /* scaling fixed size widgets item width */ - item_width = panel_space / (float)layout->row.columns; - item_offset = (float)layout->row.index * item_width; - item_spacing = (float)layout->row.index * spacing.x; - } break; - case NK_LAYOUT_DYNAMIC_ROW: { - /* scaling single ratio widget width */ - item_width = layout->row.item_width * panel_space; - item_offset = layout->row.item_offset; - item_spacing = 0; - - if (modify) { - layout->row.item_offset += item_width + spacing.x; - layout->row.filled += layout->row.item_width; - layout->row.index = 0; - } - } break; - case NK_LAYOUT_DYNAMIC_FREE: { - /* panel width depended free widget placing */ - bounds->x = layout->at_x + (layout->bounds.w * layout->row.item.x); - bounds->x -= *layout->offset_x; - bounds->y = layout->at_y + (layout->row.height * layout->row.item.y); - bounds->y -= *layout->offset_y; - bounds->w = layout->bounds.w * layout->row.item.w; - bounds->h = layout->row.height * layout->row.item.h; - return; - }; - case NK_LAYOUT_DYNAMIC: { - /* scaling arrays of panel width ratios for every widget */ - float ratio; - NK_ASSERT(layout->row.ratio); - ratio = (layout->row.ratio[layout->row.index] < 0) ? - layout->row.item_width : layout->row.ratio[layout->row.index]; - - item_spacing = (float)layout->row.index * spacing.x; - item_width = (ratio * panel_space); - item_offset = layout->row.item_offset; - - if (modify) { - layout->row.item_offset += item_width; - layout->row.filled += ratio; - } - } break; - case NK_LAYOUT_STATIC_FIXED: { - /* non-scaling fixed widgets item width */ - item_width = layout->row.item_width; - item_offset = (float)layout->row.index * item_width; - item_spacing = (float)layout->row.index * spacing.x; - } break; - case NK_LAYOUT_STATIC_ROW: { - /* scaling single ratio widget width */ - item_width = layout->row.item_width; - item_offset = layout->row.item_offset; - item_spacing = (float)layout->row.index * spacing.x; - if (modify) layout->row.item_offset += item_width; - } break; - case NK_LAYOUT_STATIC_FREE: { - /* free widget placing */ - bounds->x = layout->at_x + layout->row.item.x; - bounds->w = layout->row.item.w; - if (((bounds->x + bounds->w) > layout->max_x) && modify) - layout->max_x = (bounds->x + bounds->w); - bounds->x -= *layout->offset_x; - bounds->y = layout->at_y + layout->row.item.y; - bounds->y -= *layout->offset_y; - bounds->h = layout->row.item.h; - return; - }; - case NK_LAYOUT_STATIC: { - /* non-scaling array of panel pixel width for every widget */ - item_spacing = (float)layout->row.index * spacing.x; - item_width = layout->row.ratio[layout->row.index]; - item_offset = layout->row.item_offset; - if (modify) layout->row.item_offset += item_width; - } break; - default: NK_ASSERT(0); break; - }; - - /* set the bounds of the newly allocated widget */ - bounds->w = item_width; - bounds->h = layout->row.height - spacing.y; - bounds->y = layout->at_y - *layout->offset_y; - bounds->x = layout->at_x + item_offset + item_spacing + padding.x; - if (((bounds->x + bounds->w) > layout->max_x) && modify) - layout->max_x = bounds->x + bounds->w; - bounds->x -= *layout->offset_x; -} - -NK_INTERN void -nk_panel_alloc_space(struct nk_rect *bounds, const struct nk_context *ctx) -{ - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - /* check if the end of the row has been hit and begin new row if so */ - win = ctx->current; - layout = win->layout; - if (layout->row.index >= layout->row.columns) - nk_panel_alloc_row(ctx, win); - - /* calculate widget position and size */ - nk_layout_widget_space(bounds, ctx, win, nk_true); - layout->row.index++; -} - -NK_INTERN void -nk_layout_peek(struct nk_rect *bounds, struct nk_context *ctx) -{ - float y; - int index; - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - layout = win->layout; - y = layout->at_y; - index = layout->row.index; - if (layout->row.index >= layout->row.columns) { - layout->at_y += layout->row.height; - layout->row.index = 0; - } - nk_layout_widget_space(bounds, ctx, win, nk_false); - layout->at_y = y; - layout->row.index = index; -} - -NK_INTERN int -nk_tree_state_base(struct nk_context *ctx, enum nk_tree_type type, - struct nk_image *img, const char *title, enum nk_collapse_states *state) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_style *style; - struct nk_command_buffer *out; - const struct nk_input *in; - const struct nk_style_button *button; - enum nk_symbol_type symbol; - - struct nk_vec2 item_spacing; - struct nk_rect header = {0,0,0,0}; - struct nk_rect sym = {0,0,0,0}; - struct nk_text text; - - nk_flags ws = 0; - enum nk_widget_layout_states widget_state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - /* cache some data */ - win = ctx->current; - layout = win->layout; - out = &win->buffer; - style = &ctx->style; - item_spacing = style->window.spacing; - - /* calculate header bounds and draw background */ - nk_layout_row_dynamic(ctx, style->font->height + 2 * style->tab.padding.y, 1); - widget_state = nk_widget(&header, ctx); - if (type == NK_TREE_TAB) { - const struct nk_style_item *background = &style->tab.background; - if (background->type == NK_STYLE_ITEM_IMAGE) { - nk_draw_image(out, header, &background->data.image, nk_white); - text.background = nk_rgba(0,0,0,0); - } else { - text.background = background->data.color; - nk_fill_rect(out, header, 0, style->tab.border_color); - nk_fill_rect(out, nk_shrink_rect(header, style->tab.border), - style->tab.rounding, background->data.color); - } - } else text.background = style->window.background; - - /* update node state */ - in = (!(layout->flags & NK_WINDOW_ROM)) ? &ctx->input: 0; - in = (in && widget_state == NK_WIDGET_VALID) ? &ctx->input : 0; - if (nk_button_behavior(&ws, header, in, NK_BUTTON_DEFAULT)) - *state = (*state == NK_MAXIMIZED) ? NK_MINIMIZED : NK_MAXIMIZED; - - /* select correct button style */ - if (*state == NK_MAXIMIZED) { - symbol = style->tab.sym_maximize; - if (type == NK_TREE_TAB) - button = &style->tab.tab_maximize_button; - else button = &style->tab.node_maximize_button; - } else { - symbol = style->tab.sym_minimize; - if (type == NK_TREE_TAB) - button = &style->tab.tab_minimize_button; - else button = &style->tab.node_minimize_button; - } - - {/* draw triangle button */ - sym.w = sym.h = style->font->height; - sym.y = header.y + style->tab.padding.y; - sym.x = header.x + style->tab.padding.x; - nk_do_button_symbol(&ws, &win->buffer, sym, symbol, NK_BUTTON_DEFAULT, - button, 0, style->font); - - if (img) { - /* draw optional image icon */ - sym.x = sym.x + sym.w + 4 * item_spacing.x; - nk_draw_image(&win->buffer, sym, img, nk_white); - sym.w = style->font->height + style->tab.spacing.x;} - } - - {/* draw label */ - struct nk_rect label; - header.w = NK_MAX(header.w, sym.w + item_spacing.x); - label.x = sym.x + sym.w + item_spacing.x; - label.y = sym.y; - label.w = header.w - (sym.w + item_spacing.y + style->tab.indent); - label.h = style->font->height; - text.text = style->tab.text; - text.padding = nk_vec2(0,0); - nk_widget_text(out, label, title, nk_strlen(title), &text, - NK_TEXT_LEFT, style->font);} - - /* increase x-axis cursor widget position pointer */ - if (*state == NK_MAXIMIZED) { - layout->at_x = header.x + *layout->offset_x + style->tab.indent; - layout->bounds.w = NK_MAX(layout->bounds.w, style->tab.indent); - layout->bounds.w -= (style->tab.indent + style->window.padding.x); - layout->row.tree_depth++; - return nk_true; - } else return nk_false; -} - -NK_INTERN int -nk_tree_base(struct nk_context *ctx, enum nk_tree_type type, - struct nk_image *img, const char *title, enum nk_collapse_states initial_state, - const char *hash, int len, int line) -{ - struct nk_window *win = ctx->current; - int title_len = 0; - nk_hash tree_hash = 0; - nk_uint *state = 0; - - /* retrieve tree state from internal widget state tables */ - if (!hash) { - title_len = (int)nk_strlen(title); - tree_hash = nk_murmur_hash(title, (int)title_len, (nk_hash)line); - } else tree_hash = nk_murmur_hash(hash, len, (nk_hash)line); - state = nk_find_value(win, tree_hash); - if (!state) { - state = nk_add_value(ctx, win, tree_hash, 0); - *state = initial_state; - } - return nk_tree_state_base(ctx, type, img, title, (enum nk_collapse_states*)state); -} - -NK_API int -nk_tree_state_push(struct nk_context *ctx, enum nk_tree_type type, - const char *title, enum nk_collapse_states *state) -{return nk_tree_state_base(ctx, type, 0, title, state);} - -NK_API int -nk_tree_state_image_push(struct nk_context *ctx, enum nk_tree_type type, - struct nk_image img, const char *title, enum nk_collapse_states *state) -{return nk_tree_state_base(ctx, type, &img, title, state);} - -NK_API void -nk_tree_state_pop(struct nk_context *ctx) -{ - struct nk_window *win = 0; - struct nk_panel *layout = 0; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - layout = win->layout; - layout->at_x -= ctx->style.tab.indent + ctx->style.window.padding.x; - layout->bounds.w += ctx->style.tab.indent + ctx->style.window.padding.x; - NK_ASSERT(layout->row.tree_depth); - layout->row.tree_depth--; -} - -NK_API int -nk_tree_push_hashed(struct nk_context *ctx, enum nk_tree_type type, - const char *title, enum nk_collapse_states initial_state, - const char *hash, int len, int line) -{return nk_tree_base(ctx, type, 0, title, initial_state, hash, len, line);} - -NK_API int -nk_tree_image_push_hashed(struct nk_context *ctx, enum nk_tree_type type, - struct nk_image img, const char *title, enum nk_collapse_states initial_state, - const char *hash, int len,int seed) -{return nk_tree_base(ctx, type, &img, title, initial_state, hash, len, seed);} - -NK_API void -nk_tree_pop(struct nk_context *ctx) -{nk_tree_state_pop(ctx);} - -/*---------------------------------------------------------------- - * - * WIDGETS - * - * --------------------------------------------------------------*/ -NK_API struct nk_rect -nk_widget_bounds(struct nk_context *ctx) -{ - struct nk_rect bounds; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return nk_rect(0,0,0,0); - nk_layout_peek(&bounds, ctx); - return bounds; -} - -NK_API struct nk_vec2 -nk_widget_position(struct nk_context *ctx) -{ - struct nk_rect bounds; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return nk_vec2(0,0); - - nk_layout_peek(&bounds, ctx); - return nk_vec2(bounds.x, bounds.y); -} - -NK_API struct nk_vec2 -nk_widget_size(struct nk_context *ctx) -{ - struct nk_rect bounds; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return nk_vec2(0,0); - - nk_layout_peek(&bounds, ctx); - return nk_vec2(bounds.w, bounds.h); -} - -NK_API float -nk_widget_width(struct nk_context *ctx) -{ - struct nk_rect bounds; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return 0; - - nk_layout_peek(&bounds, ctx); - return bounds.w; -} - -NK_API float -nk_widget_height(struct nk_context *ctx) -{ - struct nk_rect bounds; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return 0; - - nk_layout_peek(&bounds, ctx); - return bounds.h; -} - -NK_API int -nk_widget_is_hovered(struct nk_context *ctx) -{ - int ret; - struct nk_rect bounds; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return 0; - - nk_layout_peek(&bounds, ctx); - ret = (ctx->active == ctx->current); - ret = ret && nk_input_is_mouse_hovering_rect(&ctx->input, bounds); - return ret; -} - -NK_API int -nk_widget_is_mouse_clicked(struct nk_context *ctx, enum nk_buttons btn) -{ - int ret; - struct nk_rect bounds; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return 0; - - nk_layout_peek(&bounds, ctx); - ret = (ctx->active == ctx->current); - ret = ret && nk_input_mouse_clicked(&ctx->input, btn, bounds); - return ret; -} - -NK_API int -nk_widget_has_mouse_click_down(struct nk_context *ctx, enum nk_buttons btn, int down) -{ - int ret; - struct nk_rect bounds; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return 0; - - nk_layout_peek(&bounds, ctx); - ret = (ctx->active == ctx->current); - ret = ret && nk_input_has_mouse_click_down_in_rect(&ctx->input, btn, bounds, down); - return ret; -} - -NK_API enum nk_widget_layout_states -nk_widget(struct nk_rect *bounds, const struct nk_context *ctx) -{ - struct nk_rect *c = 0; - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return NK_WIDGET_INVALID; - - /* allocate space and check if the widget needs to be updated and drawn */ - nk_panel_alloc_space(bounds, ctx); - win = ctx->current; - layout = win->layout; - c = &layout->clip; - - /* if one of these triggers you forgot to add an `if` condition around either - a window, group, popup, combobox or contextual menu `begin` and `end` block. - Example: - if (nk_begin(...) {...} nk_end(...); or - if (nk_group_begin(...) { nk_group_end(...);} */ - NK_ASSERT(!(layout->flags & NK_WINDOW_MINIMIZED)); - NK_ASSERT(!(layout->flags & NK_WINDOW_HIDDEN)); - NK_ASSERT(!(layout->flags & NK_WINDOW_CLOSED)); - - /* need to convert to int here to remove floating point error */ - bounds->x = (float)((int)bounds->x); - bounds->y = (float)((int)bounds->y); - bounds->w = (float)((int)bounds->w); - bounds->h = (float)((int)bounds->h); - - if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds->x, bounds->y, bounds->w, bounds->h)) - return NK_WIDGET_INVALID; - if (!NK_CONTAINS(bounds->x, bounds->y, bounds->w, bounds->h, c->x, c->y, c->w, c->h)) - return NK_WIDGET_ROM; - return NK_WIDGET_VALID; -} - -NK_API enum nk_widget_layout_states -nk_widget_fitting(struct nk_rect *bounds, struct nk_context *ctx, - struct nk_vec2 item_padding) -{ - /* update the bounds to stand without padding */ - struct nk_window *win; - struct nk_style *style; - struct nk_panel *layout; - enum nk_widget_layout_states state; - struct nk_vec2 panel_padding; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return NK_WIDGET_INVALID; - - win = ctx->current; - style = &ctx->style; - layout = win->layout; - state = nk_widget(bounds, ctx); - - panel_padding = nk_panel_get_padding(style, layout->type); - if (layout->row.index == 1) { - bounds->w += panel_padding.x; - bounds->x -= panel_padding.x; - } else bounds->x -= item_padding.x; - - if (layout->row.index == layout->row.columns) - bounds->w += panel_padding.x; - else bounds->w += item_padding.x; - return state; -} - -/*---------------------------------------------------------------- - * - * MISC - * - * --------------------------------------------------------------*/ -NK_API void -nk_spacing(struct nk_context *ctx, int cols) -{ - struct nk_window *win; - struct nk_panel *layout; - struct nk_rect nil; - int i, index, rows; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - /* spacing over row boundaries */ - win = ctx->current; - layout = win->layout; - index = (layout->row.index + cols) % layout->row.columns; - rows = (layout->row.index + cols) / layout->row.columns; - if (rows) { - for (i = 0; i < rows; ++i) - nk_panel_alloc_row(ctx, win); - cols = index; - } - - /* non table layout need to allocate space */ - if (layout->row.type != NK_LAYOUT_DYNAMIC_FIXED && - layout->row.type != NK_LAYOUT_STATIC_FIXED) { - for (i = 0; i < cols; ++i) - nk_panel_alloc_space(&nil, ctx); - } - layout->row.index = index; -} - -/*---------------------------------------------------------------- - * - * TEXT - * - * --------------------------------------------------------------*/ -NK_API void -nk_text_colored(struct nk_context *ctx, const char *str, int len, - nk_flags alignment, struct nk_color color) -{ - struct nk_window *win; - const struct nk_style *style; - - struct nk_vec2 item_padding; - struct nk_rect bounds; - struct nk_text text; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) return; - - win = ctx->current; - style = &ctx->style; - nk_panel_alloc_space(&bounds, ctx); - item_padding = style->text.padding; - - text.padding.x = item_padding.x; - text.padding.y = item_padding.y; - text.background = style->window.background; - text.text = color; - nk_widget_text(&win->buffer, bounds, str, len, &text, alignment, style->font); -} - -NK_API void -nk_text_wrap_colored(struct nk_context *ctx, const char *str, - int len, struct nk_color color) -{ - struct nk_window *win; - const struct nk_style *style; - - struct nk_vec2 item_padding; - struct nk_rect bounds; - struct nk_text text; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) return; - - win = ctx->current; - style = &ctx->style; - nk_panel_alloc_space(&bounds, ctx); - item_padding = style->text.padding; - - text.padding.x = item_padding.x; - text.padding.y = item_padding.y; - text.background = style->window.background; - text.text = color; - nk_widget_text_wrap(&win->buffer, bounds, str, len, &text, style->font); -} - -#ifdef NK_INCLUDE_STANDARD_VARARGS -NK_API void -nk_labelf_colored(struct nk_context *ctx, nk_flags flags, - struct nk_color color, const char *fmt, ...) -{ - char buf[256]; - va_list args; - va_start(args, fmt); - nk_strfmt(buf, NK_LEN(buf), fmt, args); - nk_label_colored(ctx, buf, flags, color); - va_end(args); -} - -NK_API void -nk_labelf_colored_wrap(struct nk_context *ctx, struct nk_color color, - const char *fmt, ...) -{ - char buf[256]; - va_list args; - va_start(args, fmt); - nk_strfmt(buf, NK_LEN(buf), fmt, args); - nk_label_colored_wrap(ctx, buf, color); - va_end(args); -} - -NK_API void -nk_labelf(struct nk_context *ctx, nk_flags flags, const char *fmt, ...) -{ - char buf[256]; - va_list args; - va_start(args, fmt); - nk_strfmt(buf, NK_LEN(buf), fmt, args); - nk_label(ctx, buf, flags); - va_end(args); -} - -NK_API void -nk_labelf_wrap(struct nk_context *ctx, const char *fmt,...) -{ - char buf[256]; - va_list args; - va_start(args, fmt); - nk_strfmt(buf, NK_LEN(buf), fmt, args); - nk_label_wrap(ctx, buf); - va_end(args); -} - -NK_API void -nk_value_bool(struct nk_context *ctx, const char *prefix, int value) -{nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, ((value) ? "true": "false"));} - -NK_API void -nk_value_int(struct nk_context *ctx, const char *prefix, int value) -{nk_labelf(ctx, NK_TEXT_LEFT, "%s: %d", prefix, value);} - -NK_API void -nk_value_uint(struct nk_context *ctx, const char *prefix, unsigned int value) -{nk_labelf(ctx, NK_TEXT_LEFT, "%s: %u", prefix, value);} - -NK_API void -nk_value_float(struct nk_context *ctx, const char *prefix, float value) -{ - double double_value = (double)value; - nk_labelf(ctx, NK_TEXT_LEFT, "%s: %.3f", prefix, double_value); -} - -NK_API void -nk_value_color_byte(struct nk_context *ctx, const char *p, struct nk_color c) -{nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%d, %d, %d, %d)", p, c.r, c.g, c.b, c.a);} - -NK_API void -nk_value_color_float(struct nk_context *ctx, const char *p, struct nk_color color) -{ - double c[4]; nk_color_dv(c, color); - nk_labelf(ctx, NK_TEXT_LEFT, "%s: (%.2f, %.2f, %.2f, %.2f)", - p, c[0], c[1], c[2], c[3]); -} - -NK_API void -nk_value_color_hex(struct nk_context *ctx, const char *prefix, struct nk_color color) -{ - char hex[16]; - nk_color_hex_rgba(hex, color); - nk_labelf(ctx, NK_TEXT_LEFT, "%s: %s", prefix, hex); -} -#endif - -NK_API void -nk_text(struct nk_context *ctx, const char *str, int len, nk_flags alignment) -{ - NK_ASSERT(ctx); - if (!ctx) return; - nk_text_colored(ctx, str, len, alignment, ctx->style.text.color); -} - -NK_API void -nk_text_wrap(struct nk_context *ctx, const char *str, int len) -{ - NK_ASSERT(ctx); - if (!ctx) return; - nk_text_wrap_colored(ctx, str, len, ctx->style.text.color); -} - -NK_API void -nk_label(struct nk_context *ctx, const char *str, nk_flags alignment) -{nk_text(ctx, str, nk_strlen(str), alignment);} - -NK_API void -nk_label_colored(struct nk_context *ctx, const char *str, nk_flags align, - struct nk_color color) -{nk_text_colored(ctx, str, nk_strlen(str), align, color);} - -NK_API void -nk_label_wrap(struct nk_context *ctx, const char *str) -{nk_text_wrap(ctx, str, nk_strlen(str));} - -NK_API void -nk_label_colored_wrap(struct nk_context *ctx, const char *str, struct nk_color color) -{nk_text_wrap_colored(ctx, str, nk_strlen(str), color);} - -NK_API void -nk_image(struct nk_context *ctx, struct nk_image img) -{ - struct nk_window *win; - struct nk_rect bounds; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) return; - - win = ctx->current; - if (!nk_widget(&bounds, ctx)) return; - nk_draw_image(&win->buffer, bounds, &img, nk_white); -} - -/*---------------------------------------------------------------- - * - * BUTTON - * - * --------------------------------------------------------------*/ -NK_API void -nk_button_set_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) -{ - NK_ASSERT(ctx); - if (!ctx) return; - ctx->button_behavior = behavior; -} - -NK_API int -nk_button_push_behavior(struct nk_context *ctx, enum nk_button_behavior behavior) -{ - struct nk_config_stack_button_behavior *button_stack; - struct nk_config_stack_button_behavior_element *element; - - NK_ASSERT(ctx); - if (!ctx) return 0; - - button_stack = &ctx->stacks.button_behaviors; - NK_ASSERT(button_stack->head < (int)NK_LEN(button_stack->elements)); - if (button_stack->head >= (int)NK_LEN(button_stack->elements)) - return 0; - - element = &button_stack->elements[button_stack->head++]; - element->address = &ctx->button_behavior; - element->old_value = ctx->button_behavior; - ctx->button_behavior = behavior; - return 1; -} - -NK_API int -nk_button_pop_behavior(struct nk_context *ctx) -{ - struct nk_config_stack_button_behavior *button_stack; - struct nk_config_stack_button_behavior_element *element; - - NK_ASSERT(ctx); - if (!ctx) return 0; - - button_stack = &ctx->stacks.button_behaviors; - NK_ASSERT(button_stack->head > 0); - if (button_stack->head < 1) - return 0; - - element = &button_stack->elements[--button_stack->head]; - *element->address = element->old_value; - return 1; -} - -NK_API int -nk_button_text_styled(struct nk_context *ctx, - const struct nk_style_button *style, const char *title, int len) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_input *in; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(style); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!style || !ctx || !ctx->current || !ctx->current->layout) return 0; - - win = ctx->current; - layout = win->layout; - state = nk_widget(&bounds, ctx); - - if (!state) return 0; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - return nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, - title, len, style->text_alignment, ctx->button_behavior, - style, in, ctx->style.font); -} - -NK_API int -nk_button_text(struct nk_context *ctx, const char *title, int len) -{ - NK_ASSERT(ctx); - if (!ctx) return 0; - return nk_button_text_styled(ctx, &ctx->style.button, title, len); -} - -NK_API int nk_button_label_styled(struct nk_context *ctx, - const struct nk_style_button *style, const char *title) -{return nk_button_text_styled(ctx, style, title, nk_strlen(title));} - -NK_API int nk_button_label(struct nk_context *ctx, const char *title) -{return nk_button_text(ctx, title, nk_strlen(title));} - -NK_API int -nk_button_color(struct nk_context *ctx, struct nk_color color) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_input *in; - struct nk_style_button button; - - int ret = 0; - struct nk_rect bounds; - struct nk_rect content; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - layout = win->layout; - - state = nk_widget(&bounds, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - - button = ctx->style.button; - button.normal = nk_style_item_color(color); - button.hover = nk_style_item_color(color); - button.active = nk_style_item_color(color); - ret = nk_do_button(&ctx->last_widget_state, &win->buffer, bounds, - &button, in, ctx->button_behavior, &content); - nk_draw_button(&win->buffer, &bounds, ctx->last_widget_state, &button); - return ret; -} - -NK_API int -nk_button_symbol_styled(struct nk_context *ctx, - const struct nk_style_button *style, enum nk_symbol_type symbol) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_input *in; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - layout = win->layout; - state = nk_widget(&bounds, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - return nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, bounds, - symbol, ctx->button_behavior, style, in, ctx->style.font); -} - -NK_API int -nk_button_symbol(struct nk_context *ctx, enum nk_symbol_type symbol) -{ - NK_ASSERT(ctx); - if (!ctx) return 0; - return nk_button_symbol_styled(ctx, &ctx->style.button, symbol); -} - -NK_API int -nk_button_image_styled(struct nk_context *ctx, const struct nk_style_button *style, - struct nk_image img) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_input *in; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - layout = win->layout; - - state = nk_widget(&bounds, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - return nk_do_button_image(&ctx->last_widget_state, &win->buffer, bounds, - img, ctx->button_behavior, style, in); -} - -NK_API int -nk_button_image(struct nk_context *ctx, struct nk_image img) -{ - NK_ASSERT(ctx); - if (!ctx) return 0; - return nk_button_image_styled(ctx, &ctx->style.button, img); -} - -NK_API int -nk_button_symbol_text_styled(struct nk_context *ctx, - const struct nk_style_button *style, enum nk_symbol_type symbol, - const char *text, int len, nk_flags align) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_input *in; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - layout = win->layout; - - state = nk_widget(&bounds, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - return nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, - symbol, text, len, align, ctx->button_behavior, - style, ctx->style.font, in); -} - -NK_API int -nk_button_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, - const char* text, int len, nk_flags align) -{ - NK_ASSERT(ctx); - if (!ctx) return 0; - return nk_button_symbol_text_styled(ctx, &ctx->style.button, symbol, text, len, align); -} - -NK_API int nk_button_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, - const char *label, nk_flags align) -{return nk_button_symbol_text(ctx, symbol, label, nk_strlen(label), align);} - -NK_API int nk_button_symbol_label_styled(struct nk_context *ctx, - const struct nk_style_button *style, enum nk_symbol_type symbol, - const char *title, nk_flags align) -{return nk_button_symbol_text_styled(ctx, style, symbol, title, nk_strlen(title), align);} - -NK_API int -nk_button_image_text_styled(struct nk_context *ctx, - const struct nk_style_button *style, struct nk_image img, const char *text, - int len, nk_flags align) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_input *in; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - layout = win->layout; - - state = nk_widget(&bounds, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - return nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, - bounds, img, text, len, align, ctx->button_behavior, - style, ctx->style.font, in); -} - -NK_API int -nk_button_image_text(struct nk_context *ctx, struct nk_image img, - const char *text, int len, nk_flags align) -{return nk_button_image_text_styled(ctx, &ctx->style.button,img, text, len, align);} - - -NK_API int nk_button_image_label(struct nk_context *ctx, struct nk_image img, - const char *label, nk_flags align) -{return nk_button_image_text(ctx, img, label, nk_strlen(label), align);} - -NK_API int nk_button_image_label_styled(struct nk_context *ctx, - const struct nk_style_button *style, struct nk_image img, - const char *label, nk_flags text_alignment) -{return nk_button_image_text_styled(ctx, style, img, label, nk_strlen(label), text_alignment);} - -/*---------------------------------------------------------------- - * - * SELECTABLE - * - * --------------------------------------------------------------*/ -NK_API int -nk_selectable_text(struct nk_context *ctx, const char *str, int len, - nk_flags align, int *value) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_input *in; - const struct nk_style *style; - - enum nk_widget_layout_states state; - struct nk_rect bounds; - - NK_ASSERT(ctx); - NK_ASSERT(value); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout || !value) - return 0; - - win = ctx->current; - layout = win->layout; - style = &ctx->style; - - state = nk_widget(&bounds, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - return nk_do_selectable(&ctx->last_widget_state, &win->buffer, bounds, - str, len, align, value, &style->selectable, in, style->font); -} - -NK_API int -nk_selectable_image_text(struct nk_context *ctx, struct nk_image img, - const char *str, int len, nk_flags align, int *value) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_input *in; - const struct nk_style *style; - - enum nk_widget_layout_states state; - struct nk_rect bounds; - - NK_ASSERT(ctx); - NK_ASSERT(value); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout || !value) - return 0; - - win = ctx->current; - layout = win->layout; - style = &ctx->style; - - state = nk_widget(&bounds, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - return nk_do_selectable_image(&ctx->last_widget_state, &win->buffer, bounds, - str, len, align, value, &img, &style->selectable, in, style->font); -} - -NK_API int nk_select_text(struct nk_context *ctx, const char *str, int len, - nk_flags align, int value) -{nk_selectable_text(ctx, str, len, align, &value);return value;} - -NK_API int nk_selectable_label(struct nk_context *ctx, const char *str, nk_flags align, int *value) -{return nk_selectable_text(ctx, str, nk_strlen(str), align, value);} - -NK_API int nk_selectable_image_label(struct nk_context *ctx,struct nk_image img, - const char *str, nk_flags align, int *value) -{return nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, value);} - -NK_API int nk_select_label(struct nk_context *ctx, const char *str, nk_flags align, int value) -{nk_selectable_text(ctx, str, nk_strlen(str), align, &value);return value;} - -NK_API int nk_select_image_label(struct nk_context *ctx, struct nk_image img, - const char *str, nk_flags align, int value) -{nk_selectable_image_text(ctx, img, str, nk_strlen(str), align, &value);return value;} - -NK_API int nk_select_image_text(struct nk_context *ctx, struct nk_image img, - const char *str, int len, nk_flags align, int value) -{nk_selectable_image_text(ctx, img, str, len, align, &value);return value;} - -/*---------------------------------------------------------------- - * - * CHECKBOX - * - * --------------------------------------------------------------*/ -NK_API int -nk_check_text(struct nk_context *ctx, const char *text, int len, int active) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_input *in; - const struct nk_style *style; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return active; - - win = ctx->current; - style = &ctx->style; - layout = win->layout; - - state = nk_widget(&bounds, ctx); - if (!state) return active; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &active, - text, len, NK_TOGGLE_CHECK, &style->checkbox, in, style->font); - return active; -} - -NK_API unsigned int -nk_check_flags_text(struct nk_context *ctx, const char *text, int len, - unsigned int flags, unsigned int value) -{ - int old_active; - NK_ASSERT(ctx); - NK_ASSERT(text); - if (!ctx || !text) return flags; - old_active = (int)((flags & value) & value); - if (nk_check_text(ctx, text, len, old_active)) - flags |= value; - else flags &= ~value; - return flags; -} - -NK_API int -nk_checkbox_text(struct nk_context *ctx, const char *text, int len, int *active) -{ - int old_val; - NK_ASSERT(ctx); - NK_ASSERT(text); - NK_ASSERT(active); - if (!ctx || !text || !active) return 0; - old_val = *active; - *active = nk_check_text(ctx, text, len, *active); - return old_val != *active; -} - -NK_API int -nk_checkbox_flags_text(struct nk_context *ctx, const char *text, int len, - unsigned int *flags, unsigned int value) -{ - int active; - NK_ASSERT(ctx); - NK_ASSERT(text); - NK_ASSERT(flags); - if (!ctx || !text || !flags) return 0; - - active = (int)((*flags & value) & value); - if (nk_checkbox_text(ctx, text, len, &active)) { - if (active) *flags |= value; - else *flags &= ~value; - return 1; - } - return 0; -} - -NK_API int nk_check_label(struct nk_context *ctx, const char *label, int active) -{return nk_check_text(ctx, label, nk_strlen(label), active);} - -NK_API unsigned int nk_check_flags_label(struct nk_context *ctx, const char *label, - unsigned int flags, unsigned int value) -{return nk_check_flags_text(ctx, label, nk_strlen(label), flags, value);} - -NK_API int nk_checkbox_label(struct nk_context *ctx, const char *label, int *active) -{return nk_checkbox_text(ctx, label, nk_strlen(label), active);} - -NK_API int nk_checkbox_flags_label(struct nk_context *ctx, const char *label, - unsigned int *flags, unsigned int value) -{return nk_checkbox_flags_text(ctx, label, nk_strlen(label), flags, value);} - -/*---------------------------------------------------------------- - * - * OPTION - * - * --------------------------------------------------------------*/ -NK_API int -nk_option_text(struct nk_context *ctx, const char *text, int len, int is_active) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_input *in; - const struct nk_style *style; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return is_active; - - win = ctx->current; - style = &ctx->style; - layout = win->layout; - - state = nk_widget(&bounds, ctx); - if (!state) return state; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - nk_do_toggle(&ctx->last_widget_state, &win->buffer, bounds, &is_active, - text, len, NK_TOGGLE_OPTION, &style->option, in, style->font); - return is_active; -} - -NK_API int -nk_radio_text(struct nk_context *ctx, const char *text, int len, int *active) -{ - int old_value; - NK_ASSERT(ctx); - NK_ASSERT(text); - NK_ASSERT(active); - if (!ctx || !text || !active) return 0; - old_value = *active; - *active = nk_option_text(ctx, text, len, old_value); - return old_value != *active; -} - -NK_API int -nk_option_label(struct nk_context *ctx, const char *label, int active) -{return nk_option_text(ctx, label, nk_strlen(label), active);} - -NK_API int -nk_radio_label(struct nk_context *ctx, const char *label, int *active) -{return nk_radio_text(ctx, label, nk_strlen(label), active);} - -/*---------------------------------------------------------------- - * - * SLIDER - * - * --------------------------------------------------------------*/ -NK_API int -nk_slider_float(struct nk_context *ctx, float min_value, float *value, float max_value, - float value_step) -{ - struct nk_window *win; - struct nk_panel *layout; - struct nk_input *in; - const struct nk_style *style; - - int ret = 0; - float old_value; - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - NK_ASSERT(value); - if (!ctx || !ctx->current || !ctx->current->layout || !value) - return ret; - - win = ctx->current; - style = &ctx->style; - layout = win->layout; - - state = nk_widget(&bounds, ctx); - if (!state) return ret; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - - old_value = *value; - *value = nk_do_slider(&ctx->last_widget_state, &win->buffer, bounds, min_value, - old_value, max_value, value_step, &style->slider, in, style->font); - return (old_value > *value || old_value < *value); -} - -NK_API float -nk_slide_float(struct nk_context *ctx, float min, float val, float max, float step) -{ - nk_slider_float(ctx, min, &val, max, step); return val; -} - -NK_API int -nk_slide_int(struct nk_context *ctx, int min, int val, int max, int step) -{ - float value = (float)val; - nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); - return (int)value; -} - -NK_API int -nk_slider_int(struct nk_context *ctx, int min, int *val, int max, int step) -{ - int ret; - float value = (float)*val; - ret = nk_slider_float(ctx, (float)min, &value, (float)max, (float)step); - *val = (int)value; - return ret; -} - -/*---------------------------------------------------------------- - * - * PROGRESSBAR - * - * --------------------------------------------------------------*/ -NK_API int -nk_progress(struct nk_context *ctx, nk_size *cur, nk_size max, int is_modifyable) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_style *style; - const struct nk_input *in; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - nk_size old_value; - - NK_ASSERT(ctx); - NK_ASSERT(cur); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout || !cur) - return 0; - - win = ctx->current; - style = &ctx->style; - layout = win->layout; - state = nk_widget(&bounds, ctx); - if (!state) return 0; - - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - old_value = *cur; - *cur = nk_do_progress(&ctx->last_widget_state, &win->buffer, bounds, - *cur, max, is_modifyable, &style->progress, in); - return (*cur != old_value); -} - -NK_API nk_size nk_prog(struct nk_context *ctx, nk_size cur, nk_size max, int modifyable) -{nk_progress(ctx, &cur, max, modifyable);return cur;} - -/*---------------------------------------------------------------- - * - * EDIT - * - * --------------------------------------------------------------*/ -NK_API void -nk_edit_focus(struct nk_context *ctx, nk_flags flags) -{ - nk_hash hash; - struct nk_window *win; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return; - - win = ctx->current; - hash = win->edit.seq; - win->edit.active = nk_true; - win->edit.name = hash; - if (flags & NK_EDIT_ALWAYS_INSERT_MODE) - win->edit.mode = NK_TEXT_EDIT_MODE_INSERT; -} - -NK_API nk_flags -nk_edit_string(struct nk_context *ctx, nk_flags flags, - char *memory, int *len, int max, nk_plugin_filter filter) -{ - nk_hash hash; - nk_flags state; - struct nk_text_edit *edit; - struct nk_window *win; - - NK_ASSERT(ctx); - NK_ASSERT(memory); - NK_ASSERT(len); - if (!ctx || !memory || !len) - return 0; - - filter = (!filter) ? nk_filter_default: filter; - win = ctx->current; - hash = win->edit.seq; - edit = &ctx->text_edit; - nk_textedit_clear_state(&ctx->text_edit, (flags & NK_EDIT_MULTILINE)? - NK_TEXT_EDIT_MULTI_LINE: NK_TEXT_EDIT_SINGLE_LINE, filter); - - if (win->edit.active && hash == win->edit.name) { - if (flags & NK_EDIT_NO_CURSOR) - edit->cursor = nk_utf_len(memory, *len); - else edit->cursor = win->edit.cursor; - if (!(flags & NK_EDIT_SELECTABLE)) { - edit->select_start = win->edit.cursor; - edit->select_end = win->edit.cursor; - } else { - edit->select_start = win->edit.sel_start; - edit->select_end = win->edit.sel_end; - } - edit->mode = win->edit.mode; - edit->scrollbar.x = (float)win->edit.scrollbar.x; - edit->scrollbar.y = (float)win->edit.scrollbar.y; - edit->active = nk_true; - } else edit->active = nk_false; - - max = NK_MAX(1, max); - *len = NK_MIN(*len, max-1); - nk_str_init_fixed(&edit->string, memory, (nk_size)max); - edit->string.buffer.allocated = (nk_size)*len; - edit->string.len = nk_utf_len(memory, *len); - state = nk_edit_buffer(ctx, flags, edit, filter); - *len = (int)edit->string.buffer.allocated; - - if (edit->active) { - win->edit.cursor = edit->cursor; - win->edit.sel_start = edit->select_start; - win->edit.sel_end = edit->select_end; - win->edit.mode = edit->mode; - win->edit.scrollbar.x = (nk_ushort)edit->scrollbar.x; - win->edit.scrollbar.y = (nk_ushort)edit->scrollbar.y; - } - return state; -} - -NK_API nk_flags -nk_edit_buffer(struct nk_context *ctx, nk_flags flags, - struct nk_text_edit *edit, nk_plugin_filter filter) -{ - struct nk_window *win; - struct nk_style *style; - struct nk_input *in; - - enum nk_widget_layout_states state; - struct nk_rect bounds; - - nk_flags ret_flags = 0; - unsigned char prev_state; - nk_hash hash; - - /* make sure correct values */ - NK_ASSERT(ctx); - NK_ASSERT(edit); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - style = &ctx->style; - state = nk_widget(&bounds, ctx); - if (!state) return state; - in = (win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - - /* check if edit is currently hot item */ - hash = win->edit.seq++; - if (win->edit.active && hash == win->edit.name) { - if (flags & NK_EDIT_NO_CURSOR) - edit->cursor = edit->string.len; - if (!(flags & NK_EDIT_SELECTABLE)) { - edit->select_start = edit->cursor; - edit->select_end = edit->cursor; - } - if (flags & NK_EDIT_CLIPBOARD) - edit->clip = ctx->clip; - } - - filter = (!filter) ? nk_filter_default: filter; - prev_state = (unsigned char)edit->active; - in = (flags & NK_EDIT_READ_ONLY) ? 0: in; - ret_flags = nk_do_edit(&ctx->last_widget_state, &win->buffer, bounds, flags, - filter, edit, &style->edit, in, style->font); - - if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) - ctx->style.cursor_active = ctx->style.cursors[NK_CURSOR_TEXT]; - if (edit->active && prev_state != edit->active) { - /* current edit is now hot */ - win->edit.active = nk_true; - win->edit.name = hash; - } else if (prev_state && !edit->active) { - /* current edit is now cold */ - win->edit.active = nk_false; - } - return ret_flags; -} - -NK_API nk_flags -nk_edit_string_zero_terminated(struct nk_context *ctx, nk_flags flags, - char *buffer, int max, nk_plugin_filter filter) -{ - nk_flags result; - int len = nk_strlen(buffer); - result = nk_edit_string(ctx, flags, buffer, &len, max, filter); - buffer[NK_MIN(NK_MAX(max-1,0), len)] = '\0'; - return result; -} - -/*---------------------------------------------------------------- - * - * PROPERTY - * - * --------------------------------------------------------------*/ -NK_INTERN struct nk_property_variant -nk_property_variant_int(int value, int min_value, int max_value, int step) -{ - struct nk_property_variant result; - result.kind = NK_PROPERTY_INT; - result.value.i = value; - result.min_value.i = min_value; - result.max_value.i = max_value; - result.step.i = step; - return result; -} - -NK_INTERN struct nk_property_variant -nk_property_variant_float(float value, float min_value, float max_value, float step) -{ - struct nk_property_variant result; - result.kind = NK_PROPERTY_FLOAT; - result.value.f = value; - result.min_value.f = min_value; - result.max_value.f = max_value; - result.step.f = step; - return result; -} - -NK_INTERN struct nk_property_variant -nk_property_variant_double(double value, double min_value, double max_value, - double step) -{ - struct nk_property_variant result; - result.kind = NK_PROPERTY_DOUBLE; - result.value.d = value; - result.min_value.d = min_value; - result.max_value.d = max_value; - result.step.d = step; - return result; -} - -NK_INTERN 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) -{ - struct nk_window *win; - struct nk_panel *layout; - struct nk_input *in; - const struct nk_style *style; - - struct nk_rect bounds; - enum nk_widget_layout_states s; - - int *state = 0; - nk_hash hash = 0; - char *buffer = 0; - int *len = 0; - int *cursor = 0; - int old_state; - - char dummy_buffer[NK_MAX_NUMBER_BUFFER]; - int dummy_state = NK_PROPERTY_DEFAULT; - int dummy_length = 0; - int dummy_cursor = 0; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - win = ctx->current; - layout = win->layout; - style = &ctx->style; - s = nk_widget(&bounds, ctx); - if (!s) return; - in = (s == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - - /* calculate hash from name */ - if (name[0] == '#') { - hash = nk_murmur_hash(name, (int)nk_strlen(name), win->property.seq++); - name++; /* special number hash */ - } else hash = nk_murmur_hash(name, (int)nk_strlen(name), 42); - - /* check if property is currently hot item */ - if (win->property.active && hash == win->property.name) { - buffer = win->property.buffer; - len = &win->property.length; - cursor = &win->property.cursor; - state = &win->property.state; - } else { - buffer = dummy_buffer; - len = &dummy_length; - cursor = &dummy_cursor; - state = &dummy_state; - } - - /* execute property widget */ - old_state = *state; - nk_do_property(&ctx->last_widget_state, &win->buffer, bounds, name, - variant, inc_per_pixel, buffer, len, state, cursor, - &style->property, filter, in, style->font, &ctx->text_edit); - - if (in && *state != NK_PROPERTY_DEFAULT && !win->property.active) { - /* current property is now hot */ - win->property.active = 1; - NK_MEMCPY(win->property.buffer, buffer, (nk_size)*len); - win->property.length = *len; - win->property.cursor = *cursor; - win->property.state = *state; - win->property.name = hash; - if (*state == NK_PROPERTY_DRAG) { - ctx->input.mouse.grab = nk_true; - ctx->input.mouse.grabbed = nk_true; - } - } - - /* check if previously active property is now inactive */ - if (*state == NK_PROPERTY_DEFAULT && old_state != NK_PROPERTY_DEFAULT) { - if (old_state == NK_PROPERTY_DRAG) { - ctx->input.mouse.grab = nk_false; - ctx->input.mouse.grabbed = nk_false; - ctx->input.mouse.ungrab = nk_true; - } - win->property.active = 0; - } -} - -NK_API void -nk_property_int(struct nk_context *ctx, const char *name, - int min, int *val, int max, int step, float inc_per_pixel) -{ - struct nk_property_variant variant; - NK_ASSERT(ctx); - NK_ASSERT(name); - NK_ASSERT(val); - - if (!ctx || !ctx->current || !name || !val) return; - variant = nk_property_variant_int(*val, min, max, step); - nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); - *val = variant.value.i; -} - -NK_API void -nk_property_float(struct nk_context *ctx, const char *name, - float min, float *val, float max, float step, float inc_per_pixel) -{ - struct nk_property_variant variant; - NK_ASSERT(ctx); - NK_ASSERT(name); - NK_ASSERT(val); - - if (!ctx || !ctx->current || !name || !val) return; - variant = nk_property_variant_float(*val, min, max, step); - nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); - *val = variant.value.f; -} - -NK_API void -nk_property_double(struct nk_context *ctx, const char *name, - double min, double *val, double max, double step, float inc_per_pixel) -{ - struct nk_property_variant variant; - NK_ASSERT(ctx); - NK_ASSERT(name); - NK_ASSERT(val); - - if (!ctx || !ctx->current || !name || !val) return; - variant = nk_property_variant_double(*val, min, max, step); - nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); - *val = variant.value.d; -} - -NK_API int -nk_propertyi(struct nk_context *ctx, const char *name, int min, int val, - int max, int step, float inc_per_pixel) -{ - struct nk_property_variant variant; - NK_ASSERT(ctx); - NK_ASSERT(name); - - if (!ctx || !ctx->current || !name) return val; - variant = nk_property_variant_int(val, min, max, step); - nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_INT); - val = variant.value.i; - return val; -} - -NK_API float -nk_propertyf(struct nk_context *ctx, const char *name, float min, - float val, float max, float step, float inc_per_pixel) -{ - struct nk_property_variant variant; - NK_ASSERT(ctx); - NK_ASSERT(name); - - if (!ctx || !ctx->current || !name) return val; - variant = nk_property_variant_float(val, min, max, step); - nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); - val = variant.value.f; - return val; -} - -NK_API double -nk_propertyd(struct nk_context *ctx, const char *name, double min, - double val, double max, double step, float inc_per_pixel) -{ - struct nk_property_variant variant; - NK_ASSERT(ctx); - NK_ASSERT(name); - - if (!ctx || !ctx->current || !name) return val; - variant = nk_property_variant_double(val, min, max, step); - nk_property(ctx, name, &variant, inc_per_pixel, NK_FILTER_FLOAT); - val = variant.value.d; - return val; -} - -/*---------------------------------------------------------------- - * - * COLOR PICKER - * - * --------------------------------------------------------------*/ -NK_API int -nk_color_pick(struct nk_context * ctx, struct nk_color *color, - enum nk_color_format fmt) -{ - struct nk_window *win; - struct nk_panel *layout; - const struct nk_style *config; - const struct nk_input *in; - - enum nk_widget_layout_states state; - struct nk_rect bounds; - - NK_ASSERT(ctx); - NK_ASSERT(color); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout || !color) - return 0; - - win = ctx->current; - config = &ctx->style; - layout = win->layout; - state = nk_widget(&bounds, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - return nk_do_color_picker(&ctx->last_widget_state, &win->buffer, color, fmt, bounds, - nk_vec2(0,0), in, config->font); -} - -NK_API struct nk_color -nk_color_picker(struct nk_context *ctx, struct nk_color color, - enum nk_color_format fmt) -{ - nk_color_pick(ctx, &color, fmt); - return color; -} - -/* ------------------------------------------------------------- - * - * CHART - * - * --------------------------------------------------------------*/ -NK_API int -nk_chart_begin_colored(struct nk_context *ctx, enum nk_chart_type type, - struct nk_color color, struct nk_color highlight, - int count, float min_value, float max_value) -{ - struct nk_window *win; - struct nk_chart *chart; - const struct nk_style *config; - const struct nk_style_chart *style; - - const struct nk_style_item *background; - struct nk_rect bounds = {0, 0, 0, 0}; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - - if (!ctx || !ctx->current || !ctx->current->layout) return 0; - if (!nk_widget(&bounds, ctx)) { - chart = &ctx->current->layout->chart; - nk_zero(chart, sizeof(*chart)); - return 0; - } - - win = ctx->current; - config = &ctx->style; - chart = &win->layout->chart; - style = &config->chart; - - /* setup basic generic chart */ - nk_zero(chart, sizeof(*chart)); - chart->x = bounds.x + style->padding.x; - chart->y = bounds.y + style->padding.y; - chart->w = bounds.w - 2 * style->padding.x; - chart->h = bounds.h - 2 * style->padding.y; - chart->w = NK_MAX(chart->w, 2 * style->padding.x); - chart->h = NK_MAX(chart->h, 2 * style->padding.y); - - /* add first slot into chart */ - {struct nk_chart_slot *slot = &chart->slots[chart->slot++]; - slot->type = type; - slot->count = count; - slot->color = color; - slot->highlight = highlight; - slot->min = NK_MIN(min_value, max_value); - slot->max = NK_MAX(min_value, max_value); - slot->range = slot->max - slot->min;} - - /* draw chart background */ - background = &style->background; - if (background->type == NK_STYLE_ITEM_IMAGE) { - nk_draw_image(&win->buffer, bounds, &background->data.image, nk_white); - } else { - nk_fill_rect(&win->buffer, bounds, style->rounding, style->border_color); - nk_fill_rect(&win->buffer, nk_shrink_rect(bounds, style->border), - style->rounding, style->background.data.color); - } - return 1; -} - -NK_API int -nk_chart_begin(struct nk_context *ctx, const enum nk_chart_type type, - int count, float min_value, float max_value) -{return nk_chart_begin_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);} - -NK_API void -nk_chart_add_slot_colored(struct nk_context *ctx, const enum nk_chart_type type, - struct nk_color color, struct nk_color highlight, - int count, float min_value, float max_value) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - NK_ASSERT(ctx->current->layout->chart.slot < NK_CHART_MAX_SLOT); - if (!ctx || !ctx->current || !ctx->current->layout) return; - if (ctx->current->layout->chart.slot >= NK_CHART_MAX_SLOT) return; - - /* add another slot into the graph */ - {struct nk_chart *chart = &ctx->current->layout->chart; - struct nk_chart_slot *slot = &chart->slots[chart->slot++]; - slot->type = type; - slot->count = count; - slot->color = color; - slot->highlight = highlight; - slot->min = NK_MIN(min_value, max_value); - slot->max = NK_MAX(min_value, max_value); - slot->range = slot->max - slot->min;} -} - -NK_API void -nk_chart_add_slot(struct nk_context *ctx, const enum nk_chart_type type, - int count, float min_value, float max_value) -{nk_chart_add_slot_colored(ctx, type, ctx->style.chart.color, ctx->style.chart.selected_color, count, min_value, max_value);} - -NK_INTERN nk_flags -nk_chart_push_line(struct nk_context *ctx, struct nk_window *win, - struct nk_chart *g, float value, int slot) -{ - struct nk_panel *layout = win->layout; - const struct nk_input *i = &ctx->input; - struct nk_command_buffer *out = &win->buffer; - - nk_flags ret = 0; - struct nk_vec2 cur; - struct nk_rect bounds; - struct nk_color color; - float step; - float range; - float ratio; - - NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); - step = g->w / (float)g->slots[slot].count; - range = g->slots[slot].max - g->slots[slot].min; - ratio = (value - g->slots[slot].min) / range; - - if (g->slots[slot].index == 0) { - /* first data point does not have a connection */ - g->slots[slot].last.x = g->x; - g->slots[slot].last.y = (g->y + g->h) - ratio * (float)g->h; - - bounds.x = g->slots[slot].last.x - 2; - bounds.y = g->slots[slot].last.y - 2; - bounds.w = bounds.h = 4; - - color = g->slots[slot].color; - if (!(layout->flags & NK_WINDOW_ROM) && - NK_INBOX(i->mouse.pos.x,i->mouse.pos.y, g->slots[slot].last.x-3, g->slots[slot].last.y-3, 6, 6)){ - ret = nk_input_is_mouse_hovering_rect(i, bounds) ? NK_CHART_HOVERING : 0; - ret |= (i->mouse.buttons[NK_BUTTON_LEFT].down && - i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; - color = g->slots[slot].highlight; - } - nk_fill_rect(out, bounds, 0, color); - g->slots[slot].index += 1; - return ret; - } - - /* draw a line between the last data point and the new one */ - color = g->slots[slot].color; - cur.x = g->x + (float)(step * (float)g->slots[slot].index); - cur.y = (g->y + g->h) - (ratio * (float)g->h); - nk_stroke_line(out, g->slots[slot].last.x, g->slots[slot].last.y, cur.x, cur.y, 1.0f, color); - - bounds.x = cur.x - 3; - bounds.y = cur.y - 3; - bounds.w = bounds.h = 6; - - /* user selection of current data point */ - if (!(layout->flags & NK_WINDOW_ROM)) { - if (nk_input_is_mouse_hovering_rect(i, bounds)) { - ret = NK_CHART_HOVERING; - ret |= (!i->mouse.buttons[NK_BUTTON_LEFT].down && - i->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; - color = g->slots[slot].highlight; - } - } - nk_fill_rect(out, nk_rect(cur.x - 2, cur.y - 2, 4, 4), 0, color); - - /* save current data point position */ - g->slots[slot].last.x = cur.x; - g->slots[slot].last.y = cur.y; - g->slots[slot].index += 1; - return ret; -} - -NK_INTERN nk_flags -nk_chart_push_column(const struct nk_context *ctx, struct nk_window *win, - struct nk_chart *chart, float value, int slot) -{ - struct nk_command_buffer *out = &win->buffer; - const struct nk_input *in = &ctx->input; - struct nk_panel *layout = win->layout; - - float ratio; - nk_flags ret = 0; - struct nk_color color; - struct nk_rect item = {0,0,0,0}; - - NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); - if (chart->slots[slot].index >= chart->slots[slot].count) - return nk_false; - if (chart->slots[slot].count) { - float padding = (float)(chart->slots[slot].count-1); - item.w = (chart->w - padding) / (float)(chart->slots[slot].count); - } - - /* calculate bounds of current bar chart entry */ - color = chart->slots[slot].color;; - item.h = chart->h * NK_ABS((value/chart->slots[slot].range)); - if (value >= 0) { - ratio = (value + NK_ABS(chart->slots[slot].min)) / NK_ABS(chart->slots[slot].range); - item.y = (chart->y + chart->h) - chart->h * ratio; - } else { - ratio = (value - chart->slots[slot].max) / chart->slots[slot].range; - item.y = chart->y + (chart->h * NK_ABS(ratio)) - item.h; - } - item.x = chart->x + ((float)chart->slots[slot].index * item.w); - item.x = item.x + ((float)chart->slots[slot].index); - - /* user chart bar selection */ - if (!(layout->flags & NK_WINDOW_ROM) && - NK_INBOX(in->mouse.pos.x,in->mouse.pos.y,item.x,item.y,item.w,item.h)) { - ret = NK_CHART_HOVERING; - ret |= (!in->mouse.buttons[NK_BUTTON_LEFT].down && - in->mouse.buttons[NK_BUTTON_LEFT].clicked) ? NK_CHART_CLICKED: 0; - color = chart->slots[slot].highlight; - } - nk_fill_rect(out, item, 0, color); - chart->slots[slot].index += 1; - return ret; -} - -NK_API nk_flags -nk_chart_push_slot(struct nk_context *ctx, float value, int slot) -{ - nk_flags flags; - struct nk_window *win; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(slot >= 0 && slot < NK_CHART_MAX_SLOT); - NK_ASSERT(slot < ctx->current->layout->chart.slot); - if (!ctx || !ctx->current || slot >= NK_CHART_MAX_SLOT) return nk_false; - if (slot >= ctx->current->layout->chart.slot) return nk_false; - - win = ctx->current; - if (win->layout->chart.slot < slot) return nk_false; - switch (win->layout->chart.slots[slot].type) { - case NK_CHART_LINES: - flags = nk_chart_push_line(ctx, win, &win->layout->chart, value, slot); break; - case NK_CHART_COLUMN: - flags = nk_chart_push_column(ctx, win, &win->layout->chart, value, slot); break; - default: - case NK_CHART_MAX: - flags = 0; - } - return flags; -} - -NK_API nk_flags -nk_chart_push(struct nk_context *ctx, float value) -{return nk_chart_push_slot(ctx, value, 0);} - -NK_API void -nk_chart_end(struct nk_context *ctx) -{ - struct nk_window *win; - struct nk_chart *chart; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return; - - win = ctx->current; - chart = &win->layout->chart; - NK_MEMSET(chart, 0, sizeof(*chart)); - return; -} - -NK_API void -nk_plot(struct nk_context *ctx, enum nk_chart_type type, const float *values, - int count, int offset) -{ - int i = 0; - float min_value; - float max_value; - - NK_ASSERT(ctx); - NK_ASSERT(values); - if (!ctx || !values || !count) return; - - min_value = values[offset]; - max_value = values[offset]; - for (i = 0; i < count; ++i) { - min_value = NK_MIN(values[i + offset], min_value); - max_value = NK_MAX(values[i + offset], max_value); - } - nk_chart_begin(ctx, type, count, min_value, max_value); - for (i = 0; i < count; ++i) - nk_chart_push(ctx, values[i + offset]); - nk_chart_end(ctx); -} - -NK_API void -nk_plot_function(struct nk_context *ctx, enum nk_chart_type type, void *userdata, - float(*value_getter)(void* user, int index), int count, int offset) -{ - int i = 0; - float min_value; - float max_value; - - NK_ASSERT(ctx); - NK_ASSERT(value_getter); - if (!ctx || !value_getter || !count) return; - - max_value = min_value = value_getter(userdata, offset); - for (i = 0; i < count; ++i) { - float value = value_getter(userdata, i + offset); - min_value = NK_MIN(value, min_value); - max_value = NK_MAX(value, max_value); - } - nk_chart_begin(ctx, type, count, min_value, max_value); - for (i = 0; i < count; ++i) - nk_chart_push(ctx, value_getter(userdata, i + offset)); - nk_chart_end(ctx); -} - -/* ------------------------------------------------------------- - * - * GROUP - * - * --------------------------------------------------------------*/ -NK_API int -nk_group_scrolled_offset_begin(struct nk_context *ctx, - nk_uint *x_offset, nk_uint *y_offset, const char *title, nk_flags flags) -{ - struct nk_rect bounds; - struct nk_window panel; - struct nk_window *win; - - win = ctx->current; - nk_panel_alloc_space(&bounds, ctx); - - {const struct nk_rect *c = &win->layout->clip; - if (!NK_INTERSECT(c->x, c->y, c->w, c->h, bounds.x, bounds.y, bounds.w, bounds.h) && - !(flags & NK_WINDOW_MOVABLE)) { - return 0; - }} - if (win->flags & NK_WINDOW_ROM) - flags |= NK_WINDOW_ROM; - - /* initialize a fake window to create the layout from */ - nk_zero(&panel, sizeof(panel)); - panel.bounds = bounds; - panel.flags = flags; - panel.scrollbar.x = *x_offset; - panel.scrollbar.y = *y_offset; - panel.buffer = win->buffer; - panel.layout = (struct nk_panel*)nk_create_panel(ctx); - ctx->current = &panel; - nk_panel_begin(ctx, (flags & NK_WINDOW_TITLE) ? title: 0, NK_PANEL_GROUP); - - win->buffer = panel.buffer; - win->buffer.clip = panel.layout->clip; - panel.layout->offset_x = x_offset; - panel.layout->offset_y = y_offset; - panel.layout->parent = win->layout; - win->layout = panel.layout; - ctx->current = win; - return 1; - -} - -NK_API void -nk_group_scrolled_end(struct nk_context *ctx) -{ - struct nk_window *win; - struct nk_panel *parent; - struct nk_panel *g; - - struct nk_rect clip; - struct nk_window pan; - struct nk_vec2 panel_padding; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) - return; - - /* make sure nk_group_begin was called correctly */ - NK_ASSERT(ctx->current); - win = ctx->current; - NK_ASSERT(win->layout); - g = win->layout; - NK_ASSERT(g->parent); - parent = g->parent; - - /* dummy window */ - nk_zero_struct(pan); - panel_padding = nk_panel_get_padding(&ctx->style, NK_PANEL_GROUP); - pan.bounds.y = g->bounds.y - (g->header_height + g->menu.h); - pan.bounds.x = g->bounds.x - panel_padding.x; - pan.bounds.w = g->bounds.w + 2 * panel_padding.x; - pan.bounds.h = g->bounds.h + g->header_height + g->menu.h; - if (g->flags & NK_WINDOW_BORDER) { - pan.bounds.x -= g->border; - pan.bounds.y -= g->border; - pan.bounds.w += 2*g->border; - pan.bounds.h += 2*g->border; - } - if (!(g->flags & NK_WINDOW_NO_SCROLLBAR)) { - pan.bounds.w += ctx->style.window.scrollbar_size.x; - pan.bounds.h += ctx->style.window.scrollbar_size.y; - } - pan.scrollbar.x = *g->offset_x; - pan.scrollbar.y = *g->offset_y; - pan.flags = g->flags; - pan.buffer = win->buffer; - pan.layout = g; - pan.parent = win; - ctx->current = &pan; - - /* make sure group has correct clipping rectangle */ - nk_unify(&clip, &parent->clip, pan.bounds.x, pan.bounds.y, - pan.bounds.x + pan.bounds.w, pan.bounds.y + pan.bounds.h + panel_padding.x); - nk_push_scissor(&pan.buffer, clip); - nk_end(ctx); - - win->buffer = pan.buffer; - nk_push_scissor(&win->buffer, parent->clip); - ctx->current = win; - win->layout = parent; - g->bounds = pan.bounds; - return; -} - -NK_API int -nk_group_scrolled_begin(struct nk_context *ctx, - struct nk_scroll *scroll, const char *title, nk_flags flags) -{return nk_group_scrolled_offset_begin(ctx, &scroll->x, &scroll->y, title, flags);} - -NK_API int -nk_group_begin(struct nk_context *ctx, const char *title, nk_flags flags) -{ - int title_len; - nk_hash title_hash; - struct nk_window *win; - nk_uint *x_offset; - nk_uint *y_offset; - - NK_ASSERT(ctx); - NK_ASSERT(title); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout || !title) - return 0; - - /* find persistent group scrollbar value */ - win = ctx->current; - title_len = (int)nk_strlen(title); - title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP); - x_offset = nk_find_value(win, title_hash); - if (!x_offset) { - x_offset = nk_add_value(ctx, win, title_hash, 0); - y_offset = nk_add_value(ctx, win, title_hash+1, 0); - - NK_ASSERT(x_offset); - NK_ASSERT(y_offset); - if (!x_offset || !y_offset) return 0; - *x_offset = *y_offset = 0; - } else y_offset = nk_find_value(win, title_hash+1); - return nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); -} - -NK_API void -nk_group_end(struct nk_context *ctx) -{nk_group_scrolled_end(ctx);} - -NK_API int -nk_list_view_begin(struct nk_context *ctx, struct nk_list_view *view, - const char *title, nk_flags flags, int row_height, int row_count) -{ - int title_len; - nk_hash title_hash; - nk_uint *x_offset; - nk_uint *y_offset; - - int result; - struct nk_window *win; - struct nk_panel *layout; - const struct nk_style *style; - struct nk_vec2 item_spacing; - - NK_ASSERT(ctx); - NK_ASSERT(view); - NK_ASSERT(title); - if (!ctx || !view || !title) return 0; - - win = ctx->current; - style = &ctx->style; - item_spacing = style->window.spacing; - row_height += NK_MAX(0, (int)item_spacing.y); - - /* find persistent list view scrollbar offset */ - title_len = (int)nk_strlen(title); - title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_GROUP); - x_offset = nk_find_value(win, title_hash); - if (!x_offset) { - x_offset = nk_add_value(ctx, win, title_hash, 0); - y_offset = nk_add_value(ctx, win, title_hash+1, 0); - - NK_ASSERT(x_offset); - NK_ASSERT(y_offset); - if (!x_offset || !y_offset) return 0; - *x_offset = *y_offset = 0; - } else y_offset = nk_find_value(win, title_hash+1); - view->scroll_value = *y_offset; - view->scroll_pointer = y_offset; - - *y_offset = 0; - result = nk_group_scrolled_offset_begin(ctx, x_offset, y_offset, title, flags); - win = ctx->current; - layout = win->layout; - - view->total_height = row_height * NK_MAX(row_count,1); - view->begin = (int)NK_MAX((view->scroll_value / (float)row_height), 0.0f); - view->count = (int)NK_MAX(nk_iceilf((layout->clip.h)/(float)row_height), 0); - view->end = view->begin + view->count; - view->ctx = ctx; - return result; -} - -NK_API void -nk_list_view_end(struct nk_list_view *view) -{ - struct nk_context *ctx; - struct nk_window *win; - struct nk_panel *layout; - - NK_ASSERT(view); - NK_ASSERT(view->ctx); - NK_ASSERT(view->scroll_pointer); - if (!view || !view->ctx) return; - - ctx = view->ctx; - win = ctx->current; - layout = win->layout; - layout->at_y = layout->bounds.y + (float)view->total_height; - *view->scroll_pointer = *view->scroll_pointer + view->scroll_value; - nk_group_end(view->ctx); -} - -/* -------------------------------------------------------------- - * - * POPUP - * - * --------------------------------------------------------------*/ -NK_API int -nk_popup_begin(struct nk_context *ctx, enum nk_popup_type type, - const char *title, nk_flags flags, struct nk_rect rect) -{ - struct nk_window *popup; - struct nk_window *win; - struct nk_panel *panel; - - int title_len; - nk_hash title_hash; - nk_size allocated; - - NK_ASSERT(ctx); - NK_ASSERT(title); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - panel = win->layout; - NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP) && "popups are not allowed to have popups"); - title_len = (int)nk_strlen(title); - title_hash = nk_murmur_hash(title, (int)title_len, NK_PANEL_POPUP); - - popup = win->popup.win; - if (!popup) { - popup = (struct nk_window*)nk_create_window(ctx); - popup->parent = win; - win->popup.win = popup; - win->popup.active = 0; - win->popup.type = NK_PANEL_POPUP; - } - - /* make sure we have to correct popup */ - if (win->popup.name != title_hash) { - if (!win->popup.active) { - nk_zero(popup, sizeof(*popup)); - win->popup.name = title_hash; - win->popup.active = 1; - win->popup.type = NK_PANEL_POPUP; - } else return 0; - } - - /* popup position is local to window */ - ctx->current = popup; - rect.x += win->layout->clip.x; - rect.y += win->layout->clip.y; - - /* setup popup data */ - popup->parent = win; - popup->bounds = rect; - popup->seq = ctx->seq; - popup->layout = (struct nk_panel*)nk_create_panel(ctx); - popup->flags = flags; - popup->flags |= NK_WINDOW_BORDER; - if (type == NK_POPUP_DYNAMIC) - popup->flags |= NK_WINDOW_DYNAMIC; - - popup->buffer = win->buffer; - nk_start_popup(ctx, win); - allocated = ctx->memory.allocated; - nk_push_scissor(&popup->buffer, nk_null_rect); - - if (nk_panel_begin(ctx, title, NK_PANEL_POPUP)) { - /* popup is running therefore invalidate parent panels */ - struct nk_panel *root; - root = win->layout; - while (root) { - root->flags |= NK_WINDOW_ROM; - root->flags &= ~(nk_flags)NK_WINDOW_REMOVE_ROM; - root = root->parent; - } - win->popup.active = 1; - popup->layout->offset_x = &popup->scrollbar.x; - popup->layout->offset_y = &popup->scrollbar.y; - popup->layout->parent = win->layout; - return 1; - } else { - /* popup was closed/is invalid so cleanup */ - struct nk_panel *root; - root = win->layout; - while (root) { - root->flags |= NK_WINDOW_REMOVE_ROM; - root = root->parent; - } - win->layout->popup_buffer.active = 0; - win->popup.active = 0; - ctx->memory.allocated = allocated; - ctx->current = win; - nk_free_panel(ctx, popup->layout); - popup->layout = 0; - return 0; - } -} - -NK_INTERN int -nk_nonblock_begin(struct nk_context *ctx, - nk_flags flags, struct nk_rect body, struct nk_rect header, - enum nk_panel_type panel_type) -{ - struct nk_window *popup; - struct nk_window *win; - struct nk_panel *panel; - int is_active = nk_true; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - /* popups cannot have popups */ - win = ctx->current; - panel = win->layout; - NK_ASSERT(!(panel->type & NK_PANEL_SET_POPUP)); - popup = win->popup.win; - if (!popup) { - /* create window for nonblocking popup */ - popup = (struct nk_window*)nk_create_window(ctx); - popup->parent = win; - win->popup.win = popup; - win->popup.type = panel_type; - nk_command_buffer_init(&popup->buffer, &ctx->memory, NK_CLIPPING_ON); - } else { - /* close the popup if user pressed outside or in the header */ - int pressed, in_body, in_header; - pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); - in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); - in_header = nk_input_is_mouse_hovering_rect(&ctx->input, header); - if (pressed && (!in_body || in_header)) - is_active = nk_false; - } - win->popup.header = header; - - if (!is_active) { - /* remove read only mode from all parent panels */ - struct nk_panel *root; - root = win->layout; - while (root) { - root->flags |= NK_WINDOW_REMOVE_ROM; - root = root->parent; - } - return is_active; - } - - popup->bounds = body; - popup->parent = win; - popup->layout = (struct nk_panel*)nk_create_panel(ctx); - popup->flags = flags; - popup->flags |= NK_WINDOW_BORDER; - popup->flags |= NK_WINDOW_DYNAMIC; - popup->seq = ctx->seq; - win->popup.active = 1; - NK_ASSERT(popup->layout); - - nk_start_popup(ctx, win); - popup->buffer = win->buffer; - nk_push_scissor(&popup->buffer, nk_null_rect); - ctx->current = popup; - - nk_panel_begin(ctx, 0, panel_type); - win->buffer = popup->buffer; - popup->layout->parent = win->layout; - popup->layout->offset_x = &popup->scrollbar.x; - popup->layout->offset_y = &popup->scrollbar.y; - - /* set read only mode to all parent panels */ - {struct nk_panel *root; - root = win->layout; - while (root) { - root->flags |= NK_WINDOW_ROM; - root = root->parent; - }} - return is_active; -} - -NK_API void -nk_popup_close(struct nk_context *ctx) -{ - struct nk_window *popup; - NK_ASSERT(ctx); - if (!ctx || !ctx->current) return; - - popup = ctx->current; - NK_ASSERT(popup->parent); - NK_ASSERT(popup->layout->type & NK_PANEL_SET_POPUP); - popup->flags |= NK_WINDOW_HIDDEN; -} - -NK_API void -nk_popup_end(struct nk_context *ctx) -{ - struct nk_window *win; - struct nk_window *popup; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return; - - popup = ctx->current; - if (!popup->parent) return; - win = popup->parent; - if (popup->flags & NK_WINDOW_HIDDEN) { - struct nk_panel *root; - root = win->layout; - while (root) { - root->flags |= NK_WINDOW_REMOVE_ROM; - root = root->parent; - } - win->popup.active = 0; - } - nk_push_scissor(&popup->buffer, nk_null_rect); - nk_end(ctx); - - win->buffer = popup->buffer; - nk_finish_popup(ctx, win); - ctx->current = win; - nk_push_scissor(&win->buffer, win->layout->clip); -} -/* ------------------------------------------------------------- - * - * TOOLTIP - * - * -------------------------------------------------------------- */ -NK_API int -nk_tooltip_begin(struct nk_context *ctx, float width) -{ - struct nk_window *win; - const struct nk_input *in; - struct nk_rect bounds; - int ret; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - /* make sure that no nonblocking popup is currently active */ - win = ctx->current; - in = &ctx->input; - if (win->popup.win && (win->popup.type & NK_PANEL_SET_NONBLOCK)) - return 0; - - bounds.w = width; - bounds.h = nk_null_rect.h; - bounds.x = (in->mouse.pos.x + 1) - win->layout->clip.x; - bounds.y = (in->mouse.pos.y + 1) - win->layout->clip.y; - - ret = nk_popup_begin(ctx, NK_POPUP_DYNAMIC, - "__##Tooltip##__", NK_WINDOW_NO_SCROLLBAR|NK_WINDOW_BORDER, bounds); - if (ret) win->layout->flags &= ~(nk_flags)NK_WINDOW_ROM; - win->popup.type = NK_PANEL_TOOLTIP; - ctx->current->layout->type = NK_PANEL_TOOLTIP; - return ret; -} - -NK_API void -nk_tooltip_end(struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return; - ctx->current->seq--; - nk_popup_close(ctx); - nk_popup_end(ctx); -} - -NK_API void -nk_tooltip(struct nk_context *ctx, const char *text) -{ - const struct nk_style *style; - struct nk_vec2 padding; - - int text_len; - float text_width; - float text_height; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - NK_ASSERT(text); - if (!ctx || !ctx->current || !ctx->current->layout || !text) - return; - - /* fetch configuration data */ - style = &ctx->style; - padding = style->window.padding; - - /* calculate size of the text and tooltip */ - text_len = nk_strlen(text); - text_width = style->font->width(style->font->userdata, - style->font->height, text, text_len); - text_width += (4 * padding.x); - text_height = (style->font->height + 2 * padding.y); - - /* execute tooltip and fill with text */ - if (nk_tooltip_begin(ctx, (float)text_width)) { - nk_layout_row_dynamic(ctx, (float)text_height, 1); - nk_text(ctx, text, text_len, NK_TEXT_LEFT); - nk_tooltip_end(ctx); - } -} -/* ------------------------------------------------------------- - * - * CONTEXTUAL - * - * -------------------------------------------------------------- */ -NK_API int -nk_contextual_begin(struct nk_context *ctx, nk_flags flags, struct nk_vec2 size, - struct nk_rect trigger_bounds) -{ - struct nk_window *win; - struct nk_window *popup; - struct nk_rect body; - - NK_STORAGE const struct nk_rect null_rect = {0,0,0,0}; - int is_clicked = 0; - int is_active = 0; - int is_open = 0; - int ret = 0; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - ++win->popup.con_count; - - /* check if currently active contextual is active */ - popup = win->popup.win; - is_open = (popup && win->popup.type == NK_PANEL_CONTEXTUAL); - is_clicked = nk_input_mouse_clicked(&ctx->input, NK_BUTTON_RIGHT, trigger_bounds); - if (win->popup.active_con && win->popup.con_count != win->popup.active_con) - return 0; - if ((is_clicked && is_open && !is_active) || (!is_open && !is_active && !is_clicked)) - return 0; - - /* calculate contextual position on click */ - win->popup.active_con = win->popup.con_count; - if (is_clicked) { - body.x = ctx->input.mouse.pos.x; - body.y = ctx->input.mouse.pos.y; - } else { - body.x = popup->bounds.x; - body.y = popup->bounds.y; - } - body.w = size.x; - body.h = size.y; - - /* start nonblocking contextual popup */ - ret = nk_nonblock_begin(ctx, flags|NK_WINDOW_NO_SCROLLBAR, body, - null_rect, NK_PANEL_CONTEXTUAL); - if (ret) win->popup.type = NK_PANEL_CONTEXTUAL; - else { - win->popup.active_con = 0; - if (win->popup.win) - win->popup.win->flags = 0; - } - return ret; -} - -NK_API int -nk_contextual_item_text(struct nk_context *ctx, const char *text, int len, - nk_flags alignment) -{ - struct nk_window *win; - const struct nk_input *in; - const struct nk_style *style; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - style = &ctx->style; - state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); - if (!state) return nk_false; - - in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, bounds, - text, len, alignment, NK_BUTTON_DEFAULT, &style->contextual_button, in, style->font)) { - nk_contextual_close(ctx); - return nk_true; - } - return nk_false; -} - -NK_API int nk_contextual_item_label(struct nk_context *ctx, const char *label, nk_flags align) -{return nk_contextual_item_text(ctx, label, nk_strlen(label), align);} - -NK_API int -nk_contextual_item_image_text(struct nk_context *ctx, struct nk_image img, - const char *text, int len, nk_flags align) -{ - struct nk_window *win; - const struct nk_input *in; - const struct nk_style *style; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - style = &ctx->style; - state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); - if (!state) return nk_false; - - in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, bounds, - img, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)){ - nk_contextual_close(ctx); - return nk_true; - } - return nk_false; -} - -NK_API int nk_contextual_item_image_label(struct nk_context *ctx, struct nk_image img, - const char *label, nk_flags align) -{return nk_contextual_item_image_text(ctx, img, label, nk_strlen(label), align);} - -NK_API int -nk_contextual_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type symbol, - const char *text, int len, nk_flags align) -{ - struct nk_window *win; - const struct nk_input *in; - const struct nk_style *style; - - struct nk_rect bounds; - enum nk_widget_layout_states state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - style = &ctx->style; - state = nk_widget_fitting(&bounds, ctx, style->contextual_button.padding); - if (!state) return nk_false; - - in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, bounds, - symbol, text, len, align, NK_BUTTON_DEFAULT, &style->contextual_button, style->font, in)) { - nk_contextual_close(ctx); - return nk_true; - } - return nk_false; -} - -NK_API int nk_contextual_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type symbol, - const char *text, nk_flags align) -{return nk_contextual_item_symbol_text(ctx, symbol, text, nk_strlen(text), align);} - -NK_API void -nk_contextual_close(struct nk_context *ctx) -{ - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) return; - nk_popup_close(ctx); -} - -NK_API void -nk_contextual_end(struct nk_context *ctx) -{ - struct nk_window *popup; - struct nk_panel *panel; - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - if (!ctx || !ctx->current) return; - - popup = ctx->current; - panel = popup->layout; - NK_ASSERT(popup->parent); - NK_ASSERT(panel->type & NK_PANEL_SET_POPUP); - if (panel->flags & NK_WINDOW_DYNAMIC) { - /* Close behavior - This is a bit hack solution since we do not now before we end our popup - how big it will be. We therefore do not directly know when a - click outside the non-blocking popup must close it at that direct frame. - Instead it will be closed in the next frame.*/ - struct nk_rect body = {0,0,0,0}; - if (panel->at_y < (panel->bounds.y + panel->bounds.h)) { - struct nk_vec2 padding = nk_panel_get_padding(&ctx->style, panel->type); - body = panel->bounds; - body.y = (panel->at_y + panel->footer_height + panel->border + padding.y + panel->row.height); - body.h = (panel->bounds.y + panel->bounds.h) - body.y; - } - - {int pressed = nk_input_is_mouse_pressed(&ctx->input, NK_BUTTON_LEFT); - int in_body = nk_input_is_mouse_hovering_rect(&ctx->input, body); - if (pressed && in_body) - popup->flags |= NK_WINDOW_HIDDEN; - } - } - if (popup->flags & NK_WINDOW_HIDDEN) - popup->seq = 0; - nk_popup_end(ctx); - return; -} -/* ------------------------------------------------------------- - * - * COMBO - * - * --------------------------------------------------------------*/ -NK_INTERN int -nk_combo_begin(struct nk_context *ctx, struct nk_window *win, - struct nk_vec2 size, int is_clicked, struct nk_rect header) -{ - struct nk_window *popup; - int is_open = 0; - int is_active = 0; - struct nk_rect body; - nk_hash hash; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - popup = win->popup.win; - body.x = header.x; - body.w = size.x; - body.y = header.y + header.h-ctx->style.window.combo_border; - body.h = size.y; - - hash = win->popup.combo_count++; - is_open = (popup) ? nk_true:nk_false; - is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_COMBO); - if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || - (!is_open && !is_active && !is_clicked)) return 0; - if (!nk_nonblock_begin(ctx, 0, body, - (is_clicked && is_open)?nk_rect(0,0,0,0):header, NK_PANEL_COMBO)) return 0; - - win->popup.type = NK_PANEL_COMBO; - win->popup.name = hash; - return 1; -} - -NK_API int -nk_combo_begin_text(struct nk_context *ctx, const char *selected, int len, - struct nk_vec2 size) -{ - const struct nk_input *in; - struct nk_window *win; - struct nk_style *style; - - enum nk_widget_layout_states s; - int is_clicked = nk_false; - struct nk_rect header; - const struct nk_style_item *background; - struct nk_text text; - - NK_ASSERT(ctx); - NK_ASSERT(selected); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout || !selected) - return 0; - - win = ctx->current; - style = &ctx->style; - s = nk_widget(&header, ctx); - if (s == NK_WIDGET_INVALID) - return 0; - - in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; - if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) - is_clicked = nk_true; - - /* draw combo box header background and border */ - if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { - background = &style->combo.active; - text.text = style->combo.label_active; - } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { - background = &style->combo.hover; - text.text = style->combo.label_hover; - } else { - background = &style->combo.normal; - text.text = style->combo.label_normal; - } - if (background->type == NK_STYLE_ITEM_IMAGE) { - text.background = nk_rgba(0,0,0,0); - nk_draw_image(&win->buffer, header, &background->data.image, nk_white); - } else { - text.background = background->data.color; - nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); - nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); - } - { - /* print currently selected text item */ - struct nk_rect label; - struct nk_rect button; - struct nk_rect content; - - enum nk_symbol_type sym; - if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) - sym = style->combo.sym_hover; - else if (is_clicked) - sym = style->combo.sym_active; - else sym = style->combo.sym_normal; - - /* calculate button */ - button.w = header.h - 2 * style->combo.button_padding.y; - button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; - button.y = header.y + style->combo.button_padding.y; - button.h = button.w; - - content.x = button.x + style->combo.button.padding.x; - content.y = button.y + style->combo.button.padding.y; - content.w = button.w - 2 * style->combo.button.padding.x; - content.h = button.h - 2 * style->combo.button.padding.y; - - /* draw selected label */ - text.padding = nk_vec2(0,0); - label.x = header.x + style->combo.content_padding.x; - label.y = header.y + style->combo.content_padding.y; - label.w = button.x - (style->combo.content_padding.x + style->combo.spacing.x) - label.x;; - label.h = header.h - 2 * style->combo.content_padding.y; - nk_widget_text(&win->buffer, label, selected, len, &text, - NK_TEXT_LEFT, ctx->style.font); - - /* draw open/close button */ - nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, - &ctx->style.combo.button, sym, style->font); - } - return nk_combo_begin(ctx, win, size, is_clicked, header); -} - -NK_API int nk_combo_begin_label(struct nk_context *ctx, const char *selected, struct nk_vec2 size) -{return nk_combo_begin_text(ctx, selected, nk_strlen(selected), size);} - -NK_API int -nk_combo_begin_color(struct nk_context *ctx, struct nk_color color, struct nk_vec2 size) -{ - struct nk_window *win; - struct nk_style *style; - const struct nk_input *in; - - struct nk_rect header; - int is_clicked = nk_false; - enum nk_widget_layout_states s; - const struct nk_style_item *background; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - style = &ctx->style; - s = nk_widget(&header, ctx); - if (s == NK_WIDGET_INVALID) - return 0; - - in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; - if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) - is_clicked = nk_true; - - /* draw combo box header background and border */ - if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) - background = &style->combo.active; - else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) - background = &style->combo.hover; - else background = &style->combo.normal; - - if (background->type == NK_STYLE_ITEM_IMAGE) { - nk_draw_image(&win->buffer, header, &background->data.image,nk_white); - } else { - nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); - nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); - } - { - struct nk_rect content; - struct nk_rect button; - struct nk_rect bounds; - - enum nk_symbol_type sym; - if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) - sym = style->combo.sym_hover; - else if (is_clicked) - sym = style->combo.sym_active; - else sym = style->combo.sym_normal; - - /* calculate button */ - button.w = header.h - 2 * style->combo.button_padding.y; - button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; - button.y = header.y + style->combo.button_padding.y; - button.h = button.w; - - content.x = button.x + style->combo.button.padding.x; - content.y = button.y + style->combo.button.padding.y; - content.w = button.w - 2 * style->combo.button.padding.x; - content.h = button.h - 2 * style->combo.button.padding.y; - - /* draw color */ - bounds.h = header.h - 4 * style->combo.content_padding.y; - bounds.y = header.y + 2 * style->combo.content_padding.y; - bounds.x = header.x + 2 * style->combo.content_padding.x; - bounds.w = (button.x - (style->combo.content_padding.x + style->combo.spacing.x)) - bounds.x; - nk_fill_rect(&win->buffer, bounds, 0, color); - - /* draw open/close button */ - nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, - &ctx->style.combo.button, sym, style->font); - } - return nk_combo_begin(ctx, win, size, is_clicked, header); -} - -NK_API int -nk_combo_begin_symbol(struct nk_context *ctx, enum nk_symbol_type symbol, struct nk_vec2 size) -{ - struct nk_window *win; - struct nk_style *style; - const struct nk_input *in; - - struct nk_rect header; - int is_clicked = nk_false; - enum nk_widget_layout_states s; - const struct nk_style_item *background; - struct nk_color sym_background; - struct nk_color symbol_color; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - style = &ctx->style; - s = nk_widget(&header, ctx); - if (s == NK_WIDGET_INVALID) - return 0; - - in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; - if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) - is_clicked = nk_true; - - /* draw combo box header background and border */ - if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { - background = &style->combo.active; - symbol_color = style->combo.symbol_active; - } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { - background = &style->combo.hover; - symbol_color = style->combo.symbol_hover; - } else { - background = &style->combo.normal; - symbol_color = style->combo.symbol_hover; - } - - if (background->type == NK_STYLE_ITEM_IMAGE) { - sym_background = nk_rgba(0,0,0,0); - nk_draw_image(&win->buffer, header, &background->data.image, nk_white); - } else { - sym_background = background->data.color; - nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); - nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); - } - { - struct nk_rect bounds = {0,0,0,0}; - struct nk_rect content; - struct nk_rect button; - - enum nk_symbol_type sym; - if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) - sym = style->combo.sym_hover; - else if (is_clicked) - sym = style->combo.sym_active; - else sym = style->combo.sym_normal; - - /* calculate button */ - button.w = header.h - 2 * style->combo.button_padding.y; - button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; - button.y = header.y + style->combo.button_padding.y; - button.h = button.w; - - content.x = button.x + style->combo.button.padding.x; - content.y = button.y + style->combo.button.padding.y; - content.w = button.w - 2 * style->combo.button.padding.x; - content.h = button.h - 2 * style->combo.button.padding.y; - - /* draw symbol */ - bounds.h = header.h - 2 * style->combo.content_padding.y; - bounds.y = header.y + style->combo.content_padding.y; - bounds.x = header.x + style->combo.content_padding.x; - bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; - nk_draw_symbol(&win->buffer, symbol, bounds, sym_background, symbol_color, - 1.0f, style->font); - - /* draw open/close button */ - nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, - &ctx->style.combo.button, sym, style->font); - } - return nk_combo_begin(ctx, win, size, is_clicked, header); -} - -NK_API int -nk_combo_begin_symbol_text(struct nk_context *ctx, const char *selected, int len, - enum nk_symbol_type symbol, struct nk_vec2 size) -{ - struct nk_window *win; - struct nk_style *style; - struct nk_input *in; - - struct nk_rect header; - int is_clicked = nk_false; - enum nk_widget_layout_states s; - const struct nk_style_item *background; - struct nk_color symbol_color; - struct nk_text text; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - style = &ctx->style; - s = nk_widget(&header, ctx); - if (!s) return 0; - - in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; - if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) - is_clicked = nk_true; - - /* draw combo box header background and border */ - if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { - background = &style->combo.active; - symbol_color = style->combo.symbol_active; - text.text = style->combo.label_active; - } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { - background = &style->combo.hover; - symbol_color = style->combo.symbol_hover; - text.text = style->combo.label_hover; - } else { - background = &style->combo.normal; - symbol_color = style->combo.symbol_normal; - text.text = style->combo.label_normal; - } - if (background->type == NK_STYLE_ITEM_IMAGE) { - text.background = nk_rgba(0,0,0,0); - nk_draw_image(&win->buffer, header, &background->data.image, nk_white); - } else { - text.background = background->data.color; - nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); - nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); - } - { - struct nk_rect content; - struct nk_rect button; - struct nk_rect label; - struct nk_rect image; - - enum nk_symbol_type sym; - if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) - sym = style->combo.sym_hover; - else if (is_clicked) - sym = style->combo.sym_active; - else sym = style->combo.sym_normal; - - /* calculate button */ - button.w = header.h - 2 * style->combo.button_padding.y; - button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; - button.y = header.y + style->combo.button_padding.y; - button.h = button.w; - - content.x = button.x + style->combo.button.padding.x; - content.y = button.y + style->combo.button.padding.y; - content.w = button.w - 2 * style->combo.button.padding.x; - content.h = button.h - 2 * style->combo.button.padding.y; - nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, - &ctx->style.combo.button, sym, style->font); - - /* draw symbol */ - image.x = header.x + style->combo.content_padding.x; - image.y = header.y + style->combo.content_padding.y; - image.h = header.h - 2 * style->combo.content_padding.y; - image.w = image.h; - nk_draw_symbol(&win->buffer, symbol, image, text.background, symbol_color, - 1.0f, style->font); - - /* draw label */ - text.padding = nk_vec2(0,0); - label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; - label.y = header.y + style->combo.content_padding.y; - label.w = (button.x - style->combo.content_padding.x) - label.x; - label.h = header.h - 2 * style->combo.content_padding.y; - nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); - } - return nk_combo_begin(ctx, win, size, is_clicked, header); -} - -NK_API int -nk_combo_begin_image(struct nk_context *ctx, struct nk_image img, struct nk_vec2 size) -{ - struct nk_window *win; - struct nk_style *style; - const struct nk_input *in; - - struct nk_rect header; - int is_clicked = nk_false; - enum nk_widget_layout_states s; - const struct nk_style_item *background; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - style = &ctx->style; - s = nk_widget(&header, ctx); - if (s == NK_WIDGET_INVALID) - return 0; - - in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; - if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) - is_clicked = nk_true; - - /* draw combo box header background and border */ - if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) - background = &style->combo.active; - else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) - background = &style->combo.hover; - else background = &style->combo.normal; - - if (background->type == NK_STYLE_ITEM_IMAGE) { - nk_draw_image(&win->buffer, header, &background->data.image, nk_white); - } else { - nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); - nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); - } - { - struct nk_rect bounds = {0,0,0,0}; - struct nk_rect content; - struct nk_rect button; - - enum nk_symbol_type sym; - if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) - sym = style->combo.sym_hover; - else if (is_clicked) - sym = style->combo.sym_active; - else sym = style->combo.sym_normal; - - /* calculate button */ - button.w = header.h - 2 * style->combo.button_padding.y; - button.x = (header.x + header.w - header.h) - style->combo.button_padding.y; - button.y = header.y + style->combo.button_padding.y; - button.h = button.w; - - content.x = button.x + style->combo.button.padding.x; - content.y = button.y + style->combo.button.padding.y; - content.w = button.w - 2 * style->combo.button.padding.x; - content.h = button.h - 2 * style->combo.button.padding.y; - - /* draw image */ - bounds.h = header.h - 2 * style->combo.content_padding.y; - bounds.y = header.y + style->combo.content_padding.y; - bounds.x = header.x + style->combo.content_padding.x; - bounds.w = (button.x - style->combo.content_padding.y) - bounds.x; - nk_draw_image(&win->buffer, bounds, &img, nk_white); - - /* draw open/close button */ - nk_draw_button_symbol(&win->buffer, &bounds, &content, ctx->last_widget_state, - &ctx->style.combo.button, sym, style->font); - } - return nk_combo_begin(ctx, win, size, is_clicked, header); -} - -NK_API int -nk_combo_begin_image_text(struct nk_context *ctx, const char *selected, int len, - struct nk_image img, struct nk_vec2 size) -{ - struct nk_window *win; - struct nk_style *style; - struct nk_input *in; - - struct nk_rect header; - int is_clicked = nk_false; - enum nk_widget_layout_states s; - const struct nk_style_item *background; - struct nk_text text; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - style = &ctx->style; - s = nk_widget(&header, ctx); - if (!s) return 0; - - in = (win->layout->flags & NK_WINDOW_ROM || s == NK_WIDGET_ROM)? 0: &ctx->input; - if (nk_button_behavior(&ctx->last_widget_state, header, in, NK_BUTTON_DEFAULT)) - is_clicked = nk_true; - - /* draw combo box header background and border */ - if (ctx->last_widget_state & NK_WIDGET_STATE_ACTIVED) { - background = &style->combo.active; - text.text = style->combo.label_active; - } else if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) { - background = &style->combo.hover; - text.text = style->combo.label_hover; - } else { - background = &style->combo.normal; - text.text = style->combo.label_normal; - } - if (background->type == NK_STYLE_ITEM_IMAGE) { - text.background = nk_rgba(0,0,0,0); - nk_draw_image(&win->buffer, header, &background->data.image, nk_white); - } else { - text.background = background->data.color; - nk_fill_rect(&win->buffer, header, style->combo.rounding, background->data.color); - nk_stroke_rect(&win->buffer, header, style->combo.rounding, style->combo.border, style->combo.border_color); - } - { - struct nk_rect content; - struct nk_rect button; - struct nk_rect label; - struct nk_rect image; - - enum nk_symbol_type sym; - if (ctx->last_widget_state & NK_WIDGET_STATE_HOVER) - sym = style->combo.sym_hover; - else if (is_clicked) - sym = style->combo.sym_active; - else sym = style->combo.sym_normal; - - /* calculate button */ - button.w = header.h - 2 * style->combo.button_padding.y; - button.x = (header.x + header.w - header.h) - style->combo.button_padding.x; - button.y = header.y + style->combo.button_padding.y; - button.h = button.w; - - content.x = button.x + style->combo.button.padding.x; - content.y = button.y + style->combo.button.padding.y; - content.w = button.w - 2 * style->combo.button.padding.x; - content.h = button.h - 2 * style->combo.button.padding.y; - nk_draw_button_symbol(&win->buffer, &button, &content, ctx->last_widget_state, - &ctx->style.combo.button, sym, style->font); - - /* draw image */ - image.x = header.x + style->combo.content_padding.x; - image.y = header.y + style->combo.content_padding.y; - image.h = header.h - 2 * style->combo.content_padding.y; - image.w = image.h; - nk_draw_image(&win->buffer, image, &img, nk_white); - - /* draw label */ - text.padding = nk_vec2(0,0); - label.x = image.x + image.w + style->combo.spacing.x + style->combo.content_padding.x; - label.y = header.y + style->combo.content_padding.y; - label.w = (button.x - style->combo.content_padding.x) - label.x; - label.h = header.h - 2 * style->combo.content_padding.y; - nk_widget_text(&win->buffer, label, selected, len, &text, NK_TEXT_LEFT, style->font); - } - return nk_combo_begin(ctx, win, size, is_clicked, header); -} - -NK_API int nk_combo_begin_symbol_label(struct nk_context *ctx, - const char *selected, enum nk_symbol_type type, struct nk_vec2 size) -{return nk_combo_begin_symbol_text(ctx, selected, nk_strlen(selected), type, size);} - -NK_API int nk_combo_begin_image_label(struct nk_context *ctx, - const char *selected, struct nk_image img, struct nk_vec2 size) -{return nk_combo_begin_image_text(ctx, selected, nk_strlen(selected), img, size);} - -NK_API int nk_combo_item_text(struct nk_context *ctx, const char *text, int len,nk_flags align) -{return nk_contextual_item_text(ctx, text, len, align);} - -NK_API int nk_combo_item_label(struct nk_context *ctx, const char *label, nk_flags align) -{return nk_contextual_item_label(ctx, label, align);} - -NK_API int nk_combo_item_image_text(struct nk_context *ctx, struct nk_image img, const char *text, - int len, nk_flags alignment) -{return nk_contextual_item_image_text(ctx, img, text, len, alignment);} - -NK_API int nk_combo_item_image_label(struct nk_context *ctx, struct nk_image img, - const char *text, nk_flags alignment) -{return nk_contextual_item_image_label(ctx, img, text, alignment);} - -NK_API int nk_combo_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, - const char *text, int len, nk_flags alignment) -{return nk_contextual_item_symbol_text(ctx, sym, text, len, alignment);} - -NK_API int nk_combo_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, - const char *label, nk_flags alignment) -{return nk_contextual_item_symbol_label(ctx, sym, label, alignment);} - -NK_API void nk_combo_end(struct nk_context *ctx) -{nk_contextual_end(ctx);} - -NK_API void nk_combo_close(struct nk_context *ctx) -{nk_contextual_close(ctx);} - -NK_API int -nk_combo(struct nk_context *ctx, const char **items, int count, - int selected, int item_height, struct nk_vec2 size) -{ - int i = 0; - int max_height; - struct nk_vec2 item_spacing; - struct nk_vec2 window_padding; - - NK_ASSERT(ctx); - NK_ASSERT(items); - NK_ASSERT(ctx->current); - if (!ctx || !items ||!count) - return selected; - - item_spacing = ctx->style.window.spacing; - window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); - max_height = count * item_height + count * (int)item_spacing.y; - max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; - size.y = NK_MIN(size.y, (float)max_height); - if (nk_combo_begin_label(ctx, items[selected], size)) { - nk_layout_row_dynamic(ctx, (float)item_height, 1); - for (i = 0; i < count; ++i) { - if (nk_combo_item_label(ctx, items[i], NK_TEXT_LEFT)) - selected = i; - } - nk_combo_end(ctx); - } - return selected; -} - -NK_API int -nk_combo_separator(struct nk_context *ctx, const char *items_separated_by_separator, - int separator, int selected, int count, int item_height, struct nk_vec2 size) -{ - int i; - int max_height; - struct nk_vec2 item_spacing; - struct nk_vec2 window_padding; - const char *current_item; - const char *iter; - int length = 0; - - NK_ASSERT(ctx); - NK_ASSERT(items_separated_by_separator); - if (!ctx || !items_separated_by_separator) - return selected; - - /* calculate popup window */ - item_spacing = ctx->style.window.spacing; - window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); - max_height = count * item_height + count * (int)item_spacing.y; - max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; - size.y = NK_MIN(size.y, (float)max_height); - - /* find selected item */ - current_item = items_separated_by_separator; - for (i = 0; i < count; ++i) { - iter = current_item; - while (*iter && *iter != separator) iter++; - length = (int)(iter - current_item); - if (i == selected) break; - current_item = iter + 1; - } - - if (nk_combo_begin_text(ctx, current_item, length, size)) { - current_item = items_separated_by_separator; - nk_layout_row_dynamic(ctx, (float)item_height, 1); - for (i = 0; i < count; ++i) { - iter = current_item; - while (*iter && *iter != separator) iter++; - length = (int)(iter - current_item); - if (nk_combo_item_text(ctx, current_item, length, NK_TEXT_LEFT)) - selected = i; - current_item = current_item + length + 1; - } - nk_combo_end(ctx); - } - return selected; -} - -NK_API int -nk_combo_string(struct nk_context *ctx, const char *items_separated_by_zeros, - int selected, int count, int item_height, struct nk_vec2 size) -{return nk_combo_separator(ctx, items_separated_by_zeros, '\0', selected, count, item_height, size);} - -NK_API int -nk_combo_callback(struct nk_context *ctx, void(*item_getter)(void*, int, const char**), - void *userdata, int selected, int count, int item_height, struct nk_vec2 size) -{ - int i; - int max_height; - struct nk_vec2 item_spacing; - struct nk_vec2 window_padding; - const char *item; - - NK_ASSERT(ctx); - NK_ASSERT(item_getter); - if (!ctx || !item_getter) - return selected; - - /* calculate popup window */ - item_spacing = ctx->style.window.spacing; - window_padding = nk_panel_get_padding(&ctx->style, ctx->current->layout->type); - max_height = count * item_height + count * (int)item_spacing.y; - max_height += (int)item_spacing.y * 2 + (int)window_padding.y * 2; - size.y = NK_MIN(size.y, (float)max_height); - - item_getter(userdata, selected, &item); - if (nk_combo_begin_label(ctx, item, size)) { - nk_layout_row_dynamic(ctx, (float)item_height, 1); - for (i = 0; i < count; ++i) { - item_getter(userdata, i, &item); - if (nk_combo_item_label(ctx, item, NK_TEXT_LEFT)) - selected = i; - } - nk_combo_end(ctx); - } - return selected; -} - -NK_API void nk_combobox(struct nk_context *ctx, const char **items, int count, - int *selected, int item_height, struct nk_vec2 size) -{*selected = nk_combo(ctx, items, count, *selected, item_height, size);} - -NK_API void nk_combobox_string(struct nk_context *ctx, const char *items_separated_by_zeros, - int *selected, int count, int item_height, struct nk_vec2 size) -{*selected = nk_combo_string(ctx, items_separated_by_zeros, *selected, count, item_height, size);} - -NK_API void nk_combobox_separator(struct nk_context *ctx, const char *items_separated_by_separator, - int separator,int *selected, int count, int item_height, struct nk_vec2 size) -{*selected = nk_combo_separator(ctx, items_separated_by_separator, separator, - *selected, count, item_height, size);} - -NK_API void nk_combobox_callback(struct nk_context *ctx, - void(*item_getter)(void* data, int id, const char **out_text), - void *userdata, int *selected, int count, int item_height, struct nk_vec2 size) -{*selected = nk_combo_callback(ctx, item_getter, userdata, *selected, count, item_height, size);} - -/* - * ------------------------------------------------------------- - * - * MENU - * - * -------------------------------------------------------------- - */ -NK_INTERN int -nk_menu_begin(struct nk_context *ctx, struct nk_window *win, - const char *id, int is_clicked, struct nk_rect header, struct nk_vec2 size) -{ - int is_open = 0; - int is_active = 0; - struct nk_rect body; - struct nk_window *popup; - nk_hash hash = nk_murmur_hash(id, (int)nk_strlen(id), NK_PANEL_MENU); - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - body.x = header.x; - body.w = size.x; - body.y = header.y + header.h; - body.h = size.y; - - popup = win->popup.win; - is_open = popup ? nk_true : nk_false; - is_active = (popup && (win->popup.name == hash) && win->popup.type == NK_PANEL_MENU); - if ((is_clicked && is_open && !is_active) || (is_open && !is_active) || - (!is_open && !is_active && !is_clicked)) return 0; - if (!nk_nonblock_begin(ctx, NK_WINDOW_NO_SCROLLBAR, body, header, NK_PANEL_MENU)) - return 0; - - win->popup.type = NK_PANEL_MENU; - win->popup.name = hash; - return 1; -} - -NK_API int -nk_menu_begin_text(struct nk_context *ctx, const char *title, int len, - nk_flags align, struct nk_vec2 size) -{ - struct nk_window *win; - const struct nk_input *in; - struct nk_rect header; - int is_clicked = nk_false; - nk_flags state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - state = nk_widget(&header, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || win->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - if (nk_do_button_text(&ctx->last_widget_state, &win->buffer, header, - title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) - is_clicked = nk_true; - return nk_menu_begin(ctx, win, title, is_clicked, header, size); -} - -NK_API int nk_menu_begin_label(struct nk_context *ctx, - const char *text, nk_flags align, struct nk_vec2 size) -{return nk_menu_begin_text(ctx, text, nk_strlen(text), align, size);} - -NK_API int -nk_menu_begin_image(struct nk_context *ctx, const char *id, struct nk_image img, - struct nk_vec2 size) -{ - struct nk_window *win; - struct nk_rect header; - const struct nk_input *in; - int is_clicked = nk_false; - nk_flags state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - state = nk_widget(&header, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - if (nk_do_button_image(&ctx->last_widget_state, &win->buffer, header, - img, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in)) - is_clicked = nk_true; - return nk_menu_begin(ctx, win, id, is_clicked, header, size); -} - -NK_API int -nk_menu_begin_symbol(struct nk_context *ctx, const char *id, - enum nk_symbol_type sym, struct nk_vec2 size) -{ - struct nk_window *win; - const struct nk_input *in; - struct nk_rect header; - int is_clicked = nk_false; - nk_flags state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - state = nk_widget(&header, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - if (nk_do_button_symbol(&ctx->last_widget_state, &win->buffer, header, - sym, NK_BUTTON_DEFAULT, &ctx->style.menu_button, in, ctx->style.font)) - is_clicked = nk_true; - return nk_menu_begin(ctx, win, id, is_clicked, header, size); -} - -NK_API int -nk_menu_begin_image_text(struct nk_context *ctx, const char *title, int len, - nk_flags align, struct nk_image img, struct nk_vec2 size) -{ - struct nk_window *win; - struct nk_rect header; - const struct nk_input *in; - int is_clicked = nk_false; - nk_flags state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - state = nk_widget(&header, ctx); - if (!state) return 0; - in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - if (nk_do_button_text_image(&ctx->last_widget_state, &win->buffer, - header, img, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, - ctx->style.font, in)) - is_clicked = nk_true; - return nk_menu_begin(ctx, win, title, is_clicked, header, size); -} - -NK_API int nk_menu_begin_image_label(struct nk_context *ctx, - const char *title, nk_flags align, struct nk_image img, struct nk_vec2 size) -{return nk_menu_begin_image_text(ctx, title, nk_strlen(title), align, img, size);} - -NK_API int -nk_menu_begin_symbol_text(struct nk_context *ctx, const char *title, int len, - nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size) -{ - struct nk_window *win; - struct nk_rect header; - const struct nk_input *in; - int is_clicked = nk_false; - nk_flags state; - - NK_ASSERT(ctx); - NK_ASSERT(ctx->current); - NK_ASSERT(ctx->current->layout); - if (!ctx || !ctx->current || !ctx->current->layout) - return 0; - - win = ctx->current; - state = nk_widget(&header, ctx); - if (!state) return 0; - - in = (state == NK_WIDGET_ROM || win->layout->flags & NK_WINDOW_ROM) ? 0 : &ctx->input; - if (nk_do_button_text_symbol(&ctx->last_widget_state, &win->buffer, - header, sym, title, len, align, NK_BUTTON_DEFAULT, &ctx->style.menu_button, - ctx->style.font, in)) is_clicked = nk_true; - return nk_menu_begin(ctx, win, title, is_clicked, header, size); -} - -NK_API int nk_menu_begin_symbol_label(struct nk_context *ctx, - const char *title, nk_flags align, enum nk_symbol_type sym, struct nk_vec2 size ) -{return nk_menu_begin_symbol_text(ctx, title, nk_strlen(title), align,sym,size);} - -NK_API int nk_menu_item_text(struct nk_context *ctx, const char *title, int len, nk_flags align) -{return nk_contextual_item_text(ctx, title, len, align);} - -NK_API int nk_menu_item_label(struct nk_context *ctx, const char *label, nk_flags align) -{return nk_contextual_item_label(ctx, label, align);} - -NK_API int nk_menu_item_image_label(struct nk_context *ctx, struct nk_image img, - const char *label, nk_flags align) -{return nk_contextual_item_image_label(ctx, img, label, align);} - -NK_API int nk_menu_item_image_text(struct nk_context *ctx, struct nk_image img, - const char *text, int len, nk_flags align) -{return nk_contextual_item_image_text(ctx, img, text, len, align);} - -NK_API int nk_menu_item_symbol_text(struct nk_context *ctx, enum nk_symbol_type sym, - const char *text, int len, nk_flags align) -{return nk_contextual_item_symbol_text(ctx, sym, text, len, align);} - -NK_API int nk_menu_item_symbol_label(struct nk_context *ctx, enum nk_symbol_type sym, - const char *label, nk_flags align) -{return nk_contextual_item_symbol_label(ctx, sym, label, align);} - -NK_API void nk_menu_close(struct nk_context *ctx) -{nk_contextual_close(ctx);} - -NK_API void -nk_menu_end(struct nk_context *ctx) -{nk_contextual_end(ctx);} - -#endif diff --git a/deps/nuklear/package.json b/deps/nuklear/package.json deleted file mode 100644 index edff9246..00000000 --- a/deps/nuklear/package.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "name": "nuklear", - "version": "1.0.0", - "repo": "vurtun/nuklear", - "description": "A small ANSI C gui toolkit", - "keywords": ["gl", "ui", "toolkit"], - "src": ["nuklear.h"] -}