Note Of PanGo

History Key

  • New content
  • Removed content

Recent Versions

Choose two versions to compare, or click the link to view it.

  1. 2. over 3 years by wycc
  2. 1. over 3 years by wycc
 

The programming model of pango

The pango API will store the attributes of the text in a separate data structure PangoAttrList. The PangoAttrList contains a list of PangoAttribute. Each PangoAttribute contains an attribute, such as font or color, and start and end position. The attribute will be applied into the specified range of the text.

The PangoAttribute is defined as

struct _PangoAttribute
{
  const PangoAttrClass *klass;
  guint start_index;    /* in bytes */
  guint end_index;      /* in bytes. The character at this index is not included */
};

We need to specify the start_index and end_index to indicate the range of the text, which this attribute is applied into. For example, we can use the following code to change the font size to 30 from 3rd to 10th characters in the string.

PangoAttribute *attr = pango_attr_size_new(30);
attr->start_index = 2;
attr->end_index = 9;
pango_attr_list_insert(attrlist, attr);

The range of each attribute can be overlapped. The pango_itemize will generate a list of PangoItem which can be used to render the text. Each PangoItem contains a range of text and a PangoAnalysis. The PangoAnalysis contains all attributes for each text segments. We can use this list to render the text segment one by one. The pango_shape can help us to generate a PangoGlyphString which can be used to draw on the backend. For example, for the cairo backend, we can use

items = pango_itemize(context, text,0,strlen(text), attrlist, NULL);
while(items) {
    PangoItem *item = (PangoItem *) items->data;
    pango_shape(text+item->offset,item->length, &item->analysis, glyphstr);
    cairo_moveto(cr,x,y);
    pango_cairo_show_glyph_string(cr, font, glyphstr);
    ...... update x and y ..........
    items=items->next;
}

High level API

We can use the above API to render the text on the cairo surface. However, the above API does not provide the layout capability. It means that we need to set the current position of each item in the cairo manually like the above example. The pango provide a higher level API which can decide the position of each item for us. This is defined in the pango_layout_xxxx. We will use the pango cairo as example. Other backend renderer will have similar functions.

The pango_cairo_create_layout can be used to create a layout from the cairo surface. We can use pango_layout_set_text to set the text buffer of the layout engine. We can use the pango_layout_set_markup to feed the text and attributes into the layout. Of course, we can choice to use the pango_layout_set_attributes to associate the attributes information for the text separately.

In additio to the attributes, we need to setup the layout parameters as well. The pango layout provides the following parameters

  • width: pango_layout_set_width
  • height: pango_layout_set_height
  • line breaking mode: pango_layout_set_wrap
  • ellipsize: pamgo_layout_set_ellipsize
  • indent: pango_layout_set_indent
  • spacing: pango_layout_set_spacing
  • justify: pango_layout_set_justfify
  • auto_dir: pango_layout_set_auto_dir
  • alignment: pango_layout_set_alignment
  • tabs: pango_layout_set_tabs

After the text and attributes of the text is assigned, we can use the pango_cairo_show_layout to draw the content of the layout on the cairo surface. We can use pango layout to implement the text field API easily. We explain each of them below.

Implementation of the text field API in pamgopango

mb_text_new

We can call pango_cairo_create_layout to create an instance of pango layout and stored it inside the mb_text_t.

mb_text_set_text

This function is a simple pango_layout_set_text.

mb_text_set_style

We will use the pango_layout_get_attributes to get the PangoAttrList of the layout. And then convert the mb_textstyle_t into the PangoAttribute. We may need to create multiple PangoAttribute for the mb_textstyle_t. We can use the pango_attr_list_insert to append the new attribute and the use the pango_layout_set_attributes to updatethe attribute list.

However, there is one issue here. Since we append the new attribute in each call, the number of attributes might become very large if we call this function repeatly. Therefore, we will do an optimize. We will iterate the attribute list. If one attribute if completely hidden by the new attribute, we will remove it from the list. For example, if we have the following attribute list

no    start      end       attribute
1     1          2           bold
2     2          5           bold
3     1          3           bold

When the 3 is inserted, 1 will be deleted since it is completely covered by the 3. However, the 2 will still there since it is not completely blocked by the entry 3.

mb_text_get_style

mb_text_set_color

This is the convenient function which will insert a new color attribute for the whole string.