701 lines
14 KiB
C
701 lines
14 KiB
C
|
/***************************************************************************/
|
||
|
/* */
|
||
|
/* ttpost.c */
|
||
|
/* */
|
||
|
/* Postscript names table processing (body). */
|
||
|
/* */
|
||
|
/* Copyright 1996-1999 by */
|
||
|
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
|
||
|
/* */
|
||
|
/* This file is part of the FreeType project, and may only be used */
|
||
|
/* modified and distributed under the terms of the FreeType project */
|
||
|
/* license, LICENSE.TXT. By continuing to use, modify, or distribute */
|
||
|
/* this file you indicate that you have read the license and */
|
||
|
/* understand and accept it fully. */
|
||
|
/* */
|
||
|
/***************************************************************************/
|
||
|
|
||
|
|
||
|
/*************************************************************************/
|
||
|
/* */
|
||
|
/* The post table is not completely loaded by the core engine. This */
|
||
|
/* file loads the missing PS glyph names and implements an API to access */
|
||
|
/* them. */
|
||
|
/* */
|
||
|
/*************************************************************************/
|
||
|
|
||
|
|
||
|
#include <ttpost.h>
|
||
|
#include <ftstream.h>
|
||
|
#include <tterrors.h>
|
||
|
#include <ttload.h>
|
||
|
#include <tttags.h>
|
||
|
|
||
|
/* the 258 default Mac PS glyph names */
|
||
|
|
||
|
const TT_String* TT_Mac_Postscript_Names[258] =
|
||
|
{
|
||
|
/* 0 */
|
||
|
".notdef",
|
||
|
".null",
|
||
|
"CR",
|
||
|
"space",
|
||
|
"exclam",
|
||
|
"quotedbl",
|
||
|
"numbersign",
|
||
|
"dollar",
|
||
|
"percent",
|
||
|
"ampersand",
|
||
|
|
||
|
/* 10 */
|
||
|
"quotesingle",
|
||
|
"parenleft",
|
||
|
"parenright",
|
||
|
"asterisk",
|
||
|
"plus",
|
||
|
"comma",
|
||
|
"hyphen",
|
||
|
"period",
|
||
|
"slash",
|
||
|
"zero",
|
||
|
|
||
|
/* 20 */
|
||
|
"one",
|
||
|
"two",
|
||
|
"three",
|
||
|
"four",
|
||
|
"five",
|
||
|
"six",
|
||
|
"seven",
|
||
|
"eight",
|
||
|
"nine",
|
||
|
"colon",
|
||
|
|
||
|
/* 30 */
|
||
|
"semicolon",
|
||
|
"less",
|
||
|
"equal",
|
||
|
"greater", "question",
|
||
|
"at",
|
||
|
"A",
|
||
|
"B",
|
||
|
"C",
|
||
|
"D",
|
||
|
|
||
|
/* 40 */
|
||
|
"E",
|
||
|
"F",
|
||
|
"G",
|
||
|
"H",
|
||
|
"I",
|
||
|
"J",
|
||
|
"K",
|
||
|
"L",
|
||
|
"M",
|
||
|
"N",
|
||
|
|
||
|
/* 50 */
|
||
|
"O",
|
||
|
"P",
|
||
|
"Q",
|
||
|
"R",
|
||
|
"S",
|
||
|
"T",
|
||
|
"U",
|
||
|
"V",
|
||
|
"W",
|
||
|
"X",
|
||
|
|
||
|
/* 60 */
|
||
|
"Y",
|
||
|
"Z",
|
||
|
"bracketleft",
|
||
|
"backslash",
|
||
|
"bracketright",
|
||
|
"asciicircum",
|
||
|
"underscore",
|
||
|
"grave",
|
||
|
"a",
|
||
|
"b",
|
||
|
|
||
|
/* 70 */
|
||
|
"c",
|
||
|
"d",
|
||
|
"e",
|
||
|
"f",
|
||
|
"g",
|
||
|
"h",
|
||
|
"i",
|
||
|
"j",
|
||
|
"k",
|
||
|
"l",
|
||
|
|
||
|
/* 80 */
|
||
|
"m",
|
||
|
"n",
|
||
|
"o",
|
||
|
"p",
|
||
|
"q",
|
||
|
"r",
|
||
|
"s",
|
||
|
"t",
|
||
|
"u",
|
||
|
"v",
|
||
|
|
||
|
/* 90 */
|
||
|
"w",
|
||
|
"x",
|
||
|
"y",
|
||
|
"z",
|
||
|
"braceleft",
|
||
|
"bar",
|
||
|
"braceright",
|
||
|
"asciitilde",
|
||
|
"Adieresis",
|
||
|
"Aring",
|
||
|
|
||
|
/* 100 */
|
||
|
"Ccedilla",
|
||
|
"Eacute",
|
||
|
"Ntilde",
|
||
|
"Odieresis",
|
||
|
"Udieresis",
|
||
|
"aacute",
|
||
|
"agrave",
|
||
|
"acircumflex",
|
||
|
"adieresis",
|
||
|
"atilde",
|
||
|
|
||
|
/* 110 */
|
||
|
"aring",
|
||
|
"ccedilla",
|
||
|
"eacute",
|
||
|
"egrave",
|
||
|
"ecircumflex",
|
||
|
"edieresis",
|
||
|
"iacute",
|
||
|
"igrave",
|
||
|
"icircumflex",
|
||
|
"idieresis",
|
||
|
|
||
|
/* 120 */
|
||
|
"ntilde",
|
||
|
"oacute",
|
||
|
"ograve",
|
||
|
"ocircumflex",
|
||
|
"odieresis",
|
||
|
"otilde",
|
||
|
"uacute",
|
||
|
"ugrave",
|
||
|
"ucircumflex",
|
||
|
"udieresis",
|
||
|
|
||
|
/* 130 */
|
||
|
"dagger",
|
||
|
"degree",
|
||
|
"cent",
|
||
|
"sterling",
|
||
|
"section",
|
||
|
"bullet",
|
||
|
"paragraph",
|
||
|
"germandbls",
|
||
|
"registered",
|
||
|
"copyright",
|
||
|
|
||
|
/* 140 */
|
||
|
"trademark",
|
||
|
"acute",
|
||
|
"dieresis",
|
||
|
"notequal",
|
||
|
"AE",
|
||
|
"Oslash",
|
||
|
"infinity",
|
||
|
"plusminus",
|
||
|
"lessequal",
|
||
|
"greaterequal",
|
||
|
|
||
|
/* 150 */
|
||
|
"yen",
|
||
|
"mu",
|
||
|
"partialdiff",
|
||
|
"summation",
|
||
|
"product",
|
||
|
"pi",
|
||
|
"integral",
|
||
|
"ordfeminine",
|
||
|
"ordmasculine",
|
||
|
"Omega",
|
||
|
|
||
|
/* 160 */
|
||
|
"ae",
|
||
|
"oslash",
|
||
|
"questiondown",
|
||
|
"exclamdown",
|
||
|
"logicalnot",
|
||
|
"radical",
|
||
|
"florin",
|
||
|
"approxequal",
|
||
|
"Delta",
|
||
|
"guillemotleft",
|
||
|
|
||
|
/* 170 */
|
||
|
"guillemotright",
|
||
|
"ellipsis",
|
||
|
"nbspace",
|
||
|
"Agrave",
|
||
|
"Atilde",
|
||
|
"Otilde",
|
||
|
"OE",
|
||
|
"oe",
|
||
|
"endash",
|
||
|
"emdash",
|
||
|
|
||
|
/* 180 */
|
||
|
"quotedblleft",
|
||
|
"quotedblright",
|
||
|
"quoteleft",
|
||
|
"quoteright",
|
||
|
"divide",
|
||
|
"lozenge",
|
||
|
"ydieresis",
|
||
|
"Ydieresis",
|
||
|
"fraction",
|
||
|
"currency",
|
||
|
|
||
|
/* 190 */
|
||
|
"guilsinglleft",
|
||
|
"guilsinglright",
|
||
|
"fi",
|
||
|
"fl",
|
||
|
"daggerdbl",
|
||
|
"periodcentered",
|
||
|
"quotesinglbase",
|
||
|
"quotedblbase",
|
||
|
"perthousand",
|
||
|
"Acircumflex",
|
||
|
|
||
|
/* 200 */
|
||
|
"Ecircumflex",
|
||
|
"Aacute",
|
||
|
"Edieresis",
|
||
|
"Egrave",
|
||
|
"Iacute",
|
||
|
"Icircumflex",
|
||
|
"Idieresis",
|
||
|
"Igrave",
|
||
|
"Oacute",
|
||
|
"Ocircumflex",
|
||
|
|
||
|
/* 210 */
|
||
|
"apple",
|
||
|
"Ograve",
|
||
|
"Uacute",
|
||
|
"Ucircumflex",
|
||
|
"Ugrave",
|
||
|
"dotlessi",
|
||
|
"circumflex",
|
||
|
"tilde",
|
||
|
"macron",
|
||
|
"breve",
|
||
|
|
||
|
/* 220 */
|
||
|
"dotaccent",
|
||
|
"ring",
|
||
|
"cedilla",
|
||
|
"hungarumlaut",
|
||
|
"ogonek",
|
||
|
"caron",
|
||
|
"Lslash",
|
||
|
"lslash",
|
||
|
"Scaron",
|
||
|
"scaron",
|
||
|
|
||
|
/* 230 */
|
||
|
"Zcaron",
|
||
|
"zcaron",
|
||
|
"brokenbar",
|
||
|
"Eth",
|
||
|
"eth",
|
||
|
"Yacute",
|
||
|
"yacute",
|
||
|
"Thorn",
|
||
|
"thorn",
|
||
|
"minus",
|
||
|
|
||
|
/* 240 */
|
||
|
"multiply",
|
||
|
"onesuperior",
|
||
|
"twosuperior",
|
||
|
"threesuperior",
|
||
|
"onehalf",
|
||
|
"onequarter",
|
||
|
"threequarters",
|
||
|
"franc",
|
||
|
"Gbreve",
|
||
|
"gbreve",
|
||
|
|
||
|
/* 250 */
|
||
|
"Idot",
|
||
|
"Scedilla",
|
||
|
"scedilla",
|
||
|
"Cacute",
|
||
|
"cacute",
|
||
|
"Ccaron",
|
||
|
"ccaron",
|
||
|
"dmacron",
|
||
|
};
|
||
|
|
||
|
|
||
|
static
|
||
|
TT_Error Load_Format_20( TT_Face face,
|
||
|
FT_Stream stream )
|
||
|
{
|
||
|
FT_Memory memory = stream->memory;
|
||
|
TT_Error error;
|
||
|
|
||
|
TT_Int num_glyphs;
|
||
|
TT_Int num_names;
|
||
|
|
||
|
TT_UShort* glyph_indices = 0;
|
||
|
TT_Char** name_strings = 0;
|
||
|
|
||
|
|
||
|
if ( READ_UShort( num_glyphs ) )
|
||
|
goto Exit;
|
||
|
|
||
|
/* UNDOCUMENTED! The number of glyphs in this table can be smaller */
|
||
|
/* than the value in the maxp table (cf. cyberbit.ttf). */
|
||
|
|
||
|
/* There already exist fonts which have more than 32768 glyph names */
|
||
|
/* in this table, so the test for this threshold has been dropped. */
|
||
|
|
||
|
if ( num_glyphs > face->root.num_glyphs )
|
||
|
{
|
||
|
error = TT_Err_Invalid_File_Format;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
/* load the indices */
|
||
|
{
|
||
|
TT_Int n;
|
||
|
|
||
|
if ( ALLOC_ARRAY ( glyph_indices, num_glyphs, TT_UShort ) ||
|
||
|
ACCESS_Frame( num_glyphs * 2L ) )
|
||
|
goto Fail;
|
||
|
|
||
|
for ( n = 0; n < num_glyphs; n++ )
|
||
|
glyph_indices[n] = GET_UShort();
|
||
|
|
||
|
FORGET_Frame();
|
||
|
}
|
||
|
|
||
|
/* compute number of names stored in table */
|
||
|
{
|
||
|
TT_Int n;
|
||
|
|
||
|
num_names = 0;
|
||
|
|
||
|
for ( n = 0; n < num_glyphs; n++ )
|
||
|
{
|
||
|
TT_Int index;
|
||
|
|
||
|
index = glyph_indices[n];
|
||
|
if ( index >= 258 )
|
||
|
{
|
||
|
index -= 257;
|
||
|
if ( index > num_names )
|
||
|
num_names = index;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* now load the name strings */
|
||
|
{
|
||
|
TT_Int n;
|
||
|
|
||
|
if ( ALLOC_ARRAY( name_strings, num_names, TT_Char* ) )
|
||
|
goto Fail;
|
||
|
|
||
|
for ( n = 0; n < num_names; n++ )
|
||
|
{
|
||
|
TT_UInt len;
|
||
|
|
||
|
if ( READ_Byte ( len ) ||
|
||
|
ALLOC_ARRAY( name_strings[n], len+1, TT_Char ) ||
|
||
|
FILE_Read ( name_strings[n], len ) )
|
||
|
goto Fail1;
|
||
|
|
||
|
name_strings[n][len] = '\0';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* all right, set table fields and exit successfuly */
|
||
|
{
|
||
|
TT_Post_20* table = &face->postscript_names.names.format_20;
|
||
|
|
||
|
table->num_glyphs = num_glyphs;
|
||
|
table->num_names = num_names;
|
||
|
table->glyph_indices = glyph_indices;
|
||
|
table->glyph_names = name_strings;
|
||
|
}
|
||
|
return TT_Err_Ok;
|
||
|
|
||
|
|
||
|
Fail1:
|
||
|
{
|
||
|
TT_Int n;
|
||
|
|
||
|
for ( n = 0; n < num_names; n++ )
|
||
|
FREE( name_strings[n] );
|
||
|
}
|
||
|
|
||
|
Fail:
|
||
|
FREE( name_strings );
|
||
|
FREE( glyph_indices );
|
||
|
|
||
|
Exit:
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
|
||
|
static
|
||
|
TT_Error Load_Format_25( TT_Face face,
|
||
|
FT_Stream stream )
|
||
|
{
|
||
|
FT_Memory memory = stream->memory;
|
||
|
TT_Error error;
|
||
|
|
||
|
TT_Int num_glyphs;
|
||
|
TT_Char* offset_table = 0;
|
||
|
|
||
|
|
||
|
/* UNDOCUMENTED! This value appears only in the Apple TT specs. */
|
||
|
if ( READ_UShort( num_glyphs ) )
|
||
|
goto Exit;
|
||
|
|
||
|
/* check the number of glyphs */
|
||
|
if ( num_glyphs > face->root.num_glyphs || num_glyphs > 258 )
|
||
|
{
|
||
|
error = TT_Err_Invalid_File_Format;
|
||
|
goto Exit;
|
||
|
}
|
||
|
|
||
|
if ( ALLOC ( offset_table, num_glyphs ) ||
|
||
|
FILE_Read( offset_table, num_glyphs ) )
|
||
|
goto Fail;
|
||
|
|
||
|
/* now check the offset table */
|
||
|
{
|
||
|
TT_Int n;
|
||
|
|
||
|
|
||
|
for ( n = 0; n < num_glyphs; n++ )
|
||
|
{
|
||
|
TT_Long index = (TT_Long)n + offset_table[n];
|
||
|
|
||
|
|
||
|
if ( index < 0 || index > num_glyphs )
|
||
|
{
|
||
|
error = TT_Err_Invalid_File_Format;
|
||
|
goto Fail;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* OK, set table fields and exit successfuly */
|
||
|
{
|
||
|
TT_Post_25* table = &face->postscript_names.names.format_25;
|
||
|
|
||
|
|
||
|
table->num_glyphs = num_glyphs;
|
||
|
table->offsets = offset_table;
|
||
|
}
|
||
|
|
||
|
return TT_Err_Ok;
|
||
|
|
||
|
Fail:
|
||
|
FREE( offset_table );
|
||
|
|
||
|
Exit:
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
|
||
|
static
|
||
|
TT_Error Load_Post_Names( TT_Face face )
|
||
|
{
|
||
|
FT_Stream stream;
|
||
|
TT_Error error;
|
||
|
|
||
|
/* get a stream for the face's resource */
|
||
|
stream = face->root.stream;
|
||
|
|
||
|
/* seek to the beginning of the PS names table */
|
||
|
error = face->goto_table( face, TTAG_post, stream, 0 );
|
||
|
if (error) goto Exit;
|
||
|
|
||
|
/* now read postscript table */
|
||
|
switch ( face->postscript.FormatType )
|
||
|
{
|
||
|
case 0x00020000:
|
||
|
error = Load_Format_20( face, stream );
|
||
|
break;
|
||
|
|
||
|
case 0x00028000:
|
||
|
error = Load_Format_25( face, stream );
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
error = TT_Err_Invalid_File_Format;
|
||
|
}
|
||
|
|
||
|
face->postscript_names.loaded = 1;
|
||
|
|
||
|
Exit:
|
||
|
return error;
|
||
|
}
|
||
|
|
||
|
|
||
|
LOCAL_FUNC
|
||
|
void TT_Free_Post_Names( TT_Face face )
|
||
|
{
|
||
|
FT_Memory memory = face->root.memory;
|
||
|
TT_Post_Names* names = &face->postscript_names;
|
||
|
|
||
|
|
||
|
if ( names->loaded )
|
||
|
{
|
||
|
switch ( face->postscript.FormatType )
|
||
|
{
|
||
|
case 0x00020000:
|
||
|
{
|
||
|
TT_Post_20* table = &names->names.format_20;
|
||
|
TT_UInt n;
|
||
|
|
||
|
|
||
|
FREE( table->glyph_indices );
|
||
|
table->num_glyphs = 0;
|
||
|
|
||
|
for ( n = 0; n < table->num_names; n++ )
|
||
|
FREE( table->glyph_names[n] );
|
||
|
|
||
|
FREE( table->glyph_names );
|
||
|
table->num_names = 0;
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 0x00028000:
|
||
|
{
|
||
|
TT_Post_25* table = &names->names.format_25;
|
||
|
|
||
|
|
||
|
FREE( table->offsets );
|
||
|
table->num_glyphs = 0;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
names->loaded = 0;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*************************************************************************/
|
||
|
/* */
|
||
|
/* <Function> */
|
||
|
/* TT_Get_PS_Name */
|
||
|
/* */
|
||
|
/* <Description> */
|
||
|
/* Gets the PostScript glyph name of a glyph. */
|
||
|
/* */
|
||
|
/* <Input> */
|
||
|
/* index :: The glyph index. */
|
||
|
/* */
|
||
|
/* PSname :: The address of a string pointer. Will be NULL in case */
|
||
|
/* of error, otherwise it is a pointer to the glyph name. */
|
||
|
/* */
|
||
|
/* You must not modify the returned string! */
|
||
|
/* */
|
||
|
/* <Output> */
|
||
|
/* TrueType error code. 0 means success. */
|
||
|
/* */
|
||
|
EXPORT_FUNC
|
||
|
TT_Error TT_Get_PS_Name( TT_Face face,
|
||
|
TT_UInt index,
|
||
|
TT_String** PSname )
|
||
|
{
|
||
|
TT_Error error;
|
||
|
TT_Post_Names* names;
|
||
|
|
||
|
if ( !face )
|
||
|
return TT_Err_Invalid_Face_Handle;
|
||
|
|
||
|
if ( index >= (TT_UInt)face->root.num_glyphs )
|
||
|
return TT_Err_Invalid_Glyph_Index;
|
||
|
|
||
|
names = &face->postscript_names;
|
||
|
|
||
|
/* `.notdef' by default */
|
||
|
*PSname = (TT_String*)TT_Mac_Postscript_Names[0];
|
||
|
|
||
|
switch ( face->postscript.FormatType )
|
||
|
{
|
||
|
case 0x00010000:
|
||
|
if ( index < 258 ) /* paranoid checking */
|
||
|
*PSname = (TT_String*)TT_Mac_Postscript_Names[index];
|
||
|
break;
|
||
|
|
||
|
case 0x00020000:
|
||
|
{
|
||
|
TT_Post_20* table = &names->names.format_20;
|
||
|
|
||
|
|
||
|
if ( !names->loaded )
|
||
|
{
|
||
|
error = Load_Post_Names( face );
|
||
|
if ( error )
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( index < table->num_glyphs )
|
||
|
{
|
||
|
TT_UShort name_index = table->glyph_indices[index];
|
||
|
|
||
|
|
||
|
if ( name_index < 258 )
|
||
|
*PSname = (TT_String*)TT_Mac_Postscript_Names[name_index];
|
||
|
else
|
||
|
*PSname = (TT_String*)table->glyph_names[name_index - 258];
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 0x00028000:
|
||
|
{
|
||
|
TT_Post_25* table = &names->names.format_25;
|
||
|
|
||
|
|
||
|
if ( !names->loaded )
|
||
|
{
|
||
|
error = Load_Post_Names( face );
|
||
|
if ( error )
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
if ( index < table->num_glyphs ) /* paranoid checking */
|
||
|
{
|
||
|
index += table->offsets[index];
|
||
|
*PSname = (TT_String*)TT_Mac_Postscript_Names[index];
|
||
|
}
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
case 0x00030000:
|
||
|
break; /* nothing to do */
|
||
|
}
|
||
|
|
||
|
return TT_Err_Ok;
|
||
|
}
|
||
|
|
||
|
|
||
|
/* END */
|