FreeType 1.31.1
This commit is contained in:
522
lib/extend/ftxpost.c
Normal file
522
lib/extend/ftxpost.c
Normal file
@@ -0,0 +1,522 @@
|
||||
/*******************************************************************
|
||||
*
|
||||
* ftxpost.c
|
||||
*
|
||||
* post table support API extension 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 "ftxpost.h"
|
||||
|
||||
#include "tttypes.h"
|
||||
#include "ttobjs.h"
|
||||
#include "tttables.h"
|
||||
#include "ttload.h" /* for the macros */
|
||||
#include "ttfile.h"
|
||||
#include "tttags.h"
|
||||
#include "ttmemory.h"
|
||||
#include "ttextend.h"
|
||||
|
||||
|
||||
#define POST_ID Build_Extension_ID( 'p', 'o', 's', 't' )
|
||||
|
||||
|
||||
/* the 258 default Mac PS glyph names */
|
||||
|
||||
String* TT_Post_Default_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_Post_20* post20,
|
||||
PFace input )
|
||||
{
|
||||
DEFINE_LOAD_LOCALS( input->stream );
|
||||
|
||||
UShort nameindex, n, num;
|
||||
Byte len;
|
||||
|
||||
|
||||
if ( ACCESS_Frame( 2L ) )
|
||||
return error;
|
||||
|
||||
num = GET_UShort();
|
||||
|
||||
FORGET_Frame();
|
||||
|
||||
/* 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 > input->numGlyphs )
|
||||
return TT_Err_Invalid_Post_Table;
|
||||
|
||||
post20->numGlyphs = num;
|
||||
|
||||
if ( ALLOC_ARRAY( post20->glyphNameIndex, num, TT_UShort ) )
|
||||
return error;
|
||||
|
||||
if ( ACCESS_Frame( num * 2L ) )
|
||||
goto Fail;
|
||||
|
||||
for ( n = 0; n < num; n++ )
|
||||
{
|
||||
post20->glyphNameIndex[n] = GET_UShort();
|
||||
|
||||
if ( post20->glyphNameIndex[n] > 258 + num )
|
||||
{
|
||||
FORGET_Frame();
|
||||
error = TT_Err_Invalid_Post_Table;
|
||||
goto Fail;
|
||||
}
|
||||
}
|
||||
|
||||
FORGET_Frame();
|
||||
|
||||
if ( ALLOC_ARRAY( post20->glyphNames, num, Char* ) )
|
||||
goto Fail;
|
||||
|
||||
/* We must initialize the glyphNames array for proper */
|
||||
/* deallocation. */
|
||||
for ( n = 0; n < num; n++ )
|
||||
post20->glyphNames[n] = NULL;
|
||||
|
||||
/* Now we can read the glyph names which are stored in */
|
||||
/* Pascal string format. */
|
||||
for ( n = 0; n < num; n++ )
|
||||
{
|
||||
nameindex = post20->glyphNameIndex[n];
|
||||
|
||||
if ( nameindex < 258 )
|
||||
; /* default Mac glyph, do nothing */
|
||||
else
|
||||
{
|
||||
if ( ACCESS_Frame( 1L ) )
|
||||
goto Fail1;
|
||||
|
||||
len = GET_Byte();
|
||||
|
||||
FORGET_Frame();
|
||||
|
||||
if ( ALLOC_ARRAY( post20->glyphNames[nameindex - 258],
|
||||
len + 1, Char ) ||
|
||||
FILE_Read( post20->glyphNames[nameindex - 258], len ) )
|
||||
goto Fail1;
|
||||
|
||||
/* we make a C string */
|
||||
post20->glyphNames[nameindex - 258][len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
return TT_Err_Ok;
|
||||
|
||||
|
||||
Fail1:
|
||||
for ( n = 0; n < num; n++ )
|
||||
if ( post20->glyphNames[n] )
|
||||
FREE( post20->glyphNames[n] );
|
||||
|
||||
FREE( post20->glyphNames );
|
||||
|
||||
Fail:
|
||||
FREE( post20->glyphNameIndex );
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static TT_Error Load_Format_25( TT_Post_25* post25,
|
||||
PFace input )
|
||||
{
|
||||
DEFINE_LOAD_LOCALS( input->stream );
|
||||
|
||||
UShort n, num;
|
||||
|
||||
|
||||
if ( ACCESS_Frame( 2L ) )
|
||||
return error;
|
||||
|
||||
/* UNDOCUMENTED! This value appears only in the Apple TT specs. */
|
||||
num = GET_UShort();
|
||||
|
||||
FORGET_Frame();
|
||||
|
||||
if ( num > input->numGlyphs || num > 258 )
|
||||
return TT_Err_Invalid_Post_Table;
|
||||
|
||||
post25->numGlyphs = num;
|
||||
|
||||
if ( ALLOC_ARRAY( post25->offset, num, Char ) )
|
||||
return error;
|
||||
|
||||
if ( ACCESS_Frame( num ) )
|
||||
goto Fail;
|
||||
|
||||
for ( n = 0; n < num; n++ )
|
||||
{
|
||||
post25->offset[n] = GET_Char();
|
||||
|
||||
/* We add 128 to the tests to avoid problems with negative */
|
||||
/* values for comparison. */
|
||||
if ( n + ( post25->offset[n] + 128 ) > num + 128 ||
|
||||
n + ( post25->offset[n] + 128 ) < 128 )
|
||||
{
|
||||
FORGET_Frame();
|
||||
error = TT_Err_Invalid_Post_Table;
|
||||
goto Fail;
|
||||
}
|
||||
}
|
||||
|
||||
FORGET_Frame();
|
||||
|
||||
return TT_Err_Ok;
|
||||
|
||||
|
||||
Fail:
|
||||
FREE( post25->offset );
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
static TT_Error Post_Create( void* ext,
|
||||
PFace face )
|
||||
{
|
||||
TT_Post* post = (TT_Post*)ext;
|
||||
Long table;
|
||||
|
||||
|
||||
/* by convention */
|
||||
if ( !post )
|
||||
return TT_Err_Ok;
|
||||
|
||||
/* we store the start offset and the size of the subtable */
|
||||
table = TT_LookUp_Table( face, TTAG_post );
|
||||
post->offset = face->dirTables[table].Offset + 32L;
|
||||
post->length = face->dirTables[table].Length - 32L;
|
||||
post->loaded = FALSE;
|
||||
|
||||
return TT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
static TT_Error Post_Destroy( void* ext,
|
||||
PFace face )
|
||||
{
|
||||
TT_Post* post = (TT_Post*)ext;
|
||||
UShort n;
|
||||
|
||||
|
||||
/* by convention */
|
||||
if ( !post )
|
||||
return TT_Err_Ok;
|
||||
|
||||
if ( post->loaded )
|
||||
{
|
||||
switch ( face->postscript.FormatType )
|
||||
{
|
||||
case 0x00010000: /* nothing to do */
|
||||
break;
|
||||
|
||||
case 0x00020000:
|
||||
for ( n = 0; n < post->p.post20.numGlyphs; n++ )
|
||||
if ( post->p.post20.glyphNames[n] )
|
||||
FREE( post->p.post20.glyphNames[n] );
|
||||
FREE( post->p.post20.glyphNames );
|
||||
FREE( post->p.post20.glyphNameIndex );
|
||||
break;
|
||||
|
||||
case 0x00028000:
|
||||
FREE( post->p.post25.offset );
|
||||
break;
|
||||
|
||||
case 0x00030000: /* nothing to do */
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case 0x00040000:
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
; /* invalid format, do nothing */
|
||||
}
|
||||
}
|
||||
|
||||
return TT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
EXPORT_FUNC
|
||||
TT_Error TT_Init_Post_Extension( TT_Engine engine )
|
||||
{
|
||||
PEngine_Instance _engine = HANDLE_Engine( engine );
|
||||
|
||||
TT_Error error;
|
||||
|
||||
|
||||
if ( !_engine )
|
||||
return TT_Err_Invalid_Engine;
|
||||
|
||||
error = TT_Register_Extension( _engine,
|
||||
POST_ID,
|
||||
sizeof ( TT_Post ),
|
||||
Post_Create,
|
||||
Post_Destroy );
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* Function : TT_Load_PS_Names
|
||||
*
|
||||
* Description : Loads the PostScript Glyph Name subtable (if any).
|
||||
*
|
||||
* Output : error code
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
EXPORT_FUNC
|
||||
TT_Error TT_Load_PS_Names( TT_Face face,
|
||||
TT_Post* ppost )
|
||||
{
|
||||
PFace faze = HANDLE_Face( face );
|
||||
TT_Error error;
|
||||
TT_Stream stream;
|
||||
TT_Post* post;
|
||||
|
||||
|
||||
if ( !faze )
|
||||
return TT_Err_Invalid_Face_Handle;
|
||||
|
||||
error = TT_Extension_Get( faze, POST_ID, (void**)&post );
|
||||
if ( error )
|
||||
return error;
|
||||
|
||||
if ( USE_Stream( faze->stream, stream ) )
|
||||
return error;
|
||||
|
||||
|
||||
switch ( faze->postscript.FormatType )
|
||||
{
|
||||
case 0x00010000:
|
||||
error = TT_Err_Ok; /* nothing to do */
|
||||
break;
|
||||
|
||||
case 0x00020000:
|
||||
if ( FILE_Seek( post->offset ) )
|
||||
goto Fail;
|
||||
|
||||
error = Load_Format_20( &post->p.post20, faze );
|
||||
break;
|
||||
|
||||
case 0x00028000: /* 2.5 in 16.16 format */
|
||||
if ( FILE_Seek( post->offset ) )
|
||||
goto Fail;
|
||||
|
||||
error = Load_Format_25( &post->p.post25, faze );
|
||||
break;
|
||||
|
||||
case 0x00030000:
|
||||
error = TT_Err_Ok; /* nothing to do */
|
||||
break;
|
||||
|
||||
#if 0
|
||||
case 0x00040000:
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
error = TT_Err_Invalid_Post_Table_Format;
|
||||
break;
|
||||
}
|
||||
|
||||
if ( !error )
|
||||
{
|
||||
post->loaded = TRUE;
|
||||
*ppost = *post;
|
||||
}
|
||||
|
||||
|
||||
Fail:
|
||||
DONE_Stream( stream );
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
/*******************************************************************
|
||||
*
|
||||
* Function : TT_Get_PS_Name
|
||||
*
|
||||
* Description : Gets the PostScript Glyph Name of a glyph.
|
||||
*
|
||||
* Input : index glyph index
|
||||
* PSname address of a string pointer.
|
||||
* Will be NULL in case of error; otherwise it
|
||||
* contains a pointer to the glyph name.
|
||||
*
|
||||
* You must not modify the returned string!
|
||||
*
|
||||
* Output : error code
|
||||
*
|
||||
******************************************************************/
|
||||
|
||||
EXPORT_FUNC
|
||||
TT_Error TT_Get_PS_Name( TT_Face face,
|
||||
TT_UShort index,
|
||||
TT_String** PSname )
|
||||
{
|
||||
PFace faze = HANDLE_Face( face );
|
||||
TT_Error error;
|
||||
TT_Post* post;
|
||||
UShort nameindex;
|
||||
|
||||
|
||||
if ( !faze )
|
||||
return TT_Err_Invalid_Face_Handle;
|
||||
|
||||
if ( index >= faze->numGlyphs )
|
||||
return TT_Err_Invalid_Glyph_Index;
|
||||
|
||||
error = TT_Extension_Get( faze, POST_ID, (void**)&post );
|
||||
if ( error )
|
||||
return error;
|
||||
|
||||
|
||||
*PSname = TT_Post_Default_Names[0]; /* default value */
|
||||
|
||||
switch ( faze->postscript.FormatType )
|
||||
{
|
||||
case 0x00010000:
|
||||
if ( index < 258 ) /* paranoid checking */
|
||||
*PSname = TT_Post_Default_Names[index];
|
||||
break;
|
||||
|
||||
case 0x00020000:
|
||||
if ( index < post->p.post20.numGlyphs )
|
||||
nameindex = post->p.post20.glyphNameIndex[index];
|
||||
else
|
||||
break;
|
||||
|
||||
if ( nameindex < 258 )
|
||||
*PSname = TT_Post_Default_Names[nameindex];
|
||||
else
|
||||
*PSname = (String*)post->p.post20.glyphNames[nameindex - 258];
|
||||
break;
|
||||
|
||||
case 0x00028000:
|
||||
if ( index < post->p.post25.numGlyphs ) /* paranoid checking */
|
||||
*PSname = TT_Post_Default_Names[index + post->p.post25.offset[index]];
|
||||
break;
|
||||
|
||||
case 0x00030000:
|
||||
break; /* nothing to do */
|
||||
|
||||
#if 0
|
||||
case 0x00040000:
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
; /* should never happen */
|
||||
}
|
||||
|
||||
return TT_Err_Ok;
|
||||
}
|
||||
|
||||
|
||||
/* END */
|
||||
Reference in New Issue
Block a user