Skip to content

Commit

Permalink
add axis UI.
Browse files Browse the repository at this point in the history
  • Loading branch information
wutipong committed Jan 21, 2024
1 parent ae8446e commit 3db41f2
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 50 deletions.
45 changes: 26 additions & 19 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,45 +17,52 @@ add_executable(font-render-tester
"colors.hpp"
)

target_compile_features(font-render-tester PRIVATE cxx_std_17)
set_property(TARGET font-render-tester PROPERTY CXX_STANDARD 17)
target_compile_features(font-render-tester PRIVATE cxx_std_23)
set_property(TARGET font-render-tester PROPERTY CXX_STANDARD 23)
set_property(TARGET font-render-tester PROPERTY CXX_STANDARD_REQUIRED ON)

if (MSVC)
set_property(TARGET font-render-tester PROPERTY WIN32_EXECUTABLE ON)
target_compile_options(font-render-tester PRIVATE /Zc:__cplusplus)
set_property(TARGET font-render-tester PROPERTY WIN32_EXECUTABLE ON)
target_compile_options(font-render-tester PRIVATE /Zc:__cplusplus)
endif ()


find_package(SDL2 CONFIG REQUIRED)
find_package(fmt CONFIG REQUIRED)
find_package(freetype CONFIG REQUIRED)
find_package(harfbuzz CONFIG REQUIRED)
find_package(imgui CONFIG REQUIRED)
find_package(magic_enum CONFIG REQUIRED)
find_package(SDL2 CONFIG REQUIRED)
find_package(spdlog CONFIG REQUIRED)
find_package(utf8cpp CONFIG REQUIRED)

target_include_directories(font-render-tester PRIVATE ${STB_INCLUDE_DIRS})

target_link_libraries(font-render-tester PRIVATE
fmt::fmt
freetype
harfbuzz::harfbuzz
imgui::imgui
magic_enum::magic_enum
SDL2::SDL2 SDL2::SDL2main
imgui::imgui harfbuzz::harfbuzz
utf8::cpp utf8cpp::utf8cpp freetype spdlog::spdlog spdlog::spdlog_header_only)
spdlog::spdlog spdlog::spdlog_header_only
utf8::cpp utf8cpp::utf8cpp
)

function(copy_resources)
set(oneValueArgs TARGET TARGET)
set(multiValueArgs TARGET INPUT)
set(oneValueArgs DESTINATION)
set(oneValueArgs TARGET TARGET)
set(multiValueArgs TARGET INPUT)
set(oneValueArgs DESTINATION)

cmake_parse_arguments(COPY_RESOURCES "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN}
)
cmake_parse_arguments(COPY_RESOURCES "${options}" "${oneValueArgs}"
"${multiValueArgs}" ${ARGN}
)

file(GLOB COPY_RESOURCES_INPUT_FILES ${COPY_RESOURCES_INPUT})
file(GLOB COPY_RESOURCES_INPUT_FILES ${COPY_RESOURCES_INPUT})

add_custom_target(${COPY_RESOURCES_TARGET} ALL
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:font-render-tester>/${COPY_RESOURCES_DESTINATION}/"
COMMAND ${CMAKE_COMMAND} -E copy ${COPY_RESOURCES_INPUT_FILES} "$<TARGET_FILE_DIR:font-render-tester>/${COPY_RESOURCES_DESTINATION}/"
)
add_custom_target(${COPY_RESOURCES_TARGET} ALL
COMMAND ${CMAKE_COMMAND} -E make_directory "$<TARGET_FILE_DIR:font-render-tester>/${COPY_RESOURCES_DESTINATION}/"
COMMAND ${CMAKE_COMMAND} -E copy ${COPY_RESOURCES_INPUT_FILES} "$<TARGET_FILE_DIR:font-render-tester>/${COPY_RESOURCES_DESTINATION}/"
)
endfunction()

