Pango

Pango es una biblioteca de código abierto (licencia LGPL) que se utiliza para el diseño y dibujo de texto (renderizado de texto), con énfasis en la internacionalización.

Pango tiene soporte multiplataforma (escrito en C, depende de la biblioteca GLib) aunque hasta ahora quizá la mayor parte del trabajo con Pango se ha hecho en el contexto de las herramientas GTK+. Pango está diseñado de forma modular, esto significa que puede ser usado por aplicaciones de diferentes arquitecturas o metodologías de programación, si bien destaca su integración con Cairo.

Prácticamente todas las distribuciones Linux instalan Pango por defecto (de hecho, las versiones linux de Firefox y de Thunderbird de Mozilla utilizan Pango para la renderización de texto).

Para la correcta compilación con valac se debe indicar específicamente que se requiere Pango de esta forma:

$valac --pkg pango nombre_programa.gs

Y al principio del código: uses Pango

Una primera prueba (si te resulta extraño el código Gtk, visita Interfaz Gtk en esta Wiki):

// compila con valac --pkg gtk+-3.0 --pkg pango nombre_archivo.gs
uses Gtk
uses Pango
 
init 
	Gtk.init (ref args)
	var TestGtk = new Ventana()
	TestGtk.show_all()
	Gtk.main()
 
class Ventana : Window
	init		
		title = "Test Genie + Pango"
		default_width = 500
		default_height = 200
		window_position = WindowPosition.CENTER
		destroy.connect(Gtk.main_quit)
 
		var etiqueta = new Label("Hola Genie + Pango")
 
		var fontdesc = new Pango.FontDescription()
		fontdesc.set_family("Purisa")
		fontdesc.set_size((int)(24 * Pango.SCALE))
 
		//etiqueta.modify_font(fontdesc)  	// funciona pero OBSOLETO desde v 3.0
		//etiqueta.override_font(fontdesc)	// funciona pero OBSOLETO desde v 3.16
 
		var attr_list = new Pango.AttrList()
		fuente:Pango.Attribute = new Pango.AttrFontDesc	(fontdesc)
		attr_list.insert ((owned)fuente)
		etiqueta.set_attributes(attr_list)
 
		add (etiqueta)

Este código nos devuelve esta ventana:

Otros atributos de Pango para aplicar al texto (recuerda que ya vimos otras formas de dar formato al texto de las etiquetas en Gtk con set_use_markup()).

// compila con valac --pkg gtk+-3.0 --pkg pango nombre_archivo.gs
uses Gtk
uses Pango
 
init 
	Gtk.init (ref args)
	var TestGtk = new Ventana()
	TestGtk.show_all()
	Gtk.main()
 
class Ventana : Window
	init		
		title = "Test Genie + Pango"
		set_border_width(8)
		window_position = WindowPosition.CENTER
		destroy.connect(Gtk.main_quit)
 
		var caja = new Box (Orientation.VERTICAL, 0)
		add (caja)
 
		texto: string = "Hola Genie + Pango" 
		var etiqueta = new Label(texto)
 
		var attr_list = new Pango.AttrList()
 
		fondo_color:Pango.Attribute = Pango.attr_background_new(65535, 0, 0)
		fondo_trans: Pango.Attribute = Pango.attr_background_alpha_new(30000)
		texto_color:Pango.Attribute = Pango.attr_foreground_new(0, 0, 65535)
		texto_escala:Pango.Attribute = Pango.attr_scale_new(3)
		fuente:Pango.Attribute = Pango.attr_family_new("Serif")
		bold:Pango.Attribute = Pango.attr_weight_new(Pango.Weight.ULTRABOLD)
		sub:Pango.Attribute = Pango.attr_underline_new(Pango.Underline.DOUBLE)
		sep:Pango.Attribute = Pango.attr_letter_spacing_new(10000)
 
		attr_list.insert ((owned)fondo_color)
		attr_list.insert ((owned)fondo_trans)
		attr_list.insert ((owned)texto_color)
		attr_list.insert ((owned)texto_escala)
		attr_list.insert ((owned)fuente)
		attr_list.insert ((owned)bold)
		attr_list.insert ((owned)sub)
		attr_list.insert ((owned)sep)
 
		etiqueta.set_attributes(attr_list)
 
		caja.pack_start (etiqueta, true, false, 0)

