Text
Introduction
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.
Source Code
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/ui/tools/text-tool.cpp
, src/text-editing.cpp
, and src/text-chemistry.cpp
. The text Toolbar code is in src/widgets/text-toolbar.cpp
. The Text and Font dialog code is in src/ui/dialog/text-edit.cpp
.
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 insrc/sp-text.cpp
andsrc/sp-tspan.cpp
. - 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
src/sp-flowtext.cpp
,src/sp-flowregion.cpp
, andsrc/sp-flowdiv.cpp
. - 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
sp-textpath.h
andsp-tspan.cpp
. - 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
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 src/libnrtype
:
FontFactory.h/FontFactory.cpp
font-instance.h/FontInstance.cpp
font-lister.h/FontLister.cpp
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
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 (Layout-TNG-Output.cpp
).
Text Rendering
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.