From nobody Sat Aug 26 17:43:51 2023 X-Original-To: dev-commits-ports-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4RY41g47CWz4qnVv; Sat, 26 Aug 2023 17:43:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4RY41g3XXMz3gfH; Sat, 26 Aug 2023 17:43:51 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1693071831; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nR0WT2af5Q1dICV9bebDQ46K1RB9WkCvH9UBXjVedF4=; b=lpf4Ze0RRIjQZbl6RZcB6XQsk48427O+tGhrmV+9F2MWX5QDKjLOhp5vuEQQ84UGkGusES 1cxi7QM7KqnKv+h/dNccAyFzMz64ZgeCG839lQHpQ8gGZJTqaqPPwfLrkBIAJsGM+8zJv7 MIwQnIFjOPJXvoaYM3TsmwyFkistm+09w78xXdMHBTHVvaUZn2TYcgV1Xy95jgV3NVDGR5 IoyJ5hSNKSK+sy4Qj8wxR413/J40RGZwRdD6lsenBO6F3E0/WnBk/v0MnFlSGDrkSffuWi PTPPbaq7ZnBuAOYdtP3k4t/Qh1SjK0UyvjQujIli3SXlXx3j2Ub1g+I8B2gIPg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1693071831; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nR0WT2af5Q1dICV9bebDQ46K1RB9WkCvH9UBXjVedF4=; b=I9tLL5Y/KybSD//65eMan5ouvx19K8JQqPlVSVAZpoTj38G/LpWDVKiL62nDr1IPeAuz0a HShuuX70pyvW03akB43/pewUvG0dhPaD45PoJhy/pd1mzXpMLopus1KT+zCWx4aEM9mze/ x7kToGfdj7wzFg0Si5MVkXyxppgXF0sjKtPfFUn+HbP9ahAUtimEoaWYUBrAYhJ7lLzAII nZ322ZKDtYYUj0uwOny1YWw3zKJlWcz+Aqb+R0H6Yxzuq/6U8OrS2KQIlQ4zXC9ZZZ3nEi 7dUxEKUpuh7KlGqXL0iwzczCPEhgCHLNihJmqMxRY3xn9cb1FXlFpTs8Ir2hGA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1693071831; a=rsa-sha256; cv=none; b=OLN93LdUGafFyUieMWTHvSQPfPejLnJiisp8UN4x+IqNGH5cDbsan8ybrq0M5MK5y57HAD QG9+MmAgHUBj0fPBIqgcXA0X17gbCYH1CSAvw3vcBsN3J+usbDyB0V3H4Alw9LjbXuRl40 kq8Fx9K7a5THOWkjX+V5X7sAuMknv5/y0v+P0XRy7s8vZw3UAJXAHgYlut8odmGbgGsDPF Ukuo3aXAMgygc8kuisjKX26A0MAPXzZbnnE+uQHvKvn9/9DhQLwAAM/WuNT3GyLuVIMYpo A1hqmFcGPGKG3tR83bixwZeMAmP4oDctF+Xjgq2cBUTZ/4fKq8mmbd0Ajo5zIw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4RY41g2bwkzkvJ; Sat, 26 Aug 2023 17:43:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 37QHhpKf014416; Sat, 26 Aug 2023 17:43:51 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 37QHhpFe014412; Sat, 26 Aug 2023 17:43:51 GMT (envelope-from git) Date: Sat, 26 Aug 2023 17:43:51 GMT Message-Id: <202308261743.37QHhpFe014412@gitrepo.freebsd.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org From: Charlie Li Subject: git: c41b45f3bfa8 - main - graphics/inkscape: update to 1.3 List-Id: Commit messages for all branches of the ports repository List-Archive: https://lists.freebsd.org/archives/dev-commits-ports-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-ports-all@freebsd.org X-BeenThere: dev-commits-ports-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: vishwin X-Git-Repository: ports X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: c41b45f3bfa8136d1ff0b58bafd4a41845b59c1c Auto-Submitted: auto-generated The branch main has been updated by vishwin: URL: https://cgit.FreeBSD.org/ports/commit/?id=c41b45f3bfa8136d1ff0b58bafd4a41845b59c1c commit c41b45f3bfa8136d1ff0b58bafd4a41845b59c1c Author: Charlie Li AuthorDate: 2023-08-18 10:35:43 +0000 Commit: Charlie Li 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 -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 - #include -- - #endif - --typedef std::unordered_map 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 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 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 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 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(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()) - { -- 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 fontNameMap; -- std::map::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 const& first, std::pair const& second) -@@ -418,20 +496,20 @@ static bool ustringPairSort(std::pair const& fi - return first.second < second.second; - } - --void FontFactory::GetUIFamilies(std::vector& out) -+void FontFactory::GetUIFamilies(std::vector &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 > sorted; -+ std::vector> 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& 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(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(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 - #include - #include -+#include - - #include - #include "style.h" - --/* Freetype */ - #include - #include - #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 { -- size_t operator()(PangoFontDescription *const &x) const; --}; --struct font_descr_equal : public std::binary_function { -- 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 ***