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 @@ - - - - - - - FreeType 2 Internals - I/O Frames - - - - - - -
-

FreeType 2.0 Build System

- -
-

-© 2000 David Turner (david@freetype.org)
-© 2000 The FreeType Development Team -(devel@freetype.org) -

- -
- -


- -

Table of Content

- -
-

Introduction

-

I. Features & Background

- -

II. Overview of the build process

- -

III. Build setup details

-

IV. Library compilation details

- - -
- -
-

Introduction:

- -

This document describes the new build system that was introduced - with FreeType 2.

- -


-
-

I. Features and Background:

- -

The FreeType 2 build system is a set of Makefiles and sub-Makefiles that - are used to build the library on a very large variety of systems easily. - One of its main features are the following:

- -
-

1. Convenience, not Requirement

-
    -

    Even though the build system is rather sophisticated, it simply is a - convenience that was written simply to allow the compilation of the - FreeType 2 library on as many platforms as possible, as easily as - possible. However, it is not a requirement and the library can be - compiled manually or in a graphical IDE without using it, with minimal - efforts

    - -

    (for more information on this topic, see the BUILD - document that comes with your release of FreeType, in its Detailed - Compilation Guide section).

    -
- -
-

2. Compiler and platform independence

-
    -

    The FreeType 2 build system can be used with any compiler, on any platform. - It is independent of object file suffix, executable file suffix, directory - separator convention (i.e. "/" or "\"), and compiler flags for path - inclusion, macro definition, output naming, ansi compliance, etc..

    - -

    Supporting a new compiler is trivial and only requires writing a minimal - configuration sub-makefile that contains several Makefile variables - definitions that are later used by the rest of the build system. This is - described in details later in the document.

    -
- -
-

3. Uses GNU Make

-
    -

    The build system works exclusively with GNU Make. Reason - is that it is the only make utility that has all the features required to - implement the build system as described below. Moreover, it is already - ported to hundreds of various distinct platforms and is widely and - freely available.

    - -

    It also uses the native command line shell. You thus - don't need a Unix-like shell on your platform. - For example, FreeType 2 already compiles on Unix, Dos, Windows - and OS/2 right "out of the box" (assuming you have GNU Make - installed).

    - -

    Finally, note that the build system is specifically designed - for gnu make and will fail with any other make tool. We have - no plans to support a different tools, as you'll rapidly - understand by reading this document or looking at the sub-makefiles - themselves.

    -
- -
-

4. Automatic host platform detection

-
    -

    When you launch the build system for the first time, by simply invoking - GNU make in the top-level directory, it automatically tries to detect - your current platform in order to choose the best configuration - sub-makefile available. It then displays what it found. If everything - is ok, you can then launch compilation of the library, by invoking make - a second time.

    - -

    The following platforms are currently automatically detected:

    -
      -
    • Dos (plain-dos, windows in Dos mode, or Dos session under OS/2) -
    • Windows 95, 98 + Windows NT (a.k.a win32) -
    • OS/2 -
    • Unix (uses Autoconf/Automake) -
    - -

    Note that adding support for a new platform requires writing a minimal - number of very small files, and simply putting them in a new sub-directory - of freetype2/config.

    -
- -
-

5. User-selectable builds

-
    -

    The platform auto-detection rules try to setup the build for a default - compiler (gcc for most platforms), with default build options - for the library (which normally is - "all features enable, no debugging"), as well as the default - list of modules (which is "all modules in freetype2/src")

    - -

    There are cases where it is important to specify a different compiler, - different build options or simply a different module list. The FreeType 2 - build system is designed in such a way that all of this is easily possible - from the command line, without having to touch a single file. - The latter is crucial when dealing with projects that need specific - builds of the library without modifying a single file from the FreeType - distribution.

    - -

    The exact mechanism and implementation to do this is described later in - this document. It allows, for example, to compile FreeType with any of - the following compilers on Win32: gcc, Visual C++, Win32-LCC.

    -
- -
-

6. Robustness

-
- - -

7. Simple Module Management

-
    -

    FreeType 2 has a very modular design, and is made of a core - base layer that provides its high-level API as well as - generic services used by one or more modules. - - Most modules are used to support a specific font format (like TrueType - or Type 1), and they are called font drivers. However, some of - them do not support font files directly, but rather provide helper - services to the font drivers.

    - -

    FreeType 2 is designed so that adding modules at run-time is possible - and easy. Similarly, we expect many more modules to come in the near - future and wanted a build system that makes such additions to the - source package itself dead easy. - - Indeed, all source code (base + modules) is located in the - freetype2/src directory hierarchy. And the build system is - capable of re-generating automatically the list of known modules - from the contents of this directory. Hence, adding a new font driver - to the FreeType sources simply requires to:

    - -
      -
    • Add a new sub-directory to freetype2/src -

    • Re-launch the build system

      -
    - -

    There is thus no need to edit a source file

    -
- -


- -

II. Overview of the build process(es):

- -

Before describing in details how the build system works, it is essential - to give a few examples of how it's used. This section presents - what's the build process is to the typical developer:

- -

Compiling the library is normally done in two steps: the first one - configures the build according to the current platform and possible - additional parameters, while the second simply compiles the library with - the information gathered in the configuration step.

- -
-

1. Build Setup

- -
-

a. Default build setup

-
    -

    To configure the build, simply invoke gnu make from the top-level FreeType - directory. This will launch a series of rules that will detect your current - host platform, and choose a configuration file for you. It will then display - what it found. For example, here's the output of typing the command "make" - on a win32 platform (assuming this calls GNU make):

    - -
    
    -    C:\FreeType> make
    -
    -    FreeType build system -- automatic system detection
    -
    -    The following settings are used:
    -
    -      platform                     win32
    -      compiler                     gcc
    -      configuration directory      ./config/win32
    -      configuration rules          ./config/win32/w32-gcc.mk
    -
    -    If this does not correspond to your system or settings please remove the file
    -    'config.mk' from this directory then read the INSTALL file for help.
    -
    -    Otherwise, simply type 'make' again to build the library.
    -
    -    C:\FreeType>
    -
    - -

    Note that this step copies the selected configuration file (here - ./config/win32/w32-gcc.mk) to the current directory, under - the name config.mk. This file contains data that is used - to drive the library compilation of the second step. It correspond to - the platform and compiler selected by the auto-detection phase.

    - -

    Note that you can re-generate the config.mk file anytime - by invoking make setup whenever you need it, even when the file is - already present in the current directory.

    - -

    Finally, if your platform is not correctly detected, the build system will - display and use configuration information for the virtual "ansi" platform. -

    -
-
-

b. Selecting another build configuration

-
    -

    You may not be really satisfied by the configuration file selected by the - auto-detection routines. Typically, you might be using a compiler that is - not the default one for your platform. It is however possible to re-launch - the build setup phase with an additional argument, used to specify a - different compiler/config file. For example, you can type the following - commands on Win32 systems:

    - -

    -

    make setup

    -
    -

    re-run the platform detection phase, and select the default compiler for it. - On Win32, this is gcc.

    -
    -

    make setup visualc

    -
    -

    re-run the platform detection phase, and select a config file that - corresponds to the Visual C++ compiler

    -
    -

    make setup lcc

    -
    -

    re-run the platform detection phase, and select a config file that - corresponds to the Win32-LCC compiler

    -
    -

    - -

    Note that a specific configuration is selected with a command that - looks like : make setup compiler, - where the compiler keywords depends on the platform. - Moreover, each one of them corresponds to a specific configuration - sub-makefile that is copied as config.mk in the current - directory.

    -
- - -
-

2. Library compilation

- -

Once you're satisfied with the version of config.mk that - has been copied to your current directory, you can simply re-invoke - gnu make with no arguments. The top-level Makefile will - automatically detect the config sub-makefile in the current directory, - and use it to drive the library compilation. The latter can be seen - as a series of different steps decribed here:

- -
    -
  • Compiling the ftsystem component

      - It encapsulates all low-level operations (memory management + - i/o access) for the library. Its default version, located in - ./src/base/ftsystem.c uses the ANSI C library but - system-specific implementations are also available to - improve performance (e.g. memory-mapped files on Unix). -

    - -
  • Compiling the base layer and optional components

      - They provide the library's high-level API as well as various useful - routines for client applications. Many features of the base layer can - be activated or not depending on a configuration file named - ftoption.h -

    - -
  • Compiling the modules

      - Each module is used to support a specific font format (it is then - called a font driver), or to provide helper services to - the drivers (e.g. the auto-hinter). They are all located in - sub-directories of ./src, like ./src/truetype, - ./src/type1. -

    - -
  • Compiling the ftinit component

      - This one is in charge of implementing FT_Init_FreeType, - the library initialisation routine. It also selects what modules - are activated when a new library instance is created. -

    -
-


- -

II. Details of the build setup.

- -

When the top-level Makefile is invoked, it looks for a - file named config.mk in the current directory. - If this file is found, it is used directly to build the library - (skip to Section III for details then).

- -

Otherwise, the file ./config/detect.mk is included - by the top-level Makefile and parsed. Its purpose is to drive the - platform-detection phase, by:

- -
    -
  • Defining the PLATFORM variable, which indicates - what the currently detected platform is. It is initially - set to the default value "ansi". -

    - -
  • Searching for a detect.mk file in all - subdirectories of ./config. - Each such file is included and parsed. Each of these files must - try to detect if the host platform is a system it knows - about. If so, it changes the value of the PLATFORM variable - accordingly.

    - -
  • Copying the selected configuration submakefile to the current directory - under the name config.mk.

    -
-

This is illustrated by the following graphics :

-

- -

- -

Each system-specific detect.mk works as follows:

-
    -
  • It checks that the value of PLATFORM is currently set - to ansi, which indicates that no platform was detected - for now. If this isn't true, it doesn't do anything

    - -
  • Otherwise, it runs a series of test to see wether it is on a - system it knows about. Here are a few examples of tests:

    - -

    - Unix - -

    checks for a file named /sbin/init, and runs, when it found - it, a 'configure' script to generate the relevant config sub-makefile

    -
    - Dos - -

    checks for the COMSPEC environment variable, then tries to - run the "ver" command on the current shell to check that there - is a "Dos" substring in its output; if not, it tries to find the - substring "MDOS\COMMAND" in COMSPEC, which indicates - a Dos session under OS/2.

    -
    - Win32 - -

    if the environment variable OS is defined and has the value - Windows_NT, or if COMSPEC is defined and the - "ver" returns a string that contains Windows in it, - we're on a Win32 system.

    -
    -

    - -
  • It sets the value of PLATFORM to a new value corresponding - to its platform.

    - -
  • It then tries to select a configuration - sub-makefile, depending on the current platform and any optional - make target (like "visualc" or "devel", etc..). Note that it can - even generate the file, as on Unix through Autoconf/Automake.

    - -
  • It copies the selected configuration sub-makefile to the current - directory, under the name config.mk -

- -

If one wants to support a new platform in the build system, it simply needs - to provide:

- -
    -
  • A new subdirectory, in ./config, with a file named - detect.mk in it, containing relevant checks for the system. - -
  • One or more configuration sub-makefiles that will get copied to - config.mk at build setup time. You can use the one in - ./config/ansi/config.mk as a template. -
- -

Similary, supporting a new compiler on an existing system simply means:

-
    -
  • Writing a new config sub-makefile that contains definitions used to - specify the compiler and flags for the build. - -
  • Change your ./config/system/detect.mk to recognize - a new optional build target that will copy your new config sub-makefile - instead of the default one. -
- - -


-

III. Details of the library compilation.

- -

When the top-level Makefile is invoked, it looks for a file named - config.mk in the current directory. If one is found, it - defines the BUILD_FREETYPE variable, then includes and parses it. - The structure of this file is the following: -

- -
    -
  • First, it defines a series of Make variables that describe - the host environment, like the compiler, compilation flags, - object file suffix, the directory where all object files are - placed, etc..

    - -
  • If BUILD_FREETYPE is defined, it includes the file - ./config/freetype.mk, which is in charge of - defining all the rules used to build the library object files. - (The test is useful to use the config.mk file to - compile other projects that rely on FreeType 2, like its - demonstration programs).

    - -
  • Finally, it defines the rule(s) used to link FreeType 2 object files - into a library file (e.g. libfreetype.a, freetype.lib, - freetype.dll, ...). Unfortunately, the command line interface of link tools is - a lot less standardized than those of compilers, which - explains why this rule must be defined in the system-specific - config.mk.

    -
- -

The following is an explanation of what ./config/freetype.mk - does to build the library objects: -

- -

a. Include paths

-
    -

    To avoid namespace pollution, the freetype directory prefix - is used to include all public header files of the library. This means - that a client application will typically use lines like:

    - -
    
    -    #include <freetype/freetype.h>
    -    #include <freetype/ftglyph.h>
    -
    - -

    to include one the FreeType 2 public header files. freetype.mk - uses a variable named INCLUDES to hold the inclusion - paths list, and thus starts by adding ./include to it. However, - nothing prevents - -

    freetype.mk uses a variable named INCLUDES - to hold directory inclusion-path to be used when compiling the library. - It always add ./include to this variable, which means - -

- -

b. Configuration header files:

-
    -

    Three header files used to configure the compilation of the - FreeType 2 library. Their default versions are all located in the - directory ./include/freetype/config/, even though - project specific versions can be provided on a given build, as - described later:

    - -
      -

      #include <freetype/config/ftoption.h>

        - This file contains a set of configuration macro definitions that - can be toggled to activate or deactivate certain features of the - library. By changing one of these definitions, it is possible to - compile only the features that are needed for a specific - project. Note that by default, all options are enabled. -

        - You might need to provide an alternative version of ftoption.h - for one of your own projects. -

      - -

      #include <freetype/config/ftconfig.h>

        - This file includes ftoption.h but also contains some automatic - macro definitions used to indicate some important system-specific - features (e.g: word size in bytes, DLL export prefix macros, etc..). -

        - You shouldn't normally need to change or provide an alternative - version of this file. -

      - - -

      #include <freetype/config/ftmodule.h>

        - This file is very special, as it is normally machine-generated, and - used by the ftinit component that is described below. To - understand it, one must reminds that FreeType 2 has an extremely - modular design and that it's possible to change, at run-time, - the modules it's using. The ftmodule.h file simply contains - the list of modules that are registered with each new instance of - the library. -

        - Note that the file can be re-generated automatically by invoking - make setup from the top-level directory. The re-generated - list contains all the modules that were found in subdirectories of - ./src. -

      -
    - -

    Note that we strongly advise you to avoid modifying the config files - within the FreeType 2 source directory hierarchy. Rather, it's possible - to specify alternative versions through the help of a build-specific - include path that is include before ./include in the inclusion - path.

    - -

    For example, imagine that your platform, named foo, needs a - specific version of ftoption.h -

- -

a. Compiling the ftsystem component:

-
    -

    FreeType 2 encapsulates all low-level operations (i.e. memory management - and i/o access) within a single component called ftsystem. - Its default implementation uses the ANSI C Library and is located - in ./src/base/ftsystem.c.

    - -

    However, some alternate, system-specific, implementations of - ftsystem are provided with the library in order to support more - efficient and advanced features. As an example, the file - ./config/unix/ftsystem.c is an implementation that - uses memory-mapped files rather than the slow ANSI fopen, - fread and fseek, boosting performance significantly.

    - -

    The build system is thus capable of managing alternate implementations - of ftsystem

    -
- -

b. Compiling the base layer and optional components:

-
    -

    The high-level API of the library is provided by a component called the - base layer, whose source is located in ./src/base. This - directory also contains one or more components that are optional, i.e. - that are not required by the library but provide valuable routines to - client applications.

    - -

    The features of the base library and other components are selected through - a single configuration file named - ./include/freetype/config/ftoption.h. It contains a list - of commented configuration macro definitions, that can be toggled to - activate or de-activate a certain feature or component at build time.

    - -

    For example, the code in ./src/base/ftdebug.c will be compiled - only if one of these two macros are defined in ftoption.h: - FT_DEBUG_LEVEL_ERROR or FT_DEBUG_LEVEL_TRACE

    -
- -

c. Compiling the modules:

-
    -

    Once the base layer is completed, the build system starts to compile each - additional module independently. These are simply defined as all source - code located in a sub-directory of ./src that contains a file - named rules., for example: - src/sfnt, src/truetype, src/type1, ...

    - -

    The rules. file simply contains directives used by the - build system to compile the corresponding module into a single object - file.

    -
- -

d. Compiling the ftinit component:

-
    -

    The file ./src/base/ftinit.c is special because it is used - to implement the library initialisation function FT_Init_FreeType. -

    -
- -

Typically, you will end up with all object files, as well as the - corresponding library file, residing in the freetype2/obj - directory.

- - -

1. Purpose of the configuration sub-makefile

- -

2. Managing module dependencies

- -

3.

- -


- -

IV. Managing the modules list

- -


- The build system features some important points, which are all detailed - in the following sections:

-

    -
  • Automatic host platform detection
    - The first time the top Makefile is invoked, it will - run a series of rules to detect your platform. It will then - create a system-specific configuration sub-Makefile in the - current directory, called config.mk. You can now - invoke the top Makefile a second time to compile the - library directly. -

    - The configuration sub-makefile can be regenerated any time - by invoking "make setup", which will re-run the - detection rules even if a config.mk is already present. -

    - - -

  • User-selectable builds
    -

    - - - -

  • Automatic detection of font drivers
    - FreeType is made of a "base" layer that invokes several - separately-compiled modules. Each module is a given - font driver, in charge of supporting a given font format. -

    - The list of font drivers is located in the file - "freetype2/config/system/ftmodule.h", however - it can be regenerated on-demand. Adding a new module to the - FreeType source tree is thus as easy as:

    -

      -
    • create a new directory in "freetype2/src" and - put the new driver's source code and sub-makefiles there. -

      - -

    • invoke the top Makefile with target - "modules" (as in "make modules"), - as this will automatically regenerate the list of - available drivers by detecting the new directory and - its content. -
    -

    -

- - -


- -

II. Host Platform Detection

-
    - When the top-level Makefile is invoked, it looks for a - file named config.mk in the current directory. If this - file is found, it is used to build the library - (see Section III). -

    - Otherwise, the file freetype2/config/detect.mk is included - and parsed. Its purpose is to:

    -

      -
    • Define the PLATFORM variable, which indicates - what is the currently detected platform. It is initially - set to the default value "ansi". -

      - -

    • It searches for a detect.mk file in all - subdirectories of freetype2/config. Each such - file is included and parsed. Each of these files must - try to detect if the host platform is a system it knows - about. If so, it changes the value of the PLATFORM - accordingly. -
    -

    - This is illustrated by the following graphics :

    -

    - -
    -

    - Note that each system-specific detect.mk is in charge - of copying a valid configuration makefile to the current directory - (i.e. the one where make was invoked), depending on the - current targets. For example, the Win32 detect.mk will - be able to detect a "visualc" or "lcc" target, - as described in section I. Similarly, the OS/2 detect.mk - can detect targets like "borlandc", "watcom" - or "visualage", etc.. -

- -


- -

III. Building the library

-
    - When the top-level Makefile is invoked and that it finds - a config.mk file in the current directory, it defines - the variable BUILD_FREETYPE, then includes and parses the - configuration sub-makefile. -

    - The latter defines a number of important variables that describe - the compilation process to the build system. Among other things:

    -

      -
    • the extension to be used for object files and library files - (i.e. .o and .a on Unix, .obj - and .lib on Dos-Windows-OS/2, etc..). -

      - -

    • the directory where all object files will be stored - (usually freetype2/obj), as well as the one - containing the library file (usually the same as for - objects). -

      - -

    • the command line compiler, and its compilation flags for - indicating a new include path (usually "-I"), - a new macro declaration (usually "-D") or - the target object file (usually "-o ") -
    -

    - Once these variable are defined, config.mk test for the - definition of the BUILD_FREETYPE variable. If it exists, - the makefile then includes "freetype2/config/freetype.mk" - which contains the rules required to compile the library. -

    - Note that freetype.mk also scans the subdirectories of - "freetype2/src" for a file called "rules.mk". - Each rules.mk contains, as it names suggests, the rules - required to compile a given font driver or module. -

    - Once all this parsing is done, the library can be compiled. Usually, - each font driver is compiled as a standalone object file (e.g. - sfnt.o, truetype.o and type1.o). -

    - This process can be illustrated by the following graphics:

    -

    - -
    -

    -

- -


- -

IIV. Managing the list of modules

-
    - The makefile freetype.mk only determines how to compile - each one of the modules that are located in the sub-directories of - freetype2/src. -

    - However, when the function FT_Init_FreeType is invoked at - the start of an application, it must create a new FT_Library - object, and registers all known font drivers to it by - repeatly calling FT_Add_Driver. -

    - The list of known drivers is located in the file - "freetype2/config/system/ftmodule.h", and is used - exclusively by the internal function FT_Default_Drivers. The - list in ftmodule.h must be re-generated each time you add - or remove a module from freetype2/src. -

    - This is normally performed by invoking the top-level Makefile - with the modules target, as in:

    -

      - make modules -
    -

    - This will trigger a special rule that will re-generate - ftmodule.h. To do so, the Makefile will parse all module - directories for a file called "module.mk". Each - module.mk is a tiny sub-Makefile used to add a single - module to the driver list. -

    - This is illustrated by the following graphics:

    -

    - -
    -

    - Note that the new list of modules is displayed in a very human-friendly - way after a "make modules". Here's an example with the current - source tree (on 11 Jan 2000):

    -

      -Regenerating the font drivers list in ./config/unix/ftmodule.h
      -* driver:  sfnt      ( pseudo-driver for TrueType & OpenType formats )
      -* driver:  truetype  ( Windows/Mac font files with extension *.ttf or *.ttc )
      -* driver:  type1     ( Postscript font files with extension *.pfa or *.pfb )
      --- done --
      -    
    - -
- -


- -

V. Building the demonstration programs

-
    - Several demonstration programs are located in the - "freetype2/demos" directory hierarchy. This directory also - includes a tiny graphics sub-system that is able to blit glyphs to - a great variety of surfaces, as well as display these in various - graphics libraries or windowed environments. -

    - This section describes how the demonstration programs are compiled, - using the configuration freetype2/config.mk and their own - freetype2/demos/Makefile. -

    - To compile the demonstration programs, after the library, - simply go to freetype2/demos then invoke GNU make with no - arguments. -

    - The top-level Makefile will detect the config.mk in the - upper directory and include it. Because it doesn't define - the BUILD_FREETYPE variable, this will not force the - inclusion of freetype2/config/freetype.mk as described in - the previous section. -

    - the Makefile will then include the makefile called - "freetype2/demos/graph/rules.mk". The graphics rules.mk - defines the rules required to compile the graphics sub-system. -

    - Because the graphics syb-system is also designed modularly, it is able - to use any number of "modules" to display surfaces on the screen. - The graphics modules are located in the subdirectories of - freetype2/demos/config. Each such directory contains a file - named rules.mk which is in charge of:

    -

      -
    • detecting wether the corresponding graphics library is - available at the time of compilation. -

      -

    • if it is, alter the compilation rules to include the graphics - module in the build of the graph library. -
    -

    - When the graph library is built in demos/obj, the - demonstration programs executables are generated by the top-level - Makefile. -

    - This is illustrated by the following graphics:

    -

    - -
    -
- -


-
- - - diff --git a/docs/design/demo-programs.png b/docs/design/demo-programs.png deleted file mode 100644 index f79639697..000000000 Binary files a/docs/design/demo-programs.png and /dev/null differ diff --git a/docs/design/drivers-list.png b/docs/design/drivers-list.png deleted file mode 100644 index 0cf79fa68..000000000 Binary files a/docs/design/drivers-list.png and /dev/null differ diff --git a/docs/design/index.html b/docs/design/index.html deleted file mode 100644 index 50f7f290a..000000000 --- a/docs/design/index.html +++ /dev/null @@ -1,791 +0,0 @@ - - - - - - - FreeType 2 Internals - - - - - -
-

-FreeType 2.0 Internals

- -
-

-Version 1.2

- -
-

-© 1999-2000 David Turner (david@freetype.org)
-© 1999-2000 The FreeType Development Team (devel@freetype.org)

- -


-


-
  -

Introduction:

- -

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.

- -


-


-

-I. Overview :

- -
-

-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 -
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. -
 

-It also features the following : -
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 : -
    -
  • -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
  • -
-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 : -
1) Text string rendering -
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
-Note that features 1 through 3 should be provided by the SemTex library, -which may soon become part of the standard FreeType distribution.
-
-
- -


