From 35229e3dbd7788d8a296891d3eae0535e61d0b72 Mon Sep 17 00:00:00 2001 From: blankie Date: Sat, 7 Jan 2023 16:15:21 +0700 Subject: [PATCH] Use fontconfig --- .gitignore | 3 -- Makefile | 21 +++-------- fonts.cpp | 98 ++++++++++++++++++++++++++++++++++++++++++++++++++++ fonts.h | 6 ++-- log.cpp | 10 +++++- log.h | 3 ++ main.cpp | 15 ++++++-- myimconfig.h | 5 +++ 8 files changed, 136 insertions(+), 25 deletions(-) create mode 100644 fonts.cpp create mode 100644 myimconfig.h diff --git a/.gitignore b/.gitignore index 0e030cd..668de5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,4 @@ *.o *.obj -fonts.cpp logmeow logmeow.exe -binary_to_compressed_c -binary_to_compressed_c.exe diff --git a/Makefile b/Makefile index 98321b2..883285e 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,7 @@ OBJS = $(addsuffix .o, $(basename $(notdir $(SOURCES)))) UNAME_S := $(shell uname -s) LINUX_GL_LIBS = -lGL -CXXFLAGS = -std=c++14 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/misc/cpp -I$(IMGUI_DIR)/backends +CXXFLAGS = -std=c++20 -I$(IMGUI_DIR) -I$(IMGUI_DIR)/misc/cpp -I$(IMGUI_DIR)/backends -D'IMGUI_USER_CONFIG="../myimconfig.h"' # https://t.me/NightShadowsHangout/670691 CXXFLAGS += -g -Werror -Wall -Wextra -Wshadow -Wpedantic -Wno-gnu-anonymous-struct -fno-rtti -fPIC -Wconversion -Wno-unused-parameter -Wimplicit-fallthrough LIBS = @@ -44,9 +44,9 @@ LIBS = ##--------------------------------------------------------------------- ifeq ($(UNAME_S), Linux) #LINUX - LIBS += $(LINUX_GL_LIBS) -ldl `sdl2-config --libs` + LIBS += $(LINUX_GL_LIBS) -ldl `sdl2-config --libs` -lfontconfig - CXXFLAGS += `sdl2-config --cflags` + CXXFLAGS += `sdl2-config --cflags` -DUSE_FONTCONFIG CFLAGS = $(CXXFLAGS) endif @@ -76,20 +76,7 @@ $(EXE): $(OBJS) %.o:%.cpp $(CXX) $(CXXFLAGS) -c -o $@ $< -fonts.cpp: binary_to_compressed_c fonts.h imgui/misc/fonts/DroidSans.ttf imgui/misc/fonts/Cousine-Regular.ttf - echo -e '#include "fonts.h"\n\n' > fonts.cpp - ./binary_to_compressed_c -base85 imgui/misc/fonts/DroidSans.ttf droid_sans >> fonts.cpp - ./binary_to_compressed_c -base85 imgui/misc/fonts/Cousine-Regular.ttf cousine >> fonts.cpp - echo -e 'const char* get_droid_sans_compressed_data_base85() { return droid_sans_compressed_data_base85; }\n' >> fonts.cpp - echo -e 'const char* get_cousine_compressed_data_base85() { return cousine_compressed_data_base85; }\n' >> fonts.cpp - -fonts.o: fonts.cpp - $(CXX) $(CXXFLAGS) -Wno-overlength-strings -Wno-unused-const-variable -c -o $@ $< - # dear imgui has some fucky wucky with -Wconversion, hence -Wno-conversion -binary_to_compressed_c: imgui/misc/fonts/binary_to_compressed_c.cpp - $(CXX) $(CXXFLAGS) -Wno-conversion -o $@ $< - %.o:$(IMGUI_DIR)/%.cpp $(CXX) $(CXXFLAGS) -Wno-conversion -c -o $@ $< @@ -100,4 +87,4 @@ binary_to_compressed_c: imgui/misc/fonts/binary_to_compressed_c.cpp $(CXX) $(CXXFLAGS) -Wno-conversion -c -o $@ $< clean: - rm -f $(EXE) $(OBJS) fonts.cpp binary_to_compressed_c + rm -f $(EXE) $(OBJS) diff --git a/fonts.cpp b/fonts.cpp new file mode 100644 index 0000000..62e0cd3 --- /dev/null +++ b/fonts.cpp @@ -0,0 +1,98 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include "fonts.h" + +class FcResultException : public std::exception { +public: + FcResultException(FcResult result) : _result(result) {} + const char* what() const noexcept { + switch (this->_result) { + case FcResultMatch: return "FcResultException: Object exists with the specified ID"; + case FcResultNoMatch: return "FcResultException: Object doesn't exist at all"; + case FcResultTypeMismatch: return "FcResultException: Object exists, but the type doesn't match"; + case FcResultNoId: return "FcResultException: Object exists, but has fewer values than specified"; + case FcResultOutOfMemory: return "FcResultException: malloc failed"; + } + return "FcResultException: Unknown result"; + } + +private: + FcResult _result; +}; + +static std::string get_filename(FcPattern* pattern, const char* family) { + std::string filename; + FcResult result; + FcValue font_value; + FcValue family_value = { + .type = FcTypeString, + .u = { + .s = reinterpret_cast(family) + } + }; + + if (FcPatternAdd(pattern, FC_FAMILY, family_value, FcFalse) != FcTrue) { + throw std::runtime_error(std::string("FcPatternAdd() for ") + family + " returned FcFalse"); + } + FcConfigSubstitute(nullptr, pattern, FcMatchPattern); + FcDefaultSubstitute(pattern); + + FcPattern* font_pattern = FcFontMatch(nullptr, pattern, &result); + if (!font_pattern) { + throw std::runtime_error(std::string("FcFontMatch() for ") + family + " returned nullptr"); + } + if (result != FcResultMatch) { + FcPatternDestroy(font_pattern); + throw FcResultException(result); + } + + result = FcPatternGet(font_pattern, FC_FILE, 0, &font_value); + if (result != FcResultMatch) { + FcPatternDestroy(font_pattern); + throw FcResultException(result); + } + + filename = reinterpret_cast(font_value.u.s); + FcPatternDestroy(font_pattern); + return filename; +} + +std::pair get_fonts() { + if (FcInit() != FcTrue) { + throw std::runtime_error("FcInit() returned FcFalse"); + } + + std::string monospace_filename, sans_serif_filename; + FcPattern* pattern = FcPatternCreate(); + if (!pattern) { + FcFini(); + throw std::bad_alloc(); + } + + try { + sans_serif_filename = get_filename(pattern, "sans-serif"); + } catch (const std::exception& e) { + FcPatternDestroy(pattern); + FcFini(); + throw; + } + FcPatternDel(pattern, FC_FAMILY); + try { + monospace_filename = get_filename(pattern, "monospace"); + } catch (const std::exception& e) { + FcPatternDestroy(pattern); + FcFini(); + throw; + } + + FcPatternDestroy(pattern); + FcFini(); + return std::make_pair(std::move(sans_serif_filename), std::move(monospace_filename)); +} diff --git a/fonts.h b/fonts.h index 25262ff..9389b46 100644 --- a/fonts.h +++ b/fonts.h @@ -1,4 +1,6 @@ #pragma once -const char* get_droid_sans_compressed_data_base85(); -const char* get_cousine_compressed_data_base85(); +#include +#include + +std::pair get_fonts(); diff --git a/log.cpp b/log.cpp index 9dcfc58..8298356 100644 --- a/log.cpp +++ b/log.cpp @@ -52,8 +52,16 @@ void log(std::string entry, time_t time) { } while (last_newline_pos); } +void log(std::string entry) { + log(std::move(entry), current_time()); +} + +void log(std::string action, const std::exception& e, time_t time) { + log(action + ": " + e.what(), time); +} + void log(std::string action, const std::exception& e) { - log(action + ": " + e.what(), current_time()); + log(std::move(action), e, current_time()); } std::string quote(const std::string& str) { diff --git a/log.h b/log.h index 8ac289c..e3fee54 100644 --- a/log.h +++ b/log.h @@ -6,5 +6,8 @@ extern std::string log_entries; +void log(std::string entry, time_t time); +void log(std::string entry); +void log(std::string action, const std::exception& e, time_t time); void log(std::string action, const std::exception& e); std::string quote(const std::string& str); diff --git a/main.cpp b/main.cpp index e565032..75c524f 100644 --- a/main.cpp +++ b/main.cpp @@ -110,8 +110,19 @@ int main(int, char**) { //io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f); //ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese()); //IM_ASSERT(font != NULL); - io.Fonts->AddFontFromMemoryCompressedBase85TTF(get_droid_sans_compressed_data_base85(), 16.0f); - ImFont* monospace_font = io.Fonts->AddFontFromMemoryCompressedBase85TTF(get_cousine_compressed_data_base85(), 15.0f); + ImFont* monospace_font; +#ifdef USE_FONTCONFIG + try { + std::pair fonts = get_fonts(); + io.Fonts->AddFontFromFileTTF(fonts.first.c_str(), 15.0f); + monospace_font = io.Fonts->AddFontFromFileTTF(fonts.second.c_str(), 15.0f); + } catch (const std::exception& e) { + log("Failed to get fonts", e); + monospace_font = io.Fonts->AddFontDefault(); + } +#else + monospace_font = io.Fonts->AddFontDefault(); +#endif // Main loop bool run_event_loop = true; diff --git a/myimconfig.h b/myimconfig.h new file mode 100644 index 0000000..f7dd686 --- /dev/null +++ b/myimconfig.h @@ -0,0 +1,5 @@ +#pragma once + +#include "log.h" + +#define IM_ASSERT_USER_ERROR(expr,msg) do { if (!(expr)) { log(msg); } } while (0);