3 NixOS support 2 fontconfig versions, "support" and "latest".
5 - "latest" refers to default fontconfig package (pkgs.fontconfig).
6 configuration files are linked to /etc/fonts/VERSION/conf.d/
7 - "support" refers to supportPkg (pkgs."fontconfig_${supportVersion}").
8 configuration files are linked to /etc/fonts/conf.d/
10 This module generates a package containing configuration files and link it in /etc/fonts.
12 Fontconfig reads files in folder name / file name order, so the number prepended to the configuration file name decide the order of parsing.
13 Low number means high priority.
17 { config, pkgs, lib, ... }:
22 cfg = config.fonts.fontconfig;
24 fcBool = x: "<bool>" + (boolToString x) + "</bool>";
26 # back-supported fontconfig version and package
27 # version is used for font cache generation
28 supportVersion = "210";
29 supportPkg = pkgs."fontconfig_${supportVersion}";
31 # latest fontconfig version and package
32 # version is used for configuration folder name, /etc/fonts/VERSION/
33 # note: format differs from supportVersion and can not be used with makeCacheConf
34 latestVersion = pkgs.fontconfig.configVersion;
35 latestPkg = pkgs.fontconfig;
37 # supported version fonts.conf
38 supportFontsConf = pkgs.makeFontsConf { fontconfig = supportPkg; fontDirectories = config.fonts.fonts; };
40 # configuration file to read fontconfig cache
43 cacheConfSupport = makeCacheConf { version = supportVersion; };
44 cacheConfLatest = makeCacheConf {};
46 # generate the font cache setting file for a fontconfig version
47 # use latest when no version is passed
48 # When cross-compiling, we can’t generate the cache, so we skip the
49 # <cachedir> part. fontconfig still works but is a little slower in
51 makeCacheConf = { version ? null }:
53 fcPackage = if version == null
55 else "fontconfig_${version}";
56 makeCache = fontconfig: pkgs.makeFontsCache { inherit fontconfig; fontDirectories = config.fonts.fonts; };
57 cache = makeCache pkgs.${fcPackage};
58 cache32 = makeCache pkgs.pkgsi686Linux.${fcPackage};
60 pkgs.writeText "fc-00-nixos-cache.conf" ''
62 <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
64 <!-- Font directories -->
65 ${concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.fonts)}
66 ${optionalString (pkgs.stdenv.hostPlatform == pkgs.stdenv.buildPlatform) ''
67 <!-- Pre-generated font caches -->
68 <cachedir>${cache}</cachedir>
69 ${optionalString (pkgs.stdenv.isx86_64 && cfg.cache32Bit) ''
70 <cachedir>${cache32}</cachedir>
76 # rendering settings configuration file
78 renderConf = pkgs.writeText "fc-10-nixos-rendering.conf" ''
80 <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
83 <!-- Default rendering settings -->
84 <match target="pattern">
85 <edit mode="append" name="hinting">
86 ${fcBool cfg.hinting.enable}
88 <edit mode="append" name="autohint">
89 ${fcBool cfg.hinting.autohint}
91 <edit mode="append" name="hintstyle">
92 <const>hintslight</const>
94 <edit mode="append" name="antialias">
95 ${fcBool cfg.antialias}
97 <edit mode="append" name="rgba">
98 <const>${cfg.subpixel.rgba}</const>
100 <edit mode="append" name="lcdfilter">
101 <const>lcd${cfg.subpixel.lcdfilter}</const>
105 ${optionalString (cfg.dpi != 0) ''
106 <match target="pattern">
107 <edit name="dpi" mode="assign">
108 <double>${toString cfg.dpi}</double>
116 # local configuration file
117 localConf = pkgs.writeText "fc-local.conf" cfg.localConf;
119 # default fonts configuration file
122 let genDefault = fonts: name:
123 optionalString (fonts != []) ''
124 <alias binding="same">
125 <family>${name}</family>
127 ${concatStringsSep ""
129 <family>${font}</family>
135 pkgs.writeText "fc-52-nixos-default-fonts.conf" ''
136 <?xml version='1.0'?>
137 <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
140 <!-- Default fonts -->
141 ${genDefault cfg.defaultFonts.sansSerif "sans-serif"}
143 ${genDefault cfg.defaultFonts.serif "serif"}
145 ${genDefault cfg.defaultFonts.monospace "monospace"}
147 ${genDefault cfg.defaultFonts.emoji "emoji"}
152 # bitmap font options
154 rejectBitmaps = pkgs.writeText "fc-53-no-bitmaps.conf" ''
155 <?xml version="1.0"?>
156 <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
159 ${optionalString (!cfg.allowBitmaps) ''
160 <!-- Reject bitmap fonts -->
164 <patelt name="scalable"><bool>false</bool></patelt>
170 <!-- Use embedded bitmaps in fonts like Calibri? -->
171 <match target="font">
172 <edit name="embeddedbitmap" mode="assign">
173 ${fcBool cfg.useEmbeddedBitmaps}
180 # reject Type 1 fonts
182 rejectType1 = pkgs.writeText "fc-53-nixos-reject-type1.conf" ''
183 <?xml version="1.0"?>
184 <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
187 <!-- Reject Type 1 fonts -->
191 <patelt name="fontformat"><string>Type 1</string></patelt>
199 # fontconfig configuration package
200 confPkg = pkgs.runCommand "fontconfig-conf" {
201 preferLocalBuild = true;
203 support_folder=$out/etc/fonts/conf.d
204 latest_folder=$out/etc/fonts/${latestVersion}/conf.d
206 mkdir -p $support_folder
207 mkdir -p $latest_folder
210 ln -s ${supportFontsConf} $support_folder/../fonts.conf
211 ln -s ${latestPkg.out}/etc/fonts/fonts.conf \
212 $latest_folder/../fonts.conf
214 # fontconfig default config files
215 ln -s ${supportPkg.out}/etc/fonts/conf.d/*.conf \
217 ln -s ${latestPkg.out}/etc/fonts/conf.d/*.conf \
220 # update latest 51-local.conf path to look at the latest local.conf
221 rm $latest_folder/51-local.conf
223 substitute ${latestPkg.out}/etc/fonts/conf.d/51-local.conf \
224 $latest_folder/51-local.conf \
225 --replace local.conf /etc/fonts/${latestVersion}/local.conf
227 # 00-nixos-cache.conf
228 ln -s ${cacheConfSupport} \
229 $support_folder/00-nixos-cache.conf
230 ln -s ${cacheConfLatest} $latest_folder/00-nixos-cache.conf
232 # 10-nixos-rendering.conf
233 ln -s ${renderConf} $support_folder/10-nixos-rendering.conf
234 ln -s ${renderConf} $latest_folder/10-nixos-rendering.conf
237 ${optionalString (!cfg.includeUserConf) ''
238 rm $support_folder/50-user.conf
239 rm $latest_folder/50-user.conf
242 # local.conf (indirect priority 51)
243 ${optionalString (cfg.localConf != "") ''
244 ln -s ${localConf} $support_folder/../local.conf
245 ln -s ${localConf} $latest_folder/../local.conf
248 # 52-nixos-default-fonts.conf
249 ln -s ${defaultFontsConf} $support_folder/52-nixos-default-fonts.conf
250 ln -s ${defaultFontsConf} $latest_folder/52-nixos-default-fonts.conf
253 ln -s ${rejectBitmaps} $support_folder/53-no-bitmaps.conf
254 ln -s ${rejectBitmaps} $latest_folder/53-no-bitmaps.conf
256 ${optionalString (!cfg.allowType1) ''
257 # 53-nixos-reject-type1.conf
258 ln -s ${rejectType1} $support_folder/53-nixos-reject-type1.conf
259 ln -s ${rejectType1} $latest_folder/53-nixos-reject-type1.conf
263 # Package with configuration files
264 # this merge all the packages in the fonts.fontconfig.confPackages list
265 fontconfigEtc = pkgs.buildEnv {
266 name = "fontconfig-etc";
267 paths = cfg.confPackages;
268 ignoreCollisions = true;
273 (mkRenamedOptionModule [ "fonts" "fontconfig" "ultimate" "allowBitmaps" ] [ "fonts" "fontconfig" "allowBitmaps" ])
274 (mkRenamedOptionModule [ "fonts" "fontconfig" "ultimate" "allowType1" ] [ "fonts" "fontconfig" "allowType1" ])
275 (mkRenamedOptionModule [ "fonts" "fontconfig" "ultimate" "useEmbeddedBitmaps" ] [ "fonts" "fontconfig" "useEmbeddedBitmaps" ])
276 (mkRenamedOptionModule [ "fonts" "fontconfig" "ultimate" "forceAutohint" ] [ "fonts" "fontconfig" "forceAutohint" ])
277 (mkRenamedOptionModule [ "fonts" "fontconfig" "ultimate" "renderMonoTTFAsBitmap" ] [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ])
278 (mkRemovedOptionModule [ "fonts" "fontconfig" "hinting" "style" ] "")
279 (mkRemovedOptionModule [ "fonts" "fontconfig" "forceAutohint" ] "")
280 (mkRemovedOptionModule [ "fonts" "fontconfig" "renderMonoTTFAsBitmap" ] "")
281 ] ++ lib.forEach [ "enable" "substitutions" "preset" ]
282 (opt: lib.mkRemovedOptionModule [ "fonts" "fontconfig" "ultimate" "${opt}" ] ''
283 The fonts.fontconfig.ultimate module and configuration is obsolete.
284 The repository has since been archived and activity has ceased.
285 https://github.com/bohoomil/fontconfig-ultimate/issues/171.
286 No action should be needed for font configuration, as the fonts.fontconfig
287 module is already used by default.
299 If enabled, a Fontconfig configuration file will be built
300 pointing to a set of default fonts. If you don't care about
301 running X11 applications or any other program that uses
302 Fontconfig, you can turn this option off and prevent a
303 dependency on all those fonts.
307 confPackages = mkOption {
309 type = with types; listOf path;
312 Fontconfig configuration packages.
316 antialias = mkOption {
320 Enable font antialiasing. At high resolution (> 200 DPI),
321 antialiasing has no visible effect; users of such displays may want
322 to disable this option.
330 Force DPI setting. Setting to <literal>0</literal> disables DPI
331 forcing; the DPI detected for the display will be used.
335 localConf = mkOption {
339 System-wide customization file contents, has higher priority than
340 <literal>defaultFonts</literal> settings.
345 monospace = mkOption {
346 type = types.listOf types.str;
347 default = ["DejaVu Sans Mono"];
349 System-wide default monospace font(s). Multiple fonts may be
350 listed in case multiple languages must be supported.
354 sansSerif = mkOption {
355 type = types.listOf types.str;
356 default = ["DejaVu Sans"];
358 System-wide default sans serif font(s). Multiple fonts may be
359 listed in case multiple languages must be supported.
364 type = types.listOf types.str;
365 default = ["DejaVu Serif"];
367 System-wide default serif font(s). Multiple fonts may be listed
368 in case multiple languages must be supported.
373 type = types.listOf types.str;
374 default = ["Noto Color Emoji"];
376 System-wide default emoji font(s). Multiple fonts may be listed
377 in case a font does not support all emoji.
379 Note that fontconfig matches color emoji fonts preferentially,
380 so if you want to use a black and white font while having
381 a color font installed (eg. Noto Color Emoji installed alongside
382 Noto Emoji), fontconfig will still choose the color font even
383 when it is later in the list.
393 Enable font hinting. Hinting aligns glyphs to pixel boundaries to
394 improve rendering sharpness at low resolution. At high resolution
395 (> 200 dpi) hinting will do nothing (at best); users of such
396 displays may want to disable this option.
400 autohint = mkOption {
404 Enable the autohinter in place of the default interpreter.
405 The results are usually lower quality than correctly-hinted
406 fonts, but better than unhinted fonts.
411 includeUserConf = mkOption {
415 Include the user configuration from
416 <filename>~/.config/fontconfig/fonts.conf</filename> or
417 <filename>~/.config/fontconfig/conf.d</filename>.
425 type = types.enum ["rgb" "bgr" "vrgb" "vbgr" "none"];
427 Subpixel order. The overwhelming majority of displays are
428 <literal>rgb</literal> in their normal orientation. Select
429 <literal>vrgb</literal> for mounting such a display 90 degrees
430 clockwise from its normal orientation or <literal>vbgr</literal>
431 for mounting 90 degrees counter-clockwise. Select
432 <literal>bgr</literal> in the unlikely event of mounting 180
433 degrees from the normal orientation. Reverse these directions in
434 the improbable event that the display's native subpixel order is
435 <literal>bgr</literal>.
439 lcdfilter = mkOption {
441 type = types.enum ["none" "default" "light" "legacy"];
443 FreeType LCD filter. At high resolution (> 200 DPI), LCD filtering
444 has no visible effect; users of such displays may want to select
445 <literal>none</literal>.
451 cache32Bit = mkOption {
455 Generate system fonts cache for 32-bit applications.
459 allowBitmaps = mkOption {
463 Allow bitmap fonts. Set to <literal>false</literal> to ban all
468 allowType1 = mkOption {
472 Allow Type-1 fonts. Default is <literal>false</literal> because of
477 useEmbeddedBitmaps = mkOption {
480 description = ''Use embedded bitmaps in fonts like Calibri.'';
490 environment.systemPackages = [ pkgs.fontconfig ];
491 environment.etc.fonts.source = "${fontconfigEtc}/etc/fonts/";
492 security.apparmor.includes."abstractions/fonts" = ''
494 r ${supportFontsConf}
495 r ${latestPkg.out}/etc/fonts/fonts.conf
497 # fontconfig default config files
498 r ${supportPkg.out}/etc/fonts/conf.d/*.conf,
499 r ${latestPkg.out}/etc/fonts/conf.d/*.conf,
501 substitute ${latestPkg.out}/etc/fonts/conf.d/51-local.conf \
502 $latest_folder/51-local.conf \
503 --replace local.conf /etc/fonts/${latestVersion}/local.conf
505 # 00-nixos-cache.conf
506 r ${cacheConfSupport},
507 r ${cacheConfLatest},
509 # 10-nixos-rendering.conf
512 # local.conf (indirect priority 51)
513 ${optionalString (cfg.localConf != "") ''
517 # 52-nixos-default-fonts.conf
518 r ${defaultFontsConf},
523 ${optionalString (!cfg.allowType1) ''
524 # 53-nixos-reject-type1.conf
529 (mkIf (cfg.enable && !cfg.penultimate.enable) {
530 fonts.fontconfig.confPackages = [ confPkg ];