Skip to content

Commit

Permalink
add glyph ranges
Browse files Browse the repository at this point in the history
  • Loading branch information
pkdawson committed Apr 26, 2024
1 parent 446164c commit 47f68a0
Show file tree
Hide file tree
Showing 13 changed files with 134 additions and 53 deletions.
23 changes: 21 additions & 2 deletions addons/imgui-godot/ImGuiGodot/ImGuiGD.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,28 @@ public static void ResetFonts()
_backend.ResetFonts();
}

public static void AddFont(FontFile fontData, int fontSize, bool merge = false)
public static void AddFont(
FontFile fontData,
int fontSize,
bool merge = false,
ushort[]? glyphRanges = null)
{
_backend.AddFont(fontData, fontSize, merge);
_backend.AddFont(fontData, fontSize, merge, glyphRanges);
}

/// <summary>
/// Add a font using glyph ranges from ImGui.GetIO().Fonts.GetGlyphRanges*()
/// </summary>
/// <param name="glyphRanges">pointer to an array of ushorts terminated by 0</param>
public static unsafe void AddFont(FontFile fontData, int fontSize, bool merge, nint glyphRanges)
{
ushort* p = (ushort*)glyphRanges;
int len = 1;
while (p[len++] != 0) ;
ushort[] gr = new ushort[len];
for (int i = 0; i < len; ++i)
gr[i] = p[i];
_backend.AddFont(fontData, fontSize, merge, gr);
}

public static void AddFontDefault()
Expand Down
14 changes: 12 additions & 2 deletions addons/imgui-godot/ImGuiGodot/Internal/BackendNative.cs
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,19 @@ public bool Visible
set => _gd.Set(PropertyName.Visible, value);
}

public void AddFont(FontFile fontData, int fontSize, bool merge)
public void AddFont(FontFile fontData, int fontSize, bool merge, ushort[]? glyphRanges)
{
_gd.Call(MethodName.AddFont, fontData, fontSize, merge);
if (glyphRanges != null)
{
int[] gr = new int[glyphRanges.Length];
for (int i = 0; i < glyphRanges.Length; ++i)
gr[i] = glyphRanges[i];
_gd.Call(MethodName.AddFont, fontData, fontSize, merge, gr);
}
else
{
_gd.Call(MethodName.AddFont, fontData, fontSize, merge);
}
}

public void AddFontDefault()
Expand Down
6 changes: 3 additions & 3 deletions addons/imgui-godot/ImGuiGodot/Internal/BackendNet.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@ public bool Visible
set => ImGuiLayer.Instance.Visible = value;
}

public void AddFont(FontFile fontData, int fontSize, bool merge)
public void AddFont(FontFile fontData, int fontSize, bool merge, ushort[]? glyphRanges)
{
State.Instance.Fonts.AddFont(fontData, fontSize, merge);
State.Instance.Fonts.AddFont(fontData, fontSize, merge, glyphRanges);
}

public void AddFontDefault()
{
State.Instance.Fonts.AddFont(null, 13, false);
State.Instance.Fonts.AddFont(null, 13, false, null);
}

public void Connect(Callable callable)
Expand Down
54 changes: 38 additions & 16 deletions addons/imgui-godot/ImGuiGodot/Internal/Fonts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ private sealed class FontParams
public FontFile? Font { get; init; }
public int FontSize { get; init; }
public bool Merge { get; init; }
public ushort[]? Ranges { get; init; }
}
private readonly List<FontParams> _fontConfiguration = [];

Expand All @@ -32,21 +33,30 @@ public void ResetFonts()
_fontConfiguration.Clear();
}

public void AddFont(FontFile? fontData, int fontSize, bool merge)
public void AddFont(FontFile? fontData, int fontSize, bool merge, ushort[]? ranges)
{
_fontConfiguration.Add(
new FontParams { Font = fontData, FontSize = fontSize, Merge = merge });
new FontParams
{
Font = fontData,
FontSize = fontSize,
Merge = merge,
Ranges = ranges
});
}

