I am on Ubuntu 12.04 LTS using GTK 3 and Cairo.
My application outputs graphs, diagrams and text and the user can configure the output by changing style values, a bit like CSS.
The program needs 'text-in-a-box' with line wrapping and optional jusification. I have written the code that collects stylenames and attribute values, but not yet the placement and rendering functions. I noticed that pango provides this in exactly the way I need, so I want to use that instead.
My program uses a style changes array that points into a text array (offset and length used). I have never used pango before, but I believe I have to create a PangoAttrList and I am not sure how to do this. Here is my current guess:
For each stylechange:
- use the pango_attr_xxxx_new to allocate and set attribute value in
PangoAttribute * a
- a->start_index = myoffset; a->end_index = myoffset+mylength;
The documentation mentions a pango_attribute_init. If I have to use that I would not know how to, for example where do I get the copy, and equal function addresses from and how can I set the klass.type e.g. to PANGO_ATTR_FOREGROUND which is const (compiler complains).
Here is a fragment from the code:
typedef enum
{
TXTCOL_TP ,
STYLE_TP ,
WEIGHT_TP ,
FFLIST_TP ,
FONTSIZE_TP ,
BGCOL_TP ,
//... more
} VALTYPE;
typedef struct
{
unsigned short r ;
unsigned short g ;
unsigned short b ;
} COLOUR ;
typedef struct
{
int offset; // where property starts in text
array
int len; // length (in chars) of property in text
VALTYPE valtp;
union
{
COLOUR txtcol; // text colour
int style; // normal, oblique, italic
int weight; // fontweight 100,200,300,.800,900
int fflist; // position in text pool of font family list
int fontsize; // in pts
//.... more
};
} STYLEVALUE;
static int numchgs ; // number style changes in text
static STYLEVALUE chgs [ MAXNUMCHGS ] ;
static char text [ MAXSZTEXT ] ; // text with style changes given by chgs array
PangoAttrList
* makeattrlist()
{
PangoAttrList * al = pango_attr_list_new();
PangoAttribute * a ; // common and type-dependent part
STYLEVALUE * sv ;
int k = 0 ;
while ( k < numchgs )
{
sv = &chgs [ k ] ;
switch ( sv->valtp )
{
case TXTCOL_TP:
//pango_attribute_init (???); // do I have to use this? how?
a = pango_attr_foreground_new(sv->txtcol.r, sv->txtcol.g, sv->txtcol.b );
a->klass.type = PANGO_ATTR_FOREGROUND ; // compiler complains about
this
a->start_index = sv->offset;
a->end_index = a->start_index + sv->len;
pango_attr_list_insert(al, a);
break;
case STYLE_TP:
// same uncertainties...
a = pango_attr_style_new( (PangoStyle)sv->style );
a->klass.type = PANGO_ATTR_STYLE ; // compiler complains
a->start_index =
sv->offset;
a->end_index = a->start_index + sv->len;
pango_attr_list_insert(al, a);
break;
//case WEIGHT_TP:
//case FFLIST_TP:
//case FONTSIZE_TP:
}
k++;
}
return al ;
}
static gboolean on_expose_event (GtkWidget *darea, GdkEventExpose *event, gpointer user_data)
{
cairo_t * cr = gdk_cairo_create(gtk_widget_get_window(darea));
PangoLayout * layout = pango_cairo_create_layout
(cr);
PangoAttrList * attrs = makeattrlist();
pango_layout_set_attributes(layout, attrs);
pango_layout_set_alignment(layout, PANGO_ALIGN_LEFT);
pango_layout_set_width ( layout , 180*PANGO_SCALE ) ;
pango_layout_set_wrap ( layout , PANGO_WRAP_WORD ) ;
pango_layout_set_text (layout, text, -1); // or should it be pango_layout_set_markup?
cairo_move_to (cr, 100, 30);
pango_cairo_show_layout (cr, layout);
g_object_unref (layout);
return FALSE ;
}
Am I on the right track? Would be grateful for advice.
Ken