[Qt] Initial Imgui integration

This commit is contained in:
wheremyfoodat 2024-01-28 22:27:30 +02:00
parent 8ff2d7f9b2
commit 918645479a
211 changed files with 49460 additions and 21918 deletions

View file

@ -3,6 +3,10 @@ misc/cpp/
InputText() wrappers for C++ standard library (STL) type: std::string.
This is also an example of how you may wrap your own similar types.
misc/debuggers/
Helper files for popular debuggers.
With the .natvis file, types like ImVector<> will be displayed nicely in Visual Studio debugger.
misc/fonts/
Fonts loading/merging instructions (e.g. How to handle glyph ranges, how to merge icons fonts).
Command line tool "binary_to_compressed_c" to create compressed arrays to embed data in source code.
@ -12,11 +16,6 @@ misc/freetype/
Font atlas builder/rasterizer using FreeType instead of stb_truetype.
Benefit from better FreeType rasterization, in particular for small fonts.
misc/natvis/
Natvis file to describe dear imgui types in the Visual Studio debugger.
With this, types like ImVector<> will be displayed nicely in the debugger.
You can include this file a Visual Studio project file, or install it in Visual Studio folder.
misc/single_file/
Single-file header stub.
We use this to validate compiling all *.cpp files in a same compilation unit.

View file

@ -8,3 +8,6 @@ imgui_scoped.h
Additional header file with some RAII-style wrappers for common Dear ImGui functions.
Try by merging: https://github.com/ocornut/imgui/pull/2197
Discuss at: https://github.com/ocornut/imgui/issues/2096
See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness

View file

@ -1,16 +1,21 @@
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
// This is also an example of how you may wrap your own similar types.
// Compatibility:
// - std::string support is only guaranteed to work from C++11.
// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture)
// Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness
#include "imgui.h"
#include "imgui_stdlib.h"
// Clang warnings with -Weverything
#if defined(__clang__)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wsign-conversion" // warning: implicit conversion changes signedness
#endif
struct InputTextCallback_UserData
{
std::string* Str;
@ -74,3 +79,7 @@ bool ImGui::InputTextWithHint(const char* label, const char* hint, std::string*
cb_user_data.ChainCallbackUserData = user_data;
return InputTextWithHint(label, hint, (char*)str->c_str(), str->capacity() + 1, flags, InputTextCallback, &cb_user_data);
}
#if defined(__clang__)
#pragma clang diagnostic pop
#endif

View file

@ -1,13 +1,12 @@
// dear imgui: wrappers for C++ standard library (STL) types (std::string, etc.)
// This is also an example of how you may wrap your own similar types.
// Compatibility:
// - std::string support is only guaranteed to work from C++11.
// If you try to use it pre-C++11, please share your findings (w/ info about compiler/architecture)
// Changelog:
// - v0.10: Initial version. Added InputText() / InputTextMultiline() calls with std::string
// See more C++ related extension (fmt, RAII, syntaxis sugar) on Wiki:
// https://github.com/ocornut/imgui/wiki/Useful-Extensions#cness
#pragma once
#include <string>
@ -16,7 +15,7 @@ namespace ImGui
{
// ImGui::InputText() with std::string
// Because text input needs dynamic resizing, we need to setup a callback to grow the capacity
IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextMultiline(const char* label, std::string* str, const ImVec2& size = ImVec2(0, 0), ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = NULL, void* user_data = NULL);
IMGUI_API bool InputText(const char* label, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr);
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);
IMGUI_API bool InputTextWithHint(const char* label, const char* hint, std::string* str, ImGuiInputTextFlags flags = 0, ImGuiInputTextCallback callback = nullptr, void* user_data = nullptr);
}

View file

@ -0,0 +1,16 @@
HELPER FILES FOR POPULAR DEBUGGERS
imgui.gdb
GDB: disable stepping into trivial functions.
(read comments inside file for details)
imgui.natstepfilter
Visual Studio Debugger: disable stepping into trivial functions.
(read comments inside file for details)
imgui.natvis
Visual Studio Debugger: describe Dear ImGui types for better display.
With this, types like ImVector<> will be displayed nicely in the debugger.
(read comments inside file for details)

View file

@ -0,0 +1,12 @@
# GDB configuration to aid debugging experience
# To enable these customizations edit $HOME/.gdbinit (or ./.gdbinit if local gdbinit is enabled) and add:
# add-auto-load-safe-path /path/to/imgui.gdb
# source /path/to/imgui.gdb
#
# More Information at:
# * https://sourceware.org/gdb/current/onlinedocs/gdb/gdbinit-man.html
# * https://sourceware.org/gdb/current/onlinedocs/gdb/Init-File-in-the-Current-Directory.html#Init-File-in-the-Current-Directory
# Disable stepping into trivial functions
skip -rfunction Im(Vec2|Vec4|Strv|Vector|Span)::.+

View file

