git: c41b45f3bfa8 - main - graphics/inkscape: update to 1.3

From: Charlie Li <vishwin_at_FreeBSD.org>
Date: Sat, 26 Aug 2023 17:43:51 UTC
The branch main has been updated by vishwin:

URL: https://cgit.FreeBSD.org/ports/commit/?id=c41b45f3bfa8136d1ff0b58bafd4a41845b59c1c

commit c41b45f3bfa8136d1ff0b58bafd4a41845b59c1c
Author:     Charlie Li <vishwin@FreeBSD.org>
AuthorDate: 2023-08-18 10:35:43 +0000
Commit:     Charlie Li <vishwin@FreeBSD.org>
CommitDate: 2023-08-26 17:43:35 +0000

    graphics/inkscape: update to 1.3
    
    Also update math/lib2geom to 1.3, which must be updated together
    
    Release notes: https://inkscape.org/doc/release_notes/1.3/Inkscape_1.3.html
    
    - 2.5 patches included to address system macro clashes
    - DBUS option removed, now uses GDBus from GLib instead of dbus-glib
    
    Differential Revision: https://reviews.freebsd.org/D41503
---
 graphics/inkscape/Makefile                         |   35 +-
 graphics/inkscape/distinfo                         |   20 +-
 .../patch-362f987096833dd1dfa223be82fc6a97c3795f6c | 1456 --------------------
 graphics/inkscape/files/patch-src_helper_geom.h    |   11 +
 .../patch-src_object_algorithms_graphlayout.cpp    |   10 -
 graphics/inkscape/pkg-plist                        |  443 ++++--
 math/lib2geom/Makefile                             |   33 +-
 math/lib2geom/distinfo                             |    6 +-
 math/lib2geom/pkg-plist                            |    2 +-
 9 files changed, 415 insertions(+), 1601 deletions(-)

diff --git a/graphics/inkscape/Makefile b/graphics/inkscape/Makefile
index c034ed336a68..5a8fc572d682 100644
--- a/graphics/inkscape/Makefile
+++ b/graphics/inkscape/Makefile
@@ -1,17 +1,11 @@
 PORTNAME=	inkscape
-DISTVERSION=	1.2.2
-PORTREVISION=	12
+DISTVERSION=	1.3
 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
+PATCHFILES+=	3db96bfbac475022a32b70473b767b21a8d70c7f.patch:-p1 # https://gitlab.com/inkscape/inkscape/-/issues/4427
+PATCHFILES+=	00851fede7f9162cbcacf81258d1dda823b88a5c.patch:-p1 # https://gitlab.com/inkscape/inkscape/-/merge_requests/5650
 
 MAINTAINER=	gnome@FreeBSD.org
 COMMENT=	Full featured open source SVG editor
@@ -28,10 +22,10 @@ LICENSE_FILE_LGPL3  =	${WRKSRC}/LICENSES/LGPL-3.0.txt
 LICENSE_FILE_LGPL3+ =	${WRKSRC}/LICENSES/LGPL-3.0-or-later.txt
 LICENSE_FILE_MPL11  =	${WRKSRC}/LICENSES/MPL-1.1.txt
 
+BUILD_DEPENDS=	ragel:devel/ragel
 LIB_DEPENDS=	libboost_filesystem.so:devel/boost-libs \
 		libpopt.so:devel/popt \
 		libgc.so:devel/boehm-gc \
-		libgdl-3.so:x11-toolkits/gdl \
 		libgsl.so:math/gsl \
 		liblcms2.so:graphics/lcms2 \
 		libfribidi.so:converters/fribidi \
@@ -43,6 +37,8 @@ LIB_DEPENDS=	libboost_filesystem.so:devel/boost-libs \
 		libsoup-2.4.so:devel/libsoup \
 		libyaml.so:textproc/libyaml \
 		libdouble-conversion.so:devel/double-conversion \
+		libenchant-2.so:textproc/enchant2 \
+		libepoxy.so:graphics/libepoxy \
 		lib2geom.so:math/lib2geom
 RUN_DEPENDS=	${PYNUMPY} \
 		${PYTHON_PKGNAMEPREFIX}appdirs>0:devel/py-appdirs@${PY_FLAVOR} \
@@ -53,22 +49,25 @@ RUN_DEPENDS=	${PYNUMPY} \
 		${PYTHON_PKGNAMEPREFIX}cssselect>0:www/py-cssselect@${PY_FLAVOR} \
 		${PYTHON_PKGNAMEPREFIX}requests>0:www/py-requests@${PY_FLAVOR} \
 		fig2dev:print/fig2dev