private static unsafe void AddFontToAtlas(FontFile? fontData, int fontSize, bool merge)
private static unsafe void AddFontToAtlas(FontParams fp, float scale)
{
var io = ImGui.GetIO();
int fontSize = (int)(fp.FontSize * scale);
ImFontConfig* fc = ImGuiNative.ImFontConfig_ImFontConfig();
if (merge)

if (fp.Merge)
{
fc->MergeMode = 1;
}

if (fontData == null)
if (fp.Font == null)
{
// default font
var fcptr = new ImFontConfigPtr(fc)
Expand All @@ -56,28 +66,37 @@ private static unsafe void AddFontToAtlas(FontFile? fontData, int fontSize, bool
OversampleV = 1,
PixelSnapH = true
};
ImGui.GetIO().Fonts.AddFontDefault(fc);
io.Fonts.AddFontDefault(fc);
}
else
{
ImVector ranges = GetRanges(fontData);
string name = $"{System.IO.Path.GetFileName(fontData.ResourcePath)}, {fontSize}px";
string name = $"{System.IO.Path.GetFileName(fp.Font.ResourcePath)}, {fontSize}px";
for (int i = 0; i < name.Length && i < 40; ++i)
{
fc->Name[i] = Convert.ToByte(name[i]);
}

int len = fontData.Data.Length;
int len = fp.Font.Data.Length;
// let ImGui manage this memory
IntPtr p = ImGui.MemAlloc((uint)len);
Marshal.Copy(fontData.Data, 0, p, len);
ImGui.GetIO().Fonts.AddFontFromMemoryTTF(p, len, fontSize, fc, ranges.Data);
Marshal.Copy(fp.Font.Data, 0, p, len);
if (fp.Ranges == null)
{
ImVector ranges = GetRanges(fp.Font);
io.Fonts.AddFontFromMemoryTTF(p, len, fontSize, fc, ranges.Data);
}
else
{
fixed (ushort* pranges = fp.Ranges)
{
io.Fonts.AddFontFromMemoryTTF(p, len, fontSize, fc, (nint)pranges);
}
}
}

if (merge)
{
ImGui.GetIO().Fonts.Build();
}
if (fp.Merge)
io.Fonts.Build();

ImGuiNative.ImFontConfig_destroy(fc);
}

Expand Down Expand Up @@ -129,6 +148,8 @@ public unsafe void RebuildFontAtlas(float scale)
{
var io = ImGui.GetIO();
int fontIndex = -1;

// save current font index
if (io.NativePtr->FontDefault != null)
{
for (int i = 0; i < io.Fonts.Fonts.Size; ++i)
Expand All @@ -145,7 +166,7 @@ public unsafe void RebuildFontAtlas(float scale)

foreach (var fontParams in _fontConfiguration)
{
AddFontToAtlas(fontParams.Font, (int)(fontParams.FontSize * scale), fontParams.Merge);
AddFontToAtlas(fontParams, scale);
}

io.Fonts.GetTexDataAsRGBA32(
Expand All @@ -163,6 +184,7 @@ public unsafe void RebuildFontAtlas(float scale)
io.Fonts.SetTexID((IntPtr)_fontTexture.GetRid().Id);
io.Fonts.ClearTexData();

// maintain selected font when rescaling
if (fontIndex != -1 && fontIndex < io.Fonts.Fonts.Size)
{
io.NativePtr->FontDefault = io.Fonts.Fonts[fontIndex].NativePtr;
Expand Down
2 changes: 1 addition & 1 deletion addons/imgui-godot/ImGuiGodot/Internal/IBackend.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ internal interface IBackend
public float JoyAxisDeadZone { get; set; }
public float Scale { get; set; }
public void ResetFonts();
public void AddFont(FontFile fontData, int fontSize, bool merge);
public void AddFont(FontFile fontData, int fontSize, bool merge, ushort[]? glyphRanges);
public void AddFontDefault();
public void RebuildFontAtlas(float scale);
public void Connect(Callable callable);
Expand Down
15 changes: 13 additions & 2 deletions gdext/include/imgui-godot.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ using godot::InputEvent;
using godot::JoyButton;
using godot::Key;
using godot::Object;
using godot::PackedInt32Array;
using godot::Ref;
using godot::Resource;
using godot::RID;
Expand Down Expand Up @@ -77,17 +78,26 @@ inline bool GET_IMGUIGD()

inline static void GetAtlasUVs(AtlasTexture* tex, ImVec2& uv0, ImVec2& uv1)
{
ERR_FAIL_COND(!tex);
Vector2 atlasSize = tex->get_atlas()->get_size();
uv0 = tex->get_region().get_position() / atlasSize;
uv1 = tex->get_region().get_end() / atlasSize;
}
} // namespace detail

inline void AddFont(const Ref<FontFile>& fontFile, int fontSize, bool merge = false)
inline void AddFont(const Ref<FontFile>& fontFile, int fontSize, bool merge = false, ImWchar* glyphRanges = nullptr)
{
ERR_FAIL_COND(!detail::GET_IMGUIGD());
static const StringName sn("AddFont");
detail::ImGuiGD->call(sn, fontSize, merge);
PackedInt32Array gr;
if (glyphRanges)
{
do
{
gr.append(*glyphRanges);
} while (*++glyphRanges != 0);
}
detail::ImGuiGD->call(sn, fontSize, merge, gr);
}

inline void Connect(const Callable& callable)
Expand Down Expand Up @@ -153,6 +163,7 @@ inline void SyncImGuiPtrs()

inline ImTextureID BindTexture(Texture2D* tex)
{
ERR_FAIL_COND_V(!tex, 0);
return reinterpret_cast<ImTextureID>(tex->get_rid().get_id());
}
#endif
Expand Down
4 changes: 2 additions & 2 deletions gdext/src/Context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,9 +267,9 @@ void ResetFonts()
ctx->fonts->Reset();
}

void AddFont(const Ref<FontFile>& fontFile, int fontSize, bool merge)
void AddFont(const Ref<FontFile>& fontFile, int fontSize, bool merge, const ImVector<ImWchar>& glyphRanges)
{
ctx->fonts->Add(fontFile, fontSize, merge);
ctx->fonts->Add(fontFile, fontSize, merge, glyphRanges);
}

void AddFontDefault()
Expand Down
2 changes: 1 addition & 1 deletion gdext/src/Context.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void Render();
void Shutdown();
void Connect(const Callable& callable);
void ResetFonts();
void AddFont(const Ref<FontFile>& fontFile, int fontSize, bool merge = false);
void AddFont(const Ref<FontFile>& fontFile, int fontSize, bool merge = false, const ImVector<ImWchar>& glyphRanges = {});
void AddFontDefault();
void RebuildFontAtlas(float scale = 1.0f);
void SetIniFilename(const String& fn);
Expand Down
35 changes: 19 additions & 16 deletions gdext/src/Fonts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ struct Fonts::Impl
};
std::vector<FontParams> fontConfig;

void AddFontToAtlas(const Ref<FontFile>& font, int fontSize, bool merge, const ImVector<ImWchar>& ranges);
void AddFontToAtlas(const FontParams& fp, float scale);

static ImVector<ImWchar> GetRanges(const Ref<Font>& font)
{
Expand Down Expand Up @@ -76,43 +76,45 @@ struct Fonts::Impl
}
};

