1608 lines
53 KiB
HTML
1608 lines
53 KiB
HTML
<!doctype html public "-//w3c//dtd html 4.0 transitional//en"
|
|
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
|
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type"
|
|
content="text/html; charset=iso-8859-1">
|
|
<meta name="Author"
|
|
content="David Turner">
|
|
<title>FreeType 2 Tutorial</title>
|
|
</head>
|
|
|
|
<body text="#000000"
|
|
bgcolor="#FFFFFF"
|
|
link="#0000EF"
|
|
vlink="#51188E"
|
|
alink="#FF0000">
|
|
|
|
<h1 align=center>
|
|
FreeType 2.0 Tutorial<br>
|
|
Step 2 -- managing glyphs
|
|
</h1>
|
|
|
|
<h3 align=center>
|
|
© 2000 David Turner
|
|
(<a href="mailto:david@freetype.org">david@freetype.org</a>)<br>
|
|
© 2000 The FreeType Development Team
|
|
(<a href="http://www.freetype.org">www.freetype.org</a>)
|
|
</h3>
|
|
|
|
<center>
|
|
<table width="550">
|
|
<tr><td>
|
|
|
|
<hr>
|
|
|
|
<h2>
|
|
Introduction
|
|
</h2>
|
|
|
|
<p>This is the second part of the FreeType 2 tutorial. It will teach
|
|
you the following:</p>
|
|
|
|
<ul>
|
|
<li>how to retrieve glyph metrics</li>
|
|
<li>how to easily manage glyph images</li>
|
|
<li>how to retrieve global metrics (including kerning)</li>
|
|
<li>how to render a simple string of text, with kerning</li>
|
|
<li>how to render a centered string of text (with kerning)</li>
|
|
<li>how to render a transformed string of text (with centering)</li>
|
|
<li>finally, how to access metrics in design font units if needed,
|
|
and how to scale them to device space</li>
|
|
</ul>
|
|
|
|
<hr>
|
|
|
|
<h3>
|
|
1. Glyph metrics
|
|
</h3>
|
|
|
|
<p>Glyph metrics are, as their name suggests, certain distances
|
|
associated to each glyph in order to describe how to use it to layout
|
|
text.</p>
|
|
|
|
<p>There are usually two sets of metrics for a single glyph: those used
|
|
to layout the glyph in horizontal text layouts (like Latin, Cyrillic,
|
|
Arabic, Hebrew, etc.), and those used to layout the glyph in vertical
|
|
text layouts (like some layouts of Chinese, Japanese, Korean, and
|
|
others).</p>
|
|
|
|
<p>Note that only a few font formats provide vertical metrics. You can
|
|
test wether a given face object contains them by using the macro
|
|
<tt>FT_HAS_VERTICAL(face)</tt>, which is true if vertical metrics are
|
|
available.</p>
|
|
|
|
<p>Individual glyph metrics can be accessed by first loading the glyph
|
|
in a face's glyph slot, then using the <tt>face->glyph->metrics</tt>
|
|
structure. This will be described later; for now, we observe that it
|
|
contains the following fields:</p>
|
|
|
|
<center>
|
|
<table width="90%" cellpadding=5>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>width</tt>
|
|
</td>
|
|
<td>
|
|
This is the width of the glyph image's bounding box. It is
|
|
independent of the layout direction.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>height</tt>
|
|
</td>
|
|
<td>
|
|
This is the height of the glyph image's bounding box. It is
|
|
independent of the layout direction.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>horiBearingX</tt>
|
|
</td>
|
|
<td>
|
|
For <em>horizontal text layouts</em>, this is the horizontal
|
|
distance from the current cursor position to the left-most border of
|
|
the glyph image's bounding box.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>horiBearingY</tt>
|
|
</td>
|
|
<td>
|
|
For <em>horizontal text layouts</em>, this is the vertical distance
|
|
from the current cursor position (on the baseline) to the top-most
|
|
border of the glyph image's bounding box.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>horiAdvance</tt>
|
|
</td>
|
|
<td>
|
|
For <em>horizontal text layouts</em>, this is the horizontal
|
|
distance used to increment the pen position when the glyph is drawn
|
|
as part of a string of text.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>vertBearingX</tt>
|
|
</td>
|
|
<td>
|
|
For <em>vertical text layouts</em>, this is the horizontal distance
|
|
from the current cursor position to the left-most border of the
|
|
glyph image's bounding box.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>vertBearingY</tt>
|
|
</td>
|
|
<td>
|
|
For <em>vertical text layouts</em>, this is the vertical distance
|
|
from the current cursor position (on the baseline) to the top-most
|
|
border of the glyph image's bounding box.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>vertAdvance</tt>
|
|
</td>
|
|
<td>
|
|
For <em>vertical text layouts</em>, this is the vertical distance
|
|
used to increment the pen position when the glyph is drawn as part
|
|
of a string of text.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
|
|
<p><em>As not all fonts do contain vertical metrics, the values of
|
|
<tt>vertBearingX</tt>, <tt>vertBearingY</tt>, and <tt>vertAdvance</tt>
|
|
should not be considered reliable if <tt>FT_HAS_VERTICAL(face)</tt> is
|
|
false.</em></p>
|
|
|
|
<p>The following graphics illustrate the metrics more clearly. First
|
|
horizontal metrics, where the baseline is the horizontal axis:</p>
|
|
|
|
<center>
|
|
<img src="metrics.png"
|
|
alt="horizontal metrics layout"
|
|
width=388 height=253>
|
|
</center>
|
|
|
|
<p>For vertical text layouts, the baseline is vertical and is the
|
|
vertical axis:</p>
|
|
|
|
<center>
|
|
<img src="metrics2.png"
|
|
alt="vertical metrics layout"
|
|
width=294 height=278>
|
|
</center>
|
|
|
|
<p>The metrics found in <tt>face->glyph->metrics</tt> are normally
|
|
expressed in 26.6 pixel format (i.e 1/64th of pixels), unless you use
|
|
the <tt>FT_LOAD_NO_SCALE</tt> flag when calling <tt>FT_Load_Glyph()</tt>
|
|
or <tt>FT_Load_Char()</tt>. In that case, the metrics will be expressed
|
|
in original font units.</p>
|
|
|
|
<p>The glyph slot object has a few other interesting fields that will
|
|
ease a developer's work. You can access them through
|
|
<tt>face->glyph->???</tt>:</p>
|
|
|
|
<center>
|
|
<table width="90%" cellpadding=5>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>advance</tt>
|
|
</td>
|
|
<td>
|
|
This field is an <tt>FT_Vector</tt> which holds the transformed
|
|
advance value for the glyph. This is useful if you are using a
|
|
transformation through <tt>FT_Set_Transform()</tt>, as shown in the
|
|
rotated text example of the previous part. Other than that, its
|
|
value is by default (metrics.horiAdvance,0), unless you specify
|
|
<tt>FT_LOAD_VERTICAL</tt> when loading the glyph image; it will then
|
|
be (0,metrics.vertAdvance).
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>linearHoriAdvance</tt>
|
|
</td>
|
|
<td>
|
|
This field contains the linearly-scaled value of the glyph's
|
|
horizontal advance width. Indeed, the value of
|
|
<tt>metrics.horiAdvance</tt> that is returned in the glyph slot is
|
|
normally rounded to integer pixel coordinates (i.e., it will be a
|
|
multiple of 64) by the font driver used to load the glyph
|
|
image. <tt>linearHoriAdvance</tt> is a 16.16 fixed float number
|
|
that gives the value of the original glyph advance width in
|
|
1/65536th of pixels. It can be used to perform pseudo
|
|
device-independent text layouts.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>linearVertAdvance</tt>
|
|
</td>
|
|
<td>
|
|
This is the same thing as <tt>linearHoriAdvance</tt> for the glyph's
|
|
vertical advance height. Its value is only reliable if the font
|
|
face contains vertical metrics.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
|
|
<hr>
|
|
|
|
<h3>
|
|
2. Managing glyph images
|
|
</h3>
|
|
|
|
<p>The glyph image that is loaded in a glyph slot can be converted into
|
|
a bitmap, either by using <tt>FT_LOAD_RENDER</tt> when loading it, or by
|
|
calling <tt>FT_Render_Glyph()</tt> afterwards. Each time you load a new
|
|
glyph image, the previous one is erased from the glyph slot.</p>
|
|
|
|
<p>There are times, however, where you may need to extract this image
|
|
from the glyph slot. For example, you want to cache images within your
|
|
application, or you want to apply additional transformations and
|
|
measures on it before converting it to a bitmap.</p>
|
|
|
|
<p>The FreeType 2 API has a specific extension which is capable of
|
|
dealing with glyph images in a flexible and generic way. To use it, you
|
|
first need to include the <tt>ftglyph.h</tt> header file:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
#include <freetype/ftglyph.h></pre>
|
|
</font>
|
|
|
|
<p>We will now explain how to use the functions defined in this
|
|
file.</p>
|
|
|
|
<h4>
|
|
a. Extracting the glyph image
|
|
</h4>
|
|
|
|
<p>You can extract a single glyph image very easily. Here some code
|
|
that shows how to do it.</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_Glyph glyph; /* handle to glyph image */
|
|
|
|
|
|
...
|
|
error = FT_Load_Glyph( face, glyph, FT_LOAD_NORMAL );
|
|
if ( error ) { .... }
|
|
|
|
error = FT_Get_Glyph( face->glyph, &glyph );
|
|
if ( error ) { .... }</pre>
|
|
</font>
|
|
|
|
<p>As can be seen, we have</p>
|
|
|
|
<ul>
|
|
<li>
|
|
created a variable, named <tt>glyph</tt>, of type
|
|
<tt>FT_Glyph</tt>. This is a handle (pointer) to an individual
|
|
glyph image,
|
|
</li>
|
|
<li>
|
|
loaded the glyph image normally in the face's glyph slot. We did
|
|
not use <tt>FT_LOAD_RENDER</tt> because we want to grab a scalable
|
|
glyph image in order to transform it later,
|
|
</li>
|
|
<li>
|
|
copied the glyph image from the slot into a new <tt>FT_Glyph</tt>
|
|
object by calling <tt>FT_Get_Glyph()</tt>. This function returns
|
|
an error code and sets <tt>glyph</tt>.
|
|
</li>
|
|
</ul>
|
|
|
|
<p>It is important to note that the extracted glyph is in the same
|
|
format as the original one that is still in the slot. For example, if
|
|
we are loading a glyph from a TrueType font file, the glyph image will
|
|
really be a scalable vector outline.</p>
|
|
|
|
<p>You can access the field <tt>glyph->format</tt> if you want to know
|
|
exactly how the glyph is modeled and stored. A new glyph object can
|
|
be destroyed with a call to <tt>FT_Done_Glyph()</tt>.</p>
|
|
|
|
<p>The glyph object contains exactly one glyph image and a
|
|
2d vector representing the glyph's advance in 16.16 fixed float
|
|
coordinates. The latter can be accessed directly as
|
|
<tt>glyph->advance</tt>.</p>
|
|
|
|
<p><em>Note that unlike other FreeType objects, the library doesn't
|
|
keep a list of all allocated glyph objects. This means you will need
|
|
to destroy them yourself, instead of relying on
|
|
<tt>FT_Done_FreeType()</tt> to do all the clean-up.</em></p>
|
|
|
|
<h4>
|
|
b. Transforming & copying the glyph image
|
|
</h4>
|
|
|
|
<p>If the glyph image is scalable (i.e., if <tt>glyph->format</tt> is
|
|
not <tt>ft_glyph_format_bitmap</tt>), it is possible to transform the
|
|
image anytime by a call to <tt>FT_Glyph_Transform()</tt>.</p>
|
|
|
|
<p>You can also copy a single glyph image with
|
|
<tt>FT_Glyph_Copy()</tt>. Here some example code:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_Glyph glyph, glyph2;
|
|
FT_Matrix matrix;
|
|
FT_Vector delta;
|
|
|
|
|
|
...
|
|
.. load glyph image in "glyph" ..
|
|
|
|
/* copy glyph to glyph2 */
|
|
error = FT_Glyph_Copy( glyph, &glyph2 );
|
|
if ( error ) { ... could not copy (out of memory) }
|
|
|
|
/* translate "glyph" */
|
|
delta.x = -100 * 64; /* coordinates are in 26.6 pixels */
|
|
delta.y = 50 * 64;
|
|
|
|
FT_Glyph_Transform( glyph, 0, &delta );
|
|
|
|
/* transform glyph2 (horizontal shear) */
|
|
matrix.xx = 0x10000L;
|
|
matrix.xy = 0;
|
|
matrix.yx = 0.12 * 0x10000L;
|
|
matrix.yy = 0x10000L;
|
|
|
|
FT_Glyph_Transform( glyph2, &matrix, 0 );</pre>
|
|
</font>
|
|
|
|
<p>Note that the 2x2 transformation matrix is always applied to
|
|
the 16.16 advance vector in the glyph; you thus don't need to
|
|
recompute it.</p>
|
|
|
|
<h4>
|
|
c. Measuring the glyph image
|
|
</h4>
|
|
|
|
<p>You can also retrieve the control (bounding) box of any glyph image
|
|
(scalable or not), using the <tt>FT_Glyph_Get_CBox()</tt>
|
|
function:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_BBox bbox;
|
|
|
|
|
|
...
|
|
FT_Glyph_Get_CBox( glyph, <em>bbox_mode</em>, &bbox );</pre>
|
|
</font>
|
|
|
|
<p>Coordinates are relative to the glyph origin, i.e. (0,0), using the
|
|
Y upwards convention. This function takes a special argument,
|
|
<tt>bbox_mode</tt>, to indicate how box coordinates are expressed. If
|
|
<tt>bbox_mode</tt> is set to <tt>ft_glyph_bbox_subpixels</tt>, the
|
|
coordinates are returned in 26.6 pixels (i.e. 1/64th of pixels).
|
|
|
|
<p>Note that the box's maximum coordinates are exclusive, which means
|
|
that you can always compute the width and height of the glyph image,
|
|
be it in integer or 26.6 pixels with</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
width = bbox.xMax - bbox.xMin;
|
|
height = bbox.yMax - bbox.yMin;</pre>
|
|
</font>
|
|
|
|
<p>Note also that for 26.6 coordinates, if
|
|
<tt>ft_glyph_bbox_gridfit</tt> is set in <tt>bbox_mode</tt>, the
|
|
coordinates will also be grid-fitted, which corresponds to</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
bbox.xMin = FLOOR(bbox.xMin)
|
|
bbox.yMin = FLOOR(bbox.yMin)
|
|
bbox.xMax = CEILING(bbox.xMax)
|
|
bbox.yMax = CEILING(bbox.yMax)</pre>
|
|
</font>
|
|
|
|
<p>The default value for <tt>bbox_mode</tt> is
|
|
<tt>ft_glyph_bbox_pixels</tt> (i.e. integer, grid-fitted pixel
|
|
coordinates). Please check the API reference of
|
|
<tt>FT_Glyph_Get_CBox()</tt> for other possible values.</p>
|
|
|
|
<h4>
|
|
d. Converting the glyph image to a bitmap
|
|
</h4>
|
|
|
|
<p>You may need to convert the glyph object to a bitmap once you have
|
|
conveniently cached or transformed it. This can be done easily with
|
|
the <tt>FT_Glyph_To_Bitmap()</tt> function:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_Vector origin;
|
|
|
|
|
|
origin.x = 32; /* 1/2 pixel in 26.6 format */
|
|
origin.y = 0;
|
|
|
|
error = FT_Glyph_To_Bitmap( &glyph,
|
|
<em>render_mode</em>,
|
|
&origin,
|
|
1 ); /* destroy orig. image == true */</pre>
|
|
</font>
|
|
|
|
<p>Some details on this function's parameters:</p>
|
|
|
|
<ul>
|
|
<li>
|
|
The first parameter is <em>the address of the source glyph's
|
|
handle</em>. When the function is called, it reads it to access
|
|
the source glyph object. After the call, the handle will point to
|
|
a <em>new</em> glyph object that contains the rendered bitmap.
|
|
</li>
|
|
<li>
|
|
The second parameter is a standard render mode that is used to
|
|
specify what kind of bitmap we want. It can be
|
|
<tt>ft_render_mode_default</tt> for an 8-bit anti-aliased pixmap,
|
|
or <tt>ft_render_mode_mono</tt> for a 1-bit monochrome bitmap.
|
|
</li>
|
|
<li>
|
|
The third parameter is a pointer to a 2d vector that is used
|
|
to translate the source glyph image before the conversion. Note
|
|
that the source image will be translated back to its original
|
|
position (and will thus be left unchanged) after the call. If you
|
|
do not need to translate the source glyph before rendering, set
|
|
this pointer to 0.
|
|
</li>
|
|
<li>
|
|
The last parameter is a Boolean to indicate whether the source
|
|
glyph object should be destroyed by the function. By default, the
|
|
original glyph object is never destroyed, even if its handle is
|
|
lost (it's up to client applications to keep it).
|
|
</li>
|
|
</ul>
|
|
|
|
<p>The new glyph object always contains a bitmap (when no error is
|
|
returned), and you must <em>typecast</em> its handle to the
|
|
<tt>FT_BitmapGlyph</tt> type in order to access its contents. This
|
|
type is a sort of <em>subclass</em> of <tt>FT_Glyph</tt> that contains
|
|
additional fields:</p>
|
|
|
|
<center>
|
|
<table width="90%" cellpadding=5>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>left</tt>
|
|
</td>
|
|
<td>
|
|
Just like the <tt>bitmap_left</tt> field of a glyph slot, this is
|
|
the horizontal distance from the glyph origin (0,0) to the
|
|
left-most pixel of the glyph bitmap. It is expressed in integer
|
|
pixels.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>top</tt>
|
|
</td>
|
|
<td>
|
|
Just like the <tt>bitmap_top</tt> field of a glyph slot, this is
|
|
the vertical distance from the glyph origin (0,0) to the top-most
|
|
pixel of the glyph bitmap (more exactly, to the pixel just above
|
|
the bitmap). This distance is expressed in integer pixels, and is
|
|
positive for upwards Y.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>bitmap</tt>
|
|
</td>
|
|
<td>
|
|
This is a bitmap descriptor for the glyph object, just like the
|
|
<tt>bitmap</tt> field in a glyph slot.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
|
|
<hr>
|
|
|
|
<h3>
|
|
3. Global glyph metrics
|
|
</h3>
|
|
|
|
<p>Unlike glyph metrics, global ones are used to describe distances and
|
|
features of a whole font face. They can be expressed either in 26.6
|
|
pixel format or in design <em>font units</em> for scalable formats.</p>
|
|
|
|
<h4>
|
|
a. Design global metrics
|
|
</h4>
|
|
|
|
<p>For scalable formats, all global metrics are expressed in font
|
|
units in order to be later scaled to device space, according to the
|
|
rules described in the last chapter of this part of the tutorial. You
|
|
can access them directly as fields of an <tt>FT_Face</tt> handle.</p>
|
|
|
|
<p>However, you need to check that the font face's format is scalable
|
|
before using them. This can be done with the macro
|
|
<tt>FT_IS_SCALABLE(face)</tt> which returns true if we have a scalable
|
|
format.</p>
|
|
|
|
<p>In this case, you can access the global design metrics as</p>
|
|
|
|
<center>
|
|
<table width="90%" cellpadding=5>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>units_per_EM</tt>
|
|
</td>
|
|
<td>
|
|
This is the size of the EM square for the font face. It is used
|
|
by scalable formats to scale design coordinates to device pixels,
|
|
as described by the last chapter of this part. Its value usually
|
|
is 2048 (for TrueType) or 1000 (for Type 1), but
|
|
other values are possible too. It is set to 1 for fixed-size
|
|
formats like FNT/FON/PCF/BDF.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>global_bbox</tt>
|
|
</td>
|
|
<td>
|
|
The global bounding box is defined as the largest rectangle that
|
|
can enclose all the glyphs in a font face. It is defined for
|
|
horizontal layouts only. This is not necessarily the smallest
|
|
bounding box which is possible.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>ascender</tt>
|
|
</td>
|
|
<td>
|
|
The ascender is the vertical distance from the horizontal baseline
|
|
to the height of the highest character in a font face.
|
|
<em>Unfortunately, font formats define the ascender
|
|
differently</em>. For some, it represents the ascent of all
|
|
capital Latin characters, without accents, for others it is the
|
|
ascent of the highest accented character, and finally, other
|
|
formats define it as being equal to <tt>global_bbox.yMax</tt>.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>descender</tt>
|
|
</td>
|
|
<td>
|
|
The descender is the vertical distance from the horizontal
|
|
baseline to the depth of the lowest character in a font face.
|
|
<em>Unfortunately, font formats define the descender
|
|
differently</em>. For some, it represents the descent of all
|
|
capital Latin characters, without accents, for others it is the
|
|
ascent of the lowest accented character, and finally, other
|
|
formats define it as being equal to <tt>global_bbox.yMin</tt>.
|
|
<em>This field is usually negative.</em>
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>text_height</tt>
|
|
</td>
|
|
<td>
|
|
This field is used to compute a default line spacing (i.e. the
|
|
baseline-to-baseline distance) when writing text with this font.
|
|
Note that it usually is larger than the sum of the ascender and
|
|
descender taken as absolute values. There is also no guarantee
|
|
that no glyphs can extend above or below subsequent baselines when
|
|
using this distance.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>max_advance_width</tt>
|
|
</td>
|
|
<td>
|
|
This field gives the maximum horizontal cursor advance for all
|
|
glyphs in the font. It can be used to quickly compute the maximum
|
|
advance width of a string of text. <em>It doesn't correspond to
|
|
the maximum glyph image width!</em>
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>max_advance_height</tt>
|
|
</td>
|
|
<td>
|
|
Same as <tt>max_advance_width</tt> but for vertical text layout.
|
|
It is only available in fonts providing vertical glyph metrics.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>underline_position</tt>
|
|
</td>
|
|
<td>
|
|
When displaying or rendering underlined text, this value
|
|
corresponds to the vertical position, relative to the baseline, of
|
|
the underline bar. It normally is negative (as it is below the
|
|
baseline).
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>underline_thickness</tt>
|
|
</td>
|
|
<td>
|
|
When displaying or rendering underlined text, this value
|
|
corresponds to the vertical thickness of the underline.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
|
|
<p>Notice how, unfortunately, the values of the ascender and the
|
|
descender are not reliable (due to various discrepancies in font
|
|
formats).</p>
|
|
|
|
<h4>
|
|
b. Scaled global metrics
|
|
</h4>
|
|
|
|
<p>Each size object also contains scaled versions of some of the
|
|
global metrics described above. They can be accessed directly through
|
|
the <tt>face->size->metrics</tt> structure.</p>
|
|
|
|
<p>Note that these values correspond to scaled versions of the design
|
|
global metrics, <em>with no rounding/grid-fitting performed</em>. They
|
|
are also completely independent of any hinting process. In other
|
|
words, don't rely on them to get exact metrics at the pixel level.
|
|
They are expressed in 26.6 pixel format.</p>
|
|
|
|
<center>
|
|
<table width="90%" cellpadding=5>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>ascender</tt>
|
|
</td>
|
|
<td>
|
|
This is the scaled version of the original design ascender.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>descender</tt>
|
|
</td>
|
|
<td>
|
|
This is the scaled version of the original design descender.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>height</tt>
|
|
</td>
|
|
<td>
|
|
The scaled version of the original design text height. This is
|
|
probably the only field you should really use in this structure.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>max_advance</tt>
|
|
</td>
|
|
<td>
|
|
This is the scaled version of the original design max advance.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
|
|
<p>Note that the <tt>face->size->metrics</tt> structure contains other
|
|
fields that are used to scale design coordinates to device space.
|
|
They are described below.</p>
|
|
|
|
<h4>
|
|
c. Kerning
|
|
</h4>
|
|
|
|
<p>Kerning is the process of adjusting the position of two subsequent
|
|
glyph images in a string of text, in order to improve the general
|
|
appearance of text. Basically, it means that when the glyph for an
|
|
"A" is followed by the glyph for a "V", the space between them can be
|
|
slightly reduced to avoid extra "diagonal whitespace".</p>
|
|
|
|
<p>Note that in theory, kerning can happen both in the horizontal and
|
|
vertical direction between two glyphs; however, it only happens in the
|
|
horizontal direction in nearly all cases except really extreme
|
|
ones.</p>
|
|
|
|
<p>Not all font formats contain kerning information. Instead, they
|
|
sometimes rely on an additional file that contains various glyph
|
|
metrics, including kerning, but no glyph images. A good example would
|
|
be the Type 1 format, where glyph images are stored in a file
|
|
with extension <tt>.pfa</tt> or <tt>.pfb</tt>, and where kerning
|
|
metrics can be found in an additional file with extension
|
|
<tt>.afm</tt> or <tt>.pfm</tt>.</p>
|
|
|
|
<p>FreeType 2 allows you to deal with this by providing the
|
|
<tt>FT_Attach_File()</tt> and <tt>FT_Attach_Stream()</tt> APIs. Both
|
|
functions are used to load additional metrics into a face object, by
|
|
reading them from an additional format-specific file. For example,
|
|
you could open a Type 1 font by doing the following:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
error = FT_New_Face( library,
|
|
"/usr/shared/fonts/cour.pfb",
|
|
0,
|
|
&face );
|
|
if ( error ) { ... }
|
|
|
|
error = FT_Attach_File( face, "/usr/shared/fonts/cour.afm" );
|
|
if ( error )
|
|
{
|
|
.. could not read kerning and additional metrics ..
|
|
}</pre>
|
|
</font>
|
|
|
|
<p>Note that <tt>FT_Attach_Stream()</tt> is similar to
|
|
<tt>FT_Attach_File()</tt> except that it doesn't take a C string
|
|
to name the extra file, but a <tt>FT_Stream</tt> handle. Also,
|
|
<em>reading a metrics file is in no way mandatory</em>.</p>
|
|
|
|
<p>Finally, the file attachment APIs are very generic and can be used
|
|
to load any kind of extra information for a given face. The nature of
|
|
the additional data is entirely font format specific.</p>
|
|
|
|
<p>FreeType 2 allows you to retrieve the kerning information
|
|
between two glyphs through the <tt>FT_Get_Kerning()</tt> function,
|
|
whose interface looks like</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_Vector kerning;
|
|
|
|
|
|
...
|
|
error = FT_Get_Kerning(
|
|
face, /* handle to face object */
|
|
left, /* left glyph index */
|
|
right, /* right glyph index */
|
|
<em>kerning_mode</em>, /* kerning mode */
|
|
&kerning ); /* target vector */</pre>
|
|
</font>
|
|
|
|
<p>As can be seen, the function takes a handle to a face object, the
|
|
indices of the left and right glyphs for which the kerning value is
|
|
desired, as well as an integer, called the <em>kerning mode</em>, and
|
|
a pointer to a destination vector that receives the corresponding
|
|
distances.</p>
|
|
|
|
<p>The kerning mode is very similar to <tt>bbox_mode</tt> described in
|
|
a previous part. It is an enumeration value that indicates how the
|
|
kerning distances are expressed in the target vector.</p>
|
|
|
|
<p>The default value <tt>ft_kerning_mode_default</tt> (which has
|
|
value 0) corresponds to kerning distances expressed in 26.6
|
|
grid-fitted pixels (which means that the values are multiples
|
|
of 64). For scalable formats, this means that the design kerning
|
|
distance is scaled, then rounded.</p>
|
|
|
|
<p>The value <tt>ft_kerning_mode_unfitted</tt> corresponds to kerning
|
|
distances expressed in 26.6 unfitted pixels (i.e. that do not
|
|
correspond to integer coordinates). It is the design kerning distance
|
|
that is scaled without rounding.</p>
|
|
|
|
<p>Finally, the value <tt>ft_kerning_mode_unscaled</tt> is used to
|
|
return the design kerning distance, expressed in font units. You can
|
|
later scale it to device space using the computations explained in the
|
|
last chapter of this part.</p>
|
|
|
|
<p>Note that the "left" and "right" positions correspond to the
|
|
<em>visual order</em> of the glyphs in the string of text. This is
|
|
important for bidirectional text, or when writing right-to-left
|
|
text.</p>
|
|
|
|
<hr>
|
|
|
|
<h3>
|
|
4. Simple text rendering: kerning + centering
|
|
</h3>
|
|
|
|
<p>In order to show off what we have just learned, we will now modify
|
|
the example code that was provided in the first part to render a string
|
|
of text, and enhance it to support kerning and delayed rendering.</p>
|
|
|
|
<h4>
|
|
a. Kerning support
|
|
</h4>
|
|
|
|
<p>Adding support for kerning to our code is trivial, as long as we
|
|
consider that we are still dealing with a left-to-right script like
|
|
Latin. We need to retrieve the kerning distance between two glyphs in
|
|
order to alter the pen position appropriately. The code looks
|
|
like</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_GlyphSlot slot = face->glyph; /* a small shortcut */
|
|
FT_UInt glyph_index;
|
|
FT_Bool use_kerning;
|
|
FT_UInt previous;
|
|
int pen_x, pen_y, n;
|
|
|
|
|
|
.. initialize library ..
|
|
.. create face object ..
|
|
.. set character size ..
|
|
|
|
pen_x = 300;
|
|
pen_y = 200;
|
|
|
|
use_kerning = FT_HAS_KERNING( face );
|
|
previous = 0;
|
|
|
|
for ( n = 0; n < num_chars; n++ )
|
|
{
|
|
/* convert character code to glyph index */
|
|
glyph_index = FT_Get_Char_Index( face, text[n] );
|
|
|
|
/* retrieve kerning distance and move pen position */
|
|
if ( use_kerning && previous && glyph_index )
|
|
{
|
|
FT_Vector delta;
|
|
|
|
|
|
FT_Get_Kerning( face, previous, glyph_index,
|
|
ft_kerning_mode_default, &delta );
|
|
|
|
pen_x += delta.x >> 6;
|
|
}
|
|
|
|
/* load glyph image into the slot (erase previous one) */
|
|
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_RENDER );
|
|
if ( error ) continue; /* ignore errors */
|
|
|
|
/* now, draw to our target surface */
|
|
my_draw_bitmap( &slot->bitmap,
|
|
pen_x + slot->bitmap_left,
|
|
pen_y - slot->bitmap_top );
|
|
|
|
/* increment pen position */
|
|
pen_x += slot->advance.x >> 6;
|
|
|
|
/* record current glyph index */
|
|
previous = glyph_index;
|
|
}</pre>
|
|
</font>
|
|
|
|
<p>We are done. Notice that</p>
|
|
|
|
<ul>
|
|
<li>
|
|
As kerning is determined from glyph indices, we need to
|
|
explicitly convert our character code into a glyph index, then
|
|
later call <tt>FT_Load_Glyph()</tt> instead of
|
|
<tt>FT_Load_Char()</tt>.
|
|
</li>
|
|
<li>
|
|
We use a Boolean named <tt>use_kerning</tt> which is set with the
|
|
result of the macro <tt>FT_HAS_KERNING(face)</tt>. It is
|
|
certainly faster not to call <tt>FT_Get_Kerning()</tt> if we
|
|
know that the font face does not contain kerning information.
|
|
</li>
|
|
<li>
|
|
We move the position of the pen <em>before</em> a new glyph is
|
|
drawn.
|
|
</li>
|
|
<li>
|
|
We did initialize the variable <tt>previous</tt> with the
|
|
value 0, which always correspond to the <em>missing
|
|
glyph</em> (also called <tt>.notdef</tt> in the PostScript world).
|
|
There is never any kerning distance associated with this glyph.
|
|
</li>
|
|
<li>
|
|
We do not check the error code returned by
|
|
<tt>FT_Get_Kerning()</tt>. This is because the function always
|
|
set <tt>delta</tt> to (0,0) when an error occurs.
|
|
</li>
|
|
</ul>
|
|
|
|
<h4>
|
|
b. Centering
|
|
</h4>
|
|
|
|
<p>Our code becomes more interesting but it is still a bit too simple
|
|
for normal uses. For example, the position of the pen is determined
|
|
before we do the rendering if in a real-life situation; you would want
|
|
to layout the text and measure it before computing its final position
|
|
(e.g. centering) or perform things like word-wrapping.</p>
|
|
|
|
<p>As a consequence we are now going to decompose our text rendering
|
|
function into two distinct but successive parts: The first one will
|
|
position individual glyph images on the baseline, while the second one
|
|
will render the glyphs. As will be shown, this has many
|
|
advantages.</p>
|
|
|
|
<p>We start by storing individual glyph images, as well as their
|
|
position on the baseline. This can be done with code like</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_GlyphSlot slot = face->glyph; /* a small shortcut */
|
|
FT_UInt glyph_index;
|
|
FT_Bool use_kerning;
|
|
FT_UInt previous;
|
|
int pen_x, pen_y, n;
|
|
|
|
FT_Glyph glyphs[MAX_GLYPHS]; /* glyph image */
|
|
FT_Vector pos [MAX_GLYPHS]; /* glyph position */
|
|
FT_UInt num_glyphs;
|
|
|
|
|
|
.. initialize library ..
|
|
.. create face object ..
|
|
.. set character size ..
|
|
|
|
pen_x = 0; /* start at (0,0)! */
|
|
pen_y = 0;
|
|
|
|
num_glyphs = 0;
|
|
use_kerning = FT_HAS_KERNING( face );
|
|
previous = 0;
|
|
|
|
for ( n = 0; n < num_chars; n++ )
|
|
{
|
|
/* convert character code to glyph index */
|
|
glyph_index = FT_Get_Char_Index( face, text[n] );
|
|
|
|
/* retrieve kerning distance and move pen position */
|
|
if ( use_kerning && previous && glyph_index )
|
|
{
|
|
FT_Vector delta;
|
|
|
|
|
|
FT_Get_Kerning( face, previous, glyph_index,
|
|
ft_kerning_mode_default, &delta );
|
|
|
|
pen_x += delta.x >> 6;
|
|
}
|
|
|
|
/* store current pen position */
|
|
pos[num_glyphs].x = pen_x;
|
|
pos[num_glyphs].y = pen_y;
|
|
|
|
/* load glyph image into the slot. DO NOT RENDER IT! */
|
|
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
|
|
if ( error ) continue; /* ignore errors, jump to next glyph */
|
|
|
|
/* extract glyph image and store it in our table */
|
|
error = FT_Get_Glyph( face->glyph, &glyphs[num_glyphs] );
|
|
if ( error ) continue; /* ignore errors, jump to next glyph */
|
|
|
|
/* increment pen position */
|
|
pen_x += slot->advance.x >> 6;
|
|
|
|
/* record current glyph index */
|
|
previous = glyph_index;
|
|
|
|
/* increment number of glyphs */
|
|
num_glyphs++;
|
|
}</pre>
|
|
</font>
|
|
|
|
<p>As you see, this is a very slight variation of our previous code
|
|
where we extract each glyph image from the slot, and store it, along
|
|
with the corresponding position, in our tables.</p>
|
|
|
|
<p>Note also that <tt>pen_x</tt> contains the total advance for the
|
|
string of text. We can now compute the bounding box of the text
|
|
string with a simple function like</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
void compute_string_bbox( FT_BBox* abbox )
|
|
{
|
|
FT_BBox bbox;
|
|
|
|
|
|
/* initialize string bbox to "empty" values */
|
|
bbox.xMin = bbox.yMin = 32000;
|
|
bbox.xMax = bbox.yMax = -32000;
|
|
|
|
/* for each glyph image, compute its bounding box, */
|
|
/* translate it, and grow the string bbox */
|
|
for ( n = 0; n < num_glyphs; n++ )
|
|
{
|
|
FT_BBox glyph_bbox;
|
|
|
|
|
|
FT_Glyph_Get_CBox( glyphs[n], &glyph_bbox );
|
|
|
|
glyph_bbox.xMin += pos[n].x;
|
|
glyph_bbox.xMax += pos[n].x;
|
|
glyph_bbox.yMin += pos[n].y;
|
|
glyph_bbox.yMax += pos[n].y;
|
|
|
|
if ( glyph_bbox.xMin < bbox.xMin )
|
|
bbox.xMin = glyph_bbox.xMin;
|
|
|
|
if ( glyph_bbox.yMin < bbox.yMin )
|
|
bbox.yMin = glyph_bbox.yMin;
|
|
|
|
if ( glyph_bbox.xMax > bbox.xMax )
|
|
bbox.xMax = glyph_bbox.xMax;
|
|
|
|
if ( glyph_bbox.yMax &gy; bbox.yMax )
|
|
bbox.yMax = glyph_bbox.yMax;
|
|
}
|
|
|
|
/* check that we really grew the string bbox */
|
|
if ( bbox.xMin > bbox.xMax )
|
|
{
|
|
bbox.xMin = 0;
|
|
bbox.yMin = 0;
|
|
bbox.xMax = 0;
|
|
bbox.yMax = 0;
|
|
}
|
|
|
|
/* return string bbox */
|
|
*abbox = bbox;
|
|
}</pre>
|
|
</font>
|
|
|
|
<p>The resulting bounding box dimensions can then be used to compute
|
|
the final pen position before rendering the string as in:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
/* compute string dimensions in integer pixels */
|
|
string_width = ( string_bbox.xMax - string_bbox.xMin ) / 64;
|
|
string_height = ( string_bbox.yMax - string_bbox.yMin ) / 64;
|
|
|
|
/* compute start pen position in 26.6 cartesian pixels */
|
|
start_x = ( ( my_target_width - string_width ) / 2 ) * 64;
|
|
start_y = ( ( my_target_height - string_height ) / 2 ) * 64;
|
|
|
|
for ( n = 0; n < num_glyphs; n++ )
|
|
{
|
|
FT_Glyph image;
|
|
FT_Vector pen;
|
|
|
|
|
|
image = glyphs[n];
|
|
|
|
pen.x = start_x + pos[n].x;
|
|
pen.y = start_y + pos[n].y;
|
|
|
|
error = FT_Glyph_To_Bitmap( &image, ft_render_mode_normal,
|
|
&pen.x, 0 );
|
|
if ( !error )
|
|
{
|
|
FT_BitmapGlyph bit = (FT_BitmapGlyph)image;
|
|
|
|
|
|
my_draw_bitmap( bitmap->bitmap,
|
|
bitmap->left,
|
|
my_target_height - bitmap->top );
|
|
|
|
FT_Done_Glyph( image );
|
|
}
|
|
}</pre>
|
|
</font>
|
|
|
|
<p>Some remarks:</p>
|
|
|
|
<ul>
|
|
<li>
|
|
The pen position is expressed in the cartesian space (i.e.
|
|
Y upwards).
|
|
</li>
|
|
<li>
|
|
We call <tt>FT_Glyph_To_Bitmap()</tt> with the <tt>destroy</tt>
|
|
parameter set to 0 (false), in order to avoid destroying the
|
|
original glyph image. The new glyph bitmap is accessed through
|
|
<tt>image</tt> after the call and is typecast to an
|
|
<tt>FT_BitmapGlyph</tt>.
|
|
</li>
|
|
<li>
|
|
We use translation when calling <tt>FT_Glyph_To_Bitmap()</tt>.
|
|
This ensures that the <tt>left</tt> and <tt>top</tt> fields of the
|
|
bitmap glyph object are already set to the correct pixel
|
|
coordinates in the cartesian space.
|
|
</li>
|
|
<li>
|
|
Of course, we still need to convert pixel coordinates from
|
|
cartesian to device space before rendering, hence the
|
|
<tt>my_target_height - bitmap->top</tt> in the call to
|
|
<tt>my_draw_bitmap()</tt>.
|
|
</li>
|
|
</ul>
|
|
|
|
<p>The same loop can be used to render the string anywhere on our
|
|
display surface, without the need to reload our glyph images each
|
|
time.</p>
|
|
|
|
<hr>
|
|
|
|
<h3>
|
|
5. Advanced text rendering: transformation + centering + kerning
|
|
</h3>
|
|
|
|
<p>We are now going to modify our code in order to be able to easily
|
|
transform the rendered string, for example to rotate it. We will start
|
|
by performing a few minor improvements:</p>
|
|
|
|
<h4>
|
|
a. packing & translating glyphs
|
|
</h4>
|
|
|
|
<p>We start by packing the information related to a single glyph image
|
|
into a single structure instead of parallel arrays. We thus define
|
|
the following structure type:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
typedef struct TGlyph_
|
|
{
|
|
FT_UInt index; /* glyph index */
|
|
FT_Vector pos; /* glyph origin on the baseline */
|
|
FT_Glyph image; /* glyph image */
|
|
|
|
} TGlyph, *PGlyph;</pre>
|
|
</font>
|
|
|
|
<p>We will also translate each glyph image directly after it is loaded
|
|
to its position on the baseline at load time, which has several
|
|
advantages. Our glyph sequence loader thus becomes:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_GlyphSlot slot = face->glyph; /* a small shortcut */
|
|
FT_UInt glyph_index;
|
|
FT_Bool use_kerning;
|
|
FT_UInt previous;
|
|
int pen_x, pen_y, n;
|
|
|
|
TGlyph glyphs[MAX_GLYPHS]; /* glyphs table */
|
|
PGlyph glyph; /* current glyph in table */
|
|
FT_UInt num_glyphs;
|
|
|
|
|
|
.. initialize library ..
|
|
.. create face object ..
|
|
.. set character size ..
|
|
|
|
pen_x = 0; /* start at (0,0)! */
|
|
pen_y = 0;
|
|
|
|
num_glyphs = 0;
|
|
use_kerning = FT_HAS_KERNING( face );
|
|
previous = 0;
|
|
|
|
glyph = glyphs;
|
|
for ( n = 0; n < num_chars; n++ )
|
|
{
|
|
glyph->index = FT_Get_Char_Index( face, text[n] );
|
|
|
|
if ( use_kerning && previous && glyph->index )
|
|
{
|
|
FT_Vector delta;
|
|
|
|
|
|
FT_Get_Kerning( face, previous, glyph->index,
|
|
ft_kerning_mode_default, &delta );
|
|
|
|
pen_x += delta.x >> 6;
|
|
}
|
|
|
|
/* store current pen position */
|
|
glyph->pos.x = pen_x;
|
|
glyph->pos.y = pen_y;
|
|
|
|
error = FT_Load_Glyph( face, glyph_index, FT_LOAD_DEFAULT );
|
|
if ( error ) continue;
|
|
|
|
error = FT_Get_Glyph( face->glyph, &glyph->image );
|
|
if ( error ) continue;
|
|
|
|
/* translate the glyph image now */
|
|
FT_Glyph_Transform( glyph->image, 0, &glyph->pos );
|
|
|
|
pen_x += slot->advance.x >> 6;
|
|
previous = glyph->index
|
|
|
|
/* increment number of glyphs */
|
|
glyph++;
|
|
}
|
|
|
|
/* count number of glyphs loaded */
|
|
num_glyphs = glyph - glyphs;</pre>
|
|
</font>
|
|
|
|
<p>Translating glyphs now has several advantages, as mentioned
|
|
earlier. The first one is that we don't need to translate the glyph
|
|
bounding box when we compute the string's bounding box. The code
|
|
becomes:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
void compute_string_bbox( FT_BBox* abbox )
|
|
{
|
|
FT_BBox bbox;
|
|
|
|
|
|
bbox.xMin = bbox.yMin = 32000;
|
|
bbox.xMax = bbox.yMax = -32000;
|
|
|
|
for ( n = 0; n < num_glyphs; n++ )
|
|
{
|
|
FT_BBox glyph_bbox;
|
|
|
|
|
|
FT_Glyph_Get_CBox( glyphs[n], &glyph_bbox );
|
|
|
|
if ( glyph_bbox.xMin < bbox.xMin )
|
|
bbox.xMin = glyph_bbox.xMin;
|
|
|
|
if ( glyph_bbox.yMin < bbox.yMin )
|
|
bbox.yMin = glyph_bbox.yMin;
|
|
|
|
if ( glyph_bbox.xMax > bbox.xMax )
|
|
bbox.xMax = glyph_bbox.xMax;
|
|
|
|
if ( glyph_bbox.yMax &gy; bbox.yMax )
|
|
bbox.yMax = glyph_bbox.yMax;
|
|
}
|
|
|
|
if ( bbox.xMin > bbox.xMax )
|
|
{
|
|
bbox.xMin = 0;
|
|
bbox.yMin = 0;
|
|
bbox.xMax = 0;
|
|
bbox.yMax = 0;
|
|
}
|
|
|
|
*abbox = bbox;
|
|
}</pre>
|
|
</font>
|
|
|
|
<p><tt>compute_string_bbox()</tt> can now compute the bounding box of
|
|
a transformed glyph string. For example, we can do something
|
|
like</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_BBox bbox;
|
|
FT_Matrix matrix;
|
|
FT_Vector delta;
|
|
|
|
|
|
... load glyph sequence
|
|
|
|
... setup "matrix" and "delta"
|
|
|
|
/* transform glyphs */
|
|
for ( n = 0; n < num_glyphs; n++ )
|
|
FT_Glyph_Transform( glyphs[n].image, &matrix, &delta );
|
|
|
|
/* compute bounding box of transformed glyphs */
|
|
compute_string_bbox( &bbox );</pre>
|
|
</font>
|
|
|
|
<h4>
|
|
b. Rendering a transformed glyph sequence
|
|
</h4>
|
|
|
|
<p>However, directly transforming the glyphs in our sequence is not a
|
|
useful idea if we want to reuse them in order to draw the text string
|
|
with various angles or transforms. It is better to perform the affine
|
|
transformation just before the glyph is rendered, as in the following
|
|
code:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_Vector start;
|
|
FT_Matrix transform;
|
|
|
|
|
|
/* get bbox of original glyph sequence */
|
|
compute_string_bbox( &string_bbox );
|
|
|
|
/* compute string dimensions in integer pixels */
|
|
string_width = ( string_bbox.xMax - string_bbox.xMin ) / 64;
|
|
string_height = ( string_bbox.yMax - string_bbox.yMin ) / 64;
|
|
|
|
/* set up start position in 26.6 cartesian space */
|
|
start.x = ( ( my_target_width - string_width ) / 2 ) * 64;
|
|
start.y = ( ( my_target_height - string_height ) / 2 ) * 64;
|
|
|
|
/* set up transformation (a rotation here) */
|
|
matrix.xx = (FT_Fixed)( cos( angle ) * 0x10000L );
|
|
matrix.xy = (FT_Fixed)(-sin( angle ) * 0x10000L );
|
|
matrix.yx = (FT_Fixed)( sin( angle ) * 0x10000L );
|
|
matrix.yy = (FT_Fixed)( cos( angle ) * 0x10000L );
|
|
|
|
for ( n = 0; n < num_glyphs; n++ )
|
|
{
|
|
FT_Glyph image;
|
|
FT_Vector pen;
|
|
FT_BBox bbox;
|
|
|
|
|
|
/* create a copy of the original glyph */
|
|
error = FT_Glyph_Copy( glyphs[n].image, &image );
|
|
if ( error ) continue;
|
|
|
|
/* transform copy (this will also translate it to the */
|
|
/* correct position */
|
|
FT_Glyph_Transform( image, &matrix, &start );
|
|
|
|
/* check bounding box -- if the transformed glyph image */
|
|
/* is not in our target surface, we can avoid rendering */
|
|
FT_Glyph_Get_CBox( image, ft_glyph_bbox_pixels, &bbox );
|
|
if ( bbox.xMax <= 0 || bbox.xMin >= my_target_width ||
|
|
bbox.yMax <= 0 || bbox.yMin >= my_target_height )
|
|
continue;
|
|
|
|
/* convert glyph image to bitmap (destroy the glyph */
|
|
/* copy!) */
|
|
error = FT_Glyph_To_Bitmap(
|
|
&image,
|
|
ft_render_mode_normal,
|
|
0, /* no additional translation */
|
|
1 ); /* destroy copy in "image" */
|
|
if ( !error )
|
|
{
|
|
FT_BitmapGlyph bit = (FT_BitmapGlyph)image;
|
|
|
|
|
|
my_draw_bitmap( bitmap->bitmap,
|
|
bitmap->left,
|
|
my_target_height - bitmap->top );
|
|
|
|
FT_Done_Glyph( image );
|
|
}
|
|
}</pre>
|
|
</font>
|
|
|
|
<p>There are a few changes compared to the previous version of this
|
|
code:</p>
|
|
|
|
<ul>
|
|
<li>
|
|
We keep the original glyph images untouched, by transforming a
|
|
copy.
|
|
</li>
|
|
<li>
|
|
We perform clipping computations in order to avoid rendering &
|
|
drawing glyphs that are not within our target surface.
|
|
</li>
|
|
<li>
|
|
We always destroy the copy when calling
|
|
<tt>FT_Glyph_To_Bitmap()</tt> in order to get rid of the
|
|
transformed scalable image. Note that the image is destroyed even
|
|
when the function returns an error code (which is why
|
|
<tt>FT_Done_Glyph()</tt> is only called within the compound
|
|
statement).
|
|
</li>
|
|
<li>
|
|
The translation of the glyph sequence to the start pen position is
|
|
integrated in the call to <tt>FT_Glyph_Transform()</tt> intead of
|
|
<tt>FT_Glyph_To_Bitmap()</tt>.
|
|
</li>
|
|
</ul>
|
|
|
|
<p>It is possible to call this function several times to render the
|
|
string with different angles, or even change the way <tt>start</tt>
|
|
is computed in order to move it to a different place.</p>
|
|
|
|
<p>This code is the basis of the FreeType 2 demonstration program
|
|
named <tt>ftstring.c</tt>. It could be easily extended to perform
|
|
advanced text layout or word-wrapping in the first part, without
|
|
changing the second one.</p>
|
|
|
|
<p>Note however that a normal implementation would use a glyph cache
|
|
in order to reduce memory consumption. For example, let us assume
|
|
that our text string to render is "FreeType". We would store three
|
|
identical glyph images in our table for the letter "e", which isn't
|
|
optimal (especially when you consider longer lines of text, or even
|
|
whole pages).</p>
|
|
|
|
<hr>
|
|
|
|
<h3>
|
|
6. Accessing metrics in design font units and scaling them
|
|
</h3>
|
|
|
|
<p>Scalable font formats usually store a single vectorial image, called
|
|
an <em>outline</em>, for each glyph in a face. Each outline is defined
|
|
in an abstract grid called the <em>design space</em>, with coordinates
|
|
expressed in nominal <em>font units</em>. When a glyph image is loaded,
|
|
the font driver usually scales the outline to device space according to
|
|
the current character pixel size found in a <tt>FT_Size</tt> object.
|
|
The driver may also modify the scaled outline in order to significantly
|
|
improve its appearance on a pixel-based surface (a process known as
|
|
<em>hinting</em> or <em>grid-fitting</em>).</p>
|
|
|
|
<p>This section describes how design coordinates are scaled to device
|
|
space, and how to read glyph outlines and metrics in font units. This
|
|
is important for a number of things:</p>
|
|
|
|
<ul>
|
|
<li>
|
|
<p>to perform "true" WYSIWYG text layout.</p>
|
|
</li>
|
|
<li>
|
|
<p>to access font data for conversion or analysis purposes</p>
|
|
</li>
|
|
</ul>
|
|
|
|
<h4>
|
|
a. Scaling distances to device space
|
|
</h4>
|
|
|
|
<p>Design coordinates are scaled to device space using a simple
|
|
scaling transformation whose coefficients are computed with the help
|
|
of the <em>character pixel size</em>:</p>
|
|
|
|
<font color="purple">
|
|
<pre>
|
|
device_x = design_x * x_scale
|
|
device_y = design_y * y_scale
|
|
|
|
x_scale = pixel_size_x / EM_size
|
|
y_scale = pixel_size_y / EM_size</pre>
|
|
</font>
|
|
|
|
<p>Here, the value <tt>EM_size</tt> is font-specific and corresponds
|
|
to the size of an abstract square of the design space (called the
|
|
"EM"), which is used by font designers to create glyph images. It is
|
|
thus expressed in font units. It is also accessible directly for
|
|
scalable font formats as <tt>face->units_per_EM</tt>. You should
|
|
check that a font face contains scalable glyph images by using the
|
|
<tt>FT_IS_SCALABLE(face)</tt> macro, which returns true when the font
|
|
is scalable.</p>
|
|
|
|
<p>When you call the function <tt>FT_Set_Pixel_Sizes()</tt>, you are
|
|
specifying the value of <tt>pixel_size_x</tt> and
|
|
<tt>pixel_size_y</tt>; FreeType will then immediately compute the
|
|
values of <tt>x_scale</tt> and <tt>y_scale</tt>.</p>
|
|
|
|
<p>When you call the function <tt>FT_Set_Char_Size()</tt>, you are
|
|
specifying the character size in physical "points", which is used,
|
|
along with the device's resolutions, to compute the character pixel
|
|
size, then the scaling factors.</p>
|
|
|
|
<p>Note that after calling any of these two functions, you can access
|
|
the values of the character pixel size and scaling factors as fields
|
|
of the <tt>face->size->metrics</tt> structure. These fields are:</p>
|
|
|
|
<center>
|
|
<table width="90%" cellpadding="5">
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>x_ppem</t>
|
|
</td>
|
|
<td>
|
|
This is the size in integer pixels of the EM square, which also is
|
|
the <em>horizontal character pixel size</em>, called
|
|
<tt>pixel_size_x</tt> in the above example. <tt>x_ppem</tt> means
|
|
"x pixels per EM".
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>y_ppem</tt>
|
|
</td>
|
|
<td>
|
|
This is the size in integer pixels of the EM square, which also is
|
|
the <em>vertical character pixel size</em>, called
|
|
<tt>pixel_size_y</tt> in the above example. <tt>y_ppem</tt> means
|
|
"y pixels per EM".
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>x_scale</tt>
|
|
</td>
|
|
<td>
|
|
This is a 16.16 fixed float scale that is used to directly scale
|
|
horizontal distances from design space to 1/64th of device pixels.
|
|
</td>
|
|
</tr>
|
|
<tr valign=top>
|
|
<td>
|
|
<tt>y_scale</tt>
|
|
</td>
|
|
<td>
|
|
This is a 16.16 fixed float scale that is used to directly scale
|
|
vertical distances from design space to 1/64th of device pixels.
|
|
</td>
|
|
</tr>
|
|
</table>
|
|
</center>
|
|
|
|
<p>You can scale a distance expressed in font units to 26.6 pixels
|
|
directly with the help of the <tt>FT_MulFix()</tt> function, as
|
|
in:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
/* convert design distances to 1/64th of pixels */
|
|
pixels_x = FT_MulFix( design_x, face->size->metrics.x_scale );
|
|
pixels_y = FT_MulFix( design_y, face->size->metrics.y_scale );</pre>
|
|
</font>
|
|
|
|
<p>However, you can also scale the value directly with more accuracy
|
|
by using doubles and the equations:</p>
|
|
|
|
<font color="blue">
|
|
<pre>
|
|
FT_Size_Metrics* metrics = &face->size->metrics; /* shortcut */
|
|
double pixels_x, pixels_y;
|
|
double em_size, x_scale, y_scale;
|
|
|
|
|
|
/* compute floating point scale factors */
|
|
em_size = 1.0 * face->units_per_EM;
|
|
x_scale = metrics->x_ppem / em_size;
|
|
y_scale = metrics->y_ppem / em_size;
|
|
|
|
/* convert design distances to floating point pixels */
|
|
pixels_x = design_x * x_scale;
|
|
pixels_y = design_y * y_scale;</pre>
|
|
</font>
|
|
|
|
<h4>
|
|
b. Accessing design metrics (glyph & global)
|
|
</h4>
|
|
|
|
<p>You can access glyph metrics in font units by specifying the
|
|
<tt>FT_LOAD_NO_SCALE</tt> bit flag in <tt>FT_Load_Glyph()</tt> or
|
|
<tt>FT_Load_Char()</tt>. The metrics returned in
|
|
<tt>face->glyph->metrics</tt> will then all be in font units.</p>
|
|
|
|
<p>Unscaled kerning data can be retrieved using the
|
|
<tt>ft_kerning_mode_unscaled</tt> mode.</p>
|
|
|
|
<p>Finally, a few global metrics are available directly in font units
|
|
as fields of the <tt>FT_Face</tt> handle, as described in
|
|
section 3 of this tutorial part.</p>
|
|
|
|
<hr>
|
|
|
|
<h3>
|
|
Conclusion
|
|
</h3>
|
|
|
|
<p>This is the end of the second part of the FreeType 2 tutorial;
|
|
you are now able to access glyph metrics, manage glyph images, and
|
|
render text much more intelligently (kerning, measuring, transforming
|
|
& caching).</p>
|
|
|
|
<p>With this knowledge you can build a pretty decent text service on top
|
|
of FreeType 2, and you could possibly stop there if you want.</p>
|
|
|
|
<p>The next section will deal with FreeType 2 internals (like
|
|
modules, vector outlines, font drivers, renderers), as well as a few
|
|
font format specific issues (mainly, how to access certain TrueType or
|
|
Type 1 tables).</p>
|
|
</td></tr>
|
|
</table>
|
|
</center>
|
|
|
|
</body>
|
|
</html>
|