Pango programming guide

If you're using any kind of non-default fonts, you'll want to convert your code to use the new PangoFontDescription rather than GdkFont. PangoFontDescription is much, much easier to use; to load a GdkFont you had to specify an awkward X font description string, and the resulting GdkFont was specific to a certain locale; it wouldn't work for all languages. Moreover, there were no fonts you could choose that everyone using your application was guaranteed to have, so a call to gdk_font_load() could always fail.

PangoFontDescription is much higher-level. The exact font technology used by GTK+ varies according to GDK target and how GTK+ was compiled; underneath Pango, the real implementation could be Win32 fonts, XRender fonts, traditional X fonts, TrueType fonts, or even a mixture. Pango can even assemble a collection of locale-specific fonts and use those to emulate a single Unicode font. Programmers don't have to worry about this; they specify high-level font details such as "Sans Italic 12".

A PangoFontDescription has a stringified form, described in the Pango documentation. "Sans Italic 12" is an example of such a string. The easiest way to obtain a PangoFontDescription is to call pango_font_description_from_string(). The font families "Sans", "Monospace", and "Serif" are guaranteed to exist on all GTK+ installations; these will never fail to load.

If you were using the font field in GtkStyle to change the font for a widget, you'll need to use the new font_desc field instead. However, when converting your code from GdkFont, ask yourself if setting style->font remains the easiest thing to do; gtk_label_new_from_markup() is a handy alternative provided for GtkLabel. You can pass in a string marked up with HTML-like tags affecting text attributes such as color, text size, font family, and so on. The Pango documentation describes all the tags you can use. If you do still want to modify the style, probably you can use the new gtk_widget_modify_font() function instead of fooling with styles manually. gtk_widget_modify_font() works properly when the theme changes, and is easier to use.

If you were using gdk_draw_string(), gdk_draw_text(), gtk_paint_string(), or variants thereof, you'll want to rework your code to use PangoLayout. A PangoLayout represents a paragraph of text to be rendered to the screen. With English or European text, to render a paragraph, you just break on spaces and draw each line one font height below the previous line. When you start to handle languages such as Arabic, Hindi, Japanese, Hebrew, Thai, or Korean, however, this is wrong; it simply won't work properly. Pango handles the details with PangoLayout. To render a paragraph of text, create a PangoLayout for that text, then call gdk_draw_layout or gtk_paint_layout(). To create your layout, call gtk_widget_create_pango_layout() on the widget you intend to draw on.

While you'll usually just create a layout and draw it, for more complex cases PangoLayout has a lot of useful features; it has text attributes, and you can use the HTML-like Pango markup language mentioned earlier as a convenient way to set those attributes. (The less-convenient way uses PangoAttrList directly.) PangoLayout can also handle cursors, conversion from pixel locations to text positions, and that kind of thing.

When asking for text metrics, such as the size of a PangoLayout, you'll notice that all Pango objects have a "logical size" and an "ink size." The logical size corresponds to the font metrics (ascent and descent), and should be used to position text. The logical size for a line of text will change if you add a new character that's larger than the existing characters. The ink size of some text describes the actual pixels covered by the font glyphs, so for example capital letters have a larger ink size than lowercase, and letters with "descenders" such as lowercase "y", "g", "p" have a larger ink size than letters without. Usually you don't need the ink size. Logical size should be used in widget size requests, and in any other case where you're positioning text.

Pango sizes are specified in "Pango units," which are converted to and from device units (e.g. pixels) using the PANGO_SCALE constant. There are PANGO_SCALE units per pixel.

If your application does anything complicated with text, such as text editing, you'll want to investigate Pango in more depth. Some considerations and definitions to keep in mind:

  • Logical and visual direction do not correspond. Logical direction is the sequence of characters in a string; iterating over a string moves through it logically. Visual direction is the sequence of font glyphs on the user's monitor. Overall text direction can be right-to-left instead of left-to-right; also, individual characters can be "reordered" on a smaller scale, so that glyphs representing characters are not in the same sequence as the characters themselves.

  • Glyphs do not correspond to characters. That is, multiple Unicode characters can be displayed as a single font glyph on the screen. A cluster is a set of characters represented by a single glyph. (Glyphs are the graphical characters making up a font.)

  • The process of converting a string of characters into a string of glyphs is called shaping. The low-level Pango function pango_shape() performs this operation -- PangoLayout does shaping for you, so typically you don't need to think about it.

  • Word, line, sentence, and paragraph breaks do not necessarily follow English rules. Some languages are written with no spaces, for example, so you can't use spaces to split up words. Line break rules depend on the language. Paragraphs can be broken by the newline/linefeed ('/n') character, by carriage return ('/r'), by a sequence of carriage return and line feed, or by a special Unicode paragraph separator character. You can obtain text boundary information for a paragraph of text with the functions pango_break(), pango_get_log_attrs(), and pango_find_paragraph_boundary().

  • It's not possible to put the cursor (caret, insertion mark) at all character positions. Some characters "combine" into a single logical unit, and the cursor can't go between the combined characters. A group of combined characters is called a grapheme, that is, a logical unit of writing. pango_break() and friends report valid cursor positions along with other text boundary information.

The PangoLayout structure represents and entire paragraph of text. It is initialized with a PangoContext, UTF-8 string and set of attributes for that string. Once that is done, the set of formatted lines can be extracted from the object, the layout can be rendered, and conversion between logical character positions within the layout's text, and the physical position of the resulting glyphs can be made.

There are also a number of parameters to adjust the formatting of a PangoLayout, which are illustrated in Figure?1. It is possible, as well, to ignore the 2-D setup, and simply treat the results of a PangoLayout as a list of lines.

Figure?1.?Adjustable parameters for a PangoLayout

Adjustable parameters for a PangoLayout
Basicly, in gtk program, we can call gtk_widget_get_pango_context() to get a PangoContext pointer associated with this GtkWidget. With this context, we could get/set the font description, get/set language, list font families, get font metrics, even break a string of Unicode text. Must call pango_layout_context_changed() after changing the context attributes.
For PangoLayout, we could create a pango layout from one pango context, or use gtk_widget_create_pango_layout, ro deep-copy from another layout. From gtklabel/entry ... widgets, they provide the gtk_xxx_get_layout method to retrive the layout assoicated with the widget. Must call pango_layout_context_changed() after changing the layout attributes.
With PangoLayout, we can set the attributes, get/set text, get/set width, set (no get) font description, get/set wrap, get pixel/pango_unit size (and extention size).
#include <gtk/gtk.h>

gint main (gint argc, gchar *argv[])
   GtkWidget *window;
   GtkWidget *label;
   PangoFontDescription *font;

   gtk_init (&argc, &argv);

   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);

   g_signal_connect (window, "delete_event", G_CALLBACK(gtk_widget_destroy), NULL);
   g_signal_connect (window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

   label = gtk_label_new ("Hello World!");
   font = pango_font_description_from_string ("monospace 30");
   gtk_widget_modify_font (label, font);

   gtk_container_add (GTK_CONTAINER(window), label);

   gtk_widget_show_all (window);

   gtk_main ();

   return 0;
个人分类: Linux/Gnu/Gnome
想对作者说点什么? 我来说一句

OpenGL Programming Guide, 9th Edition PDF版

2017年07月25日 57.49MB 下载

WebGL Programming Guide

2014年03月18日 20.16MB 下载