From: north Date: Thu, 20 Dec 2007 02:55:09 +0000 (+0000) Subject: working on font faq X-Git-Tag: LAST_LIBGRAPH~32^2~4965 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3f2d4989650587d433c5823144dacdd0dc7a6523;p=graphviz working on font faq --- diff --git a/doc/fontfaq.txt b/doc/fontfaq.txt index cec8f31f7..f1591ebd1 100644 --- a/doc/fontfaq.txt +++ b/doc/fontfaq.txt @@ -1,138 +1,165 @@ Graphviz and fonts. =================== -The graphviz layout engines (dot, neato, etc) create layouts with nodes sized -to enclose the text labels. This requires knowing the size of the text blocks, -which in turn requires knowing the metrics of the font glyphs and their -composition into words, taking into account wordspacing, kerning, hinting, etc. - -The font is normally selected by family name, and any other required properties, -(see: FAQ item: "Font selection") then fontconfig is used to match the font request -to a specific font available on the system. (see FAQ item: "No fontconfig.") - -[Note. In older versions of dot, fontname was a font filename, which was -exact, and which either existed or it didn't. With fontconfig, fontnames are -now family names, which fontconfig will match to the closest font it can find. -This should always succeed, but unfortunately sometimes produces surprising -results if its idea of "close" doesn't match yours.] - -Text layout is normally performed by pango, which accepts text and -produces a layout with metrics which we can use to size the node shapes. -(See FAQ item: "No pango.") - -Line drawing is provided by cairo for many output formats, and likely more in -the future, however font rendering is passed though cairo to freetype. The same -is true if gd is used for drawing. (See FAQ items: "No cairo," "No gd.") - -Font rendering is provided by freetype, which provides antialiasing, hinting, -kerning, and other low-level font features. -(See FAQ item: "No freetype.") - -The font metrics are obtained using fonts available on the system running dot. -This works fine, except for outputs like -Tps and -Tsvg where the final rendering -may be done on a different platform altogether, where the same fonts might not -be available. For these cases (in PostScript only at this time) we pass down the -expected metrics of the text block to the renderer and ask it to make a final -stretch (or squeeze) to make the text fit the metrics that were used at layout time. - -Default fonts and PostScript fonts. -=================================== +Before we launch into the gory details, we would like to explain +why this is a hard problem. The naming and rendering of text fonts +in Graphviz (and other programs) is complicated. There are several reasons: + +- Graphviz runs on a wide range of systems: Linux and other Unix +variants, Microsoft Windows, and Mac. +- Graphviz has a wide range of output formats: raster-oriented formats +like PNG and GIF; path-based ones like Postscript, PDF and SVG; some +idiosyncractic legacy formats, like troff PIC and HPGL. +- Often, output will be downloaded and displayed on a computer or other +device, different than the one where the layout was created. +- Graphviz layouts should be identical in size and appearance, +regardless of the output format. +- Graphviz can run on external libraries that help with naming and +rendering text fonts, but they are not required, and stripped-down +Graphviz tools can be built without them. In fact, Graphviz may have +to run on systems with no font files installed. +- There are several major font file formats to be supported. +- Non-Western, international character sets should be supported. +- Graphviz should provide a good set of standard fonts. +- It should be easy to specify standard fonts. +- Users should be able to load their own custom fonts. +- Output should be small to download quickly. +- Output should allow the best rendering possible in a given format. +- Output files should be easy to postprocess, for example, retaining +the objects of the original graph if possible. +- It is very helpful to work around known bugs or missing features +in support libraries and popular external tools. + +This is a tall order. Some of the goals conflict. Generally our +approach has been to define defaults that favor convenience and good +looking output, and give the user options to override the defaults. + +===Overview=== + +In the following, we will assume a ''standard'' version of Graphviz +with the full set of support libraries (fontconfig, gd, Cairo and Pango), +running on a desktop system or server with a standard installation of +font files. + +The graphviz layout engines (dot, neato, etc) create layouts with nodes +sized to enclose the text labels. This requires knowing the size of +the text blocks, which in turn requires knowing the metrics of the font +glyphs and their composition into words, taking into account wordspacing, +kerning, hinting, etc. So the overall process is: font specification, +then text layout, followed by Graphviz output (and final rendering on +the target display or device, which may or may not be by a Graphviz tool.) + + +A font is usually selected by family name ("fontname") and other properties +(see below: "Font selection"). Then fontconfig matches the request +to a system font. [Note: in older versions of Graphviz, fontname was +simply a file name. This required exact file name matching (with a little +bit of helpful name mangling under the hood, e.g. translating Times-Roman +to Times, or Helvetica to Arial on Windows systems (and yes we know +there is a difference). Under fontconfig, fontnames are family names, +which fontconfig matches to the closest font it finds. This always +"succeeds", but unfortunately produces surprising results if fontconfig's +idea of "close" doesn't match yours. This can happen when you specify +a custom (or just nonexistent) font, like Steve-North-Handwriting, +and fontconfig silently falls back to something safe like a typewriter +font.] + +Text layout is performed by pango, which accepts text and computes a +layout with metrics that determine node sizes. + +Though line drawing is provided by cairo for many output formats (and +likely more in the future), for raster output formats, font rendering +is passed though cairo to freetype. Freetype is also called if gd is +used for drawing. (gd can also be requested explicitly, e.g. dot -Tpng:gd, +or by default when Graphviz is built without cairo). Freetype provides +antialiasing, hinting, kerning, and other low-level font features. + +Font metrics are obtained from the fonts installed on the system running +Graphviz. Results are guaranteed when Graphviz outputs raster formats, +because freetype immediately renders the fonts into pixels. On the +other hand, with path-based formats like Postscript (-Tps) and SVG (-Tsvg), +final rendering may be done on a different platform altogether, with +different font files installed. Clearly, Your Milage May Vary. In the +case of Postscript, the driver in Graphviz passes the expected metrics +of the text block down to the renderer, and asks it to make a final stretch +(or squeeze) to force the text to fit the metrics that were in effect at +layout time. In Graphviz SVG, there is only a hope and a prayer that +the SVG rendering program's fonts match the ones fontconfig and freetype +used when Graphviz was run. (More about this later.) + +Default fonts and PostScript fonts. =================================== The default font in graphviz is, and always has been, Times-Roman. -Unfortunately, fontconfig doesn't recognize this PostScript-style font -specification directly, so we have custom mappings from a basic set of -PostScipt fontnames into fontconfig family names for use in all cairo and gd -based renderers. In -Tps output, these fonts are used without name -translation. - -The supported PostScript fontnames are: - AvantGarde-Book - AvantGarde-BookOblique - AvantGarde-Demi - AvantGarde-DemiOblique - Bookman-Demi - Bookman-DemiItalic - Bookman-Light - Bookman-LightItalic - Courier - Courier-Bold - Courier-BoldOblique - Courier-Oblique - Helvetica - Helvetica-Bold - Helvetica-BoldOblique - Helvetica-Narrow - Helvetica-Narrow-Bold - Helvetica-Narrow-BoldOblique - Helvetica-Narrow-Oblique - Helvetica-Oblique - NewCenturySchlbk-Bold - NewCenturySchlbk-BoldItalic - NewCenturySchlbk-Italic - NewCenturySchlbk-Roman - Palatino-Bold - Palatino-BoldItalic - Palatino-Italic - Palatino-Roman - Symbol - Times-Bold - Times-BoldItalic - Times-Italic - Times-Roman - ZapfChancery-MediumItalic - ZapfDingbats - -Font selection. -=============== - -The fontname attribute in .dot graphs is a fontconfig style -specification. From: http://www.fontconfig.org/fontconfig-user.html - - Fontconfig provides a textual representation for patterns that the library can - both accept and generate. The representation is in three parts, first a list - of family names, second a list of point sizes and finally a list of additional - properties: + +Graphviz has historically supported some ``standard'' Postscript +fonts, initially, Times-Roman, Helvetica, Courier and Symbol. +This list was later enlarged by Adobe to include 35 fonts, which are: + AvantGarde-Book AvantGarde-BookOblique AvantGarde-Demi + AvantGarde-DemiOblique Bookman-Demi Bookman-DemiItalic + Bookman-Light Bookman-LightItalic Courier Courier-Bold + Courier-BoldOblique Courier-Oblique Helvetica + Helvetica-Bold Helvetica-BoldOblique Helvetica-Narrow + Helvetica-Narrow-Bold Helvetica-Narrow-BoldOblique + Helvetica-Narrow-Oblique Helvetica-Oblique NewCenturySchlbk-Bold + NewCenturySchlbk-BoldItalic NewCenturySchlbk-Italic + NewCenturySchlbk-Roman Palatino-Bold Palatino-BoldItalic + Palatino-Italic Palatino-Roman Symbol Times-Bold Times-BoldItalic + Times-Italic Times-Roman ZapfChancery-MediumItalic ZapfDingbats + +Unfortunately, fontconfig doesn't recognize PostScript-style font +names directly, so Graphviz makes custom mappings from its list of +PostScipt names into fontconfig family names for use in all cairo +and gd based renderers. In -Tps output, these fonts are used without +name translation. + +Font selection. =============== + +The fontname attribute in .dot graphs is a fontconfig style specification. +From: http://www.fontconfig.org/fontconfig-user.html + + Fontconfig provides a textual representation for patterns that + the library can both accept and generate. The representation is + in three parts, first a family name list, second list of point sizes, + and finally a list of additional properties: -:=:=... - - Values in a list are separated with commas. The name needn't include either - families or point sizes; they can be elided. In addition, there are symbolic - constants that simultaneously indicate both a name and a value. Here are some - examples: + Values in a list are separated with commas. The name needn't + include either a family or point size; they can be elided. In + addition, there are symbolic constants that simultaneously + indicate both a name and a value. Here are some examples: - Name Meaning - ---------------------------------------------------------- - Times-12 12 point Times Roman - Times-12:bold 12 point Times Bold - Courier:italic Courier Italic in the default size - Monospace:matrix=1 .1 0 1 The users preferred monospace font - with artificial obliquing + Name Meaning + ---------------------------------------------------------- + Times-12 12 point Times Roman + Times-12:bold 12 point Times Bold + Courier:italic Courier Italic in the default size + Monospace:matrix=1 .1 0 The users preferred monospace font + with artificial obliquing -In graphviz we currently have a seperate attribute for specififying fontsize. +Graphviz currently has a seperate attribute for specififying fontsize. [ FIXME - We should allow the fontconfig style specification. "Times-20" does not - currently result in a 20pt font. + We should allow the fontconfig style specification. "Times-20" does + not currently result in a 20pt font. - This is probably because of special treatment of '-' for postscript font - names. + This is probably because of special treatment of '-' for postscript + font names. ] [ FIXME - We seem to have a bug with use of ':' in fontnames, probably because of - special treatment for filenames in Windows. + We seem to have a bug with use of ':' in fontnames, probably because + of special treatment for filenames in Windows. In fontnames, use instead of ':' to separate values. - -Nfontname="Courier:italic" doesn't produce an italic font in graphviz-2.16.1, but: - -Nfontname="Courier italic" works, but + -Nfontname="Courier:italic" doesn't produce an italic font in + graphviz-2.16.1, but: -Nfontname="Courier italic" works, but -Nfontname="Monospace matrix=1 .1 0 1" doesn't. ] -Font management with fontconfig. -================================ +Font management with fontconfig. ================================ How can I tell what fonts are available? $ fc-list @@ -140,7 +167,11 @@ How can I tell what fonts are available? How can I tell what fonts dot is using; $ dot foo.dot -Tpng -o foo.png -v 2>&1 | grep font -How can I add a new font? +How can I add a custom font? +(Note, in current versions of Graphviz with fontconfig, Cairo and +Pango this cannot be done by simply putting a file in the +current directory or setting the DOTFONTPATH path variable. +Your custom font must be explicitly installed by fontconfig tools.) $ mkdir -p ~/.fonts $ cp foo.ttf ~/.fonts/ $ fc-cache @@ -149,69 +180,125 @@ How can I ... font? See: http://www.fontconfig.org/fontconfig-user.html Can I specifiy a font by filename instead of by familyname? - Not if fontconfig is enabled. + Sorry, the answer is no. {The reason is that for this to + work, Graphviz has to intercept the font lookup before + fontconfig is called, and this can't be done when fonts + are being looked up by Pango.) + [ FIXME - I thought we still recognized any fontname containing a path separator ( '/' - or '\') as a font filename. This doesn't seem to work anymore. + I thought we still recognized any fontname containing a path separator ( + '/' or '\') as a font filename. This doesn't seem to work anymore. ] How can I be sure that a specific font is selected? - Provide enough specification in the fontname, and test it with - fc-match to ensure that your desired font is selected. - (Note, this will not ensure that the same font is used in -Tps or - -Tsvg renderings where we rely on the fonts available on the final - printer or computer.) - - -No freetype. -============ - -If graphviz is built on systems without freetype, then only the gd renderer -will be available for bitmap outputs, and all fonts will revert to a set of -builtin bitmap fonts. The poor quality of these fonts will be evident, -also, "dot ... -v 2>&1 | grep font" will indicate that the font is "" - - -No fontconfig. -============== - -If graphviz is built on systems without fontconfig (e.g. Redhat-7) then the -fontname attribute will accept a filename for a fontfile and use gd and -freetype to obtain metrics and render the font. The PATH searched for fonts -can be specified with the GDFONTPATH environment variable. - -No pango/cairo renderers will be available without fontconfig support. - - -Disabling fontconfig. -===================== + Provide enough specification in the fontname, and test it + with fc-match to ensure that your desired font is selected. + (Note, this will not ensure that the same font is used in -Tps + or -Tsvg renderings where we rely on the fonts available on the + final printer or computer.) + + Note the downside, as mentioned previously, is that Graphviz cannot + do much to warn you when fontconfig didn't find a very + good match, because fontconfig just cheerfully falls back + to some standard font. It would be really nice if the + fontconfig developers could provide a metric reflecting the + quality of the font match in their API. + +What about SVG fonts? + Graphviz has a native SVG driver that we wrote (which is the + default), and cairo's SVG driver (which you get with -Tsvg:cairo). + + Graphviz' native SVG driver generates Windows compliant names + like "Times New Roman" or Arial by default. The names work in a + lot of situations (like Firefox running on Windows), but are + not guaranteed to be portable. If you set -Gfontnames=ps, + you get Postscript names like Times-Roman. If you set -Gfontnames=svg + you are guaranteed to get rock solid standards compliant SVG. + The SVG standard says that the legal generic font names + are Serif, Sans-Serif, and Monospace (plus Cursive and + Fantasy which we don't use in Graphviz). We generate those names. + The bad news is that various downstream renderers and editors + may resolve the generic font names differently, so it's not + quite clear how your SVG will look. Many W3C examples show + how to use CSS (Cascading Style Sheets) to get around this + problem by giving a list of font family names in order of + lookup precedence, but some downstream processors (like the + inkscape editor in Linux) don't implement CSS, so we're up a tree here. + + The cairo SVG driver solves this in an effective though brute + force way: it simply encodes embeds the needed fonts as lines and + curves in the target SVG. For small examples, -Tsvg:cairo is + about 10 times bigger than -Tsvg, but maybe it's worth it for + correctness. The other problem is that such SVG is much much + slower to render, no doubt because it bypasses any system + font rendering services, and does it the old fashioned way. + +What about Postscript fonts? + + say something here. What about non-ASCII like Latin1. + what about loading your own fonts via -L like in the old + days with the weird outline font example. + +==="What if" issues for nonstandard Graphviz builds=== +The following only apply if you build your own version of Graphviz +by configuring and compiling the source code to build your own +custom executable. If you don't know what this means, it +definitely does not mean you. + +No freetype. ============ + +When graphviz is built on systems without freetype, then only the gd +renderer will be available for bitmap outputs, and the only available +fonts are a small set of builtin bitmap fonts. The poor quality of +these fonts will be evident, also, "dot ... -v 2>&1 | grep font" will +say that the font is "". This may actually be desirable +for installing minimal graphviz programs on a server where fonts +may not even be installed. + + +No fontconfig. ============== + +If graphviz is built on systems without fontconfig (e.g. Redhat-7) then +the fontname attribute will be interpreted as a font file name. The +system directories will be searched for this, or the directories can +be specified with the GDFONTPATH environment variable (or DOTFONTPATH +for historical reasons). Graphviz will use gd and freetype to obtain +metrics and render text. No pango/cairo renderers will be available +without fontconfig support. + + +Disabling fontconfig. ===================== Pango/cairo depends on fontconfig, so to disable fontconfig you also have to disable pango/cairo. The easiest way to do this temporarily is to edit /usr/lib/graphviz/config and remove the entire "libpango" block. -[ Note that any changes to this file will be lost the next time graphviz +[Note that any changes to this file will be lost the next time graphviz is updated, or "dot -c" is run with installer priviledges.] -With pango disabled, graphviz will use gd which, even if it was built -with fontconfig support, will still allow fontnames to be given as filenames. +With pango disabled, graphviz will use gd which, even if it was built with +fontconfig support, will still allow fontnames to be given as filenames. +You can also disable cairopango at build time with configure script options. -No pango/cairo. -=============== -Without pango/cairo many of the renderers will available only via gd -which produces lower quality output. +No gd. ===== -Looking forward, we expect to depend more on pango for things like: line -wrapping, multiple fonts per label, bidi. text and other internationalization -features. +Cairopango works without gd. We are moving graphviz to the pango/cairo +libraries, but gd still offers some features that are hard to replace, +such as JPEGs, GIFs and paletted color bitmap outputs. However, font support +is fully functional without gd so long as pango, cairo, fontconfig, +freetype are available. +No pango/cairo. =============== -No gd -===== +Without pango/cairo, some of the key renderers are only available +with gd, which produces lower quality (but smaller) output. -We have been trying to move graphviz to the newer pango/cairo libraries, but -gd still offers some features that are hard to replace, such as JPGs, GIFs and -paletted color bitmap outputs. However, font support is fully functional without gd -so long as pango, cairo, fontconfig, freetype are available. +Looking forward, we expect to depend more on pango for things like: +line wrapping, multiple fonts per label, bidirectional text and +other internationalization features. +No gd and no cairopango ===== +This is basically the original Graphviz without any external fonts. +It cannot render any raster formats, so it's mainly good for Postscript. +It relies on a few internal font tables