summaryrefslogtreecommitdiff
path: root/Build/source/libs/freetype/freetype-1.5/docs/convntns.txt
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/freetype/freetype-1.5/docs/convntns.txt')
-rw-r--r--Build/source/libs/freetype/freetype-1.5/docs/convntns.txt970
1 files changed, 0 insertions, 970 deletions
diff --git a/Build/source/libs/freetype/freetype-1.5/docs/convntns.txt b/Build/source/libs/freetype/freetype-1.5/docs/convntns.txt
deleted file mode 100644
index 01177854f3d..00000000000
--- a/Build/source/libs/freetype/freetype-1.5/docs/convntns.txt
+++ /dev/null
@@ -1,970 +0,0 @@
-
- Conventions and Design in the FreeType library
- ----------------------------------------------
-
-
-Table of Contents
-
-Introduction
-
-I. Style and Formatting
-
- 1. Naming
- 2. Declarations & Statements
- 3. Blocks
- 4. Macros
-
-II. Design conventions
-
- 1. Modularity and Components Layout
- 2. Configuration and Debugging
-
-III. Usage conventions
-
- 1. Error handling
- 2. Font File I/O
- 3. Memory management (due to change soon)
- 4. Support for threaded environments
- 5. Object Management
-
-
-Introduction
-============
-
-This text introduces the many conventions used within the FreeType
-library code. Please read it before trying any modifications or
-extensions of the source code.
-
-
-
-I. Style and Formatting
-=======================
-
-The following coding rules are extremely important to keep the
-library's source code homogeneously. Keep in mind the following
-points:
-
- - `Humans read source code, not machines' (Donald Knuth)
-
- The library source code should be as readable as possible, even
- by non-C experts. With `readable', two things are meant: First,
- the source code should be pleasant to the eye, with sufficient
- whitespace and newlines, to not look like a boring stack of
- characters stuck to each other. Second, the source should be
- _expressive_ enough about its goals. This convention contains
- rules that can help the source focus on its purpose, not on a
- particular implementation.
-
- - `Paper is the _ultimate_ debugger' (David Turner :-)
-
- There is nothing like sheets of paper (and a large floor) to
- help you understand the design of a library you're new to, or to
- debug it. The formatting style presented here is targeted at
- printing. For example, it is more than highly recommended to
- never produce a source line that is wider than 78 columns. More
- on this below.
-
-
-1. Naming
----------
-
- a. Components
-
- A unit of the library is called a `component'. Each component
- has at least an interface, and often a body. The library comes
- in two language flavors, C and Pascal (the latter severely out
- of date unfortunately). A component in C is defined by two
- files, one `.h' header and one `.c' body, while a Pascal
- component is contained in a single `.pas' file.
-
- All component source file names begin with the `tt' prefix, with
- the exception of the `FreeType' component. For example, the
- file component is implemented by the files `ttfile.h',
- `ttfile.c', and `ttfile.pas'. Only lowercase letters should be
- used, following the 8+3 naming convention to allow compilation
- under DOS.
-
- In the C version, a single component can have multiple bodies.
- For example, `ttfile.c' provides stream i/o through standard
- ANSI libc calls, while `ttfile2.c' implements the same thing
- using a Unix memory-mapping API.
-
- The FreeType component is an interface-only component.
-
- b. Long and expressive labels
-
- Never hesitate to use long labels for your types, variables,
- etc.! Except maybe for things like very trivial types, the
- longest is the best, as it increases the source's
- _expressiveness_. Never forget that the role of a label is to
- express the `function' of the entity it represents, not its
- implementation!
-
- NOTE: Hungarian notation is NOT expressive, as it sticks the
- `type' of a variable to its name. A label like `usFoo'
- rarely tells the use of the variable it represents.
-
- And the state of a variable (global, static, dynamic)
- isn't helpful anymore.
-
- Avoid Hungarian Notation like the *plague*!
-
-
- When forging a name with several nouns
- (e.g. `number-of-points'), use an uppercase letter for the first
- letter of each word (except the first), like:
-
- numberOfPoints
-
- You are also welcomed to introduce underscores `_' in your
- labels, especially when sticking large nouns together, as it
- `airs' the code greatly. E.g.:
-
- `numberOfPoints' or `number_Of_Points'
-
- `IncredibleFunction' or `Incredible_Function'
-
- And finally, always put a capital letter after an underscore,
- except in variable labels that are all lowercase:
-
- `number_of_points' is OK for a variable (_all_ lowercase label)
-
- `incredible_function' is NOT for a function!
- ^ ^
-
- `Microsoft_windows' is a *shame*!
- ^ ^
-
- `Microsoft_Windows' isn't really better, but at least its a
- ^ ^ correct function label within this
- convention ;-)
-
- c. Types
-
- All types that are defined for use by FreeType client
- applications are defined in the FreeType component. All types
- defined there have a label beginning with `TT_'. Examples:
-
- TT_Face, TT_F26Dot6, etc.
-
- However, the library uses a lot more of internal types that are
- defined in the Types, Tables, and Objs components (`tttypes' &
- `tttables' files).
-
- By convention, all internal types, except the simplest ones like
- integers, have their name beginning with a capital `T', like in
- 'TFoo'. Note that the first letter of `foo' is also
- capitalized. The corresponding pointer type uses a capital `P'
- instead, i.e. (TFoo*) is simply named 'PFoo'. Examples:
-
- typedef struct _TTableDir
- {
- TT_Fixed version; /* should be 0x10000 */
- UShort numTables; /* Tables number */
-
- UShort searchRange; /* These parameters are only used */
- UShort entrySelector;/* for a dichotomy search in the */
- UShort rangeShift; /* directory. We ignore them. */
- } TTableDir;
-
- typedef TTableDir* PTableDir;
-
- Note that we _always_ define a typedef for structures. The
- original struct label starts with `_T'.
-
- This convention is a famous one from the Pascal world.
-
- Try to use C or Pascal types to the very least! Rely on
- internally defined equivalent types instead. For example, not
- all compilers agree on the sign of `char'; the size of `int' is
- platform-specific, etc.
-
- There are equivalents to the most common types in the `Types'
- components, like `Short', `UShort', etc. Using the internal
- types will guarantee that you won't need to replace every
- occurence of `short' or wathever when compiling on a weird
- platform or with a weird compiler, and there are many more than
- you could think of...
-
- d. Functions
-
- The name of a function should always begin with a capital
- letter, as lowercase first letters are reserved for variables.
- The name of a function should be, again, _expressive_! Never
- hesitate to put long function names in your code: It will make
- the code much more readable.
-
- Expressiveness doesn't necessarily imply lengthiness though; for
- instance, reading shorts from a file stream is performed using
- the following functions defined in the `File' component:
-
- Get_Byte, Get_Short, Get_UShort, Get_Long, etc.
-
- Which is somewhat more readable than:
-
- cget, sget, usget, lget, etc.
-
- e. Variables
-
- Variable names should always begin with a lowercase letter.
- Lowercase first letters are reserved for variables in this
- convention, as it has been already explained above. You're
- still welcome to use long and expressive variable names.
-
- Something like `numP' can express a number of pixels, porks,
- pancakes, and much more... Something like `num_points' won't.
-
- Today, we are still using short variable labels in some parts of
- the library. We're working on removing them however...
-
- As a side note, a field name of a structure counts as a variable
- name too. There are exceptions to the first-lowercase-letter
- rule, but these are only related to fields within the structure
- defined by the TrueType specification (well, at least it
- _should_ be that way).
-
-
-2. Declarations & Statements
-----------------------------
-
- a. Columning
-
- Try to align declarations and assignments in columns, if it
- proves logical. For example (taken from `ttraster.c'):
-
- struct _TProfile
- {
- Int flow; /* Profile orientation : Asc/Descending */
- Int height; /* profile's height in scanlines */
- Int start; /* profile's start scanline */
- ULong offset; /* offset of profile's data in render pool */
- PProfile link; /* link to next profile */
- Int index; /* index of profile's entry in trace table */
- Int count_lines; /* count of lines having to be drawn */
- Int start_line; /* lines to be rendered before this profile */
- PTraceRec trace; /* pointer to profile's current trace table */
- };
-
- instead of
-
- struct _TProfile {
- Int flow; /* Profile orientation : Asc/Descending */
- Int height; /* profile's height in scanlines */
- Int start; /* profile's start scanline */
- ULong offset; /* offset of profile's data in render pool */
- PProfile link; /* link to next profile */
- Int index; /* index of profile's entry in trace table */
- Int count_lines; /* count of lines having to be drawn */
- Int start_line; /* lines to be rendered before this profile */
- PTraceRec trace; /* pointer to profile's current trace table */
- };
-
- This comes from the fact that you're more interested by the
- field and its function than by its type.
-
- Or:
-
- x = i + 1;
- y += j;
- min = 100;
-
- instead of
-
- x=i+1;
- y+=j;
- min=100;
-
- And don't hesitate to separate blocks of declarations with
- newlines to `distinguish' logical sections.
-
- E.g., taken from an old source file, in the declarations of the CMap
- loader:
-
- long n, num_SH;
- unsigned short u;
- long off;
- unsigned short l;
- long num_Seg;
- unsigned short* glArray;
- long table_start;
- int limit, i;
-
- TCMapDir cmap_dir;
- TCMapDirEntry entry_;
- PCMapTable Plcmt;
- PCMap2SubHeader Plcmsub;
- PCMap4 Plcm4;
- PCMap4Segment segments;
-
- instead of
-
- long n, num_SH;
- unsigned short u;
- long off;
- unsigned short l;
- long num_Seg;
- unsigned short *glArray;
- long table_start;
- int limit, i;
- TCMapDir cmap_dir;
- TCMapDirEntry entry_;
- PCMapTable Plcmt;
- PCMap2SubHeader Plcmsub;
- PCMap4 Plcm4;
- PCMap4Segment segments;
-
- b. Aliases and the `with' clause
-
- The Pascal language comes with a very handy `with' clause that
- is often used when dealing with the fields of a same record.
- The following Pascal source extract
-
- with table[incredibly_long_index] do
- begin
- x := some_x;
- y := some_y;
- z := wathever_the_hell;
- end;
-
- is usually translated to:
-
- table[incredibly_long_index].x = some_x;
- table[incredibly_long_index].y = some_y;
- table[incredibly_long_index].z = wathever_the_hell;
-
- When a lot of fields are involved, it is usually helpful to
- define an `alias' for the record, like in:
-
- alias = table + incredibly_long_index;
-
- alias->x = some_x;
- alias->y = some_y;
- alias->z = wathever_the_hell;
-
- which gives cleaner source code, and eases the compiler's
- optimization work.
-
- Though the use of aliases is currently not fixed in the current
- library source, it is useful to follow one of these rules:
-
- - Avoid an alias with a stupid, or cryptic name, something like:
-
- TFooRecord tfr;
- ....
- [lots of lines snipped]
- ....
-
- tfr = weird_table + weird_index;
-
- ...
-
- tfr->num = n;
-
- It doesn't really help to guess what 'tfr' stands for several
- lines after its declaration, even if it's an extreme
- contraction of one particular type.
-
- Something like `cur_record' or `alias_cmap' is better. The
- current source also uses a prefix of `Pl' for such aliases
- (like Pointer to Local alias), but this use is _not_
- encouraged. If you want to use prefixes, use `loc_', `cur_',
- or `al_' at the very least, with a descriptive name following.
-
- - Or simply use a local variable with a semi-expressive name:
-
- {
- THorizontalHeader hheader;
- TVerticalHeader vheader;
-
-
- hheader = instance->fontRes->horizontalHeader;
- vheader = instance->fontRes->verticalHeader;
-
- hheader->foo = bar;
- vheader->foo = bar2;
- ...
- }
-
- which is much better than
-
- {
- THorizontalHeader Plhhead;
- TVerticalHeader Plvhead;
-
- Plhhead = instance->fontRes->horizontalHeader;
- Plvhead = instance->fontRes->verticalHeader;
-
- Plhhead->foo = bar;
- Plvhead->foo = bar2;
- ...
- }
-
-
-3. Blocks
----------
-
- Block separation is done with `{' and `}'. We do not use the K&R
- convention which becomes only useful with an extensive use of
- tabs. The `{' and its corresponding `}' should always be on the
- same column. It makes it easier to separate a block from the rest
- of the source, and it helps your _brain_ associates the accolades
- easily (ask any Lisp programmer on the topic!).
-
- Use two spaces for the next indentation level.
-
- Never use tabs in your code, their widths may vary with editors
- and systems.
-
- Example:
-
- if (condition_test) {
- waow mamma;
- I'm doing K&R format;
- just like the Linux kernel;
- } else {
- This test failed poorly;
- }
-
- is _OUT_!
-
- if ( condition_test )
- {
- This code isn't stuck to the condition;
- read it on paper, you'll find it more;
- pleasant to the eye;
- }
- else
- {
- Of course, this is a matter of taste;
- That's just the way it is in this convention;
- and you should follow it to be homogenous with;
- the rest of the FreeType code;
- }
-
- is _IN_!
-
-
-4. Macros
----------
-
- Macros should be made of uppercase letters. When a macro label is
- forged from several words, it is possible to only uppercasify the
- first word, using an underscore to separate the nouns. This is
- used in ttload.c, ttgload.c and ttfile.c with macros like
-
- ACCESS_Frame, GET_UShort, CUR_Stream
-
- The role of the macros used throughout the engine is explained
- later in this document.
-
-
-
-II. Design Conventions
-======================
-
-
-1. Modularity and Components Layout
------------------------------------
-
- The FreeType engine has been designed with portability in mind.
- This implies the ability to compile and run it on a great variety
- of systems and weird environments, unlike many packages where the
- word strictly means `runs on a bunch of Unix-like systems'. We
- have thus decided to stick to the following restrictions:
-
- - The C version is written in ANSI C. The Pascal version compiles
- and run under Turbo Pascal 5.0 and compatible compilers.
-
- - The library, if compiled with gcc, doesn't produce any warning
- with the `-ansi -pedantic' flags. Other compilers with better
- checks may produce ANSI warnings that we'd be happy to now
- about.
-
- (NOTE: It can of course be compiled by an `average' C compiler,
- and even by a C++ one.)
-
- - It only requires in its simplest form an ANSI libc to compile,
- and no utilities other than a C pre-processor, compiler, and
- linker.
-
- - It is written in a modular fashion. Each module is called a
- `component' and is made of two files in the C version (an
- interface with suffix `.h' and body with suffix `.c' ) and one
- file in the Pascal one.
-
- - The very low-level components can be easily replaced by
- system-specific ones that do not rely on the standard libc.
- These components deal mainly with i/o, memory, and mutex
- operations.
-
- - A client application must only include one interface file named
- `freetype.h' resp. `freetype.pas' to use the engine. All other
- components should never be used or accessed by client
- applications, and their name always begin with a `tt' prefix:
-
- ttmemory, ttobjs, ttinterp, ttapi, etc.
-
- - All configuration options are gathered in two files. One
- contains the processor and OS specific configuration options,
- while the other treats options that may be enabled or disabled
- by the developer to test specific features (like assertions,
- debugging, etc).
-
- IMPORTANT NOTES:
-
- These restrictions only apply to the core engine. The package
- that comes with it contains several test programs sources that
- are much less portable, even if they present a modular model
- inspired from the engine's layout.
-
- The components currently found in the `lib' directory are:
-
- -------- high-level interface ----------------------------------
-
- freetype.h High-level API, to be used by client applications.
-
- ttapi.c Implementation of the api found in `freetype.h'.
-
- -------- configuration -----------------------------------------
-
- ttconfig.h Engine configuration options. These are commented
- and switched by hand by the developer. See
- section 2 below for more info.
-
- ft-conf.h Included by ttconfig.h, this file isn't part of
- the `lib' directory, but depends on the target
- environment. See section 2 blow for more info.
-
- -------- definitions -------------------------------------------
-
- tttypes.h The engine's internal types definitions.
- tttables.h The TrueType tables definitions, per se the Specs.
- tttags.h The TrueType table tags definitions.
- tterror.[ch] The error and debugging component.
-
- ttdebug.[ch] Only used by the debugger, should not be linked
- into a release build.
-
- ttcalc.[ch] Math component used to perform some computations
- with an intermediate 64-bit precision.
-
- -------- replaceable components --------------------------------
-
- ttmemory.[ch] Memory component. This version uses the ANSI libc
- but can be replaced easily by your own version.
-
- ttfile.[ch] Stream i/o component. This version uses the ANSI
- libc but can be replaced easily by your own
- version. Compiled only if file memory mapping
- isn't available on your system.
-
- ttfile2.[ch] Unix-specific file memory mapping version of the
- file component. It won't compile on other
- systems. Usually results in much faster file
- access (about 2x on a SCSI P166 system)
-
- ttmutex.[ch] Generic mutex component. This version is a dummy
- and should only be used for a single-thread build.
- You _need_ to replace this component's body with
- your own implementation to be able to build a
- threaded version of the engine.
-
- -------- data management ---------------------------------------
-
- ttengine.h The engine instance record definition, root of all
- engine data.
-
- ttlists.[ch] Generic lists manager.
- ttcache.[ch] Generic cache manager.
-
- ttobjs.[ch] The engine's object definitions and
- implementations module contains structures,
- constructors, destructors and methods for the
- following objects:
-
- face, instance, glyph, execution_context
-
- ttload.[c] The TrueType tables loader.
-
- ttgload.[ch] The glyph loader. A component in itself, due to
- the task's complexity.
-
- ttindex.[ch] The character mapping to glyph index conversion
- routines. Implements functions defined in
- `freetype.h'.
-
- ttinterp.[ch] The TrueType instructions interpreter. Probably
- the nicest source in this engine. Apparently,
- many have failed to produce a comparable one due
- to the very poorly written specification! It took
- David Turner three months of his spare time to get
- it working correctly! :-)
-
- ttraster.[ch] The engine's second best piece. This is the
- scan-line converter. Performs gray-level
- rendering (also known as font-smoothing) as well
- as dropout-control.
-
-
-2. Configuration and Debugging
-------------------------------
-
- As stated above, configuration depends on two files:
-
- The environment configuration file `ft-conf.h':
-
- This file contains the definitions of many configuration options
- that are processor and OS-dependent. On Unix systems, this file
- is generated automatically by the `configure' script that comes
- with the released package.
-
- On other environments, it is located in one of the architecture
- directories found in `arch' (e.g. `arch/os2/ft-conf.h').
-
- The path to this file should be passed to the compiler when
- compiling _each_ component. (typically with an -I option).
-
- The engine configuration file `ttconfig.h':
-
- This file contains many configuration options that the developer
- can turn on or off to experiment with some `features' of the
- engine that are not part of its `simplest' form. The options
- are commented.
-
- Note that the makefiles are compiler-specific.
-
- It is possible to enable the dumping of debugging information by
- compiling the components with the various debug macros. Please
- consult the file `ttconfig.h' for details.
-
- If you want to port the engine to another environment, you will
- need to
-
- - Write a new `ft-conf.h' file for it. Just copy one of those
- available and change the flags accordingly (they're all
- commented).
-
- - Replace the memory, file, and mutex components with yours,
- presenting the same interface and behaviour.
-
- - Eventually add some code in ttapi.c to initialize
- system-specific data with the engine.
-
-
-
-III. Usage conventions
-======================
-
-
-1. Error Handling
------------------
-
- Error handling has been refined to allow reentrant builds of the
- library, available only in the C version. We thus have now two
- different conventions.
-
- In Pascal:
-
- A global error variable is used to report errors when they are
- detected. All functions return a boolean that indicates success
- or failure of the call. If an error occurs within a given
- function, the latter must set the error variable and return
- `false' (which means failure).
-
- It is then possible to make several calls in a single `if'
- statement like:
-
- if not Perform_Action_1( parms_of_1 ) or
- not Perform_Action_2( parms_of_2 ) or
- not Perform_Action_3( parms_of_3 ) then goto Fail;
-
- where execution will jump to the `Fail' label whenever an error
- occurs in the sequence of actions invoked in the condition.
-
- In C:
-
- Global errors are forbidden in re-entrant builds. Each function
- thus returns directly an error code. A return value of 0 means
- that no error occured, while a non-zero other value indicates a
- failure of any kind.
-
- This convention is more constraining than the one used in the
- Pascal source. The above Pascal statement should be translated
- into the following C fragment:
-
- rc = Perform_Action_1( parms_of_1 );
- if ( rc )
- goto Fail;
-
- rc = Perform_Action_2( parms_of_2 );
- if ( rc )
- goto Fail;
-
- rc = Perform_Action_3( parms_of_3 );
- if ( rc )
- goto Fail;
-
- which, while being equivalent, isn't as pleasantly readable.
-
- One `simple' way to match the original fragment would be to
- write:
-
- if ( (rc = Perform_Action_1( parms_of_1 )) ||
- (rc = Perform_Action_2( parms_of_2 )) ||
- (rc = Perform_Action_3( parms_of_3 )) )
- goto Fail;
-
- which is better but uses assignments within expressions, which
- are always delicate to manipulate in C (the risk of writing `=='
- exists, and would go unnoticed by a compiler). Moreover, the
- assignments are a bit redundant and don't express much things
- about the actions performed (they only speak of the error
- management issue).
-
- That is why some macros have been defined for the most
- frequently used functions. They relate to low-level routines
- that are called very often (mainly i/o, mutex, and memory
- handling functions). Each macro produces an implicit assignment
- to a variable called `error' and can be used instead as a simple
- function call. Example:
-
- if ( PERFORM_Action_1( parms_of_1 ) ||
- PERFORM_Action_2( parms_of_2 ) ||
- PERFORM_Action_3( parms_of_3 ) )
- goto Fail;
-
- with
-
- #define PERFORM_Action_1( parms_1 ) \
- ( error = Perform_Action_1( parms_1 ) )
- #define PERFORM_Action_2( parms_1 ) \
- ( error = Perform_Action_2( parms_1 ) )
- #define PERFORM_Action_3( parms_1 ) \
- ( error = Perform_Action_3( parms_1 ) )
-
- defined at the beginning of the file.
-
- There, the developer only needs to define a local `error'
- variable and use the macros directly in the code, without caring
- about the actual error handling performed. Examples of such a
- usage can be found in `ttload.c' and `ttgload.c'. Moreover, the
- structure of the source files remain very similar, even though
- the error handling is very different.
-
- This convention is very close to the use of exceptions in
- languages like C++, Pascal, Java, etc. where the developer
- focuses on the actions to perform, and not on every little error
- checking.
-
-
-2. Font File I/O
-----------------
-
- a. Streams
-
- The engine uses `streams' to access the font files. A stream is
- a structure defined in the `File' component containing
- information used to access files through a system-specific i/o
- library.
-
- The current implementation of the File component uses the ANSI
- libc i/o functions. However, for the sake of embedding in light
- systems and independence of a complete libc, it is possible to
- re-implement the component for a specific system or OS, letting
- it use system calls.
-
- A stream is of type `TStream' defined in the `TTObjs' interface.
- The type is `(void*)' but actually points to a structure defined
- within the File component.
-
- A stream is created, managed and closed through the interface of
- the `File' component. Several implementations of the same
- component can co-exist, each taking advantage of specific system
- features (the file `ttfile2.c' uses memory-mapped files for
- instance) as long as it respects the interface.
-
- b. Frames
-
- TrueType is tied to the big-endian format, which implies that
- reading shorts or longs from the font file may need conversions
- depending on the target processor. To be able to easily detect
- read errors and allow simple conversion calls or macros, the
- engine is able to access a font file using `frames'.
-
- A frame is simply a sequence of successive bytes taken from the
- input file at the current position. A frame is pre-loaded into
- memory by a `TT_Access_Frame()' call of the `File' component.
-
- It is then possible to read all sizes of data through the
- `Get_xxx()' functions, like Get_Byte(), Get_Short(),
- Get_UShort(), etc.
-
- When all important data is read, the frame can be released by a
- call to `TT_Forget_Frame()'.
-
- The benefits of frames are various. Consider these two
- approaches at extracting values:
-
- if ( (error = Read_Short( &var1 )) ||
- (error = Read_Long ( &var2 )) ||
- (error = Read_Long ( &var3 )) ||
- (error = Read_Short( &var4 )) )
-
- return FAILURE;
-
- and
-
- /* Read the next 16 bytes */
- if ( (error = TT_Access_Frame( 16L )) )
- return error; /* The Frame could not be read */
-
- var1 = Get_Short(); /* extract values from the frame */
- var2 = Get_Long();
- var3 = Get_Long();
- var4 = Get_Short();
-
- TT_Forget_Frame(); /* release the frame */
-
- In the first case, there are four error assignments with four
- checks of the file read. This unnecessarily increases the size
- of the generated code. Moreover, you must be sure that `var1'
- and `var4' are short variables, `var2' and `var3' long ones, if
- you want to avoid bugs and/or compiler warnings.
-
- In the second case, you perform only one check for the read, and
- exit immediately on failure. Then the values are extracted from
- the frame, as the result of function calls. This means that you
- can use automatic type conversion; there is no problem if
- e.g. `var1' and `var4' are longs, unlike previously.
-
- On big-endian machines, the `Get_xxx()' functions could also be
- simple macros that merely peek the values directly from the
- frame, which speeds up and simplifies the generated code!
-
- And finally, frames are ideal when you are using memory-mapped
- files, as the frame is not really `pre-loaded' and never uses
- any `heap' space.
-
- IMPORTANT: You CANNOT nest several frame accesses. There is
- only one frame available at a time for a specific
- instance.
-
- It is also the programmer's responsibility to never
- extract more data than was pre-loaded in the frame!
- (But you usually know how many values you want to
- extract from the file before doing so).
-
-
-3. Memory Management
---------------------
-
- The library now uses a component which interface is similar to
- malloc()/free(). It defines only two functions.
-
- * Alloc()
-
- To be used like malloc(), except that it returns an error code,
- not an address. Its arguments are the size of the requested
- block and the address of the target pointer to the `fresh'
- block. An error code is returned in case of failure (and this
- will also set the target pointer to NULL), 0 in case of success.
-
- Alloc() should always respect the following rules:
-
- - Requesting a block of size 0 should set the target pointer to
- NULL and return no error code (i.e., return 0).
-
- - The returned block is always zeroed. This is an important
- assumption of other parts of the library.
-
- If you wish to replace the memory component with your own,
- please respect this behaviour, or your engine won't work
- correctly.
-
- * Free()
-
- As you may have already guessed, Free() is Alloc()'s
- counterpart. It takes as argument the _target pointer's
- address_! You should _never_ pass the block's address directly,
- i.e. the pointer, to Free().
-
- Free should always respect the following rules:
-
- - Calling it with a NULL argument, or the address of a NULL
- pointer is valid, and should return success.
-
- - The pointer is always set to NULL after the block's
- deallocation. This is also an important assumption of many
- other parts of the library.
-
- If you wish to replace the memory component with your own,
- please respect this behaviour, or your engine won't work
- correctly.
-
- As the pointers addresses needed as arguments are typed `void**',
- the component's interface also provides in the C version some
- macros to help use them more easily, these are:
-
- MEM_Alloc A version of Alloc that casts the argument pointer
- to (void**).
-
- ALLOC Same as MEM_Alloc, but with an assignment to a
- variable called `error'. See the section `error
- handling' above for more info on this.
-
- FREE A version of Free() that casts the argument
- pointer to (void**). There is currently no error
- handling by with this macro.
-
- MEM_Set An alias for `memset()', which can be easily
- changed to anything else if you wish to use a
- different memory manager than the functions
- provided by the ANSI libc.
-
- MEM_Copy An alias of `memcpy()' or `bcopy()' used to move
- blocks of memory. You may change it to something
- different if you wish to use something else that
- your standard libc.
-
-
-4. Support for threaded environments
-------------------------------------
-
- Support for threaded environments have been added to the C
- sources, and only to these. It is now theorically possible to
- build three distinct versions of the library:
-
- single-thread build:
-
- The default build. This one doesn't known about different
- threads. Hence, no code is generated to perform coherent data
- sharing and locking.
-
- thread-safe build:
-
- With this build, several threads can use the library at the
- same time. However, some key components can only be used by
- one single thread at a time, and use a mutex to synchronize
- access to their functions. These are mainly the file, raster
- and interpreter components.
-
- re-entrant build:
-
- A re-entrant version is able to perform certain actions in
- parallel that a thread-safe one cannot. This includes
- accessing file(s) in parallel, interpreting different
- instruction streams in parallel, or even scan-line converting
- distinct glyphs at the same time.
-
- Note that most of the latest changes in the engine are making the
- distinction between the thread-safe and re-entrant builds thinner
- than ever.
-
- There is a `ttmutex' component that presents a generic interface
- to mutex operations. It should be re-implemented for each
- platform.
-
-<to be continued>
-
-
---- end of convntns.txt ---