copy_resources(
Expand Down
63 changes: 52 additions & 11 deletions font.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,16 @@
#include <harfbuzz/hb-ft.h>
#include <spdlog/spdlog.h>

namespace {

constexpr magic_enum::containers::array<VariantAxis, hb_tag_t> AxisTags = {{{
HB_OT_TAG_VAR_AXIS_ITALIC,
HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE,
HB_OT_TAG_VAR_AXIS_SLANT,
HB_OT_TAG_VAR_AXIS_WEIGHT,
HB_OT_TAG_VAR_AXIS_WIDTH,
}}};
} // namespace

FT_Library Font::library;

Expand Down Expand Up @@ -45,9 +55,6 @@ Font::~Font() {
hb_font_destroy(hb_font);
hb_font = nullptr;

hb_face_destroy(hb_face);
hb_face = nullptr;

Invalidate();

FT_Done_Face(face);
Expand Down Expand Up @@ -92,20 +99,13 @@ bool Font::Initialize() {
}

hb_font = hb_ft_font_create_referenced(face);
hb_face = hb_ft_face_create_referenced(face);

Invalidate();
fontSize = -1;

family = face->family_name;
subFamily = face->style_name;

FT_MM_Var *mm;
FT_Get_MM_Var(face, &mm);

auto weight = HB_OT_TAG_VAR_AXIS_WEIGHT;

FT_Done_MM_Var(library, mm);
return true;
}

Expand Down Expand Up @@ -215,4 +215,45 @@ void Font::RenderText(SDL_Renderer *renderer, Context &ctx,
textRenderer(renderer, ctx, *this, str, color, language, script);
}

bool Font::IsVariableFont() const { return hb_ot_var_has_data(hb_face); }
bool Font::IsVariableFont() const {
if (!hb_font)
return false;

auto hb_face = hb_font_get_face(hb_font);
return hb_ot_var_has_data(hb_face);
}

magic_enum::containers::array<VariantAxis, std::optional<VariantAxisLimit>>
Font::GetVariantAxisLimits() const {
if (!IsVariableFont()) {
return {};
}

magic_enum::containers::array<VariantAxis, std::optional<VariantAxisLimit>>
output{};

auto hb_face = hb_font_get_face(hb_font);
auto count = hb_ot_var_get_axis_count(hb_face);

std::vector<hb_ot_var_axis_info_t> hbAxisInfo;
hbAxisInfo.resize(count);

hb_ot_var_get_axis_infos(hb_face, 0, &count, hbAxisInfo.data());

for (auto &info : hbAxisInfo) {
auto it = std::ranges::find_if( AxisTags, [&info](const hb_tag_t& t) ->bool {
return info.tag == t;
});

if (it != AxisTags.end()) {
auto tag = magic_enum::enum_cast<VariantAxis>(std::distance(AxisTags.begin(), it));
output[*tag] = {
.min = info.min_value,
.max = info.max_value,
.defaultValue = info.default_value,
};
}
}

return output;
}
31 changes: 22 additions & 9 deletions font.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,18 @@
#include <functional>
#include <hb-ot.h>
#include <iterator>
#include <magic_enum_containers.hpp>
#include <map>
#include <string>
#include <vector>

enum class TextRenderEnum {
NoShape,
LeftToRight,
RightToLeft,
TopToBottom,
};

enum class TextRenderEnum { NoShape, LeftToRight, RightToLeft, TopToBottom };
class Font;

typedef std::function<void(SDL_Renderer *renderer, Context &ctx, Font &font,
Expand All @@ -25,7 +31,6 @@ typedef std::function<void(SDL_Renderer *renderer, Context &ctx, Font &font,
TextRenderFunction;

struct Glyph {

SDL_Texture *texture;
SDL_Rect bound;
int advance;
Expand All @@ -39,12 +44,18 @@ inline float HBPosToFloat(const hb_position_t &value) {
return static_cast<float>(value) / 64.0f;
}

enum class VariantAxis : hb_tag_t {
Italic = HB_OT_TAG_VAR_AXIS_ITALIC,
OpticalSize = HB_OT_TAG_VAR_AXIS_OPTICAL_SIZE,
Slant = HB_OT_TAG_VAR_AXIS_SLANT,
Weight = HB_OT_TAG_VAR_AXIS_WEIGHT,
Width = HB_OT_TAG_VAR_AXIS_WIDTH,
enum class VariantAxis {
Italic,
OpticalSize,
Slant,
Weight,
Width,
};

struct VariantAxisLimit {
float min;
float max;
float defaultValue;
};

class Font {
Expand Down Expand Up @@ -88,6 +99,9 @@ class Font {
const SDL_Color &color, const std::string &language,
const hb_script_t &script);

magic_enum::containers::array<VariantAxis, std::optional<VariantAxisLimit>>
GetVariantAxisLimits() const;

private:
static FT_Library library;

Expand All @@ -101,7 +115,6 @@ class Font {

int fontSize{-1};
hb_font_t *hb_font{nullptr};
hb_face_t *hb_face{nullptr};

std::map<unsigned int, Glyph> glyphMap;

Expand Down
50 changes: 47 additions & 3 deletions main_scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
#include <algorithm>
#include <array>
#include <filesystem>
#include <fmt/core.h>
#include <imgui.h>
#include <imgui_internal.h>
#include <magic_enum_all.hpp>
#include <magic_enum_containers.hpp>

namespace {
constexpr ImVec4 SDLColorToImVec4(const SDL_Color &color) {
Expand Down Expand Up @@ -95,11 +98,11 @@ void MainScene::DoUI(Context &context) {

ImGui::Separator();

if(ImGui::MenuItem("Exit", "Alt+F4")) {
if (ImGui::MenuItem("Exit", "Alt+F4")) {
SDL_Event ev{};
ev.quit.type = SDL_QUIT;
ev.quit.timestamp = SDL_GetTicks();

SDL_PushEvent(&ev);
}

Expand Down Expand Up @@ -158,6 +161,37 @@ void MainScene::DoUI(Context &context) {
if (ImGui::CollapsingHeader("Parameters", ImGuiTreeNodeFlags_DefaultOpen)) {
ImGui::SliderInt("Font Size", &fontSize, 0, 128);

ImGui::SeparatorText("Variant");
ImGui::BeginDisabled(!font.IsVariableFont());

bool axisChanged = false;

static constexpr magic_enum::containers::array<VariantAxis, const char *>
axisLabel = {{{
"Italic##axis",
"Optical size##axis",
"Slant##axis",
"Weight##axis",
"Width##axis",
}}};

magic_enum::enum_for_each<VariantAxis>(
[this, &axisChanged](const VariantAxis &axis) {
if (axisLimits[axis].has_value()) {
auto [min, max, _] = *axisLimits[axis];
axisChanged |= ImGui::DragFloat(axisLabel[axis], &axisValue[axis],
1.0f, min, max);
} else {
ImGui::LabelText(axisLabel[axis], "N/A");
}
});

if (axisChanged) {
// Update variant axis.
}

ImGui::EndDisabled();

ImGui::SeparatorText("Font metrics");

ImGui::LabelText("Ascend", "%.3f", font.Ascend());
Expand Down Expand Up @@ -199,7 +233,8 @@ void MainScene::DoUI(Context &context) {

ImGui::SeparatorText("Draw color");

ImGui::ColorPicker3("Foreground##color", color, ImGuiColorEditFlags_InputRGB);
ImGui::ColorPicker3("Foreground##color", color,
ImGuiColorEditFlags_InputRGB);
}
ImGui::End();

Expand Down Expand Up @@ -269,6 +304,15 @@ void MainScene::DoUI(Context &context) {
ImGui::OpenPopup("InvalidFont");
} else {
font = newFont;
axisLimits = font.GetVariantAxisLimits();

magic_enum::enum_for_each<VariantAxis>([this](const VariantAxis &axis) {
if (!axisLimits[axis].has_value())
return;

axisValue[axis] = axisLimits[axis]->defaultValue;
});

selectedFontIndex = newSelected;
}
}
Expand Down
21 changes: 13 additions & 8 deletions main_scene.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ class MainScene : public Scene {

private:
static const inline std::string exampleText =
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod \n"
"tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim \n"
"veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea \n"
"commodo consequat. Duis aute irure dolor in reprehenderit in voluptate \n"
"velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint \n"
"occaecat cupidatat non proident, sunt in culpa qui officia deserunt \n"
"mollit anim id est laborum.";
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non \n"
"turpis justo. Etiam luctus vulputate ante ac congue. Nunc vitae \n"
"ultricies turpis, eu mollis libero. Quisque eu faucibus neque. \n"
"Aliquam risus urna, ullamcorper sit amet arcu id, feugiat semper \n"
"dolor. Maecenas commodo turpis orci, vel laoreet felis placerat \n"
"in. In nec metus tincidunt sem sagittis dapibus ut eget magna. \n"
"Aenean efficitur felis sed metus mollis varius.";

std::array<char, 4096> buffer = {0};
float color[3];
Expand Down Expand Up @@ -70,6 +70,7 @@ class MainScene : public Scene {
const char* name;
const hb_direction_t direction;
};

static constexpr std::array<DirectionPair, 3> directions = {
DirectionPair{"Left to Right", HB_DIRECTION_LTR,},
DirectionPair{ "Right To Left",HB_DIRECTION_RTL, },
Expand All @@ -88,11 +89,15 @@ class MainScene : public Scene {
LanguagePair{ "Korean Republic of Korea","ko-KR", },
LanguagePair{ "Chinese China", "zh-CN", },
LanguagePair{ "Chinese Taiwan", "zh-TW", },
LanguagePair{ "Arabic Saudi Arabia", "ar-SA", },
LanguagePair{ "Arabic Saudi Arabia", "ar-SA", },
};
// clang-format on

int selectedScript = 0;
int selectedDirection = 0;
int selectedLanguage = 0;

magic_enum::containers::array<VariantAxis, float> axisValue;
magic_enum::containers::array<VariantAxis, std::optional<VariantAxisLimit>>
axisLimits;
};
2 changes: 2 additions & 0 deletions vcpkg.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@
"name": "font-render-tester",
"version-string": "0.1.0-dev",
"dependencies": [
"fmt",
"freetype",
"harfbuzz",
"magic-enum",
"nlohmann-json",
"sdl2",
"spdlog",
Expand Down

0 comments on commit 3db41f2

Please sign in to comment.