Date: Sun, 25 Jun 2023 05:19:19 GMT From: Charlie Li <vishwin@FreeBSD.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org Subject: git: fe6320a394de - main - graphics/inkscape: partially pull in two upstream changes Message-ID: <202306250519.35P5JJvd016948@gitrepo.freebsd.org>
next in thread | raw e-mail | index | archive | help
The branch main has been updated by vishwin: URL: https://cgit.FreeBSD.org/ports/commit/?id=fe6320a394dee2aa34515a4f6f8f9ad5772d9b14 commit fe6320a394dee2aa34515a4f6f8f9ad5772d9b14 Author: Charlie Li <vishwin@FreeBSD.org> AuthorDate: 2023-06-25 05:12:27 +0000 Commit: Charlie Li <vishwin@FreeBSD.org> CommitDate: 2023-06-25 05:12:27 +0000 graphics/inkscape: partially pull in two upstream changes Both changes are for removing std::unary_function and std::binary_function, which are deprecated in C++17 and error in clang 16: - https://gitlab.com/inkscape/inkscape/-/merge_requests/4463 (partial) - https://gitlab.com/inkscape/inkscape/-/merge_requests/4483 (full) These involve code refactorings where functional changes can exist so bump PORTREVISION. Event: ARRL/RAC Field Day 2023 --- graphics/inkscape/Makefile | 8 +- graphics/inkscape/distinfo | 10 +- .../patch-362f987096833dd1dfa223be82fc6a97c3795f6c | 1456 ++++++++++++++++++++ 3 files changed, 1472 insertions(+), 2 deletions(-) diff --git a/graphics/inkscape/Makefile b/graphics/inkscape/Makefile index d1a18d6aaa8a..44b0a206e7e6 100644 --- a/graphics/inkscape/Makefile +++ b/graphics/inkscape/Makefile @@ -1,10 +1,16 @@ PORTNAME= inkscape DISTVERSION= 1.2.2 -PORTREVISION= 10 +PORTREVISION= 11 CATEGORIES= graphics gnome MASTER_SITES= https://media.inkscape.org/dl/resources/file/ PATCH_SITES= https://gitlab.com/${PORTNAME}/${PORTNAME}/-/commit/ +# https://gitlab.com/inkscape/inkscape/-/merge_requests/4463 +PATCHFILES+= c5fc06a7c29d6be9e2fb18b841e973a193428332.patch:-p1 \ + 40c4147ec66319f42129ab253d0483f91329419c.patch:-p1 \ + 57c85eec491e07949497fa67edc7c76eafde7471.patch:-p1 +# 362f987096833dd1dfa223be82fc6a97c3795f6c.patch:-p1 +PATCHFILES+= fdc7329ba5036ef5cde7bb5e61ed52a69850f5d8.patch:-p1 # https://gitlab.com/inkscape/inkscape/-/merge_requests/4483 PATCHFILES+= 781e29cd3538.patch:-p1 # https://gitlab.com/inkscape/inkscape/-/merge_requests/5111 MAINTAINER= gnome@FreeBSD.org diff --git a/graphics/inkscape/distinfo b/graphics/inkscape/distinfo index 78e786d06465..d6bdd134d472 100644 --- a/graphics/inkscape/distinfo +++ b/graphics/inkscape/distinfo @@ -1,5 +1,13 @@ -TIMESTAMP = 1670503504 +TIMESTAMP = 1687584227 SHA256 (inkscape-1.2.2.tar.xz) = a0c7fd0d03c0a21535e648ef301dcf80dd7cfc1f3545e51065fbf1ba3ee8a5c4 SIZE (inkscape-1.2.2.tar.xz) = 39392040 +SHA256 (c5fc06a7c29d6be9e2fb18b841e973a193428332.patch) = 08ca608bc5509e2398d23ef67202f7155296c36e329d1d2a3b00b37d8fd08214 +SIZE (c5fc06a7c29d6be9e2fb18b841e973a193428332.patch) = 22563 +SHA256 (40c4147ec66319f42129ab253d0483f91329419c.patch) = 05e670f7d768cfbbc5aacf233fe5c169402611b4f2949a491beb45150b95b14b +SIZE (40c4147ec66319f42129ab253d0483f91329419c.patch) = 24153 +SHA256 (57c85eec491e07949497fa67edc7c76eafde7471.patch) = e3119ce429fb60f554b42b4507becd9bee47c3cb6f71fe1fbfc46331b2bf0574 +SIZE (57c85eec491e07949497fa67edc7c76eafde7471.patch) = 26184 +SHA256 (fdc7329ba5036ef5cde7bb5e61ed52a69850f5d8.patch) = 064f76e8691b0975b6a82a21923c562d9bb9855aa08d99ece9af9da877b544d6 +SIZE (fdc7329ba5036ef5cde7bb5e61ed52a69850f5d8.patch) = 5483 SHA256 (781e29cd3538.patch) = 0dda9fb22107b81768e41c38adacf4920c9ecd2ca6ca47efa90693481b72e1b8 SIZE (781e29cd3538.patch) = 9262 diff --git a/graphics/inkscape/files/patch-362f987096833dd1dfa223be82fc6a97c3795f6c b/graphics/inkscape/files/patch-362f987096833dd1dfa223be82fc6a97c3795f6c new file mode 100644 index 000000000000..544a99b89eea --- /dev/null +++ b/graphics/inkscape/files/patch-362f987096833dd1dfa223be82fc6a97c3795f6c @@ -0,0 +1,1456 @@ +From 362f987096833dd1dfa223be82fc6a97c3795f6c Mon Sep 17 00:00:00 2001 +From: PBS <pbs3141@gmail.com> +Date: Sun, 24 Apr 2022 12:21:30 +0900 +Subject: [PATCH] FontFactory refactoring + +--- + src/display/drawing-text.cpp | 4 +- + src/display/drawing-text.h | 8 +- + src/libnrtype/FontFactory.cpp | 426 +++++++++++++++------------ + src/libnrtype/FontFactory.h | 142 +++------ + src/libnrtype/FontInstance.cpp | 36 +-- + src/libnrtype/Layout-TNG-Compute.cpp | 16 +- + src/libnrtype/Layout-TNG-Input.cpp | 4 +- + src/libnrtype/Layout-TNG-OutIter.cpp | 2 +- + src/libnrtype/Layout-TNG-Output.cpp | 2 +- + src/libnrtype/Layout-TNG.h | 8 +- + src/libnrtype/font-instance.h | 6 +- + src/libnrtype/font-lister.cpp | 2 +- + src/object/sp-flowtext.cpp | 2 +- + src/object/sp-text.cpp | 2 +- + src/ui/dialog/font-substitution.cpp | 2 +- + src/ui/dialog/glyphs.cpp | 2 +- + src/ui/dialog/text-edit.cpp | 2 +- + src/ui/dialog/text-edit.h | 2 +- + src/ui/widget/font-variants.cpp | 2 +- + src/ui/widget/font-variations.cpp | 2 +- + 20 files changed, 323 insertions(+), 349 deletions(-) + +diff --git src/display/drawing-text.cpp src/display/drawing-text.cpp +index fce8644549a..e39cff558e5 100644 +--- src/display/drawing-text.cpp ++++ src/display/drawing-text.cpp +@@ -42,7 +42,7 @@ DrawingGlyphs::~DrawingGlyphs() + } + + void +-DrawingGlyphs::setGlyph(font_instance *font, int glyph, Geom::Affine const &trans) ++DrawingGlyphs::setGlyph(FontInstance *font, int glyph, Geom::Affine const &trans) + { + _markForRendering(); + +@@ -228,7 +228,7 @@ DrawingText::clear() + } + + bool +-DrawingText::addComponent(font_instance *font, int glyph, Geom::Affine const &trans, ++DrawingText::addComponent(FontInstance *font, int glyph, Geom::Affine const &trans, + float width, float ascent, float descent, float phase_length) + { + /* original, did not save a glyph for white space characters, causes problems for text-decoration +diff --git src/display/drawing-text.h src/display/drawing-text.h +index 084c7939219..ec0bbaaeba0 100644 +--- src/display/drawing-text.h ++++ src/display/drawing-text.h +@@ -17,7 +17,7 @@ + #include "display/nr-style.h" + + class SPStyle; +-class font_instance; ++class FontInstance; + + namespace Inkscape { + +@@ -28,7 +28,7 @@ public: + DrawingGlyphs(Drawing &drawing); + ~DrawingGlyphs() override; + +- void setGlyph(font_instance *font, int glyph, Geom::Affine const &trans); ++ void setGlyph(FontInstance *font, int glyph, Geom::Affine const &trans); + void setStyle(SPStyle *style, SPStyle *context_style = nullptr) override; // Not to be used + Geom::IntRect getPickBox() const { return _pick_bbox; }; + +@@ -37,7 +37,7 @@ public: + unsigned flags, unsigned reset) override; + DrawingItem *_pickItem(Geom::Point const &p, double delta, unsigned flags) override; + +- font_instance *_font; ++ FontInstance *_font; + int _glyph; + bool _drawable; + float _width; // These three are used to set up bounding box +@@ -57,7 +57,7 @@ public: + ~DrawingText() override; + + void clear(); +- bool addComponent(font_instance *font, int glyph, Geom::Affine const &trans, ++ bool addComponent(FontInstance *font, int glyph, Geom::Affine const &trans, + float width, float ascent, float descent, float phase_length); + void setStyle(SPStyle *style, SPStyle *context_style = nullptr) override; + void setChildrenStyle(SPStyle *context_style) override; +diff --git src/libnrtype/FontFactory.cpp src/libnrtype/FontFactory.cpp +index 9ce51c27e5b..7194be15487 100644 +--- src/libnrtype/FontFactory.cpp ++++ src/libnrtype/FontFactory.cpp +@@ -11,7 +11,7 @@ + */ + + #ifdef HAVE_CONFIG_H +-# include "config.h" // only include where actually required! ++#include "config.h" // only include where actually required! + #endif + + #ifndef PANGO_ENABLE_ENGINE +@@ -35,48 +35,142 @@ + #include "libnrtype/font-instance.h" + #include "libnrtype/OpenTypeUtil.h" + +-# ifdef _WIN32 +- ++#ifdef _WIN32 + #include <glibmm.h> + #include <windows.h> +- + #endif + +-typedef std::unordered_map<PangoFontDescription*, font_instance*, font_descr_hash, font_descr_equal> FaceMapType; +- +-// need to avoid using the size field +-size_t font_descr_hash::operator()( PangoFontDescription *const &x) const { +- int h = 0; +- char const *theF = sp_font_description_get_family(x); +- h += (theF)?g_str_hash(theF):0; +- h *= 1128467; +- h += (int)pango_font_description_get_style(x); +- h *= 1128467; +- h += (int)pango_font_description_get_variant(x); +- h *= 1128467; +- h += (int)pango_font_description_get_weight(x); +- h *= 1128467; +- h += (int)pango_font_description_get_stretch(x); +- char const *theV = pango_font_description_get_variations(x); +- h *= 1128467; +- h += (theV)?g_str_hash(theV):0; +- return h; +-} ++struct FontFactory::Private ++{ ++ // A hashmap of all the loaded font instances, indexed by their PangoFontDescription. ++ // Note: Since pango already does that, using the PangoFont could work too. ++ struct Hash ++ { ++ size_t operator()(PangoFontDescription const *x) const ++ { ++ // Need to avoid using the size field. ++ size_t hash = 0; ++ auto const family = sp_font_description_get_family(x); ++ hash += family ? g_str_hash(family) : 0; ++ hash *= 1128467; ++ hash += (size_t)pango_font_description_get_style(x); ++ hash *= 1128467; ++ hash += (size_t)pango_font_description_get_variant(x); ++ hash *= 1128467; ++ hash += (size_t)pango_font_description_get_weight(x); ++ hash *= 1128467; ++ hash += (size_t)pango_font_description_get_stretch(x); ++ hash *= 1128467; ++ auto const variations = pango_font_description_get_variations(x); ++ hash += variations ? g_str_hash(variations) : 0; ++ return hash; ++ } ++ }; ++ ++ struct Compare ++ { ++ bool operator()(PangoFontDescription const *a, PangoFontDescription const *b) const ++ { ++ // return pango_font_description_equal(a, b); ++ auto const fa = sp_font_description_get_family(a); ++ auto const fb = sp_font_description_get_family(b); ++ if ((bool)fa != (bool)fb) return false; ++ if (fa && fb && std::strcmp(fa, fb) != 0) return false; ++ if (pango_font_description_get_style(a) != pango_font_description_get_style(b) ) return false; ++ if (pango_font_description_get_variant(a) != pango_font_description_get_variant(b) ) return false; ++ if (pango_font_description_get_weight(a) != pango_font_description_get_weight(b) ) return false; ++ if (pango_font_description_get_stretch(a) != pango_font_description_get_stretch(b) ) return false; ++ if (g_strcmp0(pango_font_description_get_variations(a), ++ pango_font_description_get_variations(b) ) != 0) return false; ++ return true; ++ } ++ }; ++ ++ std::unordered_map<PangoFontDescription*, FontInstance*, Hash, Compare> map; ++ ++ // A little cache for fonts, so that you don't lose your time looking up fonts in the font list. ++ // Each font in the cache is refcounted once (and deref'd when removed from the cache). ++ // Note: This cache only keeps fonts from being unref'd, and does not speed up access. ++ struct FontEntry ++ { ++ FontInstance *font; ++ double age; ++ }; ++ std::vector<FontEntry> cache; ++ static constexpr int max_cache_size = 64; ++ ++ void add_in_cache(FontInstance *font) ++ { ++ if (!font) return; ++ ++ for (auto &c : cache) { ++ c.age *= 0.9; ++ } + +-bool font_descr_equal::operator()( PangoFontDescription *const&a, PangoFontDescription *const &b) const { +- //if ( pango_font_description_equal(a,b) ) return true; +- char const *fa = sp_font_description_get_family(a); +- char const *fb = sp_font_description_get_family(b); +- if ( ( fa && fb == nullptr ) || ( fb && fa == nullptr ) ) return false; +- if ( fa && fb && strcmp(fa,fb) != 0 ) return false; +- if ( pango_font_description_get_style(a) != pango_font_description_get_style(b) ) return false; +- if ( pango_font_description_get_variant(a) != pango_font_description_get_variant(b) ) return false; +- if ( pango_font_description_get_weight(a) != pango_font_description_get_weight(b) ) return false; +- if ( pango_font_description_get_stretch(a) != pango_font_description_get_stretch(b) ) return false; +- if ( g_strcmp0( pango_font_description_get_variations(a), +- pango_font_description_get_variations(b) ) != 0 ) return false; +- return true; +-} ++ for (auto &c : cache) { ++ if (c.font == font) { ++ // printf("present\n"); ++ c.age += 1.0; ++ return; ++ } ++ } ++ ++ if (cache.size() > max_cache_size) { ++ g_warning("cache sur-plein?"); ++ return; ++ } ++ ++ font->Ref(); ++ ++ if (cache.size() == max_cache_size) { ++ // Cache is filled, unref the oldest font in it. ++ int bi = 0; ++ double ba = cache[bi].age; ++ for (int i = 1; i < cache.size(); i++) { ++ if (cache[i].age < ba) { ++ bi = i; ++ ba = cache[bi].age; ++ } ++ } ++ cache[bi].font->Unref(); ++ cache[bi] = std::move(cache.back()); ++ cache.pop_back(); ++ } ++ ++ cache.push_back({font, 1.0}); ++ } ++ ++ // The following two commented out maps were an attempt to allow Inkscape to use font faces ++ // that could not be distinguished by CSS values alone. In practice, they never were that ++ // useful as PangoFontDescription, which is used throughout our code, cannot distinguish ++ // between faces anymore than raw CSS values (with the exception of two additional weight ++ // values). ++ // ++ // During various works, for example to handle font-family lists and fonts that are not ++ // installed on the system, the code has become less reliant on these maps. And in the work to ++ // cache style information to speed up start up times, the maps were not being filled. ++ // I've removed all code that used these maps as of Oct 2014 in the experimental branch. ++ // The commented out maps are left here as a reminder of the path that was attempted. ++ // ++ // One possible method to keep track of font faces would be to use the 'display name', keeping ++ // pointers to the appropriate PangoFontFace. The font_factory loadedFaces map indexing would ++ // have to be changed to incorporate 'display name' (InkscapeFontDescription?). ++ ++ ++ // These two maps are used for translating between what's in the UI and a pango ++ // font description. This is necessary because Pango cannot always ++ // reproduce these structures from the names it gave us in the first place. ++ ++ // Key: A string produced by font_factory::ConstructFontSpecification ++ // Value: The associated PangoFontDescription ++ // typedef std::map<Glib::ustring, PangoFontDescription *> PangoStringToDescrMap; ++ // PangoStringToDescrMap fontInstanceMap; ++ ++ // Key: Family name in UI + Style name in UI ++ // Value: The associated string that should be produced with font_factory::ConstructFontSpecification ++ // typedef std::map<Glib::ustring, Glib::ustring> UIStringToPangoStringMap; ++ // UIStringToPangoStringMap fontStringMap; ++}; + + // User must free return value. + PangoFontDescription* ink_font_description_from_style(SPStyle const *style) +@@ -86,7 +180,7 @@ PangoFontDescription* ink_font_description_from_style(SPStyle const *style) + pango_font_description_set_family(descr, style->font_family.value()); + + // This duplicates Layout::EnumConversionItem... perhaps we can share code? +- switch ( style->font_style.computed ) { ++ switch (style->font_style.computed) { + case SP_CSS_FONT_STYLE_ITALIC: + pango_font_description_set_style(descr, PANGO_STYLE_ITALIC); + break; +@@ -101,7 +195,7 @@ PangoFontDescription* ink_font_description_from_style(SPStyle const *style) + break; + } + +- switch( style->font_weight.computed ) { ++ switch (style->font_weight.computed) { + case SP_CSS_FONT_WEIGHT_100: + pango_font_description_set_weight(descr, PANGO_WEIGHT_THIN); + break; +@@ -193,7 +287,7 @@ PangoFontDescription* ink_font_description_from_style(SPStyle const *style) + break; + } + +- switch ( style->font_variant.computed ) { ++ switch (style->font_variant.computed) { + case SP_CSS_FONT_VARIANT_SMALL_CAPS: + pango_font_description_set_variant(descr, PANGO_VARIANT_SMALL_CAPS); + break; +@@ -218,12 +312,11 @@ static void noop(...) {} + //#define PANGO_DEBUG g_print + #define PANGO_DEBUG noop + +- + ///////////////////// FontFactory + // the substitute function to tell fontconfig to enforce outline fonts +-static void FactorySubstituteFunc(FcPattern *pattern,gpointer /*data*/) ++static void FactorySubstituteFunc(FcPattern *pattern, gpointer /*data*/) + { +- FcPatternAddBool(pattern, "FC_OUTLINE",FcTrue); ++ FcPatternAddBool(pattern, "FC_OUTLINE", FcTrue); + //char *fam = NULL; + //FcPatternGetString(pattern, "FC_FAMILY",0, &fam); + //printf("subst_f on %s\n",fam); +@@ -235,30 +328,22 @@ FontFactory &FontFactory::get() + return factory; + } + +-FontFactory::FontFactory() : +- nbEnt(0), // Note: this "ents" cache only keeps fonts from being unreffed, does not speed up access +- maxEnt(32), +- ents(static_cast<font_entry*>(g_malloc(maxEnt*sizeof(font_entry)))), +- fontServer(pango_ft2_font_map_new()), +- fontContext(pango_font_map_create_context(fontServer)), +- fontSize(512), +- loadedPtr(new FaceMapType()) ++FontFactory::FontFactory() ++ : fontServer(pango_ft2_font_map_new()) ++ , fontContext(pango_font_map_create_context(fontServer)) ++ , priv(std::make_unique<Private>()) + { +- pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fontServer), +- 72, 72); ++ pango_ft2_font_map_set_resolution(PANGO_FT2_FONT_MAP(fontServer), 72, 72); + #if PANGO_VERSION_CHECK(1,48,0) +- pango_fc_font_map_set_default_substitute(PANGO_FC_FONT_MAP(fontServer), ++ pango_fc_font_map_set_default_substitute(PANGO_FC_FONT_MAP(fontServer), FactorySubstituteFunc, this, nullptr); + #else +- pango_ft2_font_map_set_default_substitute(PANGO_FT2_FONT_MAP(fontServer), ++ pango_ft2_font_map_set_default_substitute(PANGO_FT2_FONT_MAP(fontServer), FactorySubstituteFunc, this, nullptr); + #endif +- FactorySubstituteFunc, +- this, +- nullptr); + } + + FontFactory::~FontFactory() + { +- // FIXME: This destructor wasn't getting called for years. It turns out enabling it causes crashes on exit. ++ // FIXME: This destructor wasn't getting called for years. It turns out after finally enabling it, it crashes. + /* + for (int i = 0;i < nbEnt;i++) ents[i].f->Unref(); + if ( ents ) g_free(ents); +@@ -289,20 +374,18 @@ Glib::ustring FontFactory::ConstructFontSpecification(PangoFontDescription *font + + PangoFontDescription *copy = pango_font_description_copy(font); + +- pango_font_description_unset_fields (copy, PANGO_FONT_MASK_SIZE); +- char * copyAsString = pango_font_description_to_string(copy); ++ pango_font_description_unset_fields(copy, PANGO_FONT_MASK_SIZE); ++ char *copyAsString = pango_font_description_to_string(copy); + pangoString = copyAsString; + g_free(copyAsString); +- copyAsString = nullptr; + + pango_font_description_free(copy); +- + } + + return pangoString; + } + +-Glib::ustring FontFactory::ConstructFontSpecification(font_instance *font) ++Glib::ustring FontFactory::ConstructFontSpecification(FontInstance *font) + { + Glib::ustring pangoString; + +@@ -322,21 +405,22 @@ Glib::ustring FontFactory::ConstructFontSpecification(font_instance *font) + * + * This function should be called in place of pango_font_description_get_family() + */ +-const char *sp_font_description_get_family(PangoFontDescription const *fontDescr) { +- ++char const *sp_font_description_get_family(PangoFontDescription const *fontDescr) ++{ + static std::map<Glib::ustring, Glib::ustring> fontNameMap; +- std::map<Glib::ustring, Glib::ustring>::iterator it; + + if (fontNameMap.empty()) { +- fontNameMap.insert(std::make_pair("Sans", "sans-serif")); +- fontNameMap.insert(std::make_pair("Serif", "serif")); +- fontNameMap.insert(std::make_pair("Monospace", "monospace")); ++ fontNameMap.emplace("Sans", "sans-serif"); ++ fontNameMap.emplace("Serif", "serif"); ++ fontNameMap.emplace("Monospace", "monospace"); + } + + const char *pangoFamily = pango_font_description_get_family(fontDescr); + +- if (pangoFamily && ((it = fontNameMap.find(pangoFamily)) != fontNameMap.end())) { +- return (it->second).c_str(); ++ if (pangoFamily) { ++ if (auto it = fontNameMap.find(pangoFamily); it != fontNameMap.end()) { ++ return it->second.c_str(); ++ } + } + + return pangoFamily; +@@ -352,7 +436,7 @@ Glib::ustring FontFactory::GetUIFamilyString(PangoFontDescription const *fontDes + // For now, keep it as family name taken from pango + const char *pangoFamily = sp_font_description_get_family(fontDescr); + +- if( pangoFamily ) { ++ if (pangoFamily) { + family = pangoFamily; + } + } +@@ -376,27 +460,22 @@ Glib::ustring FontFactory::GetUIStyleString(PangoFontDescription const *fontDesc + char *fontDescrAsString = pango_font_description_to_string(fontDescrCopy); + style = fontDescrAsString; + g_free(fontDescrAsString); +- fontDescrAsString = nullptr; + pango_font_description_free(fontDescrCopy); + } + + return style; + } + +- +-///// +- + // Calculate a Style "value" based on CSS values for ordering styles. +-static int StyleNameValue( const Glib::ustring &style ) ++static int StyleNameValue(Glib::ustring const &style) + { +- +- PangoFontDescription *pfd = pango_font_description_from_string ( style.c_str() ); ++ PangoFontDescription *pfd = pango_font_description_from_string (style.c_str()); + int value = +- pango_font_description_get_weight ( pfd ) * 1000000 + +- pango_font_description_get_style ( pfd ) * 10000 + +- pango_font_description_get_stretch( pfd ) * 100 + +- pango_font_description_get_variant( pfd ); +- pango_font_description_free ( pfd ); ++ pango_font_description_get_weight (pfd) * 1000000 + ++ pango_font_description_get_style (pfd) * 10000 + ++ pango_font_description_get_stretch(pfd) * 100 + ++ pango_font_description_get_variant(pfd); ++ pango_font_description_free (pfd); + return value; + } + +@@ -408,8 +487,7 @@ static int StyleNameValue( const Glib::ustring &style ) + + static gint StyleNameCompareInternalGlib(gconstpointer a, gconstpointer b) + { +- return( StyleNameValue( ((StyleNames *)a)->CssName ) < +- StyleNameValue( ((StyleNames *)b)->CssName ) ? -1 : 1 ); ++ return StyleNameValue(((StyleNames*)a)->CssName) < StyleNameValue(((StyleNames*)b)->CssName) ? -1 : 1; + } + + static bool ustringPairSort(std::pair<PangoFontFamily*, Glib::ustring> const& first, std::pair<PangoFontFamily*, Glib::ustring> const& second) +@@ -418,20 +496,20 @@ static bool ustringPairSort(std::pair<PangoFontFamily*, Glib::ustring> const& fi + return first.second < second.second; + } + +-void FontFactory::GetUIFamilies(std::vector<PangoFontFamily *>& out) ++void FontFactory::GetUIFamilies(std::vector<PangoFontFamily*> &out) + { + // Gather the family names as listed by Pango +- PangoFontFamily** families = nullptr; ++ PangoFontFamily **families = nullptr; + int numFamilies = 0; + pango_font_map_list_families(fontServer, &families, &numFamilies); + +- std::vector<std::pair<PangoFontFamily *, Glib::ustring> > sorted; ++ std::vector<std::pair<PangoFontFamily*, Glib::ustring>> sorted; + + // not size_t + for (int currentFamily = 0; currentFamily < numFamilies; ++currentFamily) { + const char* displayName = pango_font_family_get_name(families[currentFamily]); + +- if (displayName == nullptr || *displayName == '\0') { ++ if (!displayName || *displayName == '\0') { + std::cerr << "font_factory::GetUIFamilies: Missing displayName! " << std::endl; + continue; + } +@@ -446,18 +524,18 @@ void FontFactory::GetUIFamilies(std::vector<PangoFontFamily *>& out) + + std::sort(sorted.begin(), sorted.end(), ustringPairSort); + +- for (auto & i : sorted) { ++ for (auto &i : sorted) { + out.push_back(i.first); + } + } + +-GList* FontFactory::GetUIStyles(PangoFontFamily * in) ++GList *FontFactory::GetUIStyles(PangoFontFamily *in) + { + GList* ret = nullptr; + // Gather the styles for this family +- PangoFontFace** faces = nullptr; ++ PangoFontFace **faces = nullptr; + int numFaces = 0; +- if (in == nullptr) { ++ if (!in) { + std::cerr << "font_factory::GetUIStyles(): PangoFontFamily is NULL" << std::endl; + return ret; + } +@@ -468,9 +546,9 @@ GList* FontFactory::GetUIStyles(PangoFontFamily * in) + + // If the face has a name, describe it, and then use the + // description to get the UI family and face strings +- const gchar* displayName = pango_font_face_get_face_name(faces[currentFace]); ++ gchar const *displayName = pango_font_face_get_face_name(faces[currentFace]); + // std::cout << "Display Name: " << displayName << std::endl; +- if (displayName == nullptr || *displayName == '\0') { ++ if (!displayName || *displayName == '\0') { + std::cerr << "font_factory::GetUIStyles: Missing displayName! " << std::endl; + continue; + } +@@ -483,11 +561,11 @@ GList* FontFactory::GetUIStyles(PangoFontFamily * in) + + // Disable synthesized (faux) font faces except for CSS generic faces + if (pango_font_face_is_synthesized(faces[currentFace]) ) { +- if (familyUIName.compare( "sans-serif" ) != 0 && +- familyUIName.compare( "serif" ) != 0 && +- familyUIName.compare( "monospace" ) != 0 && +- familyUIName.compare( "fantasy" ) != 0 && +- familyUIName.compare( "cursive" ) != 0 ) { ++ if (familyUIName.compare("sans-serif") != 0 && ++ familyUIName.compare("serif" ) != 0 && ++ familyUIName.compare("monospace" ) != 0 && ++ familyUIName.compare("fantasy" ) != 0 && ++ familyUIName.compare("cursive" ) != 0 ) { + continue; + } + } +@@ -547,10 +625,9 @@ GList* FontFactory::GetUIStyles(PangoFontFamily * in) + return ret; + } + +- +-font_instance* FontFactory::FaceFromStyle(SPStyle const *style) ++FontInstance* FontFactory::FaceFromStyle(SPStyle const *style) + { +- font_instance *font = nullptr; ++ FontInstance *font = nullptr; + + g_assert(style); + +@@ -567,8 +644,7 @@ font_instance* FontFactory::FaceFromStyle(SPStyle const *style) + + // If that failed, try using the CSS information in the style + if (!font) { +- PangoFontDescription* temp_descr = +- ink_font_description_from_style(style); ++ auto temp_descr = ink_font_description_from_style(style); + font = Face(temp_descr); + pango_font_description_free(temp_descr); + } +@@ -577,18 +653,18 @@ font_instance* FontFactory::FaceFromStyle(SPStyle const *style) + return font; + } + +-font_instance *FontFactory::FaceFromDescr(char const *family, char const *style) ++FontInstance *FontFactory::FaceFromDescr(char const *family, char const *style) + { + PangoFontDescription *temp_descr = pango_font_description_from_string(style); + pango_font_description_set_family(temp_descr,family); +- font_instance *res = Face(temp_descr); ++ FontInstance *res = Face(temp_descr); + pango_font_description_free(temp_descr); + return res; + } + +-font_instance* FontFactory::FaceFromPangoString(char const *pangoString) ++FontInstance* FontFactory::FaceFromPangoString(char const *pangoString) + { +- font_instance *fontInstance = nullptr; ++ FontInstance *fontInstance = nullptr; + + g_assert(pangoString); + +@@ -599,7 +675,7 @@ font_instance* FontFactory::FaceFromPangoString(char const *pangoString) + PangoFontDescription *descr = pango_font_description_from_string(pangoString); + + if (descr) { +- if (sp_font_description_get_family(descr) != nullptr) { ++ if (sp_font_description_get_family(descr)) { + fontInstance = Face(descr); + } + pango_font_description_free(descr); +@@ -609,9 +685,9 @@ font_instance* FontFactory::FaceFromPangoString(char const *pangoString) + return fontInstance; + } + +-font_instance* FontFactory::FaceFromFontSpecification(char const *fontSpecification) ++FontInstance* FontFactory::FaceFromFontSpecification(char const *fontSpecification) + { +- font_instance *font = nullptr; ++ FontInstance *font = nullptr; + + g_assert(fontSpecification); + +@@ -625,58 +701,60 @@ font_instance* FontFactory::FaceFromFontSpecification(char const *fontSpecificat + return font; + } + +-font_instance *FontFactory::Face(PangoFontDescription *descr, bool canFail) ++FontInstance *FontFactory::Face(PangoFontDescription *descr, bool canFail) + { +- pango_font_description_set_size(descr, (int) (fontSize*PANGO_SCALE)); // mandatory huge size (hinting workaround) ++ pango_font_description_set_size(descr, fontSize * PANGO_SCALE); // Mandatory huge size (hinting workaround) + +- font_instance *res = nullptr; ++ FontInstance *res = nullptr; + +- FaceMapType& loadedFaces = *static_cast<FaceMapType*>(loadedPtr); +- if ( loadedFaces.find(descr) == loadedFaces.end() ) { +- // not yet loaded ++ if (auto it = priv->map.find(descr); it != priv->map.end()) { ++ // Already loaded. ++ res = it->second; ++ res->Ref(); ++ priv->add_in_cache(res); ++ } else { ++ // Not yet loaded. + PangoFont *nFace = nullptr; + +- // workaround for bug #1025565. +- // fonts without families blow up Pango. +- if (sp_font_description_get_family(descr) != nullptr) { +- nFace = pango_font_map_load_font(fontServer,fontContext,descr); +- } +- else { ++ // Workaround for bug #1025565: fonts without families blow up Pango. ++ if (sp_font_description_get_family(descr)) { ++ nFace = pango_font_map_load_font(fontServer, fontContext, descr); ++ } else { + g_warning("%s", _("Ignoring font without family that will crash Pango")); + } + +- if ( nFace ) { ++ if (nFace) { + // duplicate FcPattern, the hard way +- res = new font_instance(); +- // store the descr of the font we asked for, since this is the key where we intend +- // to put the font_instance at in the unordered_map. the descr of the returned ++ res = new FontInstance(); ++ // Store the descr of the font we asked for, since this is the key where we intend ++ // to put the font instance at in the unordered_map. The descr of the returned + // pangofont may differ from what was asked, so we don't know (at this + // point) whether loadedFaces[that_descr] is free or not (and overwriting +- // an entry will bring deallocation problems) ++ // an entry will bring deallocation problems). + res->descr = pango_font_description_copy(descr); + res->parent = this; + res->InstallFace(nFace); +- if ( res->pFont == nullptr ) { +- // failed to install face -> bitmap font ++ if (!res->pFont) { ++ // Failed to install face -> bitmap font + // printf("face failed\n"); + res->parent = nullptr; + delete res; + res = nullptr; +- if ( canFail ) { +- char *tc = pango_font_description_to_string(descr); +- PANGO_DEBUG("falling back from %s to 'sans-serif' because InstallFace failed\n",tc); ++ if (canFail) { ++ auto const tc = pango_font_description_to_string(descr); ++ PANGO_DEBUG("falling back from %s to 'sans-serif' because InstallFace failed\n", tc); + g_free(tc); +- pango_font_description_set_family(descr,"sans-serif"); +- res = Face(descr,false); ++ pango_font_description_set_family(descr, "sans-serif"); ++ res = Face(descr, false); + } + } else { +- loadedFaces[res->descr]=res; ++ priv->map.emplace(res->descr, res); + res->Ref(); +- AddInCache(res); ++ priv->add_in_cache(res); + } + } else { +- // no match +- if ( canFail ) { ++ // No match. ++ if (canFail) { + PANGO_DEBUG("falling back to 'sans-serif'\n"); + PangoFontDescription *new_descr = pango_font_description_new(); + pango_font_description_set_family(new_descr, "sans-serif"); +@@ -686,16 +764,12 @@ font_instance *FontFactory::Face(PangoFontDescription *descr, bool canFail) + g_critical("Could not load any face for font '%s'.", pango_font_description_to_string(descr)); + } + } +- +- } else { +- // already here +- res = loadedFaces[descr]; +- res->Ref(); +- AddInCache(res); + } ++ + if (res) { + res->InitTheFace(); + } ++ + return res; + } + +@@ -714,54 +788,18 @@ font_instance *FontFactory::Face(PangoFontDescription *descr, bool canFail) + // return res; + // } + +-void FontFactory::UnrefFace(font_instance *who) ++void FontFactory::UnrefFace(FontInstance *font) + { +- if ( who ) { +- FaceMapType& loadedFaces = *static_cast<FaceMapType*>(loadedPtr); +- +- if ( loadedFaces.find(who->descr) == loadedFaces.end() ) { +- // not found +- char *tc = pango_font_description_to_string(who->descr); +- g_warning("unrefFace %p=%s: failed\n",who,tc); +- g_free(tc); +- } else { +- loadedFaces.erase(loadedFaces.find(who->descr)); +- // printf("unrefFace %p: success\n",who); +- } +- } +-} ++ if (!font) return; + +-void FontFactory::AddInCache(font_instance *who) +-{ +- if ( who == nullptr ) return; +- for (int i = 0;i < nbEnt;i++) ents[i].age *= 0.9; +- for (int i = 0;i < nbEnt;i++) { +- if ( ents[i].f == who ) { +- // printf("present\n"); +- ents[i].age += 1.0; +- return; +- } +- } +- if ( nbEnt > maxEnt ) { +- printf("cache sur-plein?\n"); +- return; +- } +- who->Ref(); +- if ( nbEnt == maxEnt ) { // cache is filled, unref the oldest-accessed font in it +- int bi = 0; +- double ba = ents[bi].age; +- for (int i = 1;i < nbEnt;i++) { +- if ( ents[i].age < ba ) { +- bi = i; +- ba = ents[bi].age; +- } +- } +- ents[bi].f->Unref(); +- ents[bi]=ents[--nbEnt]; ++ if (auto it = priv->map.find(font->descr); it != priv->map.end()) { ++ priv->map.erase(it); ++ // printf("unrefFace %p: success\n", who); ++ } else { ++ auto const tc = pango_font_description_to_string(font->descr); ++ g_warning("unrefFace %p=%s: failed\n", font, tc); ++ g_free(tc); + } +- ents[nbEnt].f = who; +- ents[nbEnt].age = 1.0; +- nbEnt++; + } + + # ifdef _WIN32 +diff --git src/libnrtype/FontFactory.h src/libnrtype/FontFactory.h +index adc9489adde..400b588af02 100644 +--- src/libnrtype/FontFactory.h ++++ src/libnrtype/FontFactory.h +@@ -14,30 +14,16 @@ + #include <functional> + #include <algorithm> + #include <utility> ++#include <memory> + + #include <pango/pango.h> + #include "style.h" + +-/* Freetype */ + #include <pango/pangoft2.h> + #include <ft2build.h> + #include FT_FREETYPE_H + +-class font_instance; +- +-namespace Glib +-{ +- class ustring; +-} +- +-// the font_factory keeps a hashmap of all the loaded font_instances, and uses the PangoFontDescription +-// as index (nota: since pango already does that, using the PangoFont could work too) +-struct font_descr_hash : public std::unary_function<PangoFontDescription*,size_t> { +- size_t operator()(PangoFontDescription *const &x) const; +-}; +-struct font_descr_equal : public std::binary_function<PangoFontDescription*, PangoFontDescription*, bool> { +- bool operator()(PangoFontDescription *const &a, PangoFontDescription *const &b) const; +-}; ++class FontInstance; + + // Constructs a PangoFontDescription from SPStyle. Font size is not included. + // User must free return value. +@@ -47,125 +33,75 @@ PangoFontDescription* ink_font_description_from_style(SPStyle const *style); + const char *sp_font_description_get_family(PangoFontDescription const *fontDescr); + + // Class for style strings: both CSS and as suggested by font. +-class StyleNames { +- +-public: +- StyleNames() = default;; +- StyleNames( Glib::ustring name ) : +- CssName( name ), DisplayName( name ) {}; +- StyleNames( Glib::ustring cssname, Glib::ustring displayname ) : +- CssName(std::move( cssname )), DisplayName(std::move( displayname )) {}; ++struct StyleNames ++{ ++ StyleNames() = default; ++ StyleNames(Glib::ustring name) : StyleNames(name, std::move(name)) {} ++ StyleNames(Glib::ustring cssname, Glib::ustring displayname) : CssName(std::move(cssname)), DisplayName(std::move(displayname)) {}; + +-public: + Glib::ustring CssName; // Style as Pango/CSS would write it. + Glib::ustring DisplayName; // Style as Font designer named it. + }; + +-// Map type for gathering UI family and style names +-// typedef std::map<Glib::ustring, std::list<StyleNames> > FamilyToStylesMap; +- + class FontFactory + { +-public: +- /** A little cache for fonts, so that you don't loose your time looking up fonts in the font list +- * each font in the cache is refcounted once (and deref'd when removed from the cache). */ +- struct font_entry { +- font_instance *f; +- double age; +- }; +- int nbEnt; ///< Number of entries. +- int maxEnt; ///< Cache size. +- font_entry *ents; +- +- // Pango data. Backend-specific structures are cast to these opaque types. +- PangoFontMap *fontServer; +- PangoContext *fontContext; +- double fontSize; /**< The huge fontsize used as workaround for hinting. +- * Different between freetype and win32. */ +- + FontFactory(); + ~FontFactory(); + ++public: + /// Returns the font factory static instance. + static FontFactory &get(); + ++ ///< The fontsize used as workaround for hinting. ++ static constexpr double fontSize = 512; ++ ++ // Pango data. Backend-specific structures are cast to these opaque types. ++ PangoFontMap *fontServer; ++ PangoContext *fontContext; ++ + /// Constructs a pango string for use with the fontStringMap (see below) +- Glib::ustring ConstructFontSpecification(PangoFontDescription *font); +- Glib::ustring ConstructFontSpecification(font_instance *font); ++ Glib::ustring ConstructFontSpecification(PangoFontDescription *font); ++ Glib::ustring ConstructFontSpecification(FontInstance *font); + + /// Returns strings to be used in the UI for family and face (or "style" as the column is labeled) +- Glib::ustring GetUIFamilyString(PangoFontDescription const *fontDescr); +- Glib::ustring GetUIStyleString(PangoFontDescription const *fontDescr); ++ Glib::ustring GetUIFamilyString(PangoFontDescription const *fontDescr); ++ Glib::ustring GetUIStyleString(PangoFontDescription const *fontDescr); + + // Helpfully inserts all font families into the provided vector +- void GetUIFamilies(std::vector<PangoFontFamily *>& out); ++ void GetUIFamilies(std::vector<PangoFontFamily*> &out); + // Retrieves style information about a family in a newly allocated GList. +- GList* GetUIStyles(PangoFontFamily * in); ++ GList *GetUIStyles(PangoFontFamily *in); + + /// Retrieve a font_instance from a style object, first trying to use the font-specification, the CSS information +- font_instance* FaceFromStyle(SPStyle const *style); ++ FontInstance *FaceFromStyle(SPStyle const *style); + + // Various functions to get a font_instance from different descriptions. +- font_instance* FaceFromDescr(char const *family, char const *style); +- font_instance* FaceFromUIStrings(char const *uiFamily, char const *uiStyle); +- font_instance* FaceFromPangoString(char const *pangoString); +- font_instance* FaceFromFontSpecification(char const *fontSpecification); +- font_instance* Face(PangoFontDescription *descr, bool canFail=true); *** 542 LINES SKIPPED ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?202306250519.35P5JJvd016948>