at 18.09-beta 15 kB view raw
1/* 2 3NixOS support 2 fontconfig versions, "support" and "latest". 4 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/ 9 10This module generates a package containing configuration files and link it in /etc/fonts. 11 12Fontconfig reads files in folder name / file name order, so the number prepended to the configuration file name decide the order of parsing. 13Low number means high priority. 14 15*/ 16 17{ config, lib, pkgs, ... }: 18 19with lib; 20 21let cfg = config.fonts.fontconfig; 22 23 fcBool = x: "<bool>" + (boolToString x) + "</bool>"; 24 25 # back-supported fontconfig version and package 26 # version is used for font cache generation 27 supportVersion = "210"; 28 supportPkg = pkgs."fontconfig_${supportVersion}"; 29 30 # latest fontconfig version and package 31 # version is used for configuration folder name, /etc/fonts/VERSION/ 32 # note: format differs from supportVersion and can not be used with makeCacheConf 33 latestVersion = pkgs.fontconfig.configVersion; 34 latestPkg = pkgs.fontconfig; 35 36 # supported version fonts.conf 37 supportFontsConf = pkgs.makeFontsConf { fontconfig = supportPkg; fontDirectories = config.fonts.fonts; }; 38 39 # configuration file to read fontconfig cache 40 # version dependent 41 # priority 0 42 cacheConfSupport = makeCacheConf { version = supportVersion; }; 43 cacheConfLatest = makeCacheConf {}; 44 45 # generate the font cache setting file for a fontconfig version 46 # use latest when no version is passed 47 makeCacheConf = { version ? null }: 48 let 49 fcPackage = if builtins.isNull version 50 then "fontconfig" 51 else "fontconfig_${version}"; 52 makeCache = fontconfig: pkgs.makeFontsCache { inherit fontconfig; fontDirectories = config.fonts.fonts; }; 53 cache = makeCache pkgs."${fcPackage}"; 54 cache32 = makeCache pkgs.pkgsi686Linux."${fcPackage}"; 55 in 56 pkgs.writeText "fc-00-nixos-cache.conf" '' 57 <?xml version='1.0'?> 58 <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> 59 <fontconfig> 60 <!-- Font directories --> 61 ${concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.fonts)} 62 <!-- Pre-generated font caches --> 63 <cachedir>${cache}</cachedir> 64 ${optionalString (pkgs.stdenv.isx86_64 && cfg.cache32Bit) '' 65 <cachedir>${cache32}</cachedir> 66 ''} 67 </fontconfig> 68 ''; 69 70 # rendering settings configuration file 71 # priority 10 72 renderConf = pkgs.writeText "fc-10-nixos-rendering.conf" '' 73 <?xml version='1.0'?> 74 <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> 75 <fontconfig> 76 77 <!-- Default rendering settings --> 78 <match target="pattern"> 79 <edit mode="append" name="hinting"> 80 ${fcBool cfg.hinting.enable} 81 </edit> 82 <edit mode="append" name="autohint"> 83 ${fcBool cfg.hinting.autohint} 84 </edit> 85 <edit mode="append" name="hintstyle"> 86 <const>hintslight</const> 87 </edit> 88 <edit mode="append" name="antialias"> 89 ${fcBool cfg.antialias} 90 </edit> 91 <edit mode="append" name="rgba"> 92 <const>${cfg.subpixel.rgba}</const> 93 </edit> 94 <edit mode="append" name="lcdfilter"> 95 <const>lcd${cfg.subpixel.lcdfilter}</const> 96 </edit> 97 </match> 98 99 ${optionalString (cfg.dpi != 0) '' 100 <match target="pattern"> 101 <edit name="dpi" mode="assign"> 102 <double>${toString cfg.dpi}</double> 103 </edit> 104 </match> 105 ''} 106 107 </fontconfig> 108 ''; 109 110 # local configuration file 111 # priority 51 112 localConf = pkgs.writeText "fc-local.conf" cfg.localConf; 113 114 # default fonts configuration file 115 # priority 52 116 defaultFontsConf = 117 let genDefault = fonts: name: 118 optionalString (fonts != []) '' 119 <alias> 120 <family>${name}</family> 121 <prefer> 122 ${concatStringsSep "" 123 (map (font: '' 124 <family>${font}</family> 125 '') fonts)} 126 </prefer> 127 </alias> 128 ''; 129 in 130 pkgs.writeText "fc-52-nixos-default-fonts.conf" '' 131 <?xml version='1.0'?> 132 <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'> 133 <fontconfig> 134 135 <!-- Default fonts --> 136 ${genDefault cfg.defaultFonts.sansSerif "sans-serif"} 137 138 ${genDefault cfg.defaultFonts.serif "serif"} 139 140 ${genDefault cfg.defaultFonts.monospace "monospace"} 141 142 </fontconfig> 143 ''; 144 145 # bitmap font options 146 # priority 53 147 rejectBitmaps = pkgs.writeText "fc-53-nixos-bitmaps.conf" '' 148 <?xml version="1.0"?> 149 <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> 150 <fontconfig> 151 152 ${optionalString (!cfg.allowBitmaps) '' 153 <!-- Reject bitmap fonts --> 154 <selectfont> 155 <rejectfont> 156 <pattern> 157 <patelt name="scalable"><bool>false</bool></patelt> 158 </pattern> 159 </rejectfont> 160 </selectfont> 161 ''} 162 163 <!-- Use embedded bitmaps in fonts like Calibri? --> 164 <match target="font"> 165 <edit name="embeddedbitmap" mode="assign"> 166 ${fcBool cfg.useEmbeddedBitmaps} 167 </edit> 168 </match> 169 170 </fontconfig> 171 ''; 172 173 # reject Type 1 fonts 174 # priority 53 175 rejectType1 = pkgs.writeText "fc-53-nixos-reject-type1.conf" '' 176 <?xml version="1.0"?> 177 <!DOCTYPE fontconfig SYSTEM "fonts.dtd"> 178 <fontconfig> 179 180 <!-- Reject Type 1 fonts --> 181 <selectfont> 182 <rejectfont> 183 <pattern> 184 <patelt name="fontformat"><string>Type 1</string></patelt> 185 </pattern> 186 </rejectfont> 187 </selectfont> 188 189 </fontconfig> 190 ''; 191 192 # fontconfig configuration package 193 confPkg = pkgs.runCommand "fontconfig-conf" {} '' 194 support_folder=$out/etc/fonts 195 latest_folder=$out/etc/fonts/${latestVersion} 196 197 mkdir -p $support_folder/conf.d 198 mkdir -p $latest_folder/conf.d 199 200 # fonts.conf 201 ln -s ${supportFontsConf} $support_folder/fonts.conf 202 ln -s ${latestPkg.out}/etc/fonts/fonts.conf \ 203 $latest_folder/fonts.conf 204 205 # fontconfig default config files 206 ln -s ${supportPkg.out}/etc/fonts/conf.d/*.conf \ 207 $support_folder/conf.d/ 208 ln -s ${latestPkg.out}/etc/fonts/conf.d/*.conf \ 209 $latest_folder/conf.d/ 210 211 # update latest 51-local.conf path to look at the latest local.conf 212 rm $latest_folder/conf.d/51-local.conf 213 214 substitute ${latestPkg.out}/etc/fonts/conf.d/51-local.conf \ 215 $latest_folder/conf.d/51-local.conf \ 216 --replace local.conf /etc/fonts/${latestVersion}/local.conf 217 218 # 00-nixos-cache.conf 219 ln -s ${cacheConfSupport} \ 220 $support_folder/conf.d/00-nixos-cache.conf 221 ln -s ${cacheConfLatest} $latest_folder/conf.d/00-nixos-cache.conf 222 223 # 10-nixos-rendering.conf 224 ln -s ${renderConf} $support_folder/conf.d/10-nixos-rendering.conf 225 ln -s ${renderConf} $latest_folder/conf.d/10-nixos-rendering.conf 226 227 # 50-user.conf 228 ${optionalString (! cfg.includeUserConf) '' 229 rm $support_folder/conf.d/50-user.conf 230 rm $latest_folder/conf.d/50-user.conf 231 ''} 232 233 # local.conf (indirect priority 51) 234 ${optionalString (cfg.localConf != "") '' 235 ln -s ${localConf} $support_folder/local.conf 236 ln -s ${localConf} $latest_folder/local.conf 237 ''} 238 239 # 52-nixos-default-fonts.conf 240 ln -s ${defaultFontsConf} $support_folder/conf.d/52-nixos-default-fonts.conf 241 ln -s ${defaultFontsConf} $latest_folder/conf.d/52-nixos-default-fonts.conf 242 243 # 53-nixos-bitmaps.conf 244 ln -s ${rejectBitmaps} $support_folder/conf.d/53-nixos-bitmaps.conf 245 ln -s ${rejectBitmaps} $latest_folder/conf.d/53-nixos-bitmaps.conf 246 247 ${optionalString (! cfg.allowType1) '' 248 # 53-nixos-reject-type1.conf 249 ln -s ${rejectType1} $support_folder/conf.d/53-nixos-reject-type1.conf 250 ln -s ${rejectType1} $latest_folder/conf.d/53-nixos-reject-type1.conf 251 ''} 252 ''; 253 254 # Package with configuration files 255 # this merge all the packages in the fonts.fontconfig.confPackages list 256 fontconfigEtc = pkgs.buildEnv { 257 name = "fontconfig-etc"; 258 paths = cfg.confPackages; 259 ignoreCollisions = true; 260 }; 261in 262{ 263 264 options = { 265 266 fonts = { 267 268 fontconfig = { 269 enable = mkOption { 270 type = types.bool; 271 default = true; 272 description = '' 273 If enabled, a Fontconfig configuration file will be built 274 pointing to a set of default fonts. If you don't care about 275 running X11 applications or any other program that uses 276 Fontconfig, you can turn this option off and prevent a 277 dependency on all those fonts. 278 ''; 279 }; 280 281 confPackages = mkOption { 282 internal = true; 283 type = with types; listOf path; 284 default = [ ]; 285 description = '' 286 Fontconfig configuration packages. 287 ''; 288 }; 289 290 antialias = mkOption { 291 type = types.bool; 292 default = true; 293 description = '' 294 Enable font antialiasing. At high resolution (> 200 DPI), 295 antialiasing has no visible effect; users of such displays may want 296 to disable this option. 297 ''; 298 }; 299 300 dpi = mkOption { 301 type = types.int; 302 default = 0; 303 description = '' 304 Force DPI setting. Setting to <literal>0</literal> disables DPI 305 forcing; the DPI detected for the display will be used. 306 ''; 307 }; 308 309 localConf = mkOption { 310 type = types.lines; 311 default = ""; 312 description = '' 313 System-wide customization file contents, has higher priority than 314 <literal>defaultFonts</literal> settings. 315 ''; 316 }; 317 318 defaultFonts = { 319 monospace = mkOption { 320 type = types.listOf types.str; 321 default = ["DejaVu Sans Mono"]; 322 description = '' 323 System-wide default monospace font(s). Multiple fonts may be 324 listed in case multiple languages must be supported. 325 ''; 326 }; 327 328 sansSerif = mkOption { 329 type = types.listOf types.str; 330 default = ["DejaVu Sans"]; 331 description = '' 332 System-wide default sans serif font(s). Multiple fonts may be 333 listed in case multiple languages must be supported. 334 ''; 335 }; 336 337 serif = mkOption { 338 type = types.listOf types.str; 339 default = ["DejaVu Serif"]; 340 description = '' 341 System-wide default serif font(s). Multiple fonts may be listed 342 in case multiple languages must be supported. 343 ''; 344 }; 345 }; 346 347 hinting = { 348 enable = mkOption { 349 type = types.bool; 350 default = true; 351 description = '' 352 Enable font hinting. Hinting aligns glyphs to pixel boundaries to 353 improve rendering sharpness at low resolution. At high resolution 354 (> 200 dpi) hinting will do nothing (at best); users of such 355 displays may want to disable this option. 356 ''; 357 }; 358 359 autohint = mkOption { 360 type = types.bool; 361 default = false; 362 description = '' 363 Enable the autohinter in place of the default interpreter. 364 The results are usually lower quality than correctly-hinted 365 fonts, but better than unhinted fonts. 366 ''; 367 }; 368 }; 369 370 includeUserConf = mkOption { 371 type = types.bool; 372 default = true; 373 description = '' 374 Include the user configuration from 375 <filename>~/.config/fontconfig/fonts.conf</filename> or 376 <filename>~/.config/fontconfig/conf.d</filename>. 377 ''; 378 }; 379 380 subpixel = { 381 382 rgba = mkOption { 383 default = "rgb"; 384 type = types.enum ["rgb" "bgr" "vrgb" "vbgr" "none"]; 385 description = '' 386 Subpixel order. The overwhelming majority of displays are 387 <literal>rgb</literal> in their normal orientation. Select 388 <literal>vrgb</literal> for mounting such a display 90 degrees 389 clockwise from its normal orientation or <literal>vbgr</literal> 390 for mounting 90 degrees counter-clockwise. Select 391 <literal>bgr</literal> in the unlikely event of mounting 180 392 degrees from the normal orientation. Reverse these directions in 393 the improbable event that the display's native subpixel order is 394 <literal>bgr</literal>. 395 ''; 396 }; 397 398 lcdfilter = mkOption { 399 default = "default"; 400 type = types.enum ["none" "default" "light" "legacy"]; 401 description = '' 402 FreeType LCD filter. At high resolution (> 200 DPI), LCD filtering 403 has no visible effect; users of such displays may want to select 404 <literal>none</literal>. 405 ''; 406 }; 407 408 }; 409 410 cache32Bit = mkOption { 411 default = false; 412 type = types.bool; 413 description = '' 414 Generate system fonts cache for 32-bit applications. 415 ''; 416 }; 417 418 allowBitmaps = mkOption { 419 type = types.bool; 420 default = true; 421 description = '' 422 Allow bitmap fonts. Set to <literal>false</literal> to ban all 423 bitmap fonts. 424 ''; 425 }; 426 427 allowType1 = mkOption { 428 type = types.bool; 429 default = false; 430 description = '' 431 Allow Type-1 fonts. Default is <literal>false</literal> because of 432 poor rendering. 433 ''; 434 }; 435 436 useEmbeddedBitmaps = mkOption { 437 type = types.bool; 438 default = false; 439 description = ''Use embedded bitmaps in fonts like Calibri.''; 440 }; 441 442 }; 443 444 }; 445 446 }; 447 config = mkMerge [ 448 (mkIf cfg.enable { 449 environment.systemPackages = [ pkgs.fontconfig ]; 450 environment.etc.fonts.source = "${fontconfigEtc}/etc/fonts/"; 451 }) 452 (mkIf (cfg.enable && !cfg.penultimate.enable) { 453 fonts.fontconfig.confPackages = [ confPkg ]; 454 }) 455 ]; 456 457}