1
Fork 0

Implement nix derivation for fonts

This commit is contained in:
prescientmoon 2024-10-04 15:17:15 +02:00
parent 68c46fb7cd
commit f3edaf9e72
Signed by: prescientmoon
SSH key fingerprint: SHA256:WFp/cO76nbarETAoQcQXuV+0h7XJsEsOCI0UsyPIy6U
9 changed files with 205 additions and 45 deletions

1
.gitignore vendored
View file

@ -1,5 +1,6 @@
.direnv .direnv
.envrc .envrc
result
shimmering/data shimmering/data
shimmering/logs shimmering/logs

View file

@ -34,7 +34,7 @@ SHIMMERING_CONFIG_DIR=shimmering/config
SHIMMERING_LOG_DIR=shimmering/logs SHIMMERING_LOG_DIR=shimmering/logs
``` ```
## Binaries ### Binaries
The project currently exposes two binaries: The project currently exposes two binaries:
@ -44,26 +44,27 @@ The project currently exposes two binaries:
- The `prepare-jackets` command prepares the provided jackets for running the bot (see the section below for more details) - The `prepare-jackets` command prepares the provided jackets for running the bot (see the section below for more details)
- The `analyse <...paths>` command is a command-line version of the `score magic` discord command. This is useful for debugging things like the OCR implementation, without having to transmit files over the network. - The `analyse <...paths>` command is a command-line version of the `score magic` discord command. This is useful for debugging things like the OCR implementation, without having to transmit files over the network.
## Future binaries ### Work in progress
3. `shimmering-server` will be a server providing scoring data over HTTP. These binaries are unstable at best, and broken at worst.
4. `shimmering-discord-presence` will be a client application that talks to `shimmering-server` in order to update your discord "currently playing" status in order to reflect the charts you are currently playing.
3. `shimmering-server` provides functionality over HTTP
4. `shimmering-discord-presence` is a client application that talks to `shimmering-server` in order to update your discord "currently playing", showing off the scores you are getting.
### Fonts ### Fonts
The following fonts must be present in `$SHIMMERING_ASSET_DIR/fonts`: The following fonts must be present in `$SHIMMERING_FONTS_DIR`:
``` ```
arial.ttf Exo[wght].ttf
exo-variable.ttf GeosansLight.ttf
geosans-light.ttf Kazesawa-Bold.ttf
kazesawa-bold.ttf Kazesawa-Regular.ttf
kazesawa-regular.ttf
noto-sans.ttf
saira-variable.ttf
unifont.otf unifont.otf
``` ```
The `shimmering-fonts` derivation of the nix flake builds the aforementioned directory.
### Assets ### Assets
Most of the assets in this repo have been drawn by me. You need to bring in your own song jackets and place them at `$SHIMMERING_ASSET_DIR/songs`. This directory must contain a subdirectory for each song in the game, with each subdirectory containing a default jacket at `base_256.jpg`. Different files can be created to override the jacket for each difficulty. For more details, check out the implementation in [./src/arcaea/jacket.rs](./src/arcaea/jacket.rs). Most of the assets in this repo have been drawn by me. You need to bring in your own song jackets and place them at `$SHIMMERING_ASSET_DIR/songs`. This directory must contain a subdirectory for each song in the game, with each subdirectory containing a default jacket at `base_256.jpg`. Different files can be created to override the jacket for each difficulty. For more details, check out the implementation in [./src/arcaea/jacket.rs](./src/arcaea/jacket.rs).

View file

