This page describes Inkscape's text processing.
Text processing is probably the most complicated part of the Inkscape code base. Processing text is a multistep process:
- Read in text, breaking it into chunks that have the same styling (usually a <tspan>) and a unique postion.
- Layout the text, taking into consideration styling (font, font-size, etc.).
- Render the text to screen.
Most of the code that handles text layout (including fonts) can be found in
src/libnrtype. The actual rendering code is in
src/drawing/drawing-text.cpp. (nr stands for New Renderer.) The GUI code is distributed over a number of files: for interactive on-screen editing look in
src/text-chemistry.cpp. The text Toolbar code is in
src/widgets/text-toolbar.cpp. The Text and Font dialog code is in
Types of Text
There are several distinct kinds of text in Inkscape:
- Normal SVG text. This is handled by the <text> and <tspan> elements. Inkscape always puts text inside a <tspan>. Multi-line text is mimicked by adding the attribute
sodipodi:role="line"to each <tspan> that represents a line. (One can also get multiline text by setting the 'white-space' property to preserve line feeds but there is no GUI and only Firefox supports this method.) The code for these elements is found in
- Flowed SVG 1.2 text. This text is flowed inside a shape. It is handled by the <flowtext> element. No browser implemented this type of text. The only know implementation other than Inkscape is in Batik (if the 'version' attribute is set to 1.2). The code for the elements used in flowed text is found in
- Text-on-a-path. This is text that flows along a path. It is handled by the <textPath> element. It is widely supported by browsers. The code for this element is found in
- SVG 2 Text-in-a-shape. This is text flowed inside a shape according to the rules of CSS. Inkscape can render such text. A GSoC project aims to replace Flowed SVG 1.2 text with this type of text. This method has the advantage that one can provide a natural fallback mechanism that works with SVG 1.1. It relies on CSS properties applied to the <text> element to define which shapes to fill.
Fonts are fundamental to the display of text. Font handling is partially operating system dependent.
Font handling code is in the following files found in
The Font Factory
The Font Factory handles retrieving a list of fonts from the operating system and stores the list in a map. If the compile time flag
USE_PANGO_WIN32 is set, the font factory uses
pango_win32_xxx functions to create the map, otherwise
pango_ft2_xxx functions are used.
The most important job of the Font Factory is to take the Pango description of a font (stored as a
PangoFontDescription) and return a font_instance that matches the description (see next section). As part of this process, the OpenType substitution tables are examined to build up a list of what glyph substitutions the font offers (this is not available when the
USE_PANGO_WIN32 flag is set).
Most of the rest of the Font Factory class code deals with extracting out information used for font selection in the GUI from the map such as a list of font families and their styles. A few adjustments are made to match Pango to CSS (Sans -> sans-serif, etc.). Pango is happy to synthesize bold and italic fonts. This is disabled except for the generic CSS faces ('sans-serif', 'serif', etc.).
The Font Instance
The font-instance class keeps track of a single font face. Like the Font Factory, the code depends on the the compile time flag
USE_PANGO_WIN32. The class functions provide access to font-wide data sush as the font's ascent, descent, and xheight.
Perhaps the most important function is
font_instance::LoadGlyph() which provides access to glyph data including the glyph outline. This glyph outline is used when rendering the glyph.
The Font Lister
The font_lister class sets up a
Gtk::ListStore containing all the fonts available on the system and those used in an SVG file (which may include fonts not on the system). It handles things like CSS 'font-family' values that include fallbacks as well as finding the best font to substitute when a specified font is not available.
A couple helper functions are also provided that are used in the GUI, including one that causes used fonts to be displayed in blue and unavailable fonts to be displayed with a red stike-through.
One weakness in the current implementation is that if two fonts have the same CSS property values, only the first is shown since there is no way to distinguish between the two using a
PangoFontDescription. To get around the limitation, CSS allows the use of the @font-face rule. It should be possible for Inkscape to add support for this rule.
Text layout is handled by first reading in a text object and breaking it up into chunks, one chunk for each piece of text that has a unique style or a specified position (through the 'x' or 'y' attributes) (
Layout-TNG_Input.cpp). Then a layout engine attempts to position each chunk in turn (
Layout-TNG-Compute.cpp). A chunk may be broken into smaller chunks if needed to by the line fitting algorithm (
Layout-TNG-Scanline-Makers.cpp). Finally, the text is output via the
Layout::show() function (
Text rendering is handled in
src/display/drawing-text.cpp. Text rendering is very similar to shape rendering except that the glyph outlines are used and that text decorations can be added.