{ config, lib, pkgs, ... }:
with lib;
let cfg = config.fonts.fontconfig;
fcBool = x: "" + (if x then "true" else "false") + "";
renderConf = pkgs.writeText "render-conf" ''
${fcBool cfg.hinting.enable}
${fcBool cfg.hinting.autohint}
hint${cfg.hinting.style}
${fcBool cfg.antialias}
${cfg.subpixel.rgba}
lcd${cfg.subpixel.lcdfilter}
${optionalString (cfg.dpi != 0) ''
${toString cfg.dpi}
''}
'';
genericAliasConf =
let genDefault = fonts: name:
optionalString (fonts != []) ''
${name}
${concatStringsSep ""
(map (font: ''
${font}
'') fonts)}
'';
in
pkgs.writeText "generic-alias-conf" ''
${genDefault cfg.defaultFonts.sansSerif "sans-serif"}
${genDefault cfg.defaultFonts.serif "serif"}
${genDefault cfg.defaultFonts.monospace "monospace"}
'';
cacheConf = let
cache = fontconfig: pkgs.makeFontsCache { inherit fontconfig; fontDirectories = config.fonts.fonts; };
in
pkgs.writeText "cache-conf" ''
${concatStringsSep "\n" (map (font: "${font}") config.fonts.fonts)}
${cache pkgs.fontconfig}
${optionalString (pkgs.stdenv.isx86_64 && cfg.cache32Bit) ''
${cache pkgs.pkgsi686Linux.fontconfig}
''}
'';
userConf = pkgs.writeText "user-conf" ''
fontconfig/conf.d
fontconfig/fonts.conf
'';
fontsConf = pkgs.makeFontsConf { fontconfig = pkgs.fontconfig_210; fontDirectories = config.fonts.fonts; };
confPkg =
let version = pkgs.fontconfig.configVersion;
in pkgs.runCommand "fontconfig-conf" {} ''
mkdir -p $out/etc/fonts/{,${version}/}conf.d
ln -s ${fontsConf} $out/etc/fonts/fonts.conf
ln -s ${pkgs.fontconfig.out}/etc/fonts/fonts.conf $out/etc/fonts/${version}/fonts.conf
ln -s ${pkgs.fontconfig.out}/etc/fonts/conf.d/* $out/etc/fonts/${version}/conf.d/
ln -s ${renderConf} $out/etc/fonts/conf.d/10-nixos-rendering.conf
ln -s ${genericAliasConf} $out/etc/fonts/conf.d/60-nixos-generic-alias.conf
ln -s ${cacheConf} $out/etc/fonts/${version}/conf.d/00-nixos.conf
ln -s ${renderConf} $out/etc/fonts/${version}/conf.d/10-nixos-rendering.conf
ln -s ${genericAliasConf} $out/etc/fonts/${version}/conf.d/30-nixos-generic-alias.conf
${optionalString cfg.includeUserConf
"ln -s ${userConf} $out/etc/fonts/${version}/conf.d/99-user.conf"}
'';
in
{
options = {
fonts = {
fontconfig = {
enable = mkOption {
type = types.bool;
default = true;
description = ''
If enabled, a Fontconfig configuration file will be built
pointing to a set of default fonts. If you don't care about
running X11 applications or any other program that uses
Fontconfig, you can turn this option off and prevent a
dependency on all those fonts.
'';
};
confPkgs = mkOption {
internal = true;
type = with types; listOf path;
default = [ ];
description = ''
Fontconfig configuration packages.
'';
};
antialias = mkOption {
type = types.bool;
default = true;
description = "Enable font antialiasing.";
};
dpi = mkOption {
type = types.int;
default = 0;
description = ''
Force DPI setting. Setting to 0 disables DPI
forcing; the DPI detected for the display will be used.
'';
};
defaultFonts = {
monospace = mkOption {
type = types.listOf types.str;
default = ["DejaVu Sans Mono"];
description = ''
System-wide default monospace font(s). Multiple fonts may be
listed in case multiple languages must be supported.
'';
};
sansSerif = mkOption {
type = types.listOf types.str;
default = ["DejaVu Sans"];
description = ''
System-wide default sans serif font(s). Multiple fonts may be
listed in case multiple languages must be supported.
'';
};
serif = mkOption {
type = types.listOf types.str;
default = ["DejaVu Serif"];
description = ''
System-wide default serif font(s). Multiple fonts may be listed
in case multiple languages must be supported.
'';
};
};
hinting = {
enable = mkOption {
type = types.bool;
default = true;
description = "Enable TrueType hinting.";
};
autohint = mkOption {
type = types.bool;
default = true;
description = ''
Enable the autohinter, which provides hinting for otherwise
un-hinted fonts. The results are usually lower quality than
correctly-hinted fonts.
'';
};
style = mkOption {
type = types.str // {
check = flip elem ["none" "slight" "medium" "full"];
};
default = "full";
description = ''
TrueType hinting style, one of none,
slight, medium, or
full.
'';
};
};
includeUserConf = mkOption {
type = types.bool;
default = true;
description = ''
Include the user configuration from
~/.config/fontconfig/fonts.conf or
~/.config/fontconfig/conf.d.
'';
};
subpixel = {
rgba = mkOption {
default = "rgb";
type = types.enum ["rgb" "bgr" "vrgb" "vbgr" "none"];
description = ''
Subpixel order, one of none,
rgb, bgr,
vrgb, or vbgr.
'';
};
lcdfilter = mkOption {
default = "default";
type = types.enum ["none" "default" "light" "legacy"];
description = ''
FreeType LCD filter, one of none,
default, light, or
legacy.
'';
};
};
cache32Bit = mkOption {
default = false;
type = types.bool;
description = ''
Generate system fonts cache for 32-bit applications.
'';
};
};
};
};
config = mkIf cfg.enable {
fonts.fontconfig.confPkgs = [ confPkg ];
environment.etc.fonts.source =
let fontConf = pkgs.symlinkJoin {
name = "fontconfig-etc";
paths = cfg.confPkgs;
};
in "${fontConf}/etc/fonts/";
environment.systemPackages = [ pkgs.fontconfig ];
};
}