git: fe6320a394de - main - graphics/inkscape: partially pull in two upstream changes

From: Charlie Li <vishwin_at_FreeBSD.org>
Date: Sun, 25 Jun 2023 05:19:19 UTC
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 ***