wolffd@0
|
1 Graphviz and fonts.
|
wolffd@0
|
2 ===================
|
wolffd@0
|
3
|
wolffd@0
|
4 Before we launch into the gory details, we would like to explain
|
wolffd@0
|
5 why this is a hard problem. The naming and rendering of text fonts
|
wolffd@0
|
6 in Graphviz (and other programs) is complicated. There are several reasons:
|
wolffd@0
|
7
|
wolffd@0
|
8 - Graphviz runs on a wide range of systems: Linux and other Unix
|
wolffd@0
|
9 variants, Microsoft Windows, and Mac.
|
wolffd@0
|
10 - Graphviz has a wide range of output formats: raster-oriented formats
|
wolffd@0
|
11 like PNG and GIF; path-based ones like Postscript, PDF and SVG; some
|
wolffd@0
|
12 idiosyncractic legacy formats, like troff PIC and HPGL.
|
wolffd@0
|
13 - Often, output will be downloaded and displayed on a computer or other
|
wolffd@0
|
14 device, different than the one where the layout was created.
|
wolffd@0
|
15 - Graphviz layouts should be identical in size and appearance,
|
wolffd@0
|
16 regardless of the output format.
|
wolffd@0
|
17 - Graphviz can run on external libraries that help with naming and
|
wolffd@0
|
18 rendering text fonts, but they are not required, and stripped-down
|
wolffd@0
|
19 Graphviz tools can be built without them. In fact, Graphviz may have
|
wolffd@0
|
20 to run on systems with no font files installed.
|
wolffd@0
|
21 - There are several major font file formats to be supported.
|
wolffd@0
|
22 - Non-Western, international character sets should be supported.
|
wolffd@0
|
23 - Graphviz should provide a good set of standard fonts.
|
wolffd@0
|
24 - It should be easy to specify standard fonts.
|
wolffd@0
|
25 - Users should be able to load their own custom fonts.
|
wolffd@0
|
26 - Output should be small to download quickly.
|
wolffd@0
|
27 - Output should allow the best rendering possible in a given format.
|
wolffd@0
|
28 - Output files should be easy to postprocess, for example, retaining
|
wolffd@0
|
29 the objects of the original graph if possible.
|
wolffd@0
|
30 - It is very helpful to work around known bugs or missing features
|
wolffd@0
|
31 in support libraries and popular external tools.
|
wolffd@0
|
32
|
wolffd@0
|
33 This is a tall order. Some of the goals conflict. Generally our
|
wolffd@0
|
34 approach has been to define defaults that favor convenience and good
|
wolffd@0
|
35 looking output, and give the user options to override the defaults.
|
wolffd@0
|
36
|
wolffd@0
|
37 ===Overview===
|
wolffd@0
|
38
|
wolffd@0
|
39 In the following, we will assume a ''standard'' version of Graphviz
|
wolffd@0
|
40 with the full set of support libraries (fontconfig, gd, Cairo and Pango),
|
wolffd@0
|
41 running on a desktop system or server with a standard installation of
|
wolffd@0
|
42 font files.
|
wolffd@0
|
43
|
wolffd@0
|
44 The graphviz layout engines (dot, neato, etc) create layouts with nodes
|
wolffd@0
|
45 sized to enclose the text labels. This requires knowing the size of
|
wolffd@0
|
46 the text blocks, which in turn requires knowing the metrics of the font
|
wolffd@0
|
47 glyphs and their composition into words, taking into account wordspacing,
|
wolffd@0
|
48 kerning, hinting, etc. So the overall process is: font specification,
|
wolffd@0
|
49 then text layout, followed by Graphviz output (and final rendering on
|
wolffd@0
|
50 the target display or device, which may or may not be by a Graphviz tool.)
|
wolffd@0
|
51
|
wolffd@0
|
52
|
wolffd@0
|
53 A font is usually selected by family name ("fontname") and other properties
|
wolffd@0
|
54 (see below: "Font selection"). Then fontconfig matches the request
|
wolffd@0
|
55 to a system font. [Note: in older versions of Graphviz, fontname was
|
wolffd@0
|
56 simply a file name. This required exact file name matching (with a little
|
wolffd@0
|
57 bit of helpful name mangling under the hood, e.g. translating Times-Roman
|
wolffd@0
|
58 to Times, or Helvetica to Arial on Windows systems (and yes we know
|
wolffd@0
|
59 there is a difference). Under fontconfig, fontnames are family names,
|
wolffd@0
|
60 which fontconfig matches to the closest font it finds. This always
|
wolffd@0
|
61 "succeeds", but unfortunately produces surprising results if fontconfig's
|
wolffd@0
|
62 idea of "close" doesn't match yours. This can happen when you specify
|
wolffd@0
|
63 a custom (or just nonexistent) font, like Steve-North-Handwriting,
|
wolffd@0
|
64 and fontconfig silently falls back to something safe like a typewriter
|
wolffd@0
|
65 font.]
|
wolffd@0
|
66
|
wolffd@0
|
67 Text layout is performed by pango, which accepts text and computes a
|
wolffd@0
|
68 layout with metrics that determine node sizes.
|
wolffd@0
|
69
|
wolffd@0
|
70 Though line drawing is provided by cairo for many output formats (and
|
wolffd@0
|
71 likely more in the future), for raster output formats, font rendering
|
wolffd@0
|
72 is passed though cairo to freetype. Freetype is also called if gd is
|
wolffd@0
|
73 used for drawing. (gd can also be requested explicitly, e.g. dot -Tpng:gd,
|
wolffd@0
|
74 or by default when Graphviz is built without cairo). Freetype provides
|
wolffd@0
|
75 antialiasing, hinting, kerning, and other low-level font features.
|
wolffd@0
|
76
|
wolffd@0
|
77 Font metrics are obtained from the fonts installed on the system running
|
wolffd@0
|
78 Graphviz. Results are guaranteed when Graphviz outputs raster formats,
|
wolffd@0
|
79 because freetype immediately renders the fonts into pixels. On the
|
wolffd@0
|
80 other hand, with path-based formats like Postscript (-Tps) and SVG (-Tsvg),
|
wolffd@0
|
81 final rendering may be done on a different platform altogether, with
|
wolffd@0
|
82 different font files installed. Clearly, Your Milage May Vary. In the
|
wolffd@0
|
83 case of Postscript, the driver in Graphviz passes the expected metrics
|
wolffd@0
|
84 of the text block down to the renderer, and asks it to make a final stretch
|
wolffd@0
|
85 (or squeeze) to force the text to fit the metrics that were in effect at
|
wolffd@0
|
86 layout time. In Graphviz SVG, there is only a hope and a prayer that
|
wolffd@0
|
87 the SVG rendering program's fonts match the ones fontconfig and freetype
|
wolffd@0
|
88 used when Graphviz was run. (More about this later.)
|
wolffd@0
|
89
|
wolffd@0
|
90 Default fonts and PostScript fonts. ===================================
|
wolffd@0
|
91
|
wolffd@0
|
92 The default font in graphviz is, and always has been, Times-Roman.
|
wolffd@0
|
93
|
wolffd@0
|
94 Graphviz has historically supported some ``standard'' Postscript
|
wolffd@0
|
95 fonts, initially, Times-Roman, Helvetica, Courier and Symbol.
|
wolffd@0
|
96 This list was later enlarged by Adobe to include 35 fonts, which are:
|
wolffd@0
|
97 AvantGarde-Book AvantGarde-BookOblique AvantGarde-Demi
|
wolffd@0
|
98 AvantGarde-DemiOblique Bookman-Demi Bookman-DemiItalic
|
wolffd@0
|
99 Bookman-Light Bookman-LightItalic Courier Courier-Bold
|
wolffd@0
|
100 Courier-BoldOblique Courier-Oblique Helvetica
|
wolffd@0
|
101 Helvetica-Bold Helvetica-BoldOblique Helvetica-Narrow
|
wolffd@0
|
102 Helvetica-Narrow-Bold Helvetica-Narrow-BoldOblique
|
wolffd@0
|
103 Helvetica-Narrow-Oblique Helvetica-Oblique NewCenturySchlbk-Bold
|
wolffd@0
|
104 NewCenturySchlbk-BoldItalic NewCenturySchlbk-Italic
|
wolffd@0
|
105 NewCenturySchlbk-Roman Palatino-Bold Palatino-BoldItalic
|
wolffd@0
|
106 Palatino-Italic Palatino-Roman Symbol Times-Bold Times-BoldItalic
|
wolffd@0
|
107 Times-Italic Times-Roman ZapfChancery-MediumItalic ZapfDingbats
|
wolffd@0
|
108
|
wolffd@0
|
109 Unfortunately, fontconfig doesn't recognize PostScript-style font
|
wolffd@0
|
110 names directly, so Graphviz makes custom mappings from its list of
|
wolffd@0
|
111 PostScipt names into fontconfig family names for use in all cairo
|
wolffd@0
|
112 and gd based renderers. In -Tps output, these fonts are used without
|
wolffd@0
|
113 name translation.
|
wolffd@0
|
114
|
wolffd@0
|
115 Font selection. ===============
|
wolffd@0
|
116
|
wolffd@0
|
117 The fontname attribute in .dot graphs is a fontconfig style specification.
|
wolffd@0
|
118 From: http://www.fontconfig.org/fontconfig-user.html
|
wolffd@0
|
119
|
wolffd@0
|
120 Fontconfig provides a textual representation for patterns that
|
wolffd@0
|
121 the library can both accept and generate. The representation is
|
wolffd@0
|
122 in three parts, first a family name list, second list of point sizes,
|
wolffd@0
|
123 and finally a list of additional properties:
|
wolffd@0
|
124
|
wolffd@0
|
125 <families>-<point sizes>:<name1>=<values1>:<name2>=<values2>...
|
wolffd@0
|
126
|
wolffd@0
|
127 Values in a list are separated with commas. The name needn't
|
wolffd@0
|
128 include either a family or point size; they can be elided. In
|
wolffd@0
|
129 addition, there are symbolic constants that simultaneously
|
wolffd@0
|
130 indicate both a name and a value. Here are some examples:
|
wolffd@0
|
131
|
wolffd@0
|
132 Name Meaning
|
wolffd@0
|
133 ----------------------------------------------------------
|
wolffd@0
|
134 Times-12 12 point Times Roman
|
wolffd@0
|
135 Times-12:bold 12 point Times Bold
|
wolffd@0
|
136 Courier:italic Courier Italic in the default size
|
wolffd@0
|
137 Monospace:matrix=1 .1 0 The users preferred monospace font
|
wolffd@0
|
138 with artificial obliquing
|
wolffd@0
|
139
|
wolffd@0
|
140 Graphviz currently has a seperate attribute for specififying fontsize.
|
wolffd@0
|
141
|
wolffd@0
|
142 [ FIXME
|
wolffd@0
|
143 We should allow the fontconfig style specification. "Times-20" does
|
wolffd@0
|
144 not currently result in a 20pt font.
|
wolffd@0
|
145
|
wolffd@0
|
146 This is probably because of special treatment of '-' for postscript
|
wolffd@0
|
147 font names.
|
wolffd@0
|
148 ]
|
wolffd@0
|
149
|
wolffd@0
|
150 [ FIXME
|
wolffd@0
|
151 We seem to have a bug with use of ':' in fontnames, probably because
|
wolffd@0
|
152 of special treatment for filenames in Windows.
|
wolffd@0
|
153
|
wolffd@0
|
154 In fontnames, use <space> instead of ':' to separate values.
|
wolffd@0
|
155
|
wolffd@0
|
156 -Nfontname="Courier:italic" doesn't produce an italic font in
|
wolffd@0
|
157 graphviz-2.16.1, but: -Nfontname="Courier italic" works, but
|
wolffd@0
|
158 -Nfontname="Monospace matrix=1 .1 0 1" doesn't.
|
wolffd@0
|
159 ]
|
wolffd@0
|
160
|
wolffd@0
|
161
|
wolffd@0
|
162 Font management with fontconfig. ================================
|
wolffd@0
|
163
|
wolffd@0
|
164 How can I tell what fonts are available?
|
wolffd@0
|
165 $ fc-list
|
wolffd@0
|
166
|
wolffd@0
|
167 How can I tell what fonts dot is using;
|
wolffd@0
|
168 $ dot foo.dot -Tpng -o foo.png -v 2>&1 | grep font
|
wolffd@0
|
169
|
wolffd@0
|
170 How can I add a custom font?
|
wolffd@0
|
171 In the current version of Graphviz with fontconfig, Cairo and
|
wolffd@0
|
172 Pango, this cannot be done by simply putting a file in the
|
wolffd@0
|
173 current directory or setting the DOTFONTPATH path variable.
|
wolffd@0
|
174 Your custom font must be explicitly installed by fontconfig tools.
|
wolffd@0
|
175
|
wolffd@0
|
176 For a single font, e.g., foo.ttf:
|
wolffd@0
|
177 $ mkdir -p ~/.fonts
|
wolffd@0
|
178 $ cp foo.ttf ~/.fonts/
|
wolffd@0
|
179
|
wolffd@0
|
180 One can run fc-cache to speed up the use of fontconfig.
|
wolffd@0
|
181 $ fc-cache
|
wolffd@0
|
182
|
wolffd@0
|
183 For Windows users, one can go to the C:\windows\fonts
|
wolffd@0
|
184 folder and use File -> Install New Font from the pull-down menus
|
wolffd@0
|
185 to install the font.
|
wolffd@0
|
186
|
wolffd@0
|
187 For a new font directory, e.g., /Library/Fonts, add a new <dir> element
|
wolffd@0
|
188
|
wolffd@0
|
189 <dir>/Library/Fonts</dir>
|
wolffd@0
|
190
|
wolffd@0
|
191 to a .conf file. Note that the file must have a correct xml structure
|
wolffd@0
|
192 as specified by the fontconfig fonts.dtd. Possible choices for the
|
wolffd@0
|
193 .conf file are local.conf in the same directory as the system-wide
|
wolffd@0
|
194 fonts.conf file, or .fonts.conf in your home directory.
|
wolffd@0
|
195
|
wolffd@0
|
196 How can I ... font?
|
wolffd@0
|
197 See: http://www.fontconfig.org/fontconfig-user.html
|
wolffd@0
|
198
|
wolffd@0
|
199 Can I specifiy a font by filename instead of by familyname?
|
wolffd@0
|
200 Sorry, the answer is no. {The reason is that for this to
|
wolffd@0
|
201 work, Graphviz has to intercept the font lookup before
|
wolffd@0
|
202 fontconfig is called, and this can't be done when fonts
|
wolffd@0
|
203 are being looked up by Pango.)
|
wolffd@0
|
204
|
wolffd@0
|
205 Some versions of fontconfig appear to recognize pathnames and
|
wolffd@0
|
206 attempt to use that, but this isn't always the case.
|
wolffd@0
|
207
|
wolffd@0
|
208 How can I be sure that a specific font is selected?
|
wolffd@0
|
209 Provide enough specification in the fontname, and test it
|
wolffd@0
|
210 with fc-match to ensure that your desired font is selected.
|
wolffd@0
|
211 (Note, this will not ensure that the same font is used in -Tps
|
wolffd@0
|
212 or -Tsvg renderings where we rely on the fonts available on the
|
wolffd@0
|
213 final printer or computer.)
|
wolffd@0
|
214
|
wolffd@0
|
215 Note the downside, as mentioned previously, is that Graphviz cannot
|
wolffd@0
|
216 do much to warn you when fontconfig didn't find a very
|
wolffd@0
|
217 good match, because fontconfig just cheerfully falls back
|
wolffd@0
|
218 to some standard font. It would be really nice if the
|
wolffd@0
|
219 fontconfig developers could provide a metric reflecting the
|
wolffd@0
|
220 quality of the font match in their API.
|
wolffd@0
|
221
|
wolffd@0
|
222 What about SVG fonts?
|
wolffd@0
|
223 Graphviz has a native SVG driver that we wrote (which is the
|
wolffd@0
|
224 default), and cairo's SVG driver (which you get with -Tsvg:cairo).
|
wolffd@0
|
225
|
wolffd@0
|
226 Graphviz' native SVG driver generates Windows compliant names
|
wolffd@0
|
227 like "Times New Roman" or Arial by default. The names work in a
|
wolffd@0
|
228 lot of situations (like Firefox running on Windows), but are
|
wolffd@0
|
229 not guaranteed to be portable. If you set -Gfontnames=ps,
|
wolffd@0
|
230 you get Postscript names like Times-Roman. If you set -Gfontnames=svg
|
wolffd@0
|
231 you are guaranteed to get rock solid standards compliant SVG.
|
wolffd@0
|
232 The SVG standard says that the legal generic font names
|
wolffd@0
|
233 are Serif, Sans-Serif, and Monospace (plus Cursive and
|
wolffd@0
|
234 Fantasy which we don't use in Graphviz). We generate those names.
|
wolffd@0
|
235 The bad news is that various downstream renderers and editors
|
wolffd@0
|
236 may resolve the generic font names differently, so it's not
|
wolffd@0
|
237 quite clear how your SVG will look. Many W3C examples show
|
wolffd@0
|
238 how to use CSS (Cascading Style Sheets) to get around this
|
wolffd@0
|
239 problem by giving a list of font family names in order of
|
wolffd@0
|
240 lookup precedence, but some downstream processors (like the
|
wolffd@0
|
241 inkscape editor in Linux) don't implement CSS, so we're up a tree here.
|
wolffd@0
|
242
|
wolffd@0
|
243 The cairo SVG driver solves this in an effective though brute
|
wolffd@0
|
244 force way: it simply encodes embeds the needed fonts as lines and
|
wolffd@0
|
245 curves in the target SVG. For small examples, -Tsvg:cairo is
|
wolffd@0
|
246 about 10 times bigger than -Tsvg, but maybe it's worth it for
|
wolffd@0
|
247 correctness. The other problem is that such SVG is much much
|
wolffd@0
|
248 slower to render, no doubt because it bypasses any system
|
wolffd@0
|
249 font rendering services, and does it the old fashioned way.
|
wolffd@0
|
250
|
wolffd@0
|
251 What about Postscript fonts?
|
wolffd@0
|
252
|
wolffd@0
|
253 say something here. What about non-ASCII like Latin1.
|
wolffd@0
|
254 what about loading your own fonts via -L like in the old
|
wolffd@0
|
255 days with the weird outline font example.
|
wolffd@0
|
256
|
wolffd@0
|
257 ==="What if" issues for nonstandard Graphviz builds===
|
wolffd@0
|
258 The following only apply if you build your own version of Graphviz
|
wolffd@0
|
259 by configuring and compiling the source code to build your own
|
wolffd@0
|
260 custom executable. If you don't know what this means, it
|
wolffd@0
|
261 definitely does not mean you.
|
wolffd@0
|
262
|
wolffd@0
|
263 No freetype. ============
|
wolffd@0
|
264
|
wolffd@0
|
265 When graphviz is built on systems without freetype, then only the gd
|
wolffd@0
|
266 renderer will be available for bitmap outputs, and the only available
|
wolffd@0
|
267 fonts are a small set of builtin bitmap fonts. The poor quality of
|
wolffd@0
|
268 these fonts will be evident, also, "dot ... -v 2>&1 | grep font" will
|
wolffd@0
|
269 say that the font is "<internal>". This may actually be desirable
|
wolffd@0
|
270 for installing minimal graphviz programs on a server where fonts
|
wolffd@0
|
271 may not even be installed.
|
wolffd@0
|
272
|
wolffd@0
|
273
|
wolffd@0
|
274 No fontconfig. ==============
|
wolffd@0
|
275
|
wolffd@0
|
276 If graphviz is built on systems without fontconfig (e.g. Redhat-7) then
|
wolffd@0
|
277 the fontname attribute will be interpreted as a font file name. The
|
wolffd@0
|
278 system directories will be searched for this, or the directories can
|
wolffd@0
|
279 be specified with the GDFONTPATH environment variable (or DOTFONTPATH
|
wolffd@0
|
280 for historical reasons). Graphviz will use gd and freetype to obtain
|
wolffd@0
|
281 metrics and render text. No pango/cairo renderers will be available
|
wolffd@0
|
282 without fontconfig support.
|
wolffd@0
|
283
|
wolffd@0
|
284
|
wolffd@0
|
285 Disabling fontconfig. =====================
|
wolffd@0
|
286
|
wolffd@0
|
287 Pango/cairo depends on fontconfig, so to disable fontconfig you also have
|
wolffd@0
|
288 to disable pango/cairo. The easiest way to do this temporarily is to
|
wolffd@0
|
289 edit /usr/lib/graphviz/config and remove the entire "libpango" block.
|
wolffd@0
|
290 [Note that any changes to this file will be lost the next time graphviz
|
wolffd@0
|
291 is updated, or "dot -c" is run with installer priviledges.]
|
wolffd@0
|
292
|
wolffd@0
|
293 With pango disabled, graphviz will use gd which, even if it was built with
|
wolffd@0
|
294 fontconfig support, will still allow fontnames to be given as filenames.
|
wolffd@0
|
295
|
wolffd@0
|
296 You can also disable cairopango at build time with configure script options.
|
wolffd@0
|
297
|
wolffd@0
|
298
|
wolffd@0
|
299 No gd. =====
|
wolffd@0
|
300
|
wolffd@0
|
301 Cairopango works without gd. We are moving graphviz to the pango/cairo
|
wolffd@0
|
302 libraries, but gd still offers some features that are hard to replace,
|
wolffd@0
|
303 such as JPEGs, GIFs and paletted color bitmap outputs. However, font support
|
wolffd@0
|
304 is fully functional without gd so long as pango, cairo, fontconfig,
|
wolffd@0
|
305 freetype are available.
|
wolffd@0
|
306
|
wolffd@0
|
307 No pango/cairo. ===============
|
wolffd@0
|
308
|
wolffd@0
|
309 Without pango/cairo, some of the key renderers are only available
|
wolffd@0
|
310 with gd, which produces lower quality (but smaller) output.
|
wolffd@0
|
311
|
wolffd@0
|
312 Looking forward, we expect to depend more on pango for things like:
|
wolffd@0
|
313 line wrapping, multiple fonts per label, bidirectional text and
|
wolffd@0
|
314 other internationalization features.
|
wolffd@0
|
315
|
wolffd@0
|
316 No gd and no cairopango =====
|
wolffd@0
|
317 This is basically the original Graphviz without any external fonts.
|
wolffd@0
|
318 It cannot render any raster formats, so it's mainly good for Postscript.
|
wolffd@0
|
319 It relies on a few internal font tables
|