1627 lines
62 KiB
HTML
1627 lines
62 KiB
HTML
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
|
|||
|
<html>
|
|||
|
<head>
|
|||
|
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
|
|||
|
<meta name="Author" content="blob">
|
|||
|
<meta name="GENERATOR" content="Mozilla/4.5 [fr] (Win98; I) [Netscape]">
|
|||
|
<title>FreeType Glyph Conventions</title>
|
|||
|
</head>
|
|||
|
<body>
|
|||
|
|
|||
|
<body text="#000000"
|
|||
|
bgcolor="#FFFFFF"
|
|||
|
link="#0000EF"
|
|||
|
vlink="#51188E"
|
|||
|
alink="#FF0000">
|
|||
|
|
|||
|
<center>
|
|||
|
<h1>
|
|||
|
FreeType Glyph Conventions</h1></center>
|
|||
|
|
|||
|
<center>
|
|||
|
<h2>
|
|||
|
version 2.0</h2></center>
|
|||
|
|
|||
|
<center>
|
|||
|
<h3>
|
|||
|
Copyright 1998-1999David Turner (<a href="mailto:david@freetype.org">david@freetype.org</a>)<br>
|
|||
|
Copyright 1999 The FreeType Development Team (<a href="devel@freetype.org">devel@freetype.org</a>)</h3></center>
|
|||
|
|
|||
|
<p><br>
|
|||
|
<hr WIDTH="100%">
|
|||
|
<h2>
|
|||
|
Introduction</h2>
|
|||
|
|
|||
|
<blockquote>This document discusses in great details the definition of
|
|||
|
various concepts related to digital typography, as well as a few specific
|
|||
|
to the FreeType library. It also explains the ways typographic information,
|
|||
|
like glyph metrics, kerning distances, etc.. is to be managed and used.
|
|||
|
It relates to the layout and display of text strings, either in a conventional
|
|||
|
(i.e. Roman) layout, or with right-to-left or vertical ones. Some aspects
|
|||
|
like rotation and transformation are explained too.
|
|||
|
<p>Comments and corrections are highly welcomed, and can be sent to the
|
|||
|
<a href="devel@freetype.org">FreeType
|
|||
|
developers list</a>.</blockquote>
|
|||
|
|
|||
|
<hr WIDTH="100%">
|
|||
|
<h2>
|
|||
|
I. Basic typographic concepts</h2>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<h3>
|
|||
|
1. Font files, format and information</h3>
|
|||
|
|
|||
|
<blockquote>A font is a collection of various character images that can
|
|||
|
be used to display or print text. The images in a single font share some
|
|||
|
common properties, including look, style, serifs, etc.. Typographically
|
|||
|
speaking, one has to distinguish between a <b>font family</b> and its multiple
|
|||
|
<b>font
|
|||
|
faces</b>, which usually differ in style though come from the same template.
|
|||
|
For example, "<i>Palatino Regular</i>" and "<i>Palatino Italic</i>" are
|
|||
|
two distinct <i>faces</i> from the same famous <i>family</i>, called "<i>Palatino</i>"
|
|||
|
itself.
|
|||
|
<p>The single term font is nearly always used in ambiguous ways to refer
|
|||
|
to either a given family or given face, depending on the context. For example,
|
|||
|
most users of word-processors use "font" to describe a font family (e.g.
|
|||
|
Courier, Palatino, etc..); however most of these families are implemented
|
|||
|
through several data files depending on the file format : for TrueType,
|
|||
|
this is usually one per face (i.e. ARIAL.TFF for "Arial Regular", ARIALI.TTF
|
|||
|
for "Arial Italic", etc..). The file is also called a "font" but really
|
|||
|
contains a font face.
|
|||
|
<p>A <i>digital font</i> is thus a data file that may contain <i>one or
|
|||
|
more font faces</i>. For each of these, it contains character images, character
|
|||
|
metrics, as well as other kind of information important to the layout of
|
|||
|
text and the processing of specific character encodings. In some awkward
|
|||
|
formats, like Adobe Type1, a single font face is described through several
|
|||
|
files (i.e. one contains the character images, another one the character
|
|||
|
metrics). We will ignore this implementation issue in most of this document
|
|||
|
and consider digital fonts as single files, though FreeType 2.0 is able
|
|||
|
to support multiple-files fonts correctly.
|
|||
|
<p>As a convenience, a font file containing more than one face is called
|
|||
|
a font collection. This case is rather rare but can be seen in many asian
|
|||
|
fonts, which contain images for two or more scripts for a given language.</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
2. Character images and mappings :</h3>
|
|||
|
|
|||
|
<blockquote>The character images are called <b>glyphs</b>. A single character
|
|||
|
can have several distinct images, i.e. several glyphs, depending on script,
|
|||
|
usage or context. Several characters can also take a single glyph (good
|
|||
|
examples are roman ligatures like "oe" and "fi" which can be represented
|
|||
|
by a single glyph like "<22>" and "?"). The relationships between characters
|
|||
|
and glyphs can be a very complex one but won't be detailed in this document.
|
|||
|
Moreover, some formats use more or less awkward schemes to store and access
|
|||
|
the glyphs. For the sake of clarity, we'll only retain the following notions
|
|||
|
when working with FreeType :
|
|||
|
<br>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
A font file contains a set of glyphs, each one can be stored as a bitmap,
|
|||
|
a vector representation or any other scheme (e.g. most scalable formats
|
|||
|
use a combination of math representation and control data/programs). These
|
|||
|
glyphs can be stored in any order in the font file, and is typically accessed
|
|||
|
through a simple glyph index.</li>
|
|||
|
</ul>
|
|||
|
</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<ul>
|
|||
|
<ul>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The font file contains one (or more) table, called a character map (or
|
|||
|
charmap in short), which is used to convert character codes for a given
|
|||
|
encoding (e.g. ASCII, Unicode, DBCS, Big5, etc..) into glyph indexes relative
|
|||
|
to the font file. A single font face may contain several charmaps. For
|
|||
|
example, most TrueType fonts contain an Apple-specific charmap as well
|
|||
|
as a Unicode charmap, which makes them usable on both Mac and Windows platforms.</li>
|
|||
|
</ul>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3>
|
|||
|
3. Character and font metrics :</h3>
|
|||
|
|
|||
|
<ul>Each glyph image is associated to various metrics which are used to
|
|||
|
describe the way it must be placed and managed when rendering text. Though
|
|||
|
they are described in more details in section III, they relate to glyph
|
|||
|
placement, cursor advances as well as text layouts. They are extremely
|
|||
|
important to compute the flow of text when rendering string of text.
|
|||
|
<p>Each scalable format also contains some global metrics, expressed in
|
|||
|
notional units, used to describe some properties of all glyphs in a same
|
|||
|
face. For example : the maximum glyph bounding box, the ascender, descender
|
|||
|
and text height for the font.
|
|||
|
<p>Though these metrics also exist for non-scalable formats, they only
|
|||
|
apply for a set of given character dimensions and resolutions, and they're
|
|||
|
usually expressed in pixels then.</ul>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><br>
|
|||
|
<hr WIDTH="100%">
|
|||
|
<h2>
|
|||
|
II. Glyph Outlines</h2>
|
|||
|
|
|||
|
<blockquote>This section describes the vectorial representation of glyph
|
|||
|
images, called outlines.
|
|||
|
<br>
|
|||
|
<h3>
|
|||
|
1. Pixels, Points and Device Resolutions :</h3>
|
|||
|
|
|||
|
<blockquote>Though it is a very common assumption when dealing with computer
|
|||
|
graphics programs, the physical dimensions of a given pixel (be it for
|
|||
|
screens or printers) are not squared. Often, the output device, be it a
|
|||
|
screen or printer exhibits varying resolutions in the horizontal and vertical
|
|||
|
directions, and this must be taken care of when rendering text.
|
|||
|
<p>It is thus common to define a device's characteristics through two numbers
|
|||
|
expressed in <b>dpi</b> (dots per inch). For example, a printer with a
|
|||
|
resolution of 300x600 dpi has 300 pixels per inch in the horizontal direction,
|
|||
|
and 600 in the vertical one. The resolution of a typical computer monitor
|
|||
|
varies with its size (a 15" and 17" monitors don't have the same pixel
|
|||
|
sizes at 640x480), and of course the graphics mode resolution.
|
|||
|
<p>As a consequence, the size of text is usually given in <b>points</b>,
|
|||
|
rather than device-specific pixels. Points are a simple <i>physical</i>
|
|||
|
unit, where 1 point = 1/72th of an inch, in digital typography. As an example,
|
|||
|
most roman books are printed with a body text which size is chosen between
|
|||
|
10 and 14 points.
|
|||
|
<p>It is thus possible to compute the size of text in pixels from the size
|
|||
|
in points through the following computation :
|
|||
|
<center>
|
|||
|
<p><tt>pixel_size = point_size * resolution / 72</tt></center>
|
|||
|
|
|||
|
<p>Where resolution is expressed in dpi. Note that because the horizontal
|
|||
|
and vertical resolutions may differ, a single point size usually defines
|
|||
|
different text width and height in pixels.
|
|||
|
<br>
|
|||
|
<p><b>IMPORTANT NOTE:</b>
|
|||
|
<br><i>Unlike what is often thought, the "size of text in pixels" is not
|
|||
|
directly related to the real dimensions of characters when they're displayed
|
|||
|
or printed. The relationship between these two concepts is a bit more complex
|
|||
|
and relate to some design choice made by the font designer. This is described
|
|||
|
in more details the next sub-section (see the explanations on the EM square).</i></blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
2. Vectorial representation :</h3>
|
|||
|
|
|||
|
<blockquote>The source format of outlines is a collection of closed paths
|
|||
|
called <b>contours</b>. Each contour delimits an outer or inner <i>region</i>
|
|||
|
of the glyph, and can be made of either <b>line segments</b> or <b>bezier
|
|||
|
arcs</b>.
|
|||
|
<p>The arcs are defined through <b>control points</b>, and can be either
|
|||
|
second-order (these are "conic beziers") or third-order ("cubic" beziers)
|
|||
|
polynomials, depending on the font format. Hence, each point of the outline
|
|||
|
has an associated <b>flag</b> indicating its type (normal or control point).
|
|||
|
And scaling the points will scale the whole outline.
|
|||
|
<p>Each glyph's original outline points are located on a grid of indivisible
|
|||
|
units. The points are usually stored in a font file as 16-bit integer grid
|
|||
|
coordinates, with the grid origin's being at (0,0); they thus range from
|
|||
|
-16384 to 16383. (even though point coordinates can be floats in other
|
|||
|
formats such as Type 1, we'll restrict our analysis to integer ones, driven
|
|||
|
by the need for simplicity..).
|
|||
|
<p><b>IMPORTANT NOTE:</b>
|
|||
|
<br><i>The grid is always oriented like the traditional mathematical 2D
|
|||
|
plane, i.e. the X axis from the left to the right, and the Y axis from
|
|||
|
bottom to top.</i>
|
|||
|
<p>In creating the glyph outlines, a type designer uses an imaginary square
|
|||
|
called the "EM square". Typically, the EM square can be thought of as a
|
|||
|
tablet on which the character are drawn. The square's size, i.e., the number
|
|||
|
of grid units on its sides, is very important for two reasons:
|
|||
|
<br>
|
|||
|
<blockquote>
|
|||
|
<li>
|
|||
|
it is the reference used to scale the outlines to a given text dimension.
|
|||
|
For example, a size of 12pt at 300x300 dpi corresponds to 12*300/72 = 50
|
|||
|
pixels. This is the size the EM square would appear on the output device
|
|||
|
if it was rendered directly. In other words, scaling from grid units to
|
|||
|
pixels uses the formula:</li>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<center><tt>pixel_size = point_size * resolution / 72</tt>
|
|||
|
<br><tt>pixel_coordinate = grid_coordinate * pixel_size / EM_size</tt></center>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<li>
|
|||
|
the greater the EM size is, the larger resolution the designer can use
|
|||
|
when digitizing outlines. For example, in the extreme example of an EM
|
|||
|
size of 4 units, there are only 25 point positions available within the
|
|||
|
EM square which is clearly not enough. Typical TrueType fonts use an EM
|
|||
|
size of 2048 units (note: with Type 1 PostScript fonts, the EM size is
|
|||
|
fixed to 1000 grid units. However, point coordinates can be expressed in
|
|||
|
floating values).</li>
|
|||
|
</blockquote>
|
|||
|
Note that glyphs can freely extend beyond the EM square if the font designer
|
|||
|
wants so. The EM is used as a convenience, and is a valuable convenience
|
|||
|
from traditional typography.
|
|||
|
<center>
|
|||
|
<p><b>Note : Grid units are very often called "font units" or "EM units".</b></center>
|
|||
|
|
|||
|
<p><b>NOTE:</b>
|
|||
|
<br><i>As said before, the pixel_size computed in the above formula
|
|||
|
does not relate directly to the size of characters on the screen. It simply
|
|||
|
is the size of the EM square if it was to be displayed directly. Each font
|
|||
|
designer is free to place its glyphs as it pleases him within the square.
|
|||
|
This explains why the letters of the following text have not the same height,
|
|||
|
even though they're displayed at the same point size with distinct fonts
|
|||
|
:</i>
|
|||
|
<center>
|
|||
|
<p><img SRC="body_comparison.png" height=40 width=580></center>
|
|||
|
|
|||
|
<p>As one can see, the glyphs of the Courier family are smaller than those
|
|||
|
of Times New Roman, which themselves are slightly smaller than those of
|
|||
|
Arial, even though everything is displayed or printed at a size of
|
|||
|
16 points. This only reflect design choices.
|
|||
|
<br> </blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
3. Hinting and Bitmap rendering</h3>
|
|||
|
|
|||
|
<blockquote>The outline as stored in a font file is called the "master"
|
|||
|
outline, as its points coordinates are expressed in font units. Before
|
|||
|
it can be converted into a bitmap, it must be scaled to a given size/resolution.
|
|||
|
This is done through a very simple transform, but always creates undesirable
|
|||
|
artifacts, e.g. stems of different widths or heights in letters like "E"
|
|||
|
or "H".
|
|||
|
<p>As a consequence, proper glyph rendering needs the scaled points to
|
|||
|
be aligned along the target device pixel grid, through an operation called
|
|||
|
"grid-fitting", and often "hinting". One of its main purpose is to ensure
|
|||
|
that important widths and heights are respected throughout the whole font
|
|||
|
(for example, it is very often desirable that the "I" and the "T" have
|
|||
|
their central vertical line of the same pixel width), as well as manage
|
|||
|
features like stems and overshoots, which can cause problems at small pixel
|
|||
|
sizes.
|
|||
|
<p>There are several ways to perform grid-fitting properly, for example
|
|||
|
most scalable formats associate some control data or programs with each
|
|||
|
glyph outline. Here is an overview :
|
|||
|
<br>
|
|||
|
<blockquote>
|
|||
|
<blockquote><b>explicit grid-fitting :</b>
|
|||
|
<blockquote>The TrueType format defines a stack-based virtual machine,
|
|||
|
for which programs can be written with the help of more than 200 opcodes
|
|||
|
(most of these relating to geometrical operations). Each glyph is thus
|
|||
|
made of both an outline and a control program, its purpose being to perform
|
|||
|
the actual grid-fitting in the way defined by the font designer.</blockquote>
|
|||
|
|
|||
|
<p><br><b>implicit grid-fitting (also called hinting) :</b>
|
|||
|
<blockquote>The Type 1 format takes a much simpler approach : each glyph
|
|||
|
is made of an outline as well as several pieces called "hints" which are
|
|||
|
used to describe some important features of the glyph, like the presence
|
|||
|
of stems, some width regularities, and the like. There aren't a lot of
|
|||
|
hint types, and it's up to the final renderer to interpret the hints in
|
|||
|
order to produce a fitted outline.</blockquote>
|
|||
|
|
|||
|
<p><br><b>automatic grid-fitting :</b>
|
|||
|
<blockquote>Some formats simply include no control information with each
|
|||
|
glyph outline, apart metrics like the advance width and height. It's then
|
|||
|
up to the renderer to "guess" the more interesting features of the outline
|
|||
|
in order to perform some decent grid-fitting.</blockquote>
|
|||
|
</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<center>
|
|||
|
<p><br>The following table summarises the pros and cons of each scheme
|
|||
|
:</center>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<center><table BORDER=0 WIDTH="80%" BGCOLOR="#CCCCCC" >
|
|||
|
<tr BGCOLOR="#999999">
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Grid-fitting scheme</font></b></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Pros</font></b></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Cons</font></b></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Explicit</font></b></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Quality</font></b>
|
|||
|
<br><font color="#000000">excellence at small sizes is possible. This is
|
|||
|
very important for screen display.</font>
|
|||
|
<p><b><font color="#000000">Consistency</font></b>
|
|||
|
<br><font color="#000000">all renderers produce the same glyph bitmaps.</font></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Speed</font></b>
|
|||
|
<br><font color="#000000">intepreting bytecode can be slow if the glyph
|
|||
|
programs are complex.</font>
|
|||
|
<p><b><font color="#000000">Size</font></b>
|
|||
|
<br><font color="#000000">glyph programs can be long</font>
|
|||
|
<p><b><font color="#000000">Technicity</font></b>
|
|||
|
<br><font color="#000000">it is extremely difficult to write good hinting
|
|||
|
programs. Very few tools available.</font></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Implicit</font></b></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Size</font></b>
|
|||
|
<br><font color="#000000">hints are usually much smaller than explicit
|
|||
|
glyph programs.</font>
|
|||
|
<p><b><font color="#000000">Speed</font></b>
|
|||
|
<br><font color="#000000">grid-fitting is usually a fast process</font></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Quality</font></b>
|
|||
|
<br><font color="#000000">often questionable at small sizes. Better with
|
|||
|
anti-aliasing though.</font>
|
|||
|
<p><b><font color="#000000">Inconsistency</font></b>
|
|||
|
<br><font color="#000000">results can vary between different renderers,
|
|||
|
or even distinct versions of the same engine.</font></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Automatic</font></b></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Size</font></b>
|
|||
|
<br><font color="#000000">no need for control information, resulting in
|
|||
|
smaller font files.</font>
|
|||
|
<p><b><font color="#000000">Speed</font></b>
|
|||
|
<br><font color="#000000">depends on the grid-fitting algo.Usually faster
|
|||
|
than explicit grid-fitting.</font></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote>
|
|||
|
<center><b><font color="#000000">Quality</font></b>
|
|||
|
<br><font color="#000000">often questionable at small sizes. Better with
|
|||
|
anti-aliasing though</font>
|
|||
|
<p><b><font color="#000000">Speed</font></b>
|
|||
|
<br><font color="#000000">depends on the grid-fitting algo.</font>
|
|||
|
<p><b><font color="#000000">Inconsistency</font></b>
|
|||
|
<br><font color="#000000">results can vary between different renderers,
|
|||
|
or even distinct versions of the same engine.</font></center>
|
|||
|
</blockquote>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
</table></center>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<hr WIDTH="100%">
|
|||
|
<h2>
|
|||
|
III. Glyph metrics</h2>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<h3>
|
|||
|
1. Baseline, Pens and Layouts</h3>
|
|||
|
The baseline is an imaginary line that is used to "guide" glyphs when rendering
|
|||
|
text. It can be horizontal (e.g. Roman, Cyrillic, Arabic, etc.) or vertical
|
|||
|
(e.g. Chinese, Japanese, Korean, etc). Moreover, to render text, a virtual
|
|||
|
point, located on the baseline, called the "pen position" or "origin",
|
|||
|
is used to locate glyphs.
|
|||
|
<p>Each layout uses a different convention for glyph placement:
|
|||
|
<br>
|
|||
|
<blockquote>
|
|||
|
<li>
|
|||
|
with horizontal layout, glyphs simply "rest" on the baseline. Text is rendered
|
|||
|
by incrementing the pen position, either to the right or to the left.</li>
|
|||
|
</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<ul>
|
|||
|
<ul>the distance between two successive pen positions is glyph-specific
|
|||
|
and is called the "advance width". Note that its value is _always_ positive,
|
|||
|
even for right-to-left oriented alphabets, like Arabic. This introduces
|
|||
|
some differences in the way text is rendered.
|
|||
|
<p>IMPORTANT NOTE: The pen position is always placed on the baseline.</ul>
|
|||
|
|
|||
|
<center><img SRC="Image1.png" height=179 width=458></center>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
with a vertical layout, glyphs are centered around the baseline:</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<center><img SRC="Image2.png" height=275 width=162></center>
|
|||
|
|
|||
|
<p><br>
|
|||
|
<h3>
|
|||
|
2. Typographic metrics and bounding boxes</h3>
|
|||
|
|
|||
|
<ul>A various number of face metrics are defined for all glyphs in a given
|
|||
|
font.
|
|||
|
<p><b>the ascent</b>
|
|||
|
<ul>this is the distance from the baseline to the highest/upper grid coordinate
|
|||
|
used to place an outline point. It is a positive value, due to the grid's
|
|||
|
orientation with the Y axis upwards.</ul>
|
|||
|
|
|||
|
<p><br><b>the descent</b>
|
|||
|
<ul>the distance from the baseline to the lowest grid coordinate used to
|
|||
|
place an outline point. This is a negative value, due to the grid's orientation.</ul>
|
|||
|
|
|||
|
<p><br><b>the linegap</b>
|
|||
|
<ul>the distance that must be placed between two lines of text. The baseline-to-baseline
|
|||
|
distance should be computed as:
|
|||
|
<center>
|
|||
|
<p><tt>ascent - descent + linegap</tt></center>
|
|||
|
if you use the typographic values.</ul>
|
|||
|
Other, simpler metrics are:
|
|||
|
<p><b>the glyph's bounding box</b>, also called "<b>bbox</b>"
|
|||
|
<ul>this is an imaginary box that encloses all glyphs from the font, as
|
|||
|
tightly as possible. It is represented by four fields, namely <tt>xMin</tt>,
|
|||
|
<tt>yMin</tt>,
|
|||
|
<tt>xMax</tt>,
|
|||
|
and <tt>yMax</tt>, that can be computed for any outline. Their values can
|
|||
|
be in font units (if measured in the original outline) or in fractional/integer
|
|||
|
pixel units (when measured on scaled outlines).
|
|||
|
<p>Note that if it wasn't for grid-fitting, you wouldn't need to know a
|
|||
|
box's complete values, but only its dimensions to know how big is a glyph
|
|||
|
outline/bitmap. However, correct rendering of hinted glyphs needs the preservation
|
|||
|
of important grid alignment on each glyph translation/placement on the
|
|||
|
baseline.</ul>
|
|||
|
<b>the internal leading</b>
|
|||
|
<ul>this concept comes directly from the world of traditional typography.
|
|||
|
It represents the amount of space within the "leading" which is reserved
|
|||
|
for glyph features that lay outside of the EM square (like accentuation).
|
|||
|
It usually can be computed as:
|
|||
|
<center>
|
|||
|
<p><tt>internal leading = ascent - descent - EM_size</tt></center>
|
|||
|
</ul>
|
|||
|
<b>the external leading</b>
|
|||
|
<ul>this is another name for the line gap.</ul>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3>
|
|||
|
3. Bearings and Advances</h3>
|
|||
|
|
|||
|
<ul>Each glyph has also distances called "bearings" and "advances". Their
|
|||
|
definition is constant, but their values depend on the layout, as the same
|
|||
|
glyph can be used to render text either horizontally or vertically:
|
|||
|
<p><b>the left side bearing: a.k.a. bearingX</b>
|
|||
|
<ul>this is the horizontal distance from the current pen position to the
|
|||
|
glyph's left bbox edge. It is positive for horizontal layouts, and most
|
|||
|
generally negative for vertical one.</ul>
|
|||
|
|
|||
|
<p><br><b>the top side bearing: a.k.a. bearingY</b>
|
|||
|
<ul>this is the vertical distance from the baseline to the top of the glyph's
|
|||
|
bbox. It is usually positive for horizontal layouts, and negative for vertical
|
|||
|
ones</ul>
|
|||
|
|
|||
|
<p><br><b>the advance width: a.k.a. advanceX</b>
|
|||
|
<ul>is the horizontal distance the pen position must be incremented (for
|
|||
|
left-to-right writing) or decremented (for right-to-left writing) by after
|
|||
|
each glyph is rendered when processing text. It is always positive for
|
|||
|
horizontal layouts, and null for vertical ones.</ul>
|
|||
|
|
|||
|
<p><br><b>the advance height: a.k.a. advanceY</b>
|
|||
|
<ul>is the vertical distance the pen position must be decremented by after
|
|||
|
each glyph is rendered. It is always null for horizontal layouts, and positive
|
|||
|
for vertical layouts.</ul>
|
|||
|
|
|||
|
<p><br><b>the glyph width</b>
|
|||
|
<ul>this is simply the glyph's horizontal extent. More simply it is (bbox.xMax-bbox.xMin)
|
|||
|
for unscaled font coordinates. For scaled glyphs, its computation requests
|
|||
|
specific care, described in the grid-fitting chapter below.</ul>
|
|||
|
|
|||
|
<p><br><b>the glyph height</b>
|
|||
|
<ul>this is simply the glyph's vertical extent. More simply, it is (bbox.yMax-bbox.yMin)
|
|||
|
for unscaled font coordinates. For scaled glyphs, its computation requests
|
|||
|
specific care, described in the grid-fitting chapter below.</ul>
|
|||
|
|
|||
|
<p><br><b>the right side bearing</b>
|
|||
|
<ul>is only used for horizontal layouts to describe the distance from the
|
|||
|
bbox's right edge to the advance width. It is in most cases a non-negative
|
|||
|
number.</ul>
|
|||
|
|
|||
|
<center><tt>advance_width - left_side_bearing - (xMax-xMin)</tt></center>
|
|||
|
|
|||
|
<p>Here is a picture giving all the details for horizontal metrics :
|
|||
|
<center>
|
|||
|
<p><img SRC="Image3.png" height=253 width=388></center>
|
|||
|
|
|||
|
<p>And here is another one for the vertical metrics :
|
|||
|
<center>
|
|||
|
<p><img SRC="Image4.png" height=278 width=294></center>
|
|||
|
</ul>
|
|||
|
|
|||
|
<h3>
|
|||
|
4. The effects of grid-fitting</h3>
|
|||
|
|
|||
|
<ul>Because hinting aligns the glyph's control points to the pixel grid,
|
|||
|
this process slightly modifies the dimensions of character images in ways
|
|||
|
that differ from simple scaling.
|
|||
|
<p>For example, the image of the lowercase "m" letter sometimes fits a
|
|||
|
square in the master grid. However, to make it readable at small pixel
|
|||
|
sizes, hinting tends to enlarge its scaled outline in order to keep its
|
|||
|
three legs distinctly visible, resulting in a larger character bitmap.
|
|||
|
<p>The glyph metrics are also influenced by the grid-fitting process. Mainly
|
|||
|
because :
|
|||
|
<br>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The image's width and height are altered. Even if this is only by one pixel,
|
|||
|
it can make a big difference at small pixel sizes</li>
|
|||
|
|
|||
|
<li>
|
|||
|
The image's bounding box is modified, thus modifying the bearings</li>
|
|||
|
|
|||
|
<li>
|
|||
|
The advances must be updated. For example, the advance width must be incremented
|
|||
|
when the hinted bitmap is larger than the scaled one, to reflect the augmented
|
|||
|
glyph width.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><br>Note also that :
|
|||
|
<br>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Because of hinting, simply scaling the font ascent or descent might not
|
|||
|
give correct results. A simple solution consists in keeping the ceiling
|
|||
|
of the scaled ascent, and floor of the scaled descent.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
There is no easy way to get the hinted glyph and advance widths of a range
|
|||
|
of glyphs, as hinting works differently on each outline. The only solution
|
|||
|
is to hint each glyph separately and record the returned values. Some formats,
|
|||
|
like TrueType, even include a table of pre-computed values for a small
|
|||
|
set of common character pixel sizes.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Hinting depends on the final character width and height in pixels, which
|
|||
|
means that it is highly resolution-dependent. This property makes correct
|
|||
|
WYSIWYG layouts difficult to implement.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><br><b>IMPORTANT NOTE:</b>
|
|||
|
<br>Performing 2D transforms on glyph outlines is very easy with FreeType.
|
|||
|
However, when using translation on a hinted outlines, one should aways
|
|||
|
take care of <b>exclusively using integer pixel distances</b> (which
|
|||
|
means that the parameters to the FT_Translate_Outline API should all be
|
|||
|
multiples of 64, as the point coordinates are in 26.6 fixed float format).
|
|||
|
<p><b>Otherwise</b>, the translation will simply <b>ruin the hinter's work</b>,
|
|||
|
resulting in a very low quality bitmaps.
|
|||
|
<br>
|
|||
|
<br> </ul>
|
|||
|
|
|||
|
<h3>
|
|||
|
5. Text widths and bounding box :</h3>
|
|||
|
|
|||
|
<ul>As seen before, the "origin" of a given glyph corresponds to the position
|
|||
|
of the pen on the baseline. It is not necessarily located on one of the
|
|||
|
glyph's bounding box corners, unlike many typical bitmapped font formats.
|
|||
|
In some cases, the origin can be out of the bounding box, in others, it
|
|||
|
can be within it, depending on the shape of the given glyph.
|
|||
|
<p>Likewise, the glyph's "advance width" is the increment to apply to the
|
|||
|
pen position during layout, and is not related to the glyph's "width",
|
|||
|
which really is the glyph's bounding width.
|
|||
|
<br>
|
|||
|
<p>The same conventions apply to strings of text. This means that :
|
|||
|
<br>
|
|||
|
<ul>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The bounding box of a given string of text doesn't necessarily contain
|
|||
|
the text cursor, nor is the latter located on one of its corners.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The string's advance width isn't related to its bounding box's dimensions.
|
|||
|
Especially if it contains beginning and terminal spaces or tabs.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Finally, additional processing like kerning creates strings of text whose
|
|||
|
dimensions are not directly related to the simple juxtaposition of individual
|
|||
|
glyph metrics. For example, the advance width of "VA" isn't the sum of
|
|||
|
the advances of "V" and "A" taken separately.</li>
|
|||
|
</ul>
|
|||
|
</ul>
|
|||
|
</ul>
|
|||
|
</ul>
|
|||
|
|
|||
|
<hr WIDTH="100%">
|
|||
|
<h2>
|
|||
|
IV. Kerning</h2>
|
|||
|
|
|||
|
<blockquote>The term 'kerning' refers to specific information used to adjust
|
|||
|
the relative positions of coincident glyphs in a string of text. This section
|
|||
|
describes several types of kerning information, as well as the way to process
|
|||
|
them when performing text layout.
|
|||
|
<br>
|
|||
|
<h3>
|
|||
|
1. Kerning pairs</h3>
|
|||
|
|
|||
|
<blockquote>Kerning consists in modifying the spacing between two successive
|
|||
|
glyphs according to their outlines. For example, a "T" and a "y" can be
|
|||
|
easily moved closer, as the top of the "y" fits nicely under the "T"'s
|
|||
|
upper right bar.
|
|||
|
<p>When laying out text with only their standard widths, some consecutive
|
|||
|
glyphs sometimes seem a bit too close or too distant. For example, the
|
|||
|
space between the 'A' and the 'V' in the following word seems a little
|
|||
|
wider than needed.
|
|||
|
<center>
|
|||
|
<p><img SRC="bravo_unkerned.png" height=37 width=116></center>
|
|||
|
|
|||
|
<p>Compare this to the same word, when the distance between these two letters
|
|||
|
has been slightly reduced :
|
|||
|
<center>
|
|||
|
<p><img SRC="bravo_kerned.png" height=37 width=107></center>
|
|||
|
|
|||
|
<p>As you can see, this adjustment can make a great difference. Some font
|
|||
|
faces thus include a table containing kerning distances for a set of given
|
|||
|
glyph pairs, used during text layout. Note that :
|
|||
|
<br>
|
|||
|
<blockquote>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The pairs are ordered, i.e. the space for pair (A,V) isn't necessarily
|
|||
|
the space for pair (V,A). They also index glyphs, and not characters.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Kerning distances can be expressed in horizontal or vertical directions,
|
|||
|
depending on layout and/or script. For example, some horizontal layouts
|
|||
|
like arabic can make use of vertical kerning adjustments between successive
|
|||
|
glyphs. A vertical script can have vertical kerning distances.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Kerning distances are expressed in grid units. They are usually oriented
|
|||
|
in the X axis, which means that a negative value indicates that two glyphs
|
|||
|
must be set closer in a horizontal layout.</li>
|
|||
|
</ul>
|
|||
|
</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
2. Applying kerning</h3>
|
|||
|
|
|||
|
<blockquote>Applying kerning when rendering text is a rather easy process.
|
|||
|
It merely consists in adding the scaled kern distance to the pen position
|
|||
|
before writing each next glyph. However, the typographically correct renderer
|
|||
|
must take a few more details in consideration.
|
|||
|
<p>The "sliding dot" problem is a good example : many font faces include
|
|||
|
a kerning distance between capital letters like "T" or "F" and a following
|
|||
|
dot ("."), in order to slide the latter glyph just right to their main
|
|||
|
leg. I.e.
|
|||
|
<center>
|
|||
|
<p><img SRC="twlewis1.png" height=38 width=314></center>
|
|||
|
|
|||
|
<p>However, this sometimes requires additional adjustments between the
|
|||
|
dot and the letter following it, depending on the shapes of the enclosing
|
|||
|
letters. When applying "standard" kerning adjustments, the previous sentence
|
|||
|
would become :
|
|||
|
<center>
|
|||
|
<p><img SRC="twlewis2.png" height=36 width=115></center>
|
|||
|
|
|||
|
<p>Which clearly is too contracted. The solution here, as exhibited in
|
|||
|
the first example is to only slide the dots when possible. Of course, this
|
|||
|
requires a certain knowledge of the text's meaning. The above adjustments
|
|||
|
would not necessarily be welcomed if we were rendering the final dot of
|
|||
|
a given paragraph.
|
|||
|
<p>This is only one example, and there are many others showing that a real
|
|||
|
typographer is needed to layout text properly. If not available, some kind
|
|||
|
of user interaction or tagging of the text could be used to specify some
|
|||
|
adjustments, but in all cases, this requires some support in applications
|
|||
|
and text libraries.
|
|||
|
<p>For more mundane and common uses, however, we can have a very simple
|
|||
|
algorithm, which avoids the sliding dot problem, and others, though
|
|||
|
not producing optimal results. It can be seen as :
|
|||
|
<br>
|
|||
|
<blockquote>
|
|||
|
<ol>
|
|||
|
<li>
|
|||
|
place the first glyph on the baseline</li>
|
|||
|
|
|||
|
<li>
|
|||
|
save the location of the pen position/origin in pen1</li>
|
|||
|
|
|||
|
<li>
|
|||
|
adjust the pen position with the kerning distance between the first and
|
|||
|
second glyph</li>
|
|||
|
|
|||
|
<li>
|
|||
|
place the second glyph and compute the next pen position/origin in pen2.</li>
|
|||
|
|
|||
|
<li>
|
|||
|
use pen1 as the next pen position if it is beyond pen2, use pen2 otherwise.</li>
|
|||
|
</ol>
|
|||
|
</blockquote>
|
|||
|
</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h2>
|
|||
|
|
|||
|
<hr WIDTH="100%"></h2>
|
|||
|
|
|||
|
<h2>
|
|||
|
V. Text processing</h2>
|
|||
|
|
|||
|
<blockquote>This section demonstrates how to use the concepts previously
|
|||
|
defined to render text, whatever the layout you use.
|
|||
|
<br>
|
|||
|
<h3>
|
|||
|
1. Writing simple text strings :</h3>
|
|||
|
|
|||
|
<blockquote>In this first example, we'll generate a simple string of Roman
|
|||
|
text, i.e. with a horizontal left-to-right layout. Using exclusively pixel
|
|||
|
metrics, the process looks like :
|
|||
|
<blockquote><tt>1) convert the character string into a series of glyph
|
|||
|
indexes.</tt>
|
|||
|
<br><tt>2) place the pen to the cursor position.</tt>
|
|||
|
<br><tt>3) get or load the glyph image.</tt>
|
|||
|
<br><tt>4) translate the glyph so that its 'origin' matches the pen position</tt>
|
|||
|
<br><tt>5) render the glyph to the target device</tt>
|
|||
|
<br><tt>6) increment the pen position by the glyph's advance width in pixels</tt>
|
|||
|
<br><tt>7) start over at step 3 for each of the remaining glyphs</tt>
|
|||
|
<br><tt>8) when all glyphs are done, set the text cursor to the new pen
|
|||
|
position</tt></blockquote>
|
|||
|
Note that kerning isn't part of this algorithm.</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
2. Sub-pixel positioning :</h3>
|
|||
|
|
|||
|
<blockquote>It is somewhat useful to use sub-pixel positioning when rendering
|
|||
|
text. This is crucial, for example, to provide semi-WYSIWYG text layouts.
|
|||
|
Text rendering is very similar to the algorithm described in sub-section
|
|||
|
1, with the following few differences :
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The pen position is expressed in fractional pixels.</li>
|
|||
|
|
|||
|
<li>
|
|||
|
Because translating a hinted outline by a non-integer distance will ruin
|
|||
|
its grid-fitting, the position of the glyph origin must be rounded before
|
|||
|
rendering the character image.</li>
|
|||
|
|
|||
|
<li>
|
|||
|
The advance width is expressed in fractional pixels, and isn't necessarily
|
|||
|
an integer.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><br>Which finally looks like :
|
|||
|
<blockquote><tt>1. convert the character string into a series of glyph
|
|||
|
indexes.</tt>
|
|||
|
<br><tt>2. place the pen to the cursor position. This can be a non-integer
|
|||
|
point.</tt>
|
|||
|
<br><tt>3. get or load the glyph image.</tt>
|
|||
|
<br><tt>4. translate the glyph so that its 'origin' matches the rounded
|
|||
|
pen position.</tt>
|
|||
|
<br><tt>5. render the glyph to the target device</tt>
|
|||
|
<br><tt>6. increment the pen position by the glyph's advance width in fractional
|
|||
|
pixels.</tt>
|
|||
|
<br><tt>7. start over at step 3 for each of the remaining glyphs</tt>
|
|||
|
<br><tt>8. when all glyphs are done, set the text cursor to the new pen
|
|||
|
position</tt></blockquote>
|
|||
|
Note that with fractional pixel positioning, the space between two given
|
|||
|
letters isn't fixed, but determined by the accumulation of previous rounding
|
|||
|
errors in glyph positioning.</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
3. Simple kerning :</h3>
|
|||
|
|
|||
|
<blockquote>Adding kerning to the basic text rendering algorithm is easy
|
|||
|
: when a kerning pair is found, simply add the scaled kerning distance
|
|||
|
to the pen position before step 4. Of course, the distance should be rounded
|
|||
|
in the case of algorithm 1, though it doesn't need to for algorithm 2.
|
|||
|
This gives us :
|
|||
|
<p>Algorithm 1 with kerning:
|
|||
|
<blockquote><tt>3) get or load the glyph image.</tt>
|
|||
|
<br><tt>4) Add the rounded scaled kerning distance, if any, to the pen
|
|||
|
position</tt>
|
|||
|
<br><tt>5) translate the glyph so that its 'origin' matches the pen position</tt>
|
|||
|
<br><tt>6) render the glyph to the target device</tt>
|
|||
|
<br><tt>7) increment the pen position by the glyph's advance width in pixels</tt>
|
|||
|
<br><tt>8) start over at step 3 for each of the remaining glyphs</tt></blockquote>
|
|||
|
|
|||
|
<p><br>Algorithm 2 with kerning:
|
|||
|
<blockquote><tt>3) get or load the glyph image.</tt>
|
|||
|
<br><tt>4) Add the scaled unrounded kerning distance, if any, to the pen
|
|||
|
position.</tt>
|
|||
|
<br><tt>5) translate the glyph so that its 'origin' matches the rounded
|
|||
|
pen position.</tt>
|
|||
|
<br><tt>6) render the glyph to the target device</tt>
|
|||
|
<br><tt>7) increment the pen position by the glyph's advance width in fractional
|
|||
|
pixels.</tt>
|
|||
|
<br><tt>8) start over at step 3 for each of the remaining glyphs</tt></blockquote>
|
|||
|
Of course, the algorithm described in section IV can also be applied to
|
|||
|
prevent the sliding dot problem if one wants to..</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
4. Right-To-Left Layout :</h3>
|
|||
|
|
|||
|
<blockquote>The process of laying out arabic or hebrew text is extremely
|
|||
|
similar. The only difference is that the pen position must be decremented
|
|||
|
before the glyph rendering (remember : the advance width is always positive,
|
|||
|
even for arabic glyphs). Thus, algorithm 1 becomes :
|
|||
|
<p>Right-to-left Algorithm 1:
|
|||
|
<blockquote><tt>3) get or load the glyph image.</tt>
|
|||
|
<br><tt>4) Decrement the pen position by the glyph's advance width in pixels</tt>
|
|||
|
<br><tt>5) translate the glyph so that its 'origin' matches the pen position</tt>
|
|||
|
<br><tt>6) render the glyph to the target device</tt>
|
|||
|
<br><tt>7) start over at step 3 for each of the remaining glyphs</tt></blockquote>
|
|||
|
|
|||
|
<p><br>The changes to Algorithm 2, as well as the inclusion of kerning
|
|||
|
are left as an exercise to the reader.
|
|||
|
<br>
|
|||
|
<br> </blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
5. Vertical layouts :</h3>
|
|||
|
|
|||
|
<blockquote>Laying out vertical text uses exactly the same processes, with
|
|||
|
the following significant differences :
|
|||
|
<br>
|
|||
|
<blockquote>
|
|||
|
<li>
|
|||
|
The baseline is vertical, and the vertical metrics must be used instead
|
|||
|
of the horizontal one.</li>
|
|||
|
|
|||
|
<li>
|
|||
|
The left bearing is usually negative, but this doesn't change the fact
|
|||
|
that the glyph origin must be located on the baseline.</li>
|
|||
|
|
|||
|
<li>
|
|||
|
The advance height is always positive, so the pen position must be decremented
|
|||
|
if one wants to write top to bottom (assuming the Y axis is oriented upwards).</li>
|
|||
|
</blockquote>
|
|||
|
Through the following algorithm :
|
|||
|
<blockquote><tt>1) convert the character string into a series of glyph
|
|||
|
indexes.</tt>
|
|||
|
<br><tt>2) place the pen to the cursor position.</tt>
|
|||
|
<br><tt>3) get or load the glyph image.</tt>
|
|||
|
<br><tt>4) translate the glyph so that its 'origin' matches the pen position</tt>
|
|||
|
<br><tt>5) render the glyph to the target device</tt>
|
|||
|
<br><tt>6) decrement the vertical pen position by the glyph's advance height
|
|||
|
in pixels</tt>
|
|||
|
<br><tt>7) start over at step 3 for each of the remaining glyphs</tt>
|
|||
|
<br><tt>8) when all glyphs are done, set the text cursor to the new pen
|
|||
|
position</tt></blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
6. WYSIWYG text layouts :</h3>
|
|||
|
|
|||
|
<blockquote>As you probably know, the acronym WYSIWYG stands for '<i>What
|
|||
|
You See Is What You Get</i>'. Basically, this means that the output of
|
|||
|
a document on the screen should match "perfectly" its printed version.
|
|||
|
A <b><i>true</i></b> wysiwyg system requires two things :
|
|||
|
<p><b>device-independent text layout</b>
|
|||
|
<blockquote>Which means that the document's formatting is the same on the
|
|||
|
screen than on any printed output, including line breaks, justification,
|
|||
|
ligatures, fonts, position of inline images, etc..</blockquote>
|
|||
|
|
|||
|
<p><br><b>matching display and print character sizes</b>
|
|||
|
<blockquote>Which means that the displayed size of a given character should
|
|||
|
match its dimensions when printed. For example, a text string which is
|
|||
|
exactly 1 inch tall when printed should also appear 1 inch tall on the
|
|||
|
screen (when using a scale of 100%).</blockquote>
|
|||
|
|
|||
|
<p><br>It is clear that matching sizes cannot be possible if the computer
|
|||
|
has no knowledge of the physical resolutions of the display device(s) it
|
|||
|
is using. And of course, this is the most common case ! That's not too
|
|||
|
unfortunate, however because most users really don't care about this
|
|||
|
feature. Legibility is much more important.
|
|||
|
<p>When the Mac appeared, Apple decided to choose a resolution of 72 dpi
|
|||
|
to describe the Macintosh screen to the font sub-system (whatever the monitor
|
|||
|
used). This choice was most probably driven by the fact that, at this resolution,
|
|||
|
1 point = 1 pixel. However; it neglected one crucial fact : as most users
|
|||
|
tend to choose a document character size between 10 and 14 points, the
|
|||
|
resultant displayed text was rather small and not too legible without scaling.
|
|||
|
Microsoft engineers took notice of this problem and chose a resolution
|
|||
|
of 96 dpi on Windows, which resulted in slightly larger, and more legible,
|
|||
|
displayed characters (for the same printed text size).
|
|||
|
<p>These distinct resolutions explain some differences when displaying
|
|||
|
text at the same character size on a Mac and a Windows machine. Moreover,
|
|||
|
it is not unusual to find some TrueType fonts with enhanced hinting (tech
|
|||
|
note: through delta-hinting) for the sizes of 10, 12, 14 and 16 points
|
|||
|
at 96 dpi.
|
|||
|
<br>
|
|||
|
<p>As for device-independent text, it is a notion that is, unfortunately,
|
|||
|
often abused. For example, many word processors, including MS Word, do
|
|||
|
not really use device-independent glyph positioning algorithms when laying
|
|||
|
out text. Rather, they use the target printer's resolution to compute <i>hinted</i>
|
|||
|
glyph metrics for the layout. Though it guarantees that the printed version
|
|||
|
is always the "nicest" it can be, especially for very low resolution printers
|
|||
|
(like dot-matrix), it has a very sad effect : changing the printer can
|
|||
|
have dramatic effects on the <i>whole</i> document layout, especially if
|
|||
|
it makes strong use of justification, uses few page breaks, etc..
|
|||
|
<p>Because the glyph metrics vary slightly when the resolution changes
|
|||
|
(due to hinting), line breaks can change enormously, when these differences
|
|||
|
accumulate over long runs of text. Try for example printing a very long
|
|||
|
document (with no page breaks) on a 300 dpi ink-jet printer, then the same
|
|||
|
one on a 3000 dpi laser printer : you'll be extremely lucky if your final
|
|||
|
page count didn't change between the prints ! Of course, we can still call
|
|||
|
this WYSIWYG, as long as the printer resolution is fixed !!
|
|||
|
<p>Some applications, like Adobe Acrobat, which targeted device-independent
|
|||
|
placement from the start, do not suffer from this problem. There are two
|
|||
|
ways to achieve this : either use the scaled and unhinted glyph metrics
|
|||
|
when laying out text both in the rendering and printing processes, or simply
|
|||
|
use wathever metrics you want and store them with the text in order to
|
|||
|
get sure they're printed the same on all devices (the latter being probably
|
|||
|
the best solution, as it also enables font substitution without breaking
|
|||
|
text layouts).
|
|||
|
<p>Just like matching sizes, device-independent placement isn't necessarily
|
|||
|
a feature that most users want. However, it is pretty clear that for any
|
|||
|
kind of professional document processing work, it <b><i>is</i></b> a requirement.</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h2>
|
|||
|
|
|||
|
<hr WIDTH="100%"></h2>
|
|||
|
|
|||
|
<h2>
|
|||
|
VI. FreeType outlines :</h2>
|
|||
|
|
|||
|
<blockquote>The purpose of this section is to present the way FreeType
|
|||
|
manages vectorial outlines, as well as the most common operations that
|
|||
|
can be applied on them.
|
|||
|
<br>
|
|||
|
<h3>
|
|||
|
1. FreeType outline description and structure :</h3>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<h4>
|
|||
|
a. Outline curve decomposition :</h4>
|
|||
|
|
|||
|
<blockquote>An outline is described as a series of closed contours in the
|
|||
|
2D plane. Each contour is made of a series of line segments and bezier
|
|||
|
arcs. Depending on the file format, these can be second-order or third-order
|
|||
|
polynomials. The former are also called quadratic or conic arcs, and they
|
|||
|
come from the TrueType format. The latter are called cubic arcs and mostly
|
|||
|
come from the Type1 format.
|
|||
|
<p>Each arc is described through a series of start, end and control points.
|
|||
|
Each point of the outline has a specific tag which indicates wether it
|
|||
|
is used to describe a line segment or an arc. The tags can take the following
|
|||
|
values :
|
|||
|
<br>
|
|||
|
<br> </blockquote>
|
|||
|
|
|||
|
<center><table CELLSPACING=5 CELLPADDING=5 WIDTH="60%" >
|
|||
|
<tr VALIGN=TOP>
|
|||
|
<td>
|
|||
|
<blockquote><b>FT_Curve_Tag_On </b></blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td VALIGN=TOP>
|
|||
|
<blockquote>Used when the point is "on" the curve. This corresponds to
|
|||
|
start and end points of segments and arcs. The other tags specify what
|
|||
|
is called an "off" point, i.e. one which isn't located on the contour itself,
|
|||
|
but serves as a control point for a bezier arc.</blockquote>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
<blockquote><b>FT_Curve_Tag_Conic</b></blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote>Used for an "off" point used to control a conic bezier arc.</blockquote>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
<blockquote><b>FT_Curve_Tag_Cubic</b></blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote>Used for an "off" point used to control a cubic bezier arc.</blockquote>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
</table></center>
|
|||
|
|
|||
|
<blockquote>
|
|||
|
<p>The following rules are applied to decompose the contour's points into
|
|||
|
segments and arcs :
|
|||
|
<blockquote>
|
|||
|
<li>
|
|||
|
two successive "on" points indicate a line segment joining them.</li>
|
|||
|
</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<ul>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
one conic "off" point amidst two "on" points indicates a conic bezier arc,
|
|||
|
the "off" point being the control point, and the "on" ones the start and
|
|||
|
end points.</li>
|
|||
|
</ul>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Two successive cubic "off" points amidst two "on" points indicate a cubic
|
|||
|
bezier arc. There must be exactly two cubic control points and two on points
|
|||
|
for each cubic arc (using a single cubic "off" point between two "on" points
|
|||
|
is forbidden, for example).</li>
|
|||
|
</ul>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
finally, two successive conic "off" points forces the rasterizer to create
|
|||
|
(during the scan-line conversion process exclusively) a virtual "on" point
|
|||
|
amidst them, at their exact middle. This greatly facilitates the definition
|
|||
|
of successive conic bezier arcs. Moreover, it's the way outlines are described
|
|||
|
in the TrueType specification.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><br>Note that it is possible to mix conic and cubic arcs in a single
|
|||
|
contour, even though no current font driver produces such outlines.
|
|||
|
<br> </ul>
|
|||
|
|
|||
|
<center><table>
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
<blockquote><img SRC="points_segment.png" height=166 width=221></blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote><img SRC="points_conic.png" height=183 width=236></blockquote>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td>
|
|||
|
<blockquote><img SRC="points_cubic.png" height=162 width=214></blockquote>
|
|||
|
</td>
|
|||
|
|
|||
|
<td>
|
|||
|
<blockquote><img SRC="points_conic2.png" height=204 width=225></blockquote>
|
|||
|
</td>
|
|||
|
</tr>
|
|||
|
</table></center>
|
|||
|
|
|||
|
<h4>
|
|||
|
b. Outline descriptor :</h4>
|
|||
|
|
|||
|
<blockquote>A FreeType outline is described through a simple structure,
|
|||
|
called <tt>FT_Outline</tt>, which fields are :
|
|||
|
<br>
|
|||
|
<br>
|
|||
|
<center><table CELLSPACING=3 CELLPADDING=3 BGCOLOR="#CCCCCC" >
|
|||
|
<tr>
|
|||
|
<td><b><tt>n_points</tt></b></td>
|
|||
|
|
|||
|
<td>the number of points in the outline</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td><b><tt>n_contours</tt></b></td>
|
|||
|
|
|||
|
<td>the number of contours in the outline</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td><b><tt>points</tt></b></td>
|
|||
|
|
|||
|
<td>array of point coordinates</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td><b><tt>contours</tt></b></td>
|
|||
|
|
|||
|
<td>array of contour end indices</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td><b><tt>flags</tt></b></td>
|
|||
|
|
|||
|
<td>array of point flags</td>
|
|||
|
</tr>
|
|||
|
</table></center>
|
|||
|
|
|||
|
<p>Here, <b><tt>points</tt></b> is a pointer to an array of <tt>FT_Vector</tt>
|
|||
|
records, used to store the vectorial coordinates of each outline point.
|
|||
|
These are expressed in 1/64th of a pixel, which is also known as the <i>26.6
|
|||
|
fixed float format</i>.
|
|||
|
<p><b><tt>contours</tt></b> is an array of point indices used to delimit
|
|||
|
contours in the outline. For example, the first contour always starts at
|
|||
|
point 0, and ends a point <b><tt>contours[0]</tt></b>. The second contour
|
|||
|
starts at point "<b><tt>contours[0]+1</tt></b>" and ends at <b><tt>contours[1]</tt></b>,
|
|||
|
etc..
|
|||
|
<p>Note that each contour is closed, and that <b><tt>n_points</tt></b>
|
|||
|
should be equal to "<b><tt>contours[n_contours-1]+1</tt></b>" for a valid
|
|||
|
outline.
|
|||
|
<p>Finally, <b><tt>flags</tt></b> is an array of bytes, used to store each
|
|||
|
outline point's tag.
|
|||
|
<br>
|
|||
|
<br> </blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
2. Bounding and control box computations :</h3>
|
|||
|
|
|||
|
<blockquote>A <b>bounding box</b> (also called "<b>bbox</b>") is simply
|
|||
|
the smallest possible rectangle that encloses the shape of a given outline.
|
|||
|
Because of the way arcs are defined, bezier control points are not necessarily
|
|||
|
contained within an outline's bounding box.
|
|||
|
<p>This situation happens when one bezier arc is, for example, the upper
|
|||
|
edge of an outline and an off point happens to be above the bbox. However,
|
|||
|
it is very rare in the case of character outlines because most font designers
|
|||
|
and creation tools always place on points at the extrema of each curved
|
|||
|
edges, as it makes hinting much easier.
|
|||
|
<p>We thus define the <b>control box</b> (a.k.a. the "<b>cbox</b>") as
|
|||
|
the smallest possible rectangle that encloses all points of a given outline
|
|||
|
(including its off points). Clearly, it always includes the bbox, and equates
|
|||
|
it in most cases.
|
|||
|
<p>Unlike the bbox, the cbox is also much faster to compute.
|
|||
|
<br>
|
|||
|
<center><table>
|
|||
|
<tr>
|
|||
|
<td><img SRC="bbox1.png" height=264 width=228></td>
|
|||
|
|
|||
|
<td><img SRC="bbox2.png" height=229 width=217></td>
|
|||
|
</tr>
|
|||
|
</table></center>
|
|||
|
|
|||
|
<p>Control and bounding boxes can be computed automatically through the
|
|||
|
functions <b><tt>FT_Get_Outline_CBox</tt></b> and <b><tt>FT_Get_Outline_BBox</tt></b>.
|
|||
|
The former function is always very fast, while the latter <i>may</i> be
|
|||
|
slow in the case of "outside" control points (as it needs to find the extreme
|
|||
|
of conic and cubic arcs for "perfect" computations). If this isn't the
|
|||
|
case, it's as fast as computing the control box.
|
|||
|
<p>Note also that even though most glyph outlines have equal cbox and bbox
|
|||
|
to ease hinting, this is not necessary the case anymore when a
|
|||
|
<br>transform like rotation is applied to them.
|
|||
|
<br> </blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
3. Coordinates, scaling and grid-fitting :</h3>
|
|||
|
|
|||
|
<blockquote>An outline point's vectorial coordinates are expressed in the
|
|||
|
26.6 format, i.e. in 1/64th of a pixel, hence coordinates (1.0, -2.5) is
|
|||
|
stored as the integer pair ( x:64, y: -192 ).
|
|||
|
<p>After a master glyph outline is scaled from the EM grid to the current
|
|||
|
character dimensions, the hinter or grid-fitter is in charge of aligning
|
|||
|
important outline points (mainly edge delimiters) to the pixel grid. Even
|
|||
|
though this process is much too complex to be described in a few lines,
|
|||
|
its purpose is mainly to round point positions, while trying to preserve
|
|||
|
important properties like widths, stems, etc..
|
|||
|
<p>The following operations can be used to round vectorial distances in
|
|||
|
the 26.6 format to the grid :
|
|||
|
<center>
|
|||
|
<p><tt>round(x) == (x+32) & -64</tt>
|
|||
|
<br><tt>floor(x) == x &
|
|||
|
-64</tt>
|
|||
|
<br><tt>ceiling(x) == (x+63) & -64</tt></center>
|
|||
|
|
|||
|
<p>Once a glyph outline is grid-fitted or transformed, it often is interesting
|
|||
|
to compute the glyph image's pixel dimensions before rendering it. To do
|
|||
|
so, one has to consider the following :
|
|||
|
<p>The scan-line converter draws all the pixels whose <i>centers</i> fall
|
|||
|
inside the glyph shape. It can also detect "<b><i>drop-outs</i></b>", i.e.
|
|||
|
discontinuities coming from extremely thin shape fragments, in order to
|
|||
|
draw the "missing" pixels. These new pixels are always located at a distance
|
|||
|
less than half of a pixel but one cannot predict easily where they'll appear
|
|||
|
before rendering.
|
|||
|
<p>This leads to the following computations :
|
|||
|
<br>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
compute the bbox</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
grid-fit the bounding box with the following :</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<ul><tt>xmin = floor( bbox.xMin )</tt>
|
|||
|
<br><tt>xmax = ceiling( bbox.xMax )</tt>
|
|||
|
<br><tt>ymin = floor( bbox.yMin )</tt>
|
|||
|
<br><tt>ymax = ceiling( bbox.yMax )</tt></ul>
|
|||
|
|
|||
|
<li>
|
|||
|
return pixel dimensions, i.e. <tt>width = (xmax - xmin)/64</tt> and <tt>height
|
|||
|
= (ymax - ymin)/64</tt></li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><br>By grid-fitting the bounding box, one guarantees that all the pixel
|
|||
|
centers that are to be drawn, <b><i>including those coming from drop-out
|
|||
|
control</i></b>, will be <b><i>within</i></b> the adjusted box. Then the
|
|||
|
box's dimensions in pixels can be computed.
|
|||
|
<p>Note also that, when <i>translating</i> a <i>grid-fitted outline</i>,
|
|||
|
one should <b><i>always</i></b> use <b><i>integer distances</i></b> to
|
|||
|
move an outline in the 2D plane. Otherwise, glyph edges won't be aligned
|
|||
|
on the pixel grid anymore, and the hinter's work will be lost, producing
|
|||
|
<b><i>very
|
|||
|
low quality </i></b>bitmaps and pixmaps..</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<hr WIDTH="100%">
|
|||
|
<h2>
|
|||
|
VII. FreeType bitmaps :</h2>
|
|||
|
|
|||
|
<blockquote>The purpose of this section is to present the way FreeType
|
|||
|
manages bitmaps and pixmaps, and how they relate to the concepts previously
|
|||
|
defined. The relationships between vectorial and pixel coordinates is explained.
|
|||
|
<br>
|
|||
|
<h3>
|
|||
|
1. FreeType bitmap and pixmap descriptor :</h3>
|
|||
|
|
|||
|
<blockquote>A bitmap or pixmap is described through a single structure,
|
|||
|
called <tt>FT_Raster_Map</tt>. It is a simple descriptor whose fields are
|
|||
|
:
|
|||
|
<br>
|
|||
|
<br>
|
|||
|
<center><table CELLSPACING=3 CELLPADDING=5 BGCOLOR="#CCCCCC" >
|
|||
|
<caption><tt>FT_Raster_Map</tt></caption>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td><b>rows</b></td>
|
|||
|
|
|||
|
<td>the number of rows, i.e. lines, in the bitmap</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td><b>width</b></td>
|
|||
|
|
|||
|
<td>the number of horizontal pixels in the bitmap</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td><b>cols</b></td>
|
|||
|
|
|||
|
<td>the number of "columns", i.e. bytes per line, in the bitmap</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td><b>flow</b></td>
|
|||
|
|
|||
|
<td>the bitmap's flow, i.e. orientation of rows (see below)</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td><b>pix_bits</b></td>
|
|||
|
|
|||
|
<td>the number of bits per pixels. valid values are 1, 4, 8 and 16</td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td><b>buffer</b></td>
|
|||
|
|
|||
|
<td>a typeless pointer to the bitmap pixel bufer</td>
|
|||
|
</tr>
|
|||
|
</table></center>
|
|||
|
|
|||
|
<p>The bitmap's <b><tt>flow</tt></b> determines wether the rows in the
|
|||
|
pixel buffer are stored in ascending or descending order. Possible values
|
|||
|
are <b><tt>FT_Flow_Up</tt></b> (value 1) and <b><tt>FT_Flow_Down</tt></b>
|
|||
|
(value -1).
|
|||
|
<p>Remember that FreeType uses the <i>Y upwards</i> convention in the 2D
|
|||
|
plane. Which means that a coordinate of (0,0) always refer to the <i>lower-left
|
|||
|
corner</i> of a bitmap.
|
|||
|
<p>In the case of an '<i>up</i>' flow, the rows are stored in increasing
|
|||
|
vertical position, which means that the first bytes of the pixel buffer
|
|||
|
are part of the <i>lower</i> bitmap row. On the opposite, a '<i>down</i>'
|
|||
|
flow means that the first buffer bytes are part of the <i>upper</i> bitmap
|
|||
|
row, i.e. the last one in ascending order.
|
|||
|
<p>As a hint, consider that when rendering an outline into a Windows or
|
|||
|
X11 bitmap buffer, one should always use a down flow in the bitmap descriptor.
|
|||
|
<br>
|
|||
|
<center><table>
|
|||
|
<tr>
|
|||
|
<td><img SRC="up_flow.png" height=298 width=291></td>
|
|||
|
|
|||
|
<td><img SRC="down_flow.png" height=298 width=313></td>
|
|||
|
</tr>
|
|||
|
|
|||
|
<tr>
|
|||
|
<td></td>
|
|||
|
|
|||
|
<td></td>
|
|||
|
</tr>
|
|||
|
</table></center>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
2. Vectorial versus pixel coordinates :</h3>
|
|||
|
|
|||
|
<blockquote>This sub-section explains the differences between vectorial
|
|||
|
and pixel coordinates. To make things clear, brackets will be used to describe
|
|||
|
pixel coordinates, e.g. [3,5], while parentheses will be used for vectorial
|
|||
|
ones, e.g. (-2,3.5).
|
|||
|
<p>In the pixel case, as we use the <i>Y upwards</i> convention, the coordinate
|
|||
|
[0,0] always refers to the <i>lower left pixel</i> of a bitmap, while coordinate
|
|||
|
[width-1, rows-1] to its <i>upper right pixel</i>.
|
|||
|
<p>In the vectorial case, point coordinates are expressed in floating units,
|
|||
|
like (1.25, -2.3). Such a position doesn't refer to a given pixel, but
|
|||
|
simply to an immaterial point in the 2D plane
|
|||
|
<p>The pixels themselves are indeed <i>square boxes</i> of the 2D plane,
|
|||
|
which centers lie in half pixel coordinates. For example, the <i>lower
|
|||
|
left pixel</i> of a bitmap is delimited by the <i>square</i> (0,0)-(1,1),
|
|||
|
its center being at location (0.5,0.5).
|
|||
|
<p>This introduces some differences when computing distances. For example,
|
|||
|
the "<i>length</i>" in pixels of the line [0,0]-[10,0] is 11. However,
|
|||
|
the vectorial distance between (0,0)-(10,0) covers exactly 10 pixel centers,
|
|||
|
hence its length if 10.
|
|||
|
<center><img SRC="grid_1.png" height=390 width=402></center>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
3. Converting outlines into bitmaps and pixmaps :</h3>
|
|||
|
|
|||
|
<blockquote>Generating a bitmap or pixmap image from a vectorial image
|
|||
|
is easy with FreeType. However, one must understand a few points regarding
|
|||
|
the positioning of the outline in the 2D plane before calling the function
|
|||
|
<b><tt>FT_Get_Outline_Bitmap</tt></b>.
|
|||
|
These are :
|
|||
|
<br>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The glyph loader and hinter always places the outline in the 2D plane so
|
|||
|
that (0,0) matches its character origin. This means that the glyph<70>s outline,
|
|||
|
and corresponding bounding box, can be placed anywhere in the 2D plane
|
|||
|
(see the graphics in section III).</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The target bitmap<61>s area is mapped to the 2D plane, with its lower left
|
|||
|
corner at (0,0). This means that a bitmap or pixmap of dimensions [<tt>w,h</tt>]
|
|||
|
will be mapped to a 2D rectangle window delimited by (0,0)-(<tt>w,h</tt>).</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
When calling <b><tt>FT_Get_Outline_Bitmap</tt></b>, everything that falls
|
|||
|
within the bitmap window is rendered, the rest is ignored.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><br>A common mistake made by many developers when they begin using FreeType
|
|||
|
is believing that a loaded outline can be directly rendered in a bitmap
|
|||
|
of adequate dimensions. The following images illustrate why this is a problem
|
|||
|
:
|
|||
|
<ul>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
the first image shows a loaded outline in the 2D plane.</li>
|
|||
|
|
|||
|
<li>
|
|||
|
the second one shows the target window for a bitmap of arbitrary dimensions
|
|||
|
[w,h]</li>
|
|||
|
|
|||
|
<li>
|
|||
|
the third one shows the juxtaposition of the outline and window in the
|
|||
|
2D plane</li>
|
|||
|
|
|||
|
<li>
|
|||
|
the last image shows what will really be rendered in the bitmap.</li>
|
|||
|
</ul>
|
|||
|
</ul>
|
|||
|
|
|||
|
<center><img SRC="clipping.png" height=151 width=539></center>
|
|||
|
|
|||
|
<p><br>
|
|||
|
<br>
|
|||
|
<br>
|
|||
|
<br>
|
|||
|
<br>
|
|||
|
<p>Indeed, in nearly all cases, the loaded or transformed outline must
|
|||
|
be translated before it is rendered into a target bitmap, in order to adjust
|
|||
|
its position relative to the target window.
|
|||
|
<p>For example, the correct way of creating a <i>standalone</i> glyph bitmap
|
|||
|
is thus to :
|
|||
|
<br>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Compute the size of the glyph bitmap. It can be computed directly from
|
|||
|
the glyph metrics, or by computing its bounding box (this is useful when
|
|||
|
a transform has been applied to the outline after the load, as the glyph
|
|||
|
metrics are not valid anymore).</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Create the bitmap with the computed dimensions. Don<6F>t forget to fill the
|
|||
|
pixel buffer with the background color.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Translate the outline so that its lower left corner matches (0,0). Don<6F>t
|
|||
|
forget that in order to preserve hinting, one should use integer, i.e.
|
|||
|
rounded distances (of course, this isn<73>t required if preserving hinting
|
|||
|
information doesn<73>t matter, like with rotated text). Usually, this means
|
|||
|
translating with a vector <tt>( -ROUND(xMin), -ROUND(yMin) )</tt>.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
Call the function <b><tt>FT_Get_Outline_Bitmap</tt></b>.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><br>In the case where one wants to write glyph images directly into
|
|||
|
a large bitmap, the outlines must be translated so that their vectorial
|
|||
|
position correspond to the current text cursor/character origin.</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h2>
|
|||
|
|
|||
|
<hr WIDTH="100%"></h2>
|
|||
|
|
|||
|
<h2>
|
|||
|
VII. FreeType anti-aliasing :</h2>
|
|||
|
<b><i>IMPORTANT NOTE :</i></b>
|
|||
|
<br>This section is still in progress, as the way FreeType 2 handles anti-aliased
|
|||
|
rendering hasn't been definitely set yet. The main reason being that a
|
|||
|
flexible way of doing things is needed in order to allow further improvements
|
|||
|
in the raster (i.e. number of gray levels > 100, etc..).
|
|||
|
<blockquote>
|
|||
|
<h3>
|
|||
|
1. What is anti-aliasing :</h3>
|
|||
|
|
|||
|
<blockquote>Anti-aliasing works by using various levels of grays to reduce
|
|||
|
the "staircase" artefacts visible on the diagonals and curves of glyph
|
|||
|
bitmaps. It is a way to artificially enhance the display resolution of
|
|||
|
the target device. It can smooth out considerably displayed or printed
|
|||
|
text.</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
2. How does it work with FreeType :</h3>
|
|||
|
|
|||
|
<blockquote>FreeType's scan-line converter is able to produce anti-aliased
|
|||
|
output directly. It is however limited to 8-bit pixmaps and 5 levels of
|
|||
|
grays (or 17 levels, depending on a build configuration option). Here's
|
|||
|
how one should use it :
|
|||
|
<h4>
|
|||
|
a. Set the gray-level palette :</h4>
|
|||
|
|
|||
|
<blockquote>The scan-line converter uses 5 levels for anti-aliased output.
|
|||
|
Level 0 corresponds to the text background color (e.g. white), and level
|
|||
|
5 to the text foreground color. Intermediate levels are used for intermediate
|
|||
|
shades of grays.
|
|||
|
<p>You must set the raster's palette when you want to use different colors,
|
|||
|
use the function <b><tt>FT_Raster_Set_Palette</tt></b> as in :
|
|||
|
<p><tt>{</tt>
|
|||
|
<br><tt> static const char gray_palette[5] = { 0, 7, 15, 31,
|
|||
|
63 };</tt>
|
|||
|
<br><tt> <20></tt>
|
|||
|
<br><tt> error = FT_Set_Raster_Palette( library, 5, palette );</tt>
|
|||
|
<br><tt>}</tt>
|
|||
|
<br>
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The first parameter is a handle to a FreeType library object. See the user
|
|||
|
guide for more details (the library contains a scan-line converter object).</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The second parameter is the number of entries in the gray-level palette.
|
|||
|
Valid values are 5 and 17 for now, but this may change in later implementations.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<ul>
|
|||
|
<li>
|
|||
|
The last parameter is a pointer to a char table containing the pixel value
|
|||
|
for each of the gray-levels. In this example, we use a background color
|
|||
|
of 0, a foreground color of 63, and intermediate values in-between.</li>
|
|||
|
</ul>
|
|||
|
|
|||
|
<p><br>The palette is copied in the raster object, as well as processed
|
|||
|
to build several lookup-tables necessary for the internal anti-aliasing
|
|||
|
algorithm.
|
|||
|
<br> </blockquote>
|
|||
|
|
|||
|
<h4>
|
|||
|
b. Render the pixmap :</h4>
|
|||
|
|
|||
|
<blockquote>The scan-line converter doesn't create bitmaps or pixmaps,
|
|||
|
it simply renders into those that are passed as parameters to the function
|
|||
|
<b><tt>FT_Get_Outline_Bitmap</tt></b>.
|
|||
|
To render an anti-aliased pixmap, simply set the target bitmap<61>s depth
|
|||
|
to 8. Note however that this target 8-bit pixmap must always have a '<b><tt>cols</tt></b>'
|
|||
|
field padded to 32-bits, which means that the number of bytes per lines
|
|||
|
of the pixmap must be a multiple of 4 !
|
|||
|
<p>Once the palette has been set, and the pixmap buffer has been created
|
|||
|
to receive the glyph image, simply call <b><tt>FT_Get_Outline_Bitmap</tt></b>.
|
|||
|
Take care of clearing the target pixmap with the background color before
|
|||
|
calling this function. For the sake of simplicity and efficiency, the raster
|
|||
|
is not able to compose anti-aliased glyph images on a pre-existing images.
|
|||
|
<p>Here's some code demonstrating how to load and render a single glyph
|
|||
|
pixmap :
|
|||
|
<p><tt>{</tt>
|
|||
|
<br><tt> FT_Outline outline;</tt>
|
|||
|
<br><tt> FT_Raster_Map pixmap;</tt>
|
|||
|
<br><tt> FT_BBox cbox;</tt>
|
|||
|
<br><tt> <20></tt>
|
|||
|
<p><i><tt> // load the outline</tt></i>
|
|||
|
<br><tt> <20></tt>
|
|||
|
<p><i><tt> // compute glyph dimensions (grid-fit cbox, etc..)</tt></i>
|
|||
|
<br><tt> FT_Get_Outline_CBox( &outline, &cbox );</tt>
|
|||
|
<p><tt> cbox.xMin = cbox.xMin & -64;
|
|||
|
// floor(xMin)</tt>
|
|||
|
<br><tt> cbox.yMin = cbox.yMin & -64;
|
|||
|
// floor(yMin)</tt>
|
|||
|
<br><tt> cbox.xMax = (cbox.xMax+32) & -64; // ceiling(xMax)</tt>
|
|||
|
<br><tt> cbox.yMax = (cbox.yMax+32) & -64; // ceiling(yMax)</tt>
|
|||
|
<p><tt> pixmap.width = (cbox.xMax - cbox.xMin)/64;</tt>
|
|||
|
<br><tt> pixmap.rows = (cbox.yMax - cbox.yMin)/64;</tt>
|
|||
|
<p><i><tt> // fill the pixmap descriptor and create the pixmap buffer</tt></i>
|
|||
|
<br><i><tt> // don't forget to pad the 'cols' field to 32 bits</tt></i>
|
|||
|
<br><tt> pixmap.pix_bits = 8;</tt>
|
|||
|
<br><tt> pixmap.flow = FT_Flow_Down;</tt>
|
|||
|
<br><tt> pixmap.cols = (pixmap.width+3) &
|
|||
|
-4; // pad 'cols' to 32 bits</tt>
|
|||
|
<br><tt> pixmap.buffer = malloc( pixmap.cols * pixmap.rows
|
|||
|
);</tt>
|
|||
|
<p><i><tt> // fill the pixmap buffer with the background color</tt></i>
|
|||
|
<br><i><tt> //</tt></i>
|
|||
|
<br><tt> memset( pixmap.buffer, 0, pixmap.cols*pixmap.rows );</tt>
|
|||
|
<p><i><tt> // translate the outline to match (0,0) with the glyph's</tt></i>
|
|||
|
<br><i><tt> // lower left corner (ignore the bearings)</tt></i>
|
|||
|
<br><i><tt> // the cbox is grid-fitted, we won't ruin the hinting.</tt></i>
|
|||
|
<br><i><tt> //</tt></i>
|
|||
|
<br><tt> FT_Translate_Outline( &outline, -cbox.xMin, -cbox.yMin
|
|||
|
);</tt>
|
|||
|
<p><i><tt> // render the anti-aliased glyph pixmap</tt></i>
|
|||
|
<br><tt> error = FT_Get_Outline_Bitmap( library, &outline, &pixmap
|
|||
|
);</tt>
|
|||
|
<p><tt> // save the bearings for later use..</tt>
|
|||
|
<br><tt> corner_x = cbox.xMin / 64;</tt>
|
|||
|
<br><tt> corner_y = cbox.yMin / 64;</tt>
|
|||
|
<br><tt>}</tt>
|
|||
|
<p>The resulting pixmap is always anti-aliased.</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
<h3>
|
|||
|
3. Possible enhancements :</h3>
|
|||
|
|
|||
|
<blockquote>FreeType's raster (i.e. its scan-line converter) is currently
|
|||
|
limited to producing either 1-bit bitmaps or anti-aliased 8-bit pixmaps.
|
|||
|
It is not possible, for example, to draw directly a bitmapped glyph image
|
|||
|
into a 4, 8 or 16-bit pixmap through a call to FT_Get_Outline_Bitmap.
|
|||
|
<p>Moreover, the anti-aliasing filter is limited to use 5 or 17 levels
|
|||
|
of grays (through 2x2 and 4x4 sub-sampling). There are cases where this
|
|||
|
could seem insufficient for optimal results and where a higher number of
|
|||
|
levels like 64 or 128 would be a good thing.
|
|||
|
<p>These enhancements are all possible but not planned for an immediate
|
|||
|
future of the FreeType engine.</blockquote>
|
|||
|
</blockquote>
|
|||
|
|
|||
|
</body>
|
|||
|
</html>
|