0061: Cairo V – Toy Text API and Image Formats
These two topics are related in that, after a short intro to Cairo’s toy text API, we use it to print a list of available image formats on our GTK window. So, let’s start with…
Cairo’s Toy Text API
Cairo’s text API has its limitations and thus it’s referred to as a toy. Doesn’t matter to me because I just wanna get some text all up in my context, so let’s just do it.
To write text in a Cairo DrawingArea
, you need to do this:
- select a font,
- set the font size,
- set a text color,
- pick a place to write it, and
- call
showText()
.
If you wanna get fancy about it, like centering the text, you need to go a few extra steps.
Text Extents
What it is: it’s the amount of space the text will take up in the DrawingArea
.
How it’s calculated:
- do all the font settings from the first list above,
- get the width and height of the
DrawingArea
, - ask the
Context
’stextExtents()
function how much screen real estate the text will take up, and - calculate where to place the text by subtracting the text extents width and height from the
DrawingArea
’s width and height.
And when you roll all that up into a callback, it looks like this:
bool onDraw(Scoped!Context context, Widget w)
{
getAllocation(size);
// set the font, size, and color
context.selectFontFace("Comic Sans MS", CairoFontSlant.NORMAL, CairoFontWeight.NORMAL);
context.setFontSize(35);
context.setSourceRgb(0.0, 0.0, 1.0);
// find the dimensions of the text so we can center it
context.textExtents("Hello World", &extents);
context.moveTo(size.width / 2 - extents.width / 2, size.height / 2 - extents.height / 2);
context.showText("Hello World");
return(true);
} // onDraw()
Cairo
’s toy text API always left-justifies text, so if we want to center it or right justify, we’re on our own as the above calculations show. But then, this API isn’t about getting fancy; for that, we have Pango which we’ll deal with sometime down the road.
Initializations
The only other thing we need to do is initialize a couple of variables at the top of the class:
GtkAllocation size;
cairo_text_extents_t extents;
Now let’s move on and do some preliminary work for the up-coming mini-series within the Cairo series, loading and saving images, which is what we’ll do in the next post.
Writing a List of Text Items to a DrawingArea
We’re going to need a few extra bits and bobs of data to get this to work. Besides a GtkAllocation
to retrieve DrawingArea
dimensions, we also need:
Pixbuf pixbuf;
ListSG formatList;
PixbufFormat pixbufFormat;
PixbufFormat[] pixbufFormats;
Here’s what they are and why we need them:
pixbuf
is a buffer associated with a CairoSurface
… effectively, it’s an image buffer tied to theDrawingArea
,formatList
is a singly-linked list of objects (ListSG
), each of which can hold various types of data, in this case, each holds a string, the name of a format, andpixbufFormat
andpixbufFormats
are there so we can use aforeach()
loop to step through and get the names of the formats.
The callback is a bit involved, so let’s look at it in chunks… although not all of this will be in the same order it appears in the code.
Callback Chunk #1
getAllocation(size);
pixbuf = getFromSurface(context.getTarget(), 0, 0, size.width, size.height);
formatList = pixbuf.getFormats();
pixbufFormats = formatList.toArray!PixbufFormat();
What we’re doing here is:
getAllocation()
gets us the size of theDrawingArea
,getTarget()
(found inside the call togetFromSurface()
) gets us the CairoSurface
which allows us to…getFromSource()
to grab thePixbuf
, and from that…- we can use
getFormats()
to get the linked list of format strings, and finally - use a bit of D magic in the form of
toArray!PixbufFormat()
to fill thepixbufFormats
array.
And what’s a PixbufFormat
? It’s a class that keeps track of details of a Pixbuf
format… its name, mime types, license associated with the image type, the file name extensions usually used for that image… all kinds of stuff. But for now, all we’re concerned with are the format names.
Now, we’ve already looked at how to set of a font with size, color and all that, so we’ll skip Callback Chunk #2 and go to…
Callback Chunk #3
The code that digs the format names out of the PixbufFormat
array and writes them to screen looks like this:
foreach(pixbufFormat; pixbufFormats)
{
context.moveTo(40, y);
format = pixbufFormat.getName();
context.showText(format);
y += 30;
}
What we have here is:
- a standard
foreach()
loop, - a
moveTo()
call for placement (with y being previously set and, in a moment, interated), - a call to
PixbufFormat.getName()
to grab the text, showText()
to slap it into the window, and finally- that iteration I mentioned in point two of this list.
Conclusion
And that’s the first step in working with images. Over the next few posts, we’ll look at how to load image, how to save them, and then after a short side trip into animating text, we’ll look at how to load a bunch of images to use in a flipbook animation.
And you don’t wanna miss that, right?
Comments? Questions? Observations?
Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
- come on over to the D Language Forum and look for one of the gtkDcoding announcement posts,
- drop by the GtkD Forum,
- follow the link below to email me, or
- go to the gtkDcoding Facebook page.
You can also subscribe via RSS so you won't miss anything. Thank you very much for dropping by.
© Copyright 2024 Ron Tarrant