├── dwm-overlay ├── third-party │ ├── imgui │ │ ├── misc │ │ │ ├── fonts │ │ │ │ ├── DroidSans.ttf │ │ │ │ ├── ProggyClean.ttf │ │ │ │ ├── ProggyTiny.ttf │ │ │ │ ├── Karla-Regular.ttf │ │ │ │ ├── Roboto-Medium.ttf │ │ │ │ ├── Cousine-Regular.ttf │ │ │ │ └── binary_to_compressed_c.cpp │ │ │ ├── debuggers │ │ │ │ ├── README.txt │ │ │ │ ├── imgui.gdb │ │ │ │ ├── imgui.natstepfilter │ │ │ │ └── imgui.natvis │ │ │ ├── cpp │ │ │ │ ├── README.txt │ │ │ │ ├── imgui_stdlib.h │ │ │ │ └── imgui_stdlib.cpp │ │ │ ├── README.txt │ │ │ ├── single_file │ │ │ │ └── imgui_single_file.h │ │ │ └── freetype │ │ │ │ ├── README.md │ │ │ │ ├── imgui_freetype.h │ │ │ │ └── imgui_freetype.cpp │ │ ├── LICENSE.txt │ │ ├── backends │ │ │ ├── imgui_impl_dx11.h │ │ │ ├── imgui_impl_win32.h │ │ │ └── imgui_impl_dx11.cpp │ │ ├── imconfig.h │ │ └── imstb_rectpack.h │ ├── vmprotect │ │ ├── lib │ │ │ ├── vmprotectsdk32.lib │ │ │ └── vmprotectsdk64.lib │ │ ├── license.txt │ │ └── include │ │ │ └── vmprotectsdk.h │ └── vtablehook │ │ ├── src │ │ └── vtablehook.cpp │ │ ├── license.txt │ │ └── include │ │ └── vtablehook.h ├── dwm-overlay.vcxproj.user ├── dwm-overlay.vcxproj.filters ├── include │ └── dxgi │ │ └── undocumented.h ├── src │ └── dllmain │ │ └── dllmain.cpp └── dwm-overlay.vcxproj ├── license.txt ├── dwm-overlay.sln └── readme.md /dwm-overlay/third-party/imgui/misc/fonts/DroidSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aurenex/dwm-overlay/HEAD/dwm-overlay/third-party/imgui/misc/fonts/DroidSans.ttf -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/fonts/ProggyClean.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aurenex/dwm-overlay/HEAD/dwm-overlay/third-party/imgui/misc/fonts/ProggyClean.ttf -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/fonts/ProggyTiny.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aurenex/dwm-overlay/HEAD/dwm-overlay/third-party/imgui/misc/fonts/ProggyTiny.ttf -------------------------------------------------------------------------------- /dwm-overlay/third-party/vmprotect/lib/vmprotectsdk32.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aurenex/dwm-overlay/HEAD/dwm-overlay/third-party/vmprotect/lib/vmprotectsdk32.lib -------------------------------------------------------------------------------- /dwm-overlay/third-party/vmprotect/lib/vmprotectsdk64.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aurenex/dwm-overlay/HEAD/dwm-overlay/third-party/vmprotect/lib/vmprotectsdk64.lib -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/fonts/Karla-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aurenex/dwm-overlay/HEAD/dwm-overlay/third-party/imgui/misc/fonts/Karla-Regular.ttf -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/fonts/Roboto-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aurenex/dwm-overlay/HEAD/dwm-overlay/third-party/imgui/misc/fonts/Roboto-Medium.ttf -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/fonts/Cousine-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aurenex/dwm-overlay/HEAD/dwm-overlay/third-party/imgui/misc/fonts/Cousine-Regular.ttf -------------------------------------------------------------------------------- /dwm-overlay/dwm-overlay.vcxproj.user: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | true 5 | 6 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/debuggers/README.txt: -------------------------------------------------------------------------------- 1 | 2 | HELPER FILES FOR POPULAR DEBUGGERS 3 | 4 | imgui.gdb 5 | GDB: disable stepping into trivial functions. 6 | (read comments inside file for details) 7 | 8 | imgui.natstepfilter 9 | Visual Studio Debugger: disable stepping into trivial functions. 10 | (read comments inside file for details) 11 | 12 | imgui.natvis 13 | Visual Studio Debugger: describe Dear ImGui types for better display. 14 | With this, types like ImVector<> will be displayed nicely in the debugger. 15 | (read comments inside file for details) 16 | 17 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/debuggers/imgui.gdb: -------------------------------------------------------------------------------- 1 | # GDB configuration to aid debugging experience 2 | 3 | # To enable these customizations edit $HOME/.gdbinit (or ./.gdbinit if local gdbinit is enabled) and add: 4 | # add-auto-load-safe-path /path/to/imgui.gdb 5 | # source /path/to/imgui.gdb 6 | # 7 | # More Information at: 8 | # * https://sourceware.org/gdb/current/onlinedocs/gdb/gdbinit-man.html 9 | # * https://sourceware.org/gdb/current/onlinedocs/gdb/Init-File-in-the-Current-Directory.html#Init-File-in-the-Current-Directory 10 | 11 | # Disable stepping into trivial functions 12 | skip -rfunction Im(Vec2|Vec4|Strv|Vector|Span)::.+ 13 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/cpp/README.txt: -------------------------------------------------------------------------------- 1 | 2 | imgui_stdlib.h + imgui_stdlib.cpp 3 | InputText() wrappers for C++ standard library (STL) type: std::string. 4 | This is also an example of how you may wrap your own similar types. 5 | 6 | imgui_scoped.h 7 | [Experimental, not currently in main repository] 8 | Additional header file with some RAII-style wrappers for common Dear ImGui functions. 9 | Try by merging: https://github.com/ocornut/imgui/pull/2197 10 | Discuss at: https://github.com/ocornut/imgui/issues/2096 11 | 12 | See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki: 13 | https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness 14 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/vtablehook/src/vtablehook.cpp: -------------------------------------------------------------------------------- 1 | #include "vtablehook/include/vtablehook.h" 2 | 3 | int unprotect(void* region) 4 | { 5 | MEMORY_BASIC_INFORMATION mbi; 6 | VirtualQuery((LPCVOID)region, &mbi, sizeof(mbi)); 7 | VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_READWRITE, &mbi.Protect); 8 | return mbi.Protect; 9 | } 10 | 11 | void protect(void* region, int protection) 12 | { 13 | MEMORY_BASIC_INFORMATION mbi; 14 | VirtualQuery((LPCVOID)region, &mbi, sizeof(mbi)); 15 | VirtualProtect(mbi.BaseAddress, mbi.RegionSize, protection, &mbi.Protect); 16 | } 17 | 18 | void* vtable::hook(void* instance, void* hook, int offset) 19 | { 20 | intptr_t vtable = *((intptr_t*)instance); 21 | intptr_t entry = vtable + sizeof(intptr_t) * offset; 22 | intptr_t original = *((intptr_t*)entry); 23 | 24 | int original_protection = unprotect((void*)entry); 25 | *((intptr_t*)entry) = (intptr_t)hook; 26 | protect((void*)entry, original_protection); 27 | 28 | return (void*)original; 29 | } -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/README.txt: -------------------------------------------------------------------------------- 1 | 2 | misc/cpp/ 3 | InputText() wrappers for C++ standard library (STL) type: std::string. 4 | This is also an example of how you may wrap your own similar types. 5 | 6 | misc/debuggers/ 7 | Helper files for popular debuggers. 8 | With the .natvis file, types like ImVector<> will be displayed nicely in Visual Studio debugger. 9 | 10 | misc/fonts/ 11 | Fonts loading/merging instructions (e.g. How to handle glyph ranges, how to merge icons fonts). 12 | Command line tool "binary_to_compressed_c" to create compressed arrays to embed data in source code. 13 | Suggested fonts and links. 14 | 15 | misc/freetype/ 16 | Font atlas builder/rasterizer using FreeType instead of stb_truetype. 17 | Benefit from better FreeType rasterization, in particular for small fonts. 18 | 19 | misc/single_file/ 20 | Single-file header stub. 21 | We use this to validate compiling all *.cpp files in a same compilation unit. 22 | Users of that technique (also called "Unity builds") can generally provide this themselves, 23 | so we don't really recommend you use this in your projects. 24 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Aurenex 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/single_file/imgui_single_file.h: -------------------------------------------------------------------------------- 1 | // dear imgui: single-file wrapper include 2 | // We use this to validate compiling all *.cpp files in a same compilation unit. 3 | // Users of that technique (also called "Unity builds") can generally provide this themselves, 4 | // so we don't really recommend you use this in your projects. 5 | 6 | // Do this: 7 | // #define IMGUI_IMPLEMENTATION 8 | // Before you include this file in *one* C++ file to create the implementation. 9 | // Using this in your project will leak the contents of imgui_internal.h and ImVec2 operators in this compilation unit. 10 | 11 | #ifdef IMGUI_IMPLEMENTATION 12 | #define IMGUI_DEFINE_MATH_OPERATORS 13 | #endif 14 | 15 | #include "../../imgui.h" 16 | #ifdef IMGUI_ENABLE_FREETYPE 17 | #include "../../misc/freetype/imgui_freetype.h" 18 | #endif 19 | 20 | #ifdef IMGUI_IMPLEMENTATION 21 | #include "../../imgui.cpp" 22 | #include "../../imgui_demo.cpp" 23 | #include "../../imgui_draw.cpp" 24 | #include "../../imgui_tables.cpp" 25 | #include "../../imgui_widgets.cpp" 26 | #ifdef IMGUI_ENABLE_FREETYPE 27 | #include "../../misc/freetype/imgui_freetype.cpp" 28 | #endif 29 | #endif 30 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/vtablehook/license.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2013 Thordin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/LICENSE.txt: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014-2024 Omar Cornut 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/cpp/imgui_stdlib.h: -------------------------------------------------------------------------------- 1 | // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) 2 | // This is also an example of how you may wrap your own similar types. 3 | 4 | // Changelog: 5 | // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string 6 | 7 | // See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki: 8 | // https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness 9 | 10 | #pragma once 11 | 12 | #include 13 | 14 | namespace ImGui 15 | { 16 | // ImGui::InputText() with std::string 17 | // Because text input needs dynamic resizing, we need to setup a callback to grow the capacity 18 | IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr); 19 | IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr); 20 | IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr); 21 | } 22 | -------------------------------------------------------------------------------- /dwm-overlay.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 17 4 | VisualStudioVersion = 17.8.34511.84 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dwm-overlay", "dwm-overlay\dwm-overlay.vcxproj", "{210C8DB9-E1FA-4714-B18D-8129EAAB2E1D}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|x64 = Debug|x64 11 | Debug|x86 = Debug|x86 12 | Release|x64 = Release|x64 13 | Release|x86 = Release|x86 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {210C8DB9-E1FA-4714-B18D-8129EAAB2E1D}.Debug|x64.ActiveCfg = Debug|x64 17 | {210C8DB9-E1FA-4714-B18D-8129EAAB2E1D}.Debug|x64.Build.0 = Debug|x64 18 | {210C8DB9-E1FA-4714-B18D-8129EAAB2E1D}.Debug|x86.ActiveCfg = Debug|Win32 19 | {210C8DB9-E1FA-4714-B18D-8129EAAB2E1D}.Debug|x86.Build.0 = Debug|Win32 20 | {210C8DB9-E1FA-4714-B18D-8129EAAB2E1D}.Release|x64.ActiveCfg = Release|x64 21 | {210C8DB9-E1FA-4714-B18D-8129EAAB2E1D}.Release|x64.Build.0 = Release|x64 22 | {210C8DB9-E1FA-4714-B18D-8129EAAB2E1D}.Release|x86.ActiveCfg = Release|Win32 23 | {210C8DB9-E1FA-4714-B18D-8129EAAB2E1D}.Release|x86.Build.0 = Release|Win32 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {6B4AF21A-1ABF-407C-8761-69CE2C8749C8} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/vtablehook/include/vtablehook.h: -------------------------------------------------------------------------------- 1 | /* 2 | The MIT License (MIT) 3 | 4 | Copyright (c) 2013 Thordin 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 10 | the Software, and to permit persons to whom the Software is furnished to do so, 11 | subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include 25 | 26 | namespace vtable 27 | { 28 | /// pointer to an instance of a class 29 | /// function to overwrite with 30 | /// 31 | /// original function 32 | void* hook(void* instance, void* hook, int offset); 33 | } -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/debuggers/imgui.natstepfilter: -------------------------------------------------------------------------------- 1 | 2 | 18 | 19 | 20 | 21 | 22 | 23 | (ImVec2|ImVec4|ImStrv)::.+ 24 | NoStepInto 25 | 26 | 27 | (ImVector|ImSpan).*::operator.+ 28 | NoStepInto 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # dwm-overlay 2 | 3 | This may be the first DWM overlay project on GitHub that gets a pointer to the IDXGISwapChainDWMLegacy virtual function table without a memory scan, using undocumented GUIDs. By default, this project only works on Windows 10/11. To support older OS versions, you need to update the offsets for the virtual function table. 4 | 5 | 6 | Sorry for the shitty code, I'll do better later. 7 | 8 | ![dwm-overlay-preview](https://github.com/aurenex/dwm-overlay/assets/125130325/eae17979-1a9a-4ab8-8b72-555331951adc) 9 | 10 | Subscribe to my Telegram [channel][tg-channel-link] or make a donation if you want to support me. 11 | 12 | ### Bugs 13 | - ~~Debug version causes system to freeze~~. 14 | - Duplicating an overlay in an area that is not updating. 15 | - The overlay disappears after reconnecting the monitor. 16 | - Doesn't work on Win11 24H2+ with NVIDIA graphics cards. 17 | 18 | ### Compilation 19 | - Clone or [download][repo-download-link] this repository. 20 | - Open the **dwm-overlay** solution file in [Visual Studio IDE][vs-download-link]. 21 | - Select the target platform. 22 | - Press `ctrl + shift + b` to compile. 23 | 24 | ### Usage 25 | - Open any DLL-injector **as administrator**. 26 | - Find the **dwm.exe** process. 27 | - Inject the `dwm-overlay.dll` into process. 28 | 29 | Before use, we strongly recommend that you read the [license][license-link]. 30 | 31 | [repo-download-link]: 32 | [vs-download-link]: 33 | [tg-channel-link]: 34 | [license-link]: <../master/license.txt> 35 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/vmprotect/license.txt: -------------------------------------------------------------------------------- 1 | All copyrights and property rights to VMProtect are exclusively owned by VMProtect Software. 2 | VMProtect is a commercial software. To receive more detailed information on how to buy the software please email info@vmpsoft.com 3 | The author reserves the right to cancel the validity of the given license for any of the further version of demo version of VMProtect. 4 | Using VMProtect for commercial purposes is forbidden, including renting or selling it, incorporating it into other programs or systems, using it in third-party software, or providing software protection services to third parties. 5 | The author guarantees that our software does not contain viruses, trojans, or other malicious code. If an antivirus detects such code in software protected by VMProtect, it may be a false positive and should not be used as a reason for a refund. 6 | VMPROTECT IS DISTRIBUTED 'AS IS'. NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE THE SOFTWARE AT YOUR OWN RISK. THE AUTHOR WILL NOT BE RESPONSIBLE FOR DATA LOSS, DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING OR MISUSING THIS SOFTWARE. 7 | You are not allowed to modify, create new versions, rent, sell, decompile, disassemble, otherwise reverse engineer, alter, delete, or hide trademarks and notices of copyrights. Using VMProtect to hide viruses, trojans, key loggers, or other malicious code is not allowed. Using it in software that violates the intellectual property rights of third parties (such as key generators, cracks, patches, or loaders) is also not allowed. 8 | Installing and using VMProtect means that you accept the terms and conditions of this license. Any violation of the terms of this agreement will result in immediate and automatic termination of this license without compensation of any charges related to the use of VMProtect and may result in criminal and/or civil prosecution. 9 | If you do not agree with the terms of this license, you must remove VMProtect files from your storage devices and stop using VMProtect. -------------------------------------------------------------------------------- /dwm-overlay/dwm-overlay.vcxproj.filters: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | 18 | 19 | Source Files 20 | 21 | 22 | Source Files 23 | 24 | 25 | Source Files 26 | 27 | 28 | Source Files 29 | 30 | 31 | Source Files 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Source Files 41 | 42 | 43 | 44 | 45 | Header Files 46 | 47 | 48 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/debuggers/imgui.natvis: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | 16 | 17 | {{Size={Size} Capacity={Capacity}}} 18 | 19 | 20 | Size 21 | Data 22 | 23 | 24 | 25 | 26 | 27 | {{Size={DataEnd-Data} }} 28 | 29 | 30 | DataEnd-Data 31 | Data 32 | 33 | 34 | 35 | 36 | 37 | {{x={x,g} y={y,g}}} 38 | 39 | 40 | 41 | {{x={x,g} y={y,g} z={z,g} w={w,g}}} 42 | 43 | 44 | 45 | {{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})}} 46 | 47 | Min 48 | Max 49 | Max.x - Min.x 50 | Max.y - Min.y 51 | 52 | 53 | 54 | 55 | {{Name {Name,s} Active {(Active||WasActive)?1:0,d} Child {(Flags & 0x01000000)?1:0,d} Popup {(Flags & 0x04000000)?1:0,d} Hidden {(Hidden)?1:0,d}} 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /dwm-overlay/include/dxgi/undocumented.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Undocumented DXGI structures 3 | * 4 | * Windows 10 21H2 IoT LTSC 5 | * dxgi.dll 10.0.19041.5794 6 | * 7 | * https://t.me/rxznve 8 | * https://t.me/aurenex 9 | * https://github.com/aurenex 10 | */ 11 | 12 | #ifndef DXGI_UNDOCUMENTED_H_GUARD 13 | #define DXGI_UNDOCUMENTED_H_GUARD 14 | 15 | // DXGI_SCROLL_RECT 24 (0x18) bytes 16 | typedef struct _DXGI_SCROLL_RECT 17 | { 18 | POINT offset; 19 | RECT region; 20 | } DXGI_SCROLL_RECT; 21 | 22 | // DXGI_PRESENT_MULTIPLANE_OVERLAY 136 (0x88) bytes 23 | typedef struct _DXGI_PRESENT_MULTIPLANE_OVERLAY 24 | { 25 | UINT LayerIndex; 26 | UINT Flags; 27 | char unknown1[0x14]; 28 | RECT SrcRect; 29 | RECT DstRect; 30 | RECT ClipRect; 31 | DXGI_MODE_ROTATION Rotation; 32 | char unknown2[0x04]; // Maybe blend 33 | UINT DirtyRectsCount; 34 | RECT* pDirtyRects; 35 | char unknown3[0x28]; 36 | } DXGI_PRESENT_MULTIPLANE_OVERLAY; 37 | 38 | MIDL_INTERFACE("f69f223b-45d3-4aa0-98c8-c40c2b231029") 39 | IDXGISwapChainDWMLegacy : public IDXGIDeviceSubObject 40 | { 41 | virtual HRESULT STDMETHODCALLTYPE Present 42 | ( 43 | UINT SyncInterval, 44 | UINT Flags 45 | ) = 0; 46 | 47 | virtual HRESULT STDMETHODCALLTYPE GetBuffer 48 | ( 49 | UINT Buffer, 50 | REFIID riid, 51 | void** ppSurface 52 | ) = 0; 53 | }; 54 | 55 | MIDL_INTERFACE("713f394e-92ca-47e7-ab81-1159c2791e54") 56 | IDXGIFactoryDWM : public IUnknown 57 | { 58 | virtual HRESULT STDMETHODCALLTYPE CreateSwapChain 59 | ( 60 | IUnknown* pDevice, 61 | DXGI_SWAP_CHAIN_DESC* pDesc, 62 | IDXGIOutput* pOutput, 63 | IDXGISwapChainDWMLegacy** ppSwapChainDWM 64 | ) = 0; 65 | }; 66 | 67 | HRESULT (STDMETHODCALLTYPE* PresentDWM) 68 | ( 69 | IDXGISwapChainDWMLegacy* pSwapChain, 70 | UINT SyncInterval, 71 | UINT PresentFlags, 72 | UINT DirtyRectsCount, 73 | const RECT* pDirtyRects, 74 | UINT ScrollRectsCount, 75 | const DXGI_SCROLL_RECT* pScrollRects, 76 | IDXGIResource* pResource, 77 | UINT FrameIndex // ??? 78 | ); 79 | 80 | HRESULT (STDMETHODCALLTYPE* PresentMultiplaneOverlay) 81 | ( 82 | IDXGISwapChainDWMLegacy* pSwapChain, 83 | UINT SyncInterval, 84 | UINT PresentFlags, 85 | DXGI_HDR_METADATA_TYPE MetadataType, 86 | const VOID* pMetadata, 87 | UINT OverlayCount, 88 | const DXGI_PRESENT_MULTIPLANE_OVERLAY* pOverlays 89 | ); 90 | 91 | #endif //DXGI_UNDOCUMENTED_H_GUARD -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/backends/imgui_impl_dx11.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX11 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). 7 | // [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. 8 | 9 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 10 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 11 | // Learn about Dear ImGui: 12 | // - FAQ https://dearimgui.com/faq 13 | // - Getting Started https://dearimgui.com/getting-started 14 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 15 | // - Introduction, links and more at the top of imgui.cpp 16 | 17 | #pragma once 18 | #include "imgui.h" // IMGUI_IMPL_API 19 | #ifndef IMGUI_DISABLE 20 | 21 | struct ID3D11Device; 22 | struct ID3D11DeviceContext; 23 | struct ID3D11SamplerState; 24 | 25 | // Follow "Getting Started" link and check examples/ folder to learn about using backends! 26 | IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context); 27 | IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown(); 28 | IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame(); 29 | IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); 30 | 31 | // Use if you want to reset your rendering device without losing Dear ImGui state. 32 | IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); 33 | IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); 34 | 35 | // [BETA] Selected render state data shared with callbacks. 36 | // This is temporarily stored in GetPlatformIO().Renderer_RenderState during the ImGui_ImplDX11_RenderDrawData() call. 37 | // (Please open an issue if you feel you need access to more data) 38 | struct ImGui_ImplDX11_RenderState 39 | { 40 | ID3D11Device* Device; 41 | ID3D11DeviceContext* DeviceContext; 42 | ID3D11SamplerState* SamplerDefault; 43 | }; 44 | 45 | #endif // #ifndef IMGUI_DISABLE 46 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/freetype/README.md: -------------------------------------------------------------------------------- 1 | # imgui_freetype 2 | 3 | Build font atlases using FreeType instead of stb_truetype (which is the default font rasterizer). 4 |
by @vuhdo, @mikesart, @ocornut. 5 | 6 | ### Usage 7 | 8 | 1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype --triplet=x64-windows`, `vcpkg integrate install`). 9 | 2. Add imgui_freetype.h/cpp alongside your project files. 10 | 3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file 11 | 12 | ### About Gamma Correct Blending 13 | 14 | FreeType assumes blending in linear space rather than gamma space. 15 | See FreeType note for [FT_Render_Glyph](https://freetype.org/freetype2/docs/reference/ft2-glyph_retrieval.html#ft_render_glyph). 16 | For correct results you need to be using sRGB and convert to linear space in the pixel shader output. 17 | The default Dear ImGui styles will be impacted by this change (alpha values will need tweaking). 18 | 19 | ### Testbed for toying with settings (for developers) 20 | 21 | See https://gist.github.com/ocornut/b3a9ecf13502fd818799a452969649ad 22 | 23 | ### Known issues 24 | 25 | - Oversampling settings are ignored but also not so much necessary with the higher quality rendering. 26 | 27 | ### Comparison 28 | 29 | Small, thin anti-aliased fonts typically benefit a lot from FreeType's hinting: 30 | ![comparing_font_rasterizers](https://user-images.githubusercontent.com/8225057/107550178-fef87f00-6bd0-11eb-8d09-e2edb2f0ccfc.gif) 31 | 32 | ### Colorful glyphs/emojis 33 | 34 | You can use the `ImGuiFreeTypeBuilderFlags_LoadColor` flag to load certain colorful glyphs. See the 35 | ["Using Colorful Glyphs/Emojis"](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md#using-colorful-glyphsemojis) section of FONTS.md. 36 | 37 | ![colored glyphs](https://user-images.githubusercontent.com/8225057/106171241-9dc4ba80-6191-11eb-8a69-ca1467b206d1.png) 38 | 39 | ### Using OpenType SVG fonts (SVGinOT) 40 | - *SVG in Open Type* is a standard by Adobe and Mozilla for color OpenType and Open Font Format fonts. It allows font creators to embed complete SVG files within a font enabling full color and even animations. 41 | - Popular fonts such as [twemoji](https://github.com/13rac1/twemoji-color-font) and fonts made with [scfbuild](https://github.com/13rac1/scfbuild) is SVGinOT 42 | - Two alternatives are possible to render SVG fonts: use "lunasvg" or "plutosvg". plutosvg will support some more fonts (e.g. NotoColorEmoji-Regular) and may load them faster. 43 | 44 | #### Using lunasvg 45 | Requires: [lunasvg](https://github.com/sammycage/lunasvg) v2.3.2 and above 46 | - Add `#define IMGUI_ENABLE_FREETYPE_LUNASVG` in your `imconfig.h`. 47 | - Get latest lunasvg binaries or build yourself. Under Windows you may use vcpkg with: `vcpkg install lunasvg --triplet=x64-windows`. 48 | 49 | #### Using plutosvg (and plutovg) 50 | - Add `#define IMGUI_ENABLE_FREETYPE_PLUTOSVG` in your `imconfig.h`. 51 | - Compile and link with plutosvg *and* plutovg (which is required by plutosvg) 52 | 53 | _Compilation hints for plutovg_ 54 | - Compile all source files in `plutovg/source/*.c` 55 | - Add include directory: `plutovg/include` + `plutovg/stb` 56 | 57 | _Compilation hints for plutosvg_ 58 | - Compile `plutosvg/source/plutosvg.c` 59 | - Add include directory: `plutosvg/source` 60 | - Add define: `PLUTOSVG_HAS_FREETYPE` 61 | - Link with: plutovg, freetype 62 | 63 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/cpp/imgui_stdlib.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.) 2 | // This is also an example of how you may wrap your own similar types. 3 | 4 | // Changelog: 5 | // - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string 6 | 7 | // See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki: 8 | // https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness 9 | 10 | #include "imgui.h" 11 | #include "imgui_stdlib.h" 12 | 13 | // Clang warnings with -Weverything 14 | #if defined(__clang__) 15 | #pragma clang diagnostic push 16 | #pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness 17 | #endif 18 | 19 | struct InputTextCallback_UserData 20 | { 21 | std::string* Str; 22 | ImGuiInputTextCallback ChainCallback; 23 | void* ChainCallbackUserData; 24 | }; 25 | 26 | static int InputTextCallback(ImGuiInputTextCallbackData* data) 27 | { 28 | InputTextCallback_UserData* user_data = (InputTextCallback_UserData*)data->UserData; 29 | if (data->EventFlag == ImGuiInputTextFlags_CallbackResize) 30 | { 31 | // Resize string callback 32 | // If for some reason we refuse the new length (BufTextLen) and/or capacity (BufSize) we need to set them back to what we want. 33 | std::string* str = user_data->Str; 34 | IM_ASSERT(data->Buf == str->c_str()); 35 | str->resize(data->BufTextLen); 36 | data->Buf = (char*)str->c_str(); 37 | } 38 | else if (user_data->ChainCallback) 39 | { 40 | // Forward to user callback, if any 41 | data->UserData = user_data->ChainCallbackUserData; 42 | return user_data->ChainCallback(data); 43 | } 44 | return 0; 45 | } 46 | 47 | bool ImGui::InputText(const char* label, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) 48 | { 49 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); 50 | flags |= ImGuiInputTextFlags_CallbackResize; 51 | 52 | InputTextCallback_UserData cb_user_data; 53 | cb_user_data.Str = str; 54 | cb_user_data.ChainCallback = callback; 55 | cb_user_data.ChainCallbackUserData = user_data; 56 | return InputText(label, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); 57 | } 58 | 59 | bool ImGui::InputTextMultiline(const char* label, std::string* str, const ImVec2& size, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) 60 | { 61 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); 62 | flags |= ImGuiInputTextFlags_CallbackResize; 63 | 64 | InputTextCallback_UserData cb_user_data; 65 | cb_user_data.Str = str; 66 | cb_user_data.ChainCallback = callback; 67 | cb_user_data.ChainCallbackUserData = user_data; 68 | return InputTextMultiline(label, (char*)str->c_str(), str->capacity() + 1, size, flags, InputTextCallback, &cb_user_data); 69 | } 70 | 71 | bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags, ImGuiInputTextCallback callback, void* user_data) 72 | { 73 | IM_ASSERT((flags & ImGuiInputTextFlags_CallbackResize) == 0); 74 | flags |= ImGuiInputTextFlags_CallbackResize; 75 | 76 | InputTextCallback_UserData cb_user_data; 77 | cb_user_data.Str = str; 78 | cb_user_data.ChainCallback = callback; 79 | cb_user_data.ChainCallbackUserData = user_data; 80 | return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data); 81 | } 82 | 83 | #if defined(__clang__) 84 | #pragma clang diagnostic pop 85 | #endif 86 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/backends/imgui_impl_win32.h: -------------------------------------------------------------------------------- 1 | // dear imgui: Platform Backend for Windows (standard windows API for 32-bits AND 64-bits applications) 2 | // This needs to be used along with a Renderer (e.g. DirectX11, OpenGL3, Vulkan..) 3 | 4 | // Implemented features: 5 | // [X] Platform: Clipboard support (for Win32 this is actually part of core dear imgui) 6 | // [X] Platform: Mouse support. Can discriminate Mouse/TouchScreen/Pen. 7 | // [X] Platform: Keyboard support. Since 1.87 we are using the io.AddKeyEvent() function. Pass ImGuiKey values to all key functions e.g. ImGui::IsKeyPressed(ImGuiKey_Space). [Legacy VK_* values are obsolete since 1.87 and not supported since 1.91.5] 8 | // [X] Platform: Gamepad support. Enabled with 'io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad'. 9 | // [X] Platform: Mouse cursor shape and visibility (ImGuiBackendFlags_HasMouseCursors). Disable with 'io.ConfigFlags |= ImGuiConfigFlags_NoMouseCursorChange'. 10 | 11 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 12 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 13 | // Learn about Dear ImGui: 14 | // - FAQ https://dearimgui.com/faq 15 | // - Getting Started https://dearimgui.com/getting-started 16 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 17 | // - Introduction, links and more at the top of imgui.cpp 18 | 19 | #pragma once 20 | #include "imgui.h" // IMGUI_IMPL_API 21 | #ifndef IMGUI_DISABLE 22 | 23 | // Follow "Getting Started" link and check examples/ folder to learn about using backends! 24 | IMGUI_IMPL_API bool ImGui_ImplWin32_Init(void* hwnd); 25 | IMGUI_IMPL_API bool ImGui_ImplWin32_InitForOpenGL(void* hwnd); 26 | IMGUI_IMPL_API void ImGui_ImplWin32_Shutdown(); 27 | IMGUI_IMPL_API void ImGui_ImplWin32_NewFrame(); 28 | 29 | // Win32 message handler your application need to call. 30 | // - Intentionally commented out in a '#if 0' block to avoid dragging dependencies on from this helper. 31 | // - You should COPY the line below into your .cpp code to forward declare the function and then you can call it. 32 | // - Call from your application's message handler. Keep calling your message handler unless this function returns TRUE. 33 | 34 | #if 0 35 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 36 | #endif 37 | 38 | // DPI-related helpers (optional) 39 | // - Use to enable DPI awareness without having to create an application manifest. 40 | // - Your own app may already do this via a manifest or explicit calls. This is mostly useful for our examples/ apps. 41 | // - In theory we could call simple functions from Windows SDK such as SetProcessDPIAware(), SetProcessDpiAwareness(), etc. 42 | // but most of the functions provided by Microsoft require Windows 8.1/10+ SDK at compile time and Windows 8/10+ at runtime, 43 | // neither we want to require the user to have. So we dynamically select and load those functions to avoid dependencies. 44 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableDpiAwareness(); 45 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForHwnd(void* hwnd); // HWND hwnd 46 | IMGUI_IMPL_API float ImGui_ImplWin32_GetDpiScaleForMonitor(void* monitor); // HMONITOR monitor 47 | 48 | // Transparency related helpers (optional) [experimental] 49 | // - Use to enable alpha compositing transparency with the desktop. 50 | // - Use together with e.g. clearing your framebuffer with zero-alpha. 51 | IMGUI_IMPL_API void ImGui_ImplWin32_EnableAlphaCompositing(void* hwnd); // HWND hwnd 52 | 53 | #endif // #ifndef IMGUI_DISABLE 54 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/vmprotect/include/vmprotectsdk.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #if defined(__APPLE__) || defined(__unix__) 4 | #define VMP_IMPORT 5 | #define VMP_API 6 | #define VMP_WCHAR unsigned short 7 | #else 8 | #define VMP_IMPORT __declspec(dllimport) 9 | #define VMP_API __stdcall 10 | #define VMP_WCHAR wchar_t 11 | #ifdef _M_IX86 12 | #pragma comment(lib, "vmprotect/lib/vmprotectsdk32.lib") 13 | #elif _M_X64 14 | #pragma comment(lib, "vmprotect/lib/vmprotectsdk64.lib") 15 | #elif _M_ARM64 16 | #pragma comment(lib, "vmprotect/lib/vmprotectarm64.lib") 17 | #else 18 | #error "Unsupported target architecture" 19 | #endif 20 | #endif // __APPLE__ || __unix__ 21 | 22 | #ifdef __cplusplus 23 | extern "C" { 24 | #endif 25 | 26 | // protection 27 | VMP_IMPORT void VMP_API VMProtectBegin(const char *); 28 | VMP_IMPORT void VMP_API VMProtectBeginVirtualization(const char *); 29 | VMP_IMPORT void VMP_API VMProtectBeginMutation(const char *); 30 | VMP_IMPORT void VMP_API VMProtectBeginUltra(const char *); 31 | VMP_IMPORT void VMP_API VMProtectBeginVirtualizationLockByKey(const char *); 32 | VMP_IMPORT void VMP_API VMProtectBeginUltraLockByKey(const char *); 33 | VMP_IMPORT void VMP_API VMProtectEnd(void); 34 | 35 | // utils 36 | VMP_IMPORT bool VMP_API VMProtectIsProtected(); 37 | VMP_IMPORT bool VMP_API VMProtectIsDebuggerPresent(bool); 38 | VMP_IMPORT bool VMP_API VMProtectIsVirtualMachinePresent(void); 39 | VMP_IMPORT bool VMP_API VMProtectIsValidImageCRC(void); 40 | VMP_IMPORT const char * VMP_API VMProtectDecryptStringA(const char *value); 41 | VMP_IMPORT const VMP_WCHAR * VMP_API VMProtectDecryptStringW(const VMP_WCHAR *value); 42 | VMP_IMPORT bool VMP_API VMProtectFreeString(const void *value); 43 | 44 | // licensing 45 | enum VMProtectSerialStateFlags 46 | { 47 | SERIAL_STATE_SUCCESS = 0, 48 | SERIAL_STATE_FLAG_CORRUPTED = 0x00000001, 49 | SERIAL_STATE_FLAG_INVALID = 0x00000002, 50 | SERIAL_STATE_FLAG_BLACKLISTED = 0x00000004, 51 | SERIAL_STATE_FLAG_DATE_EXPIRED = 0x00000008, 52 | SERIAL_STATE_FLAG_RUNNING_TIME_OVER = 0x00000010, 53 | SERIAL_STATE_FLAG_BAD_HWID = 0x00000020, 54 | SERIAL_STATE_FLAG_MAX_BUILD_EXPIRED = 0x00000040, 55 | }; 56 | 57 | #pragma pack(push, 1) 58 | typedef struct 59 | { 60 | unsigned short wYear; 61 | unsigned char bMonth; 62 | unsigned char bDay; 63 | } VMProtectDate; 64 | 65 | typedef struct 66 | { 67 | int nState; // VMProtectSerialStateFlags 68 | VMP_WCHAR wUserName[256]; // user name 69 | VMP_WCHAR wEMail[256]; // email 70 | VMProtectDate dtExpire; // date of serial number expiration 71 | VMProtectDate dtMaxBuild; // max date of build, that will accept this key 72 | int bRunningTime; // running time in minutes 73 | unsigned char nUserDataLength; // length of user data in bUserData 74 | unsigned char bUserData[255]; // up to 255 bytes of user data 75 | } VMProtectSerialNumberData; 76 | #pragma pack(pop) 77 | 78 | VMP_IMPORT int VMP_API VMProtectSetSerialNumber(const char *serial); 79 | VMP_IMPORT int VMP_API VMProtectGetSerialNumberState(); 80 | VMP_IMPORT bool VMP_API VMProtectGetSerialNumberData(VMProtectSerialNumberData *data, int size); 81 | VMP_IMPORT int VMP_API VMProtectGetCurrentHWID(char *hwid, int size); 82 | 83 | // activation 84 | enum VMProtectActivationFlags 85 | { 86 | ACTIVATION_OK = 0, 87 | ACTIVATION_SMALL_BUFFER, 88 | ACTIVATION_NO_CONNECTION, 89 | ACTIVATION_BAD_REPLY, 90 | ACTIVATION_BANNED, 91 | ACTIVATION_CORRUPTED, 92 | ACTIVATION_BAD_CODE, 93 | ACTIVATION_ALREADY_USED, 94 | ACTIVATION_SERIAL_UNKNOWN, 95 | ACTIVATION_EXPIRED, 96 | ACTIVATION_NOT_AVAILABLE 97 | }; 98 | 99 | VMP_IMPORT int VMP_API VMProtectActivateLicense(const char *code, char *serial, int size); 100 | VMP_IMPORT int VMP_API VMProtectDeactivateLicense(const char *serial); 101 | VMP_IMPORT int VMP_API VMProtectGetOfflineActivationString(const char *code, char *buf, int size); 102 | VMP_IMPORT int VMP_API VMProtectGetOfflineDeactivationString(const char *serial, char *buf, int size); 103 | 104 | #ifdef __cplusplus 105 | } 106 | #endif 107 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/freetype/imgui_freetype.h: -------------------------------------------------------------------------------- 1 | // dear imgui: FreeType font builder (used as a replacement for the stb_truetype builder) 2 | // (headers) 3 | 4 | #pragma once 5 | #include "imgui.h" // IMGUI_API 6 | #ifndef IMGUI_DISABLE 7 | 8 | // Usage: 9 | // - Add '#define IMGUI_ENABLE_FREETYPE' in your imconfig to enable support for imgui_freetype in imgui. 10 | 11 | // Optional support for OpenType SVG fonts: 12 | // - Add '#define IMGUI_ENABLE_FREETYPE_PLUTOSVG' to use plutosvg (not provided). See #7927. 13 | // - Add '#define IMGUI_ENABLE_FREETYPE_LUNASVG' to use lunasvg (not provided). See #6591. 14 | 15 | // Forward declarations 16 | struct ImFontAtlas; 17 | struct ImFontBuilderIO; 18 | 19 | // Hinting greatly impacts visuals (and glyph sizes). 20 | // - By default, hinting is enabled and the font's native hinter is preferred over the auto-hinter. 21 | // - When disabled, FreeType generates blurrier glyphs, more or less matches the stb_truetype.h 22 | // - The Default hinting mode usually looks good, but may distort glyphs in an unusual way. 23 | // - The Light hinting mode generates fuzzier glyphs but better matches Microsoft's rasterizer. 24 | // You can set those flags globaly in ImFontAtlas::FontBuilderFlags 25 | // You can set those flags on a per font basis in ImFontConfig::FontBuilderFlags 26 | enum ImGuiFreeTypeBuilderFlags 27 | { 28 | ImGuiFreeTypeBuilderFlags_NoHinting = 1 << 0, // Disable hinting. This generally generates 'blurrier' bitmap glyphs when the glyph are rendered in any of the anti-aliased modes. 29 | ImGuiFreeTypeBuilderFlags_NoAutoHint = 1 << 1, // Disable auto-hinter. 30 | ImGuiFreeTypeBuilderFlags_ForceAutoHint = 1 << 2, // Indicates that the auto-hinter is preferred over the font's native hinter. 31 | ImGuiFreeTypeBuilderFlags_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. 32 | ImGuiFreeTypeBuilderFlags_MonoHinting = 1 << 4, // Strong hinting algorithm that should only be used for monochrome output. 33 | ImGuiFreeTypeBuilderFlags_Bold = 1 << 5, // Styling: Should we artificially embolden the font? 34 | ImGuiFreeTypeBuilderFlags_Oblique = 1 << 6, // Styling: Should we slant the font, emulating italic style? 35 | ImGuiFreeTypeBuilderFlags_Monochrome = 1 << 7, // Disable anti-aliasing. Combine this with MonoHinting for best results! 36 | ImGuiFreeTypeBuilderFlags_LoadColor = 1 << 8, // Enable FreeType color-layered glyphs 37 | ImGuiFreeTypeBuilderFlags_Bitmap = 1 << 9 // Enable FreeType bitmap glyphs 38 | }; 39 | 40 | namespace ImGuiFreeType 41 | { 42 | // This is automatically assigned when using '#define IMGUI_ENABLE_FREETYPE'. 43 | // If you need to dynamically select between multiple builders: 44 | // - you can manually assign this builder with 'atlas->FontBuilderIO = ImGuiFreeType::GetBuilderForFreeType()' 45 | // - prefer deep-copying this into your own ImFontBuilderIO instance if you use hot-reloading that messes up static data. 46 | IMGUI_API const ImFontBuilderIO* GetBuilderForFreeType(); 47 | 48 | // Override allocators. By default ImGuiFreeType will use IM_ALLOC()/IM_FREE() 49 | // However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired. 50 | IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = nullptr); 51 | 52 | // Obsolete names (will be removed soon) 53 | #ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS 54 | //static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); } // Prefer using '#define IMGUI_ENABLE_FREETYPE' 55 | #endif 56 | } 57 | 58 | #endif // #ifndef IMGUI_DISABLE 59 | -------------------------------------------------------------------------------- /dwm-overlay/src/dllmain/dllmain.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include 5 | #pragma comment(lib, "d3d11.lib") 6 | 7 | #include 8 | #pragma comment(lib, "dxgi.lib") 9 | 10 | #include "dxgi/undocumented.h" 11 | 12 | #include "vtablehook/include/vtablehook.h" 13 | 14 | #include "imgui/imgui.h" 15 | #include "imgui/backends/imgui_impl_win32.h" 16 | #include "imgui/backends/imgui_impl_dx11.h" 17 | 18 | extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler 19 | (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); 20 | 21 | decltype(PresentDWM) fn_PresentDWM = nullptr; 22 | decltype(PresentMultiplaneOverlay) fn_PresentMultiplaneOverlay = nullptr; 23 | 24 | CComPtr g_Device = nullptr; 25 | CComPtr g_DeviceContext = nullptr; 26 | CComPtr g_RenderTargetView = nullptr; 27 | 28 | void draw(IDXGISwapChainDWMLegacy* pSwapChain) 29 | { 30 | if (!ImGui::GetCurrentContext()) 31 | { 32 | pSwapChain->GetDevice(IID_PPV_ARGS(&g_Device)); 33 | g_Device->GetImmediateContext(&g_DeviceContext); 34 | 35 | ImGui::CreateContext(); 36 | ImGui_ImplWin32_Init(GetDesktopWindow()); 37 | ImGui_ImplDX11_Init(g_Device, g_DeviceContext); 38 | 39 | CComPtr pRenderTargetTexture = nullptr; 40 | pSwapChain->GetBuffer(0, IID_PPV_ARGS(&pRenderTargetTexture)); 41 | g_Device->CreateRenderTargetView(pRenderTargetTexture, nullptr, &g_RenderTargetView); 42 | } 43 | 44 | // Using &g_RenderTargetView.p avoids the overridden & operator. 45 | // The '&' operator has a null check and if false it prints an error message. 46 | // Displaying any message on the main rendering thread causes a deadlock. 47 | g_DeviceContext->OMSetRenderTargets(1, &g_RenderTargetView.p, nullptr); 48 | 49 | //constexpr float clear_color[] { 1.0f, 1.0f, 1.0f, 1.0f }; 50 | //g_DeviceContext->ClearRenderTargetView(g_RenderTargetView.p, clear_color); 51 | 52 | ImGui_ImplDX11_NewFrame(); 53 | ImGui_ImplWin32_NewFrame(); 54 | ImGui::NewFrame(); 55 | 56 | ImGui::Begin("DWM overlay"); 57 | ImGui::Text("Copyright (C) 2025 Aurenex"); 58 | ImGui::Text("https://t.me/aurenex"); 59 | ImGui::End(); 60 | 61 | ImGui::Render(); 62 | ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData()); 63 | } 64 | 65 | HRESULT STDMETHODCALLTYPE hk_PresentDWM 66 | ( 67 | IDXGISwapChainDWMLegacy* pSwapChain, 68 | UINT SyncInterval, 69 | UINT PresentFlags, 70 | UINT DirtyRectsCount, 71 | const RECT* pDirtyRects, 72 | UINT ScrollRectsCount, 73 | const DXGI_SCROLL_RECT* pScrollRects, 74 | IDXGIResource* pResource, 75 | UINT FrameIndex // ??? 76 | ) 77 | { 78 | if (!(PresentFlags & DXGI_PRESENT_TEST)) 79 | draw(pSwapChain); 80 | 81 | return fn_PresentDWM( 82 | pSwapChain, 83 | SyncInterval, 84 | PresentFlags, 85 | DirtyRectsCount, 86 | pDirtyRects, 87 | ScrollRectsCount, 88 | pScrollRects, 89 | pResource, 90 | FrameIndex); 91 | } 92 | 93 | HRESULT STDMETHODCALLTYPE hk_PresentMultiplaneOverlay 94 | ( 95 | IDXGISwapChainDWMLegacy* pSwapChain, 96 | UINT SyncInterval, 97 | UINT PresentFlags, 98 | DXGI_HDR_METADATA_TYPE MetadataType, 99 | const VOID* pMetadata, 100 | UINT OverlayCount, 101 | const DXGI_PRESENT_MULTIPLANE_OVERLAY* pOverlays 102 | ) 103 | { 104 | if (!(PresentFlags & DXGI_PRESENT_TEST)) 105 | draw(pSwapChain); 106 | 107 | return fn_PresentMultiplaneOverlay( 108 | pSwapChain, 109 | SyncInterval, 110 | PresentFlags, 111 | MetadataType, 112 | pMetadata, 113 | OverlayCount, 114 | pOverlays); 115 | } 116 | 117 | LRESULT CALLBACK LowLevelKeyboardProc(int nCode, WPARAM wParam, LPARAM lParam) 118 | { 119 | const KBDLLHOOKSTRUCT* hookStruct = reinterpret_cast(lParam); 120 | 121 | // Prevent process crash if ImGui context is not created 122 | // Calling 'ImGui::GetIO' requires a created context 123 | // Which is created when the draw function is called 124 | if (ImGui::GetCurrentContext()) 125 | { 126 | const ImGuiIO& io = ImGui::GetIO(); 127 | 128 | ImGui_ImplWin32_WndProcHandler(GetDesktopWindow(), 129 | static_cast(wParam), hookStruct->vkCode, hookStruct->scanCode); 130 | 131 | if (io.WantCaptureKeyboard) 132 | return -1; 133 | } 134 | 135 | // Abnormal termination of the process if something went wrong. 136 | if (hookStruct->vkCode == VK_END) 137 | TerminateProcess(GetCurrentProcess(), EXIT_SUCCESS); 138 | 139 | return CallNextHookEx(nullptr, nCode, wParam, lParam); 140 | } 141 | 142 | LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) 143 | { 144 | const MSLLHOOKSTRUCT* hookStruct = reinterpret_cast(lParam); 145 | 146 | // Prevent process crash if ImGui context is not created 147 | // Calling 'ImGui::GetIO' requires a created context 148 | // Which is created when the draw function is called 149 | if (ImGui::GetCurrentContext()) 150 | { 151 | const ImGuiIO& io = ImGui::GetIO(); 152 | 153 | ImGui_ImplWin32_WndProcHandler(GetDesktopWindow(), static_cast(wParam), 154 | hookStruct->flags, MAKELPARAM(hookStruct->pt.x, hookStruct->pt.y)); 155 | 156 | if (io.WantCaptureMouse and wParam != WM_MOUSEMOVE) 157 | return -1; 158 | } 159 | 160 | return CallNextHookEx(nullptr, nCode, wParam, lParam); 161 | } 162 | 163 | DWORD WINAPI MainThread(LPVOID lpParameter) 164 | { 165 | CComPtr pFactory = nullptr; 166 | CreateDXGIFactory(IID_PPV_ARGS(&pFactory)); 167 | 168 | CComPtr pAdapter = nullptr; 169 | pFactory->EnumAdapters(0, &pAdapter); 170 | 171 | CComPtr pOutput = nullptr; 172 | pAdapter->EnumOutputs(0, &pOutput); 173 | 174 | CComPtr pFactoryDWM = nullptr; 175 | pFactory->QueryInterface(IID_PPV_ARGS(&pFactoryDWM)); 176 | 177 | const D3D_FEATURE_LEVEL FeatureLevels [] 178 | { 179 | D3D_FEATURE_LEVEL_10_0, 180 | D3D_FEATURE_LEVEL_11_0 181 | }; 182 | 183 | CComPtr pDevice = nullptr; 184 | CComPtr pDeviceContext = nullptr; 185 | 186 | D3D11CreateDevice 187 | ( 188 | pAdapter, 189 | D3D_DRIVER_TYPE_UNKNOWN, 190 | nullptr, 191 | D3D11_CREATE_DEVICE_SINGLETHREADED, 192 | FeatureLevels, 193 | ARRAYSIZE(FeatureLevels), 194 | D3D11_SDK_VERSION, 195 | &pDevice, 196 | nullptr, 197 | &pDeviceContext 198 | ); 199 | 200 | DXGI_SWAP_CHAIN_DESC SwapChainDesc {}; 201 | { 202 | SwapChainDesc.BufferDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM; 203 | SwapChainDesc.SampleDesc.Count = 1; 204 | SwapChainDesc.BufferCount = 1; 205 | } 206 | 207 | CComPtr pSwapChain = nullptr; 208 | pFactoryDWM->CreateSwapChain(pDevice, &SwapChainDesc, pOutput, &pSwapChain); 209 | 210 | // Current offsets are supported on Windows 10 - 11 211 | // Don't forget to update the offsets for your version 212 | fn_PresentDWM = reinterpret_cast 213 | (vtable::hook(pSwapChain, &hk_PresentDWM, 16)); 214 | fn_PresentMultiplaneOverlay = reinterpret_cast 215 | (vtable::hook(pSwapChain, &hk_PresentMultiplaneOverlay, 23)); 216 | 217 | const HHOOK hMouseHook = SetWindowsHookExW(WH_MOUSE_LL, &LowLevelMouseProc, nullptr, 0); 218 | const HHOOK hKeyboardHook = SetWindowsHookExW(WH_KEYBOARD_LL, &LowLevelKeyboardProc, nullptr, 0); 219 | 220 | // TODO: Add UnhookWindowsHookEx 221 | if (!hMouseHook or !hKeyboardHook) 222 | return EXIT_FAILURE; 223 | 224 | MSG message {}; 225 | 226 | while (GetMessageW(&message, nullptr, 0, 0) > 0) 227 | { 228 | TranslateMessage(&message); 229 | DispatchMessageW(&message); 230 | } 231 | 232 | UnhookWindowsHookEx(hMouseHook); 233 | UnhookWindowsHookEx(hKeyboardHook); 234 | 235 | return EXIT_SUCCESS; 236 | } 237 | 238 | BOOL APIENTRY DllMain(HINSTANCE hInstance, DWORD fdwReason, LPVOID lpReserved) 239 | { 240 | switch (fdwReason) 241 | { 242 | case DLL_PROCESS_ATTACH: 243 | CreateThread(nullptr, 0, &MainThread, nullptr, 0, nullptr); 244 | break; 245 | 246 | case DLL_PROCESS_DETACH: 247 | // TODO: Remove vtable hook 248 | break; 249 | } 250 | 251 | return TRUE; 252 | } 253 | -------------------------------------------------------------------------------- /dwm-overlay/dwm-overlay.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | Debug 14 | x64 15 | 16 | 17 | Release 18 | x64 19 | 20 | 21 | 22 | 17.0 23 | Win32Proj 24 | {210c8db9-e1fa-4714-b18d-8129eaab2e1d} 25 | dwmoverlay 26 | 10.0 27 | 28 | 29 | 30 | DynamicLibrary 31 | true 32 | v143 33 | Unicode 34 | 35 | 36 | DynamicLibrary 37 | false 38 | v143 39 | true 40 | Unicode 41 | 42 | 43 | DynamicLibrary 44 | true 45 | v143 46 | Unicode 47 | 48 | 49 | DynamicLibrary 50 | false 51 | v143 52 | true 53 | Unicode 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | $(SolutionDir)build\bin\ 75 | $(SolutionDir)build\obj\ 76 | 77 | 78 | $(SolutionDir)build\bin\ 79 | $(SolutionDir)build\obj\ 80 | 81 | 82 | $(SolutionDir)build\bin\ 83 | $(SolutionDir)build\obj\ 84 | 85 | 86 | $(SolutionDir)build\bin\ 87 | $(SolutionDir)build\obj\ 88 | 89 | 90 | 91 | Level3 92 | true 93 | WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) 94 | true 95 | stdcpp17 96 | include;third-party;third-party\imgui;%(AdditionalIncludeDirectories) 97 | MultiThreadedDebug 98 | OnlyExplicitInline 99 | 100 | 101 | Console 102 | true 103 | third-party;%(AdditionalLibraryDirectories) 104 | 105 | 106 | 107 | 108 | Level3 109 | true 110 | true 111 | true 112 | WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 113 | true 114 | stdcpp17 115 | include;third-party;third-party\imgui;%(AdditionalIncludeDirectories) 116 | MultiThreaded 117 | OnlyExplicitInline 118 | 119 | 120 | Console 121 | true 122 | true 123 | true 124 | third-party;%(AdditionalLibraryDirectories) 125 | 126 | 127 | 128 | 129 | Level3 130 | true 131 | _DEBUG;_CONSOLE;%(PreprocessorDefinitions) 132 | true 133 | stdcpp17 134 | include;third-party;third-party\imgui;%(AdditionalIncludeDirectories) 135 | MultiThreadedDebug 136 | OnlyExplicitInline 137 | 138 | 139 | Console 140 | true 141 | third-party;%(AdditionalLibraryDirectories) 142 | 143 | 144 | 145 | 146 | Level3 147 | true 148 | true 149 | true 150 | NDEBUG;_CONSOLE;%(PreprocessorDefinitions) 151 | true 152 | stdcpp17 153 | include;third-party;third-party\imgui;%(AdditionalIncludeDirectories) 154 | MultiThreaded 155 | OnlyExplicitInline 156 | 157 | 158 | Console 159 | true 160 | true 161 | true 162 | third-party;%(AdditionalLibraryDirectories) 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/imconfig.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------------------- 2 | // DEAR IMGUI COMPILE-TIME OPTIONS 3 | // Runtime options (clipboard callbacks, enabling various features, etc.) can generally be set via the ImGuiIO structure. 4 | // You can use ImGui::SetAllocatorFunctions() before calling ImGui::CreateContext() to rewire memory allocation functions. 5 | //----------------------------------------------------------------------------- 6 | // A) You may edit imconfig.h (and not overwrite it when updating Dear ImGui, or maintain a patch/rebased branch with your modifications to it) 7 | // B) or '#define IMGUI_USER_CONFIG "my_imgui_config.h"' in your project and then add directives in your own file without touching this template. 8 | //----------------------------------------------------------------------------- 9 | // You need to make sure that configuration settings are defined consistently _everywhere_ Dear ImGui is used, which include the imgui*.cpp 10 | // files but also _any_ of your code that uses Dear ImGui. This is because some compile-time options have an affect on data structures. 11 | // Defining those options in imconfig.h will ensure every compilation unit gets to see the same data structure layouts. 12 | // Call IMGUI_CHECKVERSION() from your .cpp file to verify that the data structures your files are using are matching the ones imgui.cpp is using. 13 | //----------------------------------------------------------------------------- 14 | 15 | #pragma once 16 | 17 | //---- Define assertion handler. Defaults to calling assert(). 18 | // If your macro uses multiple statements, make sure is enclosed in a 'do { .. } while (0)' block so it can be used as a single statement. 19 | //#define IM_ASSERT(_EXPR) MyAssert(_EXPR) 20 | //#define IM_ASSERT(_EXPR) ((void)(_EXPR)) // Disable asserts 21 | 22 | //---- Define attributes of all API symbols declarations, e.g. for DLL under Windows 23 | // Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility. 24 | // - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions() 25 | // for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details. 26 | //#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export 27 | //#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import 28 | //#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden 29 | 30 | //---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names. 31 | //#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS 32 | 33 | //---- Disable all of Dear ImGui or don't implement standard windows/tools. 34 | // It is very strongly recommended to NOT disable the demo windows and debug tool during development. They are extremely useful in day to day work. Please read comments in imgui_demo.cpp. 35 | //#define IMGUI_DISABLE // Disable everything: all headers and source files will be empty. 36 | //#define IMGUI_DISABLE_DEMO_WINDOWS // Disable demo windows: ShowDemoWindow()/ShowStyleEditor() will be empty. 37 | //#define IMGUI_DISABLE_DEBUG_TOOLS // Disable metrics/debugger and other debug tools: ShowMetricsWindow(), ShowDebugLogWindow() and ShowIDStackToolWindow() will be empty. 38 | 39 | //---- Don't implement some functions to reduce linkage requirements. 40 | //#define IMGUI_DISABLE_WIN32_DEFAULT_CLIPBOARD_FUNCTIONS // [Win32] Don't implement default clipboard handler. Won't use and link with OpenClipboard/GetClipboardData/CloseClipboard etc. (user32.lib/.a, kernel32.lib/.a) 41 | //#define IMGUI_ENABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with Visual Studio] Implement default IME handler (require imm32.lib/.a, auto-link for Visual Studio, -limm32 on command-line for MinGW) 42 | //#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a) 43 | //#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME). 44 | //#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default). 45 | //#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")). 46 | //#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf) 47 | //#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself. 48 | //#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies) 49 | //#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function. 50 | //#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions(). 51 | //#define IMGUI_DISABLE_DEFAULT_FONT // Disable default embedded font (ProggyClean.ttf), remove ~9.5 KB from output binary. AddFontDefault() will assert. 52 | //#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available 53 | 54 | //---- Enable Test Engine / Automation features. 55 | //#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details. 56 | 57 | //---- Include imgui_user.h at the end of imgui.h as a convenience 58 | // May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included. 59 | //#define IMGUI_INCLUDE_IMGUI_USER_H 60 | //#define IMGUI_USER_H_FILENAME "my_folder/my_imgui_user.h" 61 | 62 | //---- Pack vertex colors as BGRA8 instead of RGBA8 (to avoid converting from one to another). Need dedicated backend support. 63 | //#define IMGUI_USE_BGRA_PACKED_COLOR 64 | 65 | //---- Use 32-bit for ImWchar (default is 16-bit) to support Unicode planes 1-16. (e.g. point beyond 0xFFFF like emoticons, dingbats, symbols, shapes, ancient languages, etc...) 66 | //#define IMGUI_USE_WCHAR32 67 | 68 | //---- Avoid multiple STB libraries implementations, or redefine path/filenames to prioritize another version 69 | // By default the embedded implementations are declared static and not available outside of Dear ImGui sources files. 70 | //#define IMGUI_STB_TRUETYPE_FILENAME "my_folder/stb_truetype.h" 71 | //#define IMGUI_STB_RECT_PACK_FILENAME "my_folder/stb_rect_pack.h" 72 | //#define IMGUI_STB_SPRINTF_FILENAME "my_folder/stb_sprintf.h" // only used if IMGUI_USE_STB_SPRINTF is defined. 73 | //#define IMGUI_DISABLE_STB_TRUETYPE_IMPLEMENTATION 74 | //#define IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 75 | //#define IMGUI_DISABLE_STB_SPRINTF_IMPLEMENTATION // only disabled if IMGUI_USE_STB_SPRINTF is defined. 76 | 77 | //---- Use stb_sprintf.h for a faster implementation of vsnprintf instead of the one from libc (unless IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS is defined) 78 | // Compatibility checks of arguments and formats done by clang and GCC will be disabled in order to support the extra formats provided by stb_sprintf.h. 79 | //#define IMGUI_USE_STB_SPRINTF 80 | 81 | //---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui) 82 | // Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided). 83 | // On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'. 84 | //#define IMGUI_ENABLE_FREETYPE 85 | 86 | //---- Use FreeType + plutosvg or lunasvg to render OpenType SVG fonts (SVGinOT) 87 | // Only works in combination with IMGUI_ENABLE_FREETYPE. 88 | // - lunasvg is currently easier to acquire/install, as e.g. it is part of vcpkg. 89 | // - plutosvg will support more fonts and may load them faster. It currently requires to be built manually but it is fairly easy. See misc/freetype/README for instructions. 90 | // - Both require headers to be available in the include path + program to be linked with the library code (not provided). 91 | // - (note: lunasvg implementation is based on Freetype's rsvg-port.c which is licensed under CeCILL-C Free Software License Agreement) 92 | //#define IMGUI_ENABLE_FREETYPE_PLUTOSVG 93 | //#define IMGUI_ENABLE_FREETYPE_LUNASVG 94 | 95 | //---- Use stb_truetype to build and rasterize the font atlas (default) 96 | // The only purpose of this define is if you want force compilation of the stb_truetype backend ALONG with the FreeType backend. 97 | //#define IMGUI_ENABLE_STB_TRUETYPE 98 | 99 | //---- Define constructor and implicit cast operators to convert back<>forth between your math types and ImVec2/ImVec4. 100 | // This will be inlined as part of ImVec2 and ImVec4 class declarations. 101 | /* 102 | #define IM_VEC2_CLASS_EXTRA \ 103 | constexpr ImVec2(const MyVec2& f) : x(f.x), y(f.y) {} \ 104 | operator MyVec2() const { return MyVec2(x,y); } 105 | 106 | #define IM_VEC4_CLASS_EXTRA \ 107 | constexpr ImVec4(const MyVec4& f) : x(f.x), y(f.y), z(f.z), w(f.w) {} \ 108 | operator MyVec4() const { return MyVec4(x,y,z,w); } 109 | */ 110 | //---- ...Or use Dear ImGui's own very basic math operators. 111 | //#define IMGUI_DEFINE_MATH_OPERATORS 112 | 113 | //---- Use 32-bit vertex indices (default is 16-bit) is one way to allow large meshes with more than 64K vertices. 114 | // Your renderer backend will need to support it (most example renderer backends support both 16/32-bit indices). 115 | // Another way to allow large meshes while keeping 16-bit indices is to handle ImDrawCmd::VtxOffset in your renderer. 116 | // Read about ImGuiBackendFlags_RendererHasVtxOffset for details. 117 | //#define ImDrawIdx unsigned int 118 | 119 | //---- Override ImDrawCallback signature (will need to modify renderer backends accordingly) 120 | //struct ImDrawList; 121 | //struct ImDrawCmd; 122 | //typedef void (*MyImDrawCallback)(const ImDrawList* draw_list, const ImDrawCmd* cmd, void* my_renderer_user_data); 123 | //#define ImDrawCallback MyImDrawCallback 124 | 125 | //---- Debug Tools: Macro to break in Debugger (we provide a default implementation of this in the codebase) 126 | // (use 'Metrics->Tools->Item Picker' to pick widgets with the mouse and break into them for easy debugging.) 127 | //#define IM_DEBUG_BREAK IM_ASSERT(0) 128 | //#define IM_DEBUG_BREAK __debugbreak() 129 | 130 | //---- Debug Tools: Enable slower asserts 131 | //#define IMGUI_DEBUG_PARANOID 132 | 133 | //---- Tip: You can add extra functions within the ImGui:: namespace from anywhere (e.g. your own sources/header files) 134 | /* 135 | namespace ImGui 136 | { 137 | void MyFunction(const char* name, MyMatrix44* mtx); 138 | } 139 | */ 140 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/fonts/binary_to_compressed_c.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui 2 | // (binary_to_compressed_c.cpp) 3 | // Helper tool to turn a file into a C array, if you want to embed font data in your source code. 4 | 5 | // The data is first compressed with stb_compress() to reduce source code size. 6 | // Then stored in a C array: 7 | // - Base85: ~5 bytes of source code for 4 bytes of input data. 5 bytes stored in binary (suggested by @mmalex). 8 | // - As int: ~11 bytes of source code for 4 bytes of input data. 4 bytes stored in binary. Endianness dependant, need swapping on big-endian CPU. 9 | // - As char: ~12 bytes of source code for 4 bytes of input data. 4 bytes stored in binary. Not endianness dependant. 10 | // Load compressed TTF fonts with ImGui::GetIO().Fonts->AddFontFromMemoryCompressedTTF() 11 | 12 | // Build with, e.g: 13 | // # cl.exe binary_to_compressed_c.cpp 14 | // # g++ binary_to_compressed_c.cpp 15 | // # clang++ binary_to_compressed_c.cpp 16 | // You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui 17 | 18 | // Usage: 19 | // binary_to_compressed_c.exe [-nocompress] [-nostatic] [-base85] 20 | // Usage example: 21 | // # binary_to_compressed_c.exe myfont.ttf MyFont > myfont.cpp 22 | // # binary_to_compressed_c.exe -base85 myfont.ttf MyFont > myfont.cpp 23 | // Note: 24 | // Base85 encoding will be obsoleted by future version of Dear ImGui! 25 | 26 | #define _CRT_SECURE_NO_WARNINGS 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | // stb_compress* from stb.h - declaration 33 | typedef unsigned int stb_uint; 34 | typedef unsigned char stb_uchar; 35 | stb_uint stb_compress(stb_uchar* out, stb_uchar* in, stb_uint len); 36 | 37 | enum SourceEncoding 38 | { 39 | SourceEncoding_U8, // New default since 2024/11 40 | SourceEncoding_U32, 41 | SourceEncoding_Base85, 42 | }; 43 | 44 | static bool binary_to_compressed_c(const char* filename, const char* symbol, SourceEncoding source_encoding, bool use_compression, bool use_static); 45 | 46 | int main(int argc, char** argv) 47 | { 48 | if (argc < 3) 49 | { 50 | printf("Syntax: %s [-u8|-u32|-base85] [-nocompress] [-nostatic] \n", argv[0]); 51 | printf("Source encoding types:\n"); 52 | printf(" -u8 = ~12 bytes of source per 4 bytes of data. 4 bytes in binary.\n"); 53 | printf(" -u32 = ~11 bytes of source per 4 bytes of data. 4 bytes in binary. Need endianness swapping on big-endian.\n"); 54 | printf(" -base85 = ~5 bytes of source per 4 bytes of data. 5 bytes in binary. Need decoder.\n"); 55 | return 0; 56 | } 57 | 58 | int argn = 1; 59 | bool use_compression = true; 60 | bool use_static = true; 61 | SourceEncoding source_encoding = SourceEncoding_U8; // New default 62 | while (argn < (argc - 2) && argv[argn][0] == '-') 63 | { 64 | if (strcmp(argv[argn], "-u8") == 0) { source_encoding = SourceEncoding_U8; argn++; } 65 | else if (strcmp(argv[argn], "-u32") == 0) { source_encoding = SourceEncoding_U32; argn++; } 66 | else if (strcmp(argv[argn], "-base85") == 0) { source_encoding = SourceEncoding_Base85; argn++; } 67 | else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; } 68 | else if (strcmp(argv[argn], "-nostatic") == 0) { use_static = false; argn++; } 69 | else 70 | { 71 | fprintf(stderr, "Unknown argument: '%s'\n", argv[argn]); 72 | return 1; 73 | } 74 | } 75 | 76 | bool ret = binary_to_compressed_c(argv[argn], argv[argn + 1], source_encoding, use_compression, use_static); 77 | if (!ret) 78 | fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]); 79 | return ret ? 0 : 1; 80 | } 81 | 82 | char Encode85Byte(unsigned int x) 83 | { 84 | x = (x % 85) + 35; 85 | return (char)((x >= '\\') ? x + 1 : x); 86 | } 87 | 88 | bool binary_to_compressed_c(const char* filename, const char* symbol, SourceEncoding source_encoding, bool use_compression, bool use_static) 89 | { 90 | // Read file 91 | FILE* f = fopen(filename, "rb"); 92 | if (!f) return false; 93 | int data_sz; 94 | if (fseek(f, 0, SEEK_END) || (data_sz = (int)ftell(f)) == -1 || fseek(f, 0, SEEK_SET)) { fclose(f); return false; } 95 | char* data = new char[data_sz + 4]; 96 | if (fread(data, 1, data_sz, f) != (size_t)data_sz) { fclose(f); delete[] data; return false; } 97 | memset((void*)(((char*)data) + data_sz), 0, 4); 98 | fclose(f); 99 | 100 | // Compress 101 | int maxlen = data_sz + 512 + (data_sz >> 2) + sizeof(int); // total guess 102 | char* compressed = use_compression ? new char[maxlen] : data; 103 | int compressed_sz = use_compression ? stb_compress((stb_uchar*)compressed, (stb_uchar*)data, data_sz) : data_sz; 104 | if (use_compression) 105 | memset(compressed + compressed_sz, 0, maxlen - compressed_sz); 106 | 107 | // Output as Base85 encoded 108 | FILE* out = stdout; 109 | fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz); 110 | const char* static_str = use_static ? "static " : ""; 111 | const char* compressed_str = use_compression ? "compressed_" : ""; 112 | if (source_encoding == SourceEncoding_Base85) 113 | { 114 | fprintf(out, "// Exported using binary_to_compressed_c.exe -base85 \"%s\" %s\n", filename, symbol); 115 | fprintf(out, "%sconst char %s_%sdata_base85[%d+1] =\n \"", static_str, symbol, compressed_str, (int)((compressed_sz + 3) / 4)*5); 116 | char prev_c = 0; 117 | for (int src_i = 0; src_i < compressed_sz; src_i += 4) 118 | { 119 | // 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 ??. 120 | unsigned int d = *(unsigned int*)(compressed + src_i); 121 | for (unsigned int n5 = 0; n5 < 5; n5++, d /= 85) 122 | { 123 | char c = Encode85Byte(d); 124 | fprintf(out, (c == '?' && prev_c == '?') ? "\\%c" : "%c", c); 125 | prev_c = c; 126 | } 127 | if ((src_i % 112) == 112 - 4) 128 | fprintf(out, "\"\n \""); 129 | } 130 | fprintf(out, "\";\n\n"); 131 | } 132 | else if (source_encoding == SourceEncoding_U8) 133 | { 134 | // As individual bytes, not subject to endianness issues. 135 | fprintf(out, "// Exported using binary_to_compressed_c.exe -u8 \"%s\" %s\n", filename, symbol); 136 | fprintf(out, "%sconst unsigned int %s_%ssize = %d;\n", static_str, symbol, compressed_str, (int)compressed_sz); 137 | fprintf(out, "%sconst unsigned char %s_%sdata[%d] =\n{", static_str, symbol, compressed_str, (int)compressed_sz); 138 | int column = 0; 139 | for (int i = 0; i < compressed_sz; i++) 140 | { 141 | unsigned char d = *(unsigned char*)(compressed + i); 142 | if (column == 0) 143 | fprintf(out, "\n "); 144 | column += fprintf(out, "%d,", d); 145 | if (column >= 180) 146 | column = 0; 147 | } 148 | fprintf(out, "\n};\n\n"); 149 | } 150 | else if (source_encoding == SourceEncoding_U32) 151 | { 152 | // As integers 153 | fprintf(out, "// Exported using binary_to_compressed_c.exe -u32 \"%s\" %s\n", filename, symbol); 154 | fprintf(out, "%sconst unsigned int %s_%ssize = %d;\n", static_str, symbol, compressed_str, (int)compressed_sz); 155 | fprintf(out, "%sconst unsigned int %s_%sdata[%d/4] =\n{", static_str, symbol, compressed_str, (int)((compressed_sz + 3) / 4)*4); 156 | int column = 0; 157 | for (int i = 0; i < compressed_sz; i += 4) 158 | { 159 | unsigned int d = *(unsigned int*)(compressed + i); 160 | if ((column++ % 14) == 0) 161 | fprintf(out, "\n 0x%08x, ", d); 162 | else 163 | fprintf(out, "0x%08x, ", d); 164 | } 165 | fprintf(out, "\n};\n\n"); 166 | } 167 | 168 | // Cleanup 169 | delete[] data; 170 | if (use_compression) 171 | delete[] compressed; 172 | return true; 173 | } 174 | 175 | // stb_compress* from stb.h - definition 176 | 177 | //////////////////// compressor /////////////////////// 178 | 179 | static stb_uint stb_adler32(stb_uint adler32, stb_uchar *buffer, stb_uint buflen) 180 | { 181 | const unsigned long ADLER_MOD = 65521; 182 | unsigned long s1 = adler32 & 0xffff, s2 = adler32 >> 16; 183 | unsigned long blocklen, i; 184 | 185 | blocklen = buflen % 5552; 186 | while (buflen) { 187 | for (i=0; i + 7 < blocklen; i += 8) { 188 | s1 += buffer[0], s2 += s1; 189 | s1 += buffer[1], s2 += s1; 190 | s1 += buffer[2], s2 += s1; 191 | s1 += buffer[3], s2 += s1; 192 | s1 += buffer[4], s2 += s1; 193 | s1 += buffer[5], s2 += s1; 194 | s1 += buffer[6], s2 += s1; 195 | s1 += buffer[7], s2 += s1; 196 | 197 | buffer += 8; 198 | } 199 | 200 | for (; i < blocklen; ++i) 201 | s1 += *buffer++, s2 += s1; 202 | 203 | s1 %= ADLER_MOD, s2 %= ADLER_MOD; 204 | buflen -= blocklen; 205 | blocklen = 5552; 206 | } 207 | return (s2 << 16) + s1; 208 | } 209 | 210 | static unsigned int stb_matchlen(stb_uchar *m1, stb_uchar *m2, stb_uint maxlen) 211 | { 212 | stb_uint i; 213 | for (i=0; i < maxlen; ++i) 214 | if (m1[i] != m2[i]) return i; 215 | return i; 216 | } 217 | 218 | // simple implementation that just takes the source data in a big block 219 | 220 | static stb_uchar *stb__out; 221 | static FILE *stb__outfile; 222 | static stb_uint stb__outbytes; 223 | 224 | static void stb__write(unsigned char v) 225 | { 226 | fputc(v, stb__outfile); 227 | ++stb__outbytes; 228 | } 229 | 230 | //#define stb_out(v) (stb__out ? *stb__out++ = (stb_uchar) (v) : stb__write((stb_uchar) (v))) 231 | #define stb_out(v) do { if (stb__out) *stb__out++ = (stb_uchar) (v); else stb__write((stb_uchar) (v)); } while (0) 232 | 233 | static void stb_out2(stb_uint v) { stb_out(v >> 8); stb_out(v); } 234 | static void stb_out3(stb_uint v) { stb_out(v >> 16); stb_out(v >> 8); stb_out(v); } 235 | static void stb_out4(stb_uint v) { stb_out(v >> 24); stb_out(v >> 16); stb_out(v >> 8 ); stb_out(v); } 236 | 237 | static void outliterals(stb_uchar *in, int numlit) 238 | { 239 | while (numlit > 65536) { 240 | outliterals(in,65536); 241 | in += 65536; 242 | numlit -= 65536; 243 | } 244 | 245 | if (numlit == 0) ; 246 | else if (numlit <= 32) stb_out (0x000020 + numlit-1); 247 | else if (numlit <= 2048) stb_out2(0x000800 + numlit-1); 248 | else /* numlit <= 65536) */ stb_out3(0x070000 + numlit-1); 249 | 250 | if (stb__out) { 251 | memcpy(stb__out,in,numlit); 252 | stb__out += numlit; 253 | } else 254 | fwrite(in, 1, numlit, stb__outfile); 255 | } 256 | 257 | static int stb__window = 0x40000; // 256K 258 | 259 | static int stb_not_crap(int best, int dist) 260 | { 261 | return ((best > 2 && dist <= 0x00100) 262 | || (best > 5 && dist <= 0x04000) 263 | || (best > 7 && dist <= 0x80000)); 264 | } 265 | 266 | static stb_uint stb__hashsize = 32768; 267 | 268 | // note that you can play with the hashing functions all you 269 | // want without needing to change the decompressor 270 | #define stb__hc(q,h,c) (((h) << 7) + ((h) >> 25) + q[c]) 271 | #define stb__hc2(q,h,c,d) (((h) << 14) + ((h) >> 18) + (q[c] << 7) + q[d]) 272 | #define stb__hc3(q,c,d,e) ((q[c] << 14) + (q[d] << 7) + q[e]) 273 | 274 | static unsigned int stb__running_adler; 275 | 276 | static int stb_compress_chunk(stb_uchar *history, 277 | stb_uchar *start, 278 | stb_uchar *end, 279 | int length, 280 | int *pending_literals, 281 | stb_uchar **chash, 282 | stb_uint mask) 283 | { 284 | (void)history; 285 | int window = stb__window; 286 | stb_uint match_max; 287 | stb_uchar *lit_start = start - *pending_literals; 288 | stb_uchar *q = start; 289 | 290 | #define STB__SCRAMBLE(h) (((h) + ((h) >> 16)) & mask) 291 | 292 | // stop short of the end so we don't scan off the end doing 293 | // the hashing; this means we won't compress the last few bytes 294 | // unless they were part of something longer 295 | while (q < start+length && q+12 < end) { 296 | int m; 297 | stb_uint h1,h2,h3,h4, h; 298 | stb_uchar *t; 299 | int best = 2, dist=0; 300 | 301 | if (q+65536 > end) 302 | match_max = (stb_uint)(end-q); 303 | else 304 | match_max = 65536; 305 | 306 | #define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap((int)(b),(int)(d)))) 307 | 308 | #define STB__TRY(t,p) /* avoid retrying a match we already tried */ \ 309 | if (p ? dist != (int)(q-t) : 1) \ 310 | if ((m = stb_matchlen(t, q, match_max)) > best) \ 311 | if (stb__nc(m,q-(t))) \ 312 | best = m, dist = (int)(q - (t)) 313 | 314 | // rather than search for all matches, only try 4 candidate locations, 315 | // chosen based on 4 different hash functions of different lengths. 316 | // this strategy is inspired by LZO; hashing is unrolled here using the 317 | // 'hc' macro 318 | h = stb__hc3(q,0, 1, 2); h1 = STB__SCRAMBLE(h); 319 | t = chash[h1]; if (t) STB__TRY(t,0); 320 | h = stb__hc2(q,h, 3, 4); h2 = STB__SCRAMBLE(h); 321 | h = stb__hc2(q,h, 5, 6); t = chash[h2]; if (t) STB__TRY(t,1); 322 | h = stb__hc2(q,h, 7, 8); h3 = STB__SCRAMBLE(h); 323 | h = stb__hc2(q,h, 9,10); t = chash[h3]; if (t) STB__TRY(t,1); 324 | h = stb__hc2(q,h,11,12); h4 = STB__SCRAMBLE(h); 325 | t = chash[h4]; if (t) STB__TRY(t,1); 326 | 327 | // because we use a shared hash table, can only update it 328 | // _after_ we've probed all of them 329 | chash[h1] = chash[h2] = chash[h3] = chash[h4] = q; 330 | 331 | if (best > 2) 332 | assert(dist > 0); 333 | 334 | // see if our best match qualifies 335 | if (best < 3) { // fast path literals 336 | ++q; 337 | } else if (best > 2 && best <= 0x80 && dist <= 0x100) { 338 | outliterals(lit_start, (int)(q-lit_start)); lit_start = (q += best); 339 | stb_out(0x80 + best-1); 340 | stb_out(dist-1); 341 | } else if (best > 5 && best <= 0x100 && dist <= 0x4000) { 342 | outliterals(lit_start, (int)(q-lit_start)); lit_start = (q += best); 343 | stb_out2(0x4000 + dist-1); 344 | stb_out(best-1); 345 | } else if (best > 7 && best <= 0x100 && dist <= 0x80000) { 346 | outliterals(lit_start, (int)(q-lit_start)); lit_start = (q += best); 347 | stb_out3(0x180000 + dist-1); 348 | stb_out(best-1); 349 | } else if (best > 8 && best <= 0x10000 && dist <= 0x80000) { 350 | outliterals(lit_start, (int)(q-lit_start)); lit_start = (q += best); 351 | stb_out3(0x100000 + dist-1); 352 | stb_out2(best-1); 353 | } else if (best > 9 && dist <= 0x1000000) { 354 | if (best > 65536) best = 65536; 355 | outliterals(lit_start, (int)(q-lit_start)); lit_start = (q += best); 356 | if (best <= 0x100) { 357 | stb_out(0x06); 358 | stb_out3(dist-1); 359 | stb_out(best-1); 360 | } else { 361 | stb_out(0x04); 362 | stb_out3(dist-1); 363 | stb_out2(best-1); 364 | } 365 | } else { // fallback literals if no match was a balanced tradeoff 366 | ++q; 367 | } 368 | } 369 | 370 | // if we didn't get all the way, add the rest to literals 371 | if (q-start < length) 372 | q = start+length; 373 | 374 | // the literals are everything from lit_start to q 375 | *pending_literals = (int)(q - lit_start); 376 | 377 | stb__running_adler = stb_adler32(stb__running_adler, start, (stb_uint)(q - start)); 378 | return (int)(q - start); 379 | } 380 | 381 | static int stb_compress_inner(stb_uchar *input, stb_uint length) 382 | { 383 | int literals = 0; 384 | stb_uint len,i; 385 | 386 | stb_uchar **chash; 387 | chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*)); 388 | if (chash == nullptr) return 0; // failure 389 | for (i=0; i < stb__hashsize; ++i) 390 | chash[i] = nullptr; 391 | 392 | // stream signature 393 | stb_out(0x57); stb_out(0xbc); 394 | stb_out2(0); 395 | 396 | stb_out4(0); // 64-bit length requires 32-bit leading 0 397 | stb_out4(length); 398 | stb_out4(stb__window); 399 | 400 | stb__running_adler = 1; 401 | 402 | len = stb_compress_chunk(input, input, input+length, length, &literals, chash, stb__hashsize-1); 403 | assert(len == length); 404 | 405 | outliterals(input+length - literals, literals); 406 | 407 | free(chash); 408 | 409 | stb_out2(0x05fa); // end opcode 410 | 411 | stb_out4(stb__running_adler); 412 | 413 | return 1; // success 414 | } 415 | 416 | stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length) 417 | { 418 | stb__out = out; 419 | stb__outfile = nullptr; 420 | 421 | stb_compress_inner(input, length); 422 | 423 | return (stb_uint)(stb__out - out); 424 | } 425 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/imstb_rectpack.h: -------------------------------------------------------------------------------- 1 | // [DEAR IMGUI] 2 | // This is a slightly modified version of stb_rect_pack.h 1.01. 3 | // Grep for [DEAR IMGUI] to find the changes. 4 | // 5 | // stb_rect_pack.h - v1.01 - public domain - rectangle packing 6 | // Sean Barrett 2014 7 | // 8 | // Useful for e.g. packing rectangular textures into an atlas. 9 | // Does not do rotation. 10 | // 11 | // Before #including, 12 | // 13 | // #define STB_RECT_PACK_IMPLEMENTATION 14 | // 15 | // in the file that you want to have the implementation. 16 | // 17 | // Not necessarily the awesomest packing method, but better than 18 | // the totally naive one in stb_truetype (which is primarily what 19 | // this is meant to replace). 20 | // 21 | // Has only had a few tests run, may have issues. 22 | // 23 | // More docs to come. 24 | // 25 | // No memory allocations; uses qsort() and assert() from stdlib. 26 | // Can override those by defining STBRP_SORT and STBRP_ASSERT. 27 | // 28 | // This library currently uses the Skyline Bottom-Left algorithm. 29 | // 30 | // Please note: better rectangle packers are welcome! Please 31 | // implement them to the same API, but with a different init 32 | // function. 33 | // 34 | // Credits 35 | // 36 | // Library 37 | // Sean Barrett 38 | // Minor features 39 | // Martins Mozeiko 40 | // github:IntellectualKitty 41 | // 42 | // Bugfixes / warning fixes 43 | // Jeremy Jaussaud 44 | // Fabian Giesen 45 | // 46 | // Version history: 47 | // 48 | // 1.01 (2021-07-11) always use large rect mode, expose STBRP__MAXVAL in public section 49 | // 1.00 (2019-02-25) avoid small space waste; gracefully fail too-wide rectangles 50 | // 0.99 (2019-02-07) warning fixes 51 | // 0.11 (2017-03-03) return packing success/fail result 52 | // 0.10 (2016-10-25) remove cast-away-const to avoid warnings 53 | // 0.09 (2016-08-27) fix compiler warnings 54 | // 0.08 (2015-09-13) really fix bug with empty rects (w=0 or h=0) 55 | // 0.07 (2015-09-13) fix bug with empty rects (w=0 or h=0) 56 | // 0.06 (2015-04-15) added STBRP_SORT to allow replacing qsort 57 | // 0.05: added STBRP_ASSERT to allow replacing assert 58 | // 0.04: fixed minor bug in STBRP_LARGE_RECTS support 59 | // 0.01: initial release 60 | // 61 | // LICENSE 62 | // 63 | // See end of file for license information. 64 | 65 | ////////////////////////////////////////////////////////////////////////////// 66 | // 67 | // INCLUDE SECTION 68 | // 69 | 70 | #ifndef STB_INCLUDE_STB_RECT_PACK_H 71 | #define STB_INCLUDE_STB_RECT_PACK_H 72 | 73 | #define STB_RECT_PACK_VERSION 1 74 | 75 | #ifdef STBRP_STATIC 76 | #define STBRP_DEF static 77 | #else 78 | #define STBRP_DEF extern 79 | #endif 80 | 81 | #ifdef __cplusplus 82 | extern "C" { 83 | #endif 84 | 85 | typedef struct stbrp_context stbrp_context; 86 | typedef struct stbrp_node stbrp_node; 87 | typedef struct stbrp_rect stbrp_rect; 88 | 89 | typedef int stbrp_coord; 90 | 91 | #define STBRP__MAXVAL 0x7fffffff 92 | // Mostly for internal use, but this is the maximum supported coordinate value. 93 | 94 | STBRP_DEF int stbrp_pack_rects (stbrp_context *context, stbrp_rect *rects, int num_rects); 95 | // Assign packed locations to rectangles. The rectangles are of type 96 | // 'stbrp_rect' defined below, stored in the array 'rects', and there 97 | // are 'num_rects' many of them. 98 | // 99 | // Rectangles which are successfully packed have the 'was_packed' flag 100 | // set to a non-zero value and 'x' and 'y' store the minimum location 101 | // on each axis (i.e. bottom-left in cartesian coordinates, top-left 102 | // if you imagine y increasing downwards). Rectangles which do not fit 103 | // have the 'was_packed' flag set to 0. 104 | // 105 | // You should not try to access the 'rects' array from another thread 106 | // while this function is running, as the function temporarily reorders 107 | // the array while it executes. 108 | // 109 | // To pack into another rectangle, you need to call stbrp_init_target 110 | // again. To continue packing into the same rectangle, you can call 111 | // this function again. Calling this multiple times with multiple rect 112 | // arrays will probably produce worse packing results than calling it 113 | // a single time with the full rectangle array, but the option is 114 | // available. 115 | // 116 | // The function returns 1 if all of the rectangles were successfully 117 | // packed and 0 otherwise. 118 | 119 | struct stbrp_rect 120 | { 121 | // reserved for your use: 122 | int id; 123 | 124 | // input: 125 | stbrp_coord w, h; 126 | 127 | // output: 128 | stbrp_coord x, y; 129 | int was_packed; // non-zero if valid packing 130 | 131 | }; // 16 bytes, nominally 132 | 133 | 134 | STBRP_DEF void stbrp_init_target (stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes); 135 | // Initialize a rectangle packer to: 136 | // pack a rectangle that is 'width' by 'height' in dimensions 137 | // using temporary storage provided by the array 'nodes', which is 'num_nodes' long 138 | // 139 | // You must call this function every time you start packing into a new target. 140 | // 141 | // There is no "shutdown" function. The 'nodes' memory must stay valid for 142 | // the following stbrp_pack_rects() call (or calls), but can be freed after 143 | // the call (or calls) finish. 144 | // 145 | // Note: to guarantee best results, either: 146 | // 1. make sure 'num_nodes' >= 'width' 147 | // or 2. call stbrp_allow_out_of_mem() defined below with 'allow_out_of_mem = 1' 148 | // 149 | // If you don't do either of the above things, widths will be quantized to multiples 150 | // of small integers to guarantee the algorithm doesn't run out of temporary storage. 151 | // 152 | // If you do #2, then the non-quantized algorithm will be used, but the algorithm 153 | // may run out of temporary storage and be unable to pack some rectangles. 154 | 155 | STBRP_DEF void stbrp_setup_allow_out_of_mem (stbrp_context *context, int allow_out_of_mem); 156 | // Optionally call this function after init but before doing any packing to 157 | // change the handling of the out-of-temp-memory scenario, described above. 158 | // If you call init again, this will be reset to the default (false). 159 | 160 | 161 | STBRP_DEF void stbrp_setup_heuristic (stbrp_context *context, int heuristic); 162 | // Optionally select which packing heuristic the library should use. Different 163 | // heuristics will produce better/worse results for different data sets. 164 | // If you call init again, this will be reset to the default. 165 | 166 | enum 167 | { 168 | STBRP_HEURISTIC_Skyline_default=0, 169 | STBRP_HEURISTIC_Skyline_BL_sortHeight = STBRP_HEURISTIC_Skyline_default, 170 | STBRP_HEURISTIC_Skyline_BF_sortHeight 171 | }; 172 | 173 | 174 | ////////////////////////////////////////////////////////////////////////////// 175 | // 176 | // the details of the following structures don't matter to you, but they must 177 | // be visible so you can handle the memory allocations for them 178 | 179 | struct stbrp_node 180 | { 181 | stbrp_coord x,y; 182 | stbrp_node *next; 183 | }; 184 | 185 | struct stbrp_context 186 | { 187 | int width; 188 | int height; 189 | int align; 190 | int init_mode; 191 | int heuristic; 192 | int num_nodes; 193 | stbrp_node *active_head; 194 | stbrp_node *free_head; 195 | stbrp_node extra[2]; // we allocate two extra nodes so optimal user-node-count is 'width' not 'width+2' 196 | }; 197 | 198 | #ifdef __cplusplus 199 | } 200 | #endif 201 | 202 | #endif 203 | 204 | ////////////////////////////////////////////////////////////////////////////// 205 | // 206 | // IMPLEMENTATION SECTION 207 | // 208 | 209 | #ifdef STB_RECT_PACK_IMPLEMENTATION 210 | #ifndef STBRP_SORT 211 | #include 212 | #define STBRP_SORT qsort 213 | #endif 214 | 215 | #ifndef STBRP_ASSERT 216 | #include 217 | #define STBRP_ASSERT assert 218 | #endif 219 | 220 | #ifdef _MSC_VER 221 | #define STBRP__NOTUSED(v) (void)(v) 222 | #define STBRP__CDECL __cdecl 223 | #else 224 | #define STBRP__NOTUSED(v) (void)sizeof(v) 225 | #define STBRP__CDECL 226 | #endif 227 | 228 | enum 229 | { 230 | STBRP__INIT_skyline = 1 231 | }; 232 | 233 | STBRP_DEF void stbrp_setup_heuristic(stbrp_context *context, int heuristic) 234 | { 235 | switch (context->init_mode) { 236 | case STBRP__INIT_skyline: 237 | STBRP_ASSERT(heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight || heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight); 238 | context->heuristic = heuristic; 239 | break; 240 | default: 241 | STBRP_ASSERT(0); 242 | } 243 | } 244 | 245 | STBRP_DEF void stbrp_setup_allow_out_of_mem(stbrp_context *context, int allow_out_of_mem) 246 | { 247 | if (allow_out_of_mem) 248 | // if it's ok to run out of memory, then don't bother aligning them; 249 | // this gives better packing, but may fail due to OOM (even though 250 | // the rectangles easily fit). @TODO a smarter approach would be to only 251 | // quantize once we've hit OOM, then we could get rid of this parameter. 252 | context->align = 1; 253 | else { 254 | // if it's not ok to run out of memory, then quantize the widths 255 | // so that num_nodes is always enough nodes. 256 | // 257 | // I.e. num_nodes * align >= width 258 | // align >= width / num_nodes 259 | // align = ceil(width/num_nodes) 260 | 261 | context->align = (context->width + context->num_nodes-1) / context->num_nodes; 262 | } 263 | } 264 | 265 | STBRP_DEF void stbrp_init_target(stbrp_context *context, int width, int height, stbrp_node *nodes, int num_nodes) 266 | { 267 | int i; 268 | 269 | for (i=0; i < num_nodes-1; ++i) 270 | nodes[i].next = &nodes[i+1]; 271 | nodes[i].next = NULL; 272 | context->init_mode = STBRP__INIT_skyline; 273 | context->heuristic = STBRP_HEURISTIC_Skyline_default; 274 | context->free_head = &nodes[0]; 275 | context->active_head = &context->extra[0]; 276 | context->width = width; 277 | context->height = height; 278 | context->num_nodes = num_nodes; 279 | stbrp_setup_allow_out_of_mem(context, 0); 280 | 281 | // node 0 is the full width, node 1 is the sentinel (lets us not store width explicitly) 282 | context->extra[0].x = 0; 283 | context->extra[0].y = 0; 284 | context->extra[0].next = &context->extra[1]; 285 | context->extra[1].x = (stbrp_coord) width; 286 | context->extra[1].y = (1<<30); 287 | context->extra[1].next = NULL; 288 | } 289 | 290 | // find minimum y position if it starts at x1 291 | static int stbrp__skyline_find_min_y(stbrp_context *c, stbrp_node *first, int x0, int width, int *pwaste) 292 | { 293 | stbrp_node *node = first; 294 | int x1 = x0 + width; 295 | int min_y, visited_width, waste_area; 296 | 297 | STBRP__NOTUSED(c); 298 | 299 | STBRP_ASSERT(first->x <= x0); 300 | 301 | #if 0 302 | // skip in case we're past the node 303 | while (node->next->x <= x0) 304 | ++node; 305 | #else 306 | STBRP_ASSERT(node->next->x > x0); // we ended up handling this in the caller for efficiency 307 | #endif 308 | 309 | STBRP_ASSERT(node->x <= x0); 310 | 311 | min_y = 0; 312 | waste_area = 0; 313 | visited_width = 0; 314 | while (node->x < x1) { 315 | if (node->y > min_y) { 316 | // raise min_y higher. 317 | // we've accounted for all waste up to min_y, 318 | // but we'll now add more waste for everything we've visted 319 | waste_area += visited_width * (node->y - min_y); 320 | min_y = node->y; 321 | // the first time through, visited_width might be reduced 322 | if (node->x < x0) 323 | visited_width += node->next->x - x0; 324 | else 325 | visited_width += node->next->x - node->x; 326 | } else { 327 | // add waste area 328 | int under_width = node->next->x - node->x; 329 | if (under_width + visited_width > width) 330 | under_width = width - visited_width; 331 | waste_area += under_width * (min_y - node->y); 332 | visited_width += under_width; 333 | } 334 | node = node->next; 335 | } 336 | 337 | *pwaste = waste_area; 338 | return min_y; 339 | } 340 | 341 | typedef struct 342 | { 343 | int x,y; 344 | stbrp_node **prev_link; 345 | } stbrp__findresult; 346 | 347 | static stbrp__findresult stbrp__skyline_find_best_pos(stbrp_context *c, int width, int height) 348 | { 349 | int best_waste = (1<<30), best_x, best_y = (1 << 30); 350 | stbrp__findresult fr; 351 | stbrp_node **prev, *node, *tail, **best = NULL; 352 | 353 | // align to multiple of c->align 354 | width = (width + c->align - 1); 355 | width -= width % c->align; 356 | STBRP_ASSERT(width % c->align == 0); 357 | 358 | // if it can't possibly fit, bail immediately 359 | if (width > c->width || height > c->height) { 360 | fr.prev_link = NULL; 361 | fr.x = fr.y = 0; 362 | return fr; 363 | } 364 | 365 | node = c->active_head; 366 | prev = &c->active_head; 367 | while (node->x + width <= c->width) { 368 | int y,waste; 369 | y = stbrp__skyline_find_min_y(c, node, node->x, width, &waste); 370 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BL_sortHeight) { // actually just want to test BL 371 | // bottom left 372 | if (y < best_y) { 373 | best_y = y; 374 | best = prev; 375 | } 376 | } else { 377 | // best-fit 378 | if (y + height <= c->height) { 379 | // can only use it if it first vertically 380 | if (y < best_y || (y == best_y && waste < best_waste)) { 381 | best_y = y; 382 | best_waste = waste; 383 | best = prev; 384 | } 385 | } 386 | } 387 | prev = &node->next; 388 | node = node->next; 389 | } 390 | 391 | best_x = (best == NULL) ? 0 : (*best)->x; 392 | 393 | // if doing best-fit (BF), we also have to try aligning right edge to each node position 394 | // 395 | // e.g, if fitting 396 | // 397 | // ____________________ 398 | // |____________________| 399 | // 400 | // into 401 | // 402 | // | | 403 | // | ____________| 404 | // |____________| 405 | // 406 | // then right-aligned reduces waste, but bottom-left BL is always chooses left-aligned 407 | // 408 | // This makes BF take about 2x the time 409 | 410 | if (c->heuristic == STBRP_HEURISTIC_Skyline_BF_sortHeight) { 411 | tail = c->active_head; 412 | node = c->active_head; 413 | prev = &c->active_head; 414 | // find first node that's admissible 415 | while (tail->x < width) 416 | tail = tail->next; 417 | while (tail) { 418 | int xpos = tail->x - width; 419 | int y,waste; 420 | STBRP_ASSERT(xpos >= 0); 421 | // find the left position that matches this 422 | while (node->next->x <= xpos) { 423 | prev = &node->next; 424 | node = node->next; 425 | } 426 | STBRP_ASSERT(node->next->x > xpos && node->x <= xpos); 427 | y = stbrp__skyline_find_min_y(c, node, xpos, width, &waste); 428 | if (y + height <= c->height) { 429 | if (y <= best_y) { 430 | if (y < best_y || waste < best_waste || (waste==best_waste && xpos < best_x)) { 431 | best_x = xpos; 432 | //STBRP_ASSERT(y <= best_y); [DEAR IMGUI] 433 | best_y = y; 434 | best_waste = waste; 435 | best = prev; 436 | } 437 | } 438 | } 439 | tail = tail->next; 440 | } 441 | } 442 | 443 | fr.prev_link = best; 444 | fr.x = best_x; 445 | fr.y = best_y; 446 | return fr; 447 | } 448 | 449 | static stbrp__findresult stbrp__skyline_pack_rectangle(stbrp_context *context, int width, int height) 450 | { 451 | // find best position according to heuristic 452 | stbrp__findresult res = stbrp__skyline_find_best_pos(context, width, height); 453 | stbrp_node *node, *cur; 454 | 455 | // bail if: 456 | // 1. it failed 457 | // 2. the best node doesn't fit (we don't always check this) 458 | // 3. we're out of memory 459 | if (res.prev_link == NULL || res.y + height > context->height || context->free_head == NULL) { 460 | res.prev_link = NULL; 461 | return res; 462 | } 463 | 464 | // on success, create new node 465 | node = context->free_head; 466 | node->x = (stbrp_coord) res.x; 467 | node->y = (stbrp_coord) (res.y + height); 468 | 469 | context->free_head = node->next; 470 | 471 | // insert the new node into the right starting point, and 472 | // let 'cur' point to the remaining nodes needing to be 473 | // stiched back in 474 | 475 | cur = *res.prev_link; 476 | if (cur->x < res.x) { 477 | // preserve the existing one, so start testing with the next one 478 | stbrp_node *next = cur->next; 479 | cur->next = node; 480 | cur = next; 481 | } else { 482 | *res.prev_link = node; 483 | } 484 | 485 | // from here, traverse cur and free the nodes, until we get to one 486 | // that shouldn't be freed 487 | while (cur->next && cur->next->x <= res.x + width) { 488 | stbrp_node *next = cur->next; 489 | // move the current node to the free list 490 | cur->next = context->free_head; 491 | context->free_head = cur; 492 | cur = next; 493 | } 494 | 495 | // stitch the list back in 496 | node->next = cur; 497 | 498 | if (cur->x < res.x + width) 499 | cur->x = (stbrp_coord) (res.x + width); 500 | 501 | #ifdef _DEBUG 502 | cur = context->active_head; 503 | while (cur->x < context->width) { 504 | STBRP_ASSERT(cur->x < cur->next->x); 505 | cur = cur->next; 506 | } 507 | STBRP_ASSERT(cur->next == NULL); 508 | 509 | { 510 | int count=0; 511 | cur = context->active_head; 512 | while (cur) { 513 | cur = cur->next; 514 | ++count; 515 | } 516 | cur = context->free_head; 517 | while (cur) { 518 | cur = cur->next; 519 | ++count; 520 | } 521 | STBRP_ASSERT(count == context->num_nodes+2); 522 | } 523 | #endif 524 | 525 | return res; 526 | } 527 | 528 | static int STBRP__CDECL rect_height_compare(const void *a, const void *b) 529 | { 530 | const stbrp_rect *p = (const stbrp_rect *) a; 531 | const stbrp_rect *q = (const stbrp_rect *) b; 532 | if (p->h > q->h) 533 | return -1; 534 | if (p->h < q->h) 535 | return 1; 536 | return (p->w > q->w) ? -1 : (p->w < q->w); 537 | } 538 | 539 | static int STBRP__CDECL rect_original_order(const void *a, const void *b) 540 | { 541 | const stbrp_rect *p = (const stbrp_rect *) a; 542 | const stbrp_rect *q = (const stbrp_rect *) b; 543 | return (p->was_packed < q->was_packed) ? -1 : (p->was_packed > q->was_packed); 544 | } 545 | 546 | STBRP_DEF int stbrp_pack_rects(stbrp_context *context, stbrp_rect *rects, int num_rects) 547 | { 548 | int i, all_rects_packed = 1; 549 | 550 | // we use the 'was_packed' field internally to allow sorting/unsorting 551 | for (i=0; i < num_rects; ++i) { 552 | rects[i].was_packed = i; 553 | } 554 | 555 | // sort according to heuristic 556 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_height_compare); 557 | 558 | for (i=0; i < num_rects; ++i) { 559 | if (rects[i].w == 0 || rects[i].h == 0) { 560 | rects[i].x = rects[i].y = 0; // empty rect needs no space 561 | } else { 562 | stbrp__findresult fr = stbrp__skyline_pack_rectangle(context, rects[i].w, rects[i].h); 563 | if (fr.prev_link) { 564 | rects[i].x = (stbrp_coord) fr.x; 565 | rects[i].y = (stbrp_coord) fr.y; 566 | } else { 567 | rects[i].x = rects[i].y = STBRP__MAXVAL; 568 | } 569 | } 570 | } 571 | 572 | // unsort 573 | STBRP_SORT(rects, num_rects, sizeof(rects[0]), rect_original_order); 574 | 575 | // set was_packed flags and all_rects_packed status 576 | for (i=0; i < num_rects; ++i) { 577 | rects[i].was_packed = !(rects[i].x == STBRP__MAXVAL && rects[i].y == STBRP__MAXVAL); 578 | if (!rects[i].was_packed) 579 | all_rects_packed = 0; 580 | } 581 | 582 | // return the all_rects_packed status 583 | return all_rects_packed; 584 | } 585 | #endif 586 | 587 | /* 588 | ------------------------------------------------------------------------------ 589 | This software is available under 2 licenses -- choose whichever you prefer. 590 | ------------------------------------------------------------------------------ 591 | ALTERNATIVE A - MIT License 592 | Copyright (c) 2017 Sean Barrett 593 | Permission is hereby granted, free of charge, to any person obtaining a copy of 594 | this software and associated documentation files (the "Software"), to deal in 595 | the Software without restriction, including without limitation the rights to 596 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 597 | of the Software, and to permit persons to whom the Software is furnished to do 598 | so, subject to the following conditions: 599 | The above copyright notice and this permission notice shall be included in all 600 | copies or substantial portions of the Software. 601 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 602 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 603 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 604 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 605 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 606 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 607 | SOFTWARE. 608 | ------------------------------------------------------------------------------ 609 | ALTERNATIVE B - Public Domain (www.unlicense.org) 610 | This is free and unencumbered software released into the public domain. 611 | Anyone is free to copy, modify, publish, use, compile, sell, or distribute this 612 | software, either in source code form or as a compiled binary, for any purpose, 613 | commercial or non-commercial, and by any means. 614 | In jurisdictions that recognize copyright laws, the author or authors of this 615 | software dedicate any and all copyright interest in the software to the public 616 | domain. We make this dedication for the benefit of the public at large and to 617 | the detriment of our heirs and successors. We intend this dedication to be an 618 | overt act of relinquishment in perpetuity of all present and future rights to 619 | this software under copyright law. 620 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 621 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 622 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 623 | AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 624 | ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 625 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 626 | ------------------------------------------------------------------------------ 627 | */ 628 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/backends/imgui_impl_dx11.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: Renderer Backend for DirectX11 2 | // This needs to be used along with a Platform Backend (e.g. Win32) 3 | 4 | // Implemented features: 5 | // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! 6 | // [X] Renderer: Large meshes support (64k+ vertices) even with 16-bit indices (ImGuiBackendFlags_RendererHasVtxOffset). 7 | // [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)GetPlatformIO().Renderer_RenderState'. 8 | 9 | // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. 10 | // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. 11 | // Learn about Dear ImGui: 12 | // - FAQ https://dearimgui.com/faq 13 | // - Getting Started https://dearimgui.com/getting-started 14 | // - Documentation https://dearimgui.com/docs (same as your local docs/ folder). 15 | // - Introduction, links and more at the top of imgui.cpp 16 | 17 | // CHANGELOG 18 | // (minor and older changes stripped away, please see git history for details) 19 | // 2024-10-07: DirectX11: Changed default texture sampler to Clamp instead of Repeat/Wrap. 20 | // 2024-10-07: DirectX11: Expose selected render state in ImGui_ImplDX11_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. 21 | // 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11. 22 | // 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX). 23 | // 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) 24 | // 2021-02-18: DirectX11: Change blending equation to preserve alpha in output buffer. 25 | // 2019-08-01: DirectX11: Fixed code querying the Geometry Shader state (would generally error with Debug layer enabled). 26 | // 2019-07-21: DirectX11: Backup, clear and restore Geometry Shader is any is bound when calling ImGui_ImplDX11_RenderDrawData. Clearing Hull/Domain/Compute shaders without backup/restore. 27 | // 2019-05-29: DirectX11: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. 28 | // 2019-04-30: DirectX11: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. 29 | // 2018-12-03: Misc: Added #pragma comment statement to automatically link with d3dcompiler.lib when using D3DCompile(). 30 | // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. 31 | // 2018-08-01: DirectX11: Querying for IDXGIFactory instead of IDXGIFactory1 to increase compatibility. 32 | // 2018-07-13: DirectX11: Fixed unreleased resources in Init and Shutdown functions. 33 | // 2018-06-08: Misc: Extracted imgui_impl_dx11.cpp/.h away from the old combined DX11+Win32 example. 34 | // 2018-06-08: DirectX11: Use draw_data->DisplayPos and draw_data->DisplaySize to setup projection matrix and clipping rectangle. 35 | // 2018-02-16: Misc: Obsoleted the io.RenderDrawListsFn callback and exposed ImGui_ImplDX11_RenderDrawData() in the .h file so you can call it yourself. 36 | // 2018-02-06: Misc: Removed call to ImGui::Shutdown() which is not available from 1.60 WIP, user needs to call CreateContext/DestroyContext themselves. 37 | // 2016-05-07: DirectX11: Disabling depth-write. 38 | 39 | #include "imgui.h" 40 | #ifndef IMGUI_DISABLE 41 | #include "imgui_impl_dx11.h" 42 | 43 | // DirectX 44 | #include 45 | #include 46 | #include 47 | #ifdef _MSC_VER 48 | #pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below. 49 | #endif 50 | 51 | // DirectX11 data 52 | struct ImGui_ImplDX11_Data 53 | { 54 | ID3D11Device* pd3dDevice; 55 | ID3D11DeviceContext* pd3dDeviceContext; 56 | IDXGIFactory* pFactory; 57 | ID3D11Buffer* pVB; 58 | ID3D11Buffer* pIB; 59 | ID3D11VertexShader* pVertexShader; 60 | ID3D11InputLayout* pInputLayout; 61 | ID3D11Buffer* pVertexConstantBuffer; 62 | ID3D11PixelShader* pPixelShader; 63 | ID3D11SamplerState* pFontSampler; 64 | ID3D11ShaderResourceView* pFontTextureView; 65 | ID3D11RasterizerState* pRasterizerState; 66 | ID3D11BlendState* pBlendState; 67 | ID3D11DepthStencilState* pDepthStencilState; 68 | int VertexBufferSize; 69 | int IndexBufferSize; 70 | 71 | ImGui_ImplDX11_Data() { memset((void*)this, 0, sizeof(*this)); VertexBufferSize = 5000; IndexBufferSize = 10000; } 72 | }; 73 | 74 | struct VERTEX_CONSTANT_BUFFER_DX11 75 | { 76 | float mvp[4][4]; 77 | }; 78 | 79 | // Backend data stored in io.BackendRendererUserData to allow support for multiple Dear ImGui contexts 80 | // It is STRONGLY preferred that you use docking branch with multi-viewports (== single Dear ImGui context + multiple windows) instead of multiple Dear ImGui contexts. 81 | static ImGui_ImplDX11_Data* ImGui_ImplDX11_GetBackendData() 82 | { 83 | return ImGui::GetCurrentContext() ? (ImGui_ImplDX11_Data*)ImGui::GetIO().BackendRendererUserData : nullptr; 84 | } 85 | 86 | // Functions 87 | static void ImGui_ImplDX11_SetupRenderState(ImDrawData* draw_data, ID3D11DeviceContext* device_ctx) 88 | { 89 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 90 | 91 | // Setup viewport 92 | D3D11_VIEWPORT vp; 93 | memset(&vp, 0, sizeof(D3D11_VIEWPORT)); 94 | vp.Width = draw_data->DisplaySize.x; 95 | vp.Height = draw_data->DisplaySize.y; 96 | vp.MinDepth = 0.0f; 97 | vp.MaxDepth = 1.0f; 98 | vp.TopLeftX = vp.TopLeftY = 0; 99 | device_ctx->RSSetViewports(1, &vp); 100 | 101 | // Setup shader and vertex buffers 102 | unsigned int stride = sizeof(ImDrawVert); 103 | unsigned int offset = 0; 104 | device_ctx->IASetInputLayout(bd->pInputLayout); 105 | device_ctx->IASetVertexBuffers(0, 1, &bd->pVB, &stride, &offset); 106 | device_ctx->IASetIndexBuffer(bd->pIB, sizeof(ImDrawIdx) == 2 ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT, 0); 107 | device_ctx->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); 108 | device_ctx->VSSetShader(bd->pVertexShader, nullptr, 0); 109 | device_ctx->VSSetConstantBuffers(0, 1, &bd->pVertexConstantBuffer); 110 | device_ctx->PSSetShader(bd->pPixelShader, nullptr, 0); 111 | device_ctx->PSSetSamplers(0, 1, &bd->pFontSampler); 112 | device_ctx->GSSetShader(nullptr, nullptr, 0); 113 | device_ctx->HSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. 114 | device_ctx->DSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. 115 | device_ctx->CSSetShader(nullptr, nullptr, 0); // In theory we should backup and restore this as well.. very infrequently used.. 116 | 117 | // Setup blend state 118 | const float blend_factor[4] = { 0.f, 0.f, 0.f, 0.f }; 119 | device_ctx->OMSetBlendState(bd->pBlendState, blend_factor, 0xffffffff); 120 | device_ctx->OMSetDepthStencilState(bd->pDepthStencilState, 0); 121 | device_ctx->RSSetState(bd->pRasterizerState); 122 | } 123 | 124 | // Render function 125 | void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) 126 | { 127 | // Avoid rendering when minimized 128 | if (draw_data->DisplaySize.x <= 0.0f || draw_data->DisplaySize.y <= 0.0f) 129 | return; 130 | 131 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 132 | ID3D11DeviceContext* device = bd->pd3dDeviceContext; 133 | 134 | // Create and grow vertex/index buffers if needed 135 | if (!bd->pVB || bd->VertexBufferSize < draw_data->TotalVtxCount) 136 | { 137 | if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } 138 | bd->VertexBufferSize = draw_data->TotalVtxCount + 5000; 139 | D3D11_BUFFER_DESC desc; 140 | memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); 141 | desc.Usage = D3D11_USAGE_DYNAMIC; 142 | desc.ByteWidth = bd->VertexBufferSize * sizeof(ImDrawVert); 143 | desc.BindFlags = D3D11_BIND_VERTEX_BUFFER; 144 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 145 | desc.MiscFlags = 0; 146 | if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVB) < 0) 147 | return; 148 | } 149 | if (!bd->pIB || bd->IndexBufferSize < draw_data->TotalIdxCount) 150 | { 151 | if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } 152 | bd->IndexBufferSize = draw_data->TotalIdxCount + 10000; 153 | D3D11_BUFFER_DESC desc; 154 | memset(&desc, 0, sizeof(D3D11_BUFFER_DESC)); 155 | desc.Usage = D3D11_USAGE_DYNAMIC; 156 | desc.ByteWidth = bd->IndexBufferSize * sizeof(ImDrawIdx); 157 | desc.BindFlags = D3D11_BIND_INDEX_BUFFER; 158 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 159 | if (bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pIB) < 0) 160 | return; 161 | } 162 | 163 | // Upload vertex/index data into a single contiguous GPU buffer 164 | D3D11_MAPPED_SUBRESOURCE vtx_resource, idx_resource; 165 | if (device->Map(bd->pVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &vtx_resource) != S_OK) 166 | return; 167 | if (device->Map(bd->pIB, 0, D3D11_MAP_WRITE_DISCARD, 0, &idx_resource) != S_OK) 168 | return; 169 | ImDrawVert* vtx_dst = (ImDrawVert*)vtx_resource.pData; 170 | ImDrawIdx* idx_dst = (ImDrawIdx*)idx_resource.pData; 171 | for (int n = 0; n < draw_data->CmdListsCount; n++) 172 | { 173 | const ImDrawList* draw_list = draw_data->CmdLists[n]; 174 | memcpy(vtx_dst, draw_list->VtxBuffer.Data, draw_list->VtxBuffer.Size * sizeof(ImDrawVert)); 175 | memcpy(idx_dst, draw_list->IdxBuffer.Data, draw_list->IdxBuffer.Size * sizeof(ImDrawIdx)); 176 | vtx_dst += draw_list->VtxBuffer.Size; 177 | idx_dst += draw_list->IdxBuffer.Size; 178 | } 179 | device->Unmap(bd->pVB, 0); 180 | device->Unmap(bd->pIB, 0); 181 | 182 | // Setup orthographic projection matrix into our constant buffer 183 | // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. 184 | { 185 | D3D11_MAPPED_SUBRESOURCE mapped_resource; 186 | if (device->Map(bd->pVertexConstantBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped_resource) != S_OK) 187 | return; 188 | VERTEX_CONSTANT_BUFFER_DX11* constant_buffer = (VERTEX_CONSTANT_BUFFER_DX11*)mapped_resource.pData; 189 | float L = draw_data->DisplayPos.x; 190 | float R = draw_data->DisplayPos.x + draw_data->DisplaySize.x; 191 | float T = draw_data->DisplayPos.y; 192 | float B = draw_data->DisplayPos.y + draw_data->DisplaySize.y; 193 | float mvp[4][4] = 194 | { 195 | { 2.0f/(R-L), 0.0f, 0.0f, 0.0f }, 196 | { 0.0f, 2.0f/(T-B), 0.0f, 0.0f }, 197 | { 0.0f, 0.0f, 0.5f, 0.0f }, 198 | { (R+L)/(L-R), (T+B)/(B-T), 0.5f, 1.0f }, 199 | }; 200 | memcpy(&constant_buffer->mvp, mvp, sizeof(mvp)); 201 | device->Unmap(bd->pVertexConstantBuffer, 0); 202 | } 203 | 204 | // Backup DX state that will be modified to restore it afterwards (unfortunately this is very ugly looking and verbose. Close your eyes!) 205 | struct BACKUP_DX11_STATE 206 | { 207 | UINT ScissorRectsCount, ViewportsCount; 208 | D3D11_RECT ScissorRects[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 209 | D3D11_VIEWPORT Viewports[D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE]; 210 | ID3D11RasterizerState* RS; 211 | ID3D11BlendState* BlendState; 212 | FLOAT BlendFactor[4]; 213 | UINT SampleMask; 214 | UINT StencilRef; 215 | ID3D11DepthStencilState* DepthStencilState; 216 | ID3D11ShaderResourceView* PSShaderResource; 217 | ID3D11SamplerState* PSSampler; 218 | ID3D11PixelShader* PS; 219 | ID3D11VertexShader* VS; 220 | ID3D11GeometryShader* GS; 221 | UINT PSInstancesCount, VSInstancesCount, GSInstancesCount; 222 | ID3D11ClassInstance *PSInstances[256], *VSInstances[256], *GSInstances[256]; // 256 is max according to PSSetShader documentation 223 | D3D11_PRIMITIVE_TOPOLOGY PrimitiveTopology; 224 | ID3D11Buffer* IndexBuffer, *VertexBuffer, *VSConstantBuffer; 225 | UINT IndexBufferOffset, VertexBufferStride, VertexBufferOffset; 226 | DXGI_FORMAT IndexBufferFormat; 227 | ID3D11InputLayout* InputLayout; 228 | }; 229 | BACKUP_DX11_STATE old = {}; 230 | old.ScissorRectsCount = old.ViewportsCount = D3D11_VIEWPORT_AND_SCISSORRECT_OBJECT_COUNT_PER_PIPELINE; 231 | device->RSGetScissorRects(&old.ScissorRectsCount, old.ScissorRects); 232 | device->RSGetViewports(&old.ViewportsCount, old.Viewports); 233 | device->RSGetState(&old.RS); 234 | device->OMGetBlendState(&old.BlendState, old.BlendFactor, &old.SampleMask); 235 | device->OMGetDepthStencilState(&old.DepthStencilState, &old.StencilRef); 236 | device->PSGetShaderResources(0, 1, &old.PSShaderResource); 237 | device->PSGetSamplers(0, 1, &old.PSSampler); 238 | old.PSInstancesCount = old.VSInstancesCount = old.GSInstancesCount = 256; 239 | device->PSGetShader(&old.PS, old.PSInstances, &old.PSInstancesCount); 240 | device->VSGetShader(&old.VS, old.VSInstances, &old.VSInstancesCount); 241 | device->VSGetConstantBuffers(0, 1, &old.VSConstantBuffer); 242 | device->GSGetShader(&old.GS, old.GSInstances, &old.GSInstancesCount); 243 | 244 | device->IAGetPrimitiveTopology(&old.PrimitiveTopology); 245 | device->IAGetIndexBuffer(&old.IndexBuffer, &old.IndexBufferFormat, &old.IndexBufferOffset); 246 | device->IAGetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); 247 | device->IAGetInputLayout(&old.InputLayout); 248 | 249 | // Setup desired DX state 250 | ImGui_ImplDX11_SetupRenderState(draw_data, device); 251 | 252 | // Setup render state structure (for callbacks and custom texture bindings) 253 | ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); 254 | ImGui_ImplDX11_RenderState render_state; 255 | render_state.Device = bd->pd3dDevice; 256 | render_state.DeviceContext = bd->pd3dDeviceContext; 257 | render_state.SamplerDefault = bd->pFontSampler; 258 | platform_io.Renderer_RenderState = &render_state; 259 | 260 | // Render command lists 261 | // (Because we merged all buffers into a single one, we maintain our own offset into them) 262 | int global_idx_offset = 0; 263 | int global_vtx_offset = 0; 264 | ImVec2 clip_off = draw_data->DisplayPos; 265 | for (int n = 0; n < draw_data->CmdListsCount; n++) 266 | { 267 | const ImDrawList* draw_list = draw_data->CmdLists[n]; 268 | for (int cmd_i = 0; cmd_i < draw_list->CmdBuffer.Size; cmd_i++) 269 | { 270 | const ImDrawCmd* pcmd = &draw_list->CmdBuffer[cmd_i]; 271 | if (pcmd->UserCallback != nullptr) 272 | { 273 | // User callback, registered via ImDrawList::AddCallback() 274 | // (ImDrawCallback_ResetRenderState is a special callback value used by the user to request the renderer to reset render state.) 275 | if (pcmd->UserCallback == ImDrawCallback_ResetRenderState) 276 | ImGui_ImplDX11_SetupRenderState(draw_data, device); 277 | else 278 | pcmd->UserCallback(draw_list, pcmd); 279 | } 280 | else 281 | { 282 | // Project scissor/clipping rectangles into framebuffer space 283 | ImVec2 clip_min(pcmd->ClipRect.x - clip_off.x, pcmd->ClipRect.y - clip_off.y); 284 | ImVec2 clip_max(pcmd->ClipRect.z - clip_off.x, pcmd->ClipRect.w - clip_off.y); 285 | if (clip_max.x <= clip_min.x || clip_max.y <= clip_min.y) 286 | continue; 287 | 288 | // Apply scissor/clipping rectangle 289 | const D3D11_RECT r = { (LONG)clip_min.x, (LONG)clip_min.y, (LONG)clip_max.x, (LONG)clip_max.y }; 290 | device->RSSetScissorRects(1, &r); 291 | 292 | // Bind texture, Draw 293 | ID3D11ShaderResourceView* texture_srv = (ID3D11ShaderResourceView*)pcmd->GetTexID(); 294 | device->PSSetShaderResources(0, 1, &texture_srv); 295 | device->DrawIndexed(pcmd->ElemCount, pcmd->IdxOffset + global_idx_offset, pcmd->VtxOffset + global_vtx_offset); 296 | } 297 | } 298 | global_idx_offset += draw_list->IdxBuffer.Size; 299 | global_vtx_offset += draw_list->VtxBuffer.Size; 300 | } 301 | platform_io.Renderer_RenderState = nullptr; 302 | 303 | // Restore modified DX state 304 | device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); 305 | device->RSSetViewports(old.ViewportsCount, old.Viewports); 306 | device->RSSetState(old.RS); if (old.RS) old.RS->Release(); 307 | device->OMSetBlendState(old.BlendState, old.BlendFactor, old.SampleMask); if (old.BlendState) old.BlendState->Release(); 308 | device->OMSetDepthStencilState(old.DepthStencilState, old.StencilRef); if (old.DepthStencilState) old.DepthStencilState->Release(); 309 | device->PSSetShaderResources(0, 1, &old.PSShaderResource); if (old.PSShaderResource) old.PSShaderResource->Release(); 310 | device->PSSetSamplers(0, 1, &old.PSSampler); if (old.PSSampler) old.PSSampler->Release(); 311 | device->PSSetShader(old.PS, old.PSInstances, old.PSInstancesCount); if (old.PS) old.PS->Release(); 312 | for (UINT i = 0; i < old.PSInstancesCount; i++) if (old.PSInstances[i]) old.PSInstances[i]->Release(); 313 | device->VSSetShader(old.VS, old.VSInstances, old.VSInstancesCount); if (old.VS) old.VS->Release(); 314 | device->VSSetConstantBuffers(0, 1, &old.VSConstantBuffer); if (old.VSConstantBuffer) old.VSConstantBuffer->Release(); 315 | device->GSSetShader(old.GS, old.GSInstances, old.GSInstancesCount); if (old.GS) old.GS->Release(); 316 | for (UINT i = 0; i < old.VSInstancesCount; i++) if (old.VSInstances[i]) old.VSInstances[i]->Release(); 317 | device->IASetPrimitiveTopology(old.PrimitiveTopology); 318 | device->IASetIndexBuffer(old.IndexBuffer, old.IndexBufferFormat, old.IndexBufferOffset); if (old.IndexBuffer) old.IndexBuffer->Release(); 319 | device->IASetVertexBuffers(0, 1, &old.VertexBuffer, &old.VertexBufferStride, &old.VertexBufferOffset); if (old.VertexBuffer) old.VertexBuffer->Release(); 320 | device->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release(); 321 | } 322 | 323 | static void ImGui_ImplDX11_CreateFontsTexture() 324 | { 325 | // Build texture atlas 326 | ImGuiIO& io = ImGui::GetIO(); 327 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 328 | unsigned char* pixels; 329 | int width, height; 330 | io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height); 331 | 332 | // Upload texture to graphics system 333 | { 334 | D3D11_TEXTURE2D_DESC desc; 335 | ZeroMemory(&desc, sizeof(desc)); 336 | desc.Width = width; 337 | desc.Height = height; 338 | desc.MipLevels = 1; 339 | desc.ArraySize = 1; 340 | desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 341 | desc.SampleDesc.Count = 1; 342 | desc.Usage = D3D11_USAGE_DEFAULT; 343 | desc.BindFlags = D3D11_BIND_SHADER_RESOURCE; 344 | desc.CPUAccessFlags = 0; 345 | 346 | ID3D11Texture2D* pTexture = nullptr; 347 | D3D11_SUBRESOURCE_DATA subResource; 348 | subResource.pSysMem = pixels; 349 | subResource.SysMemPitch = desc.Width * 4; 350 | subResource.SysMemSlicePitch = 0; 351 | bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture); 352 | IM_ASSERT(pTexture != nullptr); 353 | 354 | // Create texture view 355 | D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc; 356 | ZeroMemory(&srvDesc, sizeof(srvDesc)); 357 | srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; 358 | srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; 359 | srvDesc.Texture2D.MipLevels = desc.MipLevels; 360 | srvDesc.Texture2D.MostDetailedMip = 0; 361 | bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView); 362 | pTexture->Release(); 363 | } 364 | 365 | // Store our identifier 366 | io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView); 367 | } 368 | 369 | static void ImGui_ImplDX11_DestroyFontsTexture() 370 | { 371 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 372 | if (bd->pFontTextureView) 373 | { 374 | bd->pFontTextureView->Release(); 375 | bd->pFontTextureView = nullptr; 376 | ImGui::GetIO().Fonts->SetTexID(0); // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well. 377 | } 378 | } 379 | 380 | bool ImGui_ImplDX11_CreateDeviceObjects() 381 | { 382 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 383 | if (!bd->pd3dDevice) 384 | return false; 385 | if (bd->pFontSampler) 386 | ImGui_ImplDX11_InvalidateDeviceObjects(); 387 | 388 | // By using D3DCompile() from / d3dcompiler.lib, we introduce a dependency to a given version of d3dcompiler_XX.dll (see D3DCOMPILER_DLL_A) 389 | // If you would like to use this DX11 sample code but remove this dependency you can: 390 | // 1) compile once, save the compiled shader blobs into a file or source code and pass them to CreateVertexShader()/CreatePixelShader() [preferred solution] 391 | // 2) use code to detect any version of the DLL and grab a pointer to D3DCompile from the DLL. 392 | // See https://github.com/ocornut/imgui/pull/638 for sources and details. 393 | 394 | // Create the vertex shader 395 | { 396 | static const char* vertexShader = 397 | "cbuffer vertexBuffer : register(b0) \ 398 | {\ 399 | float4x4 ProjectionMatrix; \ 400 | };\ 401 | struct VS_INPUT\ 402 | {\ 403 | float2 pos : POSITION;\ 404 | float4 col : COLOR0;\ 405 | float2 uv : TEXCOORD0;\ 406 | };\ 407 | \ 408 | struct PS_INPUT\ 409 | {\ 410 | float4 pos : SV_POSITION;\ 411 | float4 col : COLOR0;\ 412 | float2 uv : TEXCOORD0;\ 413 | };\ 414 | \ 415 | PS_INPUT main(VS_INPUT input)\ 416 | {\ 417 | PS_INPUT output;\ 418 | output.pos = mul( ProjectionMatrix, float4(input.pos.xy, 0.f, 1.f));\ 419 | output.col = input.col;\ 420 | output.uv = input.uv;\ 421 | return output;\ 422 | }"; 423 | 424 | ID3DBlob* vertexShaderBlob; 425 | if (FAILED(D3DCompile(vertexShader, strlen(vertexShader), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr))) 426 | return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! 427 | if (bd->pd3dDevice->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &bd->pVertexShader) != S_OK) 428 | { 429 | vertexShaderBlob->Release(); 430 | return false; 431 | } 432 | 433 | // Create the input layout 434 | D3D11_INPUT_ELEMENT_DESC local_layout[] = 435 | { 436 | { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, pos), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 437 | { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, (UINT)offsetof(ImDrawVert, uv), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 438 | { "COLOR", 0, DXGI_FORMAT_R8G8B8A8_UNORM, 0, (UINT)offsetof(ImDrawVert, col), D3D11_INPUT_PER_VERTEX_DATA, 0 }, 439 | }; 440 | if (bd->pd3dDevice->CreateInputLayout(local_layout, 3, vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &bd->pInputLayout) != S_OK) 441 | { 442 | vertexShaderBlob->Release(); 443 | return false; 444 | } 445 | vertexShaderBlob->Release(); 446 | 447 | // Create the constant buffer 448 | { 449 | D3D11_BUFFER_DESC desc; 450 | desc.ByteWidth = sizeof(VERTEX_CONSTANT_BUFFER_DX11); 451 | desc.Usage = D3D11_USAGE_DYNAMIC; 452 | desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; 453 | desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; 454 | desc.MiscFlags = 0; 455 | bd->pd3dDevice->CreateBuffer(&desc, nullptr, &bd->pVertexConstantBuffer); 456 | } 457 | } 458 | 459 | // Create the pixel shader 460 | { 461 | static const char* pixelShader = 462 | "struct PS_INPUT\ 463 | {\ 464 | float4 pos : SV_POSITION;\ 465 | float4 col : COLOR0;\ 466 | float2 uv : TEXCOORD0;\ 467 | };\ 468 | sampler sampler0;\ 469 | Texture2D texture0;\ 470 | \ 471 | float4 main(PS_INPUT input) : SV_Target\ 472 | {\ 473 | float4 out_col = input.col * texture0.Sample(sampler0, input.uv); \ 474 | return out_col; \ 475 | }"; 476 | 477 | ID3DBlob* pixelShaderBlob; 478 | if (FAILED(D3DCompile(pixelShader, strlen(pixelShader), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr))) 479 | return false; // NB: Pass ID3DBlob* pErrorBlob to D3DCompile() to get error showing in (const char*)pErrorBlob->GetBufferPointer(). Make sure to Release() the blob! 480 | if (bd->pd3dDevice->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &bd->pPixelShader) != S_OK) 481 | { 482 | pixelShaderBlob->Release(); 483 | return false; 484 | } 485 | pixelShaderBlob->Release(); 486 | } 487 | 488 | // Create the blending setup 489 | { 490 | D3D11_BLEND_DESC desc; 491 | ZeroMemory(&desc, sizeof(desc)); 492 | desc.AlphaToCoverageEnable = false; 493 | desc.RenderTarget[0].BlendEnable = true; 494 | desc.RenderTarget[0].SrcBlend = D3D11_BLEND_SRC_ALPHA; 495 | desc.RenderTarget[0].DestBlend = D3D11_BLEND_INV_SRC_ALPHA; 496 | desc.RenderTarget[0].BlendOp = D3D11_BLEND_OP_ADD; 497 | desc.RenderTarget[0].SrcBlendAlpha = D3D11_BLEND_ONE; 498 | desc.RenderTarget[0].DestBlendAlpha = D3D11_BLEND_INV_SRC_ALPHA; 499 | desc.RenderTarget[0].BlendOpAlpha = D3D11_BLEND_OP_ADD; 500 | desc.RenderTarget[0].RenderTargetWriteMask = D3D11_COLOR_WRITE_ENABLE_ALL; 501 | bd->pd3dDevice->CreateBlendState(&desc, &bd->pBlendState); 502 | } 503 | 504 | // Create the rasterizer state 505 | { 506 | D3D11_RASTERIZER_DESC desc; 507 | ZeroMemory(&desc, sizeof(desc)); 508 | desc.FillMode = D3D11_FILL_SOLID; 509 | desc.CullMode = D3D11_CULL_NONE; 510 | desc.ScissorEnable = true; 511 | desc.DepthClipEnable = true; 512 | bd->pd3dDevice->CreateRasterizerState(&desc, &bd->pRasterizerState); 513 | } 514 | 515 | // Create depth-stencil State 516 | { 517 | D3D11_DEPTH_STENCIL_DESC desc; 518 | ZeroMemory(&desc, sizeof(desc)); 519 | desc.DepthEnable = false; 520 | desc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL; 521 | desc.DepthFunc = D3D11_COMPARISON_ALWAYS; 522 | desc.StencilEnable = false; 523 | desc.FrontFace.StencilFailOp = desc.FrontFace.StencilDepthFailOp = desc.FrontFace.StencilPassOp = D3D11_STENCIL_OP_KEEP; 524 | desc.FrontFace.StencilFunc = D3D11_COMPARISON_ALWAYS; 525 | desc.BackFace = desc.FrontFace; 526 | bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState); 527 | } 528 | 529 | // Create texture sampler 530 | // (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling) 531 | { 532 | D3D11_SAMPLER_DESC desc; 533 | ZeroMemory(&desc, sizeof(desc)); 534 | desc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; 535 | desc.AddressU = D3D11_TEXTURE_ADDRESS_CLAMP; 536 | desc.AddressV = D3D11_TEXTURE_ADDRESS_CLAMP; 537 | desc.AddressW = D3D11_TEXTURE_ADDRESS_CLAMP; 538 | desc.MipLODBias = 0.f; 539 | desc.ComparisonFunc = D3D11_COMPARISON_ALWAYS; 540 | desc.MinLOD = 0.f; 541 | desc.MaxLOD = 0.f; 542 | bd->pd3dDevice->CreateSamplerState(&desc, &bd->pFontSampler); 543 | } 544 | 545 | ImGui_ImplDX11_CreateFontsTexture(); 546 | 547 | return true; 548 | } 549 | 550 | void ImGui_ImplDX11_InvalidateDeviceObjects() 551 | { 552 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 553 | if (!bd->pd3dDevice) 554 | return; 555 | 556 | ImGui_ImplDX11_DestroyFontsTexture(); 557 | 558 | if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; } 559 | if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; } 560 | if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; } 561 | if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; } 562 | if (bd->pDepthStencilState) { bd->pDepthStencilState->Release(); bd->pDepthStencilState = nullptr; } 563 | if (bd->pRasterizerState) { bd->pRasterizerState->Release(); bd->pRasterizerState = nullptr; } 564 | if (bd->pPixelShader) { bd->pPixelShader->Release(); bd->pPixelShader = nullptr; } 565 | if (bd->pVertexConstantBuffer) { bd->pVertexConstantBuffer->Release(); bd->pVertexConstantBuffer = nullptr; } 566 | if (bd->pInputLayout) { bd->pInputLayout->Release(); bd->pInputLayout = nullptr; } 567 | if (bd->pVertexShader) { bd->pVertexShader->Release(); bd->pVertexShader = nullptr; } 568 | } 569 | 570 | bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context) 571 | { 572 | ImGuiIO& io = ImGui::GetIO(); 573 | IMGUI_CHECKVERSION(); 574 | IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); 575 | 576 | // Setup backend capabilities flags 577 | ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)(); 578 | io.BackendRendererUserData = (void*)bd; 579 | io.BackendRendererName = "imgui_impl_dx11"; 580 | io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. 581 | 582 | // Get factory from device 583 | IDXGIDevice* pDXGIDevice = nullptr; 584 | IDXGIAdapter* pDXGIAdapter = nullptr; 585 | IDXGIFactory* pFactory = nullptr; 586 | 587 | if (device->QueryInterface(IID_PPV_ARGS(&pDXGIDevice)) == S_OK) 588 | if (pDXGIDevice->GetParent(IID_PPV_ARGS(&pDXGIAdapter)) == S_OK) 589 | if (pDXGIAdapter->GetParent(IID_PPV_ARGS(&pFactory)) == S_OK) 590 | { 591 | bd->pd3dDevice = device; 592 | bd->pd3dDeviceContext = device_context; 593 | bd->pFactory = pFactory; 594 | } 595 | if (pDXGIDevice) pDXGIDevice->Release(); 596 | if (pDXGIAdapter) pDXGIAdapter->Release(); 597 | bd->pd3dDevice->AddRef(); 598 | bd->pd3dDeviceContext->AddRef(); 599 | 600 | return true; 601 | } 602 | 603 | void ImGui_ImplDX11_Shutdown() 604 | { 605 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 606 | IM_ASSERT(bd != nullptr && "No renderer backend to shutdown, or already shutdown?"); 607 | ImGuiIO& io = ImGui::GetIO(); 608 | 609 | ImGui_ImplDX11_InvalidateDeviceObjects(); 610 | if (bd->pFactory) { bd->pFactory->Release(); } 611 | if (bd->pd3dDevice) { bd->pd3dDevice->Release(); } 612 | if (bd->pd3dDeviceContext) { bd->pd3dDeviceContext->Release(); } 613 | io.BackendRendererName = nullptr; 614 | io.BackendRendererUserData = nullptr; 615 | io.BackendFlags &= ~ImGuiBackendFlags_RendererHasVtxOffset; 616 | IM_DELETE(bd); 617 | } 618 | 619 | void ImGui_ImplDX11_NewFrame() 620 | { 621 | ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData(); 622 | IM_ASSERT(bd != nullptr && "Context or backend not initialized! Did you call ImGui_ImplDX11_Init()?"); 623 | 624 | if (!bd->pFontSampler) 625 | ImGui_ImplDX11_CreateDeviceObjects(); 626 | } 627 | 628 | //----------------------------------------------------------------------------- 629 | 630 | #endif // #ifndef IMGUI_DISABLE 631 | -------------------------------------------------------------------------------- /dwm-overlay/third-party/imgui/misc/freetype/imgui_freetype.cpp: -------------------------------------------------------------------------------- 1 | // dear imgui: FreeType font builder (used as a replacement for the stb_truetype builder) 2 | // (code) 3 | 4 | // Get the latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype 5 | // Original code by @vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained since 2019 by @ocornut. 6 | 7 | // CHANGELOG 8 | // (minor and older changes stripped away, please see git history for details) 9 | // 2024/10/17: added plutosvg support for SVG Fonts (seems faster/better than lunasvg). Enable by using '#define IMGUI_ENABLE_FREETYPE_PLUTOSVG'. (#7927) 10 | // 2023/11/13: added support for ImFontConfig::RasterizationDensity field for scaling render density without scaling metrics. 11 | // 2023/08/01: added support for SVG fonts, enable by using '#define IMGUI_ENABLE_FREETYPE_LUNASVG'. (#6591) 12 | // 2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly. 13 | // 2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns nullptr. 14 | // 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs. 15 | // 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a preferred texture format. 16 | // 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+). 17 | // 2021/01/26: simplified integration by using '#define IMGUI_ENABLE_FREETYPE'. renamed ImGuiFreeType::XXX flags to ImGuiFreeTypeBuilderFlags_XXX for consistency with other API. removed ImGuiFreeType::BuildFontAtlas(). 18 | // 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails. 19 | // 2019/02/09: added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!) 20 | // 2019/01/15: added support for imgui allocators + added FreeType only override function SetAllocatorFunctions(). 21 | // 2019/01/10: re-factored to match big update in STB builder. fixed texture height waste. fixed redundant glyphs when merging. support for glyph padding. 22 | // 2018/06/08: added support for ImFontConfig::GlyphMinAdvanceX, GlyphMaxAdvanceX. 23 | // 2018/02/04: moved to main imgui repository (away from http://www.github.com/ocornut/imgui_club) 24 | // 2018/01/22: fix for addition of ImFontAtlas::TexUvscale member. 25 | // 2017/10/22: minor inconsequential change to match change in master (removed an unnecessary statement). 26 | // 2017/09/26: fixes for imgui internal changes. 27 | // 2017/08/26: cleanup, optimizations, support for ImFontConfig::RasterizerFlags, ImFontConfig::RasterizerMultiply. 28 | // 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. 29 | 30 | // About Gamma Correct Blending: 31 | // - FreeType assumes blending in linear space rather than gamma space. 32 | // - See https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph 33 | // - For correct results you need to be using sRGB and convert to linear space in the pixel shader output. 34 | // - The default dear imgui styles will be impacted by this change (alpha values will need tweaking). 35 | 36 | // FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer). 37 | 38 | #include "imgui.h" 39 | #ifndef IMGUI_DISABLE 40 | #include "imgui_freetype.h" 41 | #include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*, 42 | #include 43 | #include 44 | #include FT_FREETYPE_H // 45 | #include FT_MODULE_H // 46 | #include FT_GLYPH_H // 47 | #include FT_SYNTHESIS_H // 48 | 49 | // Handle LunaSVG and PlutoSVG 50 | #if defined(IMGUI_ENABLE_FREETYPE_LUNASVG) && defined(IMGUI_ENABLE_FREETYPE_PLUTOSVG) 51 | #error "Cannot enable both IMGUI_ENABLE_FREETYPE_LUNASVG and IMGUI_ENABLE_FREETYPE_PLUTOSVG" 52 | #endif 53 | #ifdef IMGUI_ENABLE_FREETYPE_LUNASVG 54 | #include FT_OTSVG_H // 55 | #include FT_BBOX_H // 56 | #include 57 | #endif 58 | #ifdef IMGUI_ENABLE_FREETYPE_PLUTOSVG 59 | #include 60 | #endif 61 | #if defined(IMGUI_ENABLE_FREETYPE_LUNASVG) || defined (IMGUI_ENABLE_FREETYPE_PLUTOSVG) 62 | #if !((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12)) 63 | #error IMGUI_ENABLE_FREETYPE_PLUTOSVG or IMGUI_ENABLE_FREETYPE_LUNASVG requires FreeType version >= 2.12 64 | #endif 65 | #endif 66 | 67 | #ifdef _MSC_VER 68 | #pragma warning (push) 69 | #pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff) 70 | #pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3). 71 | #endif 72 | 73 | #ifdef __GNUC__ 74 | #pragma GCC diagnostic push 75 | #pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind 76 | #pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used 77 | #ifndef __clang__ 78 | #pragma GCC diagnostic ignored "-Wsubobject-linkage" // warning: 'xxxx' has a field 'xxxx' whose type uses the anonymous namespace 79 | #endif 80 | #endif 81 | 82 | //------------------------------------------------------------------------- 83 | // Data 84 | //------------------------------------------------------------------------- 85 | 86 | // Default memory allocators 87 | static void* ImGuiFreeTypeDefaultAllocFunc(size_t size, void* user_data) { IM_UNUSED(user_data); return IM_ALLOC(size); } 88 | static void ImGuiFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSED(user_data); IM_FREE(ptr); } 89 | 90 | // Current memory allocators 91 | static void* (*GImGuiFreeTypeAllocFunc)(size_t size, void* user_data) = ImGuiFreeTypeDefaultAllocFunc; 92 | static void (*GImGuiFreeTypeFreeFunc)(void* ptr, void* user_data) = ImGuiFreeTypeDefaultFreeFunc; 93 | static void* GImGuiFreeTypeAllocatorUserData = nullptr; 94 | 95 | // Lunasvg support 96 | #ifdef IMGUI_ENABLE_FREETYPE_LUNASVG 97 | static FT_Error ImGuiLunasvgPortInit(FT_Pointer* state); 98 | static void ImGuiLunasvgPortFree(FT_Pointer* state); 99 | static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state); 100 | static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_Pointer* _state); 101 | #endif 102 | 103 | //------------------------------------------------------------------------- 104 | // Code 105 | //------------------------------------------------------------------------- 106 | 107 | namespace 108 | { 109 | // Glyph metrics: 110 | // -------------- 111 | // 112 | // xmin xmax 113 | // | | 114 | // |<-------- width -------->| 115 | // | | 116 | // | +-------------------------+----------------- ymax 117 | // | | ggggggggg ggggg | ^ ^ 118 | // | | g:::::::::ggg::::g | | | 119 | // | | g:::::::::::::::::g | | | 120 | // | | g::::::ggggg::::::gg | | | 121 | // | | g:::::g g:::::g | | | 122 | // offsetX -|-------->| g:::::g g:::::g | offsetY | 123 | // | | g:::::g g:::::g | | | 124 | // | | g::::::g g:::::g | | | 125 | // | | g:::::::ggggg:::::g | | | 126 | // | | g::::::::::::::::g | | height 127 | // | | gg::::::::::::::g | | | 128 | // baseline ---*---------|---- gggggggg::::::g-----*-------- | 129 | // / | | g:::::g | | 130 | // origin | | gggggg g:::::g | | 131 | // | | g:::::gg gg:::::g | | 132 | // | | g::::::ggg:::::::g | | 133 | // | | gg:::::::::::::g | | 134 | // | | ggg::::::ggg | | 135 | // | | gggggg | v 136 | // | +-------------------------+----------------- ymin 137 | // | | 138 | // |------------- advanceX ----------->| 139 | 140 | // A structure that describe a glyph. 141 | struct GlyphInfo 142 | { 143 | int Width; // Glyph's width in pixels. 144 | int Height; // Glyph's height in pixels. 145 | FT_Int OffsetX; // The distance from the origin ("pen position") to the left of the glyph. 146 | FT_Int OffsetY; // The distance from the origin to the top of the glyph. This is usually a value < 0. 147 | float AdvanceX; // The distance from the origin to the origin of the next glyph. This is usually a value > 0. 148 | bool IsColored; // The glyph is colored 149 | }; 150 | 151 | // Font parameters and metrics. 152 | struct FontInfo 153 | { 154 | uint32_t PixelHeight; // Size this font was generated with. 155 | float Ascender; // The pixel extents above the baseline in pixels (typically positive). 156 | float Descender; // The extents below the baseline in pixels (typically negative). 157 | 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. 158 | float LineGap; // The spacing in pixels between one row's descent and the next row's ascent. 159 | float MaxAdvanceWidth; // This field gives the maximum horizontal cursor advance for all glyphs in the font. 160 | }; 161 | 162 | // FreeType glyph rasterizer. 163 | // NB: No ctor/dtor, explicitly call Init()/Shutdown() 164 | struct FreeTypeFont 165 | { 166 | bool InitFont(FT_Library ft_library, 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. 167 | void CloseFont(); 168 | void SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size 169 | const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint); 170 | const FT_Bitmap* RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info); 171 | void BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = nullptr); 172 | FreeTypeFont() { memset(this, 0, sizeof(*this)); } 173 | ~FreeTypeFont() { CloseFont(); } 174 | 175 | // [Internals] 176 | FontInfo Info; // Font descriptor of the current font. 177 | FT_Face Face; 178 | unsigned int UserFlags; // = ImFontConfig::RasterizerFlags 179 | FT_Int32 LoadFlags; 180 | FT_Render_Mode RenderMode; 181 | float RasterizationDensity; 182 | float InvRasterizationDensity; 183 | }; 184 | 185 | // From SDL_ttf: Handy routines for converting from fixed point 186 | #define FT_CEIL(X) (((X + 63) & -64) / 64) 187 | 188 | bool FreeTypeFont::InitFont(FT_Library ft_library, const ImFontConfig& cfg, unsigned int extra_font_builder_flags) 189 | { 190 | FT_Error error = FT_New_Memory_Face(ft_library, (uint8_t*)cfg.FontData, (uint32_t)cfg.FontDataSize, (uint32_t)cfg.FontNo, &Face); 191 | if (error != 0) 192 | return false; 193 | error = FT_Select_Charmap(Face, FT_ENCODING_UNICODE); 194 | if (error != 0) 195 | return false; 196 | 197 | // Convert to FreeType flags (NB: Bold and Oblique are processed separately) 198 | UserFlags = cfg.FontBuilderFlags | extra_font_builder_flags; 199 | 200 | LoadFlags = 0; 201 | if ((UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) == 0) 202 | LoadFlags |= FT_LOAD_NO_BITMAP; 203 | 204 | if (UserFlags & ImGuiFreeTypeBuilderFlags_NoHinting) 205 | LoadFlags |= FT_LOAD_NO_HINTING; 206 | if (UserFlags & ImGuiFreeTypeBuilderFlags_NoAutoHint) 207 | LoadFlags |= FT_LOAD_NO_AUTOHINT; 208 | if (UserFlags & ImGuiFreeTypeBuilderFlags_ForceAutoHint) 209 | LoadFlags |= FT_LOAD_FORCE_AUTOHINT; 210 | if (UserFlags & ImGuiFreeTypeBuilderFlags_LightHinting) 211 | LoadFlags |= FT_LOAD_TARGET_LIGHT; 212 | else if (UserFlags & ImGuiFreeTypeBuilderFlags_MonoHinting) 213 | LoadFlags |= FT_LOAD_TARGET_MONO; 214 | else 215 | LoadFlags |= FT_LOAD_TARGET_NORMAL; 216 | 217 | if (UserFlags & ImGuiFreeTypeBuilderFlags_Monochrome) 218 | RenderMode = FT_RENDER_MODE_MONO; 219 | else 220 | RenderMode = FT_RENDER_MODE_NORMAL; 221 | 222 | if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor) 223 | LoadFlags |= FT_LOAD_COLOR; 224 | 225 | RasterizationDensity = cfg.RasterizerDensity; 226 | InvRasterizationDensity = 1.0f / RasterizationDensity; 227 | 228 | memset(&Info, 0, sizeof(Info)); 229 | SetPixelHeight((uint32_t)cfg.SizePixels); 230 | 231 | return true; 232 | } 233 | 234 | void FreeTypeFont::CloseFont() 235 | { 236 | if (Face) 237 | { 238 | FT_Done_Face(Face); 239 | Face = nullptr; 240 | } 241 | } 242 | 243 | void FreeTypeFont::SetPixelHeight(int pixel_height) 244 | { 245 | // Vuhdo: I'm not sure how to deal with font sizes properly. As far as I understand, currently ImGui assumes that the 'pixel_height' 246 | // 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. 247 | // NB: FT_Set_Pixel_Sizes() doesn't seem to get us the same result. 248 | FT_Size_RequestRec req; 249 | req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM; 250 | req.width = 0; 251 | req.height = (uint32_t)(pixel_height * 64 * RasterizationDensity); 252 | req.horiResolution = 0; 253 | req.vertResolution = 0; 254 | FT_Request_Size(Face, &req); 255 | 256 | // Update font info 257 | FT_Size_Metrics metrics = Face->size->metrics; 258 | Info.PixelHeight = (uint32_t)(pixel_height * InvRasterizationDensity); 259 | Info.Ascender = (float)FT_CEIL(metrics.ascender) * InvRasterizationDensity; 260 | Info.Descender = (float)FT_CEIL(metrics.descender) * InvRasterizationDensity; 261 | Info.LineSpacing = (float)FT_CEIL(metrics.height) * InvRasterizationDensity; 262 | Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender) * InvRasterizationDensity; 263 | Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance) * InvRasterizationDensity; 264 | } 265 | 266 | const FT_Glyph_Metrics* FreeTypeFont::LoadGlyph(uint32_t codepoint) 267 | { 268 | uint32_t glyph_index = FT_Get_Char_Index(Face, codepoint); 269 | if (glyph_index == 0) 270 | return nullptr; 271 | 272 | // If this crash for you: FreeType 2.11.0 has a crash bug on some bitmap/colored fonts. 273 | // - https://gitlab.freedesktop.org/freetype/freetype/-/issues/1076 274 | // - https://github.com/ocornut/imgui/issues/4567 275 | // - https://github.com/ocornut/imgui/issues/4566 276 | // You can use FreeType 2.10, or the patched version of 2.11.0 in VcPkg, or probably any upcoming FreeType version. 277 | FT_Error error = FT_Load_Glyph(Face, glyph_index, LoadFlags); 278 | if (error) 279 | return nullptr; 280 | 281 | // Need an outline for this to work 282 | FT_GlyphSlot slot = Face->glyph; 283 | #if defined(IMGUI_ENABLE_FREETYPE_LUNASVG) || defined(IMGUI_ENABLE_FREETYPE_PLUTOSVG) 284 | IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP || slot->format == FT_GLYPH_FORMAT_SVG); 285 | #else 286 | #if ((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12)) 287 | IM_ASSERT(slot->format != FT_GLYPH_FORMAT_SVG && "The font contains SVG glyphs, you'll need to enable IMGUI_ENABLE_FREETYPE_PLUTOSVG or IMGUI_ENABLE_FREETYPE_LUNASVG in imconfig.h and install required libraries in order to use this font"); 288 | #endif 289 | IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP); 290 | #endif // IMGUI_ENABLE_FREETYPE_LUNASVG 291 | 292 | // Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting) 293 | if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold) 294 | FT_GlyphSlot_Embolden(slot); 295 | if (UserFlags & ImGuiFreeTypeBuilderFlags_Oblique) 296 | { 297 | FT_GlyphSlot_Oblique(slot); 298 | //FT_BBox bbox; 299 | //FT_Outline_Get_BBox(&slot->outline, &bbox); 300 | //slot->metrics.width = bbox.xMax - bbox.xMin; 301 | //slot->metrics.height = bbox.yMax - bbox.yMin; 302 | } 303 | 304 | return &slot->metrics; 305 | } 306 | 307 | const FT_Bitmap* FreeTypeFont::RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info) 308 | { 309 | FT_GlyphSlot slot = Face->glyph; 310 | FT_Error error = FT_Render_Glyph(slot, RenderMode); 311 | if (error != 0) 312 | return nullptr; 313 | 314 | FT_Bitmap* ft_bitmap = &Face->glyph->bitmap; 315 | out_glyph_info->Width = (int)ft_bitmap->width; 316 | out_glyph_info->Height = (int)ft_bitmap->rows; 317 | out_glyph_info->OffsetX = Face->glyph->bitmap_left; 318 | out_glyph_info->OffsetY = -Face->glyph->bitmap_top; 319 | out_glyph_info->AdvanceX = (float)FT_CEIL(slot->advance.x); 320 | out_glyph_info->IsColored = (ft_bitmap->pixel_mode == FT_PIXEL_MODE_BGRA); 321 | 322 | return ft_bitmap; 323 | } 324 | 325 | void FreeTypeFont::BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table) 326 | { 327 | IM_ASSERT(ft_bitmap != nullptr); 328 | const uint32_t w = ft_bitmap->width; 329 | const uint32_t h = ft_bitmap->rows; 330 | const uint8_t* src = ft_bitmap->buffer; 331 | const uint32_t src_pitch = ft_bitmap->pitch; 332 | 333 | switch (ft_bitmap->pixel_mode) 334 | { 335 | case FT_PIXEL_MODE_GRAY: // Grayscale image, 1 byte per pixel. 336 | { 337 | if (multiply_table == nullptr) 338 | { 339 | for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) 340 | for (uint32_t x = 0; x < w; x++) 341 | dst[x] = IM_COL32(255, 255, 255, src[x]); 342 | } 343 | else 344 | { 345 | for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) 346 | for (uint32_t x = 0; x < w; x++) 347 | dst[x] = IM_COL32(255, 255, 255, multiply_table[src[x]]); 348 | } 349 | break; 350 | } 351 | case FT_PIXEL_MODE_MONO: // Monochrome image, 1 bit per pixel. The bits in each byte are ordered from MSB to LSB. 352 | { 353 | uint8_t color0 = multiply_table ? multiply_table[0] : 0; 354 | uint8_t color1 = multiply_table ? multiply_table[255] : 255; 355 | for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) 356 | { 357 | uint8_t bits = 0; 358 | const uint8_t* bits_ptr = src; 359 | for (uint32_t x = 0; x < w; x++, bits <<= 1) 360 | { 361 | if ((x & 7) == 0) 362 | bits = *bits_ptr++; 363 | dst[x] = IM_COL32(255, 255, 255, (bits & 0x80) ? color1 : color0); 364 | } 365 | } 366 | break; 367 | } 368 | case FT_PIXEL_MODE_BGRA: 369 | { 370 | // FIXME: Converting pre-multiplied alpha to straight. Doesn't smell good. 371 | #define DE_MULTIPLY(color, alpha) ImMin((ImU32)(255.0f * (float)color / (float)(alpha + FLT_MIN) + 0.5f), 255u) 372 | if (multiply_table == nullptr) 373 | { 374 | for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) 375 | for (uint32_t x = 0; x < w; x++) 376 | { 377 | uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3]; 378 | dst[x] = IM_COL32(DE_MULTIPLY(r, a), DE_MULTIPLY(g, a), DE_MULTIPLY(b, a), a); 379 | } 380 | } 381 | else 382 | { 383 | for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch) 384 | { 385 | for (uint32_t x = 0; x < w; x++) 386 | { 387 | uint8_t r = src[x * 4 + 2], g = src[x * 4 + 1], b = src[x * 4], a = src[x * 4 + 3]; 388 | dst[x] = IM_COL32(multiply_table[DE_MULTIPLY(r, a)], multiply_table[DE_MULTIPLY(g, a)], multiply_table[DE_MULTIPLY(b, a)], multiply_table[a]); 389 | } 390 | } 391 | } 392 | #undef DE_MULTIPLY 393 | break; 394 | } 395 | default: 396 | IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!"); 397 | } 398 | } 399 | } // namespace 400 | 401 | #ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds) 402 | #ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION 403 | #define STBRP_ASSERT(x) do { IM_ASSERT(x); } while (0) 404 | #define STBRP_STATIC 405 | #define STB_RECT_PACK_IMPLEMENTATION 406 | #endif 407 | #ifdef IMGUI_STB_RECT_PACK_FILENAME 408 | #include IMGUI_STB_RECT_PACK_FILENAME 409 | #else 410 | #include "imstb_rectpack.h" 411 | #endif 412 | #endif 413 | 414 | struct ImFontBuildSrcGlyphFT 415 | { 416 | GlyphInfo Info; 417 | uint32_t Codepoint; 418 | unsigned int* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array 419 | 420 | ImFontBuildSrcGlyphFT() { memset((void*)this, 0, sizeof(*this)); } 421 | }; 422 | 423 | struct ImFontBuildSrcDataFT 424 | { 425 | FreeTypeFont Font; 426 | stbrp_rect* Rects; // Rectangle to pack. We first fill in their size and the packer will give us their position. 427 | const ImWchar* SrcRanges; // Ranges as requested by user (user is allowed to request too much, e.g. 0x0020..0xFFFF) 428 | int DstIndex; // Index into atlas->Fonts[] and dst_tmp_array[] 429 | int GlyphsHighest; // Highest requested codepoint 430 | int GlyphsCount; // Glyph count (excluding missing glyphs and glyphs already set by an earlier source font) 431 | ImBitVector GlyphsSet; // Glyph bit map (random access, 1-bit per codepoint. This will be a maximum of 8KB) 432 | ImVector GlyphsList; 433 | }; 434 | 435 | // Temporary data for one destination ImFont* (multiple source fonts can be merged into one destination ImFont) 436 | struct ImFontBuildDstDataFT 437 | { 438 | int SrcCount; // Number of source fonts targeting this destination font. 439 | int GlyphsHighest; 440 | int GlyphsCount; 441 | ImBitVector GlyphsSet; // This is used to resolve collision when multiple sources are merged into a same destination font. 442 | }; 443 | 444 | bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, unsigned int extra_flags) 445 | { 446 | IM_ASSERT(atlas->ConfigData.Size > 0); 447 | 448 | ImFontAtlasBuildInit(atlas); 449 | 450 | // Clear atlas 451 | atlas->TexID = 0; 452 | atlas->TexWidth = atlas->TexHeight = 0; 453 | atlas->TexUvScale = ImVec2(0.0f, 0.0f); 454 | atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f); 455 | atlas->ClearTexData(); 456 | 457 | // Temporary storage for building 458 | bool src_load_color = false; 459 | ImVector src_tmp_array; 460 | ImVector dst_tmp_array; 461 | src_tmp_array.resize(atlas->ConfigData.Size); 462 | dst_tmp_array.resize(atlas->Fonts.Size); 463 | memset((void*)src_tmp_array.Data, 0, (size_t)src_tmp_array.size_in_bytes()); 464 | memset((void*)dst_tmp_array.Data, 0, (size_t)dst_tmp_array.size_in_bytes()); 465 | 466 | // 1. Initialize font loading structure, check font data validity 467 | for (int src_i = 0; src_i < atlas->ConfigData.Size; src_i++) 468 | { 469 | ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; 470 | ImFontConfig& cfg = atlas->ConfigData[src_i]; 471 | FreeTypeFont& font_face = src_tmp.Font; 472 | IM_ASSERT(cfg.DstFont && (!cfg.DstFont->IsLoaded() || cfg.DstFont->ContainerAtlas == atlas)); 473 | 474 | // Find index from cfg.DstFont (we allow the user to set cfg.DstFont. Also it makes casual debugging nicer than when storing indices) 475 | src_tmp.DstIndex = -1; 476 | for (int output_i = 0; output_i < atlas->Fonts.Size && src_tmp.DstIndex == -1; output_i++) 477 | if (cfg.DstFont == atlas->Fonts[output_i]) 478 | src_tmp.DstIndex = output_i; 479 | IM_ASSERT(src_tmp.DstIndex != -1); // cfg.DstFont not pointing within atlas->Fonts[] array? 480 | if (src_tmp.DstIndex == -1) 481 | return false; 482 | 483 | // Load font 484 | if (!font_face.InitFont(ft_library, cfg, extra_flags)) 485 | return false; 486 | 487 | // Measure highest codepoints 488 | src_load_color |= (cfg.FontBuilderFlags & ImGuiFreeTypeBuilderFlags_LoadColor) != 0; 489 | ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; 490 | src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault(); 491 | for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) 492 | { 493 | // Check for valid range. This may also help detect *some* dangling pointers, because a common 494 | // user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent, 495 | // or to forget to zero-terminate the glyph range array. 496 | IM_ASSERT(src_range[0] <= src_range[1] && "Invalid range: is your glyph range array persistent? it is zero-terminated?"); 497 | src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]); 498 | } 499 | dst_tmp.SrcCount++; 500 | dst_tmp.GlyphsHighest = ImMax(dst_tmp.GlyphsHighest, src_tmp.GlyphsHighest); 501 | } 502 | 503 | // 2. For every requested codepoint, check for their presence in the font data, and handle redundancy or overlaps between source fonts to avoid unused glyphs. 504 | int total_glyphs_count = 0; 505 | for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) 506 | { 507 | ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; 508 | ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex]; 509 | src_tmp.GlyphsSet.Create(src_tmp.GlyphsHighest + 1); 510 | if (dst_tmp.GlyphsSet.Storage.empty()) 511 | dst_tmp.GlyphsSet.Create(dst_tmp.GlyphsHighest + 1); 512 | 513 | for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2) 514 | for (int codepoint = src_range[0]; codepoint <= (int)src_range[1]; codepoint++) 515 | { 516 | if (dst_tmp.GlyphsSet.TestBit(codepoint)) // Don't overwrite existing glyphs. We could make this an option (e.g. MergeOverwrite) 517 | continue; 518 | uint32_t glyph_index = FT_Get_Char_Index(src_tmp.Font.Face, codepoint); // It is actually in the font? (FIXME-OPT: We are not storing the glyph_index..) 519 | if (glyph_index == 0) 520 | continue; 521 | 522 | // Add to avail set/counters 523 | src_tmp.GlyphsCount++; 524 | dst_tmp.GlyphsCount++; 525 | src_tmp.GlyphsSet.SetBit(codepoint); 526 | dst_tmp.GlyphsSet.SetBit(codepoint); 527 | total_glyphs_count++; 528 | } 529 | } 530 | 531 | // 3. Unpack our bit map into a flat list (we now have all the Unicode points that we know are requested _and_ available _and_ not overlapping another) 532 | for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) 533 | { 534 | ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; 535 | src_tmp.GlyphsList.reserve(src_tmp.GlyphsCount); 536 | 537 | IM_ASSERT(sizeof(src_tmp.GlyphsSet.Storage.Data[0]) == sizeof(ImU32)); 538 | const ImU32* it_begin = src_tmp.GlyphsSet.Storage.begin(); 539 | const ImU32* it_end = src_tmp.GlyphsSet.Storage.end(); 540 | for (const ImU32* it = it_begin; it < it_end; it++) 541 | if (ImU32 entries_32 = *it) 542 | for (ImU32 bit_n = 0; bit_n < 32; bit_n++) 543 | if (entries_32 & ((ImU32)1 << bit_n)) 544 | { 545 | ImFontBuildSrcGlyphFT src_glyph; 546 | src_glyph.Codepoint = (ImWchar)(((it - it_begin) << 5) + bit_n); 547 | //src_glyph.GlyphIndex = 0; // FIXME-OPT: We had this info in the previous step and lost it.. 548 | src_tmp.GlyphsList.push_back(src_glyph); 549 | } 550 | src_tmp.GlyphsSet.Clear(); 551 | IM_ASSERT(src_tmp.GlyphsList.Size == src_tmp.GlyphsCount); 552 | } 553 | for (int dst_i = 0; dst_i < dst_tmp_array.Size; dst_i++) 554 | dst_tmp_array[dst_i].GlyphsSet.Clear(); 555 | dst_tmp_array.clear(); 556 | 557 | // Allocate packing character data and flag packed characters buffer as non-packed (x0=y0=x1=y1=0) 558 | // (We technically don't need to zero-clear buf_rects, but let's do it for the sake of sanity) 559 | ImVector buf_rects; 560 | buf_rects.resize(total_glyphs_count); 561 | memset(buf_rects.Data, 0, (size_t)buf_rects.size_in_bytes()); 562 | 563 | // Allocate temporary rasterization data buffers. 564 | // We could not find a way to retrieve accurate glyph size without rendering them. 565 | // (e.g. slot->metrics->width not always matching bitmap->width, especially considering the Oblique transform) 566 | // We allocate in chunks of 256 KB to not waste too much extra memory ahead. Hopefully users of FreeType won't mind the temporary allocations. 567 | const int BITMAP_BUFFERS_CHUNK_SIZE = 256 * 1024; 568 | int buf_bitmap_current_used_bytes = 0; 569 | ImVector buf_bitmap_buffers; 570 | buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE)); 571 | 572 | // 4. Gather glyphs sizes so we can pack them in our virtual canvas. 573 | // 8. Render/rasterize font characters into the texture 574 | int total_surface = 0; 575 | int buf_rects_out_n = 0; 576 | const int pack_padding = atlas->TexGlyphPadding; 577 | for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) 578 | { 579 | ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; 580 | ImFontConfig& cfg = atlas->ConfigData[src_i]; 581 | if (src_tmp.GlyphsCount == 0) 582 | continue; 583 | 584 | src_tmp.Rects = &buf_rects[buf_rects_out_n]; 585 | buf_rects_out_n += src_tmp.GlyphsCount; 586 | 587 | // Compute multiply table if requested 588 | const bool multiply_enabled = (cfg.RasterizerMultiply != 1.0f); 589 | unsigned char multiply_table[256]; 590 | if (multiply_enabled) 591 | ImFontAtlasBuildMultiplyCalcLookupTable(multiply_table, cfg.RasterizerMultiply); 592 | 593 | // Gather the sizes of all rectangles we will need to pack 594 | for (int glyph_i = 0; glyph_i < src_tmp.GlyphsList.Size; glyph_i++) 595 | { 596 | ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i]; 597 | 598 | const FT_Glyph_Metrics* metrics = src_tmp.Font.LoadGlyph(src_glyph.Codepoint); 599 | if (metrics == nullptr) 600 | continue; 601 | 602 | // Render glyph into a bitmap (currently held by FreeType) 603 | const FT_Bitmap* ft_bitmap = src_tmp.Font.RenderGlyphAndGetInfo(&src_glyph.Info); 604 | if (ft_bitmap == nullptr) 605 | continue; 606 | 607 | // Allocate new temporary chunk if needed 608 | const int bitmap_size_in_bytes = src_glyph.Info.Width * src_glyph.Info.Height * 4; 609 | if (buf_bitmap_current_used_bytes + bitmap_size_in_bytes > BITMAP_BUFFERS_CHUNK_SIZE) 610 | { 611 | buf_bitmap_current_used_bytes = 0; 612 | buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE)); 613 | } 614 | IM_ASSERT(buf_bitmap_current_used_bytes + bitmap_size_in_bytes <= BITMAP_BUFFERS_CHUNK_SIZE); // We could probably allocate custom-sized buffer instead. 615 | 616 | // Blit rasterized pixels to our temporary buffer and keep a pointer to it. 617 | src_glyph.BitmapData = (unsigned int*)(buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes); 618 | buf_bitmap_current_used_bytes += bitmap_size_in_bytes; 619 | src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width, multiply_enabled ? multiply_table : nullptr); 620 | 621 | src_tmp.Rects[glyph_i].w = (stbrp_coord)(src_glyph.Info.Width + pack_padding); 622 | src_tmp.Rects[glyph_i].h = (stbrp_coord)(src_glyph.Info.Height + pack_padding); 623 | total_surface += src_tmp.Rects[glyph_i].w * src_tmp.Rects[glyph_i].h; 624 | } 625 | } 626 | for (int i = 0; i < atlas->CustomRects.Size; i++) 627 | total_surface += (atlas->CustomRects[i].Width + pack_padding) * (atlas->CustomRects[i].Height + pack_padding); 628 | 629 | // We need a width for the skyline algorithm, any width! 630 | // The exact width doesn't really matter much, but some API/GPU have texture size limitations and increasing width can decrease height. 631 | // User can override TexDesiredWidth and TexGlyphPadding if they wish, otherwise we use a simple heuristic to select the width based on expected surface. 632 | const int surface_sqrt = (int)ImSqrt((float)total_surface) + 1; 633 | atlas->TexHeight = 0; 634 | if (atlas->TexDesiredWidth > 0) 635 | atlas->TexWidth = atlas->TexDesiredWidth; 636 | else 637 | atlas->TexWidth = (surface_sqrt >= 4096 * 0.7f) ? 4096 : (surface_sqrt >= 2048 * 0.7f) ? 2048 : (surface_sqrt >= 1024 * 0.7f) ? 1024 : 512; 638 | 639 | // 5. Start packing 640 | // Pack our extra data rectangles first, so it will be on the upper-left corner of our texture (UV will have small values). 641 | const int TEX_HEIGHT_MAX = 1024 * 32; 642 | const int num_nodes_for_packing_algorithm = atlas->TexWidth - atlas->TexGlyphPadding; 643 | ImVector pack_nodes; 644 | pack_nodes.resize(num_nodes_for_packing_algorithm); 645 | stbrp_context pack_context; 646 | stbrp_init_target(&pack_context, atlas->TexWidth - atlas->TexGlyphPadding, TEX_HEIGHT_MAX - atlas->TexGlyphPadding, pack_nodes.Data, pack_nodes.Size); 647 | ImFontAtlasBuildPackCustomRects(atlas, &pack_context); 648 | 649 | // 6. Pack each source font. No rendering yet, we are working with rectangles in an infinitely tall texture at this point. 650 | for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) 651 | { 652 | ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; 653 | if (src_tmp.GlyphsCount == 0) 654 | continue; 655 | 656 | stbrp_pack_rects(&pack_context, src_tmp.Rects, src_tmp.GlyphsCount); 657 | 658 | // Extend texture height and mark missing glyphs as non-packed so we won't render them. 659 | // FIXME: We are not handling packing failure here (would happen if we got off TEX_HEIGHT_MAX or if a single if larger than TexWidth?) 660 | for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) 661 | if (src_tmp.Rects[glyph_i].was_packed) 662 | atlas->TexHeight = ImMax(atlas->TexHeight, src_tmp.Rects[glyph_i].y + src_tmp.Rects[glyph_i].h); 663 | } 664 | 665 | // 7. Allocate texture 666 | atlas->TexHeight = (atlas->Flags & ImFontAtlasFlags_NoPowerOfTwoHeight) ? (atlas->TexHeight + 1) : ImUpperPowerOfTwo(atlas->TexHeight); 667 | atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight); 668 | if (src_load_color) 669 | { 670 | size_t tex_size = (size_t)atlas->TexWidth * atlas->TexHeight * 4; 671 | atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(tex_size); 672 | memset(atlas->TexPixelsRGBA32, 0, tex_size); 673 | } 674 | else 675 | { 676 | size_t tex_size = (size_t)atlas->TexWidth * atlas->TexHeight * 1; 677 | atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(tex_size); 678 | memset(atlas->TexPixelsAlpha8, 0, tex_size); 679 | } 680 | 681 | // 8. Copy rasterized font characters back into the main texture 682 | // 9. Setup ImFont and glyphs for runtime 683 | bool tex_use_colors = false; 684 | for (int src_i = 0; src_i < src_tmp_array.Size; src_i++) 685 | { 686 | ImFontBuildSrcDataFT& src_tmp = src_tmp_array[src_i]; 687 | 688 | // When merging fonts with MergeMode=true: 689 | // - We can have multiple input fonts writing into a same destination font. 690 | // - dst_font->ConfigData is != from cfg which is our source configuration. 691 | ImFontConfig& cfg = atlas->ConfigData[src_i]; 692 | ImFont* dst_font = cfg.DstFont; 693 | 694 | const float ascent = src_tmp.Font.Info.Ascender; 695 | const float descent = src_tmp.Font.Info.Descender; 696 | ImFontAtlasBuildSetupFont(atlas, dst_font, &cfg, ascent, descent); 697 | 698 | if (src_tmp.GlyphsCount == 0) 699 | continue; 700 | const float font_off_x = cfg.GlyphOffset.x; 701 | const float font_off_y = cfg.GlyphOffset.y + IM_ROUND(dst_font->Ascent); 702 | 703 | const int padding = atlas->TexGlyphPadding; 704 | for (int glyph_i = 0; glyph_i < src_tmp.GlyphsCount; glyph_i++) 705 | { 706 | ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i]; 707 | stbrp_rect& pack_rect = src_tmp.Rects[glyph_i]; 708 | IM_ASSERT(pack_rect.was_packed); 709 | if (pack_rect.w == 0 && pack_rect.h == 0) 710 | continue; 711 | 712 | GlyphInfo& info = src_glyph.Info; 713 | IM_ASSERT(info.Width + padding <= pack_rect.w); 714 | IM_ASSERT(info.Height + padding <= pack_rect.h); 715 | const int tx = pack_rect.x + padding; 716 | const int ty = pack_rect.y + padding; 717 | 718 | // Register glyph 719 | float x0 = info.OffsetX * src_tmp.Font.InvRasterizationDensity + font_off_x; 720 | float y0 = info.OffsetY * src_tmp.Font.InvRasterizationDensity + font_off_y; 721 | float x1 = x0 + info.Width * src_tmp.Font.InvRasterizationDensity; 722 | float y1 = y0 + info.Height * src_tmp.Font.InvRasterizationDensity; 723 | float u0 = (tx) / (float)atlas->TexWidth; 724 | float v0 = (ty) / (float)atlas->TexHeight; 725 | float u1 = (tx + info.Width) / (float)atlas->TexWidth; 726 | float v1 = (ty + info.Height) / (float)atlas->TexHeight; 727 | dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX * src_tmp.Font.InvRasterizationDensity); 728 | 729 | ImFontGlyph* dst_glyph = &dst_font->Glyphs.back(); 730 | IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint); 731 | if (src_glyph.Info.IsColored) 732 | dst_glyph->Colored = tex_use_colors = true; 733 | 734 | // Blit from temporary buffer to final texture 735 | size_t blit_src_stride = (size_t)src_glyph.Info.Width; 736 | size_t blit_dst_stride = (size_t)atlas->TexWidth; 737 | unsigned int* blit_src = src_glyph.BitmapData; 738 | if (atlas->TexPixelsAlpha8 != nullptr) 739 | { 740 | unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx; 741 | for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride) 742 | for (int x = 0; x < info.Width; x++) 743 | blit_dst[x] = (unsigned char)((blit_src[x] >> IM_COL32_A_SHIFT) & 0xFF); 744 | } 745 | else 746 | { 747 | unsigned int* blit_dst = atlas->TexPixelsRGBA32 + (ty * blit_dst_stride) + tx; 748 | for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride) 749 | for (int x = 0; x < info.Width; x++) 750 | blit_dst[x] = blit_src[x]; 751 | } 752 | } 753 | 754 | src_tmp.Rects = nullptr; 755 | } 756 | atlas->TexPixelsUseColors = tex_use_colors; 757 | 758 | // Cleanup 759 | for (int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++) 760 | IM_FREE(buf_bitmap_buffers[buf_i]); 761 | src_tmp_array.clear_destruct(); 762 | 763 | ImFontAtlasBuildFinish(atlas); 764 | 765 | return true; 766 | } 767 | 768 | // FreeType memory allocation callbacks 769 | static void* FreeType_Alloc(FT_Memory /*memory*/, long size) 770 | { 771 | return GImGuiFreeTypeAllocFunc((size_t)size, GImGuiFreeTypeAllocatorUserData); 772 | } 773 | 774 | static void FreeType_Free(FT_Memory /*memory*/, void* block) 775 | { 776 | GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData); 777 | } 778 | 779 | static void* FreeType_Realloc(FT_Memory /*memory*/, long cur_size, long new_size, void* block) 780 | { 781 | // Implement realloc() as we don't ask user to provide it. 782 | if (block == nullptr) 783 | return GImGuiFreeTypeAllocFunc((size_t)new_size, GImGuiFreeTypeAllocatorUserData); 784 | 785 | if (new_size == 0) 786 | { 787 | GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData); 788 | return nullptr; 789 | } 790 | 791 | if (new_size > cur_size) 792 | { 793 | void* new_block = GImGuiFreeTypeAllocFunc((size_t)new_size, GImGuiFreeTypeAllocatorUserData); 794 | memcpy(new_block, block, (size_t)cur_size); 795 | GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData); 796 | return new_block; 797 | } 798 | 799 | return block; 800 | } 801 | 802 | static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas) 803 | { 804 | // FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html 805 | FT_MemoryRec_ memory_rec = {}; 806 | memory_rec.user = nullptr; 807 | memory_rec.alloc = &FreeType_Alloc; 808 | memory_rec.free = &FreeType_Free; 809 | memory_rec.realloc = &FreeType_Realloc; 810 | 811 | // https://www.freetype.org/freetype2/docs/reference/ft2-module_management.html#FT_New_Library 812 | FT_Library ft_library; 813 | FT_Error error = FT_New_Library(&memory_rec, &ft_library); 814 | if (error != 0) 815 | return false; 816 | 817 | // If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator. 818 | FT_Add_Default_Modules(ft_library); 819 | 820 | #ifdef IMGUI_ENABLE_FREETYPE_LUNASVG 821 | // Install svg hooks for FreeType 822 | // https://freetype.org/freetype2/docs/reference/ft2-properties.html#svg-hooks 823 | // https://freetype.org/freetype2/docs/reference/ft2-svg_fonts.html#svg_fonts 824 | SVG_RendererHooks hooks = { ImGuiLunasvgPortInit, ImGuiLunasvgPortFree, ImGuiLunasvgPortRender, ImGuiLunasvgPortPresetSlot }; 825 | FT_Property_Set(ft_library, "ot-svg", "svg-hooks", &hooks); 826 | #endif // IMGUI_ENABLE_FREETYPE_LUNASVG 827 | #ifdef IMGUI_ENABLE_FREETYPE_PLUTOSVG 828 | // With plutosvg, use provided hooks 829 | FT_Property_Set(ft_library, "ot-svg", "svg-hooks", plutosvg_ft_svg_hooks()); 830 | #endif // IMGUI_ENABLE_FREETYPE_PLUTOSVG 831 | 832 | bool ret = ImFontAtlasBuildWithFreeTypeEx(ft_library, atlas, atlas->FontBuilderFlags); 833 | FT_Done_Library(ft_library); 834 | 835 | return ret; 836 | } 837 | 838 | const ImFontBuilderIO* ImGuiFreeType::GetBuilderForFreeType() 839 | { 840 | static ImFontBuilderIO io; 841 | io.FontBuilder_Build = ImFontAtlasBuildWithFreeType; 842 | return &io; 843 | } 844 | 845 | void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data) 846 | { 847 | GImGuiFreeTypeAllocFunc = alloc_func; 848 | GImGuiFreeTypeFreeFunc = free_func; 849 | GImGuiFreeTypeAllocatorUserData = user_data; 850 | } 851 | 852 | #ifdef IMGUI_ENABLE_FREETYPE_LUNASVG 853 | // For more details, see https://gitlab.freedesktop.org/freetype/freetype-demos/-/blob/master/src/rsvg-port.c 854 | // The original code from the demo is licensed under CeCILL-C Free Software License Agreement (https://gitlab.freedesktop.org/freetype/freetype/-/blob/master/LICENSE.TXT) 855 | struct LunasvgPortState 856 | { 857 | FT_Error err = FT_Err_Ok; 858 | lunasvg::Matrix matrix; 859 | std::unique_ptr svg = nullptr; 860 | }; 861 | 862 | static FT_Error ImGuiLunasvgPortInit(FT_Pointer* _state) 863 | { 864 | *_state = IM_NEW(LunasvgPortState)(); 865 | return FT_Err_Ok; 866 | } 867 | 868 | static void ImGuiLunasvgPortFree(FT_Pointer* _state) 869 | { 870 | IM_DELETE(*(LunasvgPortState**)_state); 871 | } 872 | 873 | static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state) 874 | { 875 | LunasvgPortState* state = *(LunasvgPortState**)_state; 876 | 877 | // If there was an error while loading the svg in ImGuiLunasvgPortPresetSlot(), the renderer hook still get called, so just returns the error. 878 | if (state->err != FT_Err_Ok) 879 | return state->err; 880 | 881 | // rows is height, pitch (or stride) equals to width * sizeof(int32) 882 | lunasvg::Bitmap bitmap((uint8_t*)slot->bitmap.buffer, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch); 883 | state->svg->setMatrix(state->svg->matrix().identity()); // Reset the svg matrix to the default value 884 | state->svg->render(bitmap, state->matrix); // state->matrix is already scaled and translated 885 | state->err = FT_Err_Ok; 886 | return state->err; 887 | } 888 | 889 | static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_Pointer* _state) 890 | { 891 | FT_SVG_Document document = (FT_SVG_Document)slot->other; 892 | LunasvgPortState* state = *(LunasvgPortState**)_state; 893 | FT_Size_Metrics& metrics = document->metrics; 894 | 895 | // This function is called twice, once in the FT_Load_Glyph() and another right before ImGuiLunasvgPortRender(). 896 | // If it's the latter, don't do anything because it's // already done in the former. 897 | if (cache) 898 | return state->err; 899 | 900 | state->svg = lunasvg::Document::loadFromData((const char*)document->svg_document, document->svg_document_length); 901 | if (state->svg == nullptr) 902 | { 903 | state->err = FT_Err_Invalid_SVG_Document; 904 | return state->err; 905 | } 906 | 907 | lunasvg::Box box = state->svg->box(); 908 | double scale = std::min(metrics.x_ppem / box.w, metrics.y_ppem / box.h); 909 | double xx = (double)document->transform.xx / (1 << 16); 910 | double xy = -(double)document->transform.xy / (1 << 16); 911 | double yx = -(double)document->transform.yx / (1 << 16); 912 | double yy = (double)document->transform.yy / (1 << 16); 913 | double x0 = (double)document->delta.x / 64 * box.w / metrics.x_ppem; 914 | double y0 = -(double)document->delta.y / 64 * box.h / metrics.y_ppem; 915 | 916 | // Scale and transform, we don't translate the svg yet 917 | state->matrix.identity(); 918 | state->matrix.scale(scale, scale); 919 | state->matrix.transform(xx, xy, yx, yy, x0, y0); 920 | state->svg->setMatrix(state->matrix); 921 | 922 | // Pre-translate the matrix for the rendering step 923 | state->matrix.translate(-box.x, -box.y); 924 | 925 | // Get the box again after the transformation 926 | box = state->svg->box(); 927 | 928 | // Calculate the bitmap size 929 | slot->bitmap_left = FT_Int(box.x); 930 | slot->bitmap_top = FT_Int(-box.y); 931 | slot->bitmap.rows = (unsigned int)(ImCeil((float)box.h)); 932 | slot->bitmap.width = (unsigned int)(ImCeil((float)box.w)); 933 | slot->bitmap.pitch = slot->bitmap.width * 4; 934 | slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA; 935 | 936 | // Compute all the bearings and set them correctly. The outline is scaled already, we just need to use the bounding box. 937 | double metrics_width = box.w; 938 | double metrics_height = box.h; 939 | double horiBearingX = box.x; 940 | double horiBearingY = -box.y; 941 | double vertBearingX = slot->metrics.horiBearingX / 64.0 - slot->metrics.horiAdvance / 64.0 / 2.0; 942 | double vertBearingY = (slot->metrics.vertAdvance / 64.0 - slot->metrics.height / 64.0) / 2.0; 943 | slot->metrics.width = FT_Pos(IM_ROUND(metrics_width * 64.0)); // Using IM_ROUND() assume width and height are positive 944 | slot->metrics.height = FT_Pos(IM_ROUND(metrics_height * 64.0)); 945 | slot->metrics.horiBearingX = FT_Pos(horiBearingX * 64); 946 | slot->metrics.horiBearingY = FT_Pos(horiBearingY * 64); 947 | slot->metrics.vertBearingX = FT_Pos(vertBearingX * 64); 948 | slot->metrics.vertBearingY = FT_Pos(vertBearingY * 64); 949 | 950 | if (slot->metrics.vertAdvance == 0) 951 | slot->metrics.vertAdvance = FT_Pos(metrics_height * 1.2 * 64.0); 952 | 953 | state->err = FT_Err_Ok; 954 | return state->err; 955 | } 956 | 957 | #endif // #ifdef IMGUI_ENABLE_FREETYPE_LUNASVG 958 | 959 | //----------------------------------------------------------------------------- 960 | 961 | #ifdef __GNUC__ 962 | #pragma GCC diagnostic pop 963 | #endif 964 | 965 | #ifdef _MSC_VER 966 | #pragma warning (pop) 967 | #endif 968 | 969 | #endif // #ifndef IMGUI_DISABLE 970 | --------------------------------------------------------------------------------