2 Configuration files are linked to /etc/fonts/conf.d/
4 This module generates a package containing configuration files and link it in /etc/fonts.
6 Fontconfig reads files in folder name / file name order, so the number prepended to the configuration file name decide the order of parsing.
7 Low number means high priority.
9 NOTE: Please take extreme care when adjusting the default settings of this module.
10 People care a lot, and I mean A LOT, about their font rendering, and you will be
11 The Person That Broke It if it changes in a way people don't like.
14 - https://github.com/NixOS/nixpkgs/pull/194594
15 - https://github.com/NixOS/nixpkgs/pull/222236
16 - https://github.com/NixOS/nixpkgs/pull/222689
18 And do not repeat our mistakes.
30 cfg = config.fonts.fontconfig;
32 fcBool = x: "<bool>" + (lib.boolToString x) + "</bool>";
33 pkg = pkgs.fontconfig;
35 # configuration file to read fontconfig cache
37 cacheConf = makeCacheConf { };
39 # generate the font cache setting file
40 # When cross-compiling, we can’t generate the cache, so we skip the
41 # <cachedir> part. fontconfig still works but is a little slower in
50 fontDirectories = config.fonts.packages;
52 cache = makeCache pkgs.fontconfig;
53 cache32 = makeCache pkgs.pkgsi686Linux.fontconfig;
55 pkgs.writeText "fc-00-nixos-cache.conf" ''
57 <!DOCTYPE fontconfig SYSTEM 'urn:fontconfig:fonts.dtd'>
59 <!-- Font directories -->
60 ${lib.concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.packages)}
61 ${lib.optionalString (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) ''
62 <!-- Pre-generated font caches -->
63 <cachedir>${cache}</cachedir>
64 ${lib.optionalString (pkgs.stdenv.hostPlatform.isx86_64 && cfg.cache32Bit) ''
65 <cachedir>${cache32}</cachedir>
71 # rendering settings configuration file
73 renderConf = pkgs.writeText "fc-10-nixos-rendering.conf" ''
75 <!DOCTYPE fontconfig SYSTEM 'urn:fontconfig:fonts.dtd'>
78 <!-- Default rendering settings -->
79 <match target="pattern">
80 <edit mode="append" name="hinting">
81 ${fcBool cfg.hinting.enable}
83 <edit mode="append" name="autohint">
84 ${fcBool cfg.hinting.autohint}
91 # local configuration file
92 localConf = pkgs.writeText "fc-local.conf" cfg.localConf;
94 # default fonts configuration file
100 lib.optionalString (fonts != [ ]) ''
101 <alias binding="same">
102 <family>${name}</family>
104 ${lib.concatStringsSep "" (
106 <family>${font}</family>
113 pkgs.writeText "fc-52-nixos-default-fonts.conf" ''
114 <?xml version='1.0'?>
115 <!DOCTYPE fontconfig SYSTEM 'urn:fontconfig:fonts.dtd'>
118 <!-- Default fonts -->
119 ${genDefault cfg.defaultFonts.sansSerif "sans-serif"}
121 ${genDefault cfg.defaultFonts.serif "serif"}
123 ${genDefault cfg.defaultFonts.monospace "monospace"}
125 ${genDefault cfg.defaultFonts.emoji "emoji"}
130 # bitmap font options
132 rejectBitmaps = pkgs.writeText "fc-53-no-bitmaps.conf" ''
133 <?xml version="1.0"?>
134 <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
137 ${lib.optionalString (!cfg.allowBitmaps) ''
138 <!-- Reject bitmap fonts -->
142 <patelt name="scalable"><bool>false</bool></patelt>
148 <!-- Use embedded bitmaps in fonts like Calibri? -->
149 <match target="font">
150 <edit name="embeddedbitmap" mode="assign">
151 ${fcBool cfg.useEmbeddedBitmaps}
158 # reject Type 1 fonts
160 rejectType1 = pkgs.writeText "fc-53-nixos-reject-type1.conf" ''
161 <?xml version="1.0"?>
162 <!DOCTYPE fontconfig SYSTEM "urn:fontconfig:fonts.dtd">
165 <!-- Reject Type 1 fonts -->
169 <patelt name="fontformat"><string>Type 1</string></patelt>
177 # Replace default linked config with a different variant
178 replaceDefaultConfig = defaultConfig: newConfig: ''
179 rm $dst/${defaultConfig}
180 ln -s ${pkg.out}/share/fontconfig/conf.avail/${newConfig} \
184 # fontconfig configuration package
186 pkgs.runCommand "fontconfig-conf"
188 preferLocalBuild = true;
191 dst=$out/etc/fonts/conf.d
195 ln -s ${pkg.out}/etc/fonts/fonts.conf \
197 # TODO: remove this legacy symlink once people stop using packages built before #95358 was merged
198 mkdir -p $out/etc/fonts/2.11
199 ln -s /etc/fonts/fonts.conf \
200 $out/etc/fonts/2.11/fonts.conf
202 # fontconfig default config files
203 ln -s ${pkg.out}/etc/fonts/conf.d/*.conf \
206 ${lib.optionalString (!cfg.antialias) (
207 replaceDefaultConfig "10-yes-antialias.conf" "10-no-antialias.conf"
210 ${lib.optionalString (cfg.hinting.style != "slight") (
211 replaceDefaultConfig "10-hinting-slight.conf" "10-hinting-${cfg.hinting.style}.conf"
214 ${lib.optionalString (cfg.subpixel.rgba != "none") (
215 replaceDefaultConfig "10-sub-pixel-none.conf" "10-sub-pixel-${cfg.subpixel.rgba}.conf"
218 ${lib.optionalString (cfg.subpixel.lcdfilter != "default") (
219 replaceDefaultConfig "11-lcdfilter-default.conf" "11-lcdfilter-${cfg.subpixel.lcdfilter}.conf"
222 # 00-nixos-cache.conf
223 ln -s ${cacheConf} $dst/00-nixos-cache.conf
225 # 10-nixos-rendering.conf
226 ln -s ${renderConf} $dst/10-nixos-rendering.conf
229 ${lib.optionalString (!cfg.includeUserConf) ''
233 # local.conf (indirect priority 51)
234 ${lib.optionalString (cfg.localConf != "") ''
235 ln -s ${localConf} $dst/../local.conf
238 # 52-nixos-default-fonts.conf
239 ln -s ${defaultFontsConf} $dst/52-nixos-default-fonts.conf
242 ln -s ${rejectBitmaps} $dst/53-no-bitmaps.conf
244 ${lib.optionalString (!cfg.allowType1) ''
245 # 53-nixos-reject-type1.conf
246 ln -s ${rejectType1} $dst/53-nixos-reject-type1.conf
250 # Package with configuration files
251 # this merge all the packages in the fonts.fontconfig.confPackages list
252 fontconfigEtc = pkgs.buildEnv {
253 name = "fontconfig-etc";
254 paths = cfg.confPackages;
255 ignoreCollisions = true;
258 fontconfigNote = "Consider manually configuring fonts.fontconfig according to personal preference.";
263 (lib.mkRenamedOptionModule
264 [ "fonts" "fontconfig" "ultimate" "allowBitmaps" ]
265 [ "fonts" "fontconfig" "allowBitmaps" ]
267 (lib.mkRenamedOptionModule
268 [ "fonts" "fontconfig" "ultimate" "allowType1" ]
269 [ "fonts" "fontconfig" "allowType1" ]
271 (lib.mkRenamedOptionModule
272 [ "fonts" "fontconfig" "ultimate" "useEmbeddedBitmaps" ]
273 [ "fonts" "fontconfig" "useEmbeddedBitmaps" ]
275 (lib.mkRenamedOptionModule
276 [ "fonts" "fontconfig" "ultimate" "forceAutohint" ]
277 [ "fonts" "fontconfig" "forceAutohint" ]
279 (lib.mkRenamedOptionModule
280 [ "fonts" "fontconfig" "ultimate" "renderMonoTTFAsBitmap" ]
281 [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ]
283 (lib.mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "")
284 (lib.mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "")
285 (lib.mkRemovedOptionModule [ "fonts" "fontconfig" "dpi" ] "Use display server-specific options")
286 (lib.mkRemovedOptionModule [ "hardware" "video" "hidpi" "enable" ] fontconfigNote)
287 (lib.mkRemovedOptionModule [ "fonts" "optimizeForVeryHighDPI" ] fontconfigNote)
289 ++ lib.forEach [ "enable" "substitutions" "preset" ] (
291 lib.mkRemovedOptionModule [ "fonts" "fontconfig" "ultimate" "${opt}" ] ''
292 The fonts.fontconfig.ultimate module and configuration is obsolete.
293 The repository has since been archived and activity has ceased.
294 https://github.com/bohoomil/fontconfig-ultimate/issues/171.
295 No action should be needed for font configuration, as the fonts.fontconfig
296 module is already used by default.
305 enable = lib.mkOption {
306 type = lib.types.bool;
309 If enabled, a Fontconfig configuration file will be built
310 pointing to a set of default fonts. If you don't care about
311 running X11 applications or any other program that uses
312 Fontconfig, you can turn this option off and prevent a
313 dependency on all those fonts.
317 confPackages = lib.mkOption {
319 type = with lib.types; listOf path;
322 Fontconfig configuration packages.
326 antialias = lib.mkOption {
327 type = lib.types.bool;
330 Enable font antialiasing. At high resolution (> 200 DPI),
331 antialiasing has no visible effect; users of such displays may want
332 to disable this option.
336 localConf = lib.mkOption {
337 type = lib.types.lines;
340 System-wide customization file contents, has higher priority than
341 `defaultFonts` settings.
346 monospace = lib.mkOption {
347 type = lib.types.listOf lib.types.str;
348 default = [ "DejaVu Sans Mono" ];
350 System-wide default monospace font(s). Multiple fonts may be
351 listed in case multiple languages must be supported.
355 sansSerif = lib.mkOption {
356 type = lib.types.listOf lib.types.str;
357 default = [ "DejaVu Sans" ];
359 System-wide default sans serif font(s). Multiple fonts may be
360 listed in case multiple languages must be supported.
364 serif = lib.mkOption {
365 type = lib.types.listOf lib.types.str;
366 default = [ "DejaVu Serif" ];
368 System-wide default serif font(s). Multiple fonts may be listed
369 in case multiple languages must be supported.
373 emoji = lib.mkOption {
374 type = lib.types.listOf lib.types.str;
375 default = [ "Noto Color Emoji" ];
377 System-wide default emoji font(s). Multiple fonts may be listed
378 in case a font does not support all emoji.
380 Note that fontconfig matches color emoji fonts preferentially,
381 so if you want to use a black and white font while having
382 a color font installed (eg. Noto Color Emoji installed alongside
383 Noto Emoji), fontconfig will still choose the color font even
384 when it is later in the list.
390 enable = lib.mkOption {
391 type = lib.types.bool;
394 Enable font hinting. Hinting aligns glyphs to pixel boundaries to
395 improve rendering sharpness at low resolution. At high resolution
396 (> 200 dpi) hinting will do nothing (at best); users of such
397 displays may want to disable this option.
401 autohint = lib.mkOption {
402 type = lib.types.bool;
405 Enable the autohinter in place of the default interpreter.
406 The results are usually lower quality than correctly-hinted
407 fonts, but better than unhinted fonts.
411 style = lib.mkOption {
412 type = lib.types.enum [
420 Hintstyle is the amount of font reshaping done to line up
423 slight will make the font more fuzzy to line up to the grid but
424 will be better in retaining font shape, while full will be a
425 crisp font that aligns well to the pixel grid but will lose a
426 greater amount of font shape.
431 from = "fonts.fontconfig.hinting.style";
432 val' = lib.removePrefix "hint" val;
433 warning = "The option `${from}` contains a deprecated value `${val}`. Use `${val'}` instead.";
435 lib.warnIf (lib.hasPrefix "hint" val) warning val';
439 includeUserConf = lib.mkOption {
440 type = lib.types.bool;
443 Include the user configuration from
444 {file}`~/.config/fontconfig/fonts.conf` or
445 {file}`~/.config/fontconfig/conf.d`.
451 rgba = lib.mkOption {
453 type = lib.types.enum [
461 Subpixel order. The overwhelming majority of displays are
462 `rgb` in their normal orientation. Select
463 `vrgb` for mounting such a display 90 degrees
464 clockwise from its normal orientation or `vbgr`
465 for mounting 90 degrees counter-clockwise. Select
466 `bgr` in the unlikely event of mounting 180
467 degrees from the normal orientation. Reverse these directions in
468 the improbable event that the display's native subpixel order is
473 lcdfilter = lib.mkOption {
475 type = lib.types.enum [
482 FreeType LCD filter. At high resolution (> 200 DPI), LCD filtering
483 has no visible effect; users of such displays may want to select
490 cache32Bit = lib.mkOption {
492 type = lib.types.bool;
494 Generate system fonts cache for 32-bit applications.
498 allowBitmaps = lib.mkOption {
499 type = lib.types.bool;
502 Allow bitmap fonts. Set to `false` to ban all
507 allowType1 = lib.mkOption {
508 type = lib.types.bool;
511 Allow Type-1 fonts. Default is `false` because of
516 useEmbeddedBitmaps = lib.mkOption {
517 type = lib.types.bool;
519 description = "Use embedded bitmaps in fonts like Calibri.";
527 config = lib.mkMerge [
528 (lib.mkIf cfg.enable {
529 environment.systemPackages = [ pkgs.fontconfig ];
530 environment.etc.fonts.source = "${fontconfigEtc}/etc/fonts/";
531 security.apparmor.includes."abstractions/fonts" = ''
533 r ${pkg.out}/etc/fonts/fonts.conf,
535 # fontconfig default config files
536 r ${pkg.out}/etc/fonts/conf.d/*.conf,
538 # 00-nixos-cache.conf
541 # 10-nixos-rendering.conf
545 ${lib.optionalString cfg.includeUserConf ''
546 r ${pkg.out}/etc/fonts/conf.d.bak/50-user.conf,
549 # local.conf (indirect priority 51)
550 ${lib.optionalString (cfg.localConf != "") ''
554 # 52-nixos-default-fonts.conf
555 r ${defaultFontsConf},
560 ${lib.optionalString (!cfg.allowType1) ''
561 # 53-nixos-reject-type1.conf
566 (lib.mkIf cfg.enable {
567 fonts.fontconfig.confPackages = [ confPkg ];