Pango también es capaz de manejar texto internacional usando directamente caracteres unicode:

// compila con valac --pkg gtk+-3.0 --pkg pango nombre_archivo.gs
uses Gtk
uses Pango
 
init 
	Gtk.init (ref args)
	var TestGtk = new Ventana()
	TestGtk.show_all()
	Gtk.main()
 
class Ventana : Window
	init		
		title = "Test Genie + Pango"
		set_border_width(8)
		window_position = WindowPosition.CENTER
		destroy.connect(Gtk.main_quit)
 
		var caja = new Box (Orientation.VERTICAL, 0)
		add (caja)
 
		texto: string = """Фёдор Михайлович Достоевский родился 30 октября (11 ноября)
1821 года в Москве.Был вторым из 7 детей. Отец, Михаил Андреевич, работал в 
госпитале для бедных. Мать, Мария Фёдоровна (в девичестве Нечаева),
происходила из купеческого рода."""
 
		texto2: string = """陀思妥耶夫斯基出生於10月30日(11月11日)
七個孩子1821 Moskve.Byl第二。他的父親,米哈伊爾,是在工作
窮人的醫院。他的母親,瑪麗亞芙娜(NEE涅恰耶夫)
它來自一個商人家庭。"""
 
		var etiqueta = new Label(texto)
		var etiqueta2 = new Label(texto2)
 
		var fontdesc = new Pango.FontDescription()
		fontdesc.set_size((int)(10 * Pango.SCALE))
 
		var attr_list = new Pango.AttrList()
		fuente:Pango.Attribute = new Pango.AttrFontDesc	(fontdesc)			
		attr_list.insert ((owned)fuente)		
 
		etiqueta.set_attributes(attr_list)
		etiqueta2.set_attributes(attr_list)
 
		caja.pack_start (etiqueta, true, false, 0)
		caja.pack_start (etiqueta2, true, false, 0)	

El siguiente ejemplo muestra las fuentes disponibles en un widget TreeView:

// compila con valac --pkg gtk+-3.0 --pkg pango nombre_archivo.gs
uses Gtk
uses Pango
 
init
	Gtk.init (ref args)
	var TestGtk = new Ventana()
	TestGtk.show_all()
	Gtk.main()
 
class Ventana : Window
 
	fam: array of FontFamily
	store: Gtk.ListStore
 
	init		
		title = "Genie + Pango"
		set_default_size (350, 250)
		set_border_width(8)
		window_position = WindowPosition.CENTER
		destroy.connect(Gtk.main_quit)
 
		// contenedor con barra de desplazamiento		
		var sw = new Gtk.ScrolledWindow(null, null)		
		sw.set_shadow_type (ShadowType.ETCHED_IN)
		sw.set_policy(PolicyType.AUTOMATIC, PolicyType.AUTOMATIC)
		add(sw)
 
		// obtenemos las fuentes en un array
		var context = Gdk.pango_context_get()
		context.list_families(out fam)
 
		// widget TreeView
		var treeView = new TreeView ()
		sw.add(treeView)  // lo añadimos al contenedor
 
		// almacen ListStore del TreeView
		store = new Gtk.ListStore (1, typeof (string))
		treeView.set_model (store)
 
		// primera fila
		encabezado:string = "FontName" + "  (" + fam.length.to_string() + ")"	// muestra número de fuentes		
		column: TreeViewColumn = new TreeViewColumn.with_attributes(
			encabezado, new CellRendererText (), "text", 0)		
		column.set_sort_column_id(0)	// clic ordena la columna (ascendente y descendente)
		treeView.append_column(column)
 
		// OTRA OPCIÓN PARA LA PRIMERA FILA:
		// treeView.insert_column_with_attributes (-1, encabezado, new CellRendererText (), "text", 0)
 
		// completamos el resto de filas con las fuentes obtenidas
		iter: TreeIter
		for ff in fam	// recorremos el array de fuentes
			store.append (out iter)	// añade una nueva fila
			store.set (iter, 0, ff.get_name())	// añade una fuente a la nueva fila

🔝