1{ config, lib, pkgs, ... }:
2
3with lib;
4
5{
6
7 options = {
8
9 fonts = {
10
11 fontconfig = {
12 enable = mkOption {
13 type = types.bool;
14 default = true;
15 description = ''
16 If enabled, a Fontconfig configuration file will be built
17 pointing to a set of default fonts. If you don't care about
18 running X11 applications or any other program that uses
19 Fontconfig, you can turn this option off and prevent a
20 dependency on all those fonts.
21 '';
22 };
23
24 antialias = mkOption {
25 type = types.bool;
26 default = true;
27 description = "Enable font antialiasing.";
28 };
29
30 dpi = mkOption {
31 type = types.int;
32 default = 0;
33 description = ''
34 Force DPI setting. Setting to <literal>0</literal> disables DPI
35 forcing; the DPI detected for the display will be used.
36 '';
37 };
38
39 defaultFonts = {
40 monospace = mkOption {
41 type = types.listOf types.str;
42 default = ["DejaVu Sans Mono"];
43 description = ''
44 System-wide default monospace font(s). Multiple fonts may be
45 listed in case multiple languages must be supported.
46 '';
47 };
48
49 sansSerif = mkOption {
50 type = types.listOf types.str;
51 default = ["DejaVu Sans"];
52 description = ''
53 System-wide default sans serif font(s). Multiple fonts may be
54 listed in case multiple languages must be supported.
55 '';
56 };
57
58 serif = mkOption {
59 type = types.listOf types.str;
60 default = ["DejaVu Serif"];
61 description = ''
62 System-wide default serif font(s). Multiple fonts may be listed
63 in case multiple languages must be supported.
64 '';
65 };
66 };
67
68 hinting = {
69 enable = mkOption {
70 type = types.bool;
71 default = true;
72 description = "Enable TrueType hinting.";
73 };
74
75 autohint = mkOption {
76 type = types.bool;
77 default = true;
78 description = ''
79 Enable the autohinter, which provides hinting for otherwise
80 un-hinted fonts. The results are usually lower quality than
81 correctly-hinted fonts.
82 '';
83 };
84
85 style = mkOption {
86 type = types.str // {
87 check = flip elem ["none" "slight" "medium" "full"];
88 };
89 default = "full";
90 description = ''
91 TrueType hinting style, one of <literal>none</literal>,
92 <literal>slight</literal>, <literal>medium</literal>, or
93 <literal>full</literal>.
94 '';
95 };
96 };
97
98 includeUserConf = mkOption {
99 type = types.bool;
100 default = true;
101 description = ''
102 Include the user configuration from
103 <filename>~/.config/fontconfig/fonts.conf</filename> or
104 <filename>~/.config/fontconfig/conf.d</filename>.
105 '';
106 };
107
108 subpixel = {
109
110 rgba = mkOption {
111 type = types.string // {
112 check = flip elem ["rgb" "bgr" "vrgb" "vbgr" "none"];
113 };
114 default = "rgb";
115 description = ''
116 Subpixel order, one of <literal>none</literal>,
117 <literal>rgb</literal>, <literal>bgr</literal>,
118 <literal>vrgb</literal>, or <literal>vbgr</literal>.
119 '';
120 };
121
122 lcdfilter = mkOption {
123 type = types.str // {
124 check = flip elem ["none" "default" "light" "legacy"];
125 };
126 default = "default";
127 description = ''
128 FreeType LCD filter, one of <literal>none</literal>,
129 <literal>default</literal>, <literal>light</literal>, or
130 <literal>legacy</literal>.
131 '';
132 };
133
134 };
135
136 };
137
138 };
139
140 };
141
142 config =
143 let fontconfig = config.fonts.fontconfig;
144 fcBool = x: "<bool>" + (if x then "true" else "false") + "</bool>";
145 renderConf = ''
146 <?xml version='1.0'?>
147 <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
148 <fontconfig>
149
150 <!-- Default rendering settings -->
151 <match target="font">
152 <edit mode="assign" name="hinting">
153 ${fcBool fontconfig.hinting.enable}
154 </edit>
155 <edit mode="assign" name="autohint">
156 ${fcBool fontconfig.hinting.autohint}
157 </edit>
158 <edit mode="assign" name="hintstyle">
159 <const>hint${fontconfig.hinting.style}</const>
160 </edit>
161 <edit mode="assign" name="antialias">
162 ${fcBool fontconfig.antialias}
163 </edit>
164 <edit mode="assign" name="rgba">
165 <const>${fontconfig.subpixel.rgba}</const>
166 </edit>
167 <edit mode="assign" name="lcdfilter">
168 <const>lcd${fontconfig.subpixel.lcdfilter}</const>
169 </edit>
170 </match>
171
172 ${optionalString (fontconfig.dpi != 0) ''
173 <match target="pattern">
174 <edit name="dpi" mode="assign">
175 <double>${toString fontconfig.dpi}</double>
176 </edit>
177 </match>
178 ''}
179
180 </fontconfig>
181 '';
182 genericAliasConf = ''
183 <?xml version='1.0'?>
184 <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
185 <fontconfig>
186
187 <!-- Default fonts -->
188 ${optionalString (fontconfig.defaultFonts.sansSerif != []) ''
189 <alias>
190 <family>sans-serif</family>
191 <prefer>
192 ${concatStringsSep "\n"
193 (map (font: "<family>${font}</family>")
194 fontconfig.defaultFonts.sansSerif)}
195 </prefer>
196 </alias>
197 ''}
198 ${optionalString (fontconfig.defaultFonts.serif != []) ''
199 <alias>
200 <family>serif</family>
201 <prefer>
202 ${concatStringsSep "\n"
203 (map (font: "<family>${font}</family>")
204 fontconfig.defaultFonts.serif)}
205 </prefer>
206 </alias>
207 ''}
208 ${optionalString (fontconfig.defaultFonts.monospace != []) ''
209 <alias>
210 <family>monospace</family>
211 <prefer>
212 ${concatStringsSep "\n"
213 (map (font: "<family>${font}</family>")
214 fontconfig.defaultFonts.monospace)}
215 </prefer>
216 </alias>
217 ''}
218
219 </fontconfig>
220 '';
221 in mkIf fontconfig.enable {
222
223 # Fontconfig 2.10 backward compatibility
224
225 # Bring in the default (upstream) fontconfig configuration, only for fontconfig 2.10
226 environment.etc."fonts/fonts.conf".source =
227 pkgs.makeFontsConf { fontconfig = pkgs.fontconfig_210; fontDirectories = config.fonts.fonts; };
228
229 environment.etc."fonts/conf.d/10-nixos-rendering.conf".text = renderConf;
230 environment.etc."fonts/conf.d/60-nixos-generic-alias.conf".text = genericAliasConf;
231
232 # Versioned fontconfig > 2.10. Take shared fonts.conf from fontconfig.
233 # Otherwise specify only font directories.
234 environment.etc."fonts/${pkgs.fontconfig.configVersion}/fonts.conf".source =
235 "${pkgs.fontconfig}/etc/fonts/fonts.conf";
236
237 environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/00-nixos.conf".text =
238 ''
239 <?xml version='1.0'?>
240 <!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
241 <fontconfig>
242 <!-- Font directories -->
243 ${concatStringsSep "\n" (map (font: "<dir>${font}</dir>") config.fonts.fonts)}
244 </fontconfig>
245 '';
246
247 environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/10-nixos-rendering.conf".text = renderConf;
248 environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/60-nixos-generic-alias.conf".text = genericAliasConf;
249
250 environment.etc."fonts/${pkgs.fontconfig.configVersion}/conf.d/99-user.conf" = {
251 enable = fontconfig.includeUserConf;
252 text = ''
253 <?xml version="1.0"?>
254 <!DOCTYPE fontconfig SYSTEM "fonts.dtd">
255 <fontconfig>
256 <include ignore_missing="yes" prefix="xdg">fontconfig/conf.d</include>
257 <include ignore_missing="yes" prefix="xdg">fontconfig/fonts.conf</include>
258 </fontconfig>
259 '';
260 };
261
262 environment.systemPackages = [ pkgs.fontconfig ];
263
264 };
265
266}