From dc356a19afbea4c17419935c1119bc60e09bbdce Mon Sep 17 00:00:00 2001 From: Werner Lemberg Date: Thu, 19 Oct 2000 05:12:00 +0000 Subject: [PATCH] Converting tabs to spaces in z1load. Edited FT1's convntns.txt and added it to FT2. --- docs/convntns.txt | 689 ++++++++++++++++++++++++++++++++++++++++++++ src/type1z/z1load.c | 83 +++--- 2 files changed, 733 insertions(+), 39 deletions(-) create mode 100644 docs/convntns.txt diff --git a/docs/convntns.txt b/docs/convntns.txt new file mode 100644 index 000000000..6653c217f --- /dev/null +++ b/docs/convntns.txt @@ -0,0 +1,689 @@ + + Conventions and Design in the FreeType 2 library + ------------------------------------------------ + + +Table of Contents + +Introduction + +I. Style and Formatting + + 1. Naming + 2. Declarations & Statements + 3. Blocks + 4. Macros + 5. Conventions + +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 + 4. Support for threaded environments + 5. Object Management + + + +Introduction +============ + +This text introduces the many conventions used within the FreeType 2 +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. 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. + + Conclusion: Avoid Hungarian Notation in FreeType 2. + + + 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 welcome 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 ;-) + + b. Data types + + Try to use C 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 + `fttypes.h' public header file, like `FT_Short', `FT_UShort', + etc. Using the internal types will guarantee that you won't + need to replace every occurence of `short' or whatever when + compiling on a weird platform or with a weird compiler, and + there are many more than you could think of... + + c. 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 various data types from a file stream is + performed using the following functions defined in the + `ftstream.c' file of the `base' module: + + FT_Get_Char(), FT_Get_Short(), FT_Get_Long(), etc. + + Which is somewhat more readable than: + + cget, sget, usget, lget, etc. + + d. Variables + + Variable names (at least meant for the public interface) 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 are 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. + + Unfortunately (mostly due to the lazyness of the developers), + short variable names are still used in many parts of the + library. Volunteers are highly welcome to improve this... + + As a side note, a field name of a structure counts as a variable + name too. + + +2. Declarations & Statements +---------------------------- + + Try to align declarations and assignments in columns, if it proves + logically. For example (taken from `ttraster.c'): + + struct TProfile_ + { + FT_F26Dot6 X; /* current coordinate during sweep */ + PProfile link; /* link to next profile - various purpose */ + PLong offset; /* start of profile's data in render pool */ + Int flow; /* profile orientation: asc/descending */ + Long height; /* profile's height in scanlines */ + Long start; /* profile's starting scanline */ + + UShort countL; /* number of lines to step before this */ + /* profile becomes drawable */ + + PProfile next; /* next profile in same contour, used */ + /* during drop-out control */ + }; + + instead of + + struct TProfile_ + { + FT_F26Dot6 X; /* current coordinate during sweep */ + PProfile link; /* link to next profile - various purpose */ + PLong offset; /* start of profile's data in render pool */ + Int flow; /* profile orientation: asc/descending */ + Long height; /* profile's height in scanlines */ + Long start; /* profile's starting scanline */ + UShort countL; /* number of lines to step before this */ + /* profile becomes drawable */ + PProfile next; /* next profile in same contour, used */ + /* during drop-out control */ + }; + + This comes from the fact that you are more interested in the field + and its function than in 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; + + +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_ associate the accolades + easily (ask any Lisp programmer on the topic!). + + Use two spaces for the next indentation level. + + Never use tabs in FreeType 2 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; + } + + should be rather formatted as + + if ( condition_test ) + { + This code isn't stuck to the condition; + read it on paper, you will find it more; + pleasant to the eye; + } + else + { + Of course, this is a matter of taste; + This is just the way it is in this convention; + and you should follow it to be homogenuous with; + the rest of the FreeType code; + } + + +4. Macros +--------- + + Macros should be made of uppercase letters. If 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 in some files for macros like + + GET_UShort(), USE_Stream(), etc. + + The role of macros used throughout the engine is explained later + in this document. + + +5. Conventions +-------------- + + Currently, FreeType 2 source code uses the following formatting + rules: + + . The data type is separated with two spaces from the variable, + structure, or function name: + + const char foo; + + Usually, the `*' operator is concatenated to the data type: + + FT_Int* pointer; + + As mentioned above, multiple declarations are vertically + aligned: + + FT_Short foo; + FT_Long bar; + FT_GlyphSlot slot; + + . Declarations are separated with two blank lines from the + following code. This intentionally disturbs the code flow to + make variable definitions more visible. + + { + char x, y; + + + x = 3; + y = 5; + } + + . An opening parenthesis follows a function directly without + space; after a built-in C keyword, one space is used: + + x = sin( y ); + y = sizeof ( long ); + + Except for casts, parentheses are surrounded with space: + + x = (char*)( foo + bar ); + + . Binary operators are surrounded by spaces; unary operators have + no space after it: + + x = ( 3 + 4 ) / ( 7 - 2 ); + y = -( 3 + 4 ) * 7; + + . Array arguments are not surrounded by spaces: + + array[3] = array[1] + array[2]; + array[4] = array[1 + 3]; + + . Comma and semicolon have only space at the right side: + + if ( x = 0; x < y; x++, y-- ) + do_something(); + + . Don't use + + if ( x == y ) a = b; + + but + + if ( x == y ) + a = b; + + in general. + + . Preprocessor directives are never indented and always start in + the first column. + + . All function/structure/variable definitions start at column + three. + + . All full-line comments (except the header of a file) start at + column three (even comments for preprocessor directives). + + . Labels are sticking out two positions to the left: + + switch ( x ) + { + case 1: + do_something(); + break; + default: + do_nothing(); + break; + } + + + +II. Design Conventions +====================== + + +1. Modularity and Components Layout +----------------------------------- + + The FreeType 2 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 entirely in ANSI C. + + - 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 -- please report. + + (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 preprocessor, compiler, and + linker. + + - It consists of modules, starting with a `base' module which + provides the API, some auxiliary modules used by the font + drivers, the font driver modules itself, and the rasterizer + modules. + + - 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 only needs to include one header file named + `freetype.h' to use the engine. Other public header files like + `ftglyph.h' or `ftimage.h' provide functional extensions. + + - All configuration options are gathered in two files, + `ftconfig.h' and `ftoption.h'. The former contains the + processor and OS specific configuration options, while the + latter treats options that may be enabled or disabled by the + user to enable and disable various features. + + +2. Configuration and Debugging +------------------------------ + + Configuration is covered by the `BUILD' documentation file. + + Debugging is controlled by two macros in `ftoption.h', + FT_DEBUG_LEVEL_ERROR and FT_DEBUG_LEVEL_TRACE; don't use them in + code to be released. Check the source code of the `ftview.c' + demonstration program (in the `ft2demos' package) how tracing can + be used and activated. + + + +III. Usage conventions +====================== + + +1. Error Handling +----------------- + + Most functions directly return an error code. A return value of 0 + (FT_Err_Ok) means that no error occured, while a non-zero other + value indicates a failure of any kind. + + We use code like this in FreeType 2: + + 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 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 in some header 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. Another advantage is that the + structure of source files remain very similar, even though the + error handling may be 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 containing information used to access files through + a system-specific i/o library. + + The default implementation of streams uses the ANSI libc i/o + functions. However, for the sake of embedding in light systems + and independence of a complete C library, it is possible to + re-implement the component for a specific system or OS, letting + it use system calls. + + 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 call to the `ACCESS_Frame()' macro. + + It is then possible to read all sizes of data through the + `GET_xxx()' macros described above. + + When all important data is read, the frame can be released by a + call to `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 ( 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(); + + 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. + + 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 has a component which uses an interface similar to + malloc()/free(). + + * FT_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. + + FT_Alloc() internally calls the ft_alloc() function defined in + an FT_Memory object. All error checking is done by FT_Alloc() + itself so that ft_alloc() directly calls malloc(). + + * FT_Realloc() + + Similar to FT_Alloc(); it calls realloc() by default. + + * FT_Free() + + As you may have already guessed, FT_Free() is FT_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 FT_Free(). + + Similar to FT_Alloc(), FT_Free() does the necessary error + checking and calls free() by default. + + As the pointers addresses needed as arguments are typed `void**', + ftmemory.h provides some macros to help use the above functions + more easily, these are: + + MEM_Alloc() A version of FT_Alloc() that casts the argument + pointer to (void**). Similar functions are + MEM_Alloc_Array(), MEM_Realloc(), and + MEM_Realloc_Array() + + 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. Similar + functions are REALLOC(), ALLOC_ARRAY(), and + REALLOC_ARRAY(). + + FREE() A version of FT_Free() that casts the argument + pointer to (void**). + + 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 necessary (e.g. not using libc). + + MEM_Move() An alias of `memmove().' Change its definition if + necessary. + + +4. Support for threaded environments +------------------------------------ + + Thread synchronisation has been dropped in FreeType 2. The + library is already re-entrant, and if you really need two threads + accessing the same FT_Library object, you should synchronize + access to it yourself with a simple mutex. + + +--- end of convntns.txt --- diff --git a/src/type1z/z1load.c b/src/type1z/z1load.c index c0669153a..37fb99e6f 100644 --- a/src/type1z/z1load.c +++ b/src/type1z/z1load.c @@ -970,10 +970,12 @@ } /* We need to `zero' out encoding_table.elements */ - for ( n = 0 ; n < count ; n++ ) + for ( n = 0; n < count; n++ ) { - char *notdef = ".notdef"; - Z1_Add_Table( char_table, n, notdef, 8 ); + char* notdef = ".notdef"; + + + Z1_Add_Table( char_table, n, notdef, 8 ); } /* Now, we will need to read a record of the form */ @@ -1180,6 +1182,7 @@ FT_UInt notdef_index = 0; FT_Byte notdef_found = 0; + if ( loader->num_glyphs ) /* with synthetic fonts, it's possible we get here twice */ return; @@ -1207,6 +1210,7 @@ FT_Int size; FT_Byte* base; + /* the format is simple: */ /* `/glyphname' + binary data */ /* */ @@ -1250,12 +1254,12 @@ /* add a trailing zero to the name table */ name_table->elements[n][len] = '\0'; - /* record index of /.notdef */ - if ( strcmp( (const char*)".notdef", - (const char*)(name_table->elements[n]) ) == 0 ) - { - notdef_index = n; - notdef_found = 1; + /* record index of /.notdef */ + if ( strcmp( (const char*)".notdef", + (const char*)(name_table->elements[n]) ) == 0 ) + { + notdef_index = n; + notdef_found = 1; } parser->root.cursor = cur2; @@ -1283,8 +1287,8 @@ /* if /.notdef is found but does not occupy index 0, do our magic. */ if ( strcmp( (const char*)".notdef", - (const char*)name_table->elements[0] ) && - notdef_found ) + (const char*)name_table->elements[0] ) && + notdef_found ) { /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */ @@ -1293,39 +1297,39 @@ /* notdef_index. */ error = Z1_Add_Table( name_table, n, - name_table->elements[0], - name_table->lengths [0] ); + name_table->elements[0], + name_table->lengths [0] ); if ( error ) - goto Fail; + goto Fail; error = Z1_Add_Table( code_table, n, - code_table->elements[0], - code_table->lengths [0] ); + code_table->elements[0], + code_table->lengths [0] ); if ( error ) - goto Fail; + goto Fail; error = Z1_Add_Table( name_table, 0, - name_table->elements[notdef_index], - name_table->lengths [notdef_index] ); + name_table->elements[notdef_index], + name_table->lengths [notdef_index] ); if ( error ) - goto Fail; + goto Fail; error = Z1_Add_Table( code_table, 0, - code_table->elements[notdef_index], - code_table->lengths [notdef_index] ); + code_table->elements[notdef_index], + code_table->lengths [notdef_index] ); if ( error ) - goto Fail; + goto Fail; error = Z1_Add_Table( name_table, notdef_index, - name_table->elements[n], - name_table->lengths [n] ); + name_table->elements[n], + name_table->lengths [n] ); if ( error ) - goto Fail; + goto Fail; error = Z1_Add_Table( code_table, notdef_index, - code_table->elements[n], - code_table->lengths [n] ); + code_table->elements[n], + code_table->lengths [n] ); if ( error ) - goto Fail; + goto Fail; } else if ( !notdef_found ) @@ -1337,8 +1341,9 @@ /* and add our own /.notdef glyph to index 0. */ /* 0 333 hsbw endchar */ - FT_Byte notdef_glyph[] = {0x8B,0xF7,0xE1,0x0D,0x0E}; - char *notdef_name = ".notdef"; + FT_Byte notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E}; + char* notdef_name = ".notdef"; + error = Z1_Add_Table( name_table, n, name_table->elements[0], @@ -1671,14 +1676,14 @@ type1->encoding.char_index[charcode] = index; type1->encoding.char_name [charcode] = (char*)glyph_name; - /* Change min/max encoded char only if glyph name is */ - /* not /.notdef */ - if ( strcmp( (const char*)".notdef", - (const char*)glyph_name ) != 0 ) - { - if (charcode < min_char) min_char = charcode; - if (charcode > max_char) max_char = charcode; - } + /* Change min/max encoded char only if glyph name is */ + /* not /.notdef */ + if ( strcmp( (const char*)".notdef", + (const char*)glyph_name ) != 0 ) + { + if (charcode < min_char) min_char = charcode; + if (charcode > max_char) max_char = charcode; + } break; } }