[cairo] A (LONG) Pango/Cairo Question

Jeremy Moles jeremy at emperorlinux.com
Wed Aug 27 14:45:56 PDT 2008

On Wed, 2008-08-27 at 14:20 -0400, Behdad Esfahbod wrote:
> Jeremy Moles wrote:
> > Hello everyone! I've been somewhat active in the IRC channel lately with
> > various questions, so I figured I'd make a thorough post here instead of
> > asking each question individually.
> > 
> > A few months back I made a post inquiring as to how I could utilize
> > Pango (and Cairo) to render glyphs to an OpenGL texture. I was directed
> > to the Clutter project, which solved this problem by creating a custom
> > PangoRenderer object and providing various callbacks (particularly a
> > "draw_glyphs" callback) which they used to render an individual glyph,
> > cache it inside and OpenGL texture, and later query that when needed
> > again as they build and position OpenGL quads based on the information
> > provided to them by the Pango layout.
> > 
> > I've been able to dissect their code a great deal over the last two
> > weeks and at this point I'm quite familiar with many of the high-level
> > concepts needed to accomplish what I'm trying to do. I have my own "from
> > scratch" implementation (though highly inspired by the Clutter project)
> > and I'm running into a few problems.
> > 
> > Firstly, I want to change the origin of my cairo image surface (which is
> > always properly sized to be compatible with OpenGL texture requirements)
> > to the bottom-left corner, which will also make it's coordinate space
> > consistent with OpenGL. To accomplish this, I use the following code:
> > 
> > 	cairo_matrix_t ms, mt, m;
> > 
> > 	cairo_matrix_init_scale(&ms, 1.0f, -1.0f);
> > 	cairo_matrix_init_translate(&mt, 0.0f, -height);
> > 	cairo_matrix_multiply(&m, &mt, &ms);
> You can do this much easier using cairo_matrix_scale() and
> cairo_matrix_translate()
> > 	cairo_set_matrix(cr, &m);
> Or if you want to set it on cr, just use cairo_identity_matrix(),
> cairo_scale(), and cairo_transform().
> > I have confirmed that this works as intended as best I can, by drawing a
> > line from 0, 0 to 512, 512--which creates a line from the bottom-left to
> > the top-right of the image.
> > 
> > Secondly, I've hooked into the Pango API and have created my own custom
> > renderer class. During it's "draw_glyphs" callback, it iterates over the
> > list of PangoGlyph structures, creates a cairo_glyph based on this data,
> > and requests that Cairo draw this glyph using "cairo_show_glyphs".
> > However, what is currently happening is that my glyphs are getting
> > rendered upside-down, and I've attached a screenshot to demonstrate
> > this. My first question then is what else should I be doing to inform
> > Cairo that the glyph should be rendered properly for my case? I've tried
> > setting the font matrix in countless ways, but everything I do simply
> > causes the text to disappear.
> Just do a scale(1,-1) on the font matrix.
> behdad
> > For a bit of additional information, here is how I actually render the
> > glyph:
> > 	
> > 	pango_font_get_glyph_extents(font, glyph, &ink_rect, 0);
> > 	pango_extents_to_pixels(&ink_rect, 0);
> > 	cairo_set_scaled_font(cr, pango_cairo_font_get_scaled_font(...))
> > 	// cairo_set_font_matrix(...)
> > 	cairo_glyph.x = -ink_rect.x;
> > 	cairo_glyph.y = -ink_rect.y;
> > 	cairo_glyph.index = glyph;
> > 
> > In the above code, I'm somewhat unclear as to why I set the
> > cairo_glyph{x, y} values with the negative versions of the ones from the
> > ink_rect object queried using the Pango API; I got this part directly
> > from the Clutter project. This, then, leads me to my last question,
> > which is what are these values and how should I use them? I understand
> > that Cairo defines them as offsets from a 0, 0 origin, but does this
> > mean that Pango works with a different origin than Cairo does?
> > 
> > I know this is a huge e-mail, but any advice would be greatly
> > appreciated. :) In summation, I will explain again what I'm trying to
> > accomplish:
> > 
> > I want to use Cairo and Pango to create an accelerated OpenGL
> > font/texturing library (for use in OpenSceneGraph). To do this, I would
> > like to change my Cairo origin to the bottom left (to be consistent with
> > OpenGL) and begin rendering/caching glyphs from left-to-right,
> > bottom-to-top. Furthermore, rather than create a new surface for each
> > individual glyph and then copy that to the "master" texture, I would
> > like to use cairo_translate() and the information provided by Pango's
> > glyph structure to move around the texture and render the glyphs
> > directly. Is this possible, or am I missing some crucial concept
> > somewhere? :)
> > 
> > Thanks!
> > 

I'm attaching a file test.c (and accompanying Makefile) that I believe
demonstrates a bug in either Cairo or my own code.

The goal of this application is to use Pangocairo to create an OpenGL
texture that caches glyphs with one pixel of space both horizontally and
vertically between each rendered item. When there are no transforms
present on the current Cairo context, everything appears to work exactly
as expected. However, when the origin is "flipped" to the bottom left
(via cairo_scale(), cairo_translate()), the glyphs are rendered subtly
different and overlap by one pixel or so, depending on font size.

In the second (failed) case, you will need to rotate the image in a
program like gimp and compare it to the original. I have also attached a
PNG image demonstrating this for convenience. Notice that in the first
"row" of text, each glyph has one pixel of space between it. In the
second "row" you'll notice that some glyphs are rendered different
(you'll need a keen eye for this :)) and that a few of them bleed
together, despite being subject to the same translations that work in
the normal mode.
> > ------------------------------------------------------------------------
> > 
> > 
> > ------------------------------------------------------------------------
> > 
> > _______________________________________________
> > cairo mailing list
> > cairo at cairographics.org
> > http://lists.cairographics.org/mailman/listinfo/cairo
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Makefile
Type: text/x-makefile
Size: 188 bytes
Desc: not available
Url : http://lists.cairographics.org/archives/cairo/attachments/20080827/1c1699fc/attachment-0001.bin 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.c
Type: text/x-csrc
Size: 5636 bytes
Desc: not available
Url : http://lists.cairographics.org/archives/cairo/attachments/20080827/1c1699fc/attachment-0001.c 
-------------- next part --------------
A non-text attachment was scrubbed...
Name: test.png
Type: image/png
Size: 3209 bytes
Desc: not available
Url : http://lists.cairographics.org/archives/cairo/attachments/20080827/1c1699fc/attachment-0001.png 

More information about the cairo mailing list