@ -21,24 +21,29 @@
# }; # };
# toolchain = pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default); # toolchain = pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default);
# toolchain = pkgs.rust-bin.stable.latest.default; # toolchain = pkgs.rust-bin.stable.latest.default;
toolchain = inputs.fenix.packages.${system}.complete.toolchain; # toolchain = inputs.fenix.packages.${system}.complete.toolchain;
spkgs = inputs.self.packages.${system};
inherit (pkgs) lib; inherit (pkgs) lib;
in in
{ {
packages.shimmeringmoon = pkgs.rustPlatform.buildRustPackage { packages = {
pname = "shimmeringmoon"; kazesawa = pkgs.callPackage ./nix/kazesawa.nix { };
version = "unstable-2024-09-06"; exo = pkgs.callPackage ./nix/exo.nix { };
geosans-light = pkgs.callPackage ./nix/geosans-light.nix { };
src = lib.cleanSource ./.; shimmering-fonts = pkgs.callPackage ./nix/fonts.nix {
# Pass custom-packaged fonts
inherit (spkgs) exo kazesawa geosans-light;
};
cargoLock = { default = spkgs.shimmeringmoon;
lockFile = ./Cargo.lock; shimmeringmoon = pkgs.callPackage ./nix/shimmeringmoon.nix {
outputHashes = { # Pass the directory of fonts
"hypertesseract-0.1.0" = "sha256-G0dos5yvvcfBKznAo1IIzLgXqRDxmyZwB93QQ6hVZSo="; inherit (spkgs) shimmering-fonts;
"plotters-0.4.0" = "sha256-9wtd7lig1vQ2RJVaEHdicfPZy2AyuoNav8shPMZ1EuE=";
};
}; };
}; };
# {{{ Devshell
devShell = pkgs.mkShell rec { devShell = pkgs.mkShell rec {
nativeBuildInputs = with pkgs; [ nativeBuildInputs = with pkgs; [
cargo cargo
@ -50,24 +55,20 @@
ruff ruff
imagemagick imagemagick
pkg-config pkg-config
# clang
# llvmPackages.clang
]; ];
buildInputs = with pkgs; [ buildInputs = with pkgs; [
freetype freetype
fontconfig fontconfig
leptonica leptonica
tesseract tesseract
# openssl
sqlite sqlite
]; ];
LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs; LD_LIBRARY_PATH = lib.makeLibraryPath buildInputs;
SHIMMERING_FONTS_DIR = spkgs.shimmering-fonts;
# compilation of -sys packages requires manually setting LIBCLANG_PATH
# LIBCLANG_PATH = "${pkgs.llvmPackages.libclang.lib}/lib";
}; };
# }}}
} }
); );

30
nix/exo.nix Normal file
View file

