diff options
Diffstat (limited to '3rdparty/imgui/misc')
-rw-r--r-- | 3rdparty/imgui/misc/README.txt | 18 | ||||
-rw-r--r-- | 3rdparty/imgui/misc/cpp/imgui_stdlib.cpp | 65 | ||||
-rw-r--r-- | 3rdparty/imgui/misc/cpp/imgui_stdlib.h | 22 | ||||
-rw-r--r-- | 3rdparty/imgui/misc/fonts/Cousine-Regular.ttf | bin | 0 -> 43912 bytes | |||
-rw-r--r-- | 3rdparty/imgui/misc/fonts/DroidSans.ttf | bin | 0 -> 190044 bytes | |||
-rw-r--r-- | 3rdparty/imgui/misc/fonts/Karla-Regular.ttf | bin | 0 -> 16848 bytes | |||
-rw-r--r-- | 3rdparty/imgui/misc/fonts/ProggyClean.ttf | bin | 0 -> 41208 bytes | |||
-rw-r--r-- | 3rdparty/imgui/misc/fonts/ProggyTiny.ttf | bin | 0 -> 35656 bytes | |||
-rw-r--r-- | 3rdparty/imgui/misc/fonts/README.txt | 290 | ||||
-rw-r--r-- | 3rdparty/imgui/misc/fonts/Roboto-Medium.ttf | bin | 0 -> 162588 bytes | |||
-rw-r--r-- | 3rdparty/imgui/misc/fonts/binary_to_compressed_c.cpp | 380 | ||||
-rw-r--r-- | 3rdparty/imgui/misc/freetype/README.md | 133 | ||||
-rw-r--r-- | 3rdparty/imgui/misc/freetype/imgui_freetype.cpp | 388 | ||||
-rw-r--r-- | 3rdparty/imgui/misc/freetype/imgui_freetype.h | 31 | ||||
-rw-r--r-- | 3rdparty/imgui/misc/natvis/README.txt | 4 | ||||
-rw-r--r-- | 3rdparty/imgui/misc/natvis/imgui.natvis | 39 |
16 files changed, 1370 insertions, 0 deletions
diff --git a/3rdparty/imgui/misc/README.txt b/3rdparty/imgui/misc/README.txt new file mode 100644 index 00000000..4bd27452 --- /dev/null +++ b/3rdparty/imgui/misc/README.txt @@ -0,0 +1,18 @@ + +misc/cpp/ + InputText() wrappers for C++ standard library (STL) types (std::string, etc.). + This is also an example of how you may wrap your own similar types. + +misc/fonts/ + Fonts loading/merging instructions (e.g. How to handle glyph ranges, how to merge icons fonts). + Command line tool "binary_to_compressed_c" to create compressed arrays to embed data in source code. + Suggested fonts and links. + +misc/freetype/ + Font atlas builder/rasterizer using FreeType instead of stb_truetype. + Benefit from better FreeType rasterization, in particular for small fonts. + +misc/natvis/ + Natvis file to describe dear imgui types in the Visual Studio debugger. + With this, types like ImVector<> will be displayed nicely in the debugger. + You can include this file a Visual Studio project file, or install it in Visual Studio folder. diff --git a/3rdparty/imgui/misc/cpp/imgui_stdlib.cpp b/3rdparty/imgui/misc/cpp/imgui_stdlib.cpp new file mode 100644 index 00000000..790d8d80 --- /dev/null +++ b/3rdparty/imgui/misc/cpp/imgui_stdlib.cpp @@ -0,0 +1,65 @@ +// imgui_stdlib.cpp +// Wrappers for C++ standard library (STL) types (std::string, etc.) +// This is also an example of how you may wrap your own similar types. + +// Compatibility: +// - std::string support is only guaranteed to work from C++11. +// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture) + +// Changelog: +// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string + +#include "imgui.h" +#include "imgui_stdlib.h" + +struct InputTextCallback_UserData +{ + std::string* Str; + ImGuiInputTextCallback ChainCallback; + void* ChainCallbackUserData; +}; + +static int InputTextCallback(ImGuiInputTextCallbackData* data) +{ + InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData; + if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) + { + // Resize string callback + // If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want. + std::string* str = user_data->Str; + IM_ASSERT(data->Buf == str->c_str()); + str->resize(data->BufTextLen); + data->Buf = (char*)str->c_str(); + } + else if (user_data->ChainCallback) + { + // Forward to user callback, if any + data->UserData = user_data->ChainCallbackUserData; + return user_data->ChainCallback(data); + } + return 0; +} + +bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +{ + IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); + flags |= ImGuiInputTextFlags_CallbackResize; + + InputTextCallback_UserData cb_user_data; + cb_user_data.Str = str; + cb_user_data.ChainCallback = callback; + cb_user_data.ChainCallbackUserData = user_data; + return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); +} + +bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) +{ + IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); + flags |= ImGuiInputTextFlags_CallbackResize; + + InputTextCallback_UserData cb_user_data; + cb_user_data.Str = str; + cb_user_data.ChainCallback = callback; + cb_user_data.ChainCallbackUserData = user_data; + return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data); +} diff --git a/3rdparty/imgui/misc/cpp/imgui_stdlib.h b/3rdparty/imgui/misc/cpp/imgui_stdlib.h new file mode 100644 index 00000000..200c45a5 --- /dev/null +++ b/3rdparty/imgui/misc/cpp/imgui_stdlib.h @@ -0,0 +1,22 @@ +// imgui_stdlib.h +// Wrappers for C++ standard library (STL) types (std::string, etc.) +// This is also an example of how you may wrap your own similar types. + +// Compatibility: +// - std::string support is only guaranteed to work from C++11. +// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture) + +// Changelog: +// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string + +#pragma once + +#include <string> + +namespace ImGui +{ + // ImGui::InputText() with std::string + // Because text input needs dynamic resizing, we need to setup a callback to grow the capacity + IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); + IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL); +} diff --git a/3rdparty/imgui/misc/fonts/Cousine-Regular.ttf b/3rdparty/imgui/misc/fonts/Cousine-Regular.ttf Binary files differnew file mode 100644 index 00000000..70a0bf90 --- /dev/null +++ b/3rdparty/imgui/misc/fonts/Cousine-Regular.ttf diff --git a/3rdparty/imgui/misc/fonts/DroidSans.ttf b/3rdparty/imgui/misc/fonts/DroidSans.ttf Binary files differnew file mode 100644 index 00000000..767c63ad --- /dev/null +++ b/3rdparty/imgui/misc/fonts/DroidSans.ttf diff --git a/3rdparty/imgui/misc/fonts/Karla-Regular.ttf b/3rdparty/imgui/misc/fonts/Karla-Regular.ttf Binary files differnew file mode 100644 index 00000000..81b3de6e --- /dev/null +++ b/3rdparty/imgui/misc/fonts/Karla-Regular.ttf diff --git a/3rdparty/imgui/misc/fonts/ProggyClean.ttf b/3rdparty/imgui/misc/fonts/ProggyClean.ttf Binary files differnew file mode 100644 index 00000000..0270cdfe --- /dev/null +++ b/3rdparty/imgui/misc/fonts/ProggyClean.ttf diff --git a/3rdparty/imgui/misc/fonts/ProggyTiny.ttf b/3rdparty/imgui/misc/fonts/ProggyTiny.ttf Binary files differnew file mode 100644 index 00000000..1c4312c3 --- /dev/null +++ b/3rdparty/imgui/misc/fonts/ProggyTiny.ttf diff --git a/3rdparty/imgui/misc/fonts/README.txt b/3rdparty/imgui/misc/fonts/README.txt new file mode 100644 index 00000000..a40bb3d1 --- /dev/null +++ b/3rdparty/imgui/misc/fonts/README.txt @@ -0,0 +1,290 @@ + +The code in imgui.cpp embeds a copy of 'ProggyClean.ttf' (by Tristan Grimmer), +a 13 pixels high, pixel-perfect font used by default. +We embed it font in source code so you can use Dear ImGui without any file system access. + +You may also load external .TTF/.OTF files. +The files in this folder are suggested fonts, provided as a convenience. +(Note: .OTF support in imstb_truetype.h currently doesn't appear to load every font) + +Fonts are rasterized in a single texture at the time of calling either of io.Fonts->GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). +Also read dear imgui FAQ in imgui.cpp! + +If you have other loading/merging/adding fonts, you can post on the Dear ImGui "Getting Started" forum: + https://discourse.dearimgui.org/c/getting-started + + +--------------------------------------- + INDEX: +--------------------------------------- + +- Readme First / FAQ +- Using Icons +- Fonts Loading Instructions +- FreeType rasterizer, Small font sizes +- Building Custom Glyph Ranges +- Embedding Fonts in Source Code +- Credits/Licences for fonts included in this folder +- Links, Other fonts + + +--------------------------------------- + README FIRST / FAQ +--------------------------------------- + + - You can use the style editor ImGui::ShowStyleEditor() to browse your fonts and understand what's going on if you have an issue. + - Make sure your font ranges data are persistent (available during the call to GetTexDataAsAlpha8()/GetTexDataAsRGBA32()/Build(). + - Use C++11 u8"my text" syntax to encode literal strings as UTF-8. e.g.: + u8"hello" + u8"こんにちは" // this will be encoded as UTF-8 + - If you want to include a backslash \ character in your string literal, you need to double them e.g. "folder\\filename". + - Please use the Discourse forum (https://discourse.dearimgui.org) and not the Github issue tracker for basic font loading questions. + + +--------------------------------------- + USING ICONS +--------------------------------------- + + Using an icon font (such as FontAwesome: http://fontawesome.io) is an easy and practical way to use icons in your ImGui application. + A common pattern is to merge the icon font within your main font, so you can embed icons directly from your strings without + having to change fonts back and forth. + + To refer to the icon UTF-8 codepoints from your C++ code, you may use those headers files created by Juliette Foucaut: + https://github.com/juliettef/IconFontCppHeaders + + The C++11 version of those files uses the u8"" utf-8 encoding syntax + \u + #define ICON_FA_SEARCH u8"\uf002" + The pre-C++11 version has the values directly encoded as utf-8: + #define ICON_FA_SEARCH "\xEF\x80\x82" + + Example: + + // Merge icons into default tool font + #include "IconsFontAwesome.h" + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->AddFontDefault(); + + ImFontConfig config; + config.MergeMode = true; + config.GlyphMinAdvanceX = 13.0f; // Use if you want to make the icon monospaced + static const ImWchar icon_ranges[] = { ICON_MIN_FA, ICON_MAX_FA, 0 }; + io.Fonts->AddFontFromFileTTF("fonts/fontawesome-webfont.ttf", 13.0f, &config, icon_ranges); + + // Usage, e.g. + ImGui::Button(ICON_FA_SEARCH " Search"); + // C string _literals_ can be concatenated at compilation time, e.g. "hello" " world" + // ICON_FA_SEARCH is defined as a string literal so this is the same as "A" "B" becoming "AB" + + // Usage, e.g. + ImGui::Text("%s among %d items", ICON_FA_SEARCH, count); + + See Links below for other icons fonts and related tools. + + +--------------------------------------- + FONTS LOADING INSTRUCTIONS +--------------------------------------- + + Load default font: + + ImGuiIO& io = ImGui::GetIO(); + io.Fonts->AddFontDefault(); + + Load .TTF/.OTF file with: + + ImGuiIO& io = ImGui::GetIO(); + ImFont* font1 = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); + ImFont* font2 = io.Fonts->AddFontFromFileTTF("anotherfont.otf", size_pixels); + + // Select font at runtime + ImGui::Text("Hello"); // use the default font (which is the first loaded font) + ImGui::PushFont(font2); + ImGui::Text("Hello with another font"); + ImGui::PopFont(); + + For advanced options create a ImFontConfig structure and pass it to the AddFont function (it will be copied internally): + + ImFontConfig config; + config.OversampleH = 3; + config.OversampleV = 1; + config.GlyphExtraSpacing.x = 1.0f; + ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, &config); + + If you have very large number of glyphs or multiple fonts, the texture may become too big for your graphics API. + The typical result of failing to upload a texture is if every glyphs appears as white rectangles. + In particular, using a large range such as GetGlyphRangesChineseSimplifiedCommon() is not recommended unless you + set OversampleH/OversampleV to 1 and use a small font size. + Mind the fact that some graphics drivers have texture size limitation. + If you are building a PC application, mind the fact that your users may use hardware with lower limitations than yours. + Some solutions: + + - 1) Reduce glyphs ranges by calculating them from source localization data. You can use ImFont::GlyphRangesBuilder for this purpose, + this will be the biggest win. + - 2) You may reduce oversampling, e.g. config.OversampleH = config.OversampleV = 1, this will largely reduce your texture size. + - 3) Set io.Fonts.TexDesiredWidth to specify a texture width to minimize texture height (see comment in ImFontAtlas::Build function). + - 4) Set io.Fonts.Flags |= ImFontAtlasFlags_NoPowerOfTwoHeight; to disable rounding the texture height to the next power of two. + + Combine two fonts into one: + + // Load a first font + ImFont* font = io.Fonts->AddFontDefault(); + + // Add character ranges and merge into the previous font + // The ranges array is not copied by the AddFont* functions and is used lazily + // so ensure it is available at the time of building or calling GetTexDataAsRGBA32(). + static const ImWchar icons_ranges[] = { 0xf000, 0xf3ff, 0 }; // Will not be copied by AddFont* so keep in scope. + ImFontConfig config; + config.MergeMode = true; + io.Fonts->AddFontFromFileTTF("DroidSans.ttf", 18.0f, &config, io.Fonts->GetGlyphRangesJapanese()); + io.Fonts->AddFontFromFileTTF("fontawesome-webfont.ttf", 18.0f, &config, icons_ranges); + io.Fonts->Build(); + + Add a fourth parameter to bake specific font ranges only: + + // Basic Latin, Extended Latin + io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesDefault()); + + // Default + Selection of 2500 Ideographs used by Simplified Chinese + io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesChineseSimplifiedCommon()); + + // Default + Hiragana, Katakana, Half-Width, Selection of 1946 Ideographs + io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels, NULL, io.Fonts->GetGlyphRangesJapanese()); + + See "BUILDING CUSTOM GLYPH RANGES" section to create your own ranges. + Offset font vertically by altering the io.Font->DisplayOffset value: + + ImFont* font = io.Fonts->AddFontFromFileTTF("font.ttf", size_pixels); + font->DisplayOffset.y = 1; // Render 1 pixel down + + +--------------------------------------- + FREETYPE RASTERIZER, SMALL FONT SIZES +--------------------------------------- + + Dear ImGui uses imstb_truetype.h to rasterize fonts (with optional oversampling). + This technique and its implementation are not ideal for fonts rendered at _small sizes_, which may appear a + little blurry or hard to read. + + There is an implementation of the ImFontAtlas builder using FreeType that you can use in the misc/freetype/ folder. + + FreeType supports auto-hinting which tends to improve the readability of small fonts. + Note that this code currently creates textures that are unoptimally too large (could be fixed with some work). + Also note that correct sRGB space blending will have an important effect on your font rendering quality. + + +--------------------------------------- + BUILDING CUSTOM GLYPH RANGES +--------------------------------------- + + You can use the ImFontAtlas::GlyphRangesBuilder helper to create glyph ranges based on text input. + For example: for a game where your script is known, if you can feed your entire script to it and only build the characters the game needs. + + ImVector<ImWchar> ranges; + ImFontAtlas::GlyphRangesBuilder builder; + builder.AddText("Hello world"); // Add a string (here "Hello world" contains 7 unique characters) + builder.AddChar(0x7262); // Add a specific character + builder.AddRanges(io.Fonts->GetGlyphRangesJapanese()); // Add one of the default ranges + builder.BuildRanges(&ranges); // Build the final result (ordered ranges with all the unique characters submitted) + + io.Fonts->AddFontFromFileTTF("myfontfile.ttf", size_in_pixels, NULL, ranges.Data); + io.Fonts->Build(); // Build the atlas while 'ranges' is still in scope and not deleted. + + +--------------------------------------- + EMBEDDING FONTS IN SOURCE CODE +--------------------------------------- + + Compile and use 'binary_to_compressed_c.cpp' to create a compressed C style array that you can embed in source code. + See the documentation in binary_to_compressed_c.cpp for instruction on how to use the tool. + You may find a precompiled version binary_to_compressed_c.exe for Windows instead of demo binaries package (see README). + The tool optionally used Base85 encoding to reduce the size of _source code_ but the read-only arrays will be about 20% bigger. + + Then load the font with: + ImFont* font = io.Fonts->AddFontFromMemoryCompressedTTF(compressed_data, compressed_data_size, size_pixels, ...); + or: + ImFont* font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(compressed_data_base85, size_pixels, ...); + + +--------------------------------------- + CREDITS/LICENSES FOR FONTS INCLUDED IN THIS FOLDER +--------------------------------------- + + Roboto-Medium.ttf + Apache License 2.0 + by Christian Robertson + https://fonts.google.com/specimen/Roboto + + Cousine-Regular.ttf + by Steve Matteson + Digitized data copyright (c) 2010 Google Corporation. + Licensed under the SIL Open Font License, Version 1.1 + https://fonts.google.com/specimen/Cousine + + DroidSans.ttf + Copyright (c) Steve Matteson + Apache License, version 2.0 + https://www.fontsquirrel.com/fonts/droid-sans + + ProggyClean.ttf + Copyright (c) 2004, 2005 Tristan Grimmer + MIT License + recommended loading setting in ImGui: Size = 13.0, DisplayOffset.Y = +1 + http://www.proggyfonts.net/ + + ProggyTiny.ttf + Copyright (c) 2004, 2005 Tristan Grimmer + MIT License + recommended loading setting in ImGui: Size = 10.0, DisplayOffset.Y = +1 + http://www.proggyfonts.net/ + + Karla-Regular.ttf + Copyright (c) 2012, Jonathan Pinhorn + SIL OPEN FONT LICENSE Version 1.1 + + +--------------------------------------- + LINKS, OTHER FONTS +--------------------------------------- + + (Icons) Icon fonts + https://fortawesome.github.io/Font-Awesome/ + https://github.com/SamBrishes/kenney-icon-font + https://design.google.com/icons/ + You can use https://github.com/juliettef/IconFontCppHeaders for C/C++ header files with name #define to access icon codepoint in source code. + + (Icons) IcoMoon - Custom Icon font builder + https://icomoon.io/app + + (Pixel perfect) Sweet16, Sweet16 Mono, by Martin Sedlak (Latin + Supplemental + Extended A) + https://github.com/kmar/Sweet16Font + Also include .inl file to use directly in dear imgui. + + (Regular) Open Sans Fonts + https://fonts.google.com/specimen/Open+Sans + + (Regular) Google Noto Fonts (worldwide languages) + https://www.google.com/get/noto/ + + (Monospace) Typefaces for source code beautification + https://github.com/chrissimpkins/codeface + + (Monospace) Programmation fonts + http://s9w.github.io/font_compare/ + + (Monospace) Proggy Programming Fonts + http://upperbounds.net + + (Monospace) Inconsolata + http://www.levien.com/type/myfonts/inconsolata.html + + (Monospace) Adobe Source Code Pro: Monospaced font family for user interface and coding environments + https://github.com/adobe-fonts/source-code-pro + + (Monospace) Monospace/Fixed Width Programmer's Fonts + http://www.lowing.org/fonts/ + + (Japanese) M+ fonts by Coji Morishita are free and include most useful Kanjis you would need. + http://mplus-fonts.sourceforge.jp/mplus-outline-fonts/index-en.html + + Or use Arial Unicode or other Unicode fonts provided with Windows for full characters coverage (not sure of their licensing). + diff --git a/3rdparty/imgui/misc/fonts/Roboto-Medium.ttf b/3rdparty/imgui/misc/fonts/Roboto-Medium.ttf Binary files differnew file mode 100644 index 00000000..39c63d74 --- /dev/null +++ b/3rdparty/imgui/misc/fonts/Roboto-Medium.ttf diff --git a/3rdparty/imgui/misc/fonts/binary_to_compressed_c.cpp b/3rdparty/imgui/misc/fonts/binary_to_compressed_c.cpp new file mode 100644 index 00000000..08b102d4 --- /dev/null +++ b/3rdparty/imgui/misc/fonts/binary_to_compressed_c.cpp @@ -0,0 +1,380 @@ +// ImGui - binary_to_compressed_c.cpp +// Helper tool to turn a file into a C array, if you want to embed font data in your source code. + +// The data is first compressed with stb_compress() to reduce source code size, +// then encoded in Base85 to fit in a string so we can fit roughly 4 bytes of compressed data into 5 bytes of source code (suggested by @mmalex) +// (If we used 32-bits constants it would require take 11 bytes of source code to encode 4 bytes, and be endianness dependent) +// Note that even with compression, the output array is likely to be bigger than the binary file.. +// Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF() + +// Build with, e.g: +// # cl.exe binary_to_compressed_c.cpp +// # gcc binary_to_compressed_c.cpp +// You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui + +// Usage: +// binary_to_compressed_c.exe [-base85] [-nocompress] <inputfile> <symbolname> +// Usage example: +// # binary_to_compressed_c.exe myfont.ttf MyFont > myfont.cpp +// # binary_to_compressed_c.exe -base85 myfont.ttf MyFont > myfont.cpp + +#define _CRT_SECURE_NO_WARNINGS +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> + +// stb_compress* from stb.h - declaration +typedef unsigned int stb_uint; +typedef unsigned char stb_uchar; +stb_uint stb_compress(stb_uchar *out,stb_uchar *in,stb_uint len); + +static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression); + +int main(int argc, char** argv) +{ + if (argc < 3) + { + printf("Syntax: %s [-base85] [-nocompress] <inputfile> <symbolname>\n", argv[0]); + return 0; + } + + int argn = 1; + bool use_base85_encoding = false; + bool use_compression = true; + if (argv[argn][0] == '-') + { + if (strcmp(argv[argn], "-base85") == 0) { use_base85_encoding = true; argn++; } + else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; } + else + { + printf("Unknown argument: '%s'\n", argv[argn]); + return 1; + } + } + + return binary_to_compressed_c(argv[argn], argv[argn+1], use_base85_encoding, use_compression) ? 0 : 1; +} + +char Encode85Byte(unsigned int x) +{ + x = (x % 85) + 35; + return (x>='\\') ? x+1 : x; +} + +bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression) +{ + // Read file + FILE* f = fopen(filename, "rb"); + if (!f) return false; + int data_sz; + if (fseek(f, 0, SEEK_END) || (data_sz = (int)ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) { fclose(f); return false; } + char* data = new char[data_sz+4]; + if (fread(data, 1, data_sz, f) != (size_t)data_sz) { fclose(f); delete[] data; return false; } + memset((void*)(((char*)data) + data_sz), 0, 4); + fclose(f); + + // Compress + int maxlen = data_sz + 512 + (data_sz >> 2) + sizeof(int); // total guess + char* compressed = use_compression ? new char[maxlen] : data; + int compressed_sz = use_compression ? stb_compress((stb_uchar*)compressed, (stb_uchar*)data, data_sz) : data_sz; + if (use_compression) + memset(compressed + compressed_sz, 0, maxlen - compressed_sz); + + // Output as Base85 encoded + FILE* out = stdout; + fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz); + fprintf(out, "// Exported using binary_to_compressed_c.cpp\n"); + const char* compressed_str = use_compression ? "compressed_" : ""; + if (use_base85_encoding) + { + fprintf(out, "static const char %s_%sdata_base85[%d+1] =\n \"", symbol, compressed_str, (int)((compressed_sz+3)/4)*5); + char prev_c = 0; + for (int src_i = 0; src_i < compressed_sz; src_i += 4) + { + // This is made a little more complicated by the fact that ??X sequences are interpreted as trigraphs by old C/C++ compilers. So we need to escape pairs of ??. + unsigned int d = *(unsigned int*)(compressed + src_i); + for (unsigned int n5 = 0; n5 < 5; n5++, d /= 85) + { + char c = Encode85Byte(d); + fprintf(out, (c == '?' && prev_c == '?') ? "\\%c" : "%c", c); + prev_c = c; + } + if ((src_i % 112) == 112-4) + fprintf(out, "\"\n \""); + } + fprintf(out, "\";\n\n"); + } + else + { + fprintf(out, "static const unsigned int %s_%ssize = %d;\n", symbol, compressed_str, (int)compressed_sz); + fprintf(out, "static const unsigned int %s_%sdata[%d/4] =\n{", symbol, compressed_str, (int)((compressed_sz+3)/4)*4); + int column = 0; + for (int i = 0; i < compressed_sz; i += 4) + { + unsigned int d = *(unsigned int*)(compressed + i); + if ((column++ % 12) == 0) + fprintf(out, "\n 0x%08x, ", d); + else + fprintf(out, "0x%08x, ", d); + } + fprintf(out, "\n};\n\n"); + } + + // Cleanup + delete[] data; + if (use_compression) + delete[] compressed; + return true; +} + +// stb_compress* from stb.h - definition + +//////////////////// compressor /////////////////////// + +static stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint 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 -= blocklen; + blocklen = 5552; + } + return (s2 << 16) + s1; +} + +static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen) +{ + stb_uint i; + for (i=0; i < maxlen; ++i) + if (m1[i] != m2[i]) return i; + return i; +} + +// simple implementation that just takes the source data in a big block + +static stb_uchar *stb__out; +static FILE *stb__outfile; +static stb_uint stb__outbytes; + +static void stb__write(unsigned char v) +{ + fputc(v, stb__outfile); + ++stb__outbytes; +} + +//#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v))) +#define stb_out(v) do { if (stb__out) *stb__out++ = (stb_uchar) (v); else stb__write((stb_uchar) (v)); } while (0) + +static void stb_out2(stb_uint v) { stb_out(v >> 8); stb_out(v); } +static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); } +static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16); stb_out(v >> 8 ); stb_out(v); } + +static void outliterals(stb_uchar *in, int numlit) +{ + while (numlit > 65536) { + outliterals(in,65536); + in += 65536; + numlit -= 65536; + } + + if (numlit == 0) ; + else if (numlit <= 32) stb_out (0x000020 + numlit-1); + else if (numlit <= 2048) stb_out2(0x000800 + numlit-1); + else /* numlit <= 65536) */ stb_out3(0x070000 + numlit-1); + + if (stb__out) { + memcpy(stb__out,in,numlit); + stb__out += numlit; + } else + fwrite(in, 1, numlit, stb__outfile); +} + +static int stb__window = 0x40000; // 256K + +static int stb_not_crap(int best, int dist) +{ + return ((best > 2 && dist <= 0x00100) + || (best > 5 && dist <= 0x04000) + || (best > 7 && dist <= 0x80000)); +} + +static stb_uint stb__hashsize = 32768; + +// note that you can play with the hashing functions all you +// want without needing to change the decompressor +#define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c]) +#define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d]) +#define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e]) + +static unsigned int stb__running_adler; + +static int stb_compress_chunk(stb_uchar *history, + stb_uchar *start, + stb_uchar *end, + int length, + int *pending_literals, + stb_uchar **chash, + stb_uint mask) +{ + (void)history; + int window = stb__window; + stb_uint match_max; + stb_uchar *lit_start = start - *pending_literals; + stb_uchar *q = start; + +#define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask) + + // stop short of the end so we don't scan off the end doing + // the hashing; this means we won't compress the last few bytes + // unless they were part of something longer + while (q < start+length && q+12 < end) { + int m; + stb_uint h1,h2,h3,h4, h; + stb_uchar *t; + int best = 2, dist=0; + + if (q+65536 > end) + match_max = end-q; + else + match_max = 65536; + +#define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d))) + +#define STB__TRY(t,p) /* avoid retrying a match we already tried */ \ + if (p ? dist != q-t : 1) \ + if ((m = stb_matchlen(t, q, match_max)) > best) \ + if (stb__nc(m,q-(t))) \ + best = m, dist = q - (t) + + // rather than search for all matches, only try 4 candidate locations, + // chosen based on 4 different hash functions of different lengths. + // this strategy is inspired by LZO; hashing is unrolled here using the + // 'hc' macro + h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h); + t = chash[h1]; if (t) STB__TRY(t,0); + h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h); + h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1); + h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h); + h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1); + h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h); + t = chash[h4]; if (t) STB__TRY(t,1); + + // because we use a shared hash table, can only update it + // _after_ we've probed all of them + chash[h1] = chash[h2] = chash[h3] = chash[h4] = q; + + if (best > 2) + assert(dist > 0); + + // see if our best match qualifies + if (best < 3) { // fast path literals + ++q; + } else if (best > 2 && best <= 0x80 && dist <= 0x100) { + outliterals(lit_start, q-lit_start); lit_start = (q += best); + stb_out(0x80 + best-1); + stb_out(dist-1); + } else if (best > 5 && best <= 0x100 && dist <= 0x4000) { + outliterals(lit_start, q-lit_start); lit_start = (q += best); + stb_out2(0x4000 + dist-1); + stb_out(best-1); + } else if (best > 7 && best <= 0x100 && dist <= 0x80000) { + outliterals(lit_start, q-lit_start); lit_start = (q += best); + stb_out3(0x180000 + dist-1); + stb_out(best-1); + } else if (best > 8 && best <= 0x10000 && dist <= 0x80000) { + outliterals(lit_start, q-lit_start); lit_start = (q += best); + stb_out3(0x100000 + dist-1); + stb_out2(best-1); + } else if (best > 9 && dist <= 0x1000000) { + if (best > 65536) best = 65536; + outliterals(lit_start, q-lit_start); lit_start = (q += best); + if (best <= 0x100) { + stb_out(0x06); + stb_out3(dist-1); + stb_out(best-1); + } else { + stb_out(0x04); + stb_out3(dist-1); + stb_out2(best-1); + } + } else { // fallback literals if no match was a balanced tradeoff + ++q; + } + } + + // if we didn't get all the way, add the rest to literals + if (q-start < length) + q = start+length; + + // the literals are everything from lit_start to q + *pending_literals = (q - lit_start); + + stb__running_adler = stb_adler32(stb__running_adler, start, q - start); + return q - start; +} + +static int stb_compress_inner(stb_uchar *input, stb_uint length) +{ + int literals = 0; + stb_uint len,i; + + stb_uchar **chash; + chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*)); + if (chash == NULL) return 0; // failure + for (i=0; i < stb__hashsize; ++i) + chash[i] = NULL; + + // stream signature + stb_out(0x57); stb_out(0xbc); + stb_out2(0); + + stb_out4(0); // 64-bit length requires 32-bit leading 0 + stb_out4(length); + stb_out4(stb__window); + + stb__running_adler = 1; + + len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1); + assert(len == length); + + outliterals(input+length - literals, literals); + + free(chash); + + stb_out2(0x05fa); // end opcode + + stb_out4(stb__running_adler); + + return 1; // success +} + +stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length) +{ + stb__out = out; + stb__outfile = NULL; + + stb_compress_inner(input, length); + + return stb__out - out; +} diff --git a/3rdparty/imgui/misc/freetype/README.md b/3rdparty/imgui/misc/freetype/README.md new file mode 100644 index 00000000..ba633f69 --- /dev/null +++ b/3rdparty/imgui/misc/freetype/README.md @@ -0,0 +1,133 @@ +# imgui_freetype + +This is an attempt to replace stb_truetype (the default imgui's font rasterizer) with FreeType. +Currently not optimal and probably has some limitations or bugs. +By [Vuhdo](https://github.com/Vuhdo) (Aleksei Skriabin). Improvements by @mikesart. Maintained by @ocornut. + +**Usage** +1. Get latest FreeType binaries or build yourself. +2. Add imgui_freetype.h/cpp alongside your imgui sources. +3. Include imgui_freetype.h after imgui.h. +4. Call ImGuiFreeType::BuildFontAtlas() *BEFORE* calling ImFontAtlas::GetTexDataAsRGBA32() or ImFontAtlas::Build() (so normal Build() won't be called): + +```cpp +// See ImGuiFreeType::RasterizationFlags +unsigned int flags = ImGuiFreeType::NoHinting; +ImGuiFreeType::BuildFontAtlas(io.Fonts, flags); +io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); +``` + +**Gamma Correct Blending** +FreeType assumes blending in linear space rather than gamma space. +See FreeType note for [FT_Render_Glyph](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph). +For correct results you need to be using sRGB and convert to linear space in the pixel shader output. +The default imgui styles will be impacted by this change (alpha values will need tweaking). + +**Test code Usage** +```cpp +#include "misc/freetype/imgui_freetype.h" +#include "misc/freetype/imgui_freetype.cpp" + +// Load various small fonts +ImGuiIO& io = ImGui::GetIO(); +io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 13.0f); +io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 13.0f); +io.Fonts->AddFontDefault(); + +FreeTypeTest freetype_test; + +// Main Loop +while (true) +{ + if (freetype_test.UpdateRebuild()) + { + // REUPLOAD FONT TEXTURE TO GPU + // e.g ImGui_ImplGlfwGL3_InvalidateDeviceObjects() + ImGui_ImplGlfwGL3_CreateDeviceObjects() + } + ImGui::NewFrame(); + freetype_test.ShowFreetypeOptionsWindow(); + ... + } +} +``` + +**Test code** +```cpp +#include "misc/freetype/imgui_freetype.h" +#include "misc/freetype/imgui_freetype.cpp" + +struct FreeTypeTest +{ + enum FontBuildMode + { + FontBuildMode_FreeType, + FontBuildMode_Stb, + }; + + FontBuildMode BuildMode; + bool WantRebuild; + float FontsMultiply; + unsigned int FontsFlags; + + FreeTypeTest() + { + BuildMode = FontBuildMode_FreeType; + WantRebuild = true; + FontsMultiply = 1.0f; + FontsFlags = 0; + } + + // Call _BEFORE_ NewFrame() + bool UpdateRebuild() + { + if (!WantRebuild) + return false; + ImGuiIO& io = ImGui::GetIO(); + for (int n = 0; n < io.Fonts->Fonts.Size; n++) + { + io.Fonts->Fonts[n]->ConfigData->RasterizerMultiply = FontsMultiply; + io.Fonts->Fonts[n]->ConfigData->RasterizerFlags = (BuildMode == FontBuildMode_FreeType) ? FontsFlags : 0x00; + } + if (BuildMode == FontBuildMode_FreeType) + ImGuiFreeType::BuildFontAtlas(io.Fonts, FontsFlags); + else if (BuildMode == FontBuildMode_Stb) + io.Fonts->Build(); + WantRebuild = false; + return true; + } + + // Call to draw interface + void ShowFreetypeOptionsWindow() + { + ImGui::Begin("FreeType Options"); + ImGui::ShowFontSelector("Fonts"); + WantRebuild |= ImGui::RadioButton("FreeType", (int*)&BuildMode, FontBuildMode_FreeType); + ImGui::SameLine(); + WantRebuild |= ImGui::RadioButton("Stb (Default)", (int*)&BuildMode, FontBuildMode_Stb); + WantRebuild |= ImGui::DragFloat("Multiply", &FontsMultiply, 0.001f, 0.0f, 2.0f); + if (BuildMode == FontBuildMode_FreeType) + { + WantRebuild |= ImGui::CheckboxFlags("NoHinting", &FontsFlags, ImGuiFreeType::NoHinting); + WantRebuild |= ImGui::CheckboxFlags("NoAutoHint", &FontsFlags, ImGuiFreeType::NoAutoHint); + WantRebuild |= ImGui::CheckboxFlags("ForceAutoHint", &FontsFlags, ImGuiFreeType::ForceAutoHint); + WantRebuild |= ImGui::CheckboxFlags("LightHinting", &FontsFlags, ImGuiFreeType::LightHinting); + WantRebuild |= ImGui::CheckboxFlags("MonoHinting", &FontsFlags, ImGuiFreeType::MonoHinting); + WantRebuild |= ImGui::CheckboxFlags("Bold", &FontsFlags, ImGuiFreeType::Bold); + WantRebuild |= ImGui::CheckboxFlags("Oblique", &FontsFlags, ImGuiFreeType::Oblique); + } + ImGui::End(); + } +}; +``` + +**Known issues** +- Output texture has excessive resolution (lots of vertical waste). +- FreeType's memory allocator is not overridden. +- `cfg.OversampleH`, `OversampleV` are ignored (but perhaps not so necessary with this rasterizer). + +**Obligatory comparison screenshots** + +Using Windows built-in segoeui.ttf font. Open in new browser tabs, view at 1080p+. + +![freetype rasterizer](https://raw.githubusercontent.com/wiki/ocornut/imgui_club/images/freetype_20170817.png) + diff --git a/3rdparty/imgui/misc/freetype/imgui_freetype.cpp b/3rdparty/imgui/misc/freetype/imgui_freetype.cpp new file mode 100644 index 00000000..33bdb140 --- /dev/null +++ b/3rdparty/imgui/misc/freetype/imgui_freetype.cpp @@ -0,0 +1,388 @@ +// Wrapper to use Freetype (instead of stb_truetype) for Dear ImGui +// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype +// Original code by @Vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained by @ocornut + +// Changelog: +// - v0.50: (2017/08/16) imported from https://github.com/Vuhdo/imgui_freetype into http://www.github.com/ocornut/imgui_club, updated for latest changes in ImFontAtlas, minor tweaks. +// - v0.51: (2017/08/26) cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply. +// - v0.52: (2017/09/26) fixes for imgui internal changes +// - v0.53: (2017/10/22) minor inconsequential change to match change in master (removed an unnecessary statement) +// - v0.54: (2018/01/22) fix for addition of ImFontAtlas::TexUvscale member +// - v0.55: (2018/02/04) moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club) +// - v0.56: (2018/06/08) added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX + +// Gamma Correct Blending: +// FreeType assumes blending in linear space rather than gamma space. +// See https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph +// For correct results you need to be using sRGB and convert to linear space in the pixel shader output. +// The default imgui styles will be impacted by this change (alpha values will need tweaking). + +// TODO: +// - Output texture has excessive resolution (lots of vertical waste). +// - FreeType's memory allocator is not overridden. +// - cfg.OversampleH, OversampleV are ignored (but perhaps not so necessary with this rasterizer). + +#include "imgui_freetype.h" +#include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*, +#include <stdint.h> +#include <ft2build.h> +#include FT_FREETYPE_H +#include FT_GLYPH_H +#include FT_SYNTHESIS_H + +#ifdef _MSC_VER +#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) +#endif + +#if defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used +#endif + +namespace +{ + // Glyph metrics: + // -------------- + // + // xmin xmax + // | | + // |<-------- width -------->| + // | | + // | +-------------------------+----------------- ymax + // | | ggggggggg ggggg | ^ ^ + // | | g:::::::::ggg::::g | | | + // | | g:::::::::::::::::g | | | + // | | g::::::ggggg::::::gg | | | + // | | g:::::g g:::::g | | | + // offsetX -|-------->| g:::::g g:::::g | offsetY | + // | | g:::::g g:::::g | | | + // | | g::::::g g:::::g | | | + // | | g:::::::ggggg:::::g | | | + // | | g::::::::::::::::g | | height + // | | gg::::::::::::::g | | | + // baseline ---*---------|---- gggggggg::::::g-----*-------- | + // / | | g:::::g | | + // origin | | gggggg g:::::g | | + // | | g:::::gg gg:::::g | | + // | | g::::::ggg:::::::g | | + // | | gg:::::::::::::g | | + // | | ggg::::::ggg | | + // | | gggggg | v + // | +-------------------------+----------------- ymin + // | | + // |------------- advanceX ----------->| + + /// A structure that describe a glyph. + struct GlyphInfo + { + float Width; // Glyph's width in pixels. + float Height; // Glyph's height in pixels. + float OffsetX; // The distance from the origin ("pen position") to the left of the glyph. + float OffsetY; // The distance from the origin to the top of the glyph. This is usually a value < 0. + float AdvanceX; // The distance from the origin to the origin of the next glyph. This is usually a value > 0. + }; + + // Font parameters and metrics. + struct FontInfo + { + uint32_t PixelHeight; // Size this font was generated with. + float Ascender; // The pixel extents above the baseline in pixels (typically positive). + float Descender; // The extents below the baseline in pixels (typically negative). + float LineSpacing; // The baseline-to-baseline distance. Note that it usually is larger than the sum of the ascender and descender taken as absolute values. There is also no guarantee that no glyphs extend above or below subsequent baselines when using this distance. Think of it as a value the designer of the font finds appropriate. + float LineGap; // The spacing in pixels between one row's descent and the next row's ascent. + float MaxAdvanceWidth; // This field gives the maximum horizontal cursor advance for all glyphs in the font. + }; + + // FreeType glyph rasterizer. + // NB: No ctor/dtor, explicitly call Init()/Shutdown() + struct FreeTypeFont + { + bool Init(const ImFontConfig& cfg, unsigned int extra_user_flags); // Initialize from an external data buffer. Doesn't copy data, and you must ensure it stays valid up to this object lifetime. + void Shutdown(); + void SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size + + bool CalcGlyphInfo(uint32_t codepoint, GlyphInfo& glyph_info, FT_Glyph& ft_glyph, FT_BitmapGlyph& ft_bitmap); + void BlitGlyph(FT_BitmapGlyph ft_bitmap, uint8_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = NULL); + + // [Internals] + FontInfo Info; // Font descriptor of the current font. + unsigned int UserFlags; // = ImFontConfig::RasterizerFlags + FT_Library FreetypeLibrary; + FT_Face FreetypeFace; + FT_Int32 FreetypeLoadFlags; + }; + + // From SDL_ttf: Handy routines for converting from fixed point + #define FT_CEIL(X) (((X + 63) & -64) / 64) + + bool FreeTypeFont::Init(const ImFontConfig& cfg, unsigned int extra_user_flags) + { + // FIXME: substitute allocator + FT_Error error = FT_Init_FreeType(&FreetypeLibrary); + if (error != 0) + return false; + error = FT_New_Memory_Face(FreetypeLibrary, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &FreetypeFace); + if (error != 0) + return false; + error = FT_Select_Charmap(FreetypeFace, FT_ENCODING_UNICODE); + if (error != 0) + return false; + + memset(&Info, 0, sizeof(Info)); + SetPixelHeight((uint32_t)cfg.SizePixels); + + // Convert to freetype flags (nb: Bold and Oblique are processed separately) + UserFlags = cfg.RasterizerFlags | extra_user_flags; + FreetypeLoadFlags = FT_LOAD_NO_BITMAP; + if (UserFlags & ImGuiFreeType::NoHinting) FreetypeLoadFlags |= FT_LOAD_NO_HINTING; + if (UserFlags & ImGuiFreeType::NoAutoHint) FreetypeLoadFlags |= FT_LOAD_NO_AUTOHINT; + if (UserFlags & ImGuiFreeType::ForceAutoHint) FreetypeLoadFlags |= FT_LOAD_FORCE_AUTOHINT; + if (UserFlags & ImGuiFreeType::LightHinting) + FreetypeLoadFlags |= FT_LOAD_TARGET_LIGHT; + else if (UserFlags & ImGuiFreeType::MonoHinting) + FreetypeLoadFlags |= FT_LOAD_TARGET_MONO; + else + FreetypeLoadFlags |= FT_LOAD_TARGET_NORMAL; + + return true; + } + + void FreeTypeFont::Shutdown() + { + if (FreetypeFace) + { + FT_Done_Face(FreetypeFace); + FreetypeFace = NULL; + FT_Done_FreeType(FreetypeLibrary); + FreetypeLibrary = NULL; + } + } + + void FreeTypeFont::SetPixelHeight(int pixel_height) + { + // I'm not sure how to deal with font sizes properly. + // As far as I understand, currently ImGui assumes that the 'pixel_height' is a maximum height of an any given glyph, + // i.e. it's the sum of font's ascender and descender. Seems strange to me. + FT_Size_RequestRec req; + req.type = FT_SIZE_REQUEST_TYPE_REAL_DIM; + req.width = 0; + req.height = (uint32_t)pixel_height * 64; + req.horiResolution = 0; + req.vertResolution = 0; + FT_Request_Size(FreetypeFace, &req); + + // update font info + FT_Size_Metrics metrics = FreetypeFace->size->metrics; + Info.PixelHeight = (uint32_t)pixel_height; + Info.Ascender = (float)FT_CEIL(metrics.ascender); + Info.Descender = (float)FT_CEIL(metrics.descender); + Info.LineSpacing = (float)FT_CEIL(metrics.height); + Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender); + Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance); + } + + bool FreeTypeFont::CalcGlyphInfo(uint32_t codepoint, GlyphInfo &glyph_info, FT_Glyph& ft_glyph, FT_BitmapGlyph& ft_bitmap) + { + uint32_t glyph_index = FT_Get_Char_Index(FreetypeFace, codepoint); + if (glyph_index == 0) + return false; + FT_Error error = FT_Load_Glyph(FreetypeFace, glyph_index, FreetypeLoadFlags); + if (error) + return false; + + // Need an outline for this to work + FT_GlyphSlot slot = FreetypeFace->glyph; + IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE); + + if (UserFlags & ImGuiFreeType::Bold) + FT_GlyphSlot_Embolden(slot); + if (UserFlags & ImGuiFreeType::Oblique) + FT_GlyphSlot_Oblique(slot); + + // Retrieve the glyph + error = FT_Get_Glyph(slot, &ft_glyph); + if (error != 0) + return false; + + // Rasterize + error = FT_Glyph_To_Bitmap(&ft_glyph, FT_RENDER_MODE_NORMAL, NULL, true); + if (error != 0) + return false; + + ft_bitmap = (FT_BitmapGlyph)ft_glyph; + glyph_info.AdvanceX = (float)FT_CEIL(slot->advance.x); + glyph_info.OffsetX = (float)ft_bitmap->left; + glyph_info.OffsetY = -(float)ft_bitmap->top; + glyph_info.Width = (float)ft_bitmap->bitmap.width; + glyph_info.Height = (float)ft_bitmap->bitmap.rows; + + return true; + } + + void FreeTypeFont::BlitGlyph(FT_BitmapGlyph ft_bitmap, uint8_t* dst, uint32_t dst_pitch, unsigned char* multiply_table) + { + IM_ASSERT(ft_bitmap != NULL); + + const uint32_t w = ft_bitmap->bitmap.width; + const uint32_t h = ft_bitmap->bitmap.rows; + const uint8_t* src = ft_bitmap->bitmap.buffer; + const uint32_t src_pitch = ft_bitmap->bitmap.pitch; + + if (multiply_table == NULL) + { + for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) + memcpy(dst, src, w); + } + else + { + for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) + for (uint32_t x = 0; x < w; x++) + dst[x] = multiply_table[src[x]]; + } + } +} + +#define STBRP_ASSERT(x) IM_ASSERT(x) +#define STBRP_STATIC +#define STB_RECT_PACK_IMPLEMENTATION +#include "imstb_rectpack.h" + +bool ImGuiFreeType::BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags) +{ + IM_ASSERT(atlas->ConfigData.Size > 0); + IM_ASSERT(atlas->TexGlyphPadding == 1); // Not supported + + ImFontAtlasBuildRegisterDefaultCustomRects(atlas); + + atlas->TexID = NULL; + atlas->TexWidth = atlas->TexHeight = 0; + atlas->TexUvScale = ImVec2(0.0f, 0.0f); + atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); + atlas->ClearTexData(); + + ImVector<FreeTypeFont> fonts; + fonts.resize(atlas->ConfigData.Size); + + ImVec2 max_glyph_size(1.0f, 1.0f); + + // Count glyphs/ranges, initialize font + int total_glyphs_count = 0; + int total_ranges_count = 0; + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) + { + ImFontConfig& cfg = atlas->ConfigData[input_i]; + FreeTypeFont& font_face = fonts[input_i]; + IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); + + if (!font_face.Init(cfg, extra_flags)) + return false; + + max_glyph_size.x = ImMax(max_glyph_size.x, font_face.Info.MaxAdvanceWidth); + max_glyph_size.y = ImMax(max_glyph_size.y, font_face.Info.Ascender - font_face.Info.Descender); + + if (!cfg.GlyphRanges) + cfg.GlyphRanges = atlas->GetGlyphRangesDefault(); + for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[ 1 ]; in_range += 2, total_ranges_count++) + total_glyphs_count += (in_range[1] - in_range[0]) + 1; + } + + // We need a width for the skyline algorithm. Using a dumb heuristic here to decide of width. User can override TexDesiredWidth and TexGlyphPadding if they wish. + // Width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. + atlas->TexWidth = (atlas->TexDesiredWidth > 0) ? atlas->TexDesiredWidth : (total_glyphs_count > 4000) ? 4096 : (total_glyphs_count > 2000) ? 2048 : (total_glyphs_count > 1000) ? 1024 : 512; + + // We don't do the original first pass to determine texture height, but just rough estimate. + // Looks ugly inaccurate and excessive, but AFAIK with FreeType we actually need to render glyphs to get exact sizes. + // Alternatively, we could just render all glyphs into a big shadow buffer, get their sizes, do the rectangle packing and just copy back from the + // shadow buffer to the texture buffer. Will give us an accurate texture height, but eat a lot of temp memory. Probably no one will notice.) + const int total_rects = total_glyphs_count + atlas->CustomRects.size(); + float min_rects_per_row = ceilf((atlas->TexWidth / (max_glyph_size.x + 1.0f))); + float min_rects_per_column = ceilf(total_rects / min_rects_per_row); + atlas->TexHeight = (int)(min_rects_per_column * (max_glyph_size.y + 1.0f)); + + // Create texture + atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight); + atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); + atlas->TexPixelsAlpha8 = (unsigned char*)ImGui::MemAlloc(atlas->TexWidth * atlas->TexHeight); + memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight); + + // Start packing + ImVector<stbrp_node> pack_nodes; + pack_nodes.resize(total_rects); + stbrp_context context; + stbrp_init_target(&context, atlas->TexWidth, atlas->TexHeight, pack_nodes.Data, total_rects); + + // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). + ImFontAtlasBuildPackCustomRects(atlas, &context); + + // Render characters, setup ImFont and glyphs for runtime + for (int input_i = 0; input_i < atlas->ConfigData.Size; input_i++) + { + ImFontConfig& cfg = atlas->ConfigData[input_i]; + FreeTypeFont& font_face = fonts[input_i]; + ImFont* dst_font = cfg.DstFont; + if (cfg.MergeMode) + dst_font->BuildLookupTable(); + + const float ascent = font_face.Info.Ascender; + const float descent = font_face.Info.Descender; + ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); + const float font_off_x = cfg.GlyphOffset.x; + const float font_off_y = cfg.GlyphOffset.y + (float)(int)(dst_font->Ascent + 0.5f); + + bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f); + unsigned char multiply_table[256]; + if (multiply_enabled) + ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); + + for (const ImWchar* in_range = cfg.GlyphRanges; in_range[0] && in_range[1]; in_range += 2) + { + for (uint32_t codepoint = in_range[0]; codepoint <= in_range[1]; ++codepoint) + { + if (cfg.MergeMode && dst_font->FindGlyphNoFallback((ImWchar)codepoint)) + continue; + + FT_Glyph ft_glyph = NULL; + FT_BitmapGlyph ft_glyph_bitmap = NULL; // NB: will point to bitmap within FT_Glyph + GlyphInfo glyph_info; + if (!font_face.CalcGlyphInfo(codepoint, glyph_info, ft_glyph, ft_glyph_bitmap)) + continue; + + // Pack rectangle + stbrp_rect rect; + rect.w = (uint16_t)glyph_info.Width + 1; // Account for texture filtering + rect.h = (uint16_t)glyph_info.Height + 1; + stbrp_pack_rects(&context, &rect, 1); + + // Copy rasterized pixels to main texture + uint8_t* blit_dst = atlas->TexPixelsAlpha8 + rect.y * atlas->TexWidth + rect.x; + font_face.BlitGlyph(ft_glyph_bitmap, blit_dst, atlas->TexWidth, multiply_enabled ? multiply_table : NULL); + FT_Done_Glyph(ft_glyph); + + float char_advance_x_org = glyph_info.AdvanceX; + float char_advance_x_mod = ImClamp(char_advance_x_org, cfg.GlyphMinAdvanceX, cfg.GlyphMaxAdvanceX); + float char_off_x = font_off_x; + if (char_advance_x_org != char_advance_x_mod) + char_off_x += cfg.PixelSnapH ? (float)(int)((char_advance_x_mod - char_advance_x_org) * 0.5f) : (char_advance_x_mod - char_advance_x_org) * 0.5f; + + // Register glyph + dst_font->AddGlyph((ImWchar)codepoint, + glyph_info.OffsetX + char_off_x, + glyph_info.OffsetY + font_off_y, + glyph_info.OffsetX + char_off_x + glyph_info.Width, + glyph_info.OffsetY + font_off_y + glyph_info.Height, + rect.x / (float)atlas->TexWidth, + rect.y / (float)atlas->TexHeight, + (rect.x + glyph_info.Width) / (float)atlas->TexWidth, + (rect.y + glyph_info.Height) / (float)atlas->TexHeight, + char_advance_x_mod); + } + } + } + + // Cleanup + for (int n = 0; n < fonts.Size; n++) + fonts[n].Shutdown(); + + ImFontAtlasBuildFinish(atlas); + + return true; +} diff --git a/3rdparty/imgui/misc/freetype/imgui_freetype.h b/3rdparty/imgui/misc/freetype/imgui_freetype.h new file mode 100644 index 00000000..b8062bf7 --- /dev/null +++ b/3rdparty/imgui/misc/freetype/imgui_freetype.h @@ -0,0 +1,31 @@ +// Wrapper to use Freetype (instead of stb_truetype) for Dear ImGui +// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype +// Original code by @Vuhdo (Aleksei Skriabin), maintained by @ocornut + +#pragma once + +#include "imgui.h" // IMGUI_API, ImFontAtlas + +namespace ImGuiFreeType +{ + // Hinting greatly impacts visuals (and glyph sizes). + // When disabled, FreeType generates blurrier glyphs, more or less matches the stb's output. + // The Default hinting mode usually looks good, but may distort glyphs in an unusual way. + // The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer. + + // You can set those flags on a per font basis in ImFontConfig::RasterizerFlags. + // Use the 'extra_flags' parameter of BuildFontAtlas() to force a flag on all your fonts. + enum RasterizerFlags + { + // By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter. + NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes. + NoAutoHint = 1 << 1, // Disable auto-hinter. + ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter. + LightHinting = 1 << 3, // A lighter hinting algorithm for gray-level modes. Many generated glyphs are fuzzier but better resemble their original shape. This is achieved by snapping glyphs to the pixel grid only vertically (Y-axis), as is done by Microsoft's ClearType and Adobe's proprietary font renderer. This preserves inter-glyph spacing in horizontal text. + MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output. + Bold = 1 << 5, // Styling: Should we artificially embolden the font? + Oblique = 1 << 6 // Styling: Should we slant the font, emulating italic style? + }; + + IMGUI_API bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int extra_flags = 0); +} diff --git a/3rdparty/imgui/misc/natvis/README.txt b/3rdparty/imgui/misc/natvis/README.txt new file mode 100644 index 00000000..60073874 --- /dev/null +++ b/3rdparty/imgui/misc/natvis/README.txt @@ -0,0 +1,4 @@ + +Natvis file to describe dear imgui types in the Visual Studio debugger. +With this, types like ImVector<> will be displayed nicely in the debugger. +You can include this file a Visual Studio project file, or install it in Visual Studio folder. diff --git a/3rdparty/imgui/misc/natvis/imgui.natvis b/3rdparty/imgui/misc/natvis/imgui.natvis new file mode 100644 index 00000000..48b20426 --- /dev/null +++ b/3rdparty/imgui/misc/natvis/imgui.natvis @@ -0,0 +1,39 @@ +<?xml version="1.0" encoding="utf-8"?> + +<!-- natvis file for Visual Studio debugger (you can include this in a project file, or install in visual studio folder) --> + +<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010"> + +<Type Name="ImVector<*>"> + <DisplayString>{{Size={Size} Capacity={Capacity}}}</DisplayString> + <Expand> + <ArrayItems> + <Size>Size</Size> + <ValuePointer>Data</ValuePointer> + </ArrayItems> + </Expand> +</Type> + +<Type Name="ImVec2"> + <DisplayString>{{x={x,g} y={y,g}}}</DisplayString> +</Type> + +<Type Name="ImVec4"> + <DisplayString>{{x={x,g} y={y,g} z={z,g} w={w,g}}}</DisplayString> +</Type> + +<Type Name="ImRect"> + <DisplayString>{{Min=({Min.x,g} {Min.y,g}) Max=({Max.x,g} {Max.y,g}) Size=({Max.x-Min.x,g} {Max.y-Min.y,g})}}</DisplayString> + <Expand> + <Item Name="Min">Min</Item> + <Item Name="Max">Max</Item> + <Item Name="[Width]">Max.x - Min.x</Item> + <Item Name="[Height]">Max.y - Min.y</Item> + </Expand> +</Type> + +<Type Name="ImGuiWindow"> + <DisplayString>{{Name={Name,s} Active {(Active||WasActive)?1:0,d} Child {(Flags & 0x01000000)?1:0,d} Popup {(Flags & 0x04000000)?1:0,d}}</DisplayString> +</Type> + +</AutoVisualizer>
\ No newline at end of file |