update for HEAD-2003021201
[reactos.git] / subsys / win32k / freetype / src / sfnt / ttpost.c
1 /***************************************************************************/
2 /*                                                                         */
3 /*  ttpost.c                                                               */
4 /*                                                                         */
5 /*    Postcript name table processing for TrueType and OpenType fonts      */
6 /*    (body).                                                              */
7 /*                                                                         */
8 /*  Copyright 1996-2000 by                                                 */
9 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
10 /*                                                                         */
11 /*  This file is part of the FreeType project, and may only be used,       */
12 /*  modified, and distributed under the terms of the FreeType project      */
13 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
14 /*  this file you indicate that you have read the license and              */
15 /*  understand and accept it fully.                                        */
16 /*                                                                         */
17 /***************************************************************************/
18
19   /*************************************************************************/
20   /*                                                                       */
21   /* The post table is not completely loaded by the core engine.  This     */
22   /* file loads the missing PS glyph names and implements an API to access */
23   /* them.                                                                 */
24   /*                                                                       */
25   /*************************************************************************/
26
27
28 #include <freetype/internal/ftstream.h>
29 #include <freetype/internal/tterrors.h>
30 #include <freetype/tttags.h>
31
32
33 #ifdef FT_FLAT_COMPILE
34
35 #include "ttpost.h"
36 #include "ttload.h"
37
38 #else
39
40 #include <freetype/src/sfnt/ttpost.h>
41 #include <freetype/src/sfnt/ttload.h>
42
43 #endif
44
45
46   /*************************************************************************/
47   /*                                                                       */
48   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
49   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
50   /* messages during execution.                                            */
51   /*                                                                       */
52 #undef  FT_COMPONENT
53 #define FT_COMPONENT  trace_ttpost
54
55
56   /* If this configuration macro is defined, we rely on the `PSNames' */
57   /* module to grab the glyph names.                                  */
58
59 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
60
61
62 #include <freetype/internal/psnames.h>
63
64 #define MAC_NAME( x )  ( (FT_String*)psnames->macintosh_name( x ) )
65
66
67 #else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
68
69
70    /* Otherwise, we ignore the `PSNames' module, and provide our own  */
71    /* table of Mac names.  Thus, it is possible to build a version of */
72    /* FreeType without the Type 1 driver & PSNames module.            */
73
74 #define  MAC_NAME( x )  TT_Post_Default_Names[x]
75
76   /* the 258 default Mac PS glyph names */
77
78   FT_String*  TT_Post_Default_Names[258] =
79   {
80     /*   0 */
81     ".notdef", ".null", "CR", "space", "exclam",
82     "quotedbl", "numbersign", "dollar", "percent", "ampersand",
83     /*  10 */
84     "quotesingle", "parenleft", "parenright", "asterisk", "plus",
85     "comma", "hyphen", "period", "slash", "zero",
86     /*  20 */
87     "one", "two", "three", "four", "five",
88     "six", "seven", "eight", "nine", "colon",
89     /*  30 */
90     "semicolon", "less", "equal", "greater", "question",
91     "at", "A", "B", "C", "D",
92     /*  40 */
93     "E", "F", "G", "H", "I",
94     "J", "K", "L", "M", "N",
95     /*  50 */
96     "O", "P", "Q", "R", "S",
97     "T", "U", "V", "W", "X",
98     /*  60 */
99     "Y", "Z", "bracketleft", "backslash", "bracketright",
100     "asciicircum", "underscore", "grave", "a", "b",
101     /*  70 */
102     "c", "d", "e", "f", "g",
103     "h", "i", "j", "k", "l",
104     /*  80 */
105     "m", "n", "o", "p", "q",
106     "r", "s", "t", "u", "v",
107     /*  90 */
108     "w", "x", "y", "z", "braceleft",
109     "bar", "braceright", "asciitilde", "Adieresis", "Aring",
110     /* 100 */
111     "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis",
112     "aacute", "agrave", "acircumflex", "adieresis", "atilde",
113     /* 110 */
114     "aring", "ccedilla", "eacute", "egrave", "ecircumflex",
115     "edieresis", "iacute", "igrave", "icircumflex", "idieresis",
116     /* 120 */
117     "ntilde", "oacute", "ograve", "ocircumflex", "odieresis",
118     "otilde", "uacute", "ugrave", "ucircumflex", "udieresis",
119     /* 130 */
120     "dagger", "degree", "cent", "sterling", "section",
121     "bullet", "paragraph", "germandbls", "registered", "copyright",
122     /* 140 */
123     "trademark", "acute", "dieresis", "notequal", "AE",
124     "Oslash", "infinity", "plusminus", "lessequal", "greaterequal",
125     /* 150 */
126     "yen", "mu", "partialdiff", "summation", "product",
127     "pi", "integral", "ordfeminine", "ordmasculine", "Omega",
128     /* 160 */
129     "ae", "oslash", "questiondown", "exclamdown", "logicalnot",
130     "radical", "florin", "approxequal", "Delta", "guillemotleft",
131     /* 170 */
132     "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde",
133     "Otilde", "OE", "oe", "endash", "emdash",
134     /* 180 */
135     "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide",
136     "lozenge", "ydieresis", "Ydieresis", "fraction", "currency",
137     /* 190 */
138     "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl",
139     "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
140     /* 200 */
141     "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute",
142     "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex",
143     /* 210 */
144     "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave",
145     "dotlessi", "circumflex", "tilde", "macron", "breve",
146     /* 220 */
147     "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek",
148     "caron", "Lslash", "lslash", "Scaron", "scaron",
149     /* 230 */
150     "Zcaron", "zcaron", "brokenbar", "Eth", "eth",
151     "Yacute", "yacute", "Thorn", "thorn", "minus",
152     /* 240 */
153     "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf",
154     "onequarter", "threequarters", "franc", "Gbreve", "gbreve",
155     /* 250 */
156     "Idot", "Scedilla", "scedilla", "Cacute", "cacute",
157     "Ccaron", "ccaron", "dmacron",
158   };
159
160
161 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */
162
163
164   static
165   FT_Error  Load_Format_20( TT_Face    face,
166                             FT_Stream  stream )
167   {
168     FT_Memory  memory = stream->memory;
169     FT_Error   error;
170
171     FT_Int     num_glyphs;
172     FT_Int     num_names;
173
174     FT_UShort* glyph_indices = 0;
175     FT_Char**  name_strings  = 0;
176
177
178     if ( READ_UShort( num_glyphs ) )
179       goto Exit;
180
181     /* UNDOCUMENTED!  The number of glyphs in this table can be smaller */
182     /* than the value in the maxp table (cf. cyberbit.ttf).             */
183
184     /* There already exist fonts which have more than 32768 glyph names */
185     /* in this table, so the test for this threshold has been dropped.  */
186
187     if ( num_glyphs > face->root.num_glyphs )
188     {
189       error = TT_Err_Invalid_File_Format;
190       goto Exit;
191     }
192
193     /* load the indices */
194     {
195       FT_Int  n;
196
197
198       if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, FT_UShort ) ||
199            ACCESS_Frame( num_glyphs * 2L )                      )
200         goto Fail;
201
202       for ( n = 0; n < num_glyphs; n++ )
203         glyph_indices[n] = GET_UShort();
204
205       FORGET_Frame();
206     }
207
208     /* compute number of names stored in table */
209     {
210       FT_Int  n;
211
212
213       num_names = 0;
214
215       for ( n = 0; n < num_glyphs; n++ )
216       {
217         FT_Int  index;
218
219
220         index = glyph_indices[n];
221         if ( index >= 258 )
222         {
223           index -= 257;
224           if ( index > num_names )
225             num_names = index;
226         }
227       }
228     }
229
230     /* now load the name strings */
231     {
232       FT_Int  n;
233
234
235       if ( ALLOC_ARRAY( name_strings, num_names, FT_Char* ) )
236         goto Fail;
237
238       for ( n = 0; n < num_names; n++ )
239       {
240         FT_UInt  len;
241
242
243         if ( READ_Byte  ( len )                               ||
244              ALLOC_ARRAY( name_strings[n], len + 1, FT_Char ) ||
245              FILE_Read  ( name_strings[n], len )              )
246           goto Fail1;
247
248         name_strings[n][len] = '\0';
249       }
250     }
251
252     /* all right, set table fields and exit successfuly */
253     {
254       TT_Post_20*  table = &face->postscript_names.names.format_20;
255
256
257       table->num_glyphs    = num_glyphs;
258       table->num_names     = num_names;
259       table->glyph_indices = glyph_indices;
260       table->glyph_names   = name_strings;
261     }
262     return TT_Err_Ok;
263
264
265   Fail1:
266     {
267       FT_Int  n;
268
269
270       for ( n = 0; n < num_names; n++ )
271         FREE( name_strings[n] );
272     }
273
274   Fail:
275     FREE( name_strings );
276     FREE( glyph_indices );
277
278   Exit:
279     return error;
280   }
281
282
283   static
284   FT_Error  Load_Format_25( TT_Face    face,
285                             FT_Stream  stream )
286   {
287     FT_Memory  memory = stream->memory;
288     FT_Error   error;
289
290     FT_Int     num_glyphs;
291     FT_Char*   offset_table = 0;
292
293
294     /* UNDOCUMENTED!  This value appears only in the Apple TT specs. */
295     if ( READ_UShort( num_glyphs ) )
296       goto Exit;
297
298     /* check the number of glyphs */
299     if ( num_glyphs > face->root.num_glyphs || num_glyphs > 258 )
300     {
301       error = TT_Err_Invalid_File_Format;
302       goto Exit;
303     }
304
305     if ( ALLOC    ( offset_table, num_glyphs ) ||
306          FILE_Read( offset_table, num_glyphs ) )
307       goto Fail;
308
309     /* now check the offset table */
310     {
311       FT_Int  n;
312
313
314       for ( n = 0; n < num_glyphs; n++ )
315       {
316         FT_Long  index = (FT_Long)n + offset_table[n];
317
318
319         if ( index < 0 || index > num_glyphs )
320         {
321           error = TT_Err_Invalid_File_Format;
322           goto Fail;
323         }
324       }
325     }
326
327     /* OK, set table fields and exit successfuly */
328     {
329       TT_Post_25*  table = &face->postscript_names.names.format_25;
330
331
332       table->num_glyphs = num_glyphs;
333       table->offsets    = offset_table;
334     }
335
336     return TT_Err_Ok;
337
338   Fail:
339     FREE( offset_table );
340
341   Exit:
342     return error;
343   }
344
345
346   static
347   FT_Error  Load_Post_Names( TT_Face  face )
348   {
349     FT_Stream   stream;
350     FT_Error    error;
351
352     /* get a stream for the face's resource */
353     stream = face->root.stream;
354
355     /* seek to the beginning of the PS names table */
356     error = face->goto_table( face, TTAG_post, stream, 0 );
357     if ( error )
358       goto Exit;
359
360     /* now read postscript table */
361     switch ( face->postscript.FormatType )
362     {
363     case 0x00020000L:
364       error = Load_Format_20( face, stream );
365       break;
366
367     case 0x00028000L:
368       error = Load_Format_25( face, stream );
369       break;
370
371     default:
372       error = TT_Err_Invalid_File_Format;
373     }
374
375     face->postscript_names.loaded = 1;
376
377   Exit:
378     return error;
379   }
380
381
382   LOCAL_FUNC
383   void  TT_Free_Post_Names( TT_Face  face )
384   {
385     FT_Memory       memory = face->root.memory;
386     TT_Post_Names*  names  = &face->postscript_names;
387
388
389     if ( names->loaded )
390     {
391       switch ( face->postscript.FormatType )
392       {
393       case 0x00020000L:
394         {
395           TT_Post_20*  table = &names->names.format_20;
396           FT_UInt      n;
397
398
399           FREE( table->glyph_indices );
400           table->num_glyphs = 0;
401
402           for ( n = 0; n < table->num_names; n++ )
403             FREE( table->glyph_names[n] );
404
405           FREE( table->glyph_names );
406           table->num_names = 0;
407         }
408         break;
409
410       case 0x00028000L:
411         {
412           TT_Post_25*  table = &names->names.format_25;
413
414
415           FREE( table->offsets );
416           table->num_glyphs = 0;
417         }
418         break;
419       }
420     }
421     names->loaded = 0;
422   }
423
424
425   /*************************************************************************/
426   /*                                                                       */
427   /* <Function>                                                            */
428   /*    TT_Get_PS_Name                                                     */
429   /*                                                                       */
430   /* <Description>                                                         */
431   /*    Gets the PostScript glyph name of a glyph.                         */
432   /*                                                                       */
433   /* <Input>                                                               */
434   /*    face   :: A handle to the parent face.                             */
435   /*                                                                       */
436   /*    index  :: The glyph index.                                         */
437   /*                                                                       */
438   /*    PSname :: The address of a string pointer.  Will be NULL in case   */
439   /*              of error, otherwise it is a pointer to the glyph name.   */
440   /*                                                                       */
441   /*              You must not modify the returned string!                 */
442   /*                                                                       */
443   /* <Output>                                                              */
444   /*    FreeType error code.  0 means success.                             */
445   /*                                                                       */
446   LOCAL_FUNC
447   FT_Error  TT_Get_PS_Name( TT_Face      face,
448                             FT_UInt      index,
449                             FT_String**  PSname )
450   {
451     FT_Error            error;
452     TT_Post_Names*      names;
453
454 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
455     PSNames_Interface*  psnames;
456 #endif
457
458
459     if ( !face )
460       return TT_Err_Invalid_Face_Handle;
461
462     if ( index >= (FT_UInt)face->root.num_glyphs )
463       return TT_Err_Invalid_Glyph_Index;
464
465 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES
466     psnames = (PSNames_Interface*)face->psnames;
467     if ( !psnames )
468       return TT_Err_Unimplemented_Feature;
469 #endif
470
471     names = &face->postscript_names;
472
473     /* `.notdef' by default */
474     *PSname = MAC_NAME( 0 );
475
476     switch ( face->postscript.FormatType )
477     {
478     case 0x00010000L:
479       if ( index < 258 )                    /* paranoid checking */
480         *PSname = MAC_NAME( index );
481       break;
482
483     case 0x00020000L:
484       {
485         TT_Post_20*  table = &names->names.format_20;
486
487
488         if ( !names->loaded )
489         {
490           error = Load_Post_Names( face );
491           if ( error )
492             break;
493         }
494
495         if ( index < table->num_glyphs )
496         {
497           FT_UShort  name_index = table->glyph_indices[index];
498
499
500           if ( name_index < 258 )
501             *PSname = MAC_NAME( name_index );
502           else
503             *PSname = (FT_String*)table->glyph_names[name_index - 258];
504         }
505       }
506       break;
507
508     case 0x00028000L:
509       {
510         TT_Post_25*  table = &names->names.format_25;
511
512
513         if ( !names->loaded )
514         {
515           error = Load_Post_Names( face );
516           if ( error )
517             break;
518         }
519
520         if ( index < table->num_glyphs )    /* paranoid checking */
521         {
522           index  += table->offsets[index];
523           *PSname = MAC_NAME( index );
524         }
525       }
526       break;
527
528     case 0x00030000L:
529       break;                                /* nothing to do */
530     }
531
532     return TT_Err_Ok;
533   }
534
535
536 /* END */