Version 5, last updated by wycc at Sep 28 19:46 2010 UTC
Text Field API
For the implementation of the parser for the text node, please refer to Text Field Parser.
Text Field API
The text field API will define a mb_text_t type which can represent a text object. We can change the text, color, font family, size and other styled of individual characters. The SVG allow us to change the style of part of string like
<text style="style1">aaaa<tspan style="style2">bbbb</tspan>cccc</text>
The "aaaa" and "cccc" is defined by the style1 and the "bbbb" is defined by both style1 and style2. The style2 will override the setting in the style1. The text field API will help us to change the text tree in the runtime.
Text Segment
Each tspan will be converted into a text segment. The top level text segment must has x and y attribute. The x and y attribute of other level are optional. If the x and y attribute are not given, the will be generated at the runtime by using the following formula
seg->x = seg->parent->x + textwidth(seg->parent)
seg->y = seg->parent->y;
if (seg->x > seg->parent->maxx) {
seg->x = seg->parent->minx;
seg->y += fontheight(seg);
}
The textwidth is the width of a string in its style. It must consider kerning as well. The fontheight can be acquired from the font. If it is not available, we can use the ascent and descent to get its value. Please refer to the TinySVG 1.2 for the details. However, the text layout engine is not a travial task. We will not write it from scratch by ouselves. Instead, we should use the pango to do the job.
The pango is a text layout engine which is designed for the GTK. However, it can be used outside the GTK easily. The pango-cairo has been integrated already. Therefore, we can use the pango-cairo engine to draw the text. In this way, we don't need to write the text layout engine by ourself. We only need to convert the SVG properties into the pango properties.
An introduction to the pango is in IBM developer works. My notes about the pango is in Note Of PanGo.
Although the SVG represent the text field as a tree of tspan, we will convert it to be a flated list of text segments. Users of MadButterfly will not see the tspan at all. Each text segment has an independent set of attributes. The Text Field API will treat the all texts inside all text segments as a single string. The following API is used to get/set properties of each character. This API is very similiar to that of the Actionscript.
Text segment
Text segment is the internal data structure of the mb_text_t. Each mb_text_t will has a list of text segment inside it. Eacg text segment is composed of a mb_textstyle_t and a string buffer and a length of the string.
typedef struct {
mb_textstyle_t *style;
int n;
char *buf;
} mb_text_segment_t;
The mb_text_t will render all mb_text_segment_t inside it by using the pango-cairo. The same surface will be reused until the mb_text_t become dirty. If any style and text are changed by using the below APIs. The mb_text_t will become dirty and then it will regenerate the cairo surface in the next redraw. Otherwise, we will use the same cairo surface to redraw the text itself.
Text Style
mb_textstyle_t *mb_textstyle_new();
void mb_textstyle_set_font(mb_textstyle_t *style, char *fontname);
void mb_textstyle_set_bold(mb_textstyle_t *style, int bold);
void mb_textstyle_set_italic(mb_textstyle_t *style, int italic);
void mb_textstyle_set_underline(mb_textstyle_t *style, int underline);
void mb_textstyle_set_color(mb_textstyle_t *style, int color);
void mb_textstyle_set_alignment(mb_textstyle_t *style, int alignment);
mb_text_set_style
void mb_text_set_style(mb_text_t *text, int begin, int end, mb_textstyle_t *style);
Change the style between begin and end to be style. This function may create multiple text segments. If any text segment is completely inside begin and end, its style will replaced by the style. If it is not completely inside it, we will break the text segments into two parts. The part which is outside will keep the original style and the other part will be put inside a new segment.
If two adjunct segments are inside the begin and end, we will merge them together.
mb_text_get_style
mb_textstyle_t *mb_text_get_style(mb_text_t *text, int n);
Return the style at position n.
mb_text_set_text
void mb_text_set_text(mb_text_t *text, char *string, int begin, int end);
Replace the text between begin and end with string. If the string is longer than end-begin+1, extra characters will be inserted into the string by using the style of end.
mb_text_get_text
void mb_text_get_text(mb_text_t *text, int begin, int end, char *buf);
Return the text between begin and end.