@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
.natstepfilter file for Visual Studio debugger.
Purpose: instruct debugger to skip some functions when using StepInto (F11)
Since Visual Studio 2022 version 17.6 Preview 2 (currently available as a "Preview" build on March 14, 2023)
It is possible to add the .natstepfilter file to your project file and it will automatically be used.
(https://developercommunity.visualstudio.com/t/allow-natstepfilter-and-natjmc-to-be-included-as-p/561718)
For older Visual Studio version prior to 2022 17.6 Preview 2:
* copy in %USERPROFILE%\Documents\Visual Studio XXXX\Visualizers (current user)
* or copy in %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers (all users)
If you have multiple VS version installed, the version that matters is the one you are using the IDE/debugger
of (not the compiling toolset). This is supported since Visual Studio 2012.
More information at: https://docs.microsoft.com/en-us/visualstudio/debugger/just-my-code?view=vs-2019#BKMK_C___Just_My_Code
-->
<StepFilter xmlns="http://schemas.microsoft.com/vstudio/debugger/natstepfilter/2010">
<!-- Disable stepping into trivial functions -->
<Function>
<Name>(ImVec2|ImVec4|ImStrv)::.+</Name>
<Action>NoStepInto</Action>
</Function>
<Function>
<Name>(ImVector|ImSpan).*::operator.+</Name>
<Action>NoStepInto</Action>
</Function>
</StepFilter>

View file

@ -1,6 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
.natvis file for Visual Studio debugger.
Purpose: provide nicer views on data types used by Dear ImGui.
<!-- natvis file for Visual Studio debugger (you can include this in a project file, or install in visual studio folder) -->
To enable:
* include file in your VS project (most recommended: not intrusive and always kept up to date!)
* or copy in %USERPROFILE%\Documents\Visual Studio XXXX\Visualizers (current user)
* or copy in %VsInstallDirectory%\Common7\Packages\Debugger\Visualizers (all users)
More information at: https://docs.microsoft.com/en-us/visualstudio/debugger/create-custom-views-of-native-objects?view=vs-2019
-->
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
@ -13,7 +22,7 @@
</ArrayItems>
</Expand>
</Type>
<Type Name="ImSpan&lt;*&gt;">
<DisplayString>{{Size={DataEnd-Data} }}</DisplayString>
<Expand>
@ -45,5 +54,9 @@
<Type Name="ImGuiWindow">
<DisplayString>{{Name {Name,s} Active {(Active||WasActive)?1:0,d} Child {(Flags &amp; 0x01000000)?1:0,d} Popup {(Flags &amp; 0x04000000)?1:0,d} Hidden {(Hidden)?1:0,d}}</DisplayString>
</Type>
</AutoVisualizer>
<Type Name="ImGuiDockNode">
<DisplayString>{{ID {ID,x} Pos=({Pos.x,g} {Pos.y,g}) Size=({Size.x,g} {Size.y,g}) Parent {(ParentNode==0)?0:ParentNode->ID,x} Childs {(ChildNodes[0] != 0)+(ChildNodes[1] != 0)} Windows {Windows.Size} }</DisplayString>
</Type>
</AutoVisualizer>

View file

@ -15,7 +15,7 @@
// You can also find a precompiled Windows binary in the binary/demo package available from https://github.com/ocornut/imgui
// Usage:
// binary_to_compressed_c.exe [-base85] [-nocompress] <inputfile> <symbolname>
// binary_to_compressed_c.exe [-base85] [-nocompress] [-nostatic] <inputfile> <symbolname>
// Usage example:
// # binary_to_compressed_c.exe myfont.ttf MyFont > myfont.cpp
// # binary_to_compressed_c.exe -base85 myfont.ttf MyFont > myfont.cpp
@ -31,23 +31,25 @@ typedef unsigned int stb_uint;
typedef unsigned char stb_uchar;
stb_uint stb_compress(stb_uchar* out, stb_uchar* in, stb_uint len);
static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression);
static bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression, bool use_static);
int main(int argc, char** argv)
{
if (argc < 3)
{
printf("Syntax: %s [-base85] [-nocompress] <inputfile> <symbolname>\n", argv[0]);
printf("Syntax: %s [-base85] [-nocompress] [-nostatic] <inputfile> <symbolname>\n", argv[0]);
return 0;
}
int argn = 1;
bool use_base85_encoding = false;
bool use_compression = true;
if (argv[argn][0] == '-')
bool use_static = true;
while (argn < (argc - 2) && argv[argn][0] == '-')
{
if (strcmp(argv[argn], "-base85") == 0) { use_base85_encoding = true; argn++; }
else if (strcmp(argv[argn], "-nocompress") == 0) { use_compression = false; argn++; }
else if (strcmp(argv[argn], "-nostatic") == 0) { use_static = false; argn++; }
else
{
fprintf(stderr, "Unknown argument: '%s'\n", argv[argn]);
@ -55,7 +57,7 @@ int main(int argc, char** argv)
}
}
bool ret = binary_to_compressed_c(argv[argn], argv[argn + 1], use_base85_encoding, use_compression);
bool ret = binary_to_compressed_c(argv[argn], argv[argn + 1], use_base85_encoding, use_compression, use_static);
if (!ret)
fprintf(stderr, "Error opening or reading file: '%s'\n", argv[argn]);
return ret ? 0 : 1;
@ -64,10 +66,10 @@ int main(int argc, char** argv)
char Encode85Byte(unsigned int x)
{
x = (x % 85) + 35;
return (x >= '\\') ? x + 1 : x;
return (char)((x >= '\\') ? x + 1 : x);
}
bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression)
bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_base85_encoding, bool use_compression, bool use_static)
{
// Read file
FILE* f = fopen(filename, "rb");
@ -90,10 +92,11 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
FILE* out = stdout;
fprintf(out, "// File: '%s' (%d bytes)\n", filename, (int)data_sz);
fprintf(out, "// Exported using binary_to_compressed_c.cpp\n");
const char* static_str = use_static ? "static " : "";
const char* compressed_str = use_compression ? "compressed_" : "";
if (use_base85_encoding)
{
fprintf(out, "static const char %s_%sdata_base85[%d+1] =\n \"", symbol, compressed_str, (int)((compressed_sz + 3) / 4)*5);
fprintf(out, "%sconst char %s_%sdata_base85[%d+1] =\n \"", static_str, symbol, compressed_str, (int)((compressed_sz + 3) / 4)*5);
char prev_c = 0;
for (int src_i = 0; src_i < compressed_sz; src_i += 4)
{
@ -112,8 +115,8 @@ bool binary_to_compressed_c(const char* filename, const char* symbol, bool use_b
}
else
{
fprintf(out, "static const unsigned int %s_%ssize = %d;\n", symbol, compressed_str, (int)compressed_sz);
fprintf(out, "static const unsigned int %s_%sdata[%d/4] =\n{", symbol, compressed_str, (int)((compressed_sz + 3) / 4)*4);
fprintf(out, "%sconst unsigned int %s_%ssize = %d;\n", static_str, symbol, compressed_str, (int)compressed_sz);
fprintf(out, "%sconst unsigned int %s_%sdata[%d/4] =\n{", static_str, symbol, compressed_str, (int)((compressed_sz + 3) / 4)*4);
int column = 0;
for (int i = 0; i < compressed_sz; i += 4)
{
@ -260,17 +263,17 @@ static int stb_compress_chunk(stb_uchar *history,
int best = 2, dist=0;
if (q+65536 > end)
match_max = end-q;
match_max = (stb_uint)(end-q);
else
match_max = 65536;
#define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap(b,d)))
#define stb__nc(b,d) ((d) <= window && ((b) > 9 || stb_not_crap((int)(b),(int)(d))))
#define STB__TRY(t,p) /* avoid retrying a match we already tried */ \
if (p ? dist != q-t : 1) \
if (p ? dist != (int)(q-t) : 1) \
if ((m = stb_matchlen(t, q, match_max)) > best) \
if (stb__nc(m,q-(t))) \
best = m, dist = q - (t)
best = m, dist = (int)(q - (t))
// rather than search for all matches, only try 4 candidate locations,
// chosen based on 4 different hash functions of different lengths.
@ -296,24 +299,24 @@ static int stb_compress_chunk(stb_uchar *history,
if (best < 3) { // fast path literals
++q;
} else if (best > 2 && best <= 0x80 && dist <= 0x100) {
outliterals(lit_start, q-lit_start); lit_start = (q += best);
outliterals(lit_start, (int)(q-lit_start)); lit_start = (q += best);
stb_out(0x80 + best-1);
stb_out(dist-1);
} else if (best > 5 && best <= 0x100 && dist <= 0x4000) {
outliterals(lit_start, q-lit_start); lit_start = (q += best);
outliterals(lit_start, (int)(q-lit_start)); lit_start = (q += best);
stb_out2(0x4000 + dist-1);
stb_out(best-1);
} else if (best > 7 && best <= 0x100 && dist <= 0x80000) {
outliterals(lit_start, q-lit_start); lit_start = (q += best);
outliterals(lit_start, (int)(q-lit_start)); lit_start = (q += best);
stb_out3(0x180000 + dist-1);
stb_out(best-1);
} else if (best > 8 && best <= 0x10000 && dist <= 0x80000) {
outliterals(lit_start, q-lit_start); lit_start = (q += best);
outliterals(lit_start, (int)(q-lit_start)); lit_start = (q += best);
stb_out3(0x100000 + dist-1);
stb_out2(best-1);
} else if (best > 9 && dist <= 0x1000000) {
if (best > 65536) best = 65536;
outliterals(lit_start, q-lit_start); lit_start = (q += best);
outliterals(lit_start, (int)(q-lit_start)); lit_start = (q += best);
if (best <= 0x100) {
stb_out(0x06);
stb_out3(dist-1);
@ -333,10 +336,10 @@ static int stb_compress_chunk(stb_uchar *history,
q = start+length;
// the literals are everything from lit_start to q
*pending_literals = (q - lit_start);
*pending_literals = (int)(q - lit_start);
stb__running_adler = stb_adler32(stb__running_adler, start, q - start);
return q - start;
stb__running_adler = stb_adler32(stb__running_adler, start, (stb_uint)(q - start));
return (int)(q - start);
}
static int stb_compress_inner(stb_uchar *input, stb_uint length)
@ -346,9 +349,9 @@ static int stb_compress_inner(stb_uchar *input, stb_uint length)
stb_uchar **chash;
chash = (stb_uchar**) malloc(stb__hashsize * sizeof(stb_uchar*));
if (chash == NULL) return 0; // failure
if (chash == nullptr) return 0; // failure
for (i=0; i < stb__hashsize; ++i)
chash[i] = NULL;
chash[i] = nullptr;
// stream signature
stb_out(0x57); stb_out(0xbc);
@ -377,9 +380,9 @@ static int stb_compress_inner(stb_uchar *input, stb_uint length)
stb_uint stb_compress(stb_uchar *out, stb_uchar *input, stb_uint length)
{
stb__out = out;
stb__outfile = NULL;
stb__outfile = nullptr;
stb_compress_inner(input, length);
return stb__out - out;
return (stb_uint)(stb__out - out);
}

View file

@ -5,14 +5,14 @@ Build font atlases using FreeType instead of stb_truetype (which is the default
### Usage
1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype`, `vcpkg integrate install`).
1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype --triplet=x64-windows`, `vcpkg integrate install`).
2. Add imgui_freetype.h/cpp alongside your project files.
3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file
### About Gamma Correct Blending
FreeType assumes blending in linear space rather than gamma space.
See FreeType note for [FT_Render_Glyph](https://www.freetype.org/freetype2/docs/reference/ft2-base_interface.html#FT_Render_Glyph).
See FreeType note for [FT_Render_Glyph](https://freetype.org/freetype2/docs/reference/ft2-glyph_retrieval.html#ft_render_glyph).
For correct results you need to be using sRGB and convert to linear space in the pixel shader output.
The default Dear ImGui styles will be impacted by this change (alpha values will need tweaking).
@ -22,9 +22,23 @@ See https://gist.github.com/ocornut/b3a9ecf13502fd818799a452969649ad
### Known issues
- Oversampling settins are ignored but also not so much necessary with the higher quality rendering.
- Oversampling settings are ignored but also not so much necessary with the higher quality rendering.
### Comparaison
### Comparison
Small, thin anti-aliased fonts are typically benefiting a lots from Freetype's hinting:
Small, thin anti-aliased fonts typically benefit a lot from FreeType's hinting:
![comparing_font_rasterizers](https://user-images.githubusercontent.com/8225057/107550178-fef87f00-6bd0-11eb-8d09-e2edb2f0ccfc.gif)
### Colorful glyphs/emojis
You can use the `ImGuiFreeTypeBuilderFlags_LoadColor` flag to load certain colorful glyphs. See the
["Using Colorful Glyphs/Emojis"](https://github.com/ocornut/imgui/blob/master/docs/FONTS.md#using-colorful-glyphsemojis) section of FONTS.md.
![colored glyphs](https://user-images.githubusercontent.com/8225057/106171241-9dc4ba80-6191-11eb-8a69-ca1467b206d1.png)
### Using OpenType SVG fonts (SVGinOT)
- *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.
- Popular fonts such as [twemoji](https://github.com/13rac1/twemoji-color-font) and fonts made with [scfbuild](https://github.com/13rac1/scfbuild) is SVGinOT
- Requires: [lunasvg](https://github.com/sammycage/lunasvg) v2.3.2 and above
1. Add `#define IMGUI_ENABLE_FREETYPE_LUNASVG` in your `imconfig.h`.
2. Get latest lunasvg binaries or build yourself. Under Windows you may use vcpkg with: `vcpkg install lunasvg --triplet=x64-windows`.

View file

@ -1,16 +1,19 @@
// dear imgui: FreeType font builder (used as a replacement for the stb_truetype builder)
// (code)
// Get latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype
// Get the latest version at https://github.com/ocornut/imgui/tree/master/misc/freetype
// Original code by @vuhdo (Aleksei Skriabin). Improvements by @mikesart. Maintained since 2019 by @ocornut.
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023/11/13: added support for ImFontConfig::RasterizationDensity field for scaling render density without scaling metrics.
// 2023/08/01: added support for SVG fonts, enable by using '#define IMGUI_ENABLE_FREETYPE_LUNASVG' (#6591)
// 2023/01/04: fixed a packing issue which in some occurrences would prevent large amount of glyphs from being packed correctly.
// 2021/08/23: fixed crash when FT_Render_Glyph() fails to render a glyph and returns NULL.
// 2021/03/05: added ImGuiFreeTypeBuilderFlags_Bitmap to load bitmap glyphs.
// 2021/03/02: set 'atlas->TexPixelsUseColors = true' to help some backends with deciding of a prefered texture format.
// 2021/01/28: added support for color-layered glyphs via ImGuiFreeTypeBuilderFlags_LoadColor (require Freetype 2.10+).
// 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().
// 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().
// 2020/06/04: fix for rare case where FT_Get_Char_Index() succeed but FT_Load_Glyph() fails.
// 2019/02/09: added RasterizerFlags::Monochrome flag to disable font anti-aliasing (combine with ::MonoHinting for best results!)
// 2019/01/15: added support for imgui allocators + added FreeType only override function SetAllocatorFunctions().
@ -31,6 +34,8 @@
// FIXME: cfg.OversampleH, OversampleV are not supported (but perhaps not so necessary with this rasterizer).
#include "imgui.h"
#ifndef IMGUI_DISABLE
#include "imgui_freetype.h"
#include "imgui_internal.h" // ImMin,ImMax,ImFontAtlasBuild*,
#include <stdint.h>
@ -40,13 +45,28 @@
#include FT_GLYPH_H // <freetype/ftglyph.h>
#include FT_SYNTHESIS_H // <freetype/ftsynth.h>
#ifdef _MSC_VER
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
#include FT_OTSVG_H // <freetype/otsvg.h>
#include FT_BBOX_H // <freetype/ftbbox.h>
#include <lunasvg.h>
#if !((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
#error IMGUI_ENABLE_FREETYPE_LUNASVG requires FreeType version >= 2.12
#endif
#endif
#if defined(__GNUC__)
#ifdef _MSC_VER
#pragma warning (push)
#pragma warning (disable: 4505) // unreferenced local function has been removed (stb stuff)
#pragma warning (disable: 26812) // [Static Analyzer] The enum type 'xxx' is unscoped. Prefer 'enum class' over 'enum' (Enum.3).
#endif
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpragmas" // warning: unknown option after '#pragma GCC diagnostic' kind
#pragma GCC diagnostic ignored "-Wunused-function" // warning: 'xxxx' defined but not used
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wsubobject-linkage" // warning: 'xxxx' has a field 'xxxx' whose type uses the anonymous namespace
#endif
#endif
//-------------------------------------------------------------------------
@ -60,7 +80,15 @@ static void ImGuiFreeTypeDefaultFreeFunc(void* ptr, void* user_data) { IM_UNUSE
// Current memory allocators
static void* (*GImGuiFreeTypeAllocFunc)(size_t size, void* user_data) = ImGuiFreeTypeDefaultAllocFunc;
static void (*GImGuiFreeTypeFreeFunc)(void* ptr, void* user_data) = ImGuiFreeTypeDefaultFreeFunc;
static void* GImGuiFreeTypeAllocatorUserData = NULL;
static void* GImGuiFreeTypeAllocatorUserData = nullptr;
// Lunasvg support
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
static FT_Error ImGuiLunasvgPortInit(FT_Pointer* state);
static void ImGuiLunasvgPortFree(FT_Pointer* state);
static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state);
static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_Pointer* _state);
#endif
//-------------------------------------------------------------------------
// Code
@ -130,7 +158,7 @@ namespace
void SetPixelHeight(int pixel_height); // Change font pixel size. All following calls to RasterizeGlyph() will use this size
const FT_Glyph_Metrics* LoadGlyph(uint32_t in_codepoint);
const FT_Bitmap* RenderGlyphAndGetInfo(GlyphInfo* out_glyph_info);
void BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = NULL);
void BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table = nullptr);
~FreeTypeFont() { CloseFont(); }
// [Internals]
@ -139,6 +167,8 @@ namespace
unsigned int UserFlags; // = ImFontConfig::RasterizerFlags
FT_Int32 LoadFlags;
FT_Render_Mode RenderMode;
float RasterizationDensity;
float InvRasterizationDensity;
};
// From SDL_ttf: Handy routines for converting from fixed point
@ -181,6 +211,9 @@ namespace
if (UserFlags & ImGuiFreeTypeBuilderFlags_LoadColor)
LoadFlags |= FT_LOAD_COLOR;
RasterizationDensity = cfg.RasterizerDensity;
InvRasterizationDensity = 1.0f / RasterizationDensity;
memset(&Info, 0, sizeof(Info));
SetPixelHeight((uint32_t)cfg.SizePixels);
@ -192,7 +225,7 @@ namespace
if (Face)
{
FT_Done_Face(Face);
Face = NULL;
Face = nullptr;
}
}
@ -204,33 +237,46 @@ namespace
FT_Size_RequestRec req;
req.type = (UserFlags & ImGuiFreeTypeBuilderFlags_Bitmap) ? FT_SIZE_REQUEST_TYPE_NOMINAL : FT_SIZE_REQUEST_TYPE_REAL_DIM;
req.width = 0;
req.height = (uint32_t)pixel_height * 64;
req.height = (uint32_t)(pixel_height * 64 * RasterizationDensity);
req.horiResolution = 0;
req.vertResolution = 0;
FT_Request_Size(Face, &req);
// Update font info
FT_Size_Metrics metrics = Face->size->metrics;
Info.PixelHeight = (uint32_t)pixel_height;
Info.Ascender = (float)FT_CEIL(metrics.ascender);
Info.Descender = (float)FT_CEIL(metrics.descender);
Info.LineSpacing = (float)FT_CEIL(metrics.height);
Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender);
Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance);
Info.PixelHeight = (uint32_t)(pixel_height * InvRasterizationDensity);
Info.Ascender = (float)FT_CEIL(metrics.ascender) * InvRasterizationDensity;
Info.Descender = (float)FT_CEIL(metrics.descender) * InvRasterizationDensity;
Info.LineSpacing = (float)FT_CEIL(metrics.height) * InvRasterizationDensity;
Info.LineGap = (float)FT_CEIL(metrics.height - metrics.ascender + metrics.descender) * InvRasterizationDensity;
Info.MaxAdvanceWidth = (float)FT_CEIL(metrics.max_advance) * InvRasterizationDensity;
}
const FT_Glyph_Metrics* FreeTypeFont::LoadGlyph(uint32_t codepoint)
{
uint32_t glyph_index = FT_Get_Char_Index(Face, codepoint);
if (glyph_index == 0)
return NULL;
return nullptr;
// If this crash for you: FreeType 2.11.0 has a crash bug on some bitmap/colored fonts.
// - https://gitlab.freedesktop.org/freetype/freetype/-/issues/1076
// - https://github.com/ocornut/imgui/issues/4567
// - https://github.com/ocornut/imgui/issues/4566
// You can use FreeType 2.10, or the patched version of 2.11.0 in VcPkg, or probably any upcoming FreeType version.
FT_Error error = FT_Load_Glyph(Face, glyph_index, LoadFlags);
if (error)
return NULL;
return nullptr;
// Need an outline for this to work
FT_GlyphSlot slot = Face->glyph;
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP || slot->format == FT_GLYPH_FORMAT_SVG);
#else
#if ((FREETYPE_MAJOR >= 2) && (FREETYPE_MINOR >= 12))
IM_ASSERT(slot->format != FT_GLYPH_FORMAT_SVG && "The font contains SVG glyphs, you'll need to enable IMGUI_ENABLE_FREETYPE_LUNASVG in imconfig.h and install required libraries in order to use this font");
#endif
IM_ASSERT(slot->format == FT_GLYPH_FORMAT_OUTLINE || slot->format == FT_GLYPH_FORMAT_BITMAP);
#endif // IMGUI_ENABLE_FREETYPE_LUNASVG
// Apply convenience transform (this is not picking from real "Bold"/"Italic" fonts! Merely applying FreeType helper transform. Oblique == Slanting)
if (UserFlags & ImGuiFreeTypeBuilderFlags_Bold)
@ -252,7 +298,7 @@ namespace
FT_GlyphSlot slot = Face->glyph;
FT_Error error = FT_Render_Glyph(slot, RenderMode);
if (error != 0)
return NULL;
return nullptr;
FT_Bitmap* ft_bitmap = &Face->glyph->bitmap;
out_glyph_info->Width = (int)ft_bitmap->width;
@ -267,7 +313,7 @@ namespace
void FreeTypeFont::BlitGlyph(const FT_Bitmap* ft_bitmap, uint32_t* dst, uint32_t dst_pitch, unsigned char* multiply_table)
{
IM_ASSERT(ft_bitmap != NULL);
IM_ASSERT(ft_bitmap != nullptr);
const uint32_t w = ft_bitmap->width;
const uint32_t h = ft_bitmap->rows;
const uint8_t* src = ft_bitmap->buffer;
@ -277,7 +323,7 @@ namespace
{
case FT_PIXEL_MODE_GRAY: // Grayscale image, 1 byte per pixel.
{
if (multiply_table == NULL)
if (multiply_table == nullptr)
{
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
for (uint32_t x = 0; x < w; x++)
@ -312,7 +358,7 @@ namespace
{
// FIXME: Converting pre-multiplied alpha to straight. Doesn't smell good.
#define DE_MULTIPLY(color, alpha) (ImU32)(255.0f * (float)color / (float)alpha + 0.5f)
if (multiply_table == NULL)
if (multiply_table == nullptr)
{
for (uint32_t y = 0; y < h; y++, src += src_pitch, dst += dst_pitch)
for (uint32_t x = 0; x < w; x++)
@ -339,7 +385,7 @@ namespace
IM_ASSERT(0 && "FreeTypeFont::BlitGlyph(): Unknown bitmap pixel mode!");
}
}
}
} // namespace
#ifndef STB_RECT_PACK_IMPLEMENTATION // in case the user already have an implementation in the _same_ compilation unit (e.g. unity builds)
#ifndef IMGUI_DISABLE_STB_RECT_PACK_IMPLEMENTATION
@ -360,7 +406,7 @@ struct ImFontBuildSrcGlyphFT
uint32_t Codepoint;
unsigned int* BitmapData; // Point within one of the dst_tmp_bitmap_buffers[] array
ImFontBuildSrcGlyphFT() { memset(this, 0, sizeof(*this)); }
ImFontBuildSrcGlyphFT() { memset((void*)this, 0, sizeof(*this)); }
};
struct ImFontBuildSrcDataFT
@ -391,7 +437,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
ImFontAtlasBuildInit(atlas);
// Clear atlas
atlas->TexID = (ImTextureID)NULL;
atlas->TexID = 0;
atlas->TexWidth = atlas->TexHeight = 0;
atlas->TexUvScale = ImVec2(0.0f, 0.0f);
atlas->TexUvWhitePixel = ImVec2(0.0f, 0.0f);
@ -432,7 +478,12 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
ImFontBuildDstDataFT& dst_tmp = dst_tmp_array[src_tmp.DstIndex];
src_tmp.SrcRanges = cfg.GlyphRanges ? cfg.GlyphRanges : atlas->GetGlyphRangesDefault();
for (const ImWchar* src_range = src_tmp.SrcRanges; src_range[0] && src_range[1]; src_range += 2)
{
// Check for valid range. This may also help detect *some* dangling pointers, because a common
// user error is to setup ImFontConfig::GlyphRanges with a pointer to data that isn't persistent.
IM_ASSERT(src_range[0] <= src_range[1]);
src_tmp.GlyphsHighest = ImMax(src_tmp.GlyphsHighest, (int)src_range[1]);
}
dst_tmp.SrcCount++;
dst_tmp.GlyphsHighest = ImMax(dst_tmp.GlyphsHighest, src_tmp.GlyphsHighest);
}
@ -500,7 +551,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
// Allocate temporary rasterization data buffers.
// We could not find a way to retrieve accurate glyph size without rendering them.
// (e.g. slot->metrics->width not always matching bitmap->width, especially considering the Oblique transform)
// We allocate in chunks of 256 KB to not waste too much extra memory ahead. Hopefully users of FreeType won't find the temporary allocations.
// 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.
const int BITMAP_BUFFERS_CHUNK_SIZE = 256 * 1024;
int buf_bitmap_current_used_bytes = 0;
ImVector<unsigned char*> buf_bitmap_buffers;
@ -533,12 +584,13 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
ImFontBuildSrcGlyphFT& src_glyph = src_tmp.GlyphsList[glyph_i];
const FT_Glyph_Metrics* metrics = src_tmp.Font.LoadGlyph(src_glyph.Codepoint);
if (metrics == NULL)
if (metrics == nullptr)
continue;
// Render glyph into a bitmap (currently held by FreeType)
const FT_Bitmap* ft_bitmap = src_tmp.Font.RenderGlyphAndGetInfo(&src_glyph.Info);
IM_ASSERT(ft_bitmap);
if (ft_bitmap == nullptr)
continue;
// Allocate new temporary chunk if needed
const int bitmap_size_in_bytes = src_glyph.Info.Width * src_glyph.Info.Height * 4;
@ -547,11 +599,12 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
buf_bitmap_current_used_bytes = 0;
buf_bitmap_buffers.push_back((unsigned char*)IM_ALLOC(BITMAP_BUFFERS_CHUNK_SIZE));
}
IM_ASSERT(buf_bitmap_current_used_bytes + bitmap_size_in_bytes <= BITMAP_BUFFERS_CHUNK_SIZE); // We could probably allocate custom-sized buffer instead.
// Blit rasterized pixels to our temporary buffer and keep a pointer to it.
src_glyph.BitmapData = (unsigned int*)(buf_bitmap_buffers.back() + buf_bitmap_current_used_bytes);
buf_bitmap_current_used_bytes += bitmap_size_in_bytes;
src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width, multiply_enabled ? multiply_table : NULL);
src_tmp.Font.BlitGlyph(ft_bitmap, src_glyph.BitmapData, src_glyph.Info.Width, multiply_enabled ? multiply_table : nullptr);
src_tmp.Rects[glyph_i].w = (stbrp_coord)(src_glyph.Info.Width + padding);
src_tmp.Rects[glyph_i].h = (stbrp_coord)(src_glyph.Info.Height + padding);
@ -576,7 +629,7 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
ImVector<stbrp_node> pack_nodes;
pack_nodes.resize(num_nodes_for_packing_algorithm);
stbrp_context pack_context;
stbrp_init_target(&pack_context, atlas->TexWidth, TEX_HEIGHT_MAX, pack_nodes.Data, pack_nodes.Size);
stbrp_init_target(&pack_context, atlas->TexWidth - atlas->TexGlyphPadding, TEX_HEIGHT_MAX - atlas->TexGlyphPadding, pack_nodes.Data, pack_nodes.Size);
ImFontAtlasBuildPackCustomRects(atlas, &pack_context);
// 6. Pack each source font. No rendering yet, we are working with rectangles in an infinitely tall texture at this point.
@ -600,13 +653,15 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
atlas->TexUvScale = ImVec2(1.0f / atlas->TexWidth, 1.0f / atlas->TexHeight);
if (src_load_color)
{
atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight * 4);
memset(atlas->TexPixelsRGBA32, 0, atlas->TexWidth * atlas->TexHeight * 4);
size_t tex_size = (size_t)atlas->TexWidth * atlas->TexHeight * 4;
atlas->TexPixelsRGBA32 = (unsigned int*)IM_ALLOC(tex_size);
memset(atlas->TexPixelsRGBA32, 0, tex_size);
}
else
{
atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(atlas->TexWidth * atlas->TexHeight);
memset(atlas->TexPixelsAlpha8, 0, atlas->TexWidth * atlas->TexHeight);
size_t tex_size = (size_t)atlas->TexWidth * atlas->TexHeight * 1;
atlas->TexPixelsAlpha8 = (unsigned char*)IM_ALLOC(tex_size);
memset(atlas->TexPixelsAlpha8, 0, tex_size);
}
// 8. Copy rasterized font characters back into the main texture
@ -645,11 +700,27 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
const int tx = pack_rect.x + padding;
const int ty = pack_rect.y + padding;
// Register glyph
float x0 = info.OffsetX * src_tmp.Font.InvRasterizationDensity + font_off_x;
float y0 = info.OffsetY * src_tmp.Font.InvRasterizationDensity + font_off_y;
float x1 = x0 + info.Width * src_tmp.Font.InvRasterizationDensity;
float y1 = y0 + info.Height * src_tmp.Font.InvRasterizationDensity;
float u0 = (tx) / (float)atlas->TexWidth;
float v0 = (ty) / (float)atlas->TexHeight;
float u1 = (tx + info.Width) / (float)atlas->TexWidth;
float v1 = (ty + info.Height) / (float)atlas->TexHeight;
dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX * src_tmp.Font.InvRasterizationDensity);
ImFontGlyph* dst_glyph = &dst_font->Glyphs.back();
IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint);
if (src_glyph.Info.IsColored)
dst_glyph->Colored = tex_use_colors = true;
// Blit from temporary buffer to final texture
size_t blit_src_stride = (size_t)src_glyph.Info.Width;
size_t blit_dst_stride = (size_t)atlas->TexWidth;
unsigned int* blit_src = src_glyph.BitmapData;
if (atlas->TexPixelsAlpha8 != NULL)
if (atlas->TexPixelsAlpha8 != nullptr)
{
unsigned char* blit_dst = atlas->TexPixelsAlpha8 + (ty * blit_dst_stride) + tx;
for (int y = 0; y < info.Height; y++, blit_dst += blit_dst_stride, blit_src += blit_src_stride)
@ -663,33 +734,16 @@ bool ImFontAtlasBuildWithFreeTypeEx(FT_Library ft_library, ImFontAtlas* atlas, u
for (int x = 0; x < info.Width; x++)
blit_dst[x] = blit_src[x];
}
// Register glyph
float x0 = info.OffsetX + font_off_x;
float y0 = info.OffsetY + font_off_y;
float x1 = x0 + info.Width;
float y1 = y0 + info.Height;
float u0 = (tx) / (float)atlas->TexWidth;
float v0 = (ty) / (float)atlas->TexHeight;
float u1 = (tx + info.Width) / (float)atlas->TexWidth;
float v1 = (ty + info.Height) / (float)atlas->TexHeight;
dst_font->AddGlyph(&cfg, (ImWchar)src_glyph.Codepoint, x0, y0, x1, y1, u0, v0, u1, v1, info.AdvanceX);
ImFontGlyph* dst_glyph = &dst_font->Glyphs.back();
IM_ASSERT(dst_glyph->Codepoint == src_glyph.Codepoint);
if (src_glyph.Info.IsColored)
dst_glyph->Colored = tex_use_colors = true;
}
src_tmp.Rects = NULL;
src_tmp.Rects = nullptr;
}
atlas->TexPixelsUseColors = tex_use_colors;
// Cleanup
for (int buf_i = 0; buf_i < buf_bitmap_buffers.Size; buf_i++)
IM_FREE(buf_bitmap_buffers[buf_i]);
for (int src_i = 0; src_i < src_tmp_array.Size; src_i++)
src_tmp_array[src_i].~ImFontBuildSrcDataFT();
src_tmp_array.clear_destruct();
ImFontAtlasBuildFinish(atlas);
@ -710,13 +764,13 @@ static void FreeType_Free(FT_Memory /*memory*/, void* block)
static void* FreeType_Realloc(FT_Memory /*memory*/, long cur_size, long new_size, void* block)
{
// Implement realloc() as we don't ask user to provide it.
if (block == NULL)
if (block == nullptr)
return GImGuiFreeTypeAllocFunc((size_t)new_size, GImGuiFreeTypeAllocatorUserData);
if (new_size == 0)
{
GImGuiFreeTypeFreeFunc(block, GImGuiFreeTypeAllocatorUserData);
return NULL;
return nullptr;
}
if (new_size > cur_size)
@ -734,7 +788,7 @@ static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas)
{
// FreeType memory management: https://www.freetype.org/freetype2/docs/design/design-4.html
FT_MemoryRec_ memory_rec = {};
memory_rec.user = NULL;
memory_rec.user = nullptr;
memory_rec.alloc = &FreeType_Alloc;
memory_rec.free = &FreeType_Free;
memory_rec.realloc = &FreeType_Realloc;
@ -748,6 +802,14 @@ static bool ImFontAtlasBuildWithFreeType(ImFontAtlas* atlas)
// If you don't call FT_Add_Default_Modules() the rest of code may work, but FreeType won't use our custom allocator.
FT_Add_Default_Modules(ft_library);
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
// Install svg hooks for FreeType
// https://freetype.org/freetype2/docs/reference/ft2-properties.html#svg-hooks
// https://freetype.org/freetype2/docs/reference/ft2-svg_fonts.html#svg_fonts
SVG_RendererHooks hooks = { ImGuiLunasvgPortInit, ImGuiLunasvgPortFree, ImGuiLunasvgPortRender, ImGuiLunasvgPortPresetSlot };
FT_Property_Set(ft_library, "ot-svg", "svg-hooks", &hooks);
#endif // IMGUI_ENABLE_FREETYPE_LUNASVG
bool ret = ImFontAtlasBuildWithFreeTypeEx(ft_library, atlas, atlas->FontBuilderFlags);
FT_Done_Library(ft_library);
@ -767,3 +829,122 @@ void ImGuiFreeType::SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* u
GImGuiFreeTypeFreeFunc = free_func;
GImGuiFreeTypeAllocatorUserData = user_data;
}
#ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
// For more details, see https://gitlab.freedesktop.org/freetype/freetype-demos/-/blob/master/src/rsvg-port.c
// 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)
struct LunasvgPortState
{
FT_Error err = FT_Err_Ok;
lunasvg::Matrix matrix;
std::unique_ptr<lunasvg::Document> svg = nullptr;
};
static FT_Error ImGuiLunasvgPortInit(FT_Pointer* _state)
{
*_state = IM_NEW(LunasvgPortState)();
return FT_Err_Ok;
}
static void ImGuiLunasvgPortFree(FT_Pointer* _state)
{
IM_DELETE(*(LunasvgPortState**)_state);
}
static FT_Error ImGuiLunasvgPortRender(FT_GlyphSlot slot, FT_Pointer* _state)
{
LunasvgPortState* state = *(LunasvgPortState**)_state;
// If there was an error while loading the svg in ImGuiLunasvgPortPresetSlot(), the renderer hook still get called, so just returns the error.
if (state->err != FT_Err_Ok)
return state->err;
// rows is height, pitch (or stride) equals to width * sizeof(int32)
lunasvg::Bitmap bitmap((uint8_t*)slot->bitmap.buffer, slot->bitmap.width, slot->bitmap.rows, slot->bitmap.pitch);
state->svg->setMatrix(state->svg->matrix().identity()); // Reset the svg matrix to the default value
state->svg->render(bitmap, state->matrix); // state->matrix is already scaled and translated
state->err = FT_Err_Ok;
return state->err;
}
static FT_Error ImGuiLunasvgPortPresetSlot(FT_GlyphSlot slot, FT_Bool cache, FT_Pointer* _state)
{
FT_SVG_Document document = (FT_SVG_Document)slot->other;
LunasvgPortState* state = *(LunasvgPortState**)_state;
FT_Size_Metrics& metrics = document->metrics;
// This function is called twice, once in the FT_Load_Glyph() and another right before ImGuiLunasvgPortRender().
// If it's the latter, don't do anything because it's // already done in the former.
if (cache)
return state->err;
state->svg = lunasvg::Document::loadFromData((const char*)document->svg_document, document->svg_document_length);
if (state->svg == nullptr)
{
state->err = FT_Err_Invalid_SVG_Document;
return state->err;
}
lunasvg::Box box = state->svg->box();
double scale = std::min(metrics.x_ppem / box.w, metrics.y_ppem / box.h);
double xx = (double)document->transform.xx / (1 << 16);
double xy = -(double)document->transform.xy / (1 << 16);
double yx = -(double)document->transform.yx / (1 << 16);
double yy = (double)document->transform.yy / (1 << 16);
double x0 = (double)document->delta.x / 64 * box.w / metrics.x_ppem;
double y0 = -(double)document->delta.y / 64 * box.h / metrics.y_ppem;
// Scale and transform, we don't translate the svg yet
state->matrix.identity();
state->matrix.scale(scale, scale);
state->matrix.transform(xx, xy, yx, yy, x0, y0);
state->svg->setMatrix(state->matrix);
// Pre-translate the matrix for the rendering step
state->matrix.translate(-box.x, -box.y);
// Get the box again after the transformation
box = state->svg->box();
// Calculate the bitmap size
slot->bitmap_left = FT_Int(box.x);
slot->bitmap_top = FT_Int(-box.y);
slot->bitmap.rows = (unsigned int)(ImCeil((float)box.h));
slot->bitmap.width = (unsigned int)(ImCeil((float)box.w));
slot->bitmap.pitch = slot->bitmap.width * 4;
slot->bitmap.pixel_mode = FT_PIXEL_MODE_BGRA;
// Compute all the bearings and set them correctly. The outline is scaled already, we just need to use the bounding box.
double metrics_width = box.w;
double metrics_height = box.h;
double horiBearingX = box.x;
double horiBearingY = -box.y;
double vertBearingX = slot->metrics.horiBearingX / 64.0 - slot->metrics.horiAdvance / 64.0 / 2.0;
double vertBearingY = (slot->metrics.vertAdvance / 64.0 - slot->metrics.height / 64.0) / 2.0;
slot->metrics.width = FT_Pos(IM_ROUND(metrics_width * 64.0)); // Using IM_ROUND() assume width and height are positive
slot->metrics.height = FT_Pos(IM_ROUND(metrics_height * 64.0));
slot->metrics.horiBearingX = FT_Pos(horiBearingX * 64);
slot->metrics.horiBearingY = FT_Pos(horiBearingY * 64);
slot->metrics.vertBearingX = FT_Pos(vertBearingX * 64);
slot->metrics.vertBearingY = FT_Pos(vertBearingY * 64);
if (slot->metrics.vertAdvance == 0)
slot->metrics.vertAdvance = FT_Pos(metrics_height * 1.2 * 64.0);
state->err = FT_Err_Ok;
return state->err;
}
#endif // #ifdef IMGUI_ENABLE_FREETYPE_LUNASVG
//-----------------------------------------------------------------------------
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#ifdef _MSC_VER
#pragma warning (pop)
#endif
#endif // #ifndef IMGUI_DISABLE

View file

@ -2,8 +2,8 @@
// (headers)
#pragma once
#include "imgui.h" // IMGUI_API
#ifndef IMGUI_DISABLE
// Forward declarations
struct ImFontAtlas;
@ -40,11 +40,12 @@ namespace ImGuiFreeType
// Override allocators. By default ImGuiFreeType will use IM_ALLOC()/IM_FREE()
// However, as FreeType does lots of allocations we provide a way for the user to redirect it to a separate memory heap if desired.
IMGUI_API void SetAllocatorFunctions(void* (*alloc_func)(size_t sz, void* user_data), void (*free_func)(void* ptr, void* user_data), void* user_data = NULL);
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);
// Obsolete names (will be removed soon)
// Prefer using '#define IMGUI_ENABLE_FREETYPE'
#ifndef IMGUI_DISABLE_OBSOLETE_FUNCTIONS
static inline bool BuildFontAtlas(ImFontAtlas* atlas, unsigned int flags = 0) { atlas->FontBuilderIO = GetBuilderForFreeType(); atlas->FontBuilderFlags = flags; return atlas->Build(); }
//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'
#endif
}
#endif // #ifndef IMGUI_DISABLE

View file

@ -1,4 +0,0 @@
Natvis file to describe dear imgui types in the Visual Studio debugger.
With this, types like ImVector<> will be displayed nicely in the debugger.
You can include this file a Visual Studio project file, or install it in Visual Studio folder.

View file

@ -7,7 +7,15 @@
// #define IMGUI_IMPLEMENTATION
// Before you include this file in *one* C++ file to create the implementation.
// Using this in your project will leak the contents of imgui_internal.h and ImVec2 operators in this compilation unit.
#ifdef IMGUI_IMPLEMENTATION
#define IMGUI_DEFINE_MATH_OPERATORS
#endif
#include "../../imgui.h"
#ifdef IMGUI_ENABLE_FREETYPE
#include "../../misc/freetype/imgui_freetype.h"
#endif
#ifdef IMGUI_IMPLEMENTATION
#include "../../imgui.cpp"
@ -15,4 +23,7 @@
#include "../../imgui_draw.cpp"
#include "../../imgui_tables.cpp"
#include "../../imgui_widgets.cpp"
#ifdef IMGUI_ENABLE_FREETYPE
#include "../../misc/freetype/imgui_freetype.cpp"
#endif
#endif