diff --git a/docs/design/build-system.html b/docs/design/build-system.html deleted file mode 100644 index b548b4566..000000000 --- a/docs/design/build-system.html +++ /dev/null @@ -1,910 +0,0 @@ - - -
- - - -
-
This document describes in great deatils the internals of FreeType 2. - It is a must read for porters and developers alike. Its purpose is to - - present the -
This document describes in great details the internals of the -FreeType 2.0 library. It is a must read for porters and developers alike. -Its purpose is to present the engine's objects, their roles and interactions. -It is assumed that the FreeType Glyph Conventions document -has been read. -- -We advise porters to also read the FreeType Porting Guide -after this document. Would-be hackers and maintainers are of course encouraged -to read the FreeType Coding Conventions document too. The -development of a new driver is described in more details in the FreeType -Driver HowTo document.
-
-- --1. Features (and what's new) :
- -FreeType 2.0 has a number of important new features that were -not found in the 1.x releases : -- -
-font-format independent API --It also features the following : -
FreeType 2.0 is able to support any kind of font format, be it fixed -or scalable, through the use of pluggable "font drivers". These drivers -can be added or replaced at run time, while applications use a new font -format-independent API. -advanced stream caching -
2.0 is able to control the number of concurrently opened streams when -using fonts. It is thus possible to open dozens or hundreds of font faces -without running out of system resources. -real reentrancy support -
It is now possible to use FreeType as a shared library with no static -data in a multi-threaded environment. The synchronization model has also -been simplified in order to make font driver writing easier. Of course, -you can build FreeType with no thread support to get a smaller library. -support for cubic beziers and 17-levels anti-aliasing -
The FreeType scan-line converter (a.k.a. raster) now supports cubic -bezier arcs seamlessly. It also provides a new anti-aliasing mode which -uses a palette of 17 levels of grays. -
performance improvements : --
The FreeType raster has been optimized, and the generation of anti-aliased -pixmaps is now 60% faster than in the 1.x release. Moreover, the TrueType -bytecode interpreter has been profiled and greatly optimised. -easier portability -
Porting and configuring FreeType is now much easier. A single file -must be provided for system-specific operations (like memory, i/o, thread -management), and a single configuration header is used to select the build -you need. -
-2. Architecture :
- -The engine is now split in several parts, which are : ---a. The base layer :
- -This part contains all the font-format independent features -of the engine which are : -- --
-- -computations/scaling
- -- -list processing
- -- -outline processing
- -- -scan-line converter
- -- -stream manager
- -- -base object classes
- -- -debugging & traces
- -- -high-level API functions
- -- -low-level system object (memory, i/o, threads)
--b. The font drivers :
- -Each font format is managed with the use of a single font driver -object. The base layer is able to manage several drivers, and these can -be easily added, removed or upgraded at runtime. Each driver has the following -features and functions : ---
-Note that FreeType 2.0 is a font service. Its purpose is to provide a unified -API for all kinds of fonts and extract individual glyph images and metrics. -However, it does not render text itself, as this operation is left to the -developer, or to higher-level libraries built on top of FreeType. Here -are a few features that are thus not implemented : -- -auto-check font format when opening a font resource (i.e. file)
- -- -access, load and/or extract all tables and data from the font file
- -- -grid-fit/hint the glyph outlines (in the case of scalable formats like -TrueType or Type1)
- -- -provide extensions to access font format-specific data and tables from -the font file
-1) Text string rendering --Note that features 1 through 3 should be provided by the SemTex library, -which may soon become part of the standard FreeType distribution.
2) Glyph bitmap/outline caching for improved performance -
3) Synthetic fonts (i.e. italicising, emboldening, underlining) -
4) Contextual glyph substitution and other advanced layout processes
-
-- --1. Objects :
- -They are several kinds of objects in FreeType, which can be -described as follows : -- -Base objects --Objects are defined in the files "base/freetype.h" and "base/ftobjs.h". -The former contains all the public object definitions usable by client -applications. The latter contains private definitions used by the rest -of the base layer and each font driver.
These objects do not relate directly to font data, but to the way it -is organised and managed. It is the basic core and provides functions that -are heavily used by each font driver. Examples are the resource objects, -used to describe font files, the system object used to manage low-level -system operations, or the raster object, used to convert vector outlines -into bitmaps or anti-aliased pixmaps. Most of the base objects are not -directly visible for client applications of FreeType. -Font objects -
The font objects directly model the data as it is found in font files. -The root classes implemented in the base layer like FT_Face, FT_Size, -FT_GlyphSlot, -must be derived in each font driver.-2. List management
- -The "base/ftlist.c" component a very simple doubly-linked -list facility which is used by the rest of the engine to create and process -lists, including iteration and finalisation. The definition of the list -node and functions are placed in the "base/freetype.h" to let -client applications access listed objects as they like. -- -The base list type is FT_List, which links nodes of type FT_ListNode -together. -
-3. Limited encapsulation
- -Unlike what happened in the 1.x releases, the FT_Face, -FT_Size, -FT_GlyphSlot and FT_CharMap types are no longer blind -pointers to opaque types. Rather, the corresponding structures are now -public (and defined in "base/freetype.h", see FT_FaceRec, -FT_SizeRec, -etc..) in order to let client applications read directly the various object -attributes they're interested in. --This breaks encapsulation of implementation, famed by OOP, but was chosen -because: -
--
- -- -it simplifies a lot the work of client applications and libraries which -don't need to perform a function call everytime they want to read one important -object attribute (nor does it force them to cache these attributes in their -own structures).
--
- -- -It reduces greatly the API, as many FT_Get_XXX functions are avoided.
--
- -- -Higher-level libraries are able to access data directly. When it -is used frequently, they don't need to cache it in their own structures.
--
- -- -It is possible to tightly link FreeType objects with higher-level ones, -in a clearer and more efficient way. This is very important when one wants -to write a C++ wrapper or a text rendering library on top of FreeType (actually, -both projects were performed in an earlier version of FreeType 2.0 which -featured classic encapsulation through get/set methods. The resulting code -was ugly and slow. Moving to a limited encapsulation approach simplified -so many things that the compiled code size was reduced by a factor of two -!).
--
-- -Finally, the API and font object structures were designed after the creation -of two scalable font drivers and one bitmap font driver. They are now very -stable and the public (visible) attributes are not going to change.
-
-
This section describes the FreeType base object classes : -- -
--1. System objects :
- -The system class is in charge of managing all low-level and -system-specific operations. This means simply memory management, i/o access -and thread synchronisation. It is implemented by the "ftsys.c" -component, whose source must be located in the configuration directory -when building FreeType. (e.g. "lib/arch/ansi/ftsys.c" for an ANSI -build, "lib/arch/unix/ftsys.c" for a Unix one, etc..). -- -Porting FreeType 2.0 really means providing a new implementation of -ftsys -(along with a few configuration file changes). Note however that its interface -is common to all ports, and located in "base/ftsys.h".
-2. Resources and Streams:
- -The concepts of files as storages, and files as streams has -been separated for FreeType 2.0. The "resource" concept was -introduced while the "stream" one has been redefined. Here -is how they work together : -- --
- -- -a "resource" is an object which models a file, seen as a storage. -There are several classes of resources, which differ usually in two ways -: the way their data is accessed by applications, and the way they're named -within the system.
-For example, when parsing files with the ANSI C library, data has to -be read (through fseek/fread) into intermediate buffers before it can be -decoded. This scheme is highly portable, but rather inefficient; when using -it, we'll describe the file as a disk-based resource. -
- -As most modern operating systems now provide memory-mapped files, which -allow direct access while improving performance and reducing memory usage. -Because data can be read directly in memory, we'll speak of a memory-based -resource in this case. For embedded systems (like printers, PDAs, etc..), -ROM-fonts fit into this category as well. -
Regarding naming, most systems use a string to name files in their storage -hierarchy. Though a typical pathname is an ASCII string ('c:\windows\fonts\times.ttf' -on Windows, '/home/fonts/times.ttf' on Unix), some OSes use different -schemes, varying from Unicode character strings to file i-node numbers. -These details are platform-specific and must be hidden to the rest of the -library in resource objects. -
A resource encapsulates the lowest details regarding a file, though -it should have NO STATE. Note that the nature or type of a resource (i.e. -disk or memory based) is important to the "stream" component only. The -rest of the library and font drivers work transparently from their implementation. -
Note also that it is perfectly possible to mix resources of distinct -natures in a single build
-
-Data can be extracted from streams through direct reads, or through the -use of frames. A frame models a run of contiguous bytes starting -from the current stream position, and of liberal size. -- -a "stream" is an object which is used to extract bytes from a resource. -Only resource objects can create streams, through its Open_Stream() -method. A stream has state, which typically consist of a file "cursor", -some intermediate buffers, a "current frame" and, of course, methods used -to extract the data from streams, resolving endianess and alignement issues.
-Methods exist to extract successive integers of any sizes, while resolving -endianess and alignement issues. Rather than a long rethorical explanation, -here's how frames are typically used : -
{ --This code does the following : -
… -
FT_Error error; -error = FT_Access_Frame( stream, 14 ); -
if (error) goto Fail; -val1 = FT_Get_Short(stream); -
val2 = FT_Get_Long(stream); -
val3 = FT_Get_Long(stream); -
val4 = FT_Get_Long(stream); -FT_Forget_Frame(stream); -
… -
}--The implementation of the resource class is located in the system component -(i.e. "arch/<system>/ftsys.c") and can thus be tailored -for a specific port of the engine. --
- -- - first, it "loads" the next 14 bytes from the current cursor position -into the stream's frame, using the FT_Access_Frame API. An error -is returned if, for example, less than 14 bytes are left in the stream -when the call occurs..
--
- -- - it extract four integers (one 16-bit short, three 32-bit longs) from -the frame using FT_Get_Short and FT_Get_Long. These function -increment the frame's cursor finally, it "releases" the stream's frame.
--
-- - Each stream has its own frame which can be accessed independently, -however, nested frame accesses are not allowed. Note also that the bytes -are effectively read from the stream on the call to FT_Access_Frame. -Any subsequent read will occur after these 14 bytes, even if less are extracted -through FT_Get_xxxx functions.
-A resource can be created through the FT_New_Resource API; -however this function only accepts an 8-bit pathname to name the target -font file, which may be inappropriate for systems using a different naming -scheme (e.g. UTF-16 pathname, i-node number, etc..). It's up to the porter -then to provide its own resource creation function (like. FT_New_UTF16_Resource, -for example) in its version of "ftsys.c". -
Note that FT_New_Resource will fail and return an error code -if the font file cannot be found, or when its font format isn't recognized -by one of the drivers installed in the library. The list or resources created -for a given library instance is thus the list of "installed font files". -
-3. Stream Manager :
- -As said before, resources do not bear states, while streams -do. Stream creation is also a very lengthy process, depending on the target -operating system (e.g. "fopen" is usually very slow). -- -Because a typical font driver will want to use a new stream on each -access to individual glyphs, being able to cache the most recently used -streams is a requirement in order to avoid considerable performance penalties. -
Stream caching is thus implemented in the "ftstream" component. -It maintains a simple LRU list of the least recently used streams. Each -stream in the cache is still opened and available for immediate processing. -When a resource is destroyed, the stream cache is parsed to remove all -related cached streams. -
Stream caching can also be disabled with a configuration macro when -using only ROM based resources (where stream opening is really quick). -It is implemented through a Stream Manager object (see ftstream.c). -
-4. Raster :
- -The raster is the component is charge of generating bitmaps -and anti-aliased pixmaps from vectorial outline definitions. It is also -sometimes called the scan-line converter. It has been completely rewritten -for FreeType 2.0 in order to support third-order bezier arcs, 17-levels -anti-aliasing (through 4x4 sub-sampling), improved performance, as well -as stand-alone compilation (in order to include it in other graphics package -without requiring the rest of the FreeType engine). -- -Because it was designed for easy re-use and embedded systems, the raster -is a rtaher 'unusual' piece of code, because it doesn't perform a single -memory allocation, nor contain any static or global variable. Rather, it -is up to client applications to allocate a raster object in their own heap -or memory space. -
Each raster object also needs a rather large block of memory called -its render pool. The pool is used during rendering (and only during it) -in order to perform the scan-line conversion. Because it accesses and manages -data directly within the pool, the raster yelds impressive performance -as well as bounded memory consumption. It can also automatically decompose -large requests into smaller individual sub-tasks. -
Finally, it never creates bitmaps or pixmaps, but simply renders into -them (providing clipping too). These must be described to the raster with -the help of a FT_Raster_Map structure (a very simple bitmap/pixmap -descriptor). -
Note that when rendering anti-aliased pixmaps, the raster doesn't use -an intermediate bitmap buffer, as filtering is part of the scan-line conversion -process. -
-5. Library objects :
- -A library object models a single instance of the FreeType engine. -This is useful when FreeType is compiled as a shared object (DLL), as it -can then be used by several applications, each with its own resources and -objects. -- -The FT_Library type is an opaque handle to a library object. -Such an object is created through a call to FT_Init_FreeType. -Once you don't need it anymore, one can destroy a library object through -FT_Done_FreeType. -
Note that in reentrant builds, several threads can access a single library -object concurrently. Such a build can be chosen by switching one configuration -macro in the file 'arch/<system>/ftconfig.h'
-6. Driver objects :
- -A driver object models an instance of a given font driver, -i.e. an element of FreeType code in charge of handling a given font format, -like TrueType, Type1, FNT, PCF, etc.. -- -Each library object contains a given set of driver objects when it is -created through FT_Init_FreeType, this set being determined at compile -time (see the file 'base/ftapi.c'). However, removing or adding drivers -is possible at run-time, in order to make upgrades easy.
-7. Diagram
- -This diagram show the object relationships for the sole base -layer. The library object is the root of the object graph : --- - -It can be read as follows : -
--
- -- -Each library object has one system, one raster and one stream manager objects. -These objects can only belong to one given library.
--
- -- -Each library contains one list of 0 or more resources, as well as one list -of 0 or more driver objects.
--
- -- -Each stream manager holds a bounded list ("0..n" where 'n' is the stream -cache's size) of stream objects. Each stream is related to one given resource -object. Each resource may be related to zero or one stream.
--
-- -Each resource is related to one driver object. A driver is related to 0 -or more resources.
-
-
Font objects are used to directly map the information found -in font files into several categories : -- -
--1. Face objects :
- -Face objects are used to model individual font faces. They -encapsulate data which isn't related to a specific character size, or a -specific glyph or glyph set. Usually, this means : -- --
-A face is created from a resource object, with the FT_New_Face -API. Each driver contains a list of opened face objects for the resources -it manages. When a driver is removed or destroyed, all its child faces -are discarded automatically with it.- -the font face's family and style names (e.g. "Palatino" + "Regular")
- -- -some flags indicating which kind of font this is (scalable or fixed ? fixed-width -or proportional ? horizontal or vertical ? etc…)
- -- -the number of glyphs, charmaps and eventually fixed character sizes (for -bitmap formats) found in the font face.
- -- -for scalable formats, some important metrics like the ascender, descender, -global font bounding box, maximum advance width, etc.. expressed in notional -font/grid units (as well as the number of units on the EM grid).
--2. Size objects :
- -Size objects are used to model a given character dimension -for a given device resolution (which really means a given character pixel -dimensions). -- -Each size object is created from a parent face object. The object can -be reset to new dimensions at any time. Each face object holds a list of -all its child sizes, these are destroyed automatically when the face object -is discarded. -
The metrics contains metrics, expressed in pixels, for the ascender, -descender, maximum advance width, etc.. -
-3. Glyph Slot objects :
- -A glyph slot is a container where one can load individual glyphs, -be they in vector of bitmap format. Each slot also contains metrics for -the glyph it contains. -- -Each face object contains one or more glyph slot object : the first -glyph slot is created automatically with its parent face, and it is possible -to add new glyph slots (this is rarely used outside of debugging purposes). -
-4. CharMap objects :
- -A charmap object is a sort of dictionary whose task is to translate -character codes in a given character encoding (like ShiftJIS, Unicode, -ANSI, etc..) into glyph indexes in a given font face. -- -A face object contains one or more charmap objects. All charmap objects -are created when the parent face is created, though they're not directly -visible to client applications (rather, they can be enumerated through -FT_Get_First_CharMap and FT_Get_Next_CharMap, or more simply picked adequately -with FT_Find_CharMap for a set of given encodings). -
-5. Diagram
- -The following diagram illustrates the relationships between -font objects : --- - -Which can be read as : -
--
- -- -each resource may have zero or more child face objects "opened" for it. -The number of faces is bounded by the number of font faces within the font -resource.
--
- -- -each driver holds a list of all the faces opened for the resources it manages. -When the driver is removed, its child faces are discarded automatically.
--
- -- -each face object has one single parent resource, and one single driver.
--
- -- -each face has one or more charmaps, and one or more glyph slots
--
- -- -each face holds a list of zero or more child size objects
--
-- -each charmap, glyph slot and size is related to one given parent face. -These objects are destroyed automatically when the parent face is discarded.
-
-
A font driver is added to a given library object through the -FT_Add_Driver -API. This function receives a structure known as a FT_DriverInterface, -which describes the driver's basic properties. -- -The FT_DriverInterface contains a set of function pointers -used for the base FreeType functionalities. However, each driver can also -provide a font-format-specific extended interface to allow client applications -to use more advanced features. -
--1. Common Interface
- -The structure of FT_DriverInterface is rather simple, -and defined in "base/ftdriver.h". It must be well known by any -developer who wants to write a new driver for the engine. We advise reading -the FreeType Driver HowTo as well as the source code of existing -drivers. Source comments.- --2. Driver-specific extensions
- -The field of the FT_DriverInterface structure is a -typeless pointer to a format-specific interface. This extended interface -is usually a structure containing function pointers as well as other kind -of information related to the driver. --It is assumed that client applications that wish to use the driver-specific -extensions are able to #include the relevant header files to understand -the format-specific interface structure.
This section relates to the configuration of the FreeType library. -By configuration, we mean selection of build options as well as the choice -of font drivers to be used for each new library object. -- - - diff --git a/docs/design/io-frames.html b/docs/design/io-frames.html deleted file mode 100644 index a5c6de7cd..000000000 --- a/docs/design/io-frames.html +++ /dev/null @@ -1,343 +0,0 @@ - - - - - -
--1. Configuration files :
- -A single file is used to configure the FreeType base engine. -As it is considered system-specific, it is located in the architecture -directories of the library, under the name "arch/<system>/ftconfig.h". -Note that the same directory should also contain a platform-specific implementation -of "ftsys.c". -- -The configuration files is a simple C header which is included by the -engine's sources during compilation. It is not included in "freetype.h", -and hence doesn't need to be copied when installing the FreeType headers -on your system. -
It is made of a series of #define or #undef statements, which are used -to select or turn off a specific option. Each option is documented with -heavy comments, and some of them are explained below.
-2. Building and Makefiles :
- -FreeType 2.0 is more complex than its 1.x release. In order -to facilitate maintenance, as well as ease considerably the writing of -new font drivers, only GNU Make is supported with FreeType 2.0. -However, it is possible to use any compiler, as well as any object or library -prefix (.o, .obj, .a, .lib etc..) with them. -- -To build FreeType 2.0, one has to be in the library directory, then -invoke its platform-specific makefile. For a Unix system, this would be -: -
--The system-specific Makefile located in 'arch/<system>' -is a tiny file used to define several variables. It then includes the file -freetype2/lib/Makefile.lib, -which contains all the gory details about library compilation. The system-specific -Makefile can be very easily modified to accomodate a new compiler/platform -(see the comments within one of these files). -% cd freetype2/lib --
% make -f arch/unix/Makefile -where 'make' is really GNU Make !
Each font driver is located in a directory like "freetype2/lib/drivers/<formatdir>". -For example, the TrueType driver is located in "drivers/truetype". -Each driver directory must contain a Makefile which will be included -by Makefile.lib. The former is used to define and build driver -object files. -
-
-- --3. Make options :
- -The base layer, as well as each font driver, are made up of -several C sources. Traditionally, one compiles each source (i.e. '.c' -file) into an object ('.o' or '.obj') file, and all of -them are grouped into a library file (i.e. '.a' or '.lib'). -- -By default, FreeType takes a slightly different approach when it comes -to compiling each part of the engine. Usually, a single tiny source is -compiled, which includes all other component sources. This results in a -single object files, with the benefits or reduced code size, usually better -compilation as well as a drastic reduction of the number of symbols exported -by the library. Of course, it is made possible through the use of specific -declaration macros in the FreeType source (see the definition of LOCAL_DEF -and LOCAL_FUNC in ftconfig.h for details). -
For a concrete example, see the source code in "base/ftbase.c" -which generates the whole base layer in a single object file. The same -build process is applied to font drivers, in order to generate one single -object file per given font format (e.g. truetype.o, type1.o, -etc..). -
Compiling the library and drivers in "normal" mode is possible, through -the use of the 'multi' target (which really means « multiple -objects »). For example, calling : -
% make -f arch/ansi/Makefile multi-Will build the FreeType library by compiling each source file to an individual -object, then linking them together. You'll notice that the library is significantly -bigger in this case. Creating a shared dll from a 'multi' build is certainly -a very poor idea, as this will export a huge quantity of symbols that aren't -useful to any client application.-4. Adding a driver at compile time
- -A driver can be included very easily in the build process by -including its Makefile in Makefile.lib. For example, -the TrueType driver is simply included with the following lines (see Makefile.lib): -- -# TrueType driver rules -- -
# -
include $(DRIVERS_DIR)/truetype/Makefile
Where DRIVERS_DIR really is "freetype2/lib/drivers", -though this can be redefined. You can, of course specify a different path -if you want to place your driver sources in another location. -Note that this only adds the driver's object files to the generated -library file. A few more steps are needed to make your FT_Library -objects use the driver. They consist in modifying the file "base/ftinit.c", -whose sole purpose is to define the set of driver objects that are to be -created with each new library object. -
-5. Adding a driver at run time
- -New driver objects can be added at run-time through the FT_Add_Driver -API. This function takes a handle to an existing library object, as well -as a pointer to a given driver interface. This interface is used to create -a new driver object and register it within the library. -- -Similarly, a single driver can be removed from a library anytime through -FT_Remove_Driver. -This will automatically discard the resources and face objects managed -by the driver.
-6. Custom library objects :
- -Finally, it is possible to build custom library objects. You -need to pass a handle to a valid FT_System object to the FT_Build_Library -API. The function will return a handle to the new fresh library object. -Note that the library has no registered drivers after the call, developers -have to add them by hand with FT_Add_Driver. -- -It is thus possible to create two distinct library objects with distinct -FT_System -implementations in the same session, which can be useful for debugging -purpose.
-
- - - - Introduction -- -This document explains the concept of I/O frames as used in the - FreeType 2 source code. It also enumerates the various functions and - macros that can be used to read them. - -It is targeted to FreeType hackers, or more simply to developers who - would like a better understanding of the library's source code. - -- - - I. What frames are -- -Simply speaking, a frame is an array of bytes in a font file that is - `preloaded' into memory in order to be rapidly parsed. Frames are useful - to ensure that every `load' is checked against end-of-file overruns, and - provides nice functions to extract data in a variety of distinct - formats. - -But an example is certainly more meaningful than anything else. The - following code - - -- error = read_short( stream, &str.value1 ); - if ( error ) goto ... - - error = read_ulong( stream, &str.value2 ); - if ( error ) goto ... - - error = read_ulong( stream, &str.value3 ); - if ( error ) goto ...- - - can easily be replaced with - - -- error = FT_Access_Frame( stream, 2 + 4 + 4 ); - if ( error ) goto ... - - str.value1 = FT_Get_Short( stream ); - str.value2 = FT_Get_ULong( stream ); - str.value3 = FT_Get_ULong( stream ); - - FT_Forget_Frame( stream );- - - Here, the call to
Each
There are several advantages to using frames: - -
- - - II. Accessing and reading a frame with macros -- -By convention in the FreeType source code, macros are able to use two - implicit variables named error and stream. This is - useful because these two variables are extremely often used in the - library, and doing this only reduces our typing requirements and make the - source code much clearer. - -Note that error must be a local variable of type
- The macro used to access a frame is - ( error = FT_Access_Frame( stream, _size_ ) ) - != FT_Err_Ok- - - Similarly, the macro - FT_Forget_Frame( stream )- - - Extracting integers can be performed with the
(Note that an Offset is an integer stored with 3 bytes on - the file.) - -All this means that the following code - - -- error = FT_Access_Frame( stream, 2 + 4 + 4 ); - if ( error ) goto ... - - str.value1 = FT_Get_Short( stream ); - str.value2 = FT_Get_ULong( stream ); - str.value3 = FT_Get_ULong( stream ); - - FT_Forget_Frame( stream );- - - can be simplified with macros: - - -- if ( ACCESS_Frame( 2 +4 + 4 ) ) goto ... - - str.value1 = GET_Short(); - str.value2 = GET_ULong(); - str.value3 = GET_ULong(); - - FORGET_Frame();- - - Which is clearer. Notice that error and stream - must be defined locally though for this code to work! - -- - - III. Alternatives -- -It is sometimes useful to read small integers from a font file without
- using a frame. Some functions have been introduced in FreeType 2 to
- do just that, and they are of the form For example, Thus, reading a single big-endian integer is shorter than using a frame - for it. - -Note that there are also macros - FT_Read_xxx( stream, &error ), error != FT_Err_Ok- - - and can be used as in - - -- if ( READ_UShort( variable1 ) || - READ_ULong ( variable2 ) ) - goto Fail;- - - if error and stream are already defined - locally. - - |
-
- Note that the only system-specific part of the library is a file - named "ftsystem.c", normally located in the directory - "freetype2/config/<system>" where <system> designates - your platform (e.g. "config/ansi/ftsystem.c" or - "config/unix/ftsystem.c"). -
-
-
- -
-
void* user | // a user-defined pointer. This is zero by default - |
void* (*alloc)( FT_System, int) | // a function used to allocate a new block - |
void* (*realloc)( FT_System, int, int, void* ) | // a function used to reallocate a given block - |
void (*free)( FT_System, void*) | // a function used to release a given block - |
- You'll notice that:
-
- - All current implementations of "ftsystem.c" provide a very simple - implementation of the FT_Memory interface by calling directly the - standard C alloc, realloc and free. -
- The FreeType source code never invokes directly the function pointers. Rather, - it calls FT_Alloc, FT_Realloc and FT_Free functions - which are defined in "freetype2/src/base/ftobjs.c". These will not be - discussed here. -
- If you want to use your own memory allocator rather than the one provided - by your build of FreeType, follow these simple steps:
-
-
-
-
- Notice that you don't need to recompile FreeType 2 to use your own memory - manager !!. -
-
-
- -
- A stream models the array of bytes found in a font file. FreeType 2 separates - streams into two families :
-
-
-
- Note that a stream's nature only determines how FreeType accesses its content, not - the way it is effectively stored. For example, in the case of a compressed font file, - one implementation may choose to uncompress the font in memory, then provide a memory - based stream to access it. Another one might chose a disk based stream to perform - on-the-fly decompression of the font data. Similarly, the font file can be stored - on a local disk, or obtained from a network. This will be completely transparent to - FreeType. -
- The stream structure is: -
-
char* base | for memory-based streams, the address - of its first byte. - - |
ulong size | the stream's size in bytes. - - |
ulong pos | the current stream position in the file - - |
descriptor | a union field used to hold either an - integer file descriptor or pointer. - This field is not used by FreeType - itself, but is left to implementations - of "ftsystem" - |
pathname | a union field that can hold either an - integer or pointer. It is not used by - FreeType itself, but is left to - implementations. These can put the - file pathname's during debugging for - example. - - |
read | a pointer to a function used to seek the - stream and/or read a run of bytes from it. - - |
close | a pointer to a function called when the - stream is closed. - - |
memory | a FT_Memory object, which is used - to allocate frames for disk-based streams. - This field is set and used by FreeType. - - |
cursor | a pointer in memory used when accessing - frames. This is set and used by FreeType. - - |
limit | a pointer in memory used when accessing - frames. This is set and used by FreeType. - |
- - The following important things must be noticed here:
-
- -
- -
- Each FT_Face needs its own stream to access font data. The most common - way to create a new FT_Stream object is to call the function - FT_New_Face. This function takes a file pathname argument that - is used to create a new stream object. -
- This is possible because each implementation of "ftsystem.c" provides - a function called FT_New_Stream which takes a file pathname and a - FT_Stream pointer as an argument. The function simply opens the file - and initialises the stream structure accordingly. It is called by FT_New_Face - to create the face's stream object. -
- A stream is only closed when the face is destroyed through FT_Done_Face. - Its close field function will then be called. Note that the function should - never destroy the FT_Stream. -
- - -
- There are cases where it is interesting to provide your own stream to create - a new face object, rather than rely on the default implementation. For example, - a filepathname, which is a C string, might not be useful on a system where files - are named with a UTF-16 string or via an i-node number of memory address (for ROM files). -
- For this purpose, the FT_Open_Face is defined. It simply takes a - FT_Stream pointer as its second argument, instead of a file pathname (the - stream must be allocated and initialised by you, so be careful). -
- Actually, the only thing that FT_New_Face does is create a new stream - through FT_New_Stream, then call FT_Open_Face to create the - face with it. -
- Note also that you can use the function FT_New_Memory_Face to create - a new font face for a memory-based font file, whose address and size can be passed - as arguments. The function automatically creates the corresponding memory-based - stream and use it to create the face. -
- -
-
- -
-
-
- - - - Introduction -- -This short tutorial will teach you how to use the FreeType 2 - library in your own applications. - -- - - 1. Header files -- -To include the main FreeType header file, simply say - - -- #include <freetype/freetype.h>- - - in your application code. Note that other files are available in the - FreeType include directory, most of them being included by - "freetype.h". They will be described later in this - tutorial. - -- - - 2. Initialize the library -- -Simply create a variable of type FT_Library named, for - example, library, and call the function - FT_Init_FreeType() as in - - -- #include <freetype/freetype.h> - - FT_Library library; - - ... - - { - ... - error = FT_Init_FreeType( &library ); - if ( error ) - { - ... an error occurred during library initialization ... - } - }- - - This function is in charge of the following: - -
As you can see, the function returns an error code, like most others - in the FreeType API. An error code of 0 always means that - the operation was successful; otherwise, the value describes the error, - and library is set to NULL. - -- - - 3. Load a font face -- -- a. From a font file -- -Create a new face object by calling FT_New_Face. - A face describes a given typeface and style. For example, - "Times New Roman Regular" and "Times New Roman Italic" correspond to - two different faces. - - -- FT_Library library; /* handle to library */ - FT_Face face; /* handle to face object */ - - error = FT_Init_FreeType( &library ); - if ( error ) { ... } - - error = FT_New_Face( library, - "/usr/share/fonts/truetype/arial.ttf", - 0, - &face ); - if ( error == FT_Err_Unknown_File_Format ) - { - ... the font file could be opened and read, but it appears - ... that its font format is unsupported - } - else if ( error ) - { - ... another error code means that the font file could not - ... be opened or read, or simply that it is broken... - }- - - As you can certainly imagine, FT_New_Face opens a font - file, then tries to extract one face from it. Its parameters are - -
To know how many faces a given font file contains, simply load its - first face (use face_index=0), then see the value of - face->num_faces which indicates how many faces are embedded - in the font file. - -- b. From memory -- -In the case where you have already loaded the font file in memory, - you can similarly create a new face object for it by calling - FT_New_Memory_Face as in - - -- FT_Library library; /* handle to library */ - FT_Face face; /* handle to face object */ - - error = FT_Init_FreeType( &library ); - if ( error ) { ... } - - error = FT_New_Memory_Face( library, - buffer, /* first byte in memory */ - size, /* size in bytes */ - 0, /* face_index */ - &face ); - if ( error ) { ... }- - - As you can see, FT_New_Memory_Face() simply takes a - pointer to the font file buffer and its size in bytes instead of a - file pathname. Other than that, it has exactly the same semantics as - FT_New_Face(). - -- c. From other sources (compressed files, network, etc.) -- -There are cases where using a file pathname or preloading the file - in memory is simply not enough. With FreeType 2, it is possible - to provide your own implementation of i/o routines. - -This is done through the FT_Open_Face() function, which - can be used to open a new font face with a custom input stream, select - a specific driver for opening, or even pass extra parameters to the - font driver when creating the object. We advise you to refer to the - FreeType 2 reference manual in order to learn how to use it. - -Note that providing a custom stream might also be used to access a - TrueType font embedded in a Postscript Type 42 wrapper. - -- - - 4. Accessing face content -- -A face object models all information that globally describes - the face. Usually, this data can be accessed directly by dereferencing - a handle, like - -
For a complete listing of all face properties and fields, please read - the FreeType 2 API Reference. - - - - - 5. Setting the current pixel size -- -FreeType 2 uses "size objects" to model all - information related to a given character size for a given face. - For example, a size object will hold the value of certain metrics - like the ascender or text height, expressed in 1/64th of a pixel, - for a character size of 12 points. - -When the FT_New_Face function is called (or one of its - cousins), it automatically creates a new size object for - the returned face. This size object is directly accessible as - face->size. - -NOTA BENE: a single face object can deal with one or more size - objects at a time, however, this is something that few programmers - really need to do. We have thus have decided to simplify the API for - the most common use (i.e. one size per face), while keeping this - feature available through additional fuctions. - -When a new face object is created, its size object defaults to the - character size of 10 pixels (both horizontally and vertically) for - scalable formats. For fixed-sizes formats, the size is more or less - undefined, which is why you must set it before trying to load a - glyph. - -To do that, simply call FT_Set_Char_Size(). Here is an - example where the character size is set to 16pt for a 300x300 dpi - device: - - -- error = FT_Set_Char_Size( - face, /* handle to face object */ - 0, /* char_width in 1/64th of points */ - 16*64, /* char_height in 1/64th of points */ - 300, /* horizontal device resolution */ - 300 ); /* vertical device resolution */- - - You will notice that: - -
This function computes the character pixel size that corresponds to - the character width and height and device resolutions. However, if you - want to specify the pixel sizes yourself, you can simply call - FT_Set_Pixel_Sizes(), as in - - -- error = FT_Set_Pixel_Sizes( - face, /* handle to face object */ - 0, /* pixel_width */ - 16 ); /* pixel_height */- - - This example will set the character pixel sizes to 16x16 pixels. - As previously, a value of 0 for one of the dimensions means - "same as the other". - -Note that both functions return an error code. Usually, an error - occurs with a fixed-size font format (like FNT or PCF) when trying to - set the pixel size to a value that is not listed in the - face->fixed_sizes array. - -- - - 6. Loading a glyph image -- -- a. Converting a character code into a glyph index -- -Usually, an application wants to load a glyph image based on its - character code, which is a unique value that defines the - character for a given encoding. For example, the character - code 65 represents the `A' in ASCII encoding. - -A face object contains one or more tables, called - charmaps, that are used to convert character codes to glyph - indices. For example, most TrueType fonts contain two charmaps. One - is used to convert Unicode character codes to glyph indices, the other - is used to convert Apple Roman encoding into glyph indices. Such - fonts can then be used either on Windows (which uses Unicode) and - Macintosh (which uses Apple Roman, bwerk). Note also that a given - charmap might not map to all the glyphs present in the font. - -By default, when a new face object is created, it lists all the - charmaps contained in the font face and selects the one that supports - Unicode character codes if it finds one. Otherwise, it tries to find - support for Latin-1, then ASCII. - -We will describe later how to look for specific charmaps in a face. - For now, we will assume that the face contains at least a Unicode - charmap that was selected during FT_New_Face(). To convert a - Unicode character code to a font glyph index, we use - FT_Get_Char_Index() as in - - -- glyph_index = FT_Get_Char_Index( face, charcode );- - - This will look the glyph index corresponding to the given - charcode in the charmap that is currently selected for the - face. If charmap is selected, the function simply returns the - charcode. - -Note that this is one of the rare FreeType functions that do not - return an error code. However, when a given character code has no - glyph image in the face, the value 0 is returned. By convention, - it always correspond to a special glyph image called the missing - glyph, which usually is represented as a box or a space. - -- b. Loading a glyph from the face -- -Once you have a glyph index, you can load the corresponding glyph - image. Note that the glyph image can be in several formats. For - example, it will be a bitmap for fixed-size formats like FNT, FON, or - PCF. It will also be a scalable vector outline for formats like - TrueType or Type 1. The glyph image can also be stored in an - alternate way that is not known at the time of writing this - documentation. - -The glyph image is always stored in a special object called a - glyph slot. As its name suggests, a glyph slot is simply a - container that is able to hold one glyph image at a time, be it a - bitmap, an outline, or something else. Each face object has a single - glyph slot object that can be accessed as - face->glyph. - -Loading a glyph image into the slot is performed by calling - FT_Load_Glyph() as in - - -- error = FT_Load_Glyph( - face, /* handle to face object */ - glyph_index, /* glyph index */ - load_flags ); /* load flags, see below */- - - The load_flags value is a set of bit flags used to - indicate some special operations. The default value - FT_LOAD_DEFAULT is 0. - -This function will try to load the corresponding glyph image - from the face. Basically, this means that: - -
The field glyph->format describe the format - used to store the glyph image in the slot. If it is not - ft_glyph_format_bitmap, one can immediately - convert it to a bitmap through FT_Render_Glyph, - as in: - - -- error = FT_Render_Glyph( - face->glyph, /* glyph slot */ - render_mode ); /* render mode */ -- - - The parameter render_mode is a set of bit flags used - to specify how to render the glyph image. Set it to 0 to render - a monochrome bitmap, or to ft_render_mode_antialias to - generate a high-quality (256 gray levels) anti-aliased bitmap - from the glyph image. - -Once you have a bitmap glyph image, you can access it directly - through glyph->bitmap (a simple bitmap descriptor), - and position it through glyph->bitmap_left and - glyph->bitmap_top. - -Note that bitmap_left is the horizontal distance from the - current pen position to the left-most border of the glyph bitmap, - while bitmap_top is the vertical distance from the - pen position (on the baseline) to the top-most border of the - glyph bitmap. It is positive to indicate an upwards - distance. - -The next section will detail the content of a glyph slot and - how to access specific glyph information (including metrics). - -- c. Using other charmaps -- -As said before, when a new face object is created, it will look for - a Unicode, Latin-1, or ASCII charmap and select it. The currently - selected charmap is accessed via face->charmap. This - field is NULL when no charmap is selected, which typically happens - when you create a new FT_Face object from a font file that - doesn't contain an ASCII, Latin-1, or Unicode charmap (rare - stuff). - -There are two ways to select a different charmap with FreeType 2. - The easiest is when the encoding you need already has a corresponding - enumeration defined in <freetype/freetype.h>, as - ft_encoding_big5. In this case, you can simply call - FT_Select_CharMap as in: - -- error = FT_Select_CharMap( - face, /* target face object */ - ft_encoding_big5 ); /* encoding.. */ -- - Another way is to manually parse the list of charmaps for the - face, this is accessible through the fields - num_charmaps and charmaps - (notice the 's') of the face object. As you could expect, - the first is the number of charmaps in the face, while the - second is a table of pointers to the charmaps - embedded in the face. - -Each charmap has a few visible fields used to describe it more - precisely. Mainly, one will look at - charmap->platform_id and - charmap->encoding_id that define a pair of - values that can be used to describe the charmap in a rather - generic way. - -Each value pair corresponds to a given encoding. For example, - the pair (3,1) corresponds to Unicode. Their list is - defined in the TrueType specification but you can also use the - file <freetype/ftnameid.h> which defines several - helpful constants to deal with them.. - -To look for a specific encoding, you need to find a corresponding - value pair in the specification, then look for it in the charmaps - list. Don't forget that some encoding correspond to several - values pair (yes it's a real mess, but blame Apple and Microsoft - on such stupidity..). Here's some code to do it: - - -- FT_CharMap found = 0; - FT_CharMap charmap; - int n; - - for ( n = 0; n < face->num_charmaps; n++ ) - { - charmap = face->charmaps[n]; - if ( charmap->platform_id == my_platform_id && - charmap->encoding_id == my_encoding_id ) - { - found = charmap; - break; - } - } - - if ( !found ) { ... } - - /* now, select the charmap for the face object */ - error = FT_Set_CharMap( face, found ); - if ( error ) { ... }- - - Once a charmap has been selected, either through - FT_Select_CharMap or FT_Set_CharMap, - it is used by all subsequent calls to - FT_Get_Char_Index(). - - -- d. Glyph Transforms: -- -It is possible to specify an affine transformation to be applied - to glyph images when they're loaded. Of course, this will only - work for scalable (vectorial) font formats. - -To do that, simply call FT_Set_Transform, as in: - -- error = FT_Set_Transform( - face, /* target face object */ - &matrix, /* pointer to 2x2 matrix */ - &delta ); /* pointer to 2d vector */ -- - This function will set the current transform for a given face - object. Its second parameter is a pointer to a simple - FT_Matrix structure that describes a 2x2 affine matrix. - The third parameter is a pointer to a FT_Vector structure - that describe a simple 2d vector. - -Note that the matrix pointer can be set to NULL, (in which case - the identity transform will be used). Coefficients of the matrix - are in 16.16 fixed float units. - -The vector pointer can also be set to NULL (in which case a delta - of (0,0) will be used). The vector coordinates are expressed in - 1/64th of a pixel (also known as 26.6 fixed floats). - -NOTA BENE: The transform is applied every glyph that is loaded - through FT_Load_Glyph. Note that loading a glyph bitmap - with a non-trivial transform will produce an error.. - -- - - 7. Accessing glyph image data -- -Glyph image data is accessible through face->glyph. - See the definition of the FT_GlyphSlot type for more details. - As stated previously, each face has a single glyph slot, where - one glyph image at a time can be loaded. Each time - you call FT_Load_Glyph(), you erase the content of the glyph - slot with a new glyph image. - -Note however that the glyph slot object itself doesn't change, only - its content, which means that you can perfectly create a "shortcut" to - access it as in - - -- { - /* shortcut to glyph slot */ - FT_GlyphSlot glyph = face->glyph; - - for ( n = 0; n < face->num_glyphs; n++ ) - { - ... load glyph n ... - ... access glyph data as glyph->xxxx - } - }- - - The glyph variable will be valid until its parent - face is destroyed. Here are a few important fields of the - glyph slot: - -
- 8. Rendering glyph outlines into bitmaps -- -You can easily test the format of the glyph image by inspecting the - face->glyph->format variable. If its value is - ft_glyph_format_bitmap, the glyph image that was loaded is a - bitmap that can be directly blit to your own surfaces through your - favorite graphics library (FreeType 2 doesn't provide bitmap - blitting routines, as you may imagine :-) - -If the format is ft_glyph_format_outline or something else, - the library provides a means to convert such glyph images to bitmaps - through what are called rasters. - -On the other hand, if the image is a scalable outline or something - else, FreeType provides a function to convert the glyph image into a - pre-existing bitmap that you will handle to it, named - FT_Get_Glyph_Bitmap. Here's a simple example code - that renders an outline into a monochrome bitmap: - - -- { - FT_GlyphSlot glyph; - - ... load glyph ... - - glyph = face->glyph; /* shortcut to glyph data */ - if ( glyph->format == ft_glyph_format_outline ) - { - FT_Bitmap bit; - - /* set-up a bitmap descriptor for our target bitmap */ - bit.rows = bitmap_height; - bit.width = bitmap_width; - bit.pitch = bitmap_row_bytes; - /* render into a mono bitmap */ - bit.pixel_mode = ft_pixel_mode_mono; - bit.buffer = bitmap_buffer; - - /* render the outline directly into the bitmap */ - error = FT_Get_Glyph_Bitmap( face, &bit ); - if ( error ) { ... } - } - }- - - You should note that FT_Get_Glyph_Bitmap() doesn't - create the bitmap. It only needs a descriptor, of type - FT_Bitmap, and writes directly into it. - -Note that the FreeType scan-converter for outlines can also generate - anti-aliased glyph bitmaps with 128 level of grays. For now, it is - restricted to rendering to 8-bit gray-level bitmaps, though this may - change in the future. Here is some code to do just that: - - -- { - FT_GlyphSlot glyph; - - ... load glyph ... - - glyph = face->glyph; /* shortcut to glyph data */ - if ( glyph->format == ft_glyph_format_outline ) - { - FT_Bitmap bit; - - /* set-up a bitmap descriptor for our target bitmap */ - bit.rows = bitmap_height; - bit.width = bitmap_width; - bit.pitch = bitmap_row_bytes; - /* 8-bit gray-level bitmap */ - bit.pixel_mode = ft_pixel_mode_gray; - /* MUST be 128 for now */ - bit.grays = 128; - bit.buffer = bitmap_buffer; - - /* clean the bitmap - IMPORTANT */ - memset( bit.buffer, 0, bit.rows*bit.pitch ); - - /* render the outline directly into the bitmap */ - error = FT_Get_Glyph_Bitmap( face, &bit ); - if ( error ) { ... } - } - }- - - You will notice that - -
|