diff options
Diffstat (limited to 'pkgs/data/fonts')
-rw-r--r-- | pkgs/data/fonts/noto-fonts/default.nix | 305 | ||||
-rw-r--r-- | pkgs/data/fonts/noto-fonts/noto-emoji.hashes.json | 7 | ||||
-rw-r--r-- | pkgs/data/fonts/noto-fonts/noto-emoji.json | 30 | ||||
-rwxr-xr-x | pkgs/data/fonts/noto-fonts/noto-emoji.py | 183 | ||||
-rw-r--r-- | pkgs/data/fonts/noto-fonts/tools.nix | 78 |
5 files changed, 0 insertions, 603 deletions
diff --git a/pkgs/data/fonts/noto-fonts/default.nix b/pkgs/data/fonts/noto-fonts/default.nix deleted file mode 100644 index b5a5d26b5122d..0000000000000 --- a/pkgs/data/fonts/noto-fonts/default.nix +++ /dev/null @@ -1,305 +0,0 @@ -{ stdenv -, stdenvNoCC -, lib -, gitUpdater -, fetchFromGitHub -, fetchurl -, cairo -, nixosTests -, pkg-config -, pngquant -, which -, imagemagick -, zopfli -, buildPackages -, variants ? [ ] -}: -let - notoLongDescription = '' - When text is rendered by a computer, sometimes characters are - displayed as “tofu”. They are little boxes to indicate your device - doesn’t have a font to display the text. - - Google has been developing a font family called Noto, which aims to - support all languages with a harmonious look and feel. Noto is - Google’s answer to tofu. The name noto is to convey the idea that - Google’s goal is to see “no more tofu”. Noto has multiple styles and - weights, and freely available to all. - ''; -in -rec { - mkNoto = - { pname - , variants ? [ ] - , longDescription ? notoLongDescription - }: - stdenvNoCC.mkDerivation rec { - inherit pname; - version = "23.11.1"; - - src = fetchFromGitHub { - owner = "notofonts"; - repo = "notofonts.github.io"; - rev = "noto-monthly-release-${version}"; - hash = "sha256-qBHLCOfVBOn9CV194S4cYw9nhHyAe2AUBJHQMvyEfW8="; - }; - - _variants = map (variant: builtins.replaceStrings [ " " ] [ "" ] variant) variants; - - installPhase = '' - # We check availability in order of variable -> otf -> ttf - # unhinted -- the hinted versions use autohint - # maintaining maximum coverage. - # - # We have a mix of otf and ttf fonts - local out_font=$out/share/fonts/noto - '' + (if _variants == [ ] then '' - for folder in $(ls -d fonts/*/); do - if [[ -d "$folder"unhinted/variable-ttf ]]; then - install -m444 -Dt $out_font "$folder"unhinted/variable-ttf/*.ttf - elif [[ -d "$folder"unhinted/otf ]]; then - install -m444 -Dt $out_font "$folder"unhinted/otf/*.otf - else - install -m444 -Dt $out_font "$folder"unhinted/ttf/*.ttf - fi - done - '' else '' - for variant in $_variants; do - if [[ -d fonts/"$variant"/unhinted/variable-ttf ]]; then - install -m444 -Dt $out_font fonts/"$variant"/unhinted/variable-ttf/*.ttf - elif [[ -d fonts/"$variant"/unhinted/otf ]]; then - install -m444 -Dt $out_font fonts/"$variant"/unhinted/otf/*.otf - else - install -m444 -Dt $out_font fonts/"$variant"/unhinted/ttf/*.ttf - fi - done - ''); - - passthru.updateScript = gitUpdater { - rev-prefix = "noto-monthly-release-"; - }; - - meta = with lib; { - description = "Beautiful and free fonts for many languages"; - homepage = "https://www.google.com/get/noto/"; - inherit longDescription; - license = licenses.ofl; - platforms = platforms.all; - maintainers = with maintainers; [ mathnerd314 emily jopejoe1 ]; - }; - }; - - mkNotoCJK = { typeface, version, sha256 }: - stdenvNoCC.mkDerivation { - pname = "noto-fonts-cjk-${lib.toLower typeface}"; - inherit version; - - src = fetchFromGitHub { - owner = "googlefonts"; - repo = "noto-cjk"; - rev = "${typeface}${version}"; - inherit sha256; - sparseCheckout = [ "${typeface}/Variable/OTC" ]; - }; - - installPhase = '' - install -m444 -Dt $out/share/fonts/opentype/noto-cjk ${typeface}/Variable/OTC/*.otf.ttc - ''; - - passthru.tests.noto-fonts = nixosTests.noto-fonts; - - meta = with lib; { - description = "Beautiful and free fonts for CJK languages"; - homepage = "https://www.google.com/get/noto/help/cjk/"; - longDescription = '' - Noto ${typeface} CJK is a ${lib.toLower typeface} typeface designed as - an intermediate style between the modern and traditional. It is - intended to be a multi-purpose digital font for user interface - designs, digital content, reading on laptops, mobile devices, and - electronic books. Noto ${typeface} CJK comprehensively covers - Simplified Chinese, Traditional Chinese, Japanese, and Korean in a - unified font family. It supports regional variants of ideographic - characters for each of the four languages. In addition, it supports - Japanese kana, vertical forms, and variant characters (itaiji); it - supports Korean hangeul — both contemporary and archaic. - ''; - license = licenses.ofl; - platforms = platforms.all; - maintainers = with maintainers; [ mathnerd314 emily ]; - }; - }; - - noto-fonts = mkNoto { - pname = "noto-fonts"; - }; - - noto-fonts-lgc-plus = mkNoto { - pname = "noto-fonts-lgc-plus"; - variants = [ - "Noto Sans" - "Noto Serif" - "Noto Sans Mono" - "Noto Music" - "Noto Sans Symbols" - "Noto Sans Symbols 2" - "Noto Sans Math" - ]; - longDescription = '' - This package provides the Noto Fonts, but only for latin, greek - and cyrillic scripts, as well as some extra fonts. To create a - custom Noto package with custom variants, see the `mkNoto` - helper function. - ''; - }; - - noto-fonts-cjk-sans = mkNotoCJK { - typeface = "Sans"; - version = "2.004"; - sha256 = "sha256-IgalJkiOAVjNxKaPAQWfb5hKeqclliR4qVXCq63FGWY="; - }; - - noto-fonts-cjk-serif = mkNotoCJK { - typeface = "Serif"; - version = "2.002"; - sha256 = "sha256-GLjpTAiHfygj1J4AdUVDJh8kykkFOglq+h4kyat5W9s="; - }; - - noto-fonts-color-emoji = - let - version = "2.042"; - emojiPythonEnv = - buildPackages.python3.withPackages (p: with p; [ fonttools nototools ]); - in - stdenvNoCC.mkDerivation { - pname = "noto-fonts-emoji"; - inherit version; - - src = fetchFromGitHub { - owner = "googlefonts"; - repo = "noto-emoji"; - rev = "v${version}"; - hash = "sha256-otJQMXrBIPrxD1vCdgcrZ2h1a9XAMbqEBFumjz1XJ54="; - }; - - depsBuildBuild = [ - buildPackages.stdenv.cc - pkg-config - cairo - ]; - - nativeBuildInputs = [ - imagemagick - zopfli - pngquant - which - emojiPythonEnv - ]; - - postPatch = '' - patchShebangs *.py - patchShebangs third_party/color_emoji/*.py - # remove check for virtualenv, since we handle - # python requirements using python.withPackages - sed -i '/ifndef VIRTUAL_ENV/,+2d' Makefile - - # Make the build verbose so it won't get culled by Hydra thinking that - # it somehow got stuck doing nothing. - sed -i 's;\t@;\t;' Makefile - ''; - - enableParallelBuilding = true; - - installPhase = '' - runHook preInstall - mkdir -p $out/share/fonts/noto - cp NotoColorEmoji.ttf $out/share/fonts/noto - runHook postInstall - ''; - - meta = with lib; { - description = "Color emoji font"; - homepage = "https://github.com/googlefonts/noto-emoji"; - license = with licenses; [ ofl asl20 ]; - platforms = platforms.all; - maintainers = with maintainers; [ mathnerd314 sternenseemann ]; - }; - }; - - noto-fonts-monochrome-emoji = - # Metadata fetched from - # https://www.googleapis.com/webfonts/v1/webfonts?key=${GOOGLE_FONTS_TOKEN}&family=Noto+Emoji - let metadata = with builtins; head (fromJSON (readFile ./noto-emoji.json)).items; - urlHashes = with builtins; fromJSON (readFile ./noto-emoji.hashes.json); - - in - stdenvNoCC.mkDerivation { - pname = "noto-fonts-monochrome-emoji"; - version = "${lib.removePrefix "v" metadata.version}.${metadata.lastModified}"; - preferLocalBuild = true; - - dontUnpack = true; - srcs = let - weightNames = { - "300" = "Light"; - regular = "Regular"; - "500" = "Medium"; - "600" = "SemiBold"; - "700" = "Bold"; - }; - in lib.mapAttrsToList - (variant: url: fetchurl { name = "NotoEmoji-${weightNames.${variant}}.ttf"; - hash = urlHashes.${url}; - inherit url; } ) - metadata.files; - - installPhase = '' - runHook preInstall - for src in $srcs; do - install -D $src $out/share/fonts/noto/$(stripHash $src) - done - runHook postInstall - ''; - - meta = with lib; { - description = "Monochrome emoji font"; - homepage = "https://fonts.google.com/noto/specimen/Noto+Emoji"; - license = [ licenses.ofl ]; - maintainers = [ maintainers.nicoo ]; - - platforms = platforms.all; - sourceProvenance = [ sourceTypes.binaryBytecode ]; - }; - }; - - noto-fonts-emoji-blob-bin = - let - pname = "noto-fonts-emoji-blob-bin"; - version = "15.0"; - in - stdenvNoCC.mkDerivation { - inherit pname version; - - src = fetchurl { - url = "https://github.com/C1710/blobmoji/releases/download/v${version}/Blobmoji.ttf"; - hash = "sha256-3MPWZ1A2ups171dNIiFTJ3C1vZiGy6I8ZF70aUfrePk="; - }; - - dontUnpack = true; - - installPhase = '' - runHook preInstall - - install -Dm 444 $src $out/share/fonts/blobmoji/Blobmoji.ttf - - runHook postInstall - ''; - - meta = with lib; { - description = "Noto Emoji with extended Blob support"; - homepage = "https://github.com/C1710/blobmoji"; - license = with licenses; [ ofl asl20 ]; - platforms = platforms.all; - maintainers = with maintainers; [ rileyinman jk ]; - }; - }; -} diff --git a/pkgs/data/fonts/noto-fonts/noto-emoji.hashes.json b/pkgs/data/fonts/noto-fonts/noto-emoji.hashes.json deleted file mode 100644 index e9ad1c327f4f9..0000000000000 --- a/pkgs/data/fonts/noto-fonts/noto-emoji.hashes.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob_10jwvS-FGJCMY.ttf": "sha256-B8XBpYycOYBjrhjlnyiz42YukIoOjGTd3NN3EY00NiQ=", - "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob-r0jwvS-FGJCMY.ttf": "sha256-Zfwh9q2GrL5Dwp+J/8Ddd2IXCaUXpQ7dE3CqgCMMyPs=", - "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob-Z0jwvS-FGJCMY.ttf": "sha256-/O5b2DzM8g97NAdJgIC/RsQ7E5P7USKq7TXyDuUE3WQ=", - "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob911TwvS-FGJCMY.ttf": "sha256-vrjB8GlhzWAe6jG/Srpy8R431VivNtWbCa5Uh4ATnmU=", - "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob9M1TwvS-FGJCMY.ttf": "sha256-EbnZt8h4Lcl0yJoOKmXlF1nfcP5hZv7n4cEQ10yBkcg=" -} diff --git a/pkgs/data/fonts/noto-fonts/noto-emoji.json b/pkgs/data/fonts/noto-fonts/noto-emoji.json deleted file mode 100644 index c729634b9e1e7..0000000000000 --- a/pkgs/data/fonts/noto-fonts/noto-emoji.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "kind": "webfonts#webfontList", - "items": [ - { - "family": "Noto Emoji", - "variants": [ - "300", - "regular", - "500", - "600", - "700" - ], - "subsets": [ - "emoji" - ], - "version": "v47", - "lastModified": "2023-09-27", - "files": { - "300": "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob_10jwvS-FGJCMY.ttf", - "regular": "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob-r0jwvS-FGJCMY.ttf", - "500": "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob-Z0jwvS-FGJCMY.ttf", - "600": "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob911TwvS-FGJCMY.ttf", - "700": "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob9M1TwvS-FGJCMY.ttf" - }, - "category": "sans-serif", - "kind": "webfonts#webfont", - "menu": "http://fonts.gstatic.com/s/notoemoji/v47/bMrnmSyK7YY-MEu6aWjPDs-ar6uWaGWuob-r0gwuQeU.ttf" - } - ] -} diff --git a/pkgs/data/fonts/noto-fonts/noto-emoji.py b/pkgs/data/fonts/noto-fonts/noto-emoji.py deleted file mode 100755 index 9f1eadd95bca5..0000000000000 --- a/pkgs/data/fonts/noto-fonts/noto-emoji.py +++ /dev/null @@ -1,183 +0,0 @@ -#!/usr/bin/env nix-shell -#! nix-shell -i "python3 -I" -p python3 - -from contextlib import contextmanager -from pathlib import Path -from typing import Iterable, Optional -from urllib import request - -import hashlib, json - - -def getMetadata(apiKey: str, family: str = "Noto Emoji"): - '''Fetch the Google Fonts metadata for a given family. - - An API key can be obtained by anyone with a Google account (🚮) from - `https://developers.google.com/fonts/docs/developer_api#APIKey` - ''' - from urllib.parse import urlencode - - with request.urlopen( - "https://www.googleapis.com/webfonts/v1/webfonts?" + - urlencode({ 'key': apiKey, 'family': family }) - ) as req: - return json.load(req) - -def getUrls(metadata) -> Iterable[str]: - '''Fetch all files' URLs from Google Fonts' metadata. - - The metadata must obey the API v1 schema, and can be obtained from: - https://www.googleapis.com/webfonts/v1/webfonts?key=${GOOGLE_FONTS_TOKEN}&family=${FAMILY} - ''' - return ( url for i in metadata['items'] for _, url in i['files'].items() ) - - -def hashUrl(url: str, *, hash: str = 'sha256'): - '''Compute the hash of the data from HTTP GETing a given `url`. - - The `hash` must be an algorithm name `hashlib.new` accepts. - ''' - with request.urlopen(url) as req: - return hashlib.new(hash, req.read()) - - -def sriEncode(h) -> str: - '''Encode a hash in the SRI format. - - Takes a `hashlib` object, and produces a string that - nixpkgs' `fetchurl` accepts as `hash` parameter. - ''' - from base64 import b64encode - return f"{h.name}-{b64encode(h.digest()).decode()}" - -def validateSRI(sri: Optional[str]) -> Optional[str]: - '''Decode an SRI hash, return `None` if invalid. - - This is not a full SRI hash parser, hash options aren't supported. - ''' - from base64 import b64decode - - if sri is None: - return None - - try: - hashName, b64 = sri.split('-', 1) - - h = hashlib.new(hashName) - digest = b64decode(b64, validate=True) - assert len(digest) == h.digest_size - - except: - return None - else: - return sri - - -def hashUrls( - urls: Iterable[str], - knownHashes: dict[str, str] = {}, -) -> dict[str, str]: - '''Generate a `dict` mapping URLs to SRI-encoded hashes. - - The `knownHashes` optional parameter can be used to avoid - re-downloading files whose URL have not changed. - ''' - return { - url: validateSRI(knownHashes.get(url)) or sriEncode(hashUrl(url)) - for url in urls - } - - -@contextmanager -def atomicFileUpdate(target: Path): - '''Atomically replace the contents of a file. - - Yields an open file to write into; upon exiting the context, - the file is closed and (atomically) replaces the `target`. - - Guarantees that the `target` was either successfully overwritten - with new content and no exception was raised, or the temporary - file was cleaned up. - ''' - from tempfile import mkstemp - fd, _p = mkstemp( - dir = target.parent, - prefix = target.name, - ) - tmpPath = Path(_p) - - try: - with open(fd, 'w') as f: - yield f - - tmpPath.replace(target) - - except Exception: - tmpPath.unlink(missing_ok = True) - raise - - -if __name__ == "__main__": - from os import environ - from urllib.error import HTTPError - - environVar = 'GOOGLE_FONTS_TOKEN' - currentDir = Path(__file__).parent - metadataPath = currentDir / 'noto-emoji.json' - - try: - apiToken = environ[environVar] - metadata = getMetadata(apiToken) - - except (KeyError, HTTPError) as exn: - # No API key in the environment, or the query was rejected. - match exn: - case KeyError if exn.args[0] == environVar: - print(f"No '{environVar}' in the environment, " - "skipping metadata update") - - case HTTPError if exn.getcode() == 403: - print("Got HTTP 403 (Forbidden)") - if apiToken != '': - print("Your Google API key appears to be valid " - "but does not grant access to the fonts API.") - print("Aborting!") - raise SystemExit(1) - - case HTTPError if exn.getcode() == 400: - # Printing the supposed token should be fine, as this is - # what the API returns on invalid tokens. - print(f"Got HTTP 400 (Bad Request), is this really an API token: '{apiToken}' ?") - case _: - # Unknown error, let's bubble it up - raise - - # In that case just use the existing metadata - with metadataPath.open() as metadataFile: - metadata = json.load(metadataFile) - - lastModified = metadata["items"][0]["lastModified"]; - print(f"Using metadata from file, last modified {lastModified}") - - else: - # If metadata was successfully fetched, validate and persist it - lastModified = metadata["items"][0]["lastModified"]; - print(f"Fetched current metadata, last modified {lastModified}") - with atomicFileUpdate(metadataPath) as metadataFile: - json.dump(metadata, metadataFile, indent = 2) - metadataFile.write("\n") # Pacify nixpkgs' dumb editor config check - - hashPath = currentDir / 'noto-emoji.hashes.json' - try: - with hashPath.open() as hashFile: - hashes = json.load(hashFile) - except FileNotFoundError: - hashes = {} - - with atomicFileUpdate(hashPath) as hashFile: - json.dump( - hashUrls(getUrls(metadata), knownHashes = hashes), - hashFile, - indent = 2, - ) - hashFile.write("\n") # Pacify nixpkgs' dumb editor config check diff --git a/pkgs/data/fonts/noto-fonts/tools.nix b/pkgs/data/fonts/noto-fonts/tools.nix deleted file mode 100644 index 1b515b486f5f9..0000000000000 --- a/pkgs/data/fonts/noto-fonts/tools.nix +++ /dev/null @@ -1,78 +0,0 @@ -{ fetchFromGitHub, lib, buildPythonPackage, pythonOlder -, afdko, appdirs, attrs, booleanoperations, brotlipy, click -, defcon, fontmath, fontparts, fontpens, fonttools, lxml -, mutatormath, pathspec, psautohint, pyclipper, pytz, regex, scour -, toml, typed-ast, ufonormalizer, ufoprocessor, unicodedata2, zopfli -, pillow, six, bash, setuptools-scm }: - -buildPythonPackage rec { - pname = "nototools"; - version = "0.2.17"; - - disabled = pythonOlder "3.6"; - - src = fetchFromGitHub { - owner = "googlefonts"; - repo = "nototools"; - rev = "v${version}"; - sha256 = "0jxydivqzggirc31jv7b4mrsjkg646zmra5m4h0pk4amgy65rvyp"; - }; - - postPatch = '' - sed -i 's/use_scm_version=.*,/version="${version}",/' setup.py - ''; - - nativeBuildInputs = [ setuptools-scm ]; - - propagatedBuildInputs = [ - afdko - appdirs - attrs - booleanoperations - brotlipy - click - defcon - fontmath - fontparts - fontpens - fonttools - lxml - mutatormath - pathspec - psautohint - pyclipper - pytz - regex - scour - toml - typed-ast - ufonormalizer - ufoprocessor - unicodedata2 - zopfli - ]; - - nativeCheckInputs = [ - pillow - six - bash - ]; - - checkPhase = '' - patchShebangs tests/ - cd tests - rm gpos_diff_test.py # needs ttxn? - ./run_tests - ''; - - postInstall = '' - cp -r third_party $out - ''; - - meta = with lib; { - description = "Noto fonts support tools and scripts plus web site generation"; - homepage = "https://github.com/googlefonts/nototools"; - license = licenses.asl20; - maintainers = with maintainers; [ ]; - }; -} |