2000-11-09 23:15:34 +01:00
|
|
|
<!doctype html public "-//w3c//dtd html 4.0 transitional//en"
|
|
|
|
"http://www.w3.org/TR/REC-html40/loose.dtd">
|
2000-11-09 01:01:38 +01:00
|
|
|
<html>
|
|
|
|
<head>
|
2000-11-09 23:15:34 +01:00
|
|
|
<meta http-equiv="Content-Type"
|
|
|
|
content="text/html; charset=iso-8859-1">
|
|
|
|
<meta name="Author"
|
|
|
|
content="David Turner">
|
|
|
|
<title>FreeType Glyph Conventions</title>
|
2000-11-09 01:01:38 +01:00
|
|
|
</head>
|
|
|
|
|
|
|
|
<body text="#000000"
|
|
|
|
bgcolor="#FFFFFF"
|
|
|
|
link="#0000EF"
|
|
|
|
vlink="#51188E"
|
|
|
|
alink="#FF0000">
|
|
|
|
|
2000-11-09 23:15:34 +01:00
|
|
|
<h1 align=center>
|
|
|
|
FreeType Glyph Conventions
|
|
|
|
</h1>
|
|
|
|
|
|
|
|
<h2 align=center>
|
|
|
|
Version 2.1
|
|
|
|
</h2>
|
|
|
|
|
|
|
|
<h3 align=center>
|
|
|
|
Copyright 1998-2000 David Turner (<a
|
|
|
|
href="mailto:david@freetype.org">david@freetype.org</a>)<br>
|
|
|
|
Copyright 2000 The FreeType Development Team (<a
|
|
|
|
href="mailto:devel@freetype.org">devel@freetype.org</a>)
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
<center>
|
|
|
|
<table width="65%">
|
|
|
|
<tr><td>
|
|
|
|
|
|
|
|
<center>
|
|
|
|
<table width="100%"
|
|
|
|
border=0
|
|
|
|
cellpadding=5>
|
|
|
|
<tr bgcolor="#CCFFCC"
|
|
|
|
valign=center>
|
|
|
|
<td align=center
|
|
|
|
width="30%">
|
|
|
|
<a href="glyphs-4.html">Previous</a>
|
|
|
|
</td>
|
|
|
|
<td align=center
|
|
|
|
width="30%">
|
|
|
|
<a href="index.html">Contents</a>
|
|
|
|
</td>
|
|
|
|
<td align=center
|
|
|
|
width="30%">
|
|
|
|
<a href="glyphs-6.html">Next</a>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</center>
|
|
|
|
|
|
|
|
<p><hr></p>
|
|
|
|
|
|
|
|
<table width="100%">
|
|
|
|
<tr bgcolor="#CCCCFF"
|
|
|
|
valign=center><td>
|
|
|
|
<h2>
|
|
|
|
V. Text processing
|
|
|
|
</h2>
|
|
|
|
</td></tr>
|
|
|
|
</table>
|
|
|
|
|
|
|
|
<p>This section demonstrates how to use the concepts previously defined
|
|
|
|
to render text, whatever the layout you use.</p>
|
|
|
|
|
|
|
|
|
|
|
|
<a name="section-1">
|
|
|
|
<h3>
|
|
|
|
1. Writing simple text strings
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
<p>In this first example, we will generate a simple string of Roman
|
|
|
|
text, i.e. with a horizontal left-to-right layout. Using exclusively
|
|
|
|
pixel metrics, the process looks like:
|
|
|
|
|
|
|
|
<tt>
|
|
|
|
<ol>
|
|
|
|
<li>
|
|
|
|
Convert the character string into a series of glyph
|
|
|
|
indices.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Place the pen to the cursor position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Get or load the glyph image.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Translate the glyph so that its 'origin' matches the pen position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Render the glyph to the target device.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Increment the pen position by the glyph's advance width in pixels.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Start over at step 3 for each of the remaining glyphs.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
When all glyphs are done, set the text cursor to the new pen
|
|
|
|
position.
|
|
|
|
</li>
|
|
|
|
</ol>
|
|
|
|
</tt>
|
|
|
|
|
|
|
|
<p>Note that kerning isn't part of this algorithm.</p>
|
|
|
|
|
|
|
|
|
|
|
|
<a name="section-2">
|
|
|
|
<h3>
|
|
|
|
2. Sub-pixel positioning
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
<p>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
|
|
|
|
subsection 1, with the following few differences:</p>
|
|
|
|
|
|
|
|
<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>
|
|
|
|
</ol>
|
|
|
|
|
|
|
|
<p>Here an improved version of the algorithm:</p>
|
|
|
|
|
|
|
|
<tt>
|
|
|
|
<ol>
|
|
|
|
<li>
|
|
|
|
Convert the character string into a series of glyph
|
|
|
|
indices.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Place the pen to the cursor position. This can be a non-integer
|
|
|
|
point.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Get or load the glyph image.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Translate the glyph so that its "origin" matches the rounded pen
|
|
|
|
position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Render the glyph to the target device.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Increment the pen position by the glyph's advance width in
|
|
|
|
fractional pixels.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Start over at step 3 for each of the remaining glyphs.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
When all glyphs are done, set the text cursor to the new pen
|
|
|
|
position.
|
|
|
|
</li>
|
|
|
|
</ol>
|
|
|
|
</tt>
|
|
|
|
|
|
|
|
<p>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.</p>
|
|
|
|
|
|
|
|
|
|
|
|
<a name="section-3">
|
|
|
|
<h3>
|
|
|
|
3. Simple kerning
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
<p>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>
|
|
|
|
|
|
|
|
<p>Algorithm 1 with kerning:</p>
|
|
|
|
|
|
|
|
<tt>
|
|
|
|
<ol>
|
|
|
|
<li>
|
|
|
|
Convert the character string into a series of glyph
|
|
|
|
indices.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Place the pen to the cursor position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Get or load the glyph image.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Add the rounded scaled kerning distance, if any, to the pen
|
|
|
|
position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Translate the glyph so that its "origin" matches the pen position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Render the glyph to the target device.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Increment the pen position by the glyph's advance width in pixels.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Start over at step 3 for each of the remaining glyphs.
|
|
|
|
</li>
|
|
|
|
</ol>
|
|
|
|
</tt>
|
|
|
|
|
|
|
|
<p>Algorithm 2 with kerning:</p>
|
|
|
|
|
|
|
|
<tt>
|
|
|
|
<ol>
|
|
|
|
<li>
|
|
|
|
Convert the character string into a series of glyph
|
|
|
|
indices.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Place the pen to the cursor position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Get or load the glyph image.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Add the scaled unrounded kerning distance, if any, to the pen
|
|
|
|
position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Translate the glyph so that its "origin" matches the rounded pen
|
|
|
|
position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Render the glyph to the target device.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Increment the pen position by the glyph's advance width in
|
|
|
|
fractional pixels.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Start over at step 3 for each of the remaining glyphs.
|
|
|
|
</li>
|
|
|
|
</ol>
|
|
|
|
</tt>
|
|
|
|
|
|
|
|
Of course, the algorithm described in section IV can also be
|
|
|
|
applied to prevent the sliding dot problem if one wants to.
|
|
|
|
|
|
|
|
|
|
|
|
<a name="section-4">
|
|
|
|
<h3>
|
|
|
|
4. Right-to-left layout
|
|
|
|
</h3>
|
|
|
|
|
2000-11-10 23:39:21 +01:00
|
|
|
<p>The process of laying out Arabic or Hebrew text is extremely similar.
|
2000-11-09 23:15:34 +01:00
|
|
|
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).</p>
|
|
|
|
|
|
|
|
<p>Right-to-left algorithm 1:</p>
|
|
|
|
|
|
|
|
<tt>
|
|
|
|
<ol>
|
|
|
|
<li>
|
|
|
|
Convert the character string into a series of glyph
|
|
|
|
indices.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Place the pen to the cursor position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Get or load the glyph image.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Decrement the pen position by the glyph's advance width in pixels.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Translate the glyph so that its "origin" matches the pen position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Render the glyph to the target device.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Start over at step 3 for each of the remaining glyphs.
|
|
|
|
</li>
|
|
|
|
</ol>
|
|
|
|
</tt>
|
|
|
|
|
|
|
|
<p>The changes to algorithm 2, as well as the inclusion of kerning
|
|
|
|
are left as an exercise to the reader.</p>
|
|
|
|
|
|
|
|
|
|
|
|
<a name="section-5">
|
|
|
|
<h3>
|
|
|
|
5. Vertical layouts
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
<p>Laying out vertical text uses exactly the same processes, with the
|
|
|
|
following significant differences:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>
|
|
|
|
<p>The baseline is vertical, and the vertical metrics must be used
|
|
|
|
instead of the horizontal one.</p>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<p>The left bearing is usually negative, but this doesn't change the
|
|
|
|
fact that the glyph origin must be located on the baseline.</p>
|
|
|
|
</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
|
|
|
|
<i>Y</i> axis is oriented upwards).
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>Here the algorithm:</p>
|
|
|
|
|
|
|
|
<tt>
|
|
|
|
<ol>
|
|
|
|
<li>
|
|
|
|
Convert the character string into a series of glyph
|
|
|
|
indices.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Place the pen to the cursor position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Get or load the glyph image.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Translate the glyph so that its "origin" matches the pen position.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Render the glyph to the target device.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Decrement the vertical pen position by the glyph's advance height
|
|
|
|
in pixels.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
Start over at step 3 for each of the remaining glyphs.
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
When all glyphs are done, set the text cursor to the new pen
|
|
|
|
position.
|
|
|
|
</li>
|
|
|
|
</ol>
|
|
|
|
</tt>
|
|
|
|
|
|
|
|
|
|
|
|
<a name="section-6">
|
|
|
|
<h3>
|
|
|
|
6. WYSIWYG text layouts
|
|
|
|
</h3>
|
|
|
|
|
|
|
|
<p>As you probably know, the acronym WYSIWYG stands for "What You See Is
|
|
|
|
What You Get". Basically, this means that the output of a document on
|
|
|
|
the screen should match "perfectly" its printed version. A
|
|
|
|
<em>true</em> WYSIWYG system requires two things:</p>
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
<li>
|
|
|
|
<p><em>device-independent text layout</em></p>
|
|
|
|
|
|
|
|
<p>This 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.</p>
|
|
|
|
</li>
|
|
|
|
<li>
|
|
|
|
<p><em>matching display and print character sizes</em></p>
|
|
|
|
|
|
|
|
<p>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%).</p>
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
<p>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 is not too
|
|
|
|
unfortunate, however, because most users really don't care about this
|
|
|
|
feature. Legibility is much more important.</p>
|
|
|
|
|
|
|
|
<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 equals exactly
|
|
|
|
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>
|
|
|
|
|
|
|
|
<p>These distinct resolutions explain some differences when displaying
|
2000-11-10 23:39:21 +01:00
|
|
|
text at the same character size on a Mac and a Windows machine.
|
2000-11-09 23:15:34 +01:00
|
|
|
Moreover, it is not unusual to find some TrueType fonts with enhanced
|
|
|
|
hinting (technical note: through delta-hinting) for the sizes of 10, 12,
|
|
|
|
14 and 16 points at 96 dpi.</p>
|
|
|
|
|
|
|
|
<p>The term <em>device-independent text</em> 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 <em>hinted</em> 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
|
|
|
|
<em>whole</em> document layout, especially if it makes strong use of
|
|
|
|
justification, uses few page breaks, etc.</p>
|
|
|
|
|
|
|
|
<p>Because 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 will 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>
|
|
|
|
|
|
|
|
<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 whatever metrics you want and store
|
|
|
|
them with the text in order to get sure they are printed the same on all
|
|
|
|
devices (the latter being probably the best solution, as it also enables
|
|
|
|
font substitution without breaking text layouts).</p>
|
|
|
|
|
|
|
|
<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
|
|
|
|
<em>is</em> a requirement.</p>
|
|
|
|
|
|
|
|
|
|
|
|
<p><hr></p>
|
|
|
|
|
|
|
|
<center>
|
|
|
|
<table width="100%"
|
|
|
|
border=0
|
|
|
|
cellpadding=5>
|
|
|
|
<tr bgcolor="#CCFFCC"
|
|
|
|
valign=center>
|
|
|
|
<td align=center
|
|
|
|
width="30%">
|
|
|
|
<a href="glyphs-4.html">Previous</a>
|
|
|
|
</td>
|
|
|
|
<td align=center
|
|
|
|
width="30%">
|
|
|
|
<a href="index.html">Contents</a>
|
|
|
|
</td>
|
|
|
|
<td align=center
|
|
|
|
width="30%">
|
|
|
|
<a href="glyphs-6.html">Next</a>
|
|
|
|
</td>
|
|
|
|
</tr>
|
|
|
|
</table>
|
|
|
|
</center>
|
|
|
|
|
|
|
|
</td></tr>
|
|
|
|
</table>
|
|
|
|
</center>
|
2000-11-09 01:01:38 +01:00
|
|
|
|
|
|
|
</body>
|
|
|
|
</html>
|