From 60784a2200ad63293db4309ae5d8c72e826084dc Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Mon, 30 Oct 2000 20:46:41 +0000 Subject: [PATCH] Formatting/correcting the first three parts of the design docs. --- docs/design/design-1.html | 152 ++++++++------ docs/design/design-2.html | 201 +++++++++--------- docs/design/design-3.html | 424 ++++++++++++++++++++------------------ docs/ft2faq.html | 3 +- 4 files changed, 424 insertions(+), 356 deletions(-) diff --git a/docs/design/design-1.html b/docs/design/design-1.html index 604fbc873..c2d1b7290 100644 --- a/docs/design/design-1.html +++ b/docs/design/design-1.html @@ -1,82 +1,102 @@ + -The Design of FreeType 2 - Introduction - - + + + + The Design of FreeType 2 - Introduction - -
+
+ -

The Design of FreeType 2

+

+ The Design of FreeType 2 +

-
-

Introduction

-
+
+ +
-

This document provides details on the design and implementation - of the FreeType 2 library. Its goal is to allow developers to - better understand the way FT2 is organized, in order to let them - extend, customize and debug it.

+ + +
+

+ Introduction +

+
-

Before anything else, it is important to understand the purpose - of this library, i.e. why it has been written:

+

This document provides details on the design and implementation of the + FreeType 2 library. Its goal is to allow developers to better + understand the way how FreeType 2 is organized, in order to let them + extend, customize, and debug it.

-
    -
  • first of all, to allow client applications to access font files - easily, wherever they could be stored, and as independently - of font format as possible.

  • +

    Before anything else, it is important to understand the + purpose of this library, i.e., why it has been written:

    -
  • to allow easy retrieval of global font data most commonly - found in normal font formats (i.e. global metrics, - encoding/charmaps, etc..)

  • +
      +
    • +

      It allows client applications to access font files easily, + wherever they could be stored, and as independently of the font format + as possible.

      +
    • +
    • +

      Easy retrieval of global font data most commonly found in + normal font formats (i.e. global metrics, encoding/charmaps, + etc.).

      +
    • +
    • +

      It allows easy retrieval of individual glyph data + (metrics, images, name, anything else).

      +
    • +
    • +

      Access to font format-specific "features" whenever + possible (e.g. SFNT tables, Multiple Masters, OpenType Layout tables, + etc.).

      +
    • +
    -
  • to allow easy retrieval of individual glyph data - (metrics, images, name, anything else)

  • +

    Its design has also severely been influenced by the following + requirements:

    -
  • to allow access to font format-specific "features" - whenever possible (e.g. SFNT tables, Multiple Masters, - OpenType Layout tables, etc..)

  • -
+
    +
  • +

    High portability. The library must be able to run on any + kind of environment. This requirement introduces a few drastic + choices that are part of FreeType 2's low-level system + interface.

    +
  • +
  • +

    Extendability. New features should be added with the + least modifications in the library's code base. This requirement + induces an extremely simple design where nearly all operations are + provided by modules.

    +
  • +
  • +

    Customization. It should be easy to build a version of the + library that only contains the features needed by a specific project. + This really is important when you need to integrate it in a font + server for embedded graphics libraries.

    +
  • +
  • +

    Compactness and efficiency. The primary target + for this library are embedded systems with low cpu and memory + resources.

    +
  • +
-

its design has also severely been influenced by the following - requirements:

+

The rest of this document is divided in several sections. First, a few + chapters will present the library's basic design as well as the + objects/data managed internally by FreeType 2.

-
    -
  • high portability, as the library must be able to run - on any kind of environment. this requirement introduces a few - drastic choices that are part of FreeType 2's low-level system - interface.

  • +

    A later section is then dedicated to library customization, relating + such topics as system-specific interfaces, how to write your own module + and how to tailor library initialization & compilation to your needs.

    -
  • extendibility, as new features should be added with - the least modifications in the library's code base. this - requirements induces an extremely simple design where nearly - all operations are provided by modules. -

  • - -
  • customization, it should be easy to build a version - of the library that only contains the features needed by a - specific project. This really is important when you need to - integrate it in a font server for embedded graphics libraries.

  • - -
  • compactness and efficiency, given that the - primary target for this library is embedded systems with low - cpu and memory resources.

  • -
- -