@ -0,0 +1,30 @@
{
stdenvNoCC,
fetchFromGitHub,
lib,
}:
stdenvNoCC.mkDerivation {
pname = "exo-1.0";
version = "unstable-2021-08-26";
src = fetchFromGitHub {
owner = "NDISCOVER";
repo = "Exo-1.0";
rev = "3be4f55b626129f17a3b82677703e48c03dc2052";
sha256 = "1l6k8q20anjcl3x7piwakgkdajkcjw70r6vfqxl8vycr0fra104d";
};
dontBuild = true;
installPhase = ''
runHook preInstall
install -Dm644 $src/fonts/variable/*.ttf -t $out/share/fonts/truetype
runHook postInstall
'';
meta = {
description = "Exo 1.0 Font Family ";
homepage = "https://fonts.google.com/specimen/Exo";
platforms = with lib.platforms; all;
license = lib.licenses.ofl;
};
}

25
nix/fonts.nix Normal file
View file

@ -0,0 +1,25 @@
{
unifont,
exo,
kazesawa,
geosans-light,
stdenvNoCC,
}:
stdenvNoCC.mkDerivation {
name = "shimmering-fonts";
dontUnpack = true;
installPhase = ''
mkdir -p $out
cp "${unifont}/share/fonts/opentype/unifont.otf" $out
cp "${exo}/share/fonts/truetype/Exo[wght].ttf" $out
cp "${kazesawa}/share/fonts/truetype/Kazesawa-Regular.ttf" $out
cp "${kazesawa}/share/fonts/truetype/Kazesawa-Bold.ttf" $out
cp "${geosans-light}/share/fonts/truetype/GeosansLight.ttf" $out
'';
meta = {
description = "Collection of fonts required by `shimmeringmoon` at runtime";
};
}

27
nix/geosans-light.nix Normal file
View file

@ -0,0 +1,27 @@
{
stdenvNoCC,
fetchzip,
lib,
}:
stdenvNoCC.mkDerivation {
name = "geosans-light";
src = fetchzip {
url = "https://dl.dafont.com/dl/?f=geo_sans_light";
sha256 = "sha256-T4N+c8pNaak2cC9WQqj8iezqVs47COIrUJv5yvpEBH4=";
extension = "zip"; # The build otherwise fails because of the query param
stripRoot = false;
};
installPhase = ''
runHook preInstall
install -Dm644 $src/*.ttf -t $out/share/fonts/truetype
runHook postInstall
'';
meta = {
description = "Exo 1.0 Font Family ";
homepage = "https://www.dafont.com/geo-sans-light.font";
platforms = with lib.platforms; all;
};
}

27
nix/kazesawa.nix Normal file
View file

@ -0,0 +1,27 @@
{
stdenvNoCC,
fetchzip,
lib,
}:
stdenvNoCC.mkDerivation rec {
pname = "kazesawa";
version = "alpha-v1";
src = fetchzip {
url = "https://github.com/kazesawa/kazesawa/releases/download/${version}/kazesawa.zip";
sha256 = "JM6QfpsoWFQh4jUODflLOwoGoRaq8UqFnaGElzkT/H4=";
stripRoot = false;
};
installPhase = ''
runHook preInstall
install -Dm644 *.ttf -t $out/share/fonts/truetype
runHook postInstall
'';
meta = {
description = "Kazesawa Font: M+ with Source Sans Pro";
homepage = "https://kazesawa.github.io/";
platforms = with lib.platforms; all;
license = lib.licenses.ofl;
};
}

55
nix/shimmeringmoon.nix Normal file
View file

@ -0,0 +1,55 @@
{
rustPlatform,
lib,
pkg-config,
makeWrapper,
freetype,
fontconfig,
leptonica,
tesseract,
openssl,
sqlite,
shimmering-fonts,
}:
rustPlatform.buildRustPackage {
pname = "shimmeringmoon";
version = "unstable-2024-09-06";
nativeBuildInputs = [
pkg-config
makeWrapper
];
buildInputs = [
freetype
fontconfig
leptonica
tesseract
openssl
sqlite
shimmering-fonts
];
# Tell the binary where to find the fonts
# postBuild = ''
# wrapProgram $out/bin/shimmering-discord-bot \
# --set SHIMMERING_FONTS_DIR ${shimmering-fonts}
# '';
checkFlags = [
# disable all tests
"--skip"
];
src = lib.cleanSource ../.;
cargoLock = {
lockFile = ../Cargo.lock;
outputHashes = {
"hypertesseract-0.1.0" = "sha256-G0dos5yvvcfBKznAo1IIzLgXqRDxmyZwB93QQ6hVZSo=";
"plotters-0.4.0" = "sha256-9wtd7lig1vQ2RJVaEHdicfPZy2AyuoNav8shPMZ1EuE=";
};
};
}

View file

@ -43,8 +43,9 @@ pub fn get_asset_dir() -> PathBuf {
// {{{ Font helpers // {{{ Font helpers
#[inline] #[inline]
fn get_font(name: &str) -> RefCell<Face> { fn get_font(name: &str) -> RefCell<Face> {
let fonts_dir = get_path("SHIMMERING_FONTS_DIR");
let face = FREETYPE_LIB.with(|lib| { let face = FREETYPE_LIB.with(|lib| {
lib.new_face(get_asset_dir().join("fonts").join(name), 0) lib.new_face(fonts_dir.join(name), 0)
.unwrap_or_else(|_| panic!("Could not load {} font", name)) .unwrap_or_else(|_| panic!("Could not load {} font", name))
}); });
RefCell::new(face) RefCell::new(face)
@ -55,25 +56,17 @@ pub fn with_font<T>(
primary: &'static LocalKey<RefCell<Face>>, primary: &'static LocalKey<RefCell<Face>>,
f: impl FnOnce(&mut [&mut Face]) -> T, f: impl FnOnce(&mut [&mut Face]) -> T,
) -> T { ) -> T {
UNI_FONT.with_borrow_mut(|uni| { UNI_FONT.with_borrow_mut(|uni| primary.with_borrow_mut(|primary| f(&mut [primary, uni])))
// NOTO_SANS_FONT.with_borrow_mut(|noto| {
// ARIAL_FONT.with_borrow_mut(|arial| {
primary.with_borrow_mut(|primary| f(&mut [primary, uni]))
// })
// })
})
} }
// }}} // }}}
// {{{ Font loading // {{{ Font loading
// TODO: I might want to embed those into the binary 🤔
thread_local! { thread_local! {
pub static FREETYPE_LIB: Library = Library::init().unwrap(); pub static FREETYPE_LIB: Library = Library::init().unwrap();
pub static SAIRA_FONT: RefCell<Face> = get_font("saira-variable.ttf"); pub static EXO_FONT: RefCell<Face> = get_font("Exo[wght].ttf");
pub static EXO_FONT: RefCell<Face> = get_font("exo-variable.ttf"); pub static GEOSANS_FONT: RefCell<Face> = get_font("GeosansLight.ttf");
pub static GEOSANS_FONT: RefCell<Face> = get_font("geosans-light.ttf"); pub static KAZESAWA_FONT: RefCell<Face> = get_font("Kazesawa-Regular.ttf");
pub static KAZESAWA_FONT: RefCell<Face> = get_font("kazesawa-regular.ttf"); pub static KAZESAWA_BOLD_FONT: RefCell<Face> = get_font("Kazesawa-Bold.ttf");
pub static KAZESAWA_BOLD_FONT: RefCell<Face> = get_font("kazesawa-bold.ttf");
pub static NOTO_SANS_FONT: RefCell<Face> = get_font("noto-sans.ttf");
pub static ARIAL_FONT: RefCell<Face> = get_font("arial.ttf");
pub static UNI_FONT: RefCell<Face> = get_font("unifont.otf"); pub static UNI_FONT: RefCell<Face> = get_font("unifont.otf");
} }
// }}} // }}}