Use fontconfig

This commit is contained in:
blankie 2023-01-07 16:15:21 +07:00
parent 680a1c93af
commit 35229e3dbd
Signed by: blankie
GPG Key ID: CC15FC822C7F61F5
8 changed files with 136 additions and 25 deletions

3
.gitignore vendored
View File

@ -1,7 +1,4 @@
*.o
*.obj
fonts.cpp
logmeow
logmeow.exe
binary_to_compressed_c
binary_to_compressed_c.exe

View File

@ -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)

98
fonts.cpp Normal file
View File

@ -0,0 +1,98 @@
#include <string>
#include <utility>
#include <exception>
#include <stdexcept>
#include <fontconfig/fontconfig.h>
#include <cstdio>
#include <cstdlib>
#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<const FcChar8*>(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<const char*>(font_value.u.s);
FcPatternDestroy(font_pattern);
return filename;
}
std::pair<std::string, std::string> 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));
}

View File

@ -1,4 +1,6 @@
#pragma once
const char* get_droid_sans_compressed_data_base85();
const char* get_cousine_compressed_data_base85();
#include <string>
#include <utility>
std::pair<std::string, std::string> get_fonts();

10
log.cpp
View File

@ -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) {

3
log.h
View File

@ -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);

View File

@ -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<std::string, std::string> 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;

5
myimconfig.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "log.h"
#define IM_ASSERT_USER_ERROR(expr,msg) do { if (!(expr)) { log(msg); } } while (0);