home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: SysTools
/
SysTools.zip
/
ft-beta.zip
/
freetype
/
docs
/
user.txt
< prev
Wrap
Text File
|
1997-10-06
|
32KB
|
863 lines
The FreeType Engine
Core Library User Guide
or
How to use the engine in your applications and font servers
by David Turner
---------------------------------------------------
Introduction
I. Basic Concepts:
1. Concepts
2. Handles
3. Conventions of use
4. Object classes
II. Extensions:
1. What is an extension?
2. Where to find them
3. Writing your own extension
Conclusion
----------------------------
Introduction:
This file has been written to present the FreeType core library to
would-be writers of applications and font servers. It first
describes the concepts on which the engine is based, then how to use
it to obtain glyph metrics, outlines and bitmaps.
The last part discusses the ability to add and use extensions to the
core library to get access to supplemental TrueType tables which are
not currently provided by the core engine. If you would like to
write your own extensions, read also the FreeType developer's guide.
I. Basic Concepts:
1. Concepts:
FreeType defines several kinds of structures, called "objects",
that are used to manage the various abstractions required to
access and display fonts.
In a care of good encapsulation, these objects are not directly
accessible from a client application. Rather, the user receives
a 'handle' for each object it queries and wants to use. This
handle is a stand-alone reference, it cannot be used like a
pointer to access directly the object's data.
2. Properties:
It is however possible to obtain and set object properties
through several functions of the API. For example, it is
possible to query a face object's properties with only a handle
for it, using the function TT_Get_Face_Properties().
Note that the data will be returned in a user-allocated
structure, but will also contain pointers addressing directly
some data found within the object.
A client application should never modify the data through these
pointers! In order to set new properties' values, the user must
always call a specific API to do so, as a certain number of
other related data might not appear in the returned structure
and imply various non-visible coherency and coercion rules.
NOTE:
A notable exception to this rule is the ability to move point
coordinates in a glyph container's outline through the pointers
returned by TT_Get_Glyph_Outline. However, this operation isn't
necessary for most programs.
3. Conventions of use:
o All API functions have their label prefixed by 'TT_', as well
as all external (i.e. client-side) types.
o To allow the use of FreeType's core engine in threaded
environments, nearly all API functions return an error code,
which is always set to 0 in case of success.
The error codes' type is TT_Error, and a listing of them is
given in the API reference (see "apiref.txt").
Some functions do not return an error code. Their result is
usually a value that takes a negative value in case of error
(this is used for functions where only one kind of error can
be reported, like an invalid glyph index).
An important note is that the engine should not leak memory
when returning an error, e.g. querying the creation of an
object will allocate several internal tables that will be
freed if a disk error occurs during a load.
o A handle is acquired through API functions labelled along the
names:
TT_Open_xxxx(), TT_New_xxxx()
where xxxx is the object's class (Face, Instance, etc.)
examples:
TT_Open_Face(), TT_Open_Collection(),
TT_New_Instance(), TT_New_Glyph()
o A handle is closed through an API labelled
TT_Close_xxxx() or TT_Done_xxxx()
where xxxx is the object's class (Face, Instance, etc.)
examples:
TT_Close_Face(), TT_Done_Instance(), TT_Done_Glyph()
o Properties are obtained through an API labelled
TT_Get_xxxx_yyyy()
where xxxx is the object's class, and yyyy its property
examples:
TT_Get_Face_Properties(), TT_Get_Instance_Metrics()
TT_Get_Glyph_Outline(), TT_Get_Glyph_Bitmap()
o Properties are set through an API labelled
TT_Set_xxxx_yyyy()
where xxxx is the object's class, and yyyy its property
examples:
TT_Set_Instance_Resolution(),
TT_Set_Instance_Pointsize()
4. Object Classes:
The following object classes are defined in this release of the
engine:
* The Face objects:
A face contains the data that is specific to a single
TrueType font file. It presents information common to all
glyphs and all point sizes like font-specific metrics and
properties.
You can open a face object by simply giving a pathname to
the TrueType file. You can later close (i.e. discard) the
face object.
You can also open a single face embedded in a TrueType
collection.
See also:
TT_Open_Face(), TT_Open_Collection(), TT_Close_Face(),
TT_Get_face_Properties()
* The Instance objects:
An instance is also called a 'pointsize' or a 'fontsize' in
some windowing systems. An instance holds the information
used to render glyphs on a specific device at a given point
size; it is always related to an opened face object.
For instance, if you want to generate glyphs for text from
the same typeface at 'sizes' of 10 and 12 points, all you
need is one face object, from which you'll create two
distinct instances.
A device is defined by its horizontal and vertical
resolution, usually specified in dots per inch (dpi). A
point size is a scaling number, given as _absolute_ values
in points, where 1 point = 1/72 inch.
The 'pixel' size, also known as the 'ppem' value (for Points
Per EM square) is computed from both the device resolution
and the point size. It determines the size of the resulting
glyph bitmaps on your screen or sheet of paper.
The default device resolution for any new instance is 96dpi
in both directions, which corresponds to VGA screens. The
default point size is 10pt. The high-level API allows you
to change this whenever you want for any given instance
object.
Note that closing a face object will automatically destroy
all its child instances (even though you can release them
yourself to free memory).
See also:
TT_New_Instance(), TT_Done_Instance(),
TT_Get_Instance_Metrics(), TT_Set_Instance_Resolution(),
TT_Set_Instance_Pointsize()
* The Glyph objects:
A Glyph object is a _container_ for the data that describes
any glyph of a given font. This means that it typically
holds:
- glyph metrics information, like bounding box or advance
width.
- outline arrays, sized large enough to hold any glyph from
the face. This size is extracted from the face's
internal 'maxProfile' table to optimize memory costs.
- other important parameters related to the 'fine'
rendering of the glyphs. This includes things like the
dropout-control mode used at low sizes.
- and it doesn't contain a bitmap or a pixmap!
A glyph object is used to load, hint and rasterize a single
glyph, as taken from the font file.
See also:
TT_New_Glyph(), TT_Done_Glyph(), TT_Get_Glyph_Metrics(),
TT_Get_Glyph_Outline(), TT_Get_Glyph_Bitmap(),
TT_Get_Glyph_Pixmap()
* The Character Map (CharMap) handle:
Glyphs can be indexed in a TrueType file in any order,
independent of any standard character encoding, like ASCII
or Unicode. For this reason, each file comes with one or
more character mapping tables, used to translate from one
specific encoding's charcodes to font glyph indexes.
There are many encoding formats, and each one can be
distinguished by two values:
- its platform ID
- its platform-specific encoding ID
Their values are defined in the TrueType specification and
won't be commented there.
It is possible to enumerate the charmaps provided by a
TrueType font and to use any of these to perform
translations.
The charmaps are loaded in memory only on demand to save the
space taken by the maps that are not needed on your system.
They are part of the face object, however.
This means that even though a charmap can be accessed
through a handle (obtained through the TT_Get_CharMap()
function), it isn't a stand-alone object. For example, you
never need to de-allocate it; this is done automatically by
the engine when its face object expires.
See also:
TT_Get_CharMap_Count(), TT_Get_CharMap_ID(),
TT_Get_CharMap(), TT_Char_Index().
II. Step-by-step Example:
Here is an example to show, step by step, how one client
application can open a font file, set one or several instances,
load any glyph, then render it to a bitmap.
a. Initialize the engine:
This is the first thing to do. You need to initialize the
engine through a call to TT_Init_FreeType(). This function will
set up a various number of structures needed by the library.
This allocates about 68kByte, of which 64kByte are dedicated to
the scan-line converter's "render pool", a workspace used for
bitmap generation. Note that even though this space is bounded,
the raster is able to render a glyph to any size or bitmap.
NOTE: You can reduce the size of this pool by modifying the
constant RASTER_RENDER_POOL in the file 'ttraster.c'.
Take care of never assigning a value smaller than 4kByte
however. A smaller pool will result in slower rendering
at large sizes.
b. Open the font file:
There are two ways to open a font face, depending on its file
format:
- If it's a TrueType file (ttf), you can simply use the API
named TT_Open_Face(), which takes the file's pathname as
argument, as well as the address of the returned face handle.
Check the returned error code to see if the file could be
opened and accessed successfully.
TT_Face face; /* face handle */
error = TT_Open_Face( "c:\work\ttf\wingding.ttf", &face );
if ( error )
{
printf( "could not open the file\n" );
...
}
- If the font is embedded in a TrueType collection (ttc), you
can use the API named TT_Open_Collection(), which takes also
the font's index within the collection's directory.
TT_Face face; /* face handle */
/* Load the collection's second face (index=1) */
error = TT_Open_Collection( "c:\work\ttf\whatever.ttc",
1, &face );
if ( error )
{
printf( "could not open the file\n" );
...
}
- Finally, when you do not know the number of faces embedded in
a TrueType collection, the following technique can be used:
o call TT_Open_Face() with the collection file's pathname.
This API recognizes collections automatically and always
return a handle for its first embedded font.
o get the face's properties through
TT_Get_Face_Properties(). These contain, among other
things, the maximum font collection index that can be used
in a call to the API TT_Open_Collection(), in its field
'max_Faces'.
TT_Face face; /* face handle */
TT_Face_Properties props; /* face properties */
/* open the first collection font */
error = TT_Open_Face( "c:\work\ttf\collection.ttc",
&face );
if ( error )
{
printf( "could not open the file\n" );
...
}
/* Get the face properties */
TT_Get_Face_Properties( face, &props );
/* Now print the number of faces */
printf( "there are %d faces in this collection file\n",
props->max_Faces + 1 );
c. Create an instance from the face object:
You must create an instance (a.k.a a pointsize) which contains
information relative to the target output device's resolutions
and a given point size.
o The instance object is created through TT_New_Instance():
TT_Instance instance;
error = TT_New_Instance( face, &instance );
if ( error )
{
printf( "could not create instance\n" );
...
}
TECHNICAL NOTE:
Creating a new instance executes its font program. This can
fail if the font is broken. Never assume that the error code
returned here is always 0.
o You must set the instance's properties to suit your needs.
They are simply its device resolutions, set through
TT_Set_Instance_Resolution(), and its point size, set through
TT_Set_Instance_Pointsize():
/* set the target horizontal and vertical resolution to */
/* 300dpi in each direction (typically for a printer) */
/* A fresh instance's default resolutions are 96dpi in */
/* both directions. */
error = TT_Set_Instance_Resolution( instance, 300, 300 );
if ( error )
{
printf( "could not set resolution" );
...
}
/* Now set the point size. Default is 10pt. */
error = TT_Set_Instance_Pointsize( instance, 12 );
if ( error )
{
printf( "could not set point size" );
...
}
TECH NOTE:
These calls may execute the font's prep program, which can
fail when the font is broken. Never assume that the error
codes returned there are always successful.
o You can also set the instance's transformation flags to tell
the glyph loading function that you're going to perform a
transformation (like rotation or slanting) on the glyph.
Note that the glyph loader doesn't perform the
transformation. It only informs the glyphs' hinting
instruction streams about these flags which may use it to
disable or enable various features (grid-fitting, drop-out
control etc).
TT_Set_Instance_Transforms( FALSE, TRUE );
to indicate that you're going to stretch, but not rotate,
this instance's glyphs. Default is, of course, both
FALSE.
d. Create a glyph container:
You need a glyph object to serve as a container for the glyphs
you want to load from the face. This is done simply by
TT_Glyph glyph; /* glyph object handle */
error = TT_New_Glyph( face, &glyph );
if ( error )
{
printf( "could not create glyph\n" );
...
}
Note that in spite of the fact that a glyph is always related
to a given face, the glyph isn't destroyed when its parent face
object is discarded, unlike instances.
e. Load the glyph:
The glyph loader is easily queried through TT_Load_Glyph().
This API function takes several arguments:
o an instance handle, to specify at which point size and
resolution the loaded glyph should be scaled and
grid-fitted.
o a glyph container, used to hold the glyph's data in memory.
Note that the instance and the glyph must relate to the
_same_ font file. An error would be produced immediately
otherwise.
o a glyph index, used to reference the glyph within the font
file. This index is not a platform specific character code.
Charmap objects are provided to translate from charcodes to
glyph indexes. All you need is to know your platform's
encoding IDs according to the TrueType specification, then
to obtain a charmap for it (if the font comes with it), and
finally to use it through TT_Char_Index() to get a glyph
index. We strongly recommend using the Unicode charmap
whenever possible.
o a load mode, indicating what kind of operations you need.
There are only two defined:
TTLOAD_SCALE_GLYPH:
When set, this flag indicates that the loaded glyph
will be scaled to fractional pixel coordinates (26.6).
If not, the coordinates will remain integer FUnits.
Please refer to the TrueType specification and the
FreeType header files for more details on the 26.6
format and other data types.
TTLOAD_HINT_GLYPH:
This flag is only in effect when the
TTLOAD_SCALE_GLYPH flag is set. It indicates that the
glyph must also be 'hinted', or 'grid-fitted' for
better display results.
You can 'or' the flags simply. As most applications will
require both flags to be set, the constant TTLOAD_DEFAULT is
defined as:
#define TTLOAD_DEFAULT (TTLOAD_SCALE_GLYPH | \
TTLOAD_HINT_GLYPH )
example:
error = TT_Load_Glyph( instance, glyph, 65, TTLOAD_DEFAULT );
if ( error )
{
printf("could not load the glyph\n");
...
}
f. Query glyph properties:
You're then able to query various glyph properties:
o The glyph metrics can be obtained through
TT_Get_Glyph_Metrics(). The data returned in the metrics
structure is:
- the glyph's left side bearing
- the glyph's advance width
- the glyph's bounding box
- its drop out control mode for better rendering
These values are expressed in 26.6 pixel units when the glyph
was loaded with scaling, or in FUnits if not.
o The glyph outline can be queried through
TT_Get_Glyph_Outline(). This can be useful to process the
points coordinates (e.g. applying stretching or rotation)
with functions like TT_Apply_Outline_Transform() or
TT_Apply_Outline_Translation(). Note that these functions do
not recompute a glyph's metrics after the transformation!
The outline's structure is described in the reference
"apiref.txt".
A bitmap or pixmap for the glyph can be queried with the APIs
TT_Get_Glyph_Bitmap() and TT_Get_Glyph_Pixmap(). These
functions take a glyph handle as an argument, as well as a
bitmap/pixmap description block and two offsets.
The target map is described through a TT_Raster_Map object,
which structure is defined in the reference (see
"apiref.txt"). The offsets are given in the same units as
the points coordinates and glyph metrics: 26.6 pixel units
for a scaled glyph, and FUnits for an unscaled one.
IMPORTANT TECH NOTE: **
***********************
When the glyph has been scaled and hinted, the offsets _must_
be multiples of 64 (i.e. integer pixel offsets). Otherwise,
you would simply ruin the grid fitting (which usually results
in ugly glyphs).
examples:
TT_Glyph_Metrics metrics;
TT_Glyph_Outline outline;
TT_Raster_Map bitmap;
TT_Get_Glyph_Metrics( glyph, &metrics );
TT_Get_Glyph_Outline( glyph, &outline );
/* set up the bitmap */
...
TT_Get_Glyph_Bitmap( glyph, &bitmap, 0, 0 );
g. When you're done:
o You can close any font face object with TT_Close_Face().
This call will automatically discard its child instances and
charmaps. However, the related glyph will remain in memory
and it is the user's responsibility not to use them for
further loads.
o You can also close the engine with a single call to
TT_Done_FreeType(). This will simply release _all_ objects
that were previously allocated, and close all font files.
III. Extensions:
1. What is an extension?
FreeType allows you to access a various number of TrueType tables,
as well as to render individual glyphs. However:
1 - it doesn't perform some high-level operations, like generating
a string text from many individual glyphs.
2 - it doesn't perform kerning (which can be needed by topic 1).
3 - it doesn't give access to all the defined TrueType tables,
especially the optional ones.
While point 1 is a feature that will never go into FreeType's core
engine, which goal is to provide easy access to font data and
rendering _individual_ glyphs, point 2 and 3 can be added to the
engine's features through extensions.
An extension is simply a small piece of code that extends the
engine's abilities and APIs. It is possible to extend the engine
without touching the core's source code, this is described in
chapter 3 below.
2. The two kinds of extensions:
There are basically two kinds of extensions, which require
different implementations.
a. API extensions:
An API extension is a set of functions that extend the FreeType
core API to give access to tables that are already loaded by the
engine, but not provided for now. An example of such data can
be:
- the horizontal metrics table (HMTX)
- the gasp table
This kind of extension is made of:
o an API extension header file, following the usage convention
introduced here (all labels prefixed with 'TT_'), and which
will be included by the clients which want to use the
extension. By convention, such header names begin with 'ftx'
(for FreeType eXtension).
examples: ftxgasp.h, ftxhtmx.h
o One or more functions used to give access to the tables that
are already loaded and managed by the engine. They usually
only copy pointers to the target structure given by the
client application since these structures are not accessible
through the 'normal' API.
b. engine extensions:
It can be sometimes useful to load and manage several tables
that are not considered by the core engine. These extensions
need to provide additional functions to fit into FreeType's
internal object management model, and are more sophisticated
than API extensions.
An example is given in this distribution to provide kerning
support (or more technically spoken, access to the kerning
tables found within the TrueType files). It is made of:
o An API extension providing new interfaces to the client
applications that need it. See the file "ftxkern.h".
o A specific implementation, providing services to create, load
and manage kerning tables as additional parts of a face
object. In the case of kerning, the directory of tables is
loaded when the face is opened, and tables themselves are
fetched from the file on demand. This implies several 'hooks'
in the core engine. See the files "ttkern.h" and "ttkern.c".
These are called 'engine extensions'.
3. Writing your own extensions:
As it was suggested earlier, writing an engine extensions is a
delicate process, as the additional code must follow a certain
number of design rules, presented in the FreeType developer
guide. There is also an extension writer's guide in the file
"extend.txt".
** NOTE **: The developer and extension writer guides are not
present in this beta. These documents will be part
of FreeType 1.0, however.
By writing your own extensions, it will be possible to support
more advanced TrueType formats like TrueType GX or OpenType in a
near future, without having to torture the engine core source at
each iteration.
If you encounter some difficulties when trying to create your
own extension, please read the core source file carefully, and
in the event that you may need changes that are not fitted to
the current extension mechanism, do not hesitate to contact the
authors at 'freetype-devel@lists.lrz-muenchen.de'
Conclusion:
This is the first version of this document, released in
FreeType's first public beta. We consider it as a "real" beta,
i.e., a functional version with a complete API, released to the
public to help us find bugs.
We invite you to read the test programs' source code to learn
more about the high-level interface.
The API is now considered frozen, and won't evolve in the future
unless we encounter important incoherencies which must be fixed.
Unlike the four previous alphas, we invite you to test and start
development of your own tools based on this API.
The engine's internals may still vary during this last phase, and
we may decide to make some of the provided extensions parts of
the core engine, but this should not affect the already existing
APIs.
We hope you have success and fun in using this engine. Much time
has been taken to make it one of the best in its genre. Remember
that it is not intended to be a complete font server or text
rendering library, but a pretty solid base for these kinds of
applications, as well as others.
We would like you to report the bugs you find, _after_ reading
the current bug report at our web page:
http://www.physiol.med.tu-muenchen.de/~robert/freetype.html
We have already many volunteers for the current projects, though
additional help can still be useful:
- an OS/2 font server based on FreeType
- an X11 font server based on FreeType
- TrueType support for the Wine Windows emulator
- ttf2bdf, a conversion tool for producing bitmaps from TTF
files
We also welcome volunteers to the following ideas:
- a text rendering library based on FreeType.
To provide various features that are not covered by
FreeType's core library, like string text rendering (with
or without kerning, with or without gray-scaling like
Win95), rotation, stretching, blitting, etc.
This library would be of great help for many environments
which cannot access a TrueType renderer. It can also be
the base of some extended font servers for some specific
systems.
- a font server for any graphical system that doesn't support
TrueType properly.
OS/2 and BeOS come to mind as systems that provide
mediocre TrueType support, which is not surprising when
one sees the fuzzy quality of the specs. Note that we
already have an OS/2 renderer on its way.
Some systems, like the AmigaOS or RISC OS, do not support
TrueType even though they provide scalable font services.
Adapting a font server from the FreeType source code
should be a relatively easy task.
There are many other systems that could benefit from a
royalty-free TrueType engine, and we encourage their
implementors to contact us and experiment with our engine.
- TrueType GX support (the font part of GX, of course)
Provided through extensions. We have no idea of the
difficulty of such support.
- OpenType support
Also through extensions. It would need a real Type1
engine!
Note from the author:
By the way, anyone wanting to rewrite the horrible Type1
renderer found in X11R5 would be MORE than welcomed!
This code is probably the worst design I've ever seen in
my life! It's slow, eats a lot of memory, uses stupid
algorithms, and the auto-hinter is a shame!
We're used to it because it 'works' more or less.
ISN'T IT TIME TO RAISE THE STANDARD OF FREE SOFTWARE ?!?
********************************************************
Resist bloat! Resist free junk!
PS:
I wouldn't like to offend mrz, author of T1lib, a
better derivative to the original renderer. I admit I
couldn't have done what he did, as bad code makes me
sick... but he uses the original engine, which still
requires about 150kByte to do much less that what we
do in about 55kByte, and renders poorly...
End of note
- Java / Java2D support
There are two possibilities:
- One could rewrite the engine entirely in Java. This
would be a hard task, and probably won't run on a JVM.
However, a native Java compiler could do wonders with
this code.
- A more practical thing would be to embed the engine in
a native Java class and integrate it to Java2D. This
would give excellent performance and good portability
(the engine is written in ANSI C).
- Alternatively, only the scan-line converter could be
kept in C for obvious performance reasons, while the
rest of the engine would be translated to Java. There
are delicate technical issues explaining why it is not
possible to use Java2D's current scan-line converter
to do this work.
- conversions and dumping tools for all kinds of formats and
platforms.
We thank you for your time and consideration.
David Turner, Robert Wilhelm, Werner Lemberg,
and all the FreeType enthusiasts...
--- End of user.txt ---