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