diff --git a/pkgs/development/python-modules/ninja/default.nix b/pkgs/development/python-modules/ninja/default.nix
new file mode 100644
index 000000000000..d3ab12c29a55
--- /dev/null
+++ b/pkgs/development/python-modules/ninja/default.nix
@@ -0,0 +1,72 @@
+{ lib
+, buildPythonPackage
+, fetchFromGitHub
+, fetchurl
+, cmake
+, setuptools-scm
+, scikit-build
+, pytestCheckHook
+, pytest-virtualenv
+}:
+let
+ # these must match NinjaUrls.cmake
+ ninja_src_url = "https://github.com/Kitware/ninja/archive/v1.11.1.g95dee.kitware.jobserver-1.tar.gz";
+ ninja_src_sha256 = "7ba84551f5b315b4270dc7c51adef5dff83a2154a3665a6c9744245c122dd0db";
+ ninja_src = fetchurl {
+ url = ninja_src_url;
+ sha256 = ninja_src_sha256;
+ };
+in
+buildPythonPackage rec {
+ pname = "ninja";
+ version = "1.11.1";
+ format = "pyproject";
+
+ src = fetchFromGitHub {
+ owner = "scikit-build";
+ repo = "ninja-python-distributions";
+ rev = version;
+ hash = "sha256-scCYsSEyN+u3qZhNhWYqHpJCl+JVJJbKz+T34gOXGJM=";
+ };
+ patches = [
+ # make sure cmake doesn't try to download the ninja sources
+ ./no-download.patch
+ ];
+
+ inherit ninja_src;
+ postUnpack = ''
+ # assume that if the hash matches, the source should be fine
+ if ! grep "${ninja_src_sha256}" $sourceRoot/NinjaUrls.cmake; then
+ echo "ninja_src_sha256 doesn't match the hash in NinjaUrls.cmake!"
+ exit 1
+ fi
+ mkdir -p "$sourceRoot/Ninja-src"
+ pushd "$sourceRoot/Ninja-src"
+ tar -xavf ${ninja_src} --strip-components 1
+ popd
+ '';
+
+ postPatch = ''
+ sed -i '/cov/d' setup.cfg
+ '';
+
+ dontUseCmakeConfigure = true;
+
+ nativeBuildInputs = [
+ setuptools-scm
+ scikit-build
+ cmake
+ ];
+
+ nativeCheckInputs = [
+ pytestCheckHook
+ pytest-virtualenv
+ ];
+
+ meta = with lib; {
+ description = "A small build system with a focus on speed";
+ homepage = "https://github.com/scikit-build/ninja-python-distributions";
+ license = licenses.asl20;
+ maintainers = with maintainers; [ _999eagle ];
+ };
+}
diff --git a/pkgs/development/python-modules/ninja/no-download.patch b/pkgs/development/python-modules/ninja/no-download.patch
new file mode 100644
index 000000000000..0937a5fde1ea
--- /dev/null
+++ b/pkgs/development/python-modules/ninja/no-download.patch
@@ -0,0 +1,10 @@
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -64,6 +64,7 @@
+ # Download selected source archive
+ ExternalProject_add(download_ninja_source
+ SOURCE_DIR ${Ninja_SOURCE_DIR}
++ DOWNLOAD_COMMAND ""
+ URL ${${src_archive}_url}
+ URL_HASH SHA256=${${src_archive}_sha256}
+ DOWNLOAD_DIR ${ARCHIVE_DOWNLOAD_DIR}
diff --git a/pkgs/development/python-modules/picosvg/default.nix b/pkgs/development/python-modules/picosvg/default.nix
new file mode 100644
index 000000000000..a04479cfb414
--- /dev/null
+++ b/pkgs/development/python-modules/picosvg/default.nix
@@ -0,0 +1,57 @@
+{ lib
+, stdenv
+, buildPythonPackage
+, fetchFromGitHub
+, fetchpatch
+, setuptools-scm
+, absl-py
+, lxml
+, skia-pathops
+, pytestCheckHook
+}:
+buildPythonPackage rec {
+ pname = "picosvg";
+ version = "0.22.0";
+
+ src = fetchFromGitHub {
+ owner = "googlefonts";
+ repo = pname;
+ rev = "v${version}";
+ hash = "sha256-J06ijF1c3ZKPqKiQha6yqfj8EjFZoZzA6i6UCCrexi8=";
+ };
+
+ patches = [
+ # see https://github.com/googlefonts/picosvg/issues/299
+ # this patch fixed a failing test case after the update to skia-pathops 0.8
+ # as soon as skia-pathops in nixpkgs is updated to 0.8, this patch should be removed
+ (fetchpatch {
+ url = "https://github.com/googlefonts/picosvg/commit/4e971ed6cd9afb412b2845d29296a0c24f086562.patch";
+ hash = "sha256-OZEipNPCSuuqcy4XggBiuGv4HN604dI4N9wlznyAwF0=";
+ revert = true;
+ })
+ ];
+
+ nativeBuildInputs = [
+ setuptools-scm
+ ];
+
+ propagatedBuildInputs = [
+ absl-py
+ lxml
+ skia-pathops
+ ];
+
+ nativeCheckInputs = [
+ pytestCheckHook
+ ];
+
+ # a few tests are failing on aarch64
+ doCheck = !stdenv.isAarch64;
+
+ meta = with lib; {
+ description = "Tool to simplify SVGs";
+ homepage = "https://github.com/googlefonts/picosvg";
+ license = licenses.asl20;
+ maintainers = with maintainers; [ _999eagle ];
+ };
+}
diff --git a/pkgs/tools/misc/nanoemoji/default.nix b/pkgs/tools/misc/nanoemoji/default.nix
new file mode 100644
index 000000000000..93817ff84798
--- /dev/null
+++ b/pkgs/tools/misc/nanoemoji/default.nix
@@ -0,0 +1,72 @@
+{ lib
+, python3
+, fetchFromGitHub
+, resvg
+, pngquant
+}:
+python3.pkgs.buildPythonApplication rec {
+ pname = "nanoemoji";
+ version = "0.15.1";
+
+ src = fetchFromGitHub {
+ owner = "googlefonts";
+ repo = pname;
+ rev = "v${version}";
+ hash = "sha256-P/lT0PnjTdYzyttICzszu4OL5kj+X8GHZ8doL3tpXQM=";
+ };
+ patches = [
+ # this is necessary because the tests clear PATH/PYTHONPATH otherwise
+ ./test-pythonpath.patch
+ # minor difference in the test output, most likely due to different dependency versions
+ ./fix-test.patch
+ ];
+
+ nativeBuildInputs = with python3.pkgs; [
+ setuptools-scm
+ pythonRelaxDepsHook
+
+ pngquant
+ resvg
+ ];
+
+ # these two packages are just prebuilt wheels containing the respective binaries
+ pythonRemoveDeps = [ "pngquant-cli" "resvg-cli" ];
+
+ propagatedBuildInputs = with python3.pkgs; [
+ absl-py
+ fonttools
+ lxml
+ ninja-python
+ picosvg
+ pillow
+ regex
+ toml
+ tomlkit
+ ufo2ft
+ ufoLib2
+ zopfli
+ ];
+
+ nativeCheckInputs = with python3.pkgs; [
+ pytestCheckHook
+
+ ninja-python
+ picosvg
+ ];
+
+ makeWrapperArgs = [
+ "--prefix PATH : ${lib.makeBinPath [ pngquant resvg ]}"
+ ];
+
+ preCheck = ''
+ # make sure the built binaries (nanoemoji/maximum_color) can be found by the test
+ export PATH="$out/bin:$PATH"
+ '';
+
+ meta = with lib; {
+ description = "A wee tool to build color fonts";
+ homepage = "https://github.com/googlefonts/nanoemoji";
+ license = licenses.asl20;
+ maintainers = with maintainers; [ _999eagle ];
+ };
+}
diff --git a/pkgs/tools/misc/nanoemoji/fix-test.patch b/pkgs/tools/misc/nanoemoji/fix-test.patch
new file mode 100644
index 000000000000..4582df9ea5b8
--- /dev/null
+++ b/pkgs/tools/misc/nanoemoji/fix-test.patch
@@ -0,0 +1,24 @@
+--- a/tests/proportional_cbdt.ttx
++++ b/tests/proportional_cbdt.ttx
+@@ -13,7 +13,7 @@
+
+
+
+-
++
+
+
+
+@@ -79,10 +79,10 @@
+
+
+
+-
++
+
+
+-
++
+
+
+
diff --git a/pkgs/tools/misc/nanoemoji/test-pythonpath.patch b/pkgs/tools/misc/nanoemoji/test-pythonpath.patch
new file mode 100644
index 000000000000..12733224560c
--- /dev/null
+++ b/pkgs/tools/misc/nanoemoji/test-pythonpath.patch
@@ -0,0 +1,14 @@
+--- a/tests/test_helper.py
++++ b/tests/test_helper.py
+@@ -269,9 +269,9 @@
+ print("subprocess:", " ".join(cmd)) # very useful on failure
+ env = {
+ # We may need to find nanoemoji and other pip-installed cli tools
+- "PATH": str(Path(shutil.which("nanoemoji")).parent),
++ "PATH": str(Path(shutil.which("nanoemoji")).parent) + ":" + os.environ["PATH"],
+ # We may need to find test modules
+- "PYTHONPATH": os.pathsep.join((str(Path(__file__).parent),)),
++ "PYTHONPATH": os.pathsep.join((str(Path(__file__).parent),)) + ":" + os.environ["PYTHONPATH"],
+ }
+ # Needed for windows CI to function; ref https://github.com/appveyor/ci/issues/1995
+ if "SYSTEMROOT" in os.environ:
diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix
index 52e51a58c119..71be4c50eee4 100644
--- a/pkgs/top-level/all-packages.nix
+++ b/pkgs/top-level/all-packages.nix
@@ -9858,6 +9858,8 @@ with pkgs;
pythonPackages = python3Packages;
};
+ nanoemoji = python3Packages.callPackage ../tools/misc/nanoemoji { };
+
nagelfar = callPackage ../development/tools/nagelfar { };
nats-top = callPackage ../tools/system/nats-top { };
diff --git a/pkgs/top-level/python-packages.nix b/pkgs/top-level/python-packages.nix
index 58ef196fe472..0bbfefe31cbe 100644
--- a/pkgs/top-level/python-packages.nix
+++ b/pkgs/top-level/python-packages.nix
@@ -7015,6 +7015,8 @@ self: super: with self; {
nine = callPackage ../development/python-modules/nine { };
+ ninja-python = callPackage ../development/python-modules/ninja { };
+
nipy = callPackage ../development/python-modules/nipy { };
nipype = callPackage ../development/python-modules/nipype {
@@ -7875,6 +7877,8 @@ self: super: with self; {
picos = callPackage ../development/python-modules/picos { };
+ picosvg = callPackage ../development/python-modules/picosvg { };
+
piccolo-theme = callPackage ../development/python-modules/piccolo-theme { };
pid = callPackage ../development/python-modules/pid { };