The rest of this document is divided in several sections. First, a - few chapters will present the library's basic design as well as the - objects/data managed internally by FreeType 2.

- -

A later section is then dedicated to library customization, relating - such topics as system-specific interfaces, how to write your own - module and how to tailor library initialisation & compilation - to your needs.

- -
+
+
diff --git a/docs/design/design-2.html b/docs/design/design-2.html index fba5c9887..b8bcb8506 100644 --- a/docs/design/design-2.html +++ b/docs/design/design-2.html @@ -1,112 +1,129 @@ + -The Design of FreeType 2 - Basic Design - - + + + + The Design of FreeType 2 - Basic Design - -
+
+ -

The Design of FreeType 2

+

+ The Design of FreeType 2 +

-
-

I. Components and APIs

-
+
+ +
-

It's better to describe FreeType 2 as a collection of - components. Each one of them is a more or less abstract - part of the library that is in charge of one specific task. We will - now explicit the connections and relationships between them.

+ + +
+

+ I. Components and APIs +

+
-

A first brief description of this system of components could be:

-
    -
  • - client applications typically call the FreeType 2 high-level - API, whose functions are implemented in a single component - called the Base Layer. -

  • +

    It's better to describe FreeType 2 as a collection of + components. Each one of them is a more or less abstract part of + the library that is in charge of one specific task. We will now explicit + the connections and relationships between them.

    -
  • - depending on the context or the task, the base - layer then calls one or more module components to - perform the work. In most cases, the client application doesn't - need to know what module was called. -

  • +

    A first brief description of this system of components could be:

    -
  • - the base layer also contains a set of routines that are - used for generic things like memory allocation, list - processing, i/o stream parsing, fixed point computation, - etc.. these functions can also be called by a module - at any time, and they form what is called the low-level - base API. -

  • -
+
    +
  • +

    Client applications typically call the FreeType 2 + high-level API, whose functions are implemented in a single + component called the Base Layer.

    +
  • +
  • +

    Depending on the context or the task, the base layer then calls one + or more module components to perform the work. In most + cases, the client application doesn't need to know which module was + called.

    +
  • +
  • +

    The base layer also contains a set of routines that are used for + generic things like memory allocation, list processing, i/o stream + parsing, fixed point computation, etc. these functions can also be + called by a module at any time, and they form what is called the + low-level base API.

    +
  • +
-

This is illustrated by the following graphics (note that component - entry points are represented as colored triangles):

+

This is illustrated by the following graphics (note that component + entry points are represented as colored triangles):

-
+
+ Basic FreeType design +
-

Now, a few additional things must be added to complete this picture:

+

Now, a few additional things must be added to complete this + picture:

-
    -
  • some parts of the base layer can be replaced for specific builds - of the library, and can thus be considered as components themselves. - this is the case for the ftsystem component, which is in - charge of implementing memory management & input stream access, - as well as the ftinit, which is in charge of library - initialisation (i.e. implementing FT_Init_FreeType). -

  • +
      +
    • +

      Some parts of the base layer can be replaced for specific builds of + the library, and can thus be considered as components themselves. + This is the case for the ftsystem component, which is in + charge of implementing memory management & input stream access, as + well as ftinit, which is in charge of library initialization + (i.e. implementing the FT_Init_FreeType() function).

      +
    • +
    • +

      FreeType 2 comes also with a set of optional + components, which can be used either as a convenience for client + applications (e.g. the ftglyph component, used to provide a + simple API to manage glyph images independently of their internal + representation), or to access format-specific features (e.g. the + ftmm component used to access and manage Multiple Masters + data in Type 1 fonts).

      +
    • +
    • +

      Finally, a module is capable of calling functions provided by + another module. This is very useful to share code and tables between + several font driver modules (for example, the truetype and + cff modules both use the routines provided by the + sfnt module).

      +
    • +
    -
  • - FreeType 2 comes also with a set of optional components, - which can be used either as a convenience for client applications - (e.g. the ftglyph component, used to provide a simple API - to manage glyph images independently of their internal representation), - or to access format-specific features (e.g. the ftmm component - used to access and manage Multiple Masters data in Type 1 fonts) -

  • +

    Hence, a more complete picture would be:

    -
  • - Finally, a module is capable of calling functions provided by - another module. This is very useful to share code and tables - between several font driver modules (for example, the truetype - and cff both use the routines provided by the sfnt - module). -

  • -
