From 5aa76b11f1c85f875405fc193b87fd51403072e8 Mon Sep 17 00:00:00 2001 From: Wutipong Wongsakuldej Date: Mon, 22 Jan 2024 04:58:21 +0700 Subject: [PATCH 1/5] refactor textdirection. --- font.cpp | 44 +++++++++++++++++++--------------------- font.hpp | 14 +++++-------- main_scene.cpp | 55 +++++++++++++++++++++++--------------------------- main_scene.hpp | 21 +++++-------------- 4 files changed, 56 insertions(+), 78 deletions(-) diff --git a/font.cpp b/font.cpp index d10cc21..e9aad9c 100644 --- a/font.cpp +++ b/font.cpp @@ -41,7 +41,7 @@ bool Font::Init() { void Font::CleanUp() { FT_Done_FreeType(library); } -Font::Font() : textRenderer(TextRenderNoShape){}; +Font::Font(){}; Font &Font::operator=(const Font &f) { data = f.data; @@ -87,8 +87,6 @@ static std::string ConvertFromFontString(const char *str, const int &length) { bool Font::Initialize() { family = ""; subFamily = ""; - textRenderer = TextRenderNoShape; - textRendererEnum = TextRenderEnum::NoShape; auto error = FT_New_Memory_Face( library, reinterpret_cast(data.data()), data.size(), 0, @@ -215,31 +213,31 @@ Glyph &Font::GetGlyphFromChar(SDL_Renderer *renderer, const char16_t &ch) { return Font::GetGlyph(renderer, index); } -void Font::SetTextRenderer(const TextRenderEnum &t) { - textRendererEnum = t; - switch (textRendererEnum) { - case TextRenderEnum::NoShape: - textRenderer = TextRenderNoShape; - break; - case TextRenderEnum::LeftToRight: - textRenderer = TextRenderLeftToRight; - break; - case TextRenderEnum::RightToLeft: - textRenderer = TextRenderRightToLeft; - break; - case TextRenderEnum::TopToBottom: - textRenderer = TextRenderTopToBottom; - break; - } -} - void Font::RenderText(SDL_Renderer *renderer, Context &ctx, - const std::string &str, const SDL_Color &color, + const std::string &str, const bool &isShaping, + const TextDirection &direction, const SDL_Color &color, const std::string &language, const hb_script_t &script) { if (!IsValid()) return; - textRenderer(renderer, ctx, *this, str, color, language, script); + if (!isShaping) { + TextRenderNoShape(renderer, ctx, *this, str, color, language, script); + return; + } + + switch (direction) { + case TextDirection::LeftToRight: + TextRenderLeftToRight(renderer, ctx, *this, str, color, language, script); + return; + + case TextDirection::RightToLeft: + TextRenderRightToLeft(renderer, ctx, *this, str, color, language, script); + return; + + case TextDirection::TopToBottom: + TextRenderTopToBottom(renderer, ctx, *this, str, color, language, script); + return; + } } bool Font::IsVariableFont() const { diff --git a/font.hpp b/font.hpp index 8bc8a7c..9b4e200 100644 --- a/font.hpp +++ b/font.hpp @@ -15,8 +15,7 @@ #include #include -enum class TextRenderEnum { - NoShape, +enum class TextDirection { LeftToRight, RightToLeft, TopToBottom, @@ -37,10 +36,10 @@ struct Glyph { int bearing; }; -inline float FTPosToFloat(const FT_Pos &value) { +constexpr inline float FTPosToFloat(const FT_Pos &value) { return static_cast(value) / 64.0f; } -inline float HBPosToFloat(const hb_position_t &value) { +constexpr inline float HBPosToFloat(const hb_position_t &value) { return static_cast(value) / 64.0f; } @@ -79,6 +78,7 @@ class Font { std::string GetFamilyName() const { return family; } std::string GetSubFamilyName() const { return subFamily; } + bool IsValid() const { return face != nullptr; } bool IsVariableFont() const; @@ -93,9 +93,8 @@ class Font { hb_font_t *HbFont() const { return hb_font; } - void SetTextRenderer(const TextRenderEnum &t); - void RenderText(SDL_Renderer *renderer, Context &ctx, const std::string &str, + const bool& isShaping, const TextDirection& direction, const SDL_Color &color, const std::string &language, const hb_script_t &script); @@ -129,9 +128,6 @@ class Font { std::string family; std::string subFamily; - TextRenderFunction textRenderer; - TextRenderEnum textRendererEnum{TextRenderEnum::NoShape}; - magic_enum::containers::array> axisInfo{}; }; diff --git a/main_scene.cpp b/main_scene.cpp index 511b2e3..97e7cca 100644 --- a/main_scene.cpp +++ b/main_scene.cpp @@ -49,23 +49,6 @@ void MainScene::Tick(SDL_Renderer *renderer, Context &ctx) { backgroundColor.b, backgroundColor.a); SDL_RenderClear(renderer); - auto textRender = TextRenderEnum::NoShape; - if (isShape) { - switch (directions[selectedDirection].direction) { - case HB_DIRECTION_LTR: - textRender = TextRenderEnum::LeftToRight; - break; - case HB_DIRECTION_TTB: - textRender = TextRenderEnum::TopToBottom; - break; - case HB_DIRECTION_RTL: - textRender = TextRenderEnum::RightToLeft; - break; - } - } - - font.SetTextRenderer(textRender); - font.SetFontSize(fontSize); SDL_Color sdlColor = { @@ -75,8 +58,8 @@ void MainScene::Tick(SDL_Renderer *renderer, Context &ctx) { 0xFF, }; - font.RenderText(renderer, ctx, std::string(buffer.data()), sdlColor, - languages[selectedLanguage].code, + font.RenderText(renderer, ctx, std::string(buffer.data()), isShape, + selectedDirection, sdlColor, languages[selectedLanguage].code, scripts[selectedScript].script); } @@ -165,7 +148,8 @@ void MainScene::DoUI(Context &context) { bool axisChanged = false; - static constexpr magic_enum::containers::array + static constexpr magic_enum::containers::array axisLabel = {{{ "Italic##axis", "Optical size##axis", @@ -219,12 +203,22 @@ void MainScene::DoUI(Context &context) { } ImGui::EndCombo(); } - if (ImGui::BeginCombo("Direction", directions[selectedDirection].name)) { - for (int i = 0; i < directions.size(); i++) { - if (ImGui::Selectable(directions[i].name, i == selectedDirection)) { - selectedDirection = i; + + constexpr magic_enum::containers::array + directionLabels{ + "Left to right", + "Right to left", + "Top to bottom", + }; + + if (ImGui::BeginCombo("Direction", directionLabels[selectedDirection])) { + magic_enum::enum_for_each([this, &directionLabels]( + const auto &dir) { + if (ImGui::Selectable(directionLabels[dir], dir == selectedDirection)) { + selectedDirection = dir; } - } + }); + ImGui::EndCombo(); } } @@ -305,12 +299,13 @@ void MainScene::DoUI(Context &context) { font = newFont; axisLimits = font.GetAxisInfos(); - magic_enum::enum_for_each([this](const VariationAxis &axis) { - if (!axisLimits[axis].has_value()) - return; + magic_enum::enum_for_each( + [this](const VariationAxis &axis) { + if (!axisLimits[axis].has_value()) + return; - axisValue[axis] = axisLimits[axis]->defaultValue; - }); + axisValue[axis] = axisLimits[axis]->defaultValue; + }); selectedFontIndex = newSelected; } diff --git a/main_scene.hpp b/main_scene.hpp index 8a767ac..1da8746 100644 --- a/main_scene.hpp +++ b/main_scene.hpp @@ -1,17 +1,16 @@ #pragma once +#include "font.hpp" +#include "imgui.h" #include "scene.hpp" #include #include #include +#include #include -#include "imgui.h" - #include "imgui-filebrowser/imfilebrowser.h" -#include "font.hpp" - class MainScene : public Scene { public: virtual bool Init(Context &context) override; @@ -66,17 +65,6 @@ class MainScene : public Scene { ScriptPair{"Arabic", HB_SCRIPT_ARABIC}, }; - struct DirectionPair { - const char* name; - const hb_direction_t direction; - }; - - static constexpr std::array directions = { - DirectionPair{"Left to Right", HB_DIRECTION_LTR,}, - DirectionPair{ "Right To Left",HB_DIRECTION_RTL, }, - DirectionPair{"Top to Bottom", HB_DIRECTION_TTB,}, - }; - struct LanguagePair { const char* name; const char* code; @@ -94,9 +82,10 @@ class MainScene : public Scene { // clang-format on int selectedScript = 0; - int selectedDirection = 0; int selectedLanguage = 0; + TextDirection selectedDirection; + magic_enum::containers::array axisValue; magic_enum::containers::array> axisLimits; From cb2d9f78a874c0544430a15da74c581f5c9503ea Mon Sep 17 00:00:00 2001 From: Wutipong Wongsakuldej Date: Mon, 22 Jan 2024 05:12:59 +0700 Subject: [PATCH 2/5] clean up some weirdness. --- main_scene.cpp | 37 ++++++++++++------------- main_scene.hpp | 75 +++++++++++++++++++++++++++++++------------------- 2 files changed, 64 insertions(+), 48 deletions(-) diff --git a/main_scene.cpp b/main_scene.cpp index 97e7cca..19f4864 100644 --- a/main_scene.cpp +++ b/main_scene.cpp @@ -58,7 +58,7 @@ void MainScene::Tick(SDL_Renderer *renderer, Context &ctx) { 0xFF, }; - font.RenderText(renderer, ctx, std::string(buffer.data()), isShape, + font.RenderText(renderer, ctx, std::string(buffer.data()), isShaping, selectedDirection, sdlColor, languages[selectedLanguage].code, scripts[selectedScript].script); } @@ -148,20 +148,16 @@ void MainScene::DoUI(Context &context) { bool axisChanged = false; - static constexpr magic_enum::containers::array - axisLabel = {{{ - "Italic##axis", - "Optical size##axis", - "Slant##axis", - "Weight##axis", - "Width##axis", - }}}; + constexpr magic_enum::containers::array + axisLabel = { + "Italic##axis", "Optical size##axis", "Slant##axis", + "Weight##axis", "Width##axis", + }; magic_enum::enum_for_each( - [this, &axisChanged](const VariationAxis &axis) { + [this, &axisChanged, &axisLabel](const VariationAxis &axis) { if (axisLimits[axis].has_value()) { - auto [min, max, _] = *axisLimits[axis]; + [[maybe_unused]] auto [min, max, _] = *axisLimits[axis]; axisChanged |= ImGui::DragFloat(axisLabel[axis], &axisValue[axis], 1.0f, min, max); } else { @@ -183,9 +179,9 @@ void MainScene::DoUI(Context &context) { ImGui::LabelText("Line height", "%.3f", font.LineHeight()); ImGui::SeparatorText("OpenType text shaping"); - ImGui::Checkbox("Enable##Shape Text", &isShape); + ImGui::Checkbox("Enable##Shape Text", &isShaping); - ImGui::BeginDisabled(!isShape); + ImGui::BeginDisabled(!isShaping); if (ImGui::BeginCombo("Language", languages[selectedLanguage].name)) { for (size_t i = 0; i < languages.size(); i++) { if (ImGui::Selectable(languages[i].name, i == selectedLanguage)) { @@ -212,12 +208,13 @@ void MainScene::DoUI(Context &context) { }; if (ImGui::BeginCombo("Direction", directionLabels[selectedDirection])) { - magic_enum::enum_for_each([this, &directionLabels]( - const auto &dir) { - if (ImGui::Selectable(directionLabels[dir], dir == selectedDirection)) { - selectedDirection = dir; - } - }); + magic_enum::enum_for_each( + [this, &directionLabels](const auto &dir) { + if (ImGui::Selectable(directionLabels[dir], + dir == selectedDirection)) { + selectedDirection = dir; + } + }); ImGui::EndCombo(); } diff --git a/main_scene.hpp b/main_scene.hpp index 1da8746..c8fb2c8 100644 --- a/main_scene.hpp +++ b/main_scene.hpp @@ -36,50 +36,69 @@ class MainScene : public Scene { std::array buffer = {0}; float color[3]; int fontSize = 64; - bool isShape = false; + bool isShaping = false; int selectedFontIndex = -1; std::vector fontPaths; - std::vector fontData; - - ImGui::FileBrowser dirChooser{ - ImGuiFileBrowserFlags_SelectDirectory, - }; + ImGui::FileBrowser dirChooser{ImGuiFileBrowserFlags_SelectDirectory}; Font font{}; - // clang-format off struct ScriptPair { - const char* name; + const char *name; const hb_script_t script; }; - static constexpr std::array scripts = { - ScriptPair{"Common", HB_SCRIPT_COMMON}, - ScriptPair{"Thai", HB_SCRIPT_THAI}, - ScriptPair{"Hiragana", HB_SCRIPT_HIRAGANA}, - ScriptPair{"Katakana", HB_SCRIPT_KATAKANA}, - ScriptPair{"Han", HB_SCRIPT_HAN}, - ScriptPair{"Hangul", HB_SCRIPT_HANGUL}, - ScriptPair{"Arabic", HB_SCRIPT_ARABIC}, + static constexpr std::array scripts{ + ScriptPair{"Common", HB_SCRIPT_COMMON}, + ScriptPair{"Thai", HB_SCRIPT_THAI}, + ScriptPair{"Hiragana", HB_SCRIPT_HIRAGANA}, + ScriptPair{"Katakana", HB_SCRIPT_KATAKANA}, + ScriptPair{"Han", HB_SCRIPT_HAN}, + ScriptPair{"Hangul", HB_SCRIPT_HANGUL}, + ScriptPair{"Arabic", HB_SCRIPT_ARABIC}, }; struct LanguagePair { - const char* name; - const char* code; + const char *name; + const char *code; }; - static constexpr std::array languages = { - LanguagePair{ "None", "", }, - LanguagePair{ "English US", "en-US", }, - LanguagePair{ "Thai Thailand", "th-TH", }, - LanguagePair{ "Japanese Japan", "ja-JP", }, - LanguagePair{ "Korean Republic of Korea","ko-KR", }, - LanguagePair{ "Chinese China", "zh-CN", }, - LanguagePair{ "Chinese Taiwan", "zh-TW", }, - LanguagePair{ "Arabic Saudi Arabia", "ar-SA", }, + + static constexpr std::array languages{ + LanguagePair{ + "None", + "", + }, + LanguagePair{ + "English US", + "en-US", + }, + LanguagePair{ + "Thai Thailand", + "th-TH", + }, + LanguagePair{ + "Japanese Japan", + "ja-JP", + }, + LanguagePair{ + "Korean Republic of Korea", + "ko-KR", + }, + LanguagePair{ + "Chinese China", + "zh-CN", + }, + LanguagePair{ + "Chinese Taiwan", + "zh-TW", + }, + LanguagePair{ + "Arabic Saudi Arabia", + "ar-SA", + }, }; - // clang-format on int selectedScript = 0; int selectedLanguage = 0; From dc18efed5677fbebfe1f89823002efa898d482fe Mon Sep 17 00:00:00 2001 From: Wutipong Wongsakuldej Date: Mon, 22 Jan 2024 22:01:36 +0700 Subject: [PATCH 3/5] add render viewport --- context.cpp | 6 +++--- main.cpp | 1 + main_scene.cpp | 24 +++++++++++++++++++----- main_scene.hpp | 4 ++-- 4 files changed, 25 insertions(+), 10 deletions(-) diff --git a/context.cpp b/context.cpp index e86e9fe..eb6a480 100644 --- a/context.cpp +++ b/context.cpp @@ -30,13 +30,13 @@ void LoadContext(Context &ctx, const std::filesystem::path &path) { json js; - // If there's something wrong with reading file, log an error and return. + // If there's something wrong with reading file, log an error and return. try { std::string str; str = LoadFile(path); js = json::parse(str); - } catch (const json::exception& e) { + } catch (const json::exception &e) { spdlog::error("Error reading context file: {}", e.what()); return; } @@ -47,7 +47,7 @@ void LoadContext(Context &ctx, const std::filesystem::path &path) { c.windowBound.w = js["window_bound"]["width"]; c.windowBound.h = js["window_bound"]["height"]; c.fontPath = js["font_path"]; - } catch (const json::exception& e) { + } catch (const json::exception &e) { spdlog::error("Error reading context file value: {}", e.what()); } diff --git a/main.cpp b/main.cpp index ae67a5c..ff1430a 100644 --- a/main.cpp +++ b/main.cpp @@ -82,6 +82,7 @@ int main(int argc, char **argv) { if (event.type == SDL_QUIT) break; } + ctx.windowBound = {0}; SDL_GetWindowSize(window, &ctx.windowBound.w, &ctx.windowBound.h); ImGui_ImplSDL2_NewFrame(window); diff --git a/main_scene.cpp b/main_scene.cpp index 19f4864..8bce800 100644 --- a/main_scene.cpp +++ b/main_scene.cpp @@ -28,6 +28,9 @@ constexpr auto f4DebugDescendColor = SDLColorToImVec4(debugDescendColor); constexpr auto f4DebugBaselineColor = SDLColorToImVec4(debugBaselineColor); constexpr auto f4DebugCaretColor = SDLColorToImVec4(debugCaretColor); +constexpr int toolbarWidth = 400; +constexpr int padding = 30; + } // namespace bool MainScene::Init(Context &context) { @@ -44,6 +47,14 @@ bool MainScene::Init(Context &context) { } void MainScene::Tick(SDL_Renderer *renderer, Context &ctx) { + SDL_Rect viewport = ctx.windowBound; + + viewport.x += padding; + viewport.y += padding; + viewport.w -= (toolbarWidth + padding *2); + viewport.h -= 2 * padding; + + SDL_RenderSetViewport(renderer, &viewport); SDL_SetRenderDrawColor(renderer, backgroundColor.r, backgroundColor.g, backgroundColor.b, backgroundColor.a); @@ -52,15 +63,17 @@ void MainScene::Tick(SDL_Renderer *renderer, Context &ctx) { font.SetFontSize(fontSize); SDL_Color sdlColor = { - static_cast(color[0] * 255.0f), - static_cast(color[1] * 255.0f), - static_cast(color[2] * 255.0f), + static_cast(foregroundColor[0] * 255.0f), + static_cast(foregroundColor[1] * 255.0f), + static_cast(foregroundColor[2] * 255.0f), 0xFF, }; font.RenderText(renderer, ctx, std::string(buffer.data()), isShaping, selectedDirection, sdlColor, languages[selectedLanguage].code, scripts[selectedScript].script); + + SDL_RenderGetViewport(renderer, nullptr); } void MainScene::Cleanup(Context &context) { Font::CleanUp(); } @@ -112,7 +125,8 @@ void MainScene::DoUI(Context &context) { } ImGui::End(); - if (ImGui::BeginViewportSideBar("toolbar", nullptr, ImGuiDir_Right, 400.0f, + if (ImGui::BeginViewportSideBar("toolbar", nullptr, ImGuiDir_Right, + toolbarWidth, ImGuiWindowFlags_NoSavedSettings)) { if (ImGui::CollapsingHeader("Font", ImGuiTreeNodeFlags_DefaultOpen)) { @@ -223,7 +237,7 @@ void MainScene::DoUI(Context &context) { ImGui::SeparatorText("Draw color"); - ImGui::ColorPicker3("Foreground##color", color, + ImGui::ColorPicker3("Foreground##color", foregroundColor, ImGuiColorEditFlags_InputRGB); } ImGui::End(); diff --git a/main_scene.hpp b/main_scene.hpp index c8fb2c8..e128753 100644 --- a/main_scene.hpp +++ b/main_scene.hpp @@ -34,7 +34,7 @@ class MainScene : public Scene { "Aenean efficitur felis sed metus mollis varius."; std::array buffer = {0}; - float color[3]; + float foregroundColor[3]; int fontSize = 64; bool isShaping = false; @@ -103,7 +103,7 @@ class MainScene : public Scene { int selectedScript = 0; int selectedLanguage = 0; - TextDirection selectedDirection; + TextDirection selectedDirection {TextDirection::LeftToRight}; magic_enum::containers::array axisValue; magic_enum::containers::array> From ff50973b75ddd178ac485923dae5a57ddcf68d5e Mon Sep 17 00:00:00 2001 From: Wutipong Wongsakuldej Date: Mon, 22 Jan 2024 22:41:32 +0700 Subject: [PATCH 4/5] move some more function out of the font class. --- colors.hpp | 26 ++++++++++++++++++++ font.cpp | 27 --------------------- font.hpp | 5 ---- main_scene.cpp | 60 +++++++++++++++++++++++++---------------------- main_scene.hpp | 6 +++-- text_renderer.cpp | 3 +-- text_renderer.hpp | 20 +++++++++------- 7 files changed, 74 insertions(+), 73 deletions(-) diff --git a/colors.hpp b/colors.hpp index 05930f2..9b933d0 100644 --- a/colors.hpp +++ b/colors.hpp @@ -2,6 +2,7 @@ #define COLORS_HPP #include +#include constexpr SDL_Color debugGlyphBoundColor{0xFF, 0xFF, 0x80, 0xFF}; constexpr SDL_Color debugBaselineColor{0xFF, 0x00, 0x00, 0xFF}; @@ -10,4 +11,29 @@ constexpr SDL_Color debugAscendColor{0x40, 0x40, 0xFF, 0x80}; constexpr SDL_Color debugDescendColor{0x40, 0xFF, 0x40, 0x80}; constexpr SDL_Color backgroundColor{0x80, 0x80, 0x80, 0xFF}; +constexpr ImVec4 SDLColorToImVec4(const SDL_Color &color) { + ImVec4 output{ + static_cast(color.r) / 255.0f, + static_cast(color.g) / 255.0f, + static_cast(color.b) / 255.0f, + static_cast(color.a) / 255.0f, + }; + + return output; +} + +constexpr auto f4DebugGlyphBoundColor = SDLColorToImVec4(debugGlyphBoundColor); +constexpr auto f4DebugAscendColor = SDLColorToImVec4(debugAscendColor); +constexpr auto f4DebugDescendColor = SDLColorToImVec4(debugDescendColor); +constexpr auto f4DebugBaselineColor = SDLColorToImVec4(debugBaselineColor); +constexpr auto f4DebugCaretColor = SDLColorToImVec4(debugCaretColor); + +constexpr SDL_Color Float4ToSDLColor(const float& r, const float& g, const float &b, const float &a = 1.0f ){ + return { + static_cast(r * 255.0f), + static_cast(g * 255.0f), + static_cast(b * 255.0f), + static_cast(a * 255.0f), + }; +} #endif \ No newline at end of file diff --git a/font.cpp b/font.cpp index e9aad9c..27aa73d 100644 --- a/font.cpp +++ b/font.cpp @@ -213,33 +213,6 @@ Glyph &Font::GetGlyphFromChar(SDL_Renderer *renderer, const char16_t &ch) { return Font::GetGlyph(renderer, index); } -void Font::RenderText(SDL_Renderer *renderer, Context &ctx, - const std::string &str, const bool &isShaping, - const TextDirection &direction, const SDL_Color &color, - const std::string &language, const hb_script_t &script) { - if (!IsValid()) - return; - - if (!isShaping) { - TextRenderNoShape(renderer, ctx, *this, str, color, language, script); - return; - } - - switch (direction) { - case TextDirection::LeftToRight: - TextRenderLeftToRight(renderer, ctx, *this, str, color, language, script); - return; - - case TextDirection::RightToLeft: - TextRenderRightToLeft(renderer, ctx, *this, str, color, language, script); - return; - - case TextDirection::TopToBottom: - TextRenderTopToBottom(renderer, ctx, *this, str, color, language, script); - return; - } -} - bool Font::IsVariableFont() const { if (!hb_font) return false; diff --git a/font.hpp b/font.hpp index 9b4e200..836eff4 100644 --- a/font.hpp +++ b/font.hpp @@ -93,11 +93,6 @@ class Font { hb_font_t *HbFont() const { return hb_font; } - void RenderText(SDL_Renderer *renderer, Context &ctx, const std::string &str, - const bool& isShaping, const TextDirection& direction, - const SDL_Color &color, const std::string &language, - const hb_script_t &script); - magic_enum::containers::array> GetAxisInfos() const; diff --git a/main_scene.cpp b/main_scene.cpp index 8bce800..214ed51 100644 --- a/main_scene.cpp +++ b/main_scene.cpp @@ -11,23 +11,6 @@ #include namespace { -constexpr ImVec4 SDLColorToImVec4(const SDL_Color &color) { - ImVec4 output{ - static_cast(color.r) / 255.0f, - static_cast(color.g) / 255.0f, - static_cast(color.b) / 255.0f, - static_cast(color.a) / 255.0f, - }; - - return output; -} - -constexpr auto f4DebugGlyphBoundColor = SDLColorToImVec4(debugGlyphBoundColor); -constexpr auto f4DebugAscendColor = SDLColorToImVec4(debugAscendColor); -constexpr auto f4DebugDescendColor = SDLColorToImVec4(debugDescendColor); -constexpr auto f4DebugBaselineColor = SDLColorToImVec4(debugBaselineColor); -constexpr auto f4DebugCaretColor = SDLColorToImVec4(debugCaretColor); - constexpr int toolbarWidth = 400; constexpr int padding = 30; @@ -51,7 +34,7 @@ void MainScene::Tick(SDL_Renderer *renderer, Context &ctx) { viewport.x += padding; viewport.y += padding; - viewport.w -= (toolbarWidth + padding *2); + viewport.w -= (toolbarWidth + padding * 2); viewport.h -= 2 * padding; SDL_RenderSetViewport(renderer, &viewport); @@ -62,16 +45,7 @@ void MainScene::Tick(SDL_Renderer *renderer, Context &ctx) { font.SetFontSize(fontSize); - SDL_Color sdlColor = { - static_cast(foregroundColor[0] * 255.0f), - static_cast(foregroundColor[1] * 255.0f), - static_cast(foregroundColor[2] * 255.0f), - 0xFF, - }; - - font.RenderText(renderer, ctx, std::string(buffer.data()), isShaping, - selectedDirection, sdlColor, languages[selectedLanguage].code, - scripts[selectedScript].script); + RenderText(renderer, ctx); SDL_RenderGetViewport(renderer, nullptr); } @@ -368,3 +342,33 @@ MainScene::ListFontFiles(const std::filesystem::path &path) { return output; } + +void MainScene::RenderText(SDL_Renderer *renderer, Context &ctx) { + if (!font.IsValid()) + return; + + std::string str(buffer.data()); + auto language = languages[selectedLanguage].code; + auto script = scripts[selectedScript].script; + + SDL_Color sdlColor = Float4ToSDLColor(foregroundColor[0], foregroundColor[1], foregroundColor[2]); + + if (!isShaping) { + TextRenderNoShape(renderer, ctx, font, str, sdlColor); + return; + } + + switch (selectedDirection) { + case TextDirection::LeftToRight: + TextRenderLeftToRight(renderer, ctx, font, str, sdlColor, language, script); + return; + + case TextDirection::RightToLeft: + TextRenderRightToLeft(renderer, ctx, font, str, sdlColor, language, script); + return; + + case TextDirection::TopToBottom: + TextRenderTopToBottom(renderer, ctx, font, str, sdlColor, language, script); + return; + } +} \ No newline at end of file diff --git a/main_scene.hpp b/main_scene.hpp index e128753..586d084 100644 --- a/main_scene.hpp +++ b/main_scene.hpp @@ -18,12 +18,14 @@ class MainScene : public Scene { virtual void Cleanup(Context &context) override; virtual void DoUI(Context &context) override; +private: void OnDirectorySelected(Context &context, const std::filesystem::path &path); static std::vector ListFontFiles(const std::filesystem::path &path); -private: + void RenderText(SDL_Renderer *renderer, Context &ctx); + static const inline std::string exampleText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non \n" "turpis justo. Etiam luctus vulputate ante ac congue. Nunc vitae \n" @@ -103,7 +105,7 @@ class MainScene : public Scene { int selectedScript = 0; int selectedLanguage = 0; - TextDirection selectedDirection {TextDirection::LeftToRight}; + TextDirection selectedDirection{TextDirection::LeftToRight}; magic_enum::containers::array axisValue; magic_enum::containers::array> diff --git a/text_renderer.cpp b/text_renderer.cpp index 153ca45..43167ca 100644 --- a/text_renderer.cpp +++ b/text_renderer.cpp @@ -90,8 +90,7 @@ void DrawVerticalLineDebug(SDL_Renderer *renderer, Context &ctx, } // namespace void TextRenderNoShape(SDL_Renderer *renderer, Context &ctx, Font &font, - const std::string &str, const SDL_Color &color, - const std::string &language, const hb_script_t &script) { + const std::string &str, const SDL_Color &color) { if (!font.IsValid()) return; diff --git a/text_renderer.hpp b/text_renderer.hpp index 142016d..e21b29e 100644 --- a/text_renderer.hpp +++ b/text_renderer.hpp @@ -6,18 +6,20 @@ #include #include -void TextRenderNoShape(SDL_Renderer *renderer, Context &ctx, Font &font, const std::string &str, - const SDL_Color &color, const std::string &language, - const hb_script_t &script); +void TextRenderNoShape(SDL_Renderer *renderer, Context &ctx, Font &font, + const std::string &str, const SDL_Color &color); -void TextRenderLeftToRight(SDL_Renderer *renderer, Context &ctx, Font &font, const std::string &str, - const SDL_Color &color, const std::string &language, +void TextRenderLeftToRight(SDL_Renderer *renderer, Context &ctx, Font &font, + const std::string &str, const SDL_Color &color, + const std::string &language, const hb_script_t &script); -void TextRenderRightToLeft(SDL_Renderer *renderer, Context &ctx, Font &font, const std::string &str, - const SDL_Color &color, const std::string &language, +void TextRenderRightToLeft(SDL_Renderer *renderer, Context &ctx, Font &font, + const std::string &str, const SDL_Color &color, + const std::string &language, const hb_script_t &script); -void TextRenderTopToBottom(SDL_Renderer *renderer, Context &ctx, Font &font, const std::string &str, - const SDL_Color &color, const std::string &language, +void TextRenderTopToBottom(SDL_Renderer *renderer, Context &ctx, Font &font, + const std::string &str, const SDL_Color &color, + const std::string &language, const hb_script_t &script); From 8c73b22c749dcbfbcf64e848526f2f54a812b7dd Mon Sep 17 00:00:00 2001 From: Wutipong Wongsakuldej Date: Mon, 22 Jan 2024 23:17:59 +0700 Subject: [PATCH 5/5] rearranging around fonts --- font.cpp | 85 +++++++++++++++++++++++------------------------ font.hpp | 27 ++++----------- main_scene.hpp | 3 +- text_renderer.hpp | 8 ++++- 4 files changed, 58 insertions(+), 65 deletions(-) diff --git a/font.cpp b/font.cpp index 27aa73d..0d199d3 100644 --- a/font.cpp +++ b/font.cpp @@ -1,18 +1,16 @@ #include "font.hpp" +#include +#include +#include #include -#include "io_util.hpp" -#include "text_renderer.hpp" -#include "texture.hpp" - #include FT_SFNT_NAMES_H #include FT_BITMAP_H #include FT_MULTIPLE_MASTERS_H - -#include -#include -#include +#include "io_util.hpp" +#include "text_renderer.hpp" +#include "texture.hpp" namespace { @@ -53,12 +51,12 @@ Font &Font::operator=(const Font &f) { Font::Font(const Font &f) : data(f.data) { Initialize(); } Font::~Font() { - hb_font_destroy(hb_font); - hb_font = nullptr; + hb_font_destroy(hbFont); + hbFont = nullptr; Invalidate(); - FT_Done_Face(face); + FT_Done_Face(ftFace); } bool Font::LoadFile(const std::string &path) { @@ -90,23 +88,23 @@ bool Font::Initialize() { auto error = FT_New_Memory_Face( library, reinterpret_cast(data.data()), data.size(), 0, - &face); + &ftFace); if (error) { data.clear(); return false; } - hb_font = hb_ft_font_create_referenced(face); + hbFont = hb_ft_font_create_referenced(ftFace); Invalidate(); fontSize = -1; - family = face->family_name; - subFamily = face->style_name; + family = ftFace->family_name; + subFamily = ftFace->style_name; if (IsVariableFont()) { - auto hb_face = hb_font_get_face(hb_font); + auto hb_face = hb_font_get_face(hbFont); auto count = hb_ot_var_get_axis_count(hb_face); std::vector hbAxisInfo; @@ -152,45 +150,45 @@ void Font::SetFontSize(const int &size) { fontSize = size; Invalidate(); - auto error = FT_Set_Pixel_Sizes(face, 0, size); - hb_ft_font_changed(hb_font); + auto error = FT_Set_Pixel_Sizes(ftFace, 0, size); + hb_ft_font_changed(hbFont); - ascend = FTPosToFloat(face->size->metrics.ascender); - descend = FTPosToFloat(face->size->metrics.descender); - height = FTPosToFloat(face->size->metrics.height); + ascend = FTPosToFloat(ftFace->size->metrics.ascender); + descend = FTPosToFloat(ftFace->size->metrics.descender); + height = FTPosToFloat(ftFace->size->metrics.height); linegap = height + descend - ascend; } Glyph Font::CreateGlyph(SDL_Renderer *renderer, const int &index) { - int bearing = 0; - int advance; + FT_Load_Glyph(ftFace, index, FT_LOAD_RENDER); - FT_Load_Glyph(face, index, FT_LOAD_RENDER); - - advance = static_cast(FTPosToFloat(face->glyph->advance.x)); - - auto width = face->glyph->bitmap.width; - auto height = face->glyph->bitmap.rows; + const auto advance = static_cast(FTPosToFloat(ftFace->glyph->advance.x)); + const auto width = ftFace->glyph->bitmap.width; + const auto height = ftFace->glyph->bitmap.rows; FT_Bitmap bitmap; FT_Bitmap_Init(&bitmap); - FT_Bitmap_Convert(library, &face->glyph->bitmap, &bitmap, 1); + FT_Bitmap_Convert(library, &ftFace->glyph->bitmap, &bitmap, 1); auto texture = LoadTextureFromBitmap(renderer, bitmap); FT_Bitmap_Done(library, &bitmap); - auto x = face->glyph->bitmap_left; - auto y = face->glyph->bitmap_top - height; + const auto x = static_cast(ftFace->glyph->bitmap_left); + const auto y = static_cast(ftFace->glyph->bitmap_top - height); - SDL_Rect bound{x, static_cast(y), static_cast(width), - static_cast(height)}; + SDL_Rect bound{ + x, + y, + static_cast(width), + static_cast(height), + }; - return {texture, bound, advance, bearing}; + return {texture, bound, advance}; } Glyph Font::CreateGlyphFromChar(SDL_Renderer *renderer, const char16_t &ch) { - auto index = FT_Get_Char_Index(face, ch); + auto index = FT_Get_Char_Index(ftFace, ch); return CreateGlyph(renderer, index); } @@ -208,16 +206,17 @@ Glyph &Font::GetGlyph(SDL_Renderer *renderer, const int &index) { } Glyph &Font::GetGlyphFromChar(SDL_Renderer *renderer, const char16_t &ch) { - const auto index = FT_Get_Char_Index(face, ch); + const auto index = FT_Get_Char_Index(ftFace, ch); return Font::GetGlyph(renderer, index); } bool Font::IsVariableFont() const { - if (!hb_font) + if (!IsValid()) return false; - auto hb_face = hb_font_get_face(hb_font); + auto hb_face = hb_font_get_face(hbFont); + return hb_ot_var_has_data(hb_face); } @@ -240,7 +239,7 @@ void Font::SetVariationValues( std::vector variations; FT_MM_Var *amaster; - FT_Get_MM_Var(face, &amaster); + FT_Get_MM_Var(ftFace, &amaster); magic_enum::enum_for_each( [&limits, &variations, &values](const VariationAxis &axis) { @@ -252,7 +251,7 @@ void Font::SetVariationValues( } }); - hb_font_set_variations(hb_font, variations.data(), variations.size()); + hb_font_set_variations(hbFont, variations.data(), variations.size()); std::vector coords; for (int i = 0; i < amaster->num_axis; i++) { @@ -273,9 +272,9 @@ void Font::SetVariationValues( } } - FT_Set_Var_Design_Coordinates(face, coords.size(), coords.data()); + FT_Set_Var_Design_Coordinates(ftFace, coords.size(), coords.data()); FT_Done_MM_Var(library, amaster); - hb_ft_font_changed(hb_font); + hb_ft_font_changed(hbFont); Invalidate(); } \ No newline at end of file diff --git a/font.hpp b/font.hpp index 836eff4..81dea86 100644 --- a/font.hpp +++ b/font.hpp @@ -15,25 +15,12 @@ #include #include -enum class TextDirection { - LeftToRight, - RightToLeft, - TopToBottom, -}; - class Font; -typedef std::function - TextRenderFunction; - struct Glyph { - SDL_Texture *texture; - SDL_Rect bound; - int advance; - int bearing; + SDL_Texture *texture{nullptr}; + SDL_Rect bound{}; + int advance = 0; }; constexpr inline float FTPosToFloat(const FT_Pos &value) { @@ -79,7 +66,7 @@ class Font { std::string GetFamilyName() const { return family; } std::string GetSubFamilyName() const { return subFamily; } - bool IsValid() const { return face != nullptr; } + bool IsValid() const { return ftFace != nullptr; } bool IsVariableFont() const; @@ -91,7 +78,7 @@ class Font { float LineGap() const { return linegap; } float LineHeight() const { return height; } - hb_font_t *HbFont() const { return hb_font; } + hb_font_t *HbFont() const { return hbFont; } magic_enum::containers::array> GetAxisInfos() const; @@ -108,10 +95,10 @@ class Font { Glyph CreateGlyphFromChar(SDL_Renderer *renderer, const char16_t &ch); std::vector data{}; - FT_Face face{}; + FT_Face ftFace{}; + hb_font_t *hbFont{nullptr}; int fontSize{-1}; - hb_font_t *hb_font{nullptr}; std::map glyphMap; diff --git a/main_scene.hpp b/main_scene.hpp index 586d084..5b259de 100644 --- a/main_scene.hpp +++ b/main_scene.hpp @@ -1,11 +1,12 @@ #pragma once #include "font.hpp" -#include "imgui.h" #include "scene.hpp" +#include "text_renderer.hpp" #include #include #include +#include #include #include diff --git a/text_renderer.hpp b/text_renderer.hpp index e21b29e..fad905f 100644 --- a/text_renderer.hpp +++ b/text_renderer.hpp @@ -1,11 +1,17 @@ #pragma once -#include #include "context.hpp" #include "font.hpp" #include +#include #include +enum class TextDirection { + LeftToRight, + RightToLeft, + TopToBottom, +}; + void TextRenderNoShape(SDL_Renderer *renderer, Context &ctx, Font &font, const std::string &str, const SDL_Color &color);