Dear All,
A first version of my text rotation patch is now available. This adds
rotation of text at any angle to DirectFB, using FreeType2 scalable fonts.
API Changes
-----------
Rotated text is drawn by creating a rotated font, and then passing that
font to DrawGlyph and DrawString as usual.
To allow the creation of rotated fonts, a new flag "DFDESC_ROTATION"
has been added to DFBFontDescriptionFlags and a new field "rotation"
has been added to DFBFontDescription. Values for the rotation field
can be calculated using one of two new macros, DFB_DEGREES and
DFB_RADIANS. Here's an example of creating a rotated font:
DFBFontDescription desc;
desc.flags = DFDESC_WIDTH|DFDESC_ROTATION;
desc.width = 50;
desc.rotation = DFB_DEGREES(45);
IDirectFBFont font = dfb.CreateFont("/path/to/font/file.ttf",desc);
(This example uses the ++DFB C++ wrapper. I trust that the syntax is
understandable to everyone. I have updated ++DFB to reflect my
changes, but not yet DFB++.)
Angles increase anti-clockwise, and zero means unrotated, so for a
left-to-right font DFB_DEGREES(90) means vertical text going up the screen.
Rotation is only implemented for the FreeType2 font provider, and only
for scalable (i.e. vector) fonts. In other cases, if DFDESC_ROTATION
is set then CreateFont will return DFB_UNSUPPORTED.
You can use the rotated font with the existing DrawGlyph and DrawString
functions with no changes:
primary.SetFont(font);
primary.DrawString("Hello",5, 100,200, DSTF_LEFT);
The methods of IDirectFBFont behave as follows:
- GetAscender, GetDescender, GetHeight, GetMaxAdvance and
GetStringWidth still return scalar values.
- GetKerning always did return a vector, though it may never have
worked properly. It now returns a vector that is suitably rotated for
the font.
- A new method, GetLineSpacingVector, returns a vector that should be
used for the line-to-line advance when laying out multiple lines of text.
- GetStringExtents and GetGlyphExtents still return rectangles. I have
modified GetStringExtents so that it always returns a valid rectangle,
i.e. with positive width and height; see my previous emails to the list
about this.
- GetGlyphExtents now returns an advance vector, rather than a scalar
advance value.
Implementation
--------------
The rotation is done within the FreeType2 library by means of the
FT_Set_Transform() function. This takes a 2x2 matrix which describes
the rotation. See the FreeType tutorials at
http://www.freetype.org/freetype2/documentation.html for examples.
The rotation value supplied by the DFB_DEGREES() and DFB_RADIANS()
macros is a fixed-point number of revolutions, with 24 fractional
bits. This means that common rotations such as 90 degrees have
rational representations.
This value is not retained, however. Instead, a pair of values in
CoreFont record an "up unit vector" for the font. This means that
trigonometry is only needed when a rotated font is created. The "up
unit vector" is an (x,y) pair indicating, in DirectFB's co-ordinate
space, which way is up for the font. For a non-rotated font, they
store (0,-1). The other fields of CoreFont are unchanged.
CoreGlyphData now records x and y advance values. In functions such as
DrawString and GetStringWidth, accumulation of the width by adding an
advance for each character has been modified to track x and y position.
Code that does not use rotation will execute a few more instructions
since x and y values are being updated where previously only x values
were used. I anticipate that this overhead will not be measureable,
however. The important thing is that there is no trigonometry, and
only minimal additional multiplication, in the non-rotated case. If
anyone with a benchmarkable application would like to try to quantify
the effect, please do so.
The Patch
---------
My patch is against DirectFB1.0.0 with the addition of Denis'
GetKerning patch posted yesterday. I suspect that it will apply
without much trouble to other versions (I have increased the diff
context size to make this more likely); feedback on that would be
appreciated. Download it from here:
http://chezphil.org/tmp/dfb_rotation_1.patch
The ++DFB patch is here:
http://chezphil.org/tmp/++dfb_rotation_1.patch
(Somehow, I often screw up when creating patch files. Please excuse me
if I got it wrong!)
Test / Demo
-----------
A test/demo program is here:
http://chezphil.org/tmp/rotation_demo.cc
Issues
------
My test program seems to show some off-by-one errors in the bounding
box calculations, and perhaps some kerning problems. I plan to fix
this. Let me know if you spot any other problems.
Notes
-----
I am coming to the opinion that DirectFB would benefit from the use of
fractional pixel positions. This was somewhat crystalised when I read
this article, which was linked to from LWN:
http://antigrain.com/research/font_rasterization/index.html
I look forward to your comments!
Regards,
Phil.
_______________________________________________
directfb-dev mailing list
[email protected]
http://mail.directfb.org/cgi-bin/mailman/listinfo/directfb-dev