From a1935d8f44cfb6c2960d5ff5531c7c7f40c5b50f Mon Sep 17 00:00:00 2001 From: Ivan Mahonin Date: Mar 22 2020 12:53:34 +0000 Subject: freetype: improve --- diff --git a/c++/freetype/src/SConstruct b/c++/freetype/src/SConstruct index 6a259aa..61775bd 100644 --- a/c++/freetype/src/SConstruct +++ b/c++/freetype/src/SConstruct @@ -4,7 +4,7 @@ env = Environment() # config -libs = ['gtkmm-3.0', 'pangomm-1.4', 'pangoft2'] +libs = ['gtkmm-3.0', 'pangomm-1.4', 'pangoft2', 'fontconfig'] # compute build options diff --git a/c++/freetype/src/freetypeview.cpp b/c++/freetype/src/freetypeview.cpp index c5adaac..2fa54bf 100644 --- a/c++/freetype/src/freetypeview.cpp +++ b/c++/freetype/src/freetypeview.cpp @@ -1,4 +1,6 @@ +#include + #include #include @@ -31,6 +33,25 @@ fill_rect( *p = color; } +static bool +is_font_file(const std::string &name) { + static const char *ext[] = { ".otf", ".otc", ".ttf", ".ttc" }; + static const int count = (int)(sizeof(ext)/sizeof(*ext)); + + bool found = false; + for(int i = 0; i < count; ++i) { + const char *e = ext[i]; + int len = 0; while(e[len]) ++len; + if ((int)name.size() < len) continue; + found = true; + for(int j = 0, k = name.size() - len; j < len; ++j, ++k) + if (tolower(name[k]) != e[j]) { found = false; break; } + if (found) break; + } + return found; +} + + FreeTypeView::FreeTypeView(): p0(new View::Point( Vector2(0, 0) )), @@ -49,10 +70,12 @@ FreeTypeView::FreeTypeView(): set_size_request(400, 400); - params.family = "Ani"; + //params.family = "Chancery Uralic"; + //params.family = "DejaVu"; + params.family = "data/font/Bradley Gratis/Bradley Gratis.ttf"; params.bold = false; params.italic = false; - params.size = 12; + params.size = 24; params.spacing = Vector2(3, 2); @@ -147,12 +170,17 @@ FreeTypeView::update_surface() { Glib::RefPtr context = font_map->create_context(); // load font + Glib::RefPtr font; Pango::FontDescription font_desc; font_desc.set_family(params.family); font_desc.set_weight(params.bold ? Pango::WEIGHT_BOLD : Pango::WEIGHT_NORMAL); font_desc.set_style(params.italic ? Pango::STYLE_ITALIC : Pango::STYLE_NORMAL); font_desc.set_absolute_size(params.size * Pango::SCALE); - Glib::RefPtr font = context->load_font(font_desc); + if (is_font_file(params.family)) + font = Layout::load_font_file(context, params.family, font_desc); + if (!font) + font = context->load_font(font_desc); + font_desc = font->describe(); // create pango layout Glib::RefPtr pango_layout = Pango::Layout::create(context); diff --git a/c++/freetype/src/layout.cpp b/c++/freetype/src/layout.cpp index 2d50b02..e294ef4 100644 --- a/c++/freetype/src/layout.cpp +++ b/c++/freetype/src/layout.cpp @@ -1,8 +1,20 @@ +#include + +#include + #include #include FT_FREETYPE_H +#include FT_TRUETYPE_TABLES_H +#include FT_TRUETYPE_IDS_H +#include FT_SFNT_NAMES_H + +#include +#include #include +#include +#include #include "layout.h" @@ -99,7 +111,7 @@ lab_fake_pango_renderer_draw_glyph( g.glyph_index = glyph; g.origin = Vector2(origin.x, origin.y)*k; - g.position = Vector2(x, y) + g.origin; + g.position = Vector2(x, y) - g.origin; g.bounds = Pair2( Vector2(bounds.p0.x, bounds.p0.y)*k, Vector2(bounds.p1.x, bounds.p1.y)*k ); } @@ -129,15 +141,72 @@ Layout::create_fontmap(bool hinting, bool antialiasing) { PangoFontMap *font_map = pango_ft2_font_map_new(); pango_ft2_font_map_set_default_substitute( - (PangoFT2FontMap*)font_map, + PANGO_FT2_FONT_MAP(font_map), lab_pango_fc_pattern_set_substitute, data, nullptr ); g_object_set_qdata((GObject*)font_map, layout_data_quark(), data); + return Glib::wrap(font_map); } +Glib::RefPtr +Layout::load_font_file( + const Glib::RefPtr &context, + const std::string &filename, + const Pango::FontDescription &font_desc ) +{ + const std::string fullpath = Glib::path_is_absolute(filename) + ? filename : Glib::get_current_dir() + "/" + filename; + + Glib::RefPtr font; + + bool desc_ready = false; + Pango::FontDescription desc = font_desc; + + FT_Library library; + if (!FT_Init_FreeType(&library)) { + FT_Face face; + if (!FT_New_Face(library, fullpath.c_str(), 0, &face)) { + desc.set_family(face->family_name); + desc.set_style( + face->style_flags & FT_STYLE_FLAG_ITALIC + ? Pango::STYLE_ITALIC : Pango::STYLE_NORMAL ); + desc.set_weight( + face->style_flags & FT_STYLE_FLAG_BOLD + ? Pango::WEIGHT_BOLD : Pango::WEIGHT_NORMAL ); + desc_ready = true; + FT_Done_Face(face); + } else { + std::cerr << "Layout::load_font_file: Cannot load font from file: " << fullpath << std::endl; + } + FT_Done_FreeType(library); + } else { + std::cerr << "Layout::load_font_file: Cannot init FreeType library" << std::endl; + } + + if (desc_ready) { + PangoFcFontMap *font_map = PANGO_FC_FONT_MAP(pango_context_get_font_map(context->gobj())); + if (font_map) { + FcConfig *config = pango_fc_font_map_get_config(font_map); + if (config || FcConfigAppFontAddFile(config, (const FcChar8*)fullpath.c_str())) { + pango_fc_font_map_config_changed(font_map); + font = context->load_font(desc); + } else { + pango_fc_font_map_config_changed(font_map); + std::cerr << "Layout::load_font_file: Cannot register font file in FontConfig: " << fullpath << std::endl; + } + } else { + std::cerr << "Layout::load_font_file: Wrong context. FreeType/FontConfig context required" << std::endl; + } + } + + return font; +} + + + Layout::Layout(const Glib::RefPtr &layout): hinting(), antialiasing() diff --git a/c++/freetype/src/layout.h b/c++/freetype/src/layout.h index b5ba9a3..8d53f3e 100644 --- a/c++/freetype/src/layout.h +++ b/c++/freetype/src/layout.h @@ -62,6 +62,10 @@ public: { return lines; } static Glib::RefPtr create_fontmap(bool hinting, bool antialiasing); + static Glib::RefPtr load_font_file( + const Glib::RefPtr &context, + const std::string &filename, + const Pango::FontDescription &font_desc ); };