home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: SysTools / SysTools.zip / ft-beta.zip / freetype / docs / convntns.txt < prev    next >
Text File  |  1997-10-06  |  36KB  |  985 lines

  1.            Conventions and Design in the FreeType library
  2.  
  3.  
  4. TOC
  5.  
  6. Introduction
  7.  
  8. I. Style and Formatting
  9.  
  10.   1. Naming
  11.   2. Declarations & Statements
  12.   3. Blocks
  13.   4. Macros
  14.  
  15. II. Design conventions
  16.  
  17.   1. Modularity and Components Layout
  18.   2. Configuration and Debugging
  19.  
  20. III. Usage conventions
  21.  
  22.   1. Error handling
  23.   2. Font File I/O
  24.   3. Memory management (due to change soon).
  25.   4. Support for threaded environments.
  26.   5. Object Management
  27.  
  28. Introduction:
  29.  
  30. This text introduces the many conventions used within the FreeType
  31. library.  Please read it before trying any modifications or extensions
  32. of the source code.
  33.  
  34. I. Style and Formatting:
  35.  
  36. The following coding rules are extremely important to keep the
  37. library's source code homogeneous.  Keep in mind the following points :
  38.  
  39.   - "Humans read source code, not machines" (Donald Knuth)
  40.  
  41.     The library source code should be as readable as possible, even by
  42.     non C experts.  By readable, two things are meant: first, the
  43.     source code should be pleasant to the eye, with sufficient
  44.     whitespace and newlines, to not look like a boring stack of
  45.     characters stuck to each other.  Second, the source should be
  46.     _expressive_ enough about its goals.  This convention contains
  47.     rules that can help the source focus on its purpose, not on a
  48.     particular implementation.
  49.  
  50.     
  51.   - "Paper is the _ultimate_ debugger" (Myself)
  52.  
  53.     There is nothing like sheets of paper (and a large floor) to help
  54.     you understand the design of a library you're new to, or to debug
  55.     it.  The formatting style presented here is targeted at printing. 
  56.     For example, it is more than highly recommended to never produce a
  57.     source line that is wider than 78 columns.  More on this below.
  58.  
  59.  
  60. 1. Naming:
  61.  
  62.   a. Components:
  63.  
  64.     A unit of the library is called a 'component'.  Each component has
  65.     at least an interface, and often a body.  The library comes in two
  66.     language flavors, C and Pascal.  A C component is defined by two
  67.     files, one '.h' header and one '.c' body, while a Pascal component
  68.     is contained in a single '.pas' file.
  69.  
  70.     All component source file names begin with the 'tt' prefix, with
  71.     the exception of the 'FreeType' component.  For example, the file
  72.     component is implemented by the files 'ttfile.h', 'ttfile.c' and
  73.     'ttfile.pas'.  Only lowercase letters should be used, following the
  74.     8+3 naming convention to allow compilation under DOS.
  75.  
  76.     In the C version, a single component can have multiple bodies.  For
  77.     example, 'ttfile.c' provides stream i/o through standard ANSI libc
  78.     calls, while 'ttfile2.c' implements the same thing using one Unix
  79.     memory-mapping API.
  80.  
  81.     The FreeType component is an interface-only component.
  82.  
  83.  
  84.   b. Long and expressive labels:
  85.  
  86.    Never hesitate to use long labels for your types, variables, etc.! 
  87.    Except maybe for things like very trivial types, the longest is the
  88.    best, as it increases the source's _expressiveness_.  Never forget
  89.    that the role of a label is to express the 'function' of the entity
  90.    it represents, not its implementation!
  91.  
  92.    NOTE:   Hungarian notation is NOT expressive, as it sticks the
  93.            'type' of a variable to its name.  A label like 'usFoo'
  94.            rarely tells the use of the variable it represents.
  95.  
  96.            And the state of a variable (global, static, dynamic)
  97.            isn't helpful anymore.
  98.  
  99.    Avoid Hungarian Notation like the *plague*!
  100.  
  101.  
  102.    When forging a name with several nouns (e.g."number-of-points"), use
  103.    an uppercase letter for the first word of each one, like:
  104.  
  105.      numberOfPoints
  106.  
  107.    you are also welcomed to introduce underscores '_' in your labels,
  108.    especially when sticking large nouns together, as it 'airs' the code
  109.    greatly.  E.g.:
  110.  
  111.      'numberOfPoints' or 'number_Of_Points'
  112.  
  113.      'IncredibleFunction' or 'Incredible_Function'
  114.        
  115.    And finally, always put a capital letter after an underscore, except
  116.    in variable labels that are all lowercase:
  117.  
  118.      'number_of_points' is OK for a variable (_all_ lowercase label)
  119.  
  120.      'incredible_function' is NOT for a function!
  121.       ^          ^
  122.  
  123.      'Microsoft_windows' is a *shame*!
  124.       ^         ^
  125.  
  126.      'Microsoft_Windows' isn't really better, but at least its a
  127.       ^         ^        correct label within this convention. :) 
  128.  
  129.   c. Types:
  130.  
  131.    All types that are defined for use by FreeType client applications
  132.    are defined in the FreeType component.  All types defined there have
  133.    a label beginning in 'TT_'.  For examples:
  134.  
  135.      TT_Face, TT_F26Dot6, etc.
  136.  
  137.    However, the library uses a lot more of internal types that are
  138.    defined in the Types,  Tables,  and  Objs components ('tttypes' &
  139.    'tttables' files).
  140.  
  141.    By convention, all internal types, except the simplest ones like
  142.    integers, have their name beginning with a capital 'T', like in
  143.    'TFoo'.  Note that the first letter of 'foo' is also capitalized. 
  144.    The corresponding pointer type uses a capital 'P' instead, i.e. 
  145.    (TFoo*) is simply named 'PFoo'. Examples:
  146.  
  147.       typedef struct  _TTableDir
  148.       {
  149.         TT_Fixed  version;        /* should be 0x10000 */
  150.         UShort    numTables;      /* Tables number     */
  151.     
  152.         UShort    searchRange;    /* These parameters are only used  */
  153.         UShort    entrySelector;  /* for a dichotomy search in the   */
  154.         UShort    rangeShift;     /* directory. We ignore them.      */
  155.       } TTableDir;
  156.     
  157.       typedef TTableDir*  PTableDir;
  158.     
  159.    Note that we _always_ define a typedef for structures.  The original
  160.    struct label starts with '_T'.
  161.  
  162.    This convention is a famous one from the Pascal world.
  163.  
  164.  
  165.    Try to use C or Pascal types to the very least!  Rely on internally
  166.    defined equivalent types instead.  For example, not all compilers
  167.    agree on the sign of 'char', the size of 'int' is platform-specific,
  168.    etc.
  169.  
  170.    There are equivalents to the most common types in the types
  171.    components, like 'Short', 'UShort', etc.  Using the internal types
  172.    will guarantee that you won't need to replace every occurence of
  173.    'short' or wathever when compiling on a weird platform or with a
  174.    weird compiler, and there are many more than you could think of...
  175.  
  176.   d. Functions:  
  177.  
  178.    The name of a function should always begin with a capital letter, as
  179.    lowercase first letters are reserved for variables.  The name of a
  180.    function should be, again, _expressive_!  Never hesitate to put long
  181.    function names in your code: it will make the code much more
  182.    readable.
  183.  
  184.    Expressive doesn't necessarily imply long though; for instance,
  185.    reading shorts from the file stream is performed using the following
  186.    functions defined in the File component:
  187.  
  188.      Get_Byte  Get_Short, Get_UShort, Get_Long, etc.
  189.  
  190.    Which is somewhat more readable than:
  191.  
  192.      cget, sget, usget, lget, etc.
  193.  
  194.   e. Variables:
  195.  
  196.    Variable names should always begin with a lowercase letter. 
  197.    Lowercase first letters are reserved for variables in this
  198.    convention, as it has been already explained above.  You're still
  199.    welcome to use long and expressive variable names.
  200.  
  201.    Something like 'numP' can express a number of pixels, porks,
  202.    pancakes, and much more... Something like 'num_points' won't.
  203.  
  204.    Today, we're still using short variable labels in some parts of
  205.    the library. We're working on removing them however...
  206.  
  207.    As a side note, a field name is a variable name too.  There are
  208.    exceptions to the first-lowercase-letter rule, but these are only
  209.    related to fields within the structure defined by the TrueType
  210.    specification (well, at least it _should_ be that way).
  211.  
  212.  
  213. 2. Declarations & Statements:
  214.  
  215.  a. Columning:
  216.  
  217.   Try to align declarations and assignments in columns, when it proves
  218.   logical. For example (taken from ttraster.c):
  219.  
  220.   struct _TProfile
  221.   {                                                                     
  222.     Int        flow;        /* Profile orientation : Asc/Descending     */
  223.     Int        height;      /* profile's height in scanlines            */
  224.     Int        start;       /* profile's start scanline                 */
  225.     ULong      offset;      /* offset of profile's data in render pool  */
  226.     PProfile   link;        /* link to next profile                     */
  227.     Int        index;       /* index of profile's entry in trace table  */
  228.     Int        count_lines; /* count of lines having to be drawn        */
  229.     Int        start_line;  /* lines to be rendered before this profile */
  230.     PTraceRec  trace;       /* pointer to profile's current trace table */
  231.   };
  232.  
  233.     instead of
  234.  
  235.   struct _TProfile {
  236.     Int flow;           /* Profile orientation : Asc/Descending     */
  237.     Int height;         /* profile's height in scanlines            */
  238.     Int start;          /* profile's start scanline                 */
  239.     ULong offset;       /* offset of profile's data in render pool  */
  240.     PProfile link;      /* link to next profile                     */
  241.     Int index;          /* index of profile's entry in trace table  */
  242.     Int count_lines;    /* count of lines having to be drawn        */
  243.     Int start_line;     /* lines to be rendered before this profile */
  244.     PTraceRec  trace;   /* pointer to profile's current trace table */
  245.   };
  246.  
  247.   This comes from the fact that you're more interested by the field
  248.   and its function than by its type.
  249.  
  250.   Or:
  251.  
  252.     x   = i + 1;
  253.     y  += j;
  254.     min = 100;
  255.  
  256.   instead of
  257.  
  258.     x=i+1;
  259.     y+=j;
  260.     min=100;
  261.  
  262.   And don't hesitate to separate blocks of declarations with newlines
  263.   to "distinguish" logical sections.
  264.  
  265.   E.g., taken from an old source file, in the declarations of the CMap
  266.   loader:
  267.  
  268.     long             n, num_SH;
  269.     unsigned short   u;
  270.     long             off;
  271.     unsigned short   l;
  272.     long             num_Seg;
  273.     unsigned short*  glArray;
  274.     long             table_start;
  275.     int              limit, i;
  276.  
  277.     TCMapDir         cmap_dir;
  278.     TCMapDirEntry    entry_;
  279.     PCMapTable       Plcmt;
  280.     PCMap2SubHeader  Plcmsub;
  281.     PCMap4           Plcm4;
  282.     PCMap4Segment    segments;
  283.  
  284.   instead of
  285.  
  286.     long n, num_SH;
  287.     unsigned short u;
  288.     long off;
  289.     unsigned short l;
  290.     long num_Seg;
  291.     unsigned short *glArray;
  292.     long table_start;
  293.     int limit, i;
  294.  
  295.     TCMapDir cmap_dir;
  296.     TCMapDirEntry entry_;
  297.     PCMapTable Plcmt;
  298.     PCMap2SubHeader Plcmsub;
  299.     PCMap4 Plcm4;
  300.     PCMap4Segment segments;
  301.  
  302.  
  303.   b. Aliases and the 'with' clause:
  304.  
  305.    The Pascal language comes with a very handy 'with' clause that is
  306.    often used when dealing with the fields of a same record.  The
  307.    following Pascal source extract
  308.  
  309.     with table[incredibly_long_index] do
  310.     begin
  311.       x := some_x;
  312.       y := some_y;
  313.       z := wathever_the_hell;
  314.     end;
  315.  
  316.   is usually translated to:
  317.  
  318.     table[incredibly_long_index].x = some_x;
  319.     table[incredibly_long_index].y = some_y;
  320.     table[incredibly_long_index].z = wathever_the_hell;
  321.  
  322.   When a lot of fields are involved, it is usually helpful to define
  323.   an 'alias' for the record, like in:
  324.  
  325.     alias = table + incredibly_long_index;
  326.  
  327.     alias->x = some_x;
  328.     alias->y = some_y;
  329.     alias->z = wathever_the_hell;
  330.  
  331.   which gives a clearer source code, and eases the compiler's
  332.   optimization work.
  333.  
  334.   Though the use of aliases is currently not fixed in the current
  335.   library source, it is useful to follow one of these rules:
  336.  
  337.   - avoid an alias with a stupid, or cryptic name, something like:
  338.  
  339.     TFooRecord  tfr;
  340.     ....
  341.     [lots of lines snipped]
  342.     ....
  343.  
  344.     tfr = weird_table + weird_index;
  345.  
  346.     ...
  347.  
  348.     tfr->num = n;  
  349.  
  350.     it doesn't really help to guess what 'tfr' stands for several lines
  351.     after its declaration, even if it's an extreme contraction of one
  352.     particular type.
  353.  
  354.     something like 'cur_record' or 'alias_cmap' is better.  The current
  355.     source also uses a prefix of 'Pl' for such aliases (like Pointer to
  356.     Local alias), but this use is _not_ encouraged.  If you want to use
  357.     prefixes, use 'loc_', 'cur_' or 'al_' at the very least, with a
  358.     descriptive name following.
  359.  
  360.     Or simply use a local variable with a semi-expressive name:
  361.  
  362.     { 
  363.       THorizontalHeader  hheader;
  364.       TVerticalHeader    vheader;
  365.  
  366.       hheader = instance->fontRes->horizontalHeader;
  367.       vheader = instance->fontRes->verticalHeader;
  368.  
  369.       hheader->foo = bar;
  370.       vheader->foo = bar2;
  371.       ...
  372.     }
  373.  
  374.     which is much better than:
  375.  
  376.     { 
  377.       THorizontalHeader Plhhead;
  378.       TVerticalHeader Plvhead;
  379.  
  380.       Plhhead = instance->fontRes->horizontalHeader;
  381.       Plvhead = instance->fontRes->verticalHeader;
  382.  
  383.       Plhhead->foo = bar;
  384.       Plvhead->foo = bar2;
  385.       ...
  386.     }
  387.  
  388.  
  389. 3. Blocks:
  390.  
  391.   Block separation is done with '{' and '}'.  We do not use the K&R
  392.   convention which becomes only useful with an extensive use of tabs. 
  393.   The '{' and its corresponding '}' should always be on the same
  394.   column.  It makes it easier to separate a block from the rest of the
  395.   source, and it helps your _brain_ associates the accolades easily
  396.   (ask any Lisp programmer on the topic!).
  397.   
  398.   Use 2 spaces for the next indentation level.
  399.  
  400.   Never use tabs in your code, their widths may vary with editors and
  401.   systems.
  402.  
  403.   Example:
  404.  
  405.     if (condition_test) {
  406.             waow mamma;
  407.             I'm doing K&R format;
  408.             just like the Linux kernel;
  409.     } else {
  410.             This test failed poorly;
  411.     }
  412.  
  413.   is _OUT_!
  414.  
  415.  
  416.     if (condition_test)
  417.     {
  418.        This code isn't stuck to the condition;
  419.        read it on paper, you'll find it more;
  420.        pleasant to the eye;
  421.     }
  422.     else
  423.     {
  424.        Of course, this is a matter of taste;
  425.        That's just the way it is in this convention;
  426.        and you should follow it to be homogenous with;
  427.        the rest of the FreeType code;
  428.     }
  429.  
  430.   is _IN_!
  431.  
  432.  
  433. 4. Macros:
  434.  
  435.   Macros should be made of uppercase letters.  When a macro label is
  436.   forged from several words, it is possible to only uppercasify the
  437.   first word, using an underscore to separate the nouns.  This is used
  438.   in ttload.c, ttgload.c and ttfile.c with macros like :
  439.  
  440.     ACCESS_Frame, GET_UShort, CUR_Stream
  441.  
  442.   The role of the macros used throughout the engine is explained later
  443.   in this document.
  444.  
  445.  
  446. II. Design Conventions:
  447.  
  448. 1. Modularity and Components Layout:
  449.  
  450.   The FreeType engine has been designed with portability in mind.
  451.   This implies the ability to compile and run it on a great variety
  452.   of systems and weird environments, unlike many packages where the
  453.   word strictly means 'run on a bunch of Unix-like systems'.  We
  454.   have thus decided to stick to the following restrictions :
  455.  
  456.   - The C version is written in ANSI C. The Pascal version compiles
  457.     and run under Turbo Pascal 5.0 and compatible compilers..
  458.   
  459.   - The library, when compiled with gcc, doesn't produce any warning
  460.     with the '-ansi -pedantic' flags. Other compilers with better
  461.     checks may produce ANSI warnings that we'd be happy to now
  462.     about.
  463.      
  464.     ( NOTE :  It can of course be compiled by an 'average' C
  465.               compiler, and even by a C++ one.. )
  466.  
  467.   - It only requires in its simplest form an ANSI libc to compile,
  468.     and no utilities other than a C pre-processor, compiler and
  469.     linker.
  470.  
  471.   - It is written in a modular fashion. Each module is called a
  472.     'component' and is made of two files in the C version ( an
  473.     interface '.h' and body '.c' ) and one file in the Pascal one.
  474.  
  475.   - The very low-level components can be easily replaced by
  476.     system-specific ones that do not rely on the standard libc.
  477.     These components deal mainly with i/o, memory and mutex
  478.     operations.
  479.  
  480.   - A client application must only include one interface file, named
  481.     'freetype.h' or 'freetype.pas' to use the engine.  All other
  482.     components should never be used or accessed by client
  483.     applications, and their name always begin with a 'tt' prefix :
  484.  
  485.       ttmemory, ttobjs, ttinterp, ttapi, etc ..
  486.  
  487.   - All configuration options are gathered in two files.  One
  488.     contains the processor and OS specific configuration options,
  489.     while the other treats options that may be enabled or disabled
  490.     by the developper to test specific features ( like assertions,
  491.     debugging, etc .. ).
  492.  
  493.  
  494.   IMPORTANT NOTES :
  495.  
  496.      These restrictions only apply to the core engine.  The package
  497.      that comes with it contains several test programs sources that
  498.      are much less portable, even if they present a modular model
  499.      inspired from the engine's layout.
  500.  
  501.   The components currently found in the 'c/lib' directory are :
  502.  
  503.    -------- high-level interface -------------------
  504.  
  505.    freetype.h    high-level API, to be used by client applications
  506.  
  507.    ttapi.c       implementation of the api found in 'freetype.h'
  508.  
  509.    -------- configuration --------------------------
  510.  
  511.    ttconfig.h    engine configuration options. These are commented
  512.                  and switched by hand by the developper.  See
  513.                  section 2 below for more info.
  514.  
  515.    ft-conf.h     included by ttconfig.h, this file isn't part of the
  516.                  'c/lib' directory, but depends on the target
  517.                  environment. See section 2 blow for more info.
  518.                  
  519.    ------- definitions -----------------------------
  520.  
  521.    tttypes.h     the engine's internal types definitions
  522.    tttables.h    the TrueType tables definitions, per se the Specs
  523.    tttags.h      the TrueType table tags definitions
  524.    tterror.h/c   the error and debugging component
  525.  
  526.    ttdebug.h/c   only used by the debugger, should not be linked into
  527.                  a release build.
  528.  
  529.    ttcalc.h/c    math component used to perform some computations
  530.                  with an intermediate 64-bit precision.
  531.  
  532.    ------- replaceable components --------------------
  533.  
  534.    ttmemory.h/c  memory component. This version uses the ANSI libc
  535.                  but can be replaced easily by  your own version.
  536.  
  537.    ttfile.h/c    stream i/o component. This version uses the ANSI
  538.                  libc but can be replaced easily by your own
  539.                  version.  Compiled only if file memomry-mapping
  540.                  isn't available on your system.
  541.  
  542.    ttfile2.h/c   Unix-specific file memory-mapping version of the
  543.                  file component.  It won't be compiled on other
  544.                  systems.  Usually results in much faster file
  545.                  access (about 2x on my SCSI P166)
  546.  
  547.    ttmutex.h/c   generic mutex component.  This version is dummy and
  548.                  should only be used for a single-thread build.  You
  549.                  _need_ to replace this component's body with your
  550.                  own implementation to be able to build a threaded
  551.                  version of the engine.
  552.  
  553.    ------- data management --------------------------
  554.  
  555.    ttengine.h    the engine instance record definition, root of
  556.                  all engine data.
  557.  
  558.    ttlists.h/c   generic lists manager
  559.    ttcache.h/c   generic cache manager
  560.  
  561.    ttobjs.h/c    the engine's object definitions and implementations
  562.                  contains structure, constructors, destructors and
  563.                  methods for the following objects :
  564.  
  565.                     face, instance, glyph, execution_context
  566.  
  567.    ttload.h/c    the TrueType tables loader.
  568.  
  569.    ttgload.h/c   the glyph loader. A component in itself, due to
  570.                  the task's complexity..
  571.  
  572.    ttindex.h/c   the character mapping to glyph index conversion
  573.                  routines.  Implements functions defined in
  574.                  'freetype.h'
  575.  
  576.    ttinterp.h/c  the TrueType instructions interpreter. Probably the
  577.                  nicest source in this engine.  Apparently, many
  578.                  have failed to produce a comparable one due to the
  579.                  very poorly written specification !!  It took me
  580.                  three months of my spare time to get it working
  581.                  correctly !! :-)
  582.  
  583.    ttraster.h/c  the engine's second best piece.  This is the
  584.                  scan-line converter.  Performs gray-level rendering
  585.                  (a.k.a. font-smoothing) as well as dropout-control.
  586.  
  587. 2. Configuration and Debugging :
  588.  
  589.   As stated above, configuration depends on two files :
  590.  
  591.   The environment configuration file :    'ft-conf.h'
  592.  
  593.     This file contains the definitions of many configuration options
  594.     that are processor and OS-dependent.  On Unix systems, this file
  595.     is generated automatically by the 'configure' script that comes
  596.     with the released package.
  597.     
  598.     On other environments, it is located on one of the architecture
  599.     directories found in 'c/arch' (e.g. 'c/arch/os2/ft-conf.h').
  600.   
  601.     The path to this file should be passed to the compiler when
  602.     compiling _each_ component. ( typically with an -I option ).
  603.  
  604.   The engine configuration file :    'ttconfig.h'
  605.  
  606.     This file contains many configuration options that the
  607.     developper can turn on or off to experiment some 'features' of
  608.     the engine that are not part of its 'simplest' form. The
  609.     options are commented.
  610.  
  611.  
  612.   Note that the makefiles are compiler-specific..
  613.  
  614.  
  615.   It is possible to enable the dumping of debugging information
  616.   by compiling the components with the DEBUG configuration constant.
  617.  
  618.   The effect of this flag will be, for the following components :
  619.  
  620.     ttload     dumps information to stderr about the tables loaded
  621.  
  622.     ttgload    dumps information to stderr about the loaded glyph
  623.  
  624.     ttmemory   compile a version of the component which includes a
  625.                very simple memory block tracking scheme. This will
  626.                dump the number of leaked blocks when the engine is
  627.                closed ( i.e. when calling TT_FreeType_Done )
  628.  
  629.     ttinterp   will include an on-line simple text-mode debugger
  630.                which will be called whenever you hint a glyph.
  631.  
  632.  
  633.  
  634.   If you want to port the engine to another environment, you will
  635.   need to :
  636.  
  637.   - write a new 'ft-conf.h' for it.  Just copy one of those available
  638.     and change the flags accordingly (they're all commented).
  639.     
  640.   - replace the memory, file and mutex component with yours,
  641.     presenting the same interface and behaviour.
  642.     
  643.   - Eventually add some code in ttapi.c to initialize system-specific
  644.     data with the engine.
  645.  
  646.  
  647.  
  648.  
  649. III. Usage conventions:
  650.  
  651.  
  652. 1. Error Handling:
  653.  
  654.   Error handling has been refined to allow reentrant builds of the
  655.   library, available only in the C version. We thus have now two
  656.   different conventions :
  657.  
  658.   In Pascal :
  659.  
  660.     A global error variable is used to report errors when they are
  661.     detected. All functions return a boolean that indicates success
  662.     or failure of the call.  When an error occurs within a given
  663.     function, the latter must set the error variable and return false
  664.     (which means failure).
  665.   
  666.     It is then possible to make several calls in a single 'if'
  667.     statement like in :
  668.   
  669.        if  not Perform_Action_1( parms_of_1 )  or
  670.            not Perform_Action_2( parms_of_2 )  or
  671.            not Perform_Action_3( parms_of_3 )  then goto Fail;
  672.   
  673.     where execution will jump to the 'Fail' label whenever an error
  674.     occurs in the sequence of actions invoked in the condition.
  675.  
  676.  
  677.   In C :
  678.  
  679.     global errors are forbidden in re-entrant builds.  Each function
  680.     thus returns directly an error code.  A return value of 0 means
  681.     that no error occured, while any other value indicates a failure
  682.     of any kind.
  683.  
  684.     This convention is more constraining than the one used in the
  685.     Pascal source. The above Pascal statement should be translated
  686.     into the following C fragment :
  687.  
  688.        rc = Perform_Action_1( parms_of_1 );
  689.        if (rc)
  690.          goto Fail;
  691.  
  692.        rc = Perform_Action_2( parms_of_2 );
  693.        if (rc)
  694.          goto Fail;
  695.  
  696.        rc = Perform_Action_3( parms_of_3 );
  697.        if (rc)
  698.          goto Fail;
  699.  
  700.     which, while being equivalent, isn't as pleasantly readable.
  701.  
  702.     One 'simple' way to match the original fragment would be to
  703.     write :
  704.  
  705.        if ( (rc = Perform_Action_1( parms_of_1 )) ||
  706.             (rc = Perform_Action_2( parms_of_2 )) ||
  707.             (rc = Perform_Action_3( parms_of_3 )) )
  708.          goto Fail;
  709.  
  710.     which is better but uses assignements within expressions, which
  711.     are always delicate to manipulate in C (the risk of writing '=='
  712.     exists, and would go unnoticed by a compilers).  Moreover, the
  713.     assignements are a bit redundant, and don't express much things
  714.     about the actions performed (they only speak of the error
  715.     management issue).
  716.  
  717.     That is why some macros have been defined for the mostly used
  718.     functions. Most of them relate to very low-level routines that
  719.     are called very often ( i/o, mutex and memory mainly ).  Each
  720.     macro produces an implicit assignement to a variable called
  721.     'error', and can be used instead as a simple function call. Eg :
  722.  
  723.       if ( PERFORM_Action_1( parms_of_1 ) ||
  724.            PERFORM_Action_2( parms_of_2 ) ||
  725.            PERFORM_Action_3( parms_of_3 ) )
  726.         goto Fail;
  727.  
  728.     with
  729.       
  730.       #define PERFORM_Action_1(parms_1) (error = Perform_Action_1(parms_1))
  731.       #define PERFORM_Action_2(parms_1) (error = Perform_Action_2(parms_1))
  732.       #define PERFORM_Action_3(parms_1) (error = Perform_Action_3(parms_1))
  733.  
  734.       defined at the beginning of the file.
  735.  
  736.     There, the developper only needs to define a local 'error' variable
  737.     and use the macros directly in its code, without caring about the
  738.     actual error handling performed. Examples of such uses can be
  739.     found in 'ttload.c' and 'ttgload.c'. Moreover, the structure of
  740.     the source files remain very similar, even though the error
  741.     handling is very different.
  742.     
  743.     This convention is very close to the use of exceptions in
  744.     languages like C++, Pascal, Java, etc.. where the developper
  745.     focuses on the actions to perform, and not every little error
  746.     checking..
  747.  
  748.  
  749. 2. Font File I/O:
  750.  
  751.   a. Streams:
  752.  
  753.     The engine uses 'streams' to access the font files.  A stream is a
  754.     structure defined in the File component containing information
  755.     used to access files through a system-specific i/o library.
  756.  
  757.     The current implementation of the File component uses the ANSI libc
  758.     i/o functions.  However, for the sake of embedding in light systems
  759.     and independence of a complete libc, it is possible to re-implement
  760.     the component for a specific system or OS, letting it use system
  761.     calls.
  762.     
  763.     A stream is of type 'TStream' defined in the TTObjs interface.
  764.     The type is (void*) but actually points to a structure defined
  765.     within the File component.
  766.  
  767.     A stream is created, managed and closed through the interface of
  768.     the File component.  Several implementations of the same
  769.     component can co-exist, each taking advantage of specific system
  770.     features (the'ttfile2.c' uses memory-mapped files for instance)
  771.     as long as it respects the interface.
  772.  
  773.   b. Frames:
  774.  
  775.     TrueType is tied to the big-endian format, which implies that
  776.     reading shorts or longs from the font file may need conversions
  777.     depending on the target processor.  To be able to easily detect
  778.     read errors and allow simple conversion calls or macros, the
  779.     engine is able to access a font file using 'frames'.
  780.  
  781.     A frame is simply a sequence of successive bytes taken from the
  782.     input file at the current position.  A frame is pre-loaded in
  783.     memory by a 'TT_Access_Frame' call of the File component.
  784.  
  785.     It is then possible to read all sizes of data through the Get_xxx
  786.     functions, like Get_Byte, Get_Short, Get_UShort, etc.
  787.  
  788.     When all important data is read, the frame can be released by a
  789.     call to 'TT_Forget_Frame'.
  790.  
  791.     The benefits of frames are various:
  792.  
  793.       Consider these two approaches at extracting values:
  794.  
  795.         if ( (error = Read_Short( &var1 )) ||
  796.              (error = Read_Long ( &var2 )) ||
  797.              (error = Read_Long ( &var3 )) ||
  798.              (error = Read_Short( &var4 )) )
  799.  
  800.           return FAILURE;
  801.  
  802.       and
  803.  
  804.         if ( (error = TT_Access_Frame( 16L )) ) /* Read 16 next bytes */
  805.           return error;                /* The Frame could not be read */
  806.  
  807.         var1 = Get_Short();   /* extract values from the frame */
  808.         var2 = Get_Long();
  809.         var3 = Get_Long();
  810.         var4 = Get_Short();
  811.  
  812.         TT_Forget_Frame();   /* release the frame */
  813.  
  814.       In the first case, there are four error assignements with
  815.       four checks of the file read.  This increases un-necessarily
  816.       the size of the generated code.  Moreover, you must be sure
  817.       that var1 and var4 are short variables, and var2/var3 long
  818.       ones, if you want to avoid bugs and/or compiler warnings.
  819.  
  820.       In the second case, you perform only one check for the read, and
  821.       exit immediately on failure.  Then the values are extracted from
  822.       the frame, as the result of function calls.  This means that you
  823.       can use automatic type conversion; there is no problem if var1
  824.       and var4 are longs, unlike previously.
  825.  
  826.       On big-endian machines, the Get_xxx functions could also be
  827.       simple macros that merely peek the values directly from the
  828.       frame, which speeds and simplifies the generated code!
  829.  
  830.       And finally, frames are ideal when you're using memory-mapped
  831.       files, as the frame is not really 'pre-loaded' and never uses any
  832.       'heap' space.
  833.  
  834.       IMPORTANT    You CANNOT nest several frame accesses.  There is
  835.                    only one available at a time for a specific
  836.                    instance.
  837.  
  838.                    It is also the programmer's responsablity to never
  839.                    extract more data than was pre-loaded in the frame! 
  840.                    (But you usually know how many values you want to
  841.                    extract from the file before doing so).
  842.  
  843.  
  844. 3. Memory Management:
  845.  
  846.   The library now uses a component which interface looks like a lot
  847.   malloc/free. It defines only two functions :
  848.  
  849.  
  850.   * Alloc
  851.  
  852.    To be used like malloc, except that it returns an error code, not
  853.    an address.  Its arguments are the size of the requested block
  854.    and the address of the target pointer to the 'fresh' block.  An
  855.    error code is returned in case of failure (and this will also set
  856.    the target pointer to NULL), 0 in case success.
  857.  
  858.    Alloc should always respect the following rules :
  859.  
  860.    - requesting a block of size 0 should set the target pointer to
  861.      NULL and return no error code (i.e. return 0)
  862.  
  863.    - the returned block is always zeroed.  This is an important
  864.      assumption of other parts of the library.
  865.  
  866.    If you wish to replace the memory component with your own, please
  867.    respect this behaviour, or your engine won't work correctly.
  868.  
  869.  
  870.   * Free
  871.  
  872.    As you may have already guessed, Free is Alloc's counterpart.  It
  873.    takes as argument the _target pointer's address_ !!  You should
  874.    _never_ pass the block's address directly, i.e. the pointer, to
  875.    Free.
  876.  
  877.    Free should always respect the following rules :
  878.  
  879.    - calling it with a NULL argument, or the address of a NULL
  880.      pointer is valid, and should return success.
  881.  
  882.    - the pointer is always set to NULL after the block's
  883.      deallocation. This is also an important assumption of many
  884.      other parts of the library.
  885.  
  886.    If you wish to replace the memory component with your own, please
  887.    respect this behaviour, or your engine won't work correctly.
  888.  
  889.  
  890.   As the pointers addresses needed as arguments are typed 'void**',
  891.   the component's interface also provides in the C version some
  892.   macros to help use them more easily, these are :
  893.  
  894.     MEM_Alloc     a version of Alloc that casts the argument pointer  
  895.                   to (void**)
  896.  
  897.     ALLOC         same as MEM_Alloc, but with an assignement to a
  898.                   variable called 'error'.  See 'error handling'
  899.                   above for more info on this.
  900.  
  901.     FREE          a version of Free that casts the argument pointer
  902.                   to (void**). There is currently no error handling
  903.                   by with this macro.
  904.  
  905.     MEM_Set       an alias for 'memset', which can be easily changed
  906.                   to anything else if you wish to use a different
  907.                   memory manager than the functions provided by the
  908.                   ANSI libc
  909.  
  910.     MEM_Copy      an alias of 'memcpy' or 'bcopy' used to move blocks  
  911.                   of memory.  You may change it to something
  912.                   different if you wish to use something else that
  913.                   your standard libc
  914.  
  915.  
  916. 4. Support for threaded environments:
  917.  
  918.   Support for threaded environments have been added to the C
  919.   sources, and only to these.  It is now theorically possible to
  920.   build three distinct versions of the library :
  921.  
  922.     single-thread build :
  923.  
  924.       The default build.  This one doesn't known about different
  925.       threads.  Hence, no code is generated to perform coherent data
  926.       sharing and locking.
  927.  
  928.     thread-safe build :
  929.  
  930.       With this build, several threads can use the library at the
  931.       same time.  However, some key components can only be used by
  932.       one single thread at a time, and use a mutex to synchronize
  933.       access to their functions.  They are mainly the file, raster
  934.       and interpreter components.
  935.  
  936.     re-entrant build :
  937.  
  938.       A re-entrant version is able to perform certain actions in
  939.       parallel that a thread-safe one cannot.  This includes
  940.       accessing file(s) in parallel, interpreting different
  941.       instruction streams in parallel, or even scan-line converting
  942.       distinct glyphs at the same time.
  943.  
  944.   Note that most of the latest changes in the engine are making the
  945.   distinction between the thread-safe and re-entrant builds thinner
  946.   than ever. The only remaining problem being the raster component.
  947.  
  948.   Note also that the threaded build is not operational if you read
  949.   this before the beta release, and that it hasn't been tested yet.
  950.  
  951.   Chances are that the beta release will only present two builds :
  952.   a singly-threaded one, as well as a re-entrant one.
  953.  
  954.   There is a ttmutex component that presents a generic interface to
  955.   mutex operations. It should be re-implemented for each platform.
  956.  
  957.  
  958. 5. Object Management :
  959.  
  960.   The engine defines and manages several kinds of objects :
  961.  
  962.    - Faces :
  963.  
  964.        A face is an object used to model a given TrueType font file,
  965.        and collects the font's data that is independent of any
  966.        output.  An application typically creates one face object per
  967.        font file it wants to use.
  968.  
  969.    - Instances :
  970.  
  971.        An instance models a face's specific data relative to a given
  972.        device resolution, pointsize and/or transform (for slanted
  973.        and rotated text).  An instance object is always tied to its
  974.        'parent' face, and is destroyed with it.  An application
  975.        typically creates one instance object per pointsize it wants
  976.        to use for a given face.
  977.  
  978.     - Glyphs :
  979.  
  980.        A glyph object is a structure used to contain the data that
  981.        can come from _any_ glyph found in a given face.  The glyph
  982.        object is created and tied from/to its 'parent' face, and is
  983.        sized
  984.        
  985.