void Fonts::Impl::AddFontToAtlas(const Ref<FontFile>& font, int fontSize, bool merge, const ImVector<ImWchar>& ranges)
void Fonts::Impl::AddFontToAtlas(const FontParams& fp, float scale)
{
auto& io = ImGui::GetIO();
int fontSize = fp.fontSize * scale;
ImFontConfig fc;
if (merge)

if (fp.merge)
fc.MergeMode = 1;

if (font.is_null())
if (fp.font.is_null())
{
// default font
fc = {};
fc.SizePixels = fontSize;
fc.OversampleH = 1;
fc.OversampleV = 1;
fc.PixelSnapH = true;
ImGui::GetIO().Fonts->AddFontDefault(&fc);
io.Fonts->AddFontDefault(&fc);
}
else
{
fs::path fontpath = (font->get_path().utf8().get_data());
fs::path fontpath = (fp.font->get_path().utf8().get_data());

// no std::format in Clang 14
std::string fontdesc = fontpath.filename().string() + ", "s + std::to_string(fontSize) + "px";
if (fontdesc.length() > 39)
fontdesc.resize(39);
std::copy(fontdesc.begin(), fontdesc.end(), fc.Name);
fc.Name[fontdesc.length()] = '\0';

int64_t len = font->get_data().size();
int64_t len = fp.font->get_data().size();
// let ImGui manage this memory
void* p = ImGui::MemAlloc(len);
memcpy(p, font->get_data().ptr(), len);
ImGui::GetIO().Fonts->AddFontFromMemoryTTF(p, len, fontSize, &fc, ranges.Data);
memcpy(p, fp.font->get_data().ptr(), len);
io.Fonts->AddFontFromMemoryTTF(p, len, fontSize, &fc, fp.ranges.Data);
}

if (merge)
{
ImGui::GetIO().Fonts->Build();
}
if (fp.merge)
io.Fonts->Build();
}

Fonts::Fonts() : impl(std::make_unique<Impl>())
Expand All @@ -131,9 +133,10 @@ void Fonts::Reset()
impl->fontConfig.clear();
}

void Fonts::Add(Ref<FontFile> fontData, int fontSize, bool merge)
void Fonts::Add(Ref<FontFile> fontData, int fontSize, bool merge, const ImVector<ImWchar>& glyphRanges)
{
impl->fontConfig.push_back({fontData, fontSize, merge, Impl::GetRanges(fontData)});
impl->fontConfig.push_back(
{fontData, fontSize, merge, glyphRanges.size() > 0 ? glyphRanges : Impl::GetRanges(fontData)});
}

void Fonts::RebuildFontAtlas(float scale)
Expand All @@ -156,7 +159,7 @@ void Fonts::RebuildFontAtlas(float scale)

for (const auto& fp : impl->fontConfig)
{
impl->AddFontToAtlas(fp.font, fp.fontSize * scale, fp.merge, fp.ranges);
impl->AddFontToAtlas(fp, scale);
}

uint8_t* pixelData;
Expand Down
4 changes: 2 additions & 2 deletions gdext/src/Fonts.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once
#include <memory>

#include <imgui.h>
#include <godot_cpp/classes/font_file.hpp>
using namespace godot;

Expand All @@ -13,7 +13,7 @@ class Fonts
~Fonts();

void Reset();
void Add(Ref<FontFile> fontData, int fontSize, bool merge = false);
void Add(Ref<FontFile> fontData, int fontSize, bool merge = false, const ImVector<ImWchar>& glyphRanges = {});
void RebuildFontAtlas(float scale);

private:
Expand Down
Loading

0 comments on commit 47f68a0

Please sign in to comment.