summaryrefslogtreecommitdiffstats
path: root/snap
diff options
context:
space:
mode:
Diffstat (limited to 'snap')
-rw-r--r--snap/README.md10
-rwxr-xr-xsnap/hooks/configure14
-rw-r--r--snap/local/filedialog-native.patch385
-rw-r--r--snap/local/glib-spawn-no-close.patch16
-rw-r--r--snap/local/print-inkscape-version.cpp42
-rwxr-xr-xsnap/local/scripts/inkscape-variables30
-rwxr-xr-xsnap/local/scripts/private-fontcache42
-rw-r--r--snap/snapcraft.yaml229
8 files changed, 768 insertions, 0 deletions
diff --git a/snap/README.md b/snap/README.md
new file mode 100644
index 0000000..baa681f
--- /dev/null
+++ b/snap/README.md
@@ -0,0 +1,10 @@
+Snap
+====
+
+This directory and `../snappy/` are used for building the snap (https://snapcraft.io/) package of Inkscape.
+
+Each commit to master sends a new build to the "edge" version.
+
+For build status and logs, see https://launchpad.net/~ted/+snap/inkscape-master. That account on launchpad.net is owned by Ted Gould <ted@gould.cx>.
+
+If the snap does no longer build or run, the most probable reason is that we added a new dependency. Have a look at the recent changes in https://gitlab.com/inkscape/inkscape-ci-docker, and try to make a similar change to `build-packages` (build dependency) or `stage-packages` (runtime dependency) in `snapcraft.yaml`.
diff --git a/snap/hooks/configure b/snap/hooks/configure
new file mode 100755
index 0000000..c9bdc26
--- /dev/null
+++ b/snap/hooks/configure
@@ -0,0 +1,14 @@
+#!/bin/sh -e
+# Small hook to build a system font cache in the Snap's system directory
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+mkdir -p $SNAP_DATA/fontconfig
+
+echo "<fontconfig>" > ${SNAP_DATA}/fontconfig/fonts.conf
+echo "<cachedir>${SNAP_DATA}/fontconfig</cachedir>" >> ${SNAP_DATA}/fontconfig/fonts.conf
+echo "<include ignore_missing=\"yes\">/etc/fonts/fonts.conf</include>" >> ${SNAP_DATA}/fontconfig/fonts.conf
+echo "</fontconfig>" >> ${SNAP_DATA}/fontconfig/fonts.conf
+
+export FONTCONFIG_FILE=${SNAP_DATA}/fontconfig/fonts.conf
+
+exec ${SNAP}/snap/command-chain/snapcraft-runner ${SNAP}/usr/bin/fc-cache --force --system-only --verbose
diff --git a/snap/local/filedialog-native.patch b/snap/local/filedialog-native.patch
new file mode 100644
index 0000000..ce82d92
--- /dev/null
+++ b/snap/local/filedialog-native.patch
@@ -0,0 +1,385 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Taken from: https://gitlab.com/inkscape/inkscape/-/merge_requests/4237
+# And used only for the snap currently.
+diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp
+index c3aba062dd963e72ec775bd9a2e3a753bf08ee0f..19203350bb3bae36e9157e538a0889b4c1de5a78 100644
+--- a/src/ui/dialog/filedialogimpl-gtkmm.cpp
++++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp
+@@ -78,41 +78,26 @@ void fileDialogExtensionToPattern(Glib::ustring &pattern, Glib::ustring &extensi
+ }
+ }
+
++/*#########################################################################
++### F I L E D I A L O G B A S E C L A S S
++#########################################################################*/
+
+-void findEntryWidgets(Gtk::Container *parent, std::vector<Gtk::Entry *> &result)
++// Small function so the translatable strings stay out of the header
++const char * FileDialogBaseGtk::accept_label(Gtk::FileChooserAction dialogType)
+ {
+- if (!parent) {
+- return;
+- }
+- std::vector<Gtk::Widget *> children = parent->get_children();
+- for (auto child : children) {
+- GtkWidget *wid = child->gobj();
+- if (GTK_IS_ENTRY(wid))
+- result.push_back(dynamic_cast<Gtk::Entry *>(child));
+- else if (GTK_IS_CONTAINER(wid))
+- findEntryWidgets(dynamic_cast<Gtk::Container *>(child), result);
++ if (dialogType == Gtk::FILE_CHOOSER_ACTION_OPEN) {
++ return _("_Open");
++ } else {
++ return _("_Save");
+ }
+ }
+
+-void findExpanderWidgets(Gtk::Container *parent, std::vector<Gtk::Expander *> &result)
++// Small function so the translatable strings stay out of the header
++const char * FileDialogBaseGtk::cancel_label()
+ {
+- if (!parent)
+- return;
+- std::vector<Gtk::Widget *> children = parent->get_children();
+- for (auto child : children) {
+- GtkWidget *wid = child->gobj();
+- if (GTK_IS_EXPANDER(wid))
+- result.push_back(dynamic_cast<Gtk::Expander *>(child));
+- else if (GTK_IS_CONTAINER(wid))
+- findExpanderWidgets(dynamic_cast<Gtk::Container *>(child), result);
+- }
++ return _("_Cancel");
+ }
+
+-
+-/*#########################################################################
+-### F I L E D I A L O G B A S E C L A S S
+-#########################################################################*/
+-
+ void FileDialogBaseGtk::internalSetup()
+ {
+ // Open executable file dialogs don't need the preview panel
+@@ -126,11 +111,15 @@ void FileDialogBaseGtk::internalSetup()
+
+ previewCheckbox.signal_toggled().connect(sigc::mem_fun(*this, &FileDialogBaseGtk::_updatePreviewCallback));
+
++ previewCheckbox.show();
++
+ svgexportCheckbox.set_label(Glib::ustring(_("Export as SVG 1.1 per settings in Preferences dialog")));
+ svgexportCheckbox.set_active(enableSVGExport);
+
+ svgexportCheckbox.signal_toggled().connect(sigc::mem_fun(*this, &FileDialogBaseGtk::_svgexportEnabledCB));
+
++ svgexportCheckbox.show();
++
+ // Catch selection-changed events, so we can adjust the text widget
+ signal_update_preview().connect(sigc::mem_fun(*this, &FileDialogBaseGtk::_updatePreviewCallback));
+
+@@ -220,7 +209,7 @@ FileOpenDialogImplGtk::FileOpenDialogImplGtk(Gtk::Window &parentWindow, const Gl
+
+
+ /* Set the pwd and/or the filename */
+- if (dir.size() > 0) {
++ if (dir.size() > 0 && Glib::getenv("GTK_USE_PORTAL").empty()) {
+ Glib::ustring udir(dir);
+ Glib::ustring::size_type len = udir.length();
+ // leaving a trailing backslash on the directory name leads to the infamous
+@@ -241,9 +230,6 @@ FileOpenDialogImplGtk::FileOpenDialogImplGtk(Gtk::Window &parentWindow, const Gl
+ //###### Add the file types menu
+ createFilterMenu();
+
+- add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
+- set_default(*add_button(_("_Open"), Gtk::RESPONSE_OK));
+-
+ //###### Allow easy access to our examples folder
+
+ using namespace Inkscape::IO::Resource;
+@@ -372,12 +358,11 @@ void FileOpenDialogImplGtk::createFilterMenu()
+ bool FileOpenDialogImplGtk::show()
+ {
+ set_modal(TRUE); // Window
+- sp_transientize(GTK_WIDGET(gobj())); // Make transient
+ gint b = run(); // Dialog
+ svgPreview.showNoPreview();
+ hide();
+
+- if (b == Gtk::RESPONSE_OK) {
++ if (b == Gtk::RESPONSE_ACCEPT) {
+ // This is a hack, to avoid the warning messages that
+ // Gtk::FileChooser::get_filter() returns
+ // should be: Gtk::FileFilter *filter = get_filter();
+@@ -511,37 +496,18 @@ FileSaveDialogImplGtk::FileSaveDialogImplGtk(Gtk::Window &parentWindow, const Gl
+
+ childBox.pack_start(checksBox);
+ childBox.pack_end(fileTypeComboBox);
++ childBox.show();
++
+ checksBox.pack_start(fileTypeCheckbox);
+ checksBox.pack_start(previewCheckbox);
+ checksBox.pack_start(svgexportCheckbox);
++ checksBox.show();
+
+ set_extra_widget(childBox);
+
+- // Let's do some customization
+- fileNameEntry = nullptr;
+- Gtk::Container *cont = get_toplevel();
+- std::vector<Gtk::Entry *> entries;
+- findEntryWidgets(cont, entries);
+- // g_message("Found %d entry widgets\n", entries.size());
+- if (!entries.empty()) {
+- // Catch when user hits [return] on the text field
+- fileNameEntry = entries[0];
+- fileNameEntry->signal_activate().connect(
+- sigc::mem_fun(*this, &FileSaveDialogImplGtk::fileNameEntryChangedCallback));
+- }
+ signal_selection_changed().connect(
+ sigc::mem_fun(*this, &FileSaveDialogImplGtk::fileNameChanged));
+
+- // Let's do more customization
+- std::vector<Gtk::Expander *> expanders;
+- findExpanderWidgets(cont, expanders);
+- // g_message("Found %d expander widgets\n", expanders.size());
+- if (!expanders.empty()) {
+- // Always show the file list
+- Gtk::Expander *expander = expanders[0];
+- expander->set_expanded(true);
+- }
+-
+ // allow easy access to the user's own templates folder
+ using namespace Inkscape::IO::Resource;
+ char const *templates = Inkscape::IO::Resource::get_path(USER, TEMPLATES);
+@@ -549,14 +515,6 @@ FileSaveDialogImplGtk::FileSaveDialogImplGtk(Gtk::Window &parentWindow, const Gl
+ Inkscape::IO::file_test(templates, G_FILE_TEST_IS_DIR) && g_path_is_absolute(templates)) {
+ add_shortcut_folder(templates);
+ }
+-
+- // if (extension == NULL)
+- // checkbox.set_sensitive(FALSE);
+-
+- add_button(_("_Cancel"), Gtk::RESPONSE_CANCEL);
+- set_default(*add_button(_("_Save"), Gtk::RESPONSE_OK));
+-
+- show_all_children();
+ }
+
+ /**
+@@ -566,44 +524,7 @@ FileSaveDialogImplGtk::~FileSaveDialogImplGtk()
+ = default;
+
+ /**
+- * Callback for fileNameEntry widget
+- */
+-void FileSaveDialogImplGtk::fileNameEntryChangedCallback()
+-{
+- if (!fileNameEntry)
+- return;
+-
+- Glib::ustring fileName = fileNameEntry->get_text();
+- if (!Glib::get_charset()) // If we are not utf8
+- fileName = Glib::filename_to_utf8(fileName);
+-
+- // g_message("User hit return. Text is '%s'\n", fileName.c_str());
+-
+- if (!Glib::path_is_absolute(fileName)) {
+- // try appending to the current path
+- // not this way: fileName = get_current_folder() + "/" + fileName;
+- std::vector<Glib::ustring> pathSegments;
+- pathSegments.emplace_back(get_current_folder());
+- pathSegments.push_back(fileName);
+- fileName = Glib::build_filename(pathSegments);
+- }
+-
+- // g_message("path:'%s'\n", fileName.c_str());
+-
+- if (Glib::file_test(fileName, Glib::FILE_TEST_IS_DIR)) {
+- set_current_folder(fileName);
+- } else if (/*Glib::file_test(fileName, Glib::FILE_TEST_IS_REGULAR)*/ true) {
+- // dialog with either (1) select a regular file or (2) cd to dir
+- // simulate an 'OK'
+- set_filename(fileName);
+- response(Gtk::RESPONSE_OK);
+- }
+-}
+-
+-
+-
+-/**
+- * Callback for fileNameEntry widget
++ * Callback for fileType widget changing
+ */
+ void FileSaveDialogImplGtk::fileTypeChangedCallback()
+ {
+@@ -649,6 +570,10 @@ void FileSaveDialogImplGtk::addFileType(Glib::ustring name, Glib::ustring patter
+ fileTypeComboBox.append(guessType.name);
+ fileTypes.push_back(guessType);
+
++ auto filter = Gtk::FileFilter::create();
++ filter->set_name(guessType.name);
++ filter->add_pattern(guessType.pattern);
++ add_filter(filter);
+
+ fileTypeComboBox.set_active(0);
+ fileTypeChangedCallback(); // call at least once to set the filter
+@@ -656,8 +581,13 @@ void FileSaveDialogImplGtk::addFileType(Glib::ustring name, Glib::ustring patter
+
+ void FileSaveDialogImplGtk::createFilterMenu()
+ {
++ if (_dialogType == CUSTOM_TYPE) {
++ return;
++ }
++
+ Inkscape::Extension::DB::OutputList extension_list;
+ Inkscape::Extension::db.get_output_list(extension_list);
++
+ knownExtensions.clear();
+
+ bool is_raster = _dialogType == RASTER_TYPES;
+@@ -680,6 +610,11 @@ void FileSaveDialogImplGtk::createFilterMenu()
+ type.extension = omod;
+ fileTypeComboBox.append(type.name);
+ fileTypes.push_back(type);
++
++ auto filter = Gtk::FileFilter::create();
++ filter->set_name(type.name);
++ filter->add_pattern(type.pattern);
++ add_filter(filter);
+ }
+
+ //#Let user choose
+@@ -690,6 +625,10 @@ void FileSaveDialogImplGtk::createFilterMenu()
+ fileTypeComboBox.append(guessType.name);
+ fileTypes.push_back(guessType);
+
++ auto filter = Gtk::FileFilter::create();
++ filter->set_name(guessType.name);
++ filter->add_pattern(guessType.pattern);
++ add_filter(filter);
+
+ fileTypeComboBox.set_active(0);
+ fileTypeChangedCallback(); // call at least once to set the filter
+@@ -704,13 +643,12 @@ bool FileSaveDialogImplGtk::show()
+ {
+ change_path(myFilename);
+ set_modal(TRUE); // Window
+- sp_transientize(GTK_WIDGET(gobj())); // Make transient
+ gint b = run(); // Dialog
+ svgPreview.showNoPreview();
+ set_preview_widget_active(false);
+ hide();
+
+- if (b == Gtk::RESPONSE_OK) {
++ if (b == Gtk::RESPONSE_ACCEPT) {
+ updateNameAndExtension();
+ Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+
+@@ -799,6 +737,11 @@ FileSaveDialogImplGtk::change_title(const Glib::ustring& title)
+ */
+ void FileSaveDialogImplGtk::change_path(const Glib::ustring &path)
+ {
++ if (!Glib::getenv("GTK_USE_PORTAL").empty()) {
++ // If we're using the portal we can't control the path
++ return;
++ }
++
+ myFilename = path;
+
+ if (Glib::file_test(myFilename, Glib::FILE_TEST_IS_DIR)) {
+@@ -842,6 +785,27 @@ void FileSaveDialogImplGtk::updateNameAndExtension()
+ myFilename = tmp;
+ }
+
++ if (!Glib::getenv("GTK_USE_PORTAL").empty()) {
++ // If we're using the portal we can't change the filename
++ // and we need to use the filter to find the extension
++ GtkFileChooser *gtkFileChooser = Gtk::FileChooser::gobj();
++ GtkFileFilter *filter = gtk_file_chooser_get_filter(gtkFileChooser);
++
++ extension = nullptr;
++ if (filter) {
++ auto name = gtk_file_filter_get_name(filter);
++
++ for (auto type : fileTypes) {
++ if (type.name == name) {
++ extension = type.extension;
++ break;
++ }
++ }
++ }
++
++ return;
++ }
++
+ Inkscape::Extension::Output *newOut = extension ? dynamic_cast<Inkscape::Extension::Output *>(extension) : nullptr;
+ if (fileTypeCheckbox.get_active() && newOut) {
+ // Append the file extension if it's not already present and display it in the file name entry field
+diff --git a/src/ui/dialog/filedialogimpl-gtkmm.h b/src/ui/dialog/filedialogimpl-gtkmm.h
+index b16d36285c300d1c423e1e75f3260baaf8276b2b..8fde5824ab79f04115441bded47550aebab2ebea 100644
+--- a/src/ui/dialog/filedialogimpl-gtkmm.h
++++ b/src/ui/dialog/filedialogimpl-gtkmm.h
+@@ -49,14 +49,6 @@ void
+ fileDialogExtensionToPattern(Glib::ustring &pattern,
+ Glib::ustring &extension);
+
+-void
+-findEntryWidgets(Gtk::Container *parent,
+- std::vector<Gtk::Entry *> &result);
+-
+-void
+-findExpanderWidgets(Gtk::Container *parent,
+- std::vector<Gtk::Expander *> &result);
+-
+ class FileType
+ {
+ public:
+@@ -75,7 +67,7 @@ class FileType
+ * This class is the base implementation for the others. This
+ * reduces redundancies and bugs.
+ */
+-class FileDialogBaseGtk : public Gtk::FileChooserDialog
++class FileDialogBaseGtk : public Gtk::FileChooserNative
+ {
+ public:
+
+@@ -84,19 +76,7 @@ public:
+ */
+ FileDialogBaseGtk(Gtk::Window& parentWindow, const Glib::ustring &title,
+ Gtk::FileChooserAction dialogType, FileDialogType type, gchar const* preferenceBase) :
+- Gtk::FileChooserDialog(parentWindow, title, dialogType),
+- preferenceBase(preferenceBase ? preferenceBase : "unknown"),
+- _dialogType(type)
+- {
+- internalSetup();
+- }
+-
+- /**
+- *
+- */
+- FileDialogBaseGtk(Gtk::Window& parentWindow, const char *title,
+- Gtk::FileChooserAction dialogType, FileDialogType type, gchar const* preferenceBase) :
+- Gtk::FileChooserDialog(parentWindow, title, dialogType),
++ Gtk::FileChooserNative(title, parentWindow, dialogType, accept_label(dialogType), cancel_label()),
+ preferenceBase(preferenceBase ? preferenceBase : "unknown"),
+ _dialogType(type)
+ {
+@@ -130,6 +110,9 @@ protected:
+ Gtk::CheckButton svgexportCheckbox;
+
+ private:
++ const char * accept_label(Gtk::FileChooserAction dialogType);
++ const char * cancel_label();
++
+ void internalSetup();
+
+ /**
+@@ -281,9 +264,8 @@ private:
+ Inkscape::Extension::Extension *extension;
+
+ /**
+- * Callback for user input into fileNameEntry
++ * Callback for file name changed
+ */
+- void fileNameEntryChangedCallback();
+ void fileNameChanged();
+ bool fromCB;
+ };
diff --git a/snap/local/glib-spawn-no-close.patch b/snap/local/glib-spawn-no-close.patch
new file mode 100644
index 0000000..c17900e
--- /dev/null
+++ b/snap/local/glib-spawn-no-close.patch
@@ -0,0 +1,16 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+# Disable closing file descriptors because the snap confinement has some
+# that it doesn't want us to close
+diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp
+index 0d0a07e4b4..d94774868e 100644
+--- a/src/extension/implementation/script.cpp
++++ b/src/extension/implementation/script.cpp
+@@ -904,7 +904,7 @@ int Script::execute (const std::list<std::string> &in_command,
+ try {
+ Glib::spawn_async_with_pipes(working_directory, // working directory
+ argv, // arg v
+- static_cast<Glib::SpawnFlags>(0), // no flags
++ Glib::SPAWN_LEAVE_DESCRIPTORS_OPEN,
+ sigc::slot<void>(),
+ &_pid, // Pid
+ nullptr, // STDIN
diff --git a/snap/local/print-inkscape-version.cpp b/snap/local/print-inkscape-version.cpp
new file mode 100644
index 0000000..17d0c17
--- /dev/null
+++ b/snap/local/print-inkscape-version.cpp
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Use the Inkscape compiled version identifier and print it out with
+// the Snap restrictions on versions. Only a few characters allowed
+// and a limit of 32 characters.
+#include "inkscape-version.h"
+
+#include <iostream>
+#include <cctype>
+
+int main (int argc, char ** argv) {
+ std::string outstr;
+
+ for (const auto& c : std::string{Inkscape::version_string}) {
+ if (outstr.length() == 32) {
+ break;
+ }
+
+ if (std::isalpha(c) || std::isdigit(c)) {
+ outstr.append(1, c);
+ continue;
+ }
+
+ if (c == '(' || c == ')' || c == ',') {
+ continue;
+ }
+
+ if (c == '.' || c == '-') {
+ outstr.append(1, c);
+ continue;
+ }
+
+ outstr.append(1, '-');
+ }
+
+ while (outstr.length() > 0 && !std::isalpha(outstr.back()) && !std::isdigit(outstr.back())) {
+ outstr.pop_back();
+ }
+
+ std::cout << outstr << std::endl;
+
+ return 0;
+}
diff --git a/snap/local/scripts/inkscape-variables b/snap/local/scripts/inkscape-variables
new file mode 100755
index 0000000..1c8d456
--- /dev/null
+++ b/snap/local/scripts/inkscape-variables
@@ -0,0 +1,30 @@
+#!/bin/bash
+# Set all the Inkscape specific environment variables
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# If we're on an older snapd that doesn't have SNAP_REAL_HOME try
+# to fake it
+if [ -z $SNAP_REAL_HOME ]; then
+SNAP_REAL_HOME=`getent passwd $UID | cut -d ':' -f 6`
+# fallback to pre-1.2 behaviour in case getent doesn't work due to apparmor
+# could suggest to install unscd to proxy requests to blocked nss module
+SNAP_REAL_HOME=${SNAP_REAL_HOME:-${SNAP_USER_DATA}/../../..}
+fi
+
+export INKSCAPE_PROFILE_DIR=${SNAP_REAL_HOME}/.config/inkscape
+export INKSCAPE_LOCALEDIR=${SNAP}/share/locale
+export INKSCAPE_DATADIR=${SNAP}/share
+export INKSCAPE_EXTENSIONS_DIR=${SNAP_USER_COMMON}/extensions/
+
+export GTK_USE_PORTAL=1
+
+export GS_LIB=${SNAP}/usr/share/ghostscript/9.55.0/Resource/Init/
+if [ ! -x ${GS_LIB} ]; then
+ echo "WARN: Ghostscript library not executable: $GS_LIB"
+fi
+
+export PYTHONPATH=/usr/lib/python3.10:/usr/lib/python3.10/lib-dynload:${SNAP}/lib/python3.10/site-packages:${SNAP}/usr/lib/python3/dist-packages
+
+cd $SNAP_REAL_HOME
+
+exec "$@"
diff --git a/snap/local/scripts/private-fontcache b/snap/local/scripts/private-fontcache
new file mode 100755
index 0000000..e85623d
--- /dev/null
+++ b/snap/local/scripts/private-fontcache
@@ -0,0 +1,42 @@
+#!/bin/bash
+# Ensure that we prioritize using the private font cache
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+# ensure_dir_exists calls `mkdir -p` if the given path is not a directory.
+# This speeds up execution time by avoiding unnecessary calls to mkdir.
+#
+# Usage: ensure_dir_exists <path> [<mkdir-options>]...
+function ensure_dir_exists() {
+ [ -d "$1" ] || mkdir -p "$@"
+}
+
+# Set $REALHOME to the users real home directory
+REALHOME=$(getent passwd $UID | cut -d ':' -f 6)
+# fallback to pre-1.2 behaviour in case getent doesn't work due to apparmor
+# could suggest to install unscd to proxy requests to blocked nss module
+REALHOME=${REALHOME:-${SNAP_USER_DATA}/../../..}
+
+# Set config folder to local path
+export XDG_CONFIG_HOME="$SNAP_USER_DATA/.config"
+ensure_dir_exists "$XDG_CONFIG_HOME"
+chmod 700 "$XDG_CONFIG_HOME"
+
+function make_user_fontconfig {
+ echo "<fontconfig>"
+ echo " <dir>$REALHOME/.local/share/fonts</dir>"
+ echo " <dir>$REALHOME/.fonts</dir>"
+ echo " <cachedir prefix=\"xdg\">fontconfig</cachedir>"
+ echo " <cachedir>$SNAP_DATA/fontconfig</cachedir>"
+ echo " <include ignore_missing=\"yes\">/etc/fonts/fonts.conf</include>"
+ if [ ! -z $SNAP_DESKTOP_RUNTIME ]; then
+ echo " <include ignore_missing=\"yes\">${SNAP_DESKTOP_RUNTIME}/etc/fonts/fonts.conf</include>"
+ fi
+ echo "</fontconfig>"
+}
+
+ensure_dir_exists "$XDG_CONFIG_HOME/fontconfig"
+make_user_fontconfig > "$XDG_CONFIG_HOME/fontconfig/fonts.conf"
+
+export FONTCONFIG_FILE=${XDG_CONFIG_HOME}/fontconfig/fonts.conf
+
+exec "$@"
diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml
new file mode 100644
index 0000000..d5b9d54
--- /dev/null
+++ b/snap/snapcraft.yaml
@@ -0,0 +1,229 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+name: inkscape
+adopt-info: inkscape
+license: GPL-3.0
+confinement: strict
+base: core22
+compression: lzo
+
+plugs:
+ dot-config-inkscape:
+ interface: personal-files
+ write: [ $HOME/.config/inkscape ]
+ gtk-3-themes:
+ interface: content
+ target: $SNAP/data-dir/themes
+ default-provider: gtk-common-themes
+ icon-themes:
+ interface: content
+ target: $SNAP/data-dir/icons
+ default-provider: gtk-common-themes
+
+slots:
+ inkscape-dbus:
+ interface: dbus
+ bus: session
+ name: org.inkscape.Inkscape
+
+assumes: [ command-chain ]
+
+parts:
+ inkscape:
+ plugin: cmake
+ source: .
+ cmake-parameters:
+ - '-DCMAKE_INSTALL_PREFIX='
+ build-packages:
+ - build-essential
+ - cmake
+ - g++
+ - intltool
+ - libart-2.0-dev
+ - libboost-all-dev
+ - libcdr-dev
+ - libdouble-conversion-dev
+ - libgc-dev
+ - libglib2.0-dev
+ - libgsl-dev
+ - libgspell-1-dev
+ - libgtk-3-dev
+ - libgtkmm-3.0-dev
+ - libgtksourceview-4-dev
+ - libharfbuzz-dev
+ - liblcms2-dev
+ - libmagick++-dev
+ - libpango1.0-dev
+ - libpoppler-glib-dev
+ - libpoppler-private-dev
+ - libpotrace-dev
+ - librevenge-dev
+ - libsigc++-2.0-dev
+ - libsoup2.4-dev
+ - libtool
+ - libvisio-dev
+ - libwpg-dev
+ - libxml-parser-perl
+ - libxml2-dev
+ - libxslt1-dev
+ - pkg-config
+ - zlib1g-dev
+ stage-packages:
+ - heif-gdk-pixbuf
+ - gir1.2-gtk-3.0
+ - libatkmm-1.6-1v5
+ - libboost-filesystem1.74.0
+ - libcairomm-1.0-1v5
+ - libcdr-0.1-1
+ - libdouble-conversion3
+ - libgc1
+ - libgdk-pixbuf2.0-0
+ - libglibmm-2.4-1v5
+ - libglib2.0-bin
+ - libgsl27
+ - libgslcblas0
+ - libgspell-1-2
+ - libgtkmm-3.0-1v5
+ - libgtksourceview-4-common
+ - libgtksourceview-4-0
+ - liblcms2-2
+ - libmagick++-6.q16-8
+ - libpangomm-1.4-1v5
+ - libpoppler-glib8
+ - libpotrace0
+ - libpsl5
+ - librevenge-0.0-0
+ - libsoup2.4-1
+ - libvisio-0.1-1
+ - libwpg-0.3-3
+ - libxslt1.1
+ - aspell
+ - imagemagick
+ - libimage-magick-perl
+ - libwmf-bin
+ - transfig
+ - libsvg-perl
+ - libxml-xql-perl
+ - python3-pil
+ - python3-gi
+ - python3-gi-cairo
+ prime:
+ - -lib/inkscape/*.a
+ - -*canberra*so* # We don't have sound permissions anyway
+ - -usr/lib/*/gtk-2.0
+ override-build: |
+ patch -p1 --batch --directory=$SNAPCRAFT_PART_SRC --input=$SNAPCRAFT_PART_SRC/snap/local/filedialog-native.patch
+ patch -p1 --batch --directory=$SNAPCRAFT_PART_SRC --input=$SNAPCRAFT_PART_SRC/snap/local/glib-spawn-no-close.patch
+ sed -i.bak -e 's|Icon=${INKSCAPE_ICONPATH}|Icon=${SNAP}/share/inkscape/branding/inkscape.svg|g' $SNAPCRAFT_PART_SRC/org.inkscape.Inkscape.desktop.template
+ snapcraftctl build
+ INKSCAPE_VERSION=`g++ -I${SNAPCRAFT_PART_SRC}/src ${SNAPCRAFT_PART_BUILD}/src/inkscape-version.cpp ${SNAPCRAFT_PROJECT_DIR}/snap/local/print-inkscape-version.cpp -o print-inkscape-version && ./print-inkscape-version`
+ echo "Inkscape Version: ${INKSCAPE_VERSION}"
+ snapcraftctl set-version "${INKSCAPE_VERSION}"
+ override-prime: |
+ snapcraftctl prime
+ sed -i "s|_have.*$||" $SNAPCRAFT_PRIME/share/bash-completion/completions/inkscape
+ parse-info: [ share/metainfo/org.inkscape.Inkscape.appdata.xml ]
+ python-deps:
+ plugin: python
+ source: .
+ python-packages:
+ - six
+ - lxml
+ - numpy
+ - cssselect
+ - pip
+ - appdirs
+ - requests
+ - pillow
+ - cachecontrol[filecache]
+ - pyserial
+ - packaging
+ - scour
+ - virtualenv
+ stage-packages:
+ - optipng
+ - pstoedit
+# - texlive-latex-base
+ snap-helpers:
+ plugin: dump
+ source: snap/local/scripts
+ desktop-helpers:
+ source: https://github.com/ubuntu/snapcraft-desktop-helpers.git
+ source-subdir: gtk
+ plugin: make
+ make-parameters: ["FLAVOR=gtk3"]
+ build-packages:
+ - libgtk-3-dev
+ - locales
+ stage-packages:
+ - libxkbcommon0 # XKB_CONFIG_ROOT
+ - fonts-ubuntu
+ - dmz-cursor-theme
+ - light-themes
+ - adwaita-icon-theme
+ - gnome-themes-standard
+ - shared-mime-info
+ - libgtk-3-0
+ - libgtk-3-bin
+ - libglib2.0-bin
+ - locales-all
+ - libc-bin
+ - xdg-user-dirs
+ - ibus-gtk3
+ - libibus-1.0-5
+ - fcitx-frontend-gtk3
+ - librsvg2-common # SVG pixbuf loader
+ prime:
+ - -*canberra*so* # We don't have sound permissions anyway
+ - -usr/lib/*/gtk-2.0
+ override-prime: |
+ snapcraftctl prime
+ glib-compile-schemas ${SNAPCRAFT_PRIME}/usr/share/glib-2.0/schemas/
+ LOCPATH=${SNAPCRAFT_PRIME}/usr/lib/locale locale-gen
+ after: [inkscape, snap-helpers, python-deps] # Last so we compile all the schemas
+ gtk-locales:
+ plugin: nil
+ override-pull: |
+ set -eux
+ apt-get download "language-pack-*-base"
+ override-build: |
+ set -eux
+ for deb in *.deb; do dpkg-deb -x $deb .; done
+ find usr/share/locale-langpack -type f -not -name "gtk30*.mo" -and -not -name "glib*.mo" -and -not -name "gdk*.mo" -and -not -name "libsoup*.mo" -and -not -name "gspell*.mo" -and -not -name "coreutils*.mo" -delete
+ mkdir -p $SNAPCRAFT_PART_INSTALL/usr/share
+ cp -r usr/share/locale-langpack $SNAPCRAFT_PART_INSTALL/usr/share/
+
+apps:
+ inkscape:
+ command: bin/inkscape
+ command-chain: [ bin/desktop-launch, inkscape-variables, private-fontcache ]
+ plugs:
+ - desktop
+ - desktop-legacy
+ - gsettings
+ - wayland
+ - x11
+ - unity7
+ - dot-config-inkscape
+ - raw-usb # plotter support
+ - network # for extension manager
+ slots:
+ - inkscape-dbus
+ desktop: share/applications/org.inkscape.Inkscape.desktop
+ common-id: org.inkscape.Inkscape
+ completer: share/bash-completion/completions/inkscape
+ viewer:
+ command: bin/inkview
+ command-chain: [ bin/desktop-launch, inkscape-variables, private-fontcache ]
+ plugs:
+ - desktop
+ - desktop-legacy
+ - gsettings
+ - wayland
+ - x11
+ - unity7
+ - dot-config-inkscape
+
+hooks:
+ configure:
+ plugs:
+ - desktop