diff options
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.txt | 970 |
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 --- |