-


-

-II. Design :

- -
-

-1. Objects :

- -
They are several kinds of objects in FreeType, which can be -described as follows : -
Base objects -
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.

-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.
- -

-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: -
  -

- - - - - - - - -
-
- -


-


-

-III. Base objects :

- -
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 : - - - - - -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. -

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 : -

{ -
  … -
  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); -
  … -
}

-This code does the following : -
-
    -
  1. - 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..
  2. -
- -
    -
  1. - 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.
  2. -
- -
    -
  1. - 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.
  2. -
-
-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. -

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 : -
  -

- - - - - - -
-
- -


-


-

-IV. Font objects :

- -
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.
- -

-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 : -
  -

- - - - - - - - - - -
-
- -


-


-

-V. Driver Interface :

- -
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.

-
- -
-

-VI. Configuration:

- -
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. -
  -

-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 -: -

-
% cd freetype2/lib -
% make -f arch/unix/Makefile -

where 'make' is really GNU Make !

-
-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). -

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.

- -
 
- - - 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 @@ - - - - - - FreeType 2 Internals - I/O Frames - - - - -

- FreeType 2.0 I/O Frames -

- -

- © 2000 David Turner - (david@freetype.org)
- © 2000 The FreeType Development Team - (www.freetype.org) -

- -
- - -
- -
- -

