1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
|
http://www.freetype.org
Glyph Hell
An introduction to glyphs, as used and defined in the FreeType engine
------------------------------------------------------------------------
Introduction
This article discusses in great detail the definition of glyph metrics, per
se the TrueType specification, and the way they are managed and used by the
FreeType engine. This information is crucial when it comes to rendering text
strings, either in a conventional (i.e. Roman) layout, or with vertical or
right-to-left ones. Some aspects like glyph rotation and transformation are
explained too.
Comments and corrections are highly welcome, and can be sent to the FreeType
developers list.
------------------------------------------------------------------------
I. An overview of font files
In TrueType, a single font file is used to contain information related to
classification, modeling and rendering of text using a given typeface. This
data is located in various independent `tables', which can be sorted in four
simple classes, as described below:
* Face Data
We call face data the amount of information related to a given
typeface, independently of any particular scaling, transformation,
and/or glyph index. This usually means some typeface-global metrics and
attributes, like family and styles, PANOSE number, typographic
ascenders and descenders, as well as some very TrueType specific items
like the font `programs' found in the fpgm and prep tables, the gasp
table, character mappings, etc.
In FreeType, a face object is used to model a font file's face data.
* Instance Data
We call instance a given pointsize/transformation, at a given device
resolution (e.g. 8pt at 96x96dpi, or 12pt at 300x600dpi, etc). Some
tables found in the font files are used to produce instance-specific
data, like the cvt table, or the prep program. Though they are often
part of the face data, their processing results in information called
instance data.
In FreeType, it is modeled through an instance object, which is always
created from an existing face object.
* Glyph Data
We call glyph data the piece of information related to specific glyphs.
This includes the following things that are described in more details
in the next sections:
o The glyph's vectorial representation, also called its outline.
o Various metrics, like the glyph's bounding box, its bearings and
advance values.
o TrueType specifies a specific instruction bytecode, used to
associate each glyph with a small program, called the glyph code.
Its purpose is to grid-fit the outline to any target instance, in
order to produce excellent output at small pixel sizes.
The FreeType engine doesn't map each glyph to a single structure, as
this would waste memory for no good reason. Rather, a glyph object is a
container, created from any active face, which can be used to load
and/or process any font glyph at any instance (or even no instance at
all). Of course, the glyph properties (outline, metrics, bitmaps, etc.)
can be extracted independently from an object once it has been loaded
or processed.
* Text and Layout Data
Finally, there is a last class of data that doesn't really fit in all
others, and that can be called text data. It comprises information
related to the grouping of glyphs together to form text. Simple
examples are the kerning table, which controls the spacing between
adjacent glyphs, as well as some of the extensions introduced in
TrueType Open, OpenType, and TrueType GX like glyph substitution
(ligatures, vertical representations), baseline management,
justification, etc.
This article focuses on the basic TrueType tables, and hence, will only
talk about kerning, as FreeType doesn't support OpenType nor GX (yet).
[Support for TrueType Open is already partially available.]
------------------------------------------------------------------------
II. Glyph Outlines
TrueType is a scalable font format; it is thus possible to render glyphs at
any scale, and under any affine transform, from a single source
representation. However, simply scaling vectorial shapes exhibits at small
sizes (where `small' refers here to anything smaller than at least
150 pixels) a collection of un-harmonious artifacts, like widths and/or
heights degradations.
Because of this, the format also provides a complete programming language
used to design small programs associated to each glyph. Its role is to align
the point positions on the pixel grid after the scaling. This operation is
hence called grid-fitting, or even hinting.
1. Vectorial representation
The source format of outlines is a collection of closed paths called
contours. Each contour delimits an outer or inner region of the glyph,
and can be made of either line segments and/or second-order beziers
(also called conic beziers or quadratics).
It is described internally as a series of successive points, with each
point having an associated flag indicating whether it is `on' or `off'
the curve. These rules are applied to decompose the contour:
o Two successive `on' points indicate a line segment joining them.
o One `off' point amidst two `on' points indicates a conic bezier,
the `off' point being the control point, and the `on' ones the
start and end points.
o Finally, two successive `off' points forces the rasterizer to
create (only during bitmap rendering) a virtual `on' point amidst
them, at their exact middle. This greatly facilitates the
definition of successive Bezier arcs.
* # on
* off
__---__
#-__ _-- -_
--__ _- -
--__ # \
--__ #
-#
Two `on' points
Two `on' points and one `off' point
between them
*
# __ Two `on' points with two `off'
\ - - points between them. The point
\ / \ marked `0' is the middle of the
- 0 \ `off' points, and is a `virtual
-_ _- # on' point where the curve passes.
-- It does not appear in the point
list.
*
Each glyph's original outline points are located on a grid of
indivisible units. The points are stored in the font file as
16-bit integer grid coordinates, with the grid origin's being at (0,0);
they thus range from -16384 to 16383.
In creating the glyph outlines, a type designer uses an imaginary
square called the EM square. Typically, the EM square encloses the
capital letter `M' and most other letters of a typical roman alphabet.
The square's size, i.e., the number of grid units on its sides, is very
important for two reasons:
o It is the reference used to scale the outlines to a given
instance. For example, a size of 12pt at 300x300dpi 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
pixel_size = point_size * resolution / 72
pixel_coordinate = grid_coordinate * pixel_size / EM_size
o 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).
Note that glyphs can freely extend beyond the EM square if the font
designer wants this. The EM is used as a convenience, and is a valuable
convenience from traditional typography.
Grid units are very often called font units or EM units.
-----------------------------------------------------------------------
IMPORTANT NOTE:
Under FreeType, scaled pixel positions are all expressed in the 26.6
fixed float format (made of a 26-bit integer mantissa, and a 6-bit
fractional part). In other words, all coordinates are multiplied by 64.
The grid lines along the integer pixel positions, are multiples of 64,
like (0,0), (64,0), (0,64), (128,128), etc., while the pixel centers
lie at middle coordinates (32 modulo 64) like (32,32), (96,32), etc.
-----------------------------------------------------------------------
2. Hinting and Bitmap rendering
As said before, simply scaling outlines to a specific instance always
creates undesirable artifacts, like stems of different widths or
heights in letters like `E' or `H'. Proper glyph rendering needs that
the scaled points are aligned along the pixel grid (hence the name
grid-fitting), and that important widths and heights are respected
throughout the whole font (for example, it is very often desirable that
the letters `I' and `T' have their central vertical line of the same
pixel width).
Type 1 PostScript font files include with each glyph a small series of
distances called hints, which are later used by the type manager to try
grid-fitting the outlines as cleverly as possible. On one hand, it has
the consequence that upgrading your font engine can enhance the visual
aspects of all fonts of your system; on the other hand, the quality of
even the best version of Adobe's Type Manager isn't always very
pleasing at small sizes (notwithstanding font smoothing).
TrueType takes a radically different approach: Each glyph has an
associated `program', designed in a specific geometrical language,
which is used to align explicitly each outline point to the pixel grid,
preserving important distances and metrics. A stack-based low-level
bytecode is used to store it in the font file, and is interpreted later
when rendering the scaled glyphs.
This means that even very complex glyphs can be rendered perfectly at
very small sizes, as long as the corresponding glyph code is designed
correctly. Moreover, a glyph can loose some of its details, like
serifs, at small sizes to become more readable, because the bytecode
provides interesting features.
However, this also have the sad implication that an ill-designed glyph
code will always render junk, whatever the font engine's version, and
that it's very difficult to produce quality glyph code. There are about
200 TrueType opcodes, and no known `high-level language' for it. Most
type artists aren't programmers at all and the only tools able to
produce quality code from vectorial representation have been
distributed to only a few font foundries, while tools available to the
public, e.g. Fontographer, are usually expensive though generating
average to mediocre glyph code.
All this explains why an enormous number of broken or ugly `free' fonts
have appeared on the TrueType scene, and that this format is now
mistakenly thought as `crap' by many people. Funnily, these are often
the same who stare at the `beauty' of the classic `Times New Roman' and
`Arial/Helvetica' at 8 points.
Once a glyph's code has been executed, the scan-line converter converts
the fitted outline into a bitmap (or a pixmap with font-smoothing).
------------------------------------------------------------------------
III. Glyph metrics
1. Baseline, Pens and Layouts
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, etc). Moreover, to render
text, a virtual point, located on the baseline, called the pen
position, is used to locate glyphs.
Each layout uses a different convention for glyph placement:
o 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.
[Image]
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.
------------------------------------------------------------------
IMPORTANT NOTE:
The pen position is always placed on the baseline in TrueType,
unlike the convention used by some graphics systems, like Windows,
to always put the pen above the line, at the ascender's position.
------------------------------------------------------------------
o With vertical layout, glyphs are centered around the baseline:
[Image]
2. Typographic metrics and bounding boxes
A various number of face metrics are defined for all glyphs in a given
font. Three of them have a rather curious status in the TrueType
specification; they only apply to horizontal layouts:
o The ascent
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.
o The descent
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.
o The linegap
The distance that must be placed between two lines of text. The
baseline-to-baseline distance should be computed as
ascent - descent + linegap
if you use the typographic values.
The problem with these metrics is that they appear three times in a
single font file, each version having a slightly different meaning:
1. The font's horizontal header provides the ascent, descent and
linegap fields, which are used to express the designer's intents,
rather than the real values that may be computed from all glyphs
in the outline. These are used by the Macintosh font engine to
perform font mapping (i.e. font substitution).
2. The OS/2 table provides the usWinAscent and usWinDescent fields.
These values are computed for glyphs of the Windows ANSI charset
only, which means that they are wrong for any other glyph. Note
that usWinDescent is always positive (i.e. looks like `-descent').
3. The OS/2 table provides the typoAscender, typoDescender and
typoLinegap values, which hopefully concern the whole font file.
These are the correct system-independent values!
All metrics are expressed in font units. If you want to use any of the
two first versions of these metrics, the TrueType specification
contains some considerations and computing tips that might help you.
Other, simpler metrics are:
o The glyph's bounding box, also called bbox
This is an imaginary box that encloses any glyph (usually as
tightly as possible). It is represented by four fields, namely
xMin, yMin, xMax, and yMax, that can be computed for any outline.
In FreeType, their values can be in font units (if measured in the
original outline) or in 26.6 pixel units (if measured on scaled
outlines).
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/bitmapa. However, correct rendering of hinted
glyphs needs the preservation of important grid alignment on each
glyph translation/placement on the baseline, which is why FreeType
always returns the complete glyph outline.
Note also that the font's header contains a global font bounding
box in font units which should enclose all glyphs in a font. This
can be used to pre-compute the maximum dimensions of any glyph at
a given instance.
o The internal leading
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
internal_leading = ascent - descent - EM_size
o The external leading
This is another name for the linegap.
3. Bearings and Advances
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.
1. The left side bearing: a.k.a. bearingX
This is the horizontal distance from the current pen position to
the glyph's left bounding box edge. It is positive for horizontal
layouts, and most generally negative for vertical one.
2. The top side bearing: a.k.a. bearingY
This is the vertical distance from the baseline to the top of the
glyph's bounding box. It is usually positive for horizontal
layouts, and negative for vertical ones
3. The advance width: a.k.a. advanceX
This 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.
4. The advance height: a.k.a. advanceY
This 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.
5. The glyph width
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.
6. The glyph height
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.
7. The right side bearing
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. The FreeType library doesn't provide this
metric directly, as it isn't really part of the TrueType
specification. It can be computed simply as
advance_width - left_side_bearing - (xMax-xMin)
[Image]
[Image]
Finally, if you use `ABC widths' under Windows and OS/2, the following
relations apply:
A = left side bearing
B = width
C = right side bearing
A+B+C = advance width
4. The effects of grid-fitting
All these metrics are stored in font units in the font file. They must
be scaled and grid-fitted properly to be used at a specific instance.
This implies several things:
o First, a glyph program not only aligns the outline along the grid
pixel, it also processes the left side bearing and the advance
width. Other grid-fitted metrics are usually available in optional
TrueType tables if you need them.
o A glyph program may decide to extend or stretch any of these two
metrics if it has a need for it. This means that you cannot assume
that the fitted metrics are simply equal to the scaled one plus or
minus a liberal distance < 1 pixel (i.e., less than 64 fractional
pixel units). For example, it is often necessary to stretch the
letter `m' horizontally at small pixel sizes to make all vertical
stems visible, while the same glyph can be perfectly `square' at
larger sizes.
o Querying the fitted metrics of all glyphs at a given instance is
very slow, as it needs to load and process each glyph
independently. For this reason, some optional TrueType tables are
defined in the specification, containing pre-computed metrics for
specific instances (the most commonly used, like 8, 9, 10, 11, 12,
and 14 points at 96dpi, for example). These tables aren't always
present in a TrueType font.
If you don't need the exact fitted value, it's much faster to
query the metrics in font units, then scale them to the instance's
dimensions.
-----------------------------------------------------------------------
IMPORTANT NOTE:
Another very important consequence of grid-fitting is the fact that
moving a fitted outline by a non-integer pixel distance will simply
ruin the hinter's work, as alignments won't be preserved. The
translated glyph will then look `ugly' when converted to a bitmap!
In other words, each time you want to translate a fitted glyph outline,
you must take care of only using integer pixel distances (the x and
y offsets must be multiples of 64, which equals to 1.0 in the 26.6
fixed float format). If you don't care about grid-fitting (typically
when rendering rotated text), you can use any offset you want and use
sub-pixel glyph placement.
-----------------------------------------------------------------------
------------------------------------------------------------------------
IV. Text processing
This section demonstrates how to use the concepts previously defined to
render text, whatever the layout you use.
1. Writing simple text strings
We will start by generating a simple string with a Roman alphabet. The
layout is thus horizontal, left to right.
For now, we will assume all glyphs are rendered in a single target
bitmap. The case of generating individual glyph bitmaps, then placing
them on demand on a device is presented in a later chapter of this
section.
Rendering the string needs to place each glyph on the baseline; this
process looks like the following:
1. Place the pen to the cursor position. The pen is always located on
the baseline. Its coordinates must be grid-fitted (i.e. multiples
of 64)!
pen_x = cursor_x;
pen_y = cursor_y;
2. Load the glyph outline and its metrics. Using the flag
TTLOAD_DEFAULT will scale and hint the glyph:
TT_Load_Glyph( instance,
glyph,
glyph_index,
TTLOAD_DEFAULT );
TT_Get_Glyph_Metrics( glyph, &metrics );
TT_Get_Glyph_Outline( glyph, &outline );
3. The loader always places the glyph outline relative to the
imaginary pen position (0,0). You thus simply need to translate
the outline by the vector:
( pen_x, pen_y )
To place it on its correct position, you can use the call
TT_Translate_Outline( outline, pen_x, pen_y );
4. Render the outline in the target bitmap, the glyph will be
surimposed on it with a binary `or' operation (FreeType never
creates glyph bitmaps by itself, it simply renders glyphs in the
arrays you pass to it. See the API reference for a complete
description of bitmaps and pixmaps).
TT_Get_Outline_Bitmap( outline, &target_bitmap );
------------------------------------------------------------------
IMPORTANT NOTE:
If you don't want to access the outline in your code, you can also
use the API function TT_Get_Glyph_Bitmap() which does the same as
the previous lines:
TT_Get_Glyph_Outline( glyph, &outline );
TT_Translate_Outline( outline, x_offset, y_offset );
TT_Get_Outline_Bitmap( outline, &target_bitmap );
TT_Translate_Outline( outline, -x_offset, -y_offset );
is equivalent to:
TT_Get_Glyph_Bitmap( glyph,
x_offset,
y_offset,
&target_bitmap );
------------------------------------------------------------------
5. Now advance the pen to its next position. The advance is always
grid-fitted when the glyph was hinted:
pen_x += metrics.advance;
The advance being grid-fitted, the pen position remains aligned on
the grid.
6. Start over on item 2 until string completion. That's it!
2. Writing right-to-left and vertical text
Generating strings for different layouts is very similar. Here are the
most important differences.
o For right-to-left text (like Arabic)
The main difference here is that, as the advance width and left
side bearings are oriented against the flow of text, the pen
position must be decremented by the advance width, before placing
and rendering the glyph. Other than that, the rest is strictly
similar.
o For vertical text (like Chinese or Japanese)
In this case, the baseline is vertical, which means that the pen
position must be shifted in the vertical direction. You need the
vertical glyph metrics to do that (using the
TT_Get_Big_Glyph_Metrics() function).
Once you get these, the rest of the process is very similar. The
glyph outline is placed relative to an imaginary origin of (0,0),
and you should translate it to the pen position before rendering
it.
The big difference is that you must decrement pen_y, rather than
increment pen_x (this is for the TrueType convention of y oriented
upwards).
pen_y -= metrics.advance;
3. Generating individual glyph bitmaps and using them to render text
Loading each glyph when rendering text is slow, and it's much more
efficient to render each one in a standalone bitmap to place it in a
cache. Text can then be rendered fast by applying simple blit
operations on the target device.
To be able to render text correctly with the bitmaps, you must record
and associate with them its fitted bearings and advances. Hence the
following process:
1. Generate the bitmaps.
+ Load the glyph and get its metrics.
TT_Load_Glyph( instance,
glyph,
glyph_index,
TTLOAD_DEFAULT );
TT_Get_Glyph_Metrics( glyph, &metrics );
The bbox is always fitted when calling TT_Get_Glyph_Metrics()
on a hinted glyph. You can then easily compute the glyph's
dimension in pixels as:
width = (bbox.xMax - bbox.xMin) / 64;
height = (bbox.yMax - bbox.yMin) / 64;
NOTE 1:
The fitted bounding box always contains all the dropouts that
may be produced by the scan-line converter. This width and
height are thus valid for all kinds of glyphs).
NOTE 2:
If you want to compute the dimensions of a rotated outline's
bitmap, compute its bounding box with TT_Get_Outline_BBox(),
then grid-fit the bbox manually:
#define FLOOR(x) ((x) & -64)
#define CEILING(x) (((x)+63) & -64)
xMin = FLOOR(xMin);
yMin = FLOOR(yMin);
yMin = CEILING(xMax);
yMax = CEILING(yMax);
then compute width and height as above.
+ Create a bitmap of the given dimension, e.g.:
bitmap.width = width;
bitmap.cols = (width+7) & -8;
bitmap.rows = height;
bitmap.flow = TT_Flow_Up;
bitmap.size = bitmap.cols * bitmap.rows;
bitmap.buffer = malloc( bitmap.size );
+ Render the glyph into the bitmap.
Don't forget to shift it by (-xMin, -yMin) to fit it in the
bitmap:
/* Note that the offsets must be grid-fitted to */
/* preserve hinting! */
TT_Get_Glyph_Bitmap( glyph,
&bitmap,
-bbox.xMin,
-bbox.yMin );
2. Store the bitmap with the following values:
bearingX / 64 = left side bearing in pixels
advance / 64 = advance width/height in pixels
When your cache is set up, you can then render text using a scheme
similar to the ones describe in 1. and 2., with the exception that
now pen positions and metrics are expressed in pixel values. We
are done!
pen_x = cursor_x;
pen_y = cursor_y;
while ( glyph_to_render )
{
access_cache( glyph_index, metrics, bitmap );
blit_bitmap_to_position
( pen_x + bearingX,
pen_y (+ bearingY depending on orientation ) );
pen_x += advance;
}
4. Device-independent text rendering
The previously described rendering processes all align glyphs on the
baseline according to metrics fitted for the display's distance. In
some cases, the display isn't the final output, and placing the glyphs
in a device-independent way is more important than anything.
A typical case is a word processor which displays text as it should
appear on paper when printed. As you've probably noticed, the glyphs
aren't always spaced uniformly on the screen as you type them,
sometimes the space between an `m' and a `t' is too small, some other
it is too large, etc.
These differences are simply due to the fact that the word processor
aligns glyphs in an device-independent way, using original metrics in
font units to do it, then scale them as it can to display text on
screen, usually at a very smaller resolution than your printer's one.
Device-independence is a crucial part of document portability, and it
is very saddening to see that most professional word processors don't
do it correctly. For example, MS Word uses the fitted metrics of the
printer's resolution, rather than the originals in font units.
This is great to get sure that your text prints very well on your
printer, but it also implies that someone printing the exact same
document on a device with different output resolutions (e.g. bubble-jet
vs. laser printers) may encounter trouble.
As the differences in advances accumulate on one line, they can sum to
the width of one or more glyphs in extreme cases, which is enough to
`overflow' the automatic justification algorithm. This may add
additional lines of printed text, or even remove some. Moreover,
supplemental lines can produce unexpected page breaks and `blank'
pages. This can be extremely painful when working with large documents,
as this `feature' may require you to redesign completely your
formatting to re-print it.
In conclusion, if you want portable document rendering, never hesitate
to use and apply device-independent terms! For example, a simple way to
produce text would be:
1. Get a scale to convert from your device-independent units to 26.6
pixels.
2. Get another scale to convert from original font units to
device-independent units.
3. Perform pen placement and advances in device-independent units.
4. To render each glyph, compute the pen's rounded position, as well
as the rounded glyph left side bearing, both expressed in 26.6
pixels (don't use the fitted metrics). You will then be able to
place the glyph and/or blit its bitmap.
5. Kerning glyphs
An interesting effect that most people appreciate is kerning. It
consists of modifying the spacing between two successive glyphs
according to their outlines. For example, the letters `T' and a `y' can
be easily moved closer, as the top of the `y' fits nicely under the
`T's upper right bar.
To perform kerning, the TrueType specification provides a specific
table (its tag being `kern'), with several storage formats. This
section doesn't explain how to access this information; however, you
can have a look at the standard extension called `ttkern.h' which comes
with FreeType.
The kerning distance between two glyphs is a value expressed in font
units which indicates whether their outline can be moved together or
apart when one follows the other. The distance isn't reflexive, which
means that the kerning for the glyph pair (`T',`y') isn't the same as
the one for (`y',`T').
The value is positive when the glyphs must be moved apart, and negative
when they must be moved closer. You can implement kerning simply by
adding its scaled and rounded value to the advance width when moving
the pen position. Here an example for horizontal kerning:
#define ROUND( x ) ( (x + 32) & -64 )
scaled_kerning = kerning * imetrics.x_scale / 0x10000;
pen_x += metrics.advance + ROUND( scaled_kerning );
6. Rotated and stretched/slanted text
In order to produce rotated glyphs with FreeType, one must understand a
few things:
o The engine doesn't apply specific transformations to the glyphs it
loads and processes (other than the simpler resolution-base
scaling and grid-fitting). If you want to rotate glyphs, you will
have to load their outline, then apply the geometric
transformations that please you (a number of APIs are there to
help you to do it easily).
o Even if the glyph loader hints `straight' glyphs, it is possible
to inform the font and glyph programs that you're going to later
transform the resulting outlines. Two flags can be passed to the
bytecode interpreter:
+ The `rotated' flag indicates that you are going to rotate the
glyphs in a non-trivial direction (i.e., on neither of the
two coordinate axis). You are advised not to set it when
writing 90 degrees-rotated text for example.
+ The `stretched' flag indicates that you are going to apply a
transformation that will distort distances. While rotations
and symmetries keep distances constant, slanting and
stretching do modify them.
These flags can be interpreted by the glyph code to toggle certain
processings which vary from one font to the other. However, most of the
TrueType fonts that were tested with FreeType, if not all of them,
simply change the dropout-mode when any of these flags is set, and/or
disable hinting when rotation is detected. We advise you to never set
these flags, even when rotating text. For what it's worth, hinted
rotated text is no uglier than un-hinted one.
You can use the function TT_Set_Instance_Transform_Flags() to set them.
Then, rendering can be done with the following calls:
/* set the flags */
TT_Set_Instance_Transforms( instance,
rotated,
stretched );
/* load a given glyph */
TT_Get_Glyph_Outline( instance,
glyph,
index,
TTLOAD_DEFAULT );
/* access its outline */
TT_Get_Glyph_Outline( instance, &outline );
/* in order to transform it */
TT_Transform_Outline( outline, &matrix );
/* and/or */
TT_Translate_Outline( outline,
x_offset, y_offset );
/* to render it */
TT_Get_Outline_Bitmap( outline, &bitmap );
Here is an example, assuming that the following variables
TT_Matrix matrix; /* 2x2 matrix */
TT_Pos x_off, y_off; /* corrective offsets */
define a transformation that can be correctly applied to a glyph
outline which have been previously placed relative to the imaginary
point position (0,0) with bearings preserved. Rendering text can now be
done as follows:
1. Initialize the pen position; when rotating, it is extremely well
advised to use sub-pixel placement as you don't care about
hinting.
pen_x = cursor_x;
pen_y = cursor_y;
2. Transform the glyph as needed, then translate it to the current
pen position:
TT_Transform_Outline( outline, &matrix );
TT_Translate_Outline( outline,
pen_x + x_off,
pen_y + y_off );
(Note that the transformation offsets have been included in the
translation.)
3. Render the bitmap, as it has now been placed correctly.
4. To change the pen position, transform the vector (0,advance) with
your matrix, and add it:
vec_x = metrics.advance;
vec_y = 0;
TT_Transform_Vector( &vec_x, &vec_y, &matrix );
pen_x += vec_x;
pen_y += vec_y;
5. Start over at 2. until completion.
-----------------------------------------------------------------------
IMPORTANT NOTE:
Do not grid-fit the pen position before rendering your glyph when
rendering rotated text. If you do, your transformed baseline won't be
preserved on each glyph, and the text will look like it's `hopping'
randomly. This is particularly visible at small sizes.
Sub-pixel precision placement is very important for clean rotated text.
-----------------------------------------------------------------------
7. Font-smoothing, a.k.a. gray-levels rendering
The FreeType engine's scan-line converter (the component also called
the rasterizer) is able to convert a vectorial glyph outline into
either a normal bitmap, or an 8-bit pixmap (a.k.a. colored bitmaps on
some systems). This last feature is called gray-level rendering or
font-smoothing, because it uses a user-supplied palette to produce
anti-aliased versions of the glyphs.
Its principle is to render a bitmap which is twice as large than the
target pixmap, then simply filtering it using a 2x2 summation.
-----------------------------------------------------------------------
NOTE:
FreeType's scan-line converter doesn't use or need an intermediate
second bitmap. Rather, filtering is performed in a single pass during
the sweep (see the file `raster.txt' for more information about it).
-----------------------------------------------------------------------
You'll notice that, as with Windows 95, FreeType's rasterizer only
grays those parts of the glyph which need it, i.e., diagonals and
curves, while keeping horizontal and vertical stems straight `black'.
This greatly improves the legibility of text, while avoiding the
`blurry' look anti-aliased fonts typically found with Adobe's Type
Manager or Acrobat.
There are thus five available gray-levels, ranging from 0 to 4, where
level 0 and level 4 are the background and foreground colors,
respectively, and where levels 1, 2, 3 are intermediate. For example,
to render black text on a white background, one can use a palette like:
palette[0] = white (background)
palette[1] = light gray
palette[2] = medium gray
palette[3] = dark gray
palette[4] = black (foreground)
To set the engine's gray-level palette, simply use the API function
TT_Set_Raster_Palette() after initialization. It expects an array of
5 chars which will be used to render the pixmaps.
Note that the rasterizer doesn't create bitmaps or pixmaps. Rather, it
simply renders glyphs in the arrays you pass to it. The generated glyph
bitmaps are simply `or'-ed to the target (with 0 being the background
as a convention); in the case of pixmaps, pixels are simply written to
the buffer, in spans of four aligned bytes.
-----------------------------------------------------------------------
NOTE:
The raster isn't able to superpose `transparent' glyphs on the target
pixmap. This means that you should always call the API functions
TT_Get_Glyph_Pixmap() and TT_Get_Outline_Pixmap() with an empty map,
and perform the superposition yourself.
This can be more or less tricky, depending on the palette you are using
and your target graphics resolution. One of the components found in the
test directory, called `display.c', has large comments on the way it
implements it for the test programs. You are encouraged to read the
test program sources to understand how one can take advantage of font
smoothing.
Pixmap surimposition is too system-specific a feature to be part of the
FreeType engine. Moreover, not everybody needs it!
-----------------------------------------------------------------------
Finally, the question of sur-imposing anti-aliased colored text on any
texture, since being even more tricky, is left as an exercise to the
reader ;-) If this topic really interests you, the FreeType mailing
list may host some helpful enthusiasts ready to answer your questions.
Who knows :-)
8. Other interesting text processes
o Glyph substitution
Substitution is used to replace one glyph by another when some
specific condition is met in the text string. Its most common
examples are ligatures (like replacing the `f' followed by `i' by
the single glyph `fi' if available in the font), as well as
positional selection as performed in the Arabic script (for those
not aware of this, each letter of the Arabic alphabet can be
written differently according to its position on words: starting,
ending, intermediate, or isolated).
The base TrueType format doesn't define any table for glyph
substitution. However, GX, TrueType Open, and OpenType provide
(incompatible) extensions to perform it. Of course, it isn't
supported by the engine, but an extension could be easily written
to access the required tables.
[Support for TrueType Open is already partially available.]
o Justification
...
To be continued...
|