+
+ Detailed FreeType design +
-

Hence, a more complete picture would be:

+

Please take note of the following important points:

-
+
    +
  • +

    An optional component can use either the high-level or base API. + This is the case of ftglyph in the above picture.

    +
  • +
  • +

    Some optional components can use module-specific interfaces ignored + by the base layer. In the above example, ftmm directly + accesses the Type 1 module to set/query data.

    +
  • +
  • +

    A replacable component can provide a function of the high-level + API. For example, ftinit provides + FT_Init_FreeType() to client applications.

    +
  • +
-

Please take note of the following important points:

- -
    -
  • - an optional component can use either the high-level or base - API. This is the case of ftglyph in the above picture. -

  • - -
  • - some optional component can use module-specific interfaces - ignored by the base layer. In the above example, ftmm - directly accesses the Type 1 module to set/query data -

  • - -
  • - a replacable component can provide a function of the high-level - API. For example, ftinit provides FT_Init_FreeType - to client applications. -

  • -
- -
+
+
diff --git a/docs/design/design-3.html b/docs/design/design-3.html index 83900f278..0c1bbd1fc 100644 --- a/docs/design/design-3.html +++ b/docs/design/design-3.html @@ -1,263 +1,293 @@ + -The Design of FreeType 2 - Public Objects - - + + + + The Design of FreeType 2 - Public Objects - -
+
+ -

The Design of FreeType 2

+

+ The Design of FreeType 2 +

-
-

II. Public Objects and Classes

-
+
+ +
-

We will now detail the abstractions provided by FreeType 2 to - client applications to manage font files and data. As you would - normally expect, these are implemented through objects/classes.

+ + +
+

+ II. Public Objects and Classes +

+
-

1. Object Orientation in FreeType 2:

+

We will now explain the abstractions provided by FreeType 2 to + client applications to manage font files and data. As you would normally + expect, these are implemented through objects/classes.

-

Though written in ANSI C, the library employs a few - techniques, inherited from object-oriented programming, to make - it easy to extend. Hence, the following conventions apply in - the FT2 source code:

+

+ 1. Object Orientation in FreeType 2 +

