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

Reply via email to