- 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 FT_Access_Frame() will

- -
    -
  • -

    Ensure that there are at least 2+4+4=10 bytes left in the - stream.

    -
  • -
  • -

    `Preload' (for disk-based streams) 10 bytes from the current - stream position.

    -
  • -
  • -

    Set the frame `cursor' to the first byte in the frame.

    -
  • -
- -

Each FT_Get_Short() or FT_Get_ULong() call - will read a big-endian integer from the stream (2 bytes for - FT_Get_Short(), 4 bytes for FT_Get_ULong) - and advance the frame cursor accordingly.

- -

FT_Forget_Frame() `releases' the frame from memory.

- -

There are several advantages to using frames:

- -
    -
  • -

    Single-check when loading tables.

    -
  • -
  • -

    Making code clearer by providing simple parsing functions - while keeping code safe from file over-runs and invalid - offsets.

    -
  • -
- -
- -

- 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 - FT_Error, while stream must be a local variable or - argument of type FT_Stream.

- -

The macro used to access a frame is ACCESS_Frame(_size_), it will - translate to

- - -
-    ( error = FT_Access_Frame( stream, _size_ ) )
-        != FT_Err_Ok
-
- -

Similarly, the macro FORGET_Frame() translates to

- - -
-    FT_Forget_Frame( stream )
-
- -

Extracting integers can be performed with the GET_xxx() - macros, like

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- Macro name - - Translation - - Description -
- GET_Byte() - - FT_Get_Byte(stream) - -

Reads an 8-bit unsigned byte.

-
- GET_Char() - - (FT_Char)
- FT_Get_Byte(stream)
-
-

Reads an 8-bit signed byte.

-
- GET_Short() - - FT_Get_Short(stream) - - Reads a 16-bit signed big-endian integer. -
- GET_UShort() - - (FT_UShort)
- FT_Get_Short(stream)
-
- Reads a 16-bit unsigned big-endian integer. -
- GET_Offset() - - FT_Get_Offset(stream) - - Reads a 24-bit signed big-endian integer. -
- GET_UOffset() - - (FT_UOffset)
- FT_Get_Offset(stream)
-
- Reads a 24-bit unsigned big-endian integer. -
- GET_Long() - - FT_Get_Long(stream) - - Reads a 32-bit signed big-endian integer. -
- GET_ULong() - - (FT_ULong)
- FT_Get_Long(stream)
-
- Reads a 32-bit unsigned big-endian integer. -
- -

(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 FT_Read_xxxx.

- -

For example, FT_Read_Short(stream, - &error) reads and returns a 2-byte big-endian integer from a - stream, and places an error code in the error - variable.

- -

Thus, reading a single big-endian integer is shorter than using a frame - for it.

- -

Note that there are also macros READ_xxx() which translate to

- - -
-    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.

- -
-
- - - diff --git a/docs/design/library-compilation.png b/docs/design/library-compilation.png deleted file mode 100644 index 7aedcb196..000000000 Binary files a/docs/design/library-compilation.png and /dev/null differ diff --git a/docs/design/logo1.png b/docs/design/logo1.png deleted file mode 100644 index d78d05d2c..000000000 Binary files a/docs/design/logo1.png and /dev/null differ diff --git a/docs/design/objects_diagram.png b/docs/design/objects_diagram.png deleted file mode 100644 index 893bf6948..000000000 Binary files a/docs/design/objects_diagram.png and /dev/null differ diff --git a/docs/design/objects_diagram2.png b/docs/design/objects_diagram2.png deleted file mode 100644 index 0ef5fa3f2..000000000 Binary files a/docs/design/objects_diagram2.png and /dev/null differ diff --git a/docs/design/platform-detection.png b/docs/design/platform-detection.png deleted file mode 100644 index a30b7e2b5..000000000 Binary files a/docs/design/platform-detection.png and /dev/null differ diff --git a/docs/design/system-interface.html b/docs/design/system-interface.html deleted file mode 100644 index c505bbe59..000000000 --- a/docs/design/system-interface.html +++ /dev/null @@ -1,258 +0,0 @@ - - - - - - - FreeType 2 Internals - - - - - -
-

-FreeType 2.0 System Interface

- -
-

-© 2000 David Turner (david@freetype.org)
-© 2000 The FreeType Development Team (devel@freetype.org)

- -


-


-
  -

Introduction:

- - -

-


-

- -

I. Memory Management

- - -

-


-

- -

II. Streams

- - - -

-


-

- -

III. Thread synchronisation

- - - diff --git a/docs/tutorial/index.html b/docs/tutorial/index.html deleted file mode 100644 index fb8a5b3ae..000000000 --- a/docs/tutorial/index.html +++ /dev/null @@ -1,871 +0,0 @@ - - - - - - FreeType 2 Tutorial - - - - -

- FreeType 2.0 Tutorial -

- -

- © 2000 David Turner - (david@freetype.org)
- © 2000 The FreeType Development Team - (www.freetype.org) -

- -
- - -
- -
- -

- 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:

- -
    -
  • -

    Creating a new instance of the FreeType 2 library, and set - the handle library to it.

    -
  • -
  • -

    Load each modules that FreeType knows about in the library. - This means that by default, your new library object is able - to handle TrueType, Type 1, CID-keyed & OpenType/CFF fonts - gracefully.

    -
  • -
- -

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

- - - - - - - - - - - - - - - - - - -
- library - -

handle to the FreeType library instance where the face object - is created

-
- filepathname - -

the font file pathname (standard C string).

-
- face_index - -

Certain font formats allow several font faces to be embedded - in a single file.

- -

This index tells which face you want to load. An error will - be returned if its value is too large.

- -

Index 0 always work though.

-
- face - -

A pointer to the handle that will be set to describe - the new face object.

- -

It is set to NULL in case of error.

-
- -

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

- - - - - - - - - - - - - - - - - - - - - - -
- face->num_glyphs - -

Gives the number of glyphs available in the font face. - A glyph is simply a character image. It doesn't necessarily - correspond to a character code though.

-
- face->flags - -

A 32-bit integer containing bit flags used to describe some - face properties. For example, the flag - FT_FACE_FLAG_SCALABLE is used to indicate that the face's - font format is scalable and that glyph images can be rendered for - all character pixel sizes. For more information on face flags, - please read the FreeType 2 API Reference.

-
- face->units_per_EM - -

This field is only valid for scalable formats (it is set to 0 - otherwise). It indicates the number of font units covered by the - EM.

-
- face->num_fixed_sizes - -

This field gives the number of embedded bitmap strikes - in the current face. A strike is simply a series of - glyph images for a given character pixel size. For example, a - font face could include strikes for pixel sizes 10, 12 - and 14. Note that even scalable font formats can have - embedded bitmap strikes!

-
- face->fixed_sizes - -

this is a pointer to an array of FT_Bitmap_Size - elements. Each FT_Bitmap_Size indicates the horizontal - and vertical pixel sizes for each of the strikes that are - present in the face.

-
- -

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:

- -
    -
  • -

    The character width and heights are specified in 1/64th of - points. A point is a physical distance, equaling 1/72th - of an inch, it's not a pixel..

    -

  • -
  • -

    The horizontal and vertical device resolutions are expressed in - dots-per-inch, or dpi. You can use 72 or - 96 dpi for display devices like the screen. The resolution - is used to compute the character pixel size from the character - point size.

    -
  • -
  • -

    A value of 0 for the character width means "same as - character height", a value of 0 for the character height - means "same as character width". Otherwise, it is possible - to specify different char widths and heights.

    -
  • -
  • -

    Using a value of 0 for the horizontal or vertical resolution means - 72 dpi, which is the default.

    -
  • -
  • -

    The first argument is a handle to a face object, not a size - object. That's normal, and must be seen as a convenience.

    -
  • -
- -

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:

- -
    -
  • -

    If a bitmap is found for the corresponding glyph and pixel - size, it will in the slot (embedded bitmaps are always - favored over native image formats, because we assume that - they are higher-quality versions of the same image. This - can be ignored by using the FT_LOAD_NO_BITMAP flag)

    -
  • - -
  • -

    Otherwise, a native image for the glyph will be loaded. - It will also be scaled to the current pixel size, as - well as hinted for certain formats like TrueType and - Type1.

    -
  • -
- -

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:

- - - - - - - - - - - - - - - - - - -
- glyph->format - -

Indicates the type of the loaded glyph image. Can be either - ft_glyph_format_bitmap, ft_glyph_format_outline, - or other values.

-
- glyph->metrics - -

A simple structure used to hold the glyph image's metrics. - Note that most distances are expressed in 1/64th of - pixels! See the API reference or the user guide for a - description of the FT_Glyph_Metrics structure.

-
- glyph->bitmap - -

If the glyph slot contains a bitmap, a simple - FT_Bitmap that describes it. See the API reference or - user guide for a description of the FT_Bitmap - structure.

-
- glyph->outline - -

When the glyph slot contains a scalable outline, this structure - describes it. See the definition of the FT_Outline - structure.

-
- -

- 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

- -
    -
  • -

    As previously, FT_Get_Glyph_Bitmap() doesn't generate - the bitmap, it simply renders to it.

    -
  • -
  • -

    The target bitmap must be cleaned before calling the function. - This is a limitation of our current anti-aliasing algorithm and is - EXTREMELY important.

    -
  • -
  • -

    The anti-aliaser uses 128 levels of grays exclusively for - now (this will probably change in a near future). This means that - you must set bit.grays to 128. The generated - image uses values from 0 (back color) to 127 (foreground color).

    -
  • -
  • -

    It is not possible to render directly an anti-aliased - outline into a pre-existing gray-level bitmap, or even any - colored-format one (like RGB16 or paletted 8-bits). We will not - discuss this issue in great details here, but the reason is that we - do not want to deal with graphics composition (or alpha-blending) - within FreeType.

    -

  • -
-
-
- - -