-
    -
  1. - each object type/class has a corresponding structure type and - a corresponding structure pointer type. the latter is called the - handle type for the type/class.

    +

    Though written in ANSI C, the library employs a few techniques, + inherited from object-oriented programming, to make it easy to extend. + Hence, the following conventions apply in the FreeType 2 source + code:

    -

    Consider that we need to manage objects of type "foo" in FT2. - We would define the following structure and handle types as - follow:

    +
      +
    1. +

      Each object type/class has a corresponding structure + type and a corresponding structure pointer + type. The latter is called the handle type for the + type/class.

      -
      
      -     typedef struct FT_FooRec_*    FT_Foo;
      +        

      Consider that we need to manage objects of type "foo" in + FreeType 2. We would define the following structure and handle + types as follows:

      - typedef struct FT_FooRec_ - { - // fields for the "foo" class - ... +
      +    typedef struct FT_FooRec_*  FT_Foo;
       
      -     } FT_FooRec;
      -  
      + typedef struct FT_FooRec_ + { + // fields for the "foo" class + ... -

      As a convention, handle types use simple but meaningful identifiers - beginning with "FT_", as in "FT_Foo", while structures use the same - name with a "Rec" suffix appended to it ('Rec' is short for "record"). - Note that each class type has a corresponding handle type. -

      + } FT_FooRec;
      + +

      As a convention, handle types use simple but meaningful + identifiers beginning with FT_, as in FT_Foo, + while structures use the same name with a Rec suffix + appended to it ("Rec" is short for "record"). Note that each + class type has a corresponding handle type.

      +
    2. +
    3. +

      Class derivation is achieved internally by wrapping base class + structures into new ones. As an example, we define a "foobar" class + that is derived from "foo". We would do something like:

      -
    4. - class derivation is achieved internally by wrapping base class - structures into new ones. As an example, let's define a "foobar" - class that is derived from "foo". We would do something like:

      +
      +    typedef struct FT_FooBarRec_*  FT_FooBar;
       
      -  
      
      -     typedef struct FT_FooBarRec_*    FT_FooBar;
      +    typedef struct  FT_FooBarRec_
      +    {
      +      // the base "foo" class fields
      +      FT_FooRec  root;
       
      -     typedef struct FT_FooBarRec_
      -     {
      -       // the base "foo" class fields
      -       FT_FooRec     root;
      +      // fields proper to the "foobar" class
      +      ...
      +    } FT_FooBarRec;
      + - // fields proper to the "foobar" class - ... +

      As you can see, we ensure that a "foobar" object is also a "foo" + object by placing a FT_FooRec at the start of the + FT_FooBarRec definition. It is called root by + convention.

      - } FT_FooBarRec; -
      +

      Note that a FT_FooBar handle also points to a "foo" + object and can be typecasted to FT_Foo. Similarly, when + the library returns a FT_Foo handle to client applications, + the object can be really implemented as a FT_FooBar or any + derived class from "foo".

      +
    5. +
    -

    As you can see, we ensure that a "foobar" object is also a "foo" - object by placing a FT_FooRec at the start of the - FT_FooBarRec definition. It is called root - by convention.

    +

    In the following sections of this chapter, we will refer to "the + FT_Foo class" to indicate the type of objects handled through + FT_Foo pointers, be they implemented as "foo" or "foobar".

    -

    Note that a FT_FooBar handle also points to a "foo" object - and can be typecasted to FT_Foo. Similarly, when the - library handles a FT_Foo handle to client applications, - the object can be really implemented as a FT_FooBar or any - derived class from "foo".

    +
    -

  2. - +

    + 2. The FT_Library class +

    -

    Note that in the following sections of this chapter, we will refer - to "the FT_Foo class" to indicate the type of objects - handled through FT_Foo pointers, be they implemented as - "foo" or "foobar".

    +

    This type corresponds to a handle to a single instance of the + library. Note that the corresponding structure FT_LibraryRec + is not defined in public header files, making client applications unable + to access its internal fields.

    -
    +

    The library object is the parent of all other objects in + FreeType 2. You need to create a new library instance before doing + anything else with the library. Similarly, destroying it will + automatically destroy all its children (i.e. faces and modules).

    -

    2. The FT_Library class:

    +

    Typical client applications should call FT_Init_FreeType() + in order to create a new library object, ready to be used for further + actions.

    -

    This type corresponds to a handle to a single instance of the - library. Note that the corresponding structure FT_LibraryRec - is not defined in public header files, making client applications - unable to access its internal fields.

    +

    Another alternative is to create a fresh new library instance by + calling the function FT_New_Library(), defined in the + <freetype/ftmodule.h> public header file. This function + will however return an "empty" library instance with no module + registered in it. You can "install" modules in the instance by calling + FT_Add_Module() manually.

    -

    The library object is the "parent" of all other objects in FreeType 2. - You need to create a new library instance before doing anything else - with the library. Similarly, destroying it will automatically - destroy all its children (i.e. faces and modules).

    +

    Calling FT_Init_FreeType() is a lot more convenient, because + this function basically registers a set of default modules into each new + library instance. The way this list is accessed and/or computed is + determined at build time, and depends on the content of the + ftinit component. This process is explained in details later + in this document.

    -

    Typical client applications should call FT_Init_FreeType, - in order to create a new library object, ready to be used for - further action.

    +

    For now, one should consider that library objects are created with + FT_Init_FreeType(), and destroyed along with all children with + FT_Done_FreeType().

    -

    Another alternative is to create a fresh new library instance - by calling the function FT_New_Library, defined in the - <freetype/ftmodule.h> public header file. This - function will however return an "empty" library instance with - no module registered in it. You can "install" modules in the - instance by calling FT_Add_Module manually.

    +
    -

    Calling FT_Init_FreeType is a lot more convenient, because - this function basically registers a set of default modules into - each new library instance. The way this list is accessed and/or - computed is determined at build time, and depends on the content - of the ftinit component. This process is explained in - details later in this document.

    +

    + 3. The FT_Face class +

    -

    For now, one should consider that library objects are created - with FT_Init_FreeType, and destroyed along with all - children with FT_Done_FreeType.

    -
    +

    A face object corresponds to a single font face, i.e., a + specific typeface with a specific style. For example, "Arial" and + "Arial Italic" correspond to two distinct faces.

    -

    3. The FT_Face class:

    +

    A face object is normally created through FT_New_Face(). + This function takes the following parameters: an FT_Library + handle, a C file pathname used to indicate which font file to open, an + index used to decide which face to load from the file (a single file may + contain several faces in certain cases), and the address of a + FT_Face handle. It returns an error code:

    -

    A face object corresponds to a single font face, i.e. - a specific typeface with a specific style. For example, "Arial" - and "Arial Italic" correspond to two distinct faces.

    +
    +    FT_Error  FT_New_Face( FT_Library   library,
    +                           const char*  filepathname,
    +                           FT_Long      face_index,
    +                           FT_Face*     face );
    +
    -

    A face object is normally created through FT_New_Face. - This function takes the following parameters: a FT_Library - handle, a C file pathname used to indicate which font file to - open, an index used to decide which face to load from the file - (a single file may contain several faces in certain cases), - as well as the address of a FT_Face handle. It returns - an error code:

    +

    In case of success, the function will return 0, and the handle + pointed to by the face parameter will be set to a non-NULL + value.

    -
    
    -  FT_Error  FT_New_Face( FT_Library   library,
    -                         const char*  filepathname,
    -                         FT_Long      face_index,
    -                         FT_Face     *face );
    -
    +

    Note that the face object contains several fields used to describe + global font data that can be accessed directly by client applications. + For example, the total number of glyphs in the face, the face's family + name, style name, the EM size for scalable formats, etc. For more + details, look at the FT_FaceRec definition in the + FreeType 2 API Reference.

    -

    in case of success, the function will return 0, and the handle - pointed to by the "face" parameter will be set to a non-NULL value.

    +
    -

    Note that the face object contains several fields used to - describe global font data that can be accessed directly by - client applications. For example, the total number of glyphs - in the face, the face's family name, style name, the EM size - for scalable formats, etc.. For more details, look at the - FT_FaceRec definition in the FT2 API Reference.

    +

    + 4. The FT_Size class +

    -
    +

    Each FT_Face object has one or more + FT_Size objects. A size object is used to store data + specific to a given character width and height. Each newly created face + object has one size, which is directly accessible as + face->size.

    -

    4. The FT_Size class:

    +

    The contents of a size object can be changed by calling either + FT_Set_Pixel_Sizes() or FT_Set_Char_Size().

    -

    Each FT_Face object has one or more FT_Size - objects. A size object is used to store data specific to a - given character width and height. Each newly created face object - has one size, which is directly accessible as face->size.

    +

    A new size object can be created with FT_New_Size(), and + destroyed manually with FT_Done_Size(). Note that typical + applications don't need to do this normally: they tend to use the + default size object provided with each FT_Face.

    -

    The content of a size object can be changed by calling either - FT_Set_Pixel_Sizes or FT_Set_Char_Size.

    +

    The public fields of FT_Size objects are defined in a very + small structure named FT_SizeRec. However, it is important to + understand that some font drivers define their own derivatives of + FT_Size to store important internal data that is re-computed + each time the character size changes. Most of the time, these are + size-specific font hints./p> -

    A new size object can be created with FT_New_Size, and - destroyed manually with FT_Done_Size. Note that typical - applications don't need to do this normally: they tend to use - the default size object provided with each FT_Face.

    +

    For example, the TrueType driver stores the scaled CVT table that + results from the execution of the "cvt" program in a TT_Size + structure, while the Type 1 driver stores scaled global metrics + (like blue zones) in a T1_Size object. Don't worry if you + don't understand the current paragraph; most of this stuff is highly + font format specific and doesn't need to be explained to client + developers :-)

    -

    The public fields of FT_Size objects are defined in - a very small structure named FT_SizeRec. However, it is - important to understand that some font drivers define their own - derivatives of FT_Size to store important internal data - that is re-computed each time the character size changes. Most of - the time, these are size-specific font hints./p> +


    -

    For example, the TrueType driver stores the scaled CVT table that - results from the execution of the "cvt" program in a TT_Size, - while the Type 1 driver stores scaled global metrics (like blue zones) - in a T1_Size object. Don't worry if you don't understand - the current paragraph, most of this stuff is highly font format - specific and doesn't need to be explained to client developers :-)

    +

    + 5. The FT_GlyphSlot class +

    -
    +

    The purpose of a glyph slot is to provide a place where glyph images + can be loaded one by one easily, independently of the glyph image format + (bitmap, vector outline, or anything else).

    -

    5. The FT_GlyphSlot class:

    +

    Ideally, once a glyph slot is created, any glyph image can be loaded + into it without additional memory allocation. In practice, this is only + possible with certain formats like TrueType which explicitly provide + data to compute a slot's maximum size.

    -

    The purpose of a glyph slot is to provide a place where glyph - images can be loaded one by one easily, independently of the - glyph image format (bitmap, vector outline, or anything else).

    +

    Another reason for glyph slots is that they are also used to hold + format-specific hints for a given glyphs as well as all other data + necessary to correctly load the glyph.

    -

    Ideally, once a glyph slot is created, any glyph image can - be loaded into it without additional memory allocation. In practice, - this is only possible with certain formats like TrueType which - explicitely provide data to compute a slot's maximum size.

    +

    The base FT_GlyphSlotRec structure only presents glyph + metrics and images to client applications, while actual implementation + may contain more sophisticated data.

    -

    Another reason for glyph slots is that they're also used to hold - format-specific hints for a given glyphs has well as all other - data necessary to correctly load the glyph.

    +

    As an example, the TrueType-specific TT_GlyphSlotRec + structure contains additional fields to hold glyph-specific bytecode, + transient outlines used during the hinting process, and a few other + things. -

    The base FT_GlyphSlotRec structure only presents glyph - metrics and images to client applications, while actual implementation - may contain more sophisticated data.

    + The Type 1-specific T1_GlyphSlotRec structure holds glyph + hints during glyph loading, as well as additional logic used to properly + hint the glyphs when a native Type 1 hinter is used.

    -

    As an example, the TrueType-specific TT_GlyphSlotRec - structure contains additional fields to hold glyph-specific bytecode, - transient outlines used during the hinting process, and a few other - things. +

    Finally, each face object has a single glyph slot that is directly + accessible as face->glyph.

    - the Type1-specific T1_GlyphSlotRec structure holds - glyph hints during glyph loading, as well as additional logic used - to properly hint the glyphs when a native T1 hinter is used.

    +
    -

    Finally, each face object has a single glyph slot, that is directly - accessible as face->glyph.

    +

    + 6. The FT_CharMap class +

    -
    +

    The FT_CharMap type is used as a handle to character map + objects, or charmaps. A charmap is simply some sort of table + or dictionary which is used to translate character codes in a given + encoding into glyph indices for the font.

    -

    6. The FT_CharMap class:

    +

    A single face may contain several charmaps. Each one of them + corresponds to a given character repertoire, like Unicode, Apple Roman, + Windows codepages, and other encodings.

    -

    Finally, the FT_CharMap type is used as a handle to - character map objects, or "charmaps" to be brief. A charmap is - simply some sort of table or dictionary which is used to translate - character codes in a given encoding into glyph indices for the - font.

    +

    Each FT_CharMap object contains a "platform" and an + "encoding" field used to identify precisely the character repertoire + corresponding to it.

    -

    A single face may contain several charmaps. Each one of them - corresponds to a given character repertoire, like Unicode, Apple Roman, - Windows codepages, and other ugly "standards".

    +

    Each font format provides its own derivative of + FT_CharMapRec and thus needs to implement these objects.

    -

    Each FT_CharMap object contains a "platform" and an "encoding" - field used to identify precisely the character repertoire corresponding - to it.

    +
    -

    Each font format provides its own derivative of FT_CharMapRec - and thus needs to implement these objects.

    +

    + 7. Objects relationships +

    -
    -

    7. Objects relationships:

    +

    The following diagram summarizes what we have just said regarding the + public objects managed by the library, as well as explicitely describes + their relationships

    -

    The following diagram summarizes what we just said regarding the - public objects managed by the library, as well as explicitely - describes their relationships:

    +
    + to be added +
    -

    Note that this picture will be updated at the end of the next - chapter, related to internal objects.

    +

    Note that this picture will be updated at the end of the next + chapter, related to internal objects.

    -
+
+
diff --git a/docs/ft2faq.html b/docs/ft2faq.html index 114758426..845aaa8ad 100644 --- a/docs/ft2faq.html +++ b/docs/ft2faq.html @@ -119,7 +119,8 @@

- General questions & answers

+ General questions & answers +