+TEST_DEPENDS=	googletest>0:devel/googletest \
+		bash:shells/bash
 
-USES=		compiler:c++17-lang cmake cpe desktop-file-utils ghostscript:run \
+USES=		compiler:c++17-lang cmake:testing cpe desktop-file-utils ghostscript:run \
 		gnome iconv:wchar_t jpeg pathfix pkgconfig python \
 		readline shebangfix tar:xz xorg
-USE_GNOME=	gdkpixbuf2 gtkmm30 libxml2 libxslt
+USE_GNOME=	cairo gdkpixbuf2 gtkmm30 gtksourceview4 libxml2 libxslt
+USE_PYTHON=	cython
 USE_XORG=	sm ice x11 xext
 USE_LDCONFIG=	yes
 
-DATETAG=	2022-12-01_b0a8486541
-
+DATETAG=	2023-07-21_0e150ed6c4
 WRKSRC=		${WRKDIR}/${PORTNAME}-${DISTVERSION}_${DATETAG}
 
+BINARY_ALIAS=	python3=${PYTHON_CMD}
 SHEBANG_FILES=	share/extensions/*.py share/extensions/genpofiles.sh \
 		share/templates/*.py man/fix-roff-punct
 
-OPTIONS_DEFINE=		OPENMP POPPLER SCRIBUS VISIO CDR DBUS WPG GVFS NLS GSPELL
+OPTIONS_DEFINE=		OPENMP POPPLER SCRIBUS VISIO CDR WPG GVFS NLS GSPELL
 OPTIONS_DEFAULT=	POPPLER VISIO CDR WPG GM GSPELL
 OPTIONS_DEFAULT_amd64=	OPENMP
 OPTIONS_DEFAULT_powerpc64=	OPENMP
@@ -82,10 +81,6 @@ CDR_CMAKE_BOOL=		WITH_LIBCDR
 CDR_LIB_DEPENDS=	librevenge-stream-0.0.so:textproc/librevenge \
 			libcdr-0.1.so:graphics/libcdr01
 
-DBUS_CMAKE_BOOL=	WITH_DBUS
-DBUS_LIB_DEPENDS=	libdbus-glib-1.so:devel/dbus-glib \
-			libdbus-1.so:devel/dbus
-
 GVFS_USE=		GNOME=gvfs
 
 OPENMP_CMAKE_BOOL=	WITH_OPENMP
@@ -119,7 +114,7 @@ NLS_CMAKE_BOOL=		WITH_NLS
 NLS_USES=		gettext
 
 GSPELL_DESC=		Support for spell checking through gspell
-GSPELL_CMAKE_BOOL= 	WITH_GSPELL
+GSPELL_CMAKE_BOOL=	WITH_GSPELL
 GSPELL_LIB_DEPENDS=	libgspell-1.so:textproc/gspell
 
 post-patch:
diff --git a/graphics/inkscape/distinfo b/graphics/inkscape/distinfo
index d6bdd134d472..5ba7f41d16ee 100644
--- a/graphics/inkscape/distinfo
+++ b/graphics/inkscape/distinfo
@@ -1,13 +1,7 @@
-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
+TIMESTAMP = 1692891317
+SHA256 (inkscape-1.3.tar.xz) = bf4f286b025e0169b8948cc14d5199a9b4c204d761c894c4b48496571ec76307
+SIZE (inkscape-1.3.tar.xz) = 85764028
+SHA256 (3db96bfbac475022a32b70473b767b21a8d70c7f.patch) = fb572fa3b566149293b0ffeae468ff6025d0e54a090d928eb8c2037afe2d3f8d
+SIZE (3db96bfbac475022a32b70473b767b21a8d70c7f.patch) = 2003
+SHA256 (00851fede7f9162cbcacf81258d1dda823b88a5c.patch) = d0ebfcb85682345d7e10d97931894acd171881a8467b70a777f37a293d255a59
+SIZE (00851fede7f9162cbcacf81258d1dda823b88a5c.patch) = 5207
diff --git a/graphics/inkscape/files/patch-362f987096833dd1dfa223be82fc6a97c3795f6c b/graphics/inkscape/files/patch-362f987096833dd1dfa223be82fc6a97c3795f6c
deleted file mode 100644
index 544a99b89eea..000000000000
--- a/graphics/inkscape/files/patch-362f987096833dd1dfa223be82fc6a97c3795f6c
+++ /dev/null
@@ -1,1456 +0,0 @@
-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.
*** 2052 LINES SKIPPED ***