freetype-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: [ft-devel] Rotated text


From: Graham Asher
Subject: RE: [ft-devel] Rotated text
Date: Mon, 7 Jul 2008 08:57:30 +0100

Frank,

I've added some brief answers to your questions below.

Best regards,

Graham

-----Original Message-----
From: Frank W. Miller [mailto:address@hidden 
Sent: 07 July 2008 04:59
To: 'Graham Asher'; address@hidden
Subject: RE: [ft-devel] Rotated text


Thanks very much for the reply.  I have a few questions as you might guess.
Your mapping software looks really great btw.

FM


-----Original Message-----
From: Graham Asher [mailto:address@hidden 
Sent: Sunday, July 06, 2008 5:19 AM
To: 'Frank W. Miller'; address@hidden
Subject: RE: [ft-devel] Rotated text

Frank,

I'm sorry that I don't have time to look at your example, but I have
successfully drawn rotated text (and text along a path, for that matter)
using FreeType, and I can give you some pieces of advice.

1. Either (i) use an FT_Matrix to set the font transform (call
FT_Set_Transform), or (ii), create an unrotated outline glyph for each
character and then rotate it using FT_Glyph_Transform. I assume from the
fact that you say that your code 'spins' the text that you know how to set
the transform parameters.

FM: I have been using both FT_Matrix and FT_Set_Transform successfully as
you have guessed.  I've had a little trouble figuring out where 0 degrees
is.  In the sample code on the FreeType site, it seems to be the positive y
axis.  When I tweaked it, I was able to get that go be the positive x axis,
which seems more logical to me.

GA: It doesn't matter where 0 degrees is - 0 degrees can be regarded as
'unrotated'.

2. Use the advance vector after it has been transformed. This is
outline_glyph->root.advance (assuming that outline_glyph is your
FT_OutlineGlyph object), and is a 16.16 fixed-point number. You will need to
keep track of the current glyph origin in 16.16 format, to avoid the text
'looking like arse', because...

FM: The way the code works, there is a "pen" variable of type FT_Vector.
The pen x and y components are set to the origin prior to entering a for
loop.  Each iteration of the for loop does this: 1) FT_Set_Transform 2)
FT_Load_Char, 3) draw the bitmap, and 4) advance the "pen" using the
face->glyph->advance.  It seems like one of two things is happening, either
my rendering of the bitmap does not fall on the baseline correctly or the
pen advance is not following the baseline.  My guess is its my bitmap
rendering but I don't know for sure.

GA: You need to store your pen variable in 16.16 coordinates. Add the x
component of face->glyph->advance to pen.x and the y component to pen.y
after drawing each glyph.

3. When you rasterize every glyph except the first one, it needs to be
offset to the sub-pixel position of its origin. For example: if your first
glyph has an unrotated baseline length of 8 pixels and you rotate the text
by 20 degrees, the rotated advance will be (8 * cos 20,8 * sin 20) = (7.518,
2.736). Thus, if your first glyph origin was at (0,0), your second glyph
origin needs to be at (7.518,2.736) to avoid a jiggling effect. Do this by
applying an offset of the fractional parts of the coordinates to each glyph
as you rasterize it, then drawing the glyph at the integer coordinates.
Thus, in this example, you need to offset the glyph by (0.518,0.736) and
draw at (7,2). FreeType works in 64ths of pixels when rasterizing, so you do
this by calling FT_Glyph_Transform with a delta argument of (0.518 *
64,0.736 * 64) = (33,47) before converting the outline glyph to a bitmap.

FM: Huh?  This makes me wonder even more what I'm doing in my previous
comment.  Is my baseline length my width or pitch from the previous glyph?
This is what's causing me trouble I think.  Maybe I'm too new to this but
there aren't that many things I can play with here, at least from what I see
in the documentation.  I do the rotation using the matrix.  I use width and
pitch and rows to figure out the bitmap size and I can take the advance.x >>
6 and advance.y >> 6 to get movements on the origin of each glyph.  I'm not
following where your application of the rotation angle to the baseline
length is coming from.  Can you be more specific about what fields in what
structures you are talking about?

GA: The baseline length ( that is, the advance, measured along the baseline)
is the vector length of the advance. To use my previous example, the
baseline length is 8 pixels - the value before rotation. The glyph bitmap
pitch is irrelevant.

You say "and I can take the advance.x >> 6 and advance.y >> 6 to get
movements on the origin of each glyph" but that is a mistake. advance.x and
advance.y are stored in 16.16 format. To convert to 64ths of a pixel (26.6
format) you need to shift right by 10, not by 6.

You also said "I'm not following where your application of the rotation
angle to the baseline length is coming from. Can you be more specific about
what fields in what
structures you are talking about?" Yes: FreeType applies the rotation to the
advance in FT_Glyph_Transform. The code is

FT_Vector_Transform( &glyph->advance, matrix );

which applies "matrix" (your rotational transform) to glyph->advance,
yielding the fractional advance x and y values I referred to above. For
example, if the advance is 8 pixels, we start off with glyph->advance.x =
8*65536 = 524288 (that is, the number 8 in 16.16 fixed-point form), and
glyph->advance.y = 0. After a rotation of 20 degrees we have
glyph->advance.x = 492670, which represents the number 7.517, and
glyph->advance.y = 179317, which represents 2.736. You convert these numbers
to 64ths of pixels by dividing by 2^10 - that is, shifting right by 10 -
neglecting rounding issues.

4. Rotated text looks much better when it is anti-aliased. But you knew that
already ;-)

FM: I want to get it working before I worry about anti-aliasing, but I will
of course want to add that at some point.

GA: I would advise doing that right now. You need only change a single flag
in the parameters you pass to FreeType, and drawing anti-aliased glyphs is
actually easier because each pixel value fits into a single byte, so you
don't have to mask and shift to get the values out. And it looks much
better.

Thanks again for the advice.  Due to my newbieness, its as clear as mud
right now.  :(

Thanks,
FM






reply via email to

[Prev in Thread] Current Thread [Next in Thread]