- the CFF loader now loads the encodings and charset tables though doesn't use them for nowdavid-pic-changes
parent
508409434c
commit
19ed8afe60
122 changed files with 3660 additions and 1606 deletions
@ -0,0 +1,366 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* cffdrivr.c */ |
||||
/* */ |
||||
/* OpenType font driver implementation (body). */ |
||||
/* */ |
||||
/* Copyright 1996-2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_FREETYPE_H |
||||
#include FT_INTERNAL_DEBUG_H |
||||
#include FT_INTERNAL_STREAM_H |
||||
#include FT_INTERNAL_SFNT_H |
||||
#include FT_TRUETYPE_NAMES_H |
||||
#include FT_INTERNAL_CFF_ERRORS_H |
||||
|
||||
#include FT_SOURCE_FILE(cff,cffdrivr.h) |
||||
#include FT_SOURCE_FILE(cff,t2gload.h) |
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
||||
/* messages during execution. */ |
||||
/* */ |
||||
#undef FT_COMPONENT |
||||
#define FT_COMPONENT trace_t2driver |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/**** F A C E S ****/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
#undef PAIR_TAG |
||||
#define PAIR_TAG( left, right ) ( ( (FT_ULong)left << 16 ) | \ |
||||
(FT_ULong)right ) |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Function> */ |
||||
/* Get_Kerning */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* A driver method used to return the kerning vector between two */ |
||||
/* glyphs of the same face. */ |
||||
/* */ |
||||
/* <Input> */ |
||||
/* face :: A handle to the source face object. */ |
||||
/* */ |
||||
/* left_glyph :: The index of the left glyph in the kern pair. */ |
||||
/* */ |
||||
/* right_glyph :: The index of the right glyph in the kern pair. */ |
||||
/* */ |
||||
/* <Output> */ |
||||
/* kerning :: The kerning vector. This is in font units for */ |
||||
/* scalable formats, and in pixels for fixed-sizes */ |
||||
/* formats. */ |
||||
/* */ |
||||
/* <Return> */ |
||||
/* FreeType error code. 0 means success. */ |
||||
/* */ |
||||
/* <Note> */ |
||||
/* Only horizontal layouts (left-to-right & right-to-left) are */ |
||||
/* supported by this function. Other layouts, or more sophisticated */ |
||||
/* kernings, are out of scope of this method (the basic driver */ |
||||
/* interface is meant to be simple). */ |
||||
/* */ |
||||
/* They can be implemented by format-specific interfaces. */ |
||||
/* */ |
||||
static |
||||
FT_Error Get_Kerning( TT_Face face, |
||||
FT_UInt left_glyph, |
||||
FT_UInt right_glyph, |
||||
FT_Vector* kerning ) |
||||
{ |
||||
TT_Kern_0_Pair* pair; |
||||
|
||||
|
||||
if ( !face ) |
||||
return T2_Err_Invalid_Face_Handle; |
||||
|
||||
kerning->x = 0; |
||||
kerning->y = 0; |
||||
|
||||
if ( face->kern_pairs ) |
||||
{ |
||||
/* there are some kerning pairs in this font file! */ |
||||
FT_ULong search_tag = PAIR_TAG( left_glyph, right_glyph ); |
||||
FT_Long left, right; |
||||
|
||||
|
||||
left = 0; |
||||
right = face->num_kern_pairs - 1; |
||||
|
||||
while ( left <= right ) |
||||
{ |
||||
FT_Int middle = left + ( ( right - left ) >> 1 ); |
||||
FT_ULong cur_pair; |
||||
|
||||
|
||||
pair = face->kern_pairs + middle; |
||||
cur_pair = PAIR_TAG( pair->left, pair->right ); |
||||
|
||||
if ( cur_pair == search_tag ) |
||||
goto Found; |
||||
|
||||
if ( cur_pair < search_tag ) |
||||
left = middle + 1; |
||||
else |
||||
right = middle - 1; |
||||
} |
||||
} |
||||
|
||||
Exit: |
||||
return T2_Err_Ok; |
||||
|
||||
Found: |
||||
kerning->x = pair->value; |
||||
goto Exit; |
||||
} |
||||
|
||||
|
||||
#undef PAIR_TAG |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Function> */ |
||||
/* Load_Glyph */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* A driver method used to load a glyph within a given glyph slot. */ |
||||
/* */ |
||||
/* <Input> */ |
||||
/* slot :: A handle to the target slot object where the glyph */ |
||||
/* will be loaded. */ |
||||
/* */ |
||||
/* size :: A handle to the source face size at which the glyph */ |
||||
/* must be scaled, loaded, etc. */ |
||||
/* */ |
||||
/* glyph_index :: The index of the glyph in the font file. */ |
||||
/* */ |
||||
/* load_flags :: A flag indicating what to load for this glyph. The */ |
||||
/* FTLOAD_??? constants can be used to control the */ |
||||
/* glyph loading process (e.g., whether the outline */ |
||||
/* should be scaled, whether to load bitmaps or not, */ |
||||
/* whether to hint the outline, etc). */ |
||||
/* */ |
||||
/* <Return> */ |
||||
/* FreeType error code. 0 means success. */ |
||||
/* */ |
||||
static |
||||
FT_Error Load_Glyph( T2_GlyphSlot slot, |
||||
T2_Size size, |
||||
FT_UShort glyph_index, |
||||
FT_UInt load_flags ) |
||||
{ |
||||
FT_Error error; |
||||
|
||||
|
||||
if ( !slot ) |
||||
return T2_Err_Invalid_Glyph_Handle; |
||||
|
||||
/* check whether we want a scaled outline or bitmap */ |
||||
if ( !size ) |
||||
load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; |
||||
|
||||
if ( load_flags & FT_LOAD_NO_SCALE ) |
||||
size = NULL; |
||||
|
||||
/* reset the size object if necessary */ |
||||
if ( size ) |
||||
{ |
||||
/* these two object must have the same parent */ |
||||
if ( size->face != slot->root.face ) |
||||
return T2_Err_Invalid_Face_Handle; |
||||
} |
||||
|
||||
/* now load the glyph outline if necessary */ |
||||
error = T2_Load_Glyph( slot, size, glyph_index, load_flags ); |
||||
|
||||
/* force drop-out mode to 2 - irrelevant now */ |
||||
/* slot->outline.dropout_mode = 2; */ |
||||
|
||||
return error; |
||||
} |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/**** C H A R A C T E R M A P P I N G S ****/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Function> */ |
||||
/* Get_Char_Index */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* Uses a charmap to return a given character code's glyph index. */ |
||||
/* */ |
||||
/* <Input> */ |
||||
/* charmap :: A handle to the source charmap object. */ |
||||
/* charcode :: The character code. */ |
||||
/* */ |
||||
/* <Return> */ |
||||
/* Glyph index. 0 means `undefined character code'. */ |
||||
/* */ |
||||
static |
||||
FT_UInt t2_get_char_index( TT_CharMap charmap, |
||||
FT_Long charcode ) |
||||
{ |
||||
FT_Error error; |
||||
T2_Face face; |
||||
TT_CMapTable* cmap; |
||||
|
||||
|
||||
cmap = &charmap->cmap; |
||||
face = (T2_Face)charmap->root.face; |
||||
|
||||
/* Load table if needed */ |
||||
if ( !cmap->loaded ) |
||||
{ |
||||
SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; |
||||
|
||||
|
||||
error = sfnt->load_charmap( face, cmap, face->root.stream ); |
||||
if ( error ) |
||||
return 0; |
||||
|
||||
cmap->loaded = TRUE; |
||||
} |
||||
|
||||
return ( cmap->get_index ? cmap->get_index( cmap, charcode ) : 0 ); |
||||
} |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/**** D R I V E R I N T E R F A C E ****/ |
||||
/**** ****/ |
||||
/**** ****/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
static |
||||
FT_Module_Interface t2_get_interface( T2_Driver driver, |
||||
const char* interface ) |
||||
{ |
||||
FT_Module sfnt; |
||||
|
||||
|
||||
/* we simply pass our request to the `sfnt' module */ |
||||
sfnt = FT_Get_Module( driver->root.root.library, "sfnt" ); |
||||
|
||||
return sfnt ? sfnt->clazz->get_interface( sfnt, interface ) : 0; |
||||
} |
||||
|
||||
|
||||
/* The FT_DriverInterface structure is defined in ftdriver.h. */ |
||||
|
||||
FT_CALLBACK_TABLE_DEF |
||||
const FT_Driver_Class cff_driver_class = |
||||
{ |
||||
/* begin with the FT_Module_Class fields */ |
||||
{ |
||||
ft_module_font_driver | ft_module_driver_scalable, |
||||
sizeof( T2_DriverRec ), |
||||
"cff", |
||||
0x10000L, |
||||
0x20000L, |
||||
|
||||
0, /* module-specific interface */ |
||||
|
||||
(FT_Module_Constructor)T2_Init_Driver, |
||||
(FT_Module_Destructor) T2_Done_Driver, |
||||
(FT_Module_Requester) t2_get_interface, |
||||
}, |
||||
|
||||
/* now the specific driver fields */ |
||||
sizeof( TT_FaceRec ), |
||||
sizeof( FT_SizeRec ), |
||||
sizeof( T2_GlyphSlotRec ), |
||||
|
||||
(FTDriver_initFace) T2_Init_Face, |
||||
(FTDriver_doneFace) T2_Done_Face, |
||||
(FTDriver_initSize) 0, |
||||
(FTDriver_doneSize) 0, |
||||
(FTDriver_initGlyphSlot)0, |
||||
(FTDriver_doneGlyphSlot)0, |
||||
|
||||
(FTDriver_setCharSizes) 0, |
||||
(FTDriver_setPixelSizes)0, |
||||
|
||||
(FTDriver_loadGlyph) Load_Glyph, |
||||
(FTDriver_getCharIndex) t2_get_char_index, |
||||
|
||||
(FTDriver_getKerning) Get_Kerning, |
||||
(FTDriver_attachFile) 0, |
||||
(FTDriver_getAdvances) 0 |
||||
}; |
||||
|
||||
|
||||
#ifdef FT_CONFIG_OPTION_DYNAMIC_DRIVERS |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Function> */ |
||||
/* getDriverClass */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* This function is used when compiling the TrueType driver as a */ |
||||
/* shared library (`.DLL' or `.so'). It will be used by the */ |
||||
/* high-level library of FreeType to retrieve the address of the */ |
||||
/* driver's generic interface. */ |
||||
/* */ |
||||
/* It shouldn't be implemented in a static build, as each driver must */ |
||||
/* have the same function as an exported entry point. */ |
||||
/* */ |
||||
/* <Return> */ |
||||
/* The address of the TrueType's driver generic interface. The */ |
||||
/* format-specific interface can then be retrieved through the method */ |
||||
/* interface->get_format_interface. */ |
||||
/* */ |
||||
FT_EXPORT_DEF( const FT_Driver_Class* ) getDriverClass( void ) |
||||
{ |
||||
return &cff_driver_class; |
||||
} |
||||
|
||||
|
||||
#endif /* CONFIG_OPTION_DYNAMIC_DRIVERS */ |
||||
|
||||
|
||||
/* END */ |
@ -0,0 +1,36 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* cffdrivr.h */ |
||||
/* */ |
||||
/* High-level OpenType driver interface (specification). */ |
||||
/* */ |
||||
/* Copyright 1996-2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
#ifndef CFFDRIVER_H |
||||
#define CFFDRIVER_H |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_INTERNAL_DRIVER_H |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
FT_CALLBACK_TABLE |
||||
const FT_Driver_Class cff_driver_class; |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* CFFDRIVER_H */ |
||||
|
||||
|
||||
/* END */ |
@ -0,0 +1,952 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* cffload.c */ |
||||
/* */ |
||||
/* OpenType and CFF data/program tables loader (body) */ |
||||
/* */ |
||||
/* Copyright 1996-2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_INTERNAL_DEBUG_H |
||||
#include FT_INTERNAL_OBJECTS_H |
||||
#include FT_INTERNAL_STREAM_H |
||||
#include FT_INTERNAL_POSTSCRIPT_NAMES_H |
||||
#include FT_INTERNAL_CFF_ERRORS_H |
||||
#include FT_TRUETYPE_TAGS_H |
||||
|
||||
#include FT_SOURCE_FILE(cff,cffload.h) |
||||
#include FT_SOURCE_FILE(cff,cffparse.h) |
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
||||
/* messages during execution. */ |
||||
/* */ |
||||
#undef FT_COMPONENT |
||||
#define FT_COMPONENT trace_t2load |
||||
|
||||
|
||||
/* read a CFF offset from memory */ |
||||
static FT_ULong |
||||
cff_get_offset( FT_Byte* p, |
||||
FT_Byte off_size ) |
||||
{ |
||||
FT_ULong result; |
||||
|
||||
|
||||
for ( result = 0; off_size > 0; off_size-- ) |
||||
{ |
||||
result <<= 8; |
||||
result |= *p++; |
||||
} |
||||
|
||||
return result; |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
cff_new_index( CFF_Index* index, |
||||
FT_Stream stream, |
||||
FT_Bool load ) |
||||
{ |
||||
FT_Error error; |
||||
FT_Memory memory = stream->memory; |
||||
FT_UShort count; |
||||
|
||||
|
||||
MEM_Set( index, 0, sizeof ( *index ) ); |
||||
|
||||
index->stream = stream; |
||||
if ( !READ_UShort( count ) && |
||||
count > 0 ) |
||||
{ |
||||
FT_Byte* p; |
||||
FT_Byte offsize; |
||||
FT_ULong data_size; |
||||
FT_ULong* poff; |
||||
|
||||
|
||||
/* there is at least one element; read the offset size, */ |
||||
/* then access the offset table to compute the index's total size */ |
||||
if ( READ_Byte( offsize ) ) |
||||
goto Exit; |
||||
|
||||
index->stream = stream; |
||||
index->count = count; |
||||
index->off_size = offsize; |
||||
data_size = (FT_ULong)( count + 1 ) * offsize; |
||||
|
||||
if ( ALLOC_ARRAY( index->offsets, count + 1, FT_ULong ) || |
||||
ACCESS_Frame( data_size ) ) |
||||
goto Exit; |
||||
|
||||
poff = index->offsets; |
||||
p = (FT_Byte*)stream->cursor; |
||||
|
||||
for ( ; (FT_Short)count >= 0; count-- ) |
||||
{ |
||||
poff[0] = cff_get_offset( p, offsize ); |
||||
poff++; |
||||
p += offsize; |
||||
} |
||||
|
||||
FORGET_Frame(); |
||||
|
||||
index->data_offset = FILE_Pos(); |
||||
data_size = poff[-1] - 1; |
||||
|
||||
if ( load ) |
||||
{ |
||||
/* load the data */ |
||||
if ( EXTRACT_Frame( data_size, index->bytes ) ) |
||||
goto Exit; |
||||
} |
||||
else |
||||
{ |
||||
/* skip the data */ |
||||
if ( FILE_Skip( data_size ) ) |
||||
goto Exit; |
||||
} |
||||
} |
||||
|
||||
Exit: |
||||
if ( error ) |
||||
FREE( index->offsets ); |
||||
|
||||
return error; |
||||
} |
||||
|
||||
|
||||
static void |
||||
cff_done_index( CFF_Index* index ) |
||||
{ |
||||
if ( index->stream ) |
||||
{ |
||||
FT_Stream stream = index->stream; |
||||
FT_Memory memory = stream->memory; |
||||
|
||||
|
||||
if ( index->bytes ) |
||||
RELEASE_Frame( index->bytes ); |
||||
|
||||
FREE( index->offsets ); |
||||
MEM_Set( index, 0, sizeof ( *index ) ); |
||||
} |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
cff_explicit_index( CFF_Index* index, |
||||
FT_Byte*** table ) |
||||
{ |
||||
FT_Error error = 0; |
||||
FT_Memory memory = index->stream->memory; |
||||
FT_UInt n, offset, old_offset; |
||||
FT_Byte** t; |
||||
|
||||
|
||||
*table = 0; |
||||
|
||||
if ( index->count > 0 && !ALLOC_ARRAY( t, index->count + 1, FT_Byte* ) ) |
||||
{ |
||||
old_offset = 1; |
||||
for ( n = 0; n <= index->count; n++ ) |
||||
{ |
||||
offset = index->offsets[n]; |
||||
if ( !offset ) |
||||
offset = old_offset; |
||||
|
||||
t[n] = index->bytes + offset - 1; |
||||
|
||||
old_offset = offset; |
||||
} |
||||
*table = t; |
||||
} |
||||
|
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF FT_Error |
||||
CFF_Access_Element( CFF_Index* index, |
||||
FT_UInt element, |
||||
FT_Byte** pbytes, |
||||
FT_ULong* pbyte_len ) |
||||
{ |
||||
FT_Error error = 0; |
||||
|
||||
|
||||
if ( index && index->count > element ) |
||||
{ |
||||
/* compute start and end offsets */ |
||||
FT_ULong off1, off2 = 0; |
||||
|
||||
|
||||
off1 = index->offsets[element]; |
||||
if ( off1 ) |
||||
{ |
||||
do |
||||
{ |
||||
element++; |
||||
off2 = index->offsets[element]; |
||||
|
||||
} while ( off2 == 0 && element < index->count ); |
||||
|
||||
if ( !off2 ) |
||||
off1 = 0; |
||||
} |
||||
|
||||
/* access element */ |
||||
if ( off1 ) |
||||
{ |
||||
*pbyte_len = off2 - off1; |
||||
|
||||
if ( index->bytes ) |
||||
{ |
||||
/* this index was completely loaded in memory, that's easy */ |
||||
*pbytes = index->bytes + off1 - 1; |
||||
} |
||||
else |
||||
{ |
||||
/* this index is still on disk/file, access it through a frame */ |
||||
FT_Stream stream = index->stream; |
||||
|
||||
|
||||
if ( FILE_Seek( index->data_offset + off1 - 1 ) || |
||||
EXTRACT_Frame( off2 - off1, *pbytes ) ) |
||||
goto Exit; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
/* empty index element */ |
||||
*pbytes = 0; |
||||
*pbyte_len = 0; |
||||
} |
||||
} |
||||
else |
||||
error = T2_Err_Invalid_Argument; |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF void |
||||
CFF_Forget_Element( CFF_Index* index, |
||||
FT_Byte** pbytes ) |
||||
{ |
||||
if ( index->bytes == 0 ) |
||||
{ |
||||
FT_Stream stream = index->stream; |
||||
|
||||
|
||||
RELEASE_Frame( *pbytes ); |
||||
} |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF FT_String* |
||||
CFF_Get_Name( CFF_Index* index, |
||||
FT_UInt element ) |
||||
{ |
||||
FT_Memory memory = index->stream->memory; |
||||
FT_Byte* bytes; |
||||
FT_ULong byte_len; |
||||
FT_Error error; |
||||
FT_String* name = 0; |
||||
|
||||
|
||||
error = CFF_Access_Element( index, element, &bytes, &byte_len ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
if ( !ALLOC( name, byte_len + 1 ) ) |
||||
{ |
||||
MEM_Copy( name, bytes, byte_len ); |
||||
name[byte_len] = 0; |
||||
} |
||||
CFF_Forget_Element( index, &bytes ); |
||||
|
||||
Exit: |
||||
return name; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF FT_String* |
||||
CFF_Get_String( CFF_Index* index, |
||||
FT_UInt sid, |
||||
PSNames_Interface* interface ) |
||||
{ |
||||
/* if it is not a standard string, return it */ |
||||
if ( sid > 390 ) |
||||
return CFF_Get_Name( index, sid - 391 ); |
||||
|
||||
/* that's a standard string, fetch a copy from the PSName module */ |
||||
{ |
||||
FT_String* name = 0; |
||||
const char* adobe_name = interface->adobe_std_strings( sid ); |
||||
FT_UInt len; |
||||
|
||||
|
||||
if ( adobe_name ) |
||||
{ |
||||
FT_Memory memory = index->stream->memory; |
||||
FT_Error error; |
||||
|
||||
|
||||
len = (FT_UInt)strlen( adobe_name ); |
||||
if ( !ALLOC( name, len + 1 ) ) |
||||
{ |
||||
MEM_Copy( name, adobe_name, len ); |
||||
name[len] = 0; |
||||
} |
||||
} |
||||
|
||||
return name; |
||||
} |
||||
} |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*** ***/ |
||||
/*** FD Select table support ***/ |
||||
/*** ***/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
|
||||
static void |
||||
CFF_Done_FD_Select( CFF_FD_Select* select, |
||||
FT_Stream stream ) |
||||
{ |
||||
if ( select->data ) |
||||
RELEASE_Frame( select->data ); |
||||
|
||||
select->data_size = 0; |
||||
select->format = 0; |
||||
select->range_count = 0; |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
CFF_Load_FD_Select( CFF_FD_Select* select, |
||||
FT_UInt num_glyphs, |
||||
FT_Stream stream, |
||||
FT_ULong offset ) |
||||
{ |
||||
FT_Error error; |
||||
FT_Byte format; |
||||
FT_UInt num_ranges; |
||||
|
||||
|
||||
/* read format */ |
||||
if ( FILE_Seek( offset ) || READ_Byte( format ) ) |
||||
goto Exit; |
||||
|
||||
select->format = format; |
||||
select->cache_count = 0; /* clear cache */ |
||||
|
||||
switch ( format ) |
||||
{ |
||||
case 0: /* format 0, that's simple */ |
||||
select->data_size = num_glyphs; |
||||
goto Load_Data; |
||||
|
||||
case 3: /* format 3, a tad more complex */ |
||||
if ( READ_UShort( num_ranges ) ) |
||||
goto Exit; |
||||
|
||||
select->data_size = num_ranges * 3 + 2; |
||||
|
||||
Load_Data: |
||||
if ( EXTRACT_Frame( select->data_size, select->data ) ) |
||||
goto Exit; |
||||
break; |
||||
|
||||
default: /* hmm... that's wrong */ |
||||
error = T2_Err_Invalid_File_Format; |
||||
} |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF FT_Byte |
||||
CFF_Get_FD( CFF_FD_Select* select, |
||||
FT_UInt glyph_index ) |
||||
{ |
||||
FT_Byte fd = 0; |
||||
|
||||
|
||||
switch ( select->format ) |
||||
{ |
||||
case 0: |
||||
fd = select->data[glyph_index]; |
||||
break; |
||||
|
||||
case 3: |
||||
/* first, compare to cache */ |
||||
if ( (FT_UInt)(glyph_index-select->cache_first) < select->cache_count ) |
||||
{ |
||||
fd = select->cache_fd; |
||||
break; |
||||
} |
||||
|
||||
/* then, lookup the ranges array */ |
||||
{ |
||||
FT_Byte* p = select->data; |
||||
FT_Byte* p_limit = p + select->data_size; |
||||
FT_Byte fd2; |
||||
FT_UInt first, limit; |
||||
|
||||
|
||||
first = NEXT_UShort( p ); |
||||
do |
||||
{ |
||||
if ( glyph_index < first ) |
||||
break; |
||||
|
||||
fd2 = *p++; |
||||
limit = NEXT_UShort( p ); |
||||
|
||||
if ( glyph_index < limit ) |
||||
{ |
||||
fd = fd2; |
||||
|
||||
/* update cache */ |
||||
select->cache_first = first; |
||||
select->cache_count = limit-first; |
||||
select->cache_fd = fd2; |
||||
break; |
||||
} |
||||
first = limit; |
||||
|
||||
} while ( p < p_limit ); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
; |
||||
} |
||||
|
||||
return fd; |
||||
} |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
/*** ***/ |
||||
/*** CFF font support ***/ |
||||
/*** ***/ |
||||
/*************************************************************************/ |
||||
/*************************************************************************/ |
||||
|
||||
static void |
||||
CFF_Done_Encoding( CFF_Encoding* encoding, |
||||
FT_Stream stream ) |
||||
{ |
||||
FT_Memory memory = stream->memory; |
||||
|
||||
FREE( encoding->bytes ); |
||||
encoding->format = 0; |
||||
encoding->size = 0; |
||||
encoding->offset = 0; |
||||
} |
||||
|
||||
|
||||
static void |
||||
CFF_Done_Charset( CFF_Charset* charset, |
||||
FT_Stream stream ) |
||||
{ |
||||
FT_Memory memory = stream->memory; |
||||
|
||||
FREE( charset->bytes ); |
||||
charset->format = 0; |
||||
charset->offset = 0; |
||||
charset->size = 0; |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
CFF_Load_Charset( CFF_Charset* charset, |
||||
FT_UInt num_glyphs, |
||||
FT_Stream stream, |
||||
FT_ULong base_offset, |
||||
FT_ULong offset ) |
||||
{ |
||||
FT_Error error = 0; |
||||
FT_Memory memory = stream->memory; |
||||
|
||||
if ( offset > 2 ) |
||||
{ |
||||
FT_ULong size = 1; |
||||
|
||||
charset->offset = base_offset + offset; |
||||
|
||||
/* we need to parse the table to determine its size */ |
||||
if ( FILE_Seek( charset->offset ) || |
||||
READ_Byte( charset->format ) ) |
||||
goto Exit; |
||||
|
||||
switch (charset->format) |
||||
{ |
||||
case 0: |
||||
{ |
||||
size += 2*(num_glyphs-1); |
||||
break; |
||||
} |
||||
|
||||
case 1: |
||||
{ |
||||
FT_UInt glyph, nleft; |
||||
|
||||
num_glyphs--; |
||||
while (num_glyphs > 0) |
||||
{ |
||||
if ( READ_UShort(glyph) || |
||||
READ_Byte(nleft) ) |
||||
goto Exit; |
||||
|
||||
size += 3; |
||||
num_glyphs -= 1 + nleft; |
||||
} |
||||
break; |
||||
} |
||||
|
||||
case 2: |
||||
{ |
||||
FT_UInt glyph, nleft; |
||||
|
||||
num_glyphs--; |
||||
while (num_glyphs > 0) |
||||
{ |
||||
if ( READ_UShort(glyph) || |
||||
READ_UShort(nleft) ) |
||||
goto Exit; |
||||
|
||||
size += 4; |
||||
num_glyphs -= 1 + nleft; |
||||
} |
||||
break; |
||||
} |
||||
|
||||
default: |
||||
FT_ERROR(( "CFF.Load_Charset: invalid table format !!\n" )); |
||||
error = FT_Err_Invalid_File_Format; |
||||
goto Exit; |
||||
} |
||||
|
||||
charset->size = size; |
||||
|
||||
if ( ALLOC( charset->bytes, size ) || |
||||
FILE_Seek( charset->offset ) || |
||||
FILE_Read( charset->bytes, size ) ) |
||||
goto Exit; |
||||
} |
||||
else |
||||
charset->offset = offset; |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
CFF_Load_Encoding( CFF_Encoding* encoding, |
||||
FT_UInt num_glyphs, |
||||
FT_Stream stream, |
||||
FT_ULong base_offset, |
||||
FT_ULong offset ) |
||||
{ |
||||
FT_Error error = 0; |
||||
FT_Memory memory = stream->memory; |
||||
FT_UInt count; |
||||
|
||||
FT_UNUSED(num_glyphs); |
||||
|
||||
if ( offset > 2 ) |
||||
{ |
||||
FT_ULong size = 1; |
||||
|
||||
encoding->offset = base_offset + offset; |
||||
|
||||
/* we need to parse the table to determine its size */ |
||||
if ( FILE_Seek( encoding->offset ) || |
||||
READ_Byte( encoding->format ) || |
||||
READ_Byte( count ) ) |
||||
goto Exit; |
||||
|
||||
switch (encoding->format & 0x7F) |
||||
{ |
||||
case 0: |
||||
{ |
||||
size = 2+count; |
||||
break; |
||||
} |
||||
|
||||
case 1: |
||||
{ |
||||
size = 2+count*2; |
||||
break; |
||||
} |
||||
|
||||
case 2: |
||||
{ |
||||
size = 2+count*3; |
||||
break; |
||||
} |
||||
|
||||
default: |
||||
FT_ERROR(( "CFF.Load_Encoding: invalid table format !!\n" )); |
||||
error = FT_Err_Invalid_File_Format; |
||||
goto Exit; |
||||
} |
||||
|
||||
if (encoding->format & 0x80) |
||||
{ |
||||
/* count supplements.. */ |
||||
if ( FILE_Seek( encoding->offset + size ) || |
||||
READ_Byte( count ) ) |
||||
goto Exit; |
||||
|
||||
size += 1+3*count; |
||||
} |
||||
|
||||
encoding->size = size; |
||||
|
||||
if ( ALLOC( encoding->bytes, size ) || |
||||
FILE_Seek( encoding->offset ) || |
||||
FILE_Read( encoding->bytes, size ) ) |
||||
goto Exit; |
||||
} |
||||
else |
||||
encoding->offset = offset; |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
|
||||
static FT_Error |
||||
CFF_Load_SubFont( CFF_SubFont* font, |
||||
CFF_Index* index, |
||||
FT_UInt font_index, |
||||
FT_Stream stream, |
||||
FT_ULong base_offset ) |
||||
{ |
||||
FT_Error error; |
||||
CFF_Parser parser; |
||||
FT_Byte* dict; |
||||
FT_ULong dict_len; |
||||
CFF_Font_Dict* top = &font->font_dict; |
||||
CFF_Private* priv = &font->private_dict; |
||||
|
||||
|
||||
CFF_Parser_Init( &parser, CFF_CODE_TOPDICT, &font->font_dict ); |
||||
|
||||
/* set defaults */ |
||||
MEM_Set( top, 0, sizeof ( *top ) ); |
||||
|
||||
top->underline_position = -100; |
||||
top->underline_thickness = 50; |
||||
top->charstring_type = 2; |
||||
top->font_matrix.xx = 0x10000L; |
||||
top->font_matrix.yy = 0x10000L; |
||||
top->cid_count = 8720; |
||||
|
||||
error = CFF_Access_Element( index, font_index, &dict, &dict_len ) || |
||||
CFF_Parser_Run( &parser, dict, dict + dict_len ); |
||||
|
||||
CFF_Forget_Element( index, &dict ); |
||||
|
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* if it is a CID font, we stop there */ |
||||
if ( top->cid_registry ) |
||||
goto Exit; |
||||
|
||||
/* parse the private dictionary, if any */ |
||||
if ( top->private_offset && top->private_size ) |
||||
{ |
||||
/* set defaults */ |
||||
MEM_Set( priv, 0, sizeof ( *priv ) ); |
||||
|
||||
priv->blue_shift = 7; |
||||
priv->blue_fuzz = 1; |
||||
priv->lenIV = -1; |
||||
priv->expansion_factor = (FT_Fixed)0.06 * 0x10000L; |
||||
priv->blue_scale = (FT_Fixed)0.039625 * 0x10000L; |
||||
|
||||
CFF_Parser_Init( &parser, CFF_CODE_PRIVATE, priv ); |
||||
|
||||
if ( FILE_Seek( base_offset + font->font_dict.private_offset ) || |
||||
ACCESS_Frame( font->font_dict.private_size ) ) |
||||
goto Exit; |
||||
|
||||
error = CFF_Parser_Run( &parser, |
||||
(FT_Byte*)stream->cursor, |
||||
(FT_Byte*)stream->limit ); |
||||
FORGET_Frame(); |
||||
if ( error ) |
||||
goto Exit; |
||||
} |
||||
|
||||
/* read the local subrs, if any */ |
||||
if ( priv->local_subrs_offset ) |
||||
{ |
||||
if ( FILE_Seek( base_offset + top->private_offset + |
||||
priv->local_subrs_offset ) ) |
||||
goto Exit; |
||||
|
||||
error = cff_new_index( &font->local_subrs_index, stream, 1 ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
font->num_local_subrs = font->local_subrs_index.count; |
||||
error = cff_explicit_index( &font->local_subrs_index, |
||||
&font->local_subrs ); |
||||
if (error) |
||||
goto Exit; |
||||
} |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
static void |
||||
CFF_Done_SubFont( FT_Memory memory, |
||||
CFF_SubFont* subfont ) |
||||
{ |
||||
if ( subfont ) |
||||
{ |
||||
cff_done_index( &subfont->local_subrs_index ); |
||||
FREE( subfont->local_subrs ); |
||||
} |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF FT_Error |
||||
CFF_Load_Font( FT_Stream stream, |
||||
FT_Int face_index, |
||||
CFF_Font* font ) |
||||
{ |
||||
static const FT_Frame_Field cff_header_fields[] = |
||||
{ |
||||
#undef FT_STRUCTURE |
||||
#define FT_STRUCTURE CFF_Font |
||||
|
||||
FT_FRAME_START( 4 ), |
||||
FT_FRAME_BYTE( version_major ), |
||||
FT_FRAME_BYTE( version_minor ), |
||||
FT_FRAME_BYTE( header_size ), |
||||
FT_FRAME_BYTE( absolute_offsize ), |
||||
FT_FRAME_END |
||||
}; |
||||
|
||||
FT_Error error; |
||||
FT_Memory memory = stream->memory; |
||||
FT_ULong base_offset; |
||||
CFF_Font_Dict* dict; |
||||
|
||||
|
||||
MEM_Set( font, 0, sizeof ( *font ) ); |
||||
|
||||
font->stream = stream; |
||||
font->memory = memory; |
||||
dict = &font->top_font.font_dict; |
||||
base_offset = FILE_Pos(); |
||||
|
||||
/* read CFF font header */ |
||||
if ( READ_Fields( cff_header_fields, font ) ) |
||||
goto Exit; |
||||
|
||||
/* check format */ |
||||
if ( font->version_major != 1 || |
||||
font->header_size < 4 || |
||||
font->absolute_offsize > 4 ) |
||||
{ |
||||
FT_TRACE2(( "[not a CFF font header!]\n" )); |
||||
error = FT_Err_Unknown_File_Format; |
||||
goto Exit; |
||||
} |
||||
|
||||
/* skip the rest of the header */ |
||||
if ( FILE_Skip( font->header_size - 4 ) ) |
||||
goto Exit; |
||||
|
||||
/* read the name, top dict, string and global subrs index */ |
||||
if ( FT_SET_ERROR(cff_new_index( &font->name_index, stream, 0 )) || |
||||
FT_SET_ERROR(cff_new_index( &font->font_dict_index, stream, 0 )) || |
||||
FT_SET_ERROR(cff_new_index( &font->string_index, stream, 0 )) || |
||||
FT_SET_ERROR(cff_new_index( &font->global_subrs_index, stream, 1 )) ) |
||||
goto Exit; |
||||
|
||||
/* well, we don't really forget the `disabled' fonts... */ |
||||
font->num_faces = font->name_index.count; |
||||
if ( face_index >= (FT_Int)font->num_faces ) |
||||
{ |
||||
FT_ERROR(( "CFF_Load_Font: incorrect face index = %d\n", |
||||
face_index )); |
||||
error = T2_Err_Invalid_Argument; |
||||
} |
||||
|
||||
/* in case of a font format check, simply exit now */ |
||||
if ( face_index < 0 ) |
||||
goto Exit; |
||||
|
||||
/* now, parse the top-level font dictionary */ |
||||
error = CFF_Load_SubFont( &font->top_font, |
||||
&font->font_dict_index, |
||||
face_index, |
||||
stream, |
||||
base_offset ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* now, check for a CID font */ |
||||
if ( dict->cid_registry ) |
||||
{ |
||||
CFF_Index fd_index; |
||||
CFF_SubFont* sub; |
||||
FT_UInt index; |
||||
|
||||
|
||||
/* this is a CID-keyed font, we must now allocate a table of */ |
||||
/* sub-fonts, then load each of them separately */ |
||||
if ( FILE_Seek( base_offset + dict->cid_fd_array_offset ) ) |
||||
goto Exit; |
||||
|
||||
error = cff_new_index( &fd_index, stream, 0 ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
if ( fd_index.count > CFF_MAX_CID_FONTS ) |
||||
{ |
||||
FT_ERROR(( "CFF_Load_Font: FD array too large in CID font\n" )); |
||||
goto Fail_CID; |
||||
} |
||||
|
||||
/* allocate & read each font dict independently */ |
||||
font->num_subfonts = fd_index.count; |
||||
if ( ALLOC_ARRAY( sub, fd_index.count, CFF_SubFont ) ) |
||||
goto Fail_CID; |
||||
|
||||
/* setup pointer table */ |
||||
for ( index = 0; index < fd_index.count; index++ ) |
||||
font->subfonts[index] = sub + index; |
||||
|
||||
/* now load each sub font independently */ |
||||
for ( index = 0; index < fd_index.count; index++ ) |
||||
{ |
||||
sub = font->subfonts[index]; |
||||
error = CFF_Load_SubFont( sub, &fd_index, index, |
||||
stream, base_offset ); |
||||
if ( error ) |
||||
goto Fail_CID; |
||||
} |
||||
|
||||
/* now load the FD Select array */ |
||||
error = CFF_Load_FD_Select( &font->fd_select, |
||||
dict->cid_count, |
||||
stream, |
||||
base_offset + dict->cid_fd_select_offset ); |
||||
|
||||
Fail_CID: |
||||
cff_done_index( &fd_index ); |
||||
|
||||
if ( error ) |
||||
goto Exit; |
||||
} |
||||
else |
||||
font->num_subfonts = 0; |
||||
|
||||
/* read the charstrings index now */ |
||||
if ( dict->charstrings_offset == 0 ) |
||||
{ |
||||
FT_ERROR(( "CFF_Load_Font: no charstrings offset!\n" )); |
||||
error = FT_Err_Unknown_File_Format; |
||||
goto Exit; |
||||
} |
||||
|
||||
if ( FILE_Seek( base_offset + dict->charstrings_offset ) ) |
||||
goto Exit; |
||||
|
||||
error = cff_new_index( &font->charstrings_index, stream, 0 ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* explicit the global subrs */ |
||||
font->num_global_subrs = font->global_subrs_index.count; |
||||
font->num_glyphs = font->charstrings_index.count; |
||||
|
||||
error = cff_explicit_index( &font->global_subrs_index, |
||||
&font->global_subrs ) ; |
||||
|
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* read the Charset and Encoding tables when available */ |
||||
error = CFF_Load_Charset( &font->charset, font->num_glyphs, stream, |
||||
base_offset, dict->charset_offset ); |
||||
if (error) |
||||
goto Exit; |
||||
|
||||
error = CFF_Load_Encoding( &font->encoding, font->num_glyphs, stream, |
||||
base_offset, dict->encoding_offset ); |
||||
if (error) |
||||
goto Exit; |
||||
|
||||
/* get the font name */ |
||||
font->font_name = CFF_Get_Name( &font->name_index, face_index ); |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
|
||||
FT_LOCAL_DEF void |
||||
CFF_Done_Font( CFF_Font* font ) |
||||
{ |
||||
FT_Memory memory = font->memory; |
||||
FT_UInt index; |
||||
|
||||
|
||||
cff_done_index( &font->global_subrs_index ); |
||||
cff_done_index( &font->string_index ); |
||||
cff_done_index( &font->font_dict_index ); |
||||
cff_done_index( &font->name_index ); |
||||
cff_done_index( &font->charstrings_index ); |
||||
|
||||
/* release font dictionaries */ |
||||
for ( index = 0; index < font->num_subfonts; index++ ) |
||||
CFF_Done_SubFont( memory, font->subfonts[index] ); |
||||
|
||||
CFF_Done_Encoding( &font->encoding, font->stream ); |
||||
CFF_Done_Charset( &font->charset, font->stream ); |
||||
|
||||
CFF_Done_SubFont( memory, &font->top_font ); |
||||
|
||||
CFF_Done_FD_Select( &font->fd_select, font->stream ); |
||||
|
||||
FREE( font->global_subrs ); |
||||
FREE( font->font_name ); |
||||
} |
||||
|
||||
|
||||
/* END */ |
@ -0,0 +1,70 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* cffload.h */ |
||||
/* */ |
||||
/* OpenType & CFF data/program tables loader (specification). */ |
||||
/* */ |
||||
/* Copyright 1996-2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
#ifndef CFFLOAD_H |
||||
#define CFFLOAD_H |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_INTERNAL_CFF_TYPES_H |
||||
#include FT_INTERNAL_POSTSCRIPT_NAMES_H |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
FT_LOCAL FT_String* |
||||
CFF_Get_Name( CFF_Index* index, |
||||
FT_UInt element ); |
||||
|
||||
|
||||
FT_LOCAL FT_String* |
||||
CFF_Get_String( CFF_Index* index, |
||||
FT_UInt sid, |
||||
PSNames_Interface* interface ); |
||||
|
||||
|
||||
FT_LOCAL FT_Error |
||||
CFF_Access_Element( CFF_Index* index, |
||||
FT_UInt element, |
||||
FT_Byte** pbytes, |
||||
FT_ULong* pbyte_len ); |
||||
|
||||
|
||||
FT_LOCAL void |
||||
CFF_Forget_Element( CFF_Index* index, |
||||
FT_Byte** pbytes ); |
||||
|
||||
|
||||
FT_LOCAL FT_Error |
||||
CFF_Load_Font( FT_Stream stream, |
||||
FT_Int face_index, |
||||
CFF_Font* font ); |
||||
|
||||
|
||||
FT_LOCAL void |
||||
CFF_Done_Font( CFF_Font* font ); |
||||
|
||||
|
||||
FT_LOCAL FT_Byte |
||||
CFF_Get_FD( CFF_FD_Select* select, |
||||
FT_UInt glyph_index ); |
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* CFFLOAD_H */ |
||||
|
||||
|
||||
/* END */ |
@ -0,0 +1,589 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* cffobjs.c */ |
||||
/* */ |
||||
/* OpenType objects manager (body). */ |
||||
/* */ |
||||
/* Copyright 1996-2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_INTERNAL_DEBUG_H |
||||
#include FT_INTERNAL_CALC_H |
||||
#include FT_INTERNAL_STREAM_H |
||||
#include FT_ERRORS_H |
||||
#include FT_TRUETYPE_NAMES_H |
||||
#include FT_TRUETYPE_TAGS_H |
||||
#include FT_INTERNAL_SFNT_H |
||||
#include FT_INTERNAL_POSTSCRIPT_NAMES_H |
||||
#include FT_SOURCE_FILE(cff,cffobjs.h) |
||||
#include FT_SOURCE_FILE(cff,cffload.h) |
||||
#include FT_INTERNAL_CFF_ERRORS_H |
||||
#include <string.h> /* for strlen() */ |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
||||
/* messages during execution. */ |
||||
/* */ |
||||
#undef FT_COMPONENT |
||||
#define FT_COMPONENT trace_t2objs |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* FACE FUNCTIONS */ |
||||
/* */ |
||||
/*************************************************************************/ |
||||
|
||||
static |
||||
FT_String* T2_StrCopy( FT_Memory memory, |
||||
const FT_String* source ) |
||||
{ |
||||
FT_Error error; |
||||
FT_String* result = 0; |
||||
FT_Int len = (FT_Int)strlen( source ); |
||||
|
||||
|
||||
if ( !ALLOC( result, len + 1 ) ) |
||||
{ |
||||
MEM_Copy( result, source, len ); |
||||
result[len] = 0; |
||||
} |
||||
return result; |
||||
} |
||||
|
||||
|
||||
#if 0 |
||||
|
||||
/* this function is used to build a Unicode charmap from the glyph names */ |
||||
/* in a file */ |
||||
static |
||||
FT_Error CFF_Build_Unicode_Charmap( T2_Face face, |
||||
FT_ULong base_offset, |
||||
PSNames_Interface* psnames ) |
||||
{ |
||||
CFF_Font* font = (CFF_Font*)face->extra.data; |
||||
FT_Memory memory = FT_FACE_MEMORY(face); |
||||
FT_UInt n, num_glyphs = face->root.num_glyphs; |
||||
const char** glyph_names; |
||||
FT_Error error; |
||||
CFF_Font_Dict* dict = &font->top_font.font_dict; |
||||
FT_ULong charset_offset; |
||||
FT_Byte format; |
||||
FT_Stream stream = face->root.stream; |
||||
|
||||
|
||||
charset_offset = dict->charset_offset; |
||||
if ( !charset_offset ) |
||||
{ |
||||
FT_ERROR(( "CFF.Build_Unicode_Charmap: charset table is missing\n" )); |
||||
error = T2_Err_Invalid_File_Format; |
||||
goto Exit; |
||||
} |
||||
|
||||
/* allocate the charmap */ |
||||
if ( ALLOC( face->charmap, ... |
||||
|
||||
/* seek to charset table and allocate glyph names table */ |
||||
if ( FILE_Seek( base_offset + charset_offset ) || |
||||
ALLOC_ARRAY( glyph_names, num_glyphs, const char* ) ) |
||||
goto Exit; |
||||
|
||||
/* now, read each glyph name and store it in the glyph name table */ |
||||
if ( READ_Byte( format ) ) |
||||
goto Fail; |
||||
|
||||
switch ( format ) |
||||
{ |
||||
case 0: /* format 0 - one SID per glyph */ |
||||
{ |
||||
const char** gname = glyph_names; |
||||
const char** limit = gname + num_glyphs; |
||||
|
||||
if ( ACCESS_Frame( num_glyphs*2 ) ) |
||||
goto Fail; |
||||
|
||||
for ( ; gname < limit; gname++ ) |
||||
gname[0] = T2_Get_String( &font->string_index, |
||||
GET_UShort(), |
||||
psnames ); |
||||
FORGET_Frame(); |
||||
break; |
||||
} |
||||
|
||||
case 1: /* format 1 - sequential ranges */ |
||||
case 2: /* format 2 - sequential ranges with 16-bit counts */ |
||||
{ |
||||
const char** gname = glyph_names; |
||||
const char** limit = gname + num_glyphs; |
||||
FT_UInt len = 3; |
||||
|
||||
if (format == 2) |
||||
len++; |
||||
|
||||
while (gname < limit) |
||||
{ |
||||
FT_UInt first; |
||||
FT_UInt count; |
||||
|
||||
if ( ACCESS_Frame( len ) ) |
||||
goto Fail; |
||||
|
||||
first = GET_UShort(); |
||||
if (format == 3) |
||||
count = GET_UShort(); |
||||
else |
||||
count = GET_Byte(); |
||||
|
||||
FORGET_Frame(); |
||||
|
||||
for ( ; count > 0; count-- ) |
||||
{ |
||||
gname[0] = T2_Get_String( &font->string_index, |
||||
first, |
||||
psnames ); |
||||
gname++; |
||||
first++; |
||||
} |
||||
} |
||||
break; |
||||
} |
||||
|
||||
default: /* unknown charset format! */ |
||||
FT_ERROR(( "CFF: unknown charset format!\n" )); |
||||
error = T2_Err_Invalid_File_Format; |
||||
goto Fail; |
||||
} |
||||
|
||||
/* all right, the glyph names were loaded, we now need to create */ |
||||
/* the corresponding unicode charmap.. */ |
||||
|
||||
Fail: |
||||
for ( n = 0; n < num_glyphs; n++ ) |
||||
FREE( glyph_names[n] ); |
||||
|
||||
FREE( glyph_names ); |
||||
|
||||
Exit: |
||||
return error; |
||||
} |
||||
|
||||
#endif /* 0 */ |
||||
|
||||
|
||||
static |
||||
FT_Encoding find_encoding( int platform_id, |
||||
int encoding_id ) |
||||
{ |
||||
typedef struct TEncoding |
||||
{ |
||||
int platform_id; |
||||
int encoding_id; |
||||
FT_Encoding encoding; |
||||
|
||||
} TEncoding; |
||||
|
||||
static |
||||
const TEncoding tt_encodings[] = |
||||
{ |
||||
{ TT_PLATFORM_ISO, -1, ft_encoding_unicode }, |
||||
|
||||
{ TT_PLATFORM_APPLE_UNICODE, -1, ft_encoding_unicode }, |
||||
|
||||
{ TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, ft_encoding_apple_roman }, |
||||
|
||||
{ TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, ft_encoding_unicode }, |
||||
{ TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, ft_encoding_sjis }, |
||||
{ TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, ft_encoding_gb2312 }, |
||||
{ TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, ft_encoding_big5 }, |
||||
{ TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, ft_encoding_wansung }, |
||||
{ TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, ft_encoding_johab } |
||||
}; |
||||
|
||||
const TEncoding *cur, *limit; |
||||
|
||||
|
||||
cur = tt_encodings; |
||||
limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); |
||||
|
||||
for ( ; cur < limit; cur++ ) |
||||
{ |
||||
if ( cur->platform_id == platform_id ) |
||||
{ |
||||
if ( cur->encoding_id == encoding_id || |
||||
cur->encoding_id == -1 ) |
||||
return cur->encoding; |
||||
} |
||||
} |
||||
|
||||
return ft_encoding_none; |
||||
} |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Function> */ |
||||
/* T2_Init_Face */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* Initializes a given OpenType face object. */ |
||||
/* */ |
||||
/* <Input> */ |
||||
/* stream :: The source font stream. */ |
||||
/* */ |
||||
/* face_index :: The index of the font face in the resource. */ |
||||
/* */ |
||||
/* num_params :: Number of additional generic parameters. Ignored. */ |
||||
/* */ |
||||
/* params :: Additional generic parameters. Ignored. */ |
||||
/* */ |
||||
/* <InOut> */ |
||||
/* face :: The newly built face object. */ |
||||
/* */ |
||||
/* <Return> */ |
||||
/* FreeType error code. 0 means success. */ |
||||
/* */ |
||||
FT_LOCAL |
||||
FT_Error T2_Init_Face( FT_Stream stream, |
||||
T2_Face face, |
||||
FT_Int face_index, |
||||
FT_Int num_params, |
||||
FT_Parameter* params ) |
||||
{ |
||||
FT_Error error; |
||||
SFNT_Interface* sfnt; |
||||
PSNames_Interface* psnames; |
||||
FT_Bool pure_cff = 1; |
||||
FT_Bool sfnt_format = 0; |
||||
|
||||
|
||||
sfnt = (SFNT_Interface*)FT_Get_Module_Interface( |
||||
face->root.driver->root.library, "sfnt" ); |
||||
if ( !sfnt ) |
||||
goto Bad_Format; |
||||
|
||||
psnames = (PSNames_Interface*)FT_Get_Module_Interface( |
||||
face->root.driver->root.library, "psnames" ); |
||||
|
||||
/* create input stream from resource */ |
||||
if ( FILE_Seek( 0 ) ) |
||||
goto Exit; |
||||
|
||||
/* check that we have a valid OpenType file */ |
||||
error = sfnt->init_face( stream, face, face_index, num_params, params ); |
||||
if ( !error ) |
||||
{ |
||||
if ( face->format_tag != 0x4F54544FL ) /* `OTTO'; OpenType/CFF font */ |
||||
{ |
||||
FT_TRACE2(( "[not a valid OpenType/CFF font]\n" )); |
||||
goto Bad_Format; |
||||
} |
||||
|
||||
/* If we are performing a simple font format check, exit immediately */ |
||||
if ( face_index < 0 ) |
||||
return T2_Err_Ok; |
||||
|
||||
sfnt_format = 1; |
||||
|
||||
/* now, the font can be either an OpenType/CFF font, or a SVG CEF */ |
||||
/* font in the later case; it doesn't have a `head' table */ |
||||
error = face->goto_table( face, TTAG_head, stream, 0 ); |
||||
if ( !error ) |
||||
{ |
||||
pure_cff = 0; |
||||
|
||||
/* Load font directory */ |
||||
error = sfnt->load_face( stream, face, |
||||
face_index, num_params, params ); |
||||
if ( error ) |
||||
goto Exit; |
||||
} |
||||
else |
||||
{ |
||||
/* load the `cmap' table by hand */ |
||||
error = sfnt->load_charmaps( face, stream ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* XXX: for now, we don't load the GPOS table, as OpenType Layout */ |
||||
/* support will be added later to FreeType 2 as a separate module */ |
||||
} |
||||
|
||||
/* now, load the CFF part of the file */ |
||||
error = face->goto_table( face, TTAG_CFF, stream, 0 ); |
||||
if ( error ) |
||||
goto Exit; |
||||
} |
||||
else |
||||
{ |
||||
/* rewind to start of file; we are going to load a pure-CFF font */ |
||||
if ( FILE_Seek( 0 ) ) |
||||
goto Exit; |
||||
error = FT_Err_Ok; |
||||
} |
||||
|
||||
/* now load and parse the CFF table in the file */ |
||||
{ |
||||
CFF_Font* cff; |
||||
FT_Memory memory = face->root.memory; |
||||
FT_Face root; |
||||
FT_UInt flags; |
||||
FT_ULong base_offset; |
||||
|
||||
|
||||
if ( ALLOC( cff, sizeof ( *cff ) ) ) |
||||
goto Exit; |
||||
|
||||
base_offset = FILE_Pos(); |
||||
|
||||
face->extra.data = cff; |
||||
error = CFF_Load_Font( stream, face_index, cff ); |
||||
if ( error ) |
||||
goto Exit; |
||||
|
||||
/* Complement the root flags with some interesting information. */ |
||||
/* Note that this is only necessary for pure CFF and CEF fonts */ |
||||
|
||||
root = &face->root; |
||||
if ( pure_cff ) |
||||
{ |
||||
CFF_Font_Dict* dict = &cff->top_font.font_dict; |
||||
|
||||
|
||||
/* we need the `PSNames' module for pure-CFF and CEF formats */ |
||||
if ( !psnames ) |
||||
{ |
||||
FT_ERROR(( "T2_Init_Face:" )); |
||||
FT_ERROR(( " cannot open CFF & CEF fonts\n" )); |
||||
FT_ERROR(( " " )); |
||||
FT_ERROR(( " without the `PSNames' module\n" )); |
||||
goto Bad_Format; |
||||
} |
||||
|
||||
/* Set up num_faces. */ |
||||
root->num_faces = cff->num_faces; |
||||
|
||||
/* compute number of glyphs */ |
||||
if ( dict->cid_registry ) |
||||
root->num_glyphs = dict->cid_count; |
||||
else |
||||
root->num_glyphs = cff->charstrings_index.count; |
||||
|
||||
/* set global bbox, as well as EM size */ |
||||
root->units_per_EM = 1000; |
||||
root->bbox = dict->font_bbox; |
||||
root->ascender = (FT_Short)root->bbox.yMax; |
||||
root->descender = (FT_Short)root->bbox.yMin; |
||||
root->height = ( ( root->ascender - root->descender ) * 12 ) / 10; |
||||
|
||||
/* retrieve font family & style name */ |
||||
root->family_name = CFF_Get_Name( &cff->name_index, face_index ); |
||||
if ( dict->cid_registry ) |
||||
{ |
||||
root->style_name = T2_StrCopy( memory, "Regular" ); /* XXXX */ |
||||
} |
||||
else |
||||
{ |
||||
root->style_name = CFF_Get_String( &cff->string_index, |
||||
dict->weight, |
||||
psnames ); |
||||
} |
||||
|
||||
/*******************************************************************/ |
||||
/* */ |
||||
/* Compute face flags. */ |
||||
/* */ |
||||
flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ |
||||
FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ |
||||
|
||||
if ( sfnt_format ) |
||||
flags |= FT_FACE_FLAG_SFNT; |
||||
|
||||
/* fixed width font? */ |
||||
if ( dict->is_fixed_pitch ) |
||||
flags |= FT_FACE_FLAG_FIXED_WIDTH; |
||||
|
||||
/* XXXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ |
||||
#if 0 |
||||
/* kerning available? */ |
||||
if ( face->kern_pairs ) |
||||
flags |= FT_FACE_FLAG_KERNING; |
||||
#endif |
||||
|
||||
root->face_flags = flags; |
||||
|
||||
/*******************************************************************/ |
||||
/* */ |
||||
/* Compute style flags. */ |
||||
/* */ |
||||
flags = 0; |
||||
|
||||
if ( dict->italic_angle ) |
||||
flags |= FT_STYLE_FLAG_ITALIC; |
||||
|
||||
/* XXX: may not be correct */ |
||||
if ( cff->top_font.private_dict.force_bold ) |
||||
flags |= FT_STYLE_FLAG_BOLD; |
||||
|
||||
root->style_flags = flags; |
||||
|
||||
/* set the charmaps if any */ |
||||
if ( sfnt_format ) |
||||
{ |
||||
/*****************************************************************/ |
||||
/* */ |
||||
/* Polish the charmaps. */ |
||||
/* */ |
||||
/* Try to set the charmap encoding according to the platform & */ |
||||
/* encoding ID of each charmap. */ |
||||
/* */ |
||||
TT_CharMap charmap; |
||||
FT_Int n; |
||||
|
||||
|
||||
charmap = face->charmaps; |
||||
root->num_charmaps = face->num_charmaps; |
||||
|
||||
/* allocate table of pointers */ |
||||
if ( ALLOC_ARRAY( root->charmaps, root->num_charmaps, FT_CharMap ) ) |
||||
goto Exit; |
||||
|
||||
for ( n = 0; n < root->num_charmaps; n++, charmap++ ) |
||||
{ |
||||
FT_Int platform = charmap->cmap.platformID; |
||||
FT_Int encoding = charmap->cmap.platformEncodingID; |
||||
|
||||
|
||||
charmap->root.face = (FT_Face)face; |
||||
charmap->root.platform_id = platform; |
||||
charmap->root.encoding_id = encoding; |
||||
charmap->root.encoding = find_encoding( platform, encoding ); |
||||
|
||||
/* now, set root->charmap with a unicode charmap */ |
||||
/* wherever available */ |
||||
if ( !root->charmap && |
||||
charmap->root.encoding == ft_encoding_unicode ) |
||||
root->charmap = (FT_CharMap)charmap; |
||||
|
||||
root->charmaps[n] = (FT_CharMap)charmap; |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
Exit: |
||||
return error; |
||||
|
||||
Bad_Format: |
||||
error = FT_Err_Unknown_File_Format; |
||||
goto Exit; |
||||
} |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Function> */ |
||||
/* T2_Done_Face */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* Finalizes a given face object. */ |
||||
/* */ |
||||
/* <Input> */ |
||||
/* face :: A pointer to the face object to destroy. */ |
||||
/* */ |
||||
FT_LOCAL |
||||
void T2_Done_Face( T2_Face face ) |
||||
{ |
||||
FT_Memory memory = face->root.memory; |
||||
SFNT_Interface* sfnt = (SFNT_Interface*)face->sfnt; |
||||
|
||||
|
||||
if ( sfnt ) |
||||
sfnt->done_face( face ); |
||||
|
||||
{ |
||||
CFF_Font* cff = (CFF_Font*)face->extra.data; |
||||
|
||||
|
||||
if ( cff ) |
||||
{ |
||||
CFF_Done_Font( cff ); |
||||
FREE( face->extra.data ); |
||||
} |
||||
} |
||||
} |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Function> */ |
||||
/* T2_Init_Driver */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* Initializes a given OpenType driver object. */ |
||||
/* */ |
||||
/* <Input> */ |
||||
/* driver :: A handle to the target driver object. */ |
||||
/* */ |
||||
/* <Return> */ |
||||
/* FreeType error code. 0 means success. */ |
||||
/* */ |
||||
FT_LOCAL_DEF |
||||
FT_Error T2_Init_Driver( T2_Driver driver ) |
||||
{ |
||||
/* init extension registry if needed */ |
||||
|
||||
#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE |
||||
|
||||
return TT_Init_Extensions( driver ); |
||||
|
||||
#else |
||||
|
||||
FT_UNUSED( driver ); |
||||
|
||||
return T2_Err_Ok; |
||||
|
||||
#endif |
||||
} |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Function> */ |
||||
/* T2_Done_Driver */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* Finalizes a given OpenType driver. */ |
||||
/* */ |
||||
/* <Input> */ |
||||
/* driver :: A handle to the target OpenType driver. */ |
||||
/* */ |
||||
FT_LOCAL_DEF |
||||
void T2_Done_Driver( T2_Driver driver ) |
||||
{ |
||||
/* destroy extensions registry if needed */ |
||||
|
||||
#ifdef TT_CONFIG_OPTION_EXTEND_ENGINE |
||||
|
||||
TT_Done_Extensions( driver ); |
||||
|
||||
#else |
||||
|
||||
FT_UNUSED( driver ); |
||||
|
||||
#endif |
||||
} |
||||
|
||||
|
||||
/* END */ |
@ -0,0 +1,141 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* cffobjs.h */ |
||||
/* */ |
||||
/* OpenType objects manager (specification). */ |
||||
/* */ |
||||
/* Copyright 1996-2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
#ifndef T2OBJS_H |
||||
#define T2OBJS_H |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_INTERNAL_OBJECTS_H |
||||
#include FT_INTERNAL_CFF_TYPES_H |
||||
#include FT_INTERNAL_CFF_ERRORS_H |
||||
#include FT_INTERNAL_POSTSCRIPT_NAMES_H |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Type> */ |
||||
/* T2_Driver */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* A handle to an OpenType driver object. */ |
||||
/* */ |
||||
typedef struct T2_DriverRec_* T2_Driver; |
||||
|
||||
typedef TT_Face T2_Face; |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Type> */ |
||||
/* T2_Size */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* A handle to an OpenType size object. */ |
||||
/* */ |
||||
typedef FT_Size T2_Size; |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* <Type> */ |
||||
/* T2_GlyphSlot */ |
||||
/* */ |
||||
/* <Description> */ |
||||
/* A handle to an OpenType glyph slot object. */ |
||||
/* */ |
||||
typedef struct T2_GlyphSlotRec_ |
||||
{ |
||||
FT_GlyphSlotRec root; |
||||
|
||||
FT_Bool hint; |
||||
FT_Bool scaled; |
||||
|
||||
FT_Fixed x_scale; |
||||
FT_Fixed y_scale; |
||||
|
||||
} T2_GlyphSlotRec, *T2_GlyphSlot; |
||||
|
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* Subglyph transformation record. */ |
||||
/* */ |
||||
typedef struct T2_Transform_ |
||||
{ |
||||
FT_Fixed xx, xy; /* transformation matrix coefficients */ |
||||
FT_Fixed yx, yy; |
||||
FT_F26Dot6 ox, oy; /* offsets */ |
||||
|
||||
} T2_Transform; |
||||
|
||||
|
||||
/* this is only used in the case of a pure CFF font with no charmap */ |
||||
typedef struct T2_CharMapRec_ |
||||
{ |
||||
TT_CharMapRec root; |
||||
PS_Unicodes unicodes; |
||||
|
||||
} T2_CharMapRec, *T2_CharMap; |
||||
|
||||
|
||||
/***********************************************************************/ |
||||
/* */ |
||||
/* TrueType driver class. */ |
||||
/* */ |
||||
typedef struct T2_DriverRec_ |
||||
{ |
||||
FT_DriverRec root; |
||||
void* extension_component; |
||||
|
||||
} T2_DriverRec; |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* Face functions */ |
||||
/* */ |
||||
FT_LOCAL FT_Error |
||||
T2_Init_Face( FT_Stream stream, |
||||
T2_Face face, |
||||
FT_Int face_index, |
||||
FT_Int num_params, |
||||
FT_Parameter* params ); |
||||
|
||||
FT_LOCAL void |
||||
T2_Done_Face( T2_Face face ); |
||||
|
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* Driver functions */ |
||||
/* */ |
||||
FT_LOCAL FT_Error |
||||
T2_Init_Driver( T2_Driver driver ); |
||||
|
||||
FT_LOCAL void |
||||
T2_Done_Driver( T2_Driver driver ); |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* T2OBJS_H */ |
||||
|
||||
|
||||
/* END */ |
@ -0,0 +1,645 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* cffparse.c */ |
||||
/* */ |
||||
/* CFF token stream parser (body) */ |
||||
/* */ |
||||
/* Copyright 1996-2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_SOURCE_FILE(cff,cffparse.h) |
||||
#include FT_INTERNAL_CFF_ERRORS_H |
||||
#include FT_INTERNAL_STREAM_H |
||||
|
||||
/*************************************************************************/ |
||||
/* */ |
||||
/* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
||||
/* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
||||
/* messages during execution. */ |
||||
/* */ |
||||
#undef FT_COMPONENT |
||||
#define FT_COMPONENT trace_t2parse |
||||
|
||||
|
||||
#define T2_Err_Stack_Underflow FT_Err_Invalid_Argument |
||||
#define T2_Err_Syntax_Error FT_Err_Invalid_Argument |
||||
|
||||
|
||||
enum |
||||
{ |
||||
cff_kind_none = 0, |
||||
cff_kind_num, |
||||
cff_kind_fixed, |
||||
cff_kind_string, |
||||
cff_kind_bool, |
||||
cff_kind_delta, |
||||
cff_kind_callback, |
||||
|
||||
cff_kind_max /* do not remove */ |
||||
}; |
||||
|
||||
|
||||
/* now generate handlers for the most simple fields */ |
||||
typedef FT_Error (*CFF_Field_Reader)( CFF_Parser* parser ); |
||||
|
||||
typedef struct CFF_Field_Handler_ |
||||
{ |
||||
int kind; |
||||
int code; |
||||
FT_UInt offset; |
||||
FT_Byte size; |
||||
CFF_Field_Reader reader; |
||||
FT_UInt array_max; |
||||
FT_UInt count_offset; |
||||
|
||||
} CFF_Field_Handler; |
||||
|
||||
|
||||
FT_LOCAL_DEF void |
||||
CFF_Parser_Init( CFF_Parser* parser, |
||||
FT_UInt code, |
||||
void* object ) |
||||
{ |
||||
MEM_Set( parser, 0, sizeof ( *parser ) ); |
||||
|
||||
parser->top = parser->stack; |
||||
parser->object_code = code; |
||||
parser->object = object; |
||||
} |
||||
|
||||
|
||||
/* reads an integer */ |
||||
static FT_Long |
||||
cff_parse_integer( FT_Byte* start, |
||||
FT_Byte* limit ) |
||||
{ |
||||
FT_Byte* p = start; |
||||
FT_Int v = *p++; |
||||
FT_Long val = 0; |
||||
|
||||
|
||||
if ( v == 28 ) |
||||
{ |
||||
if ( p + 2 > limit ) |
||||
goto Bad; |
||||
|
||||
val = (FT_Short)( ( (FT_Int)p[0] << 8 ) | p[1] ); |
||||
p += 2; |
||||
} |
||||
else if ( v == 29 ) |
||||
{ |
||||
if ( p + 4 > limit ) |
||||
goto Bad; |
||||
|
||||
val = ( (FT_Long)p[0] << 24 ) | |
||||
( (FT_Long)p[1] << 16 ) | |
||||
( (FT_Long)p[2] << 8 ) | |
||||
p[3]; |
||||
p += 4; |
||||
} |
||||
else if ( v < 247 ) |
||||
{ |
||||
val = v - 139; |
||||
} |
||||
else if ( v < 251 ) |
||||
{ |
||||
if ( p + 1 > limit ) |
||||
goto Bad; |
||||
|
||||
val = ( v - 247 ) * 256 + p[0] + 108; |
||||
p++; |
||||
} |
||||
else |
||||
{ |
||||
if ( p + 1 > limit ) |
||||
goto Bad; |
||||
|
||||
val = -( v - 251 ) * 256 - p[0] - 108; |
||||
p++; |
||||
} |
||||
|
||||
Exit: |
||||
return val; |
||||
|
||||
Bad: |
||||
val = 0; |
||||
goto Exit; |
||||
} |
||||
|
||||
|
||||
/* read a real */ |
||||
static FT_Fixed |
||||
cff_parse_real( FT_Byte* start, |
||||
FT_Byte* limit, |
||||
FT_Int power_ten ) |
||||
{ |
||||
FT_Byte* p = start; |
||||
FT_Long num, divider, result, exp; |
||||
FT_Int sign = 0, exp_sign = 0; |
||||
FT_Byte nib; |
||||
FT_Byte phase; |
||||
|
||||
|
||||
result = 0; |
||||
num = 0; |
||||
divider = 1; |
||||
|
||||
/* first of all, read the integer part */ |
||||
phase = 4; |
||||
|
||||
for (;;) |
||||
{ |
||||
|
||||
/* If we entered this iteration with phase == 4, we need to */ |
||||
/* read a new byte. This also skips past the intial 0x1E. */ |
||||
if ( phase ) |
||||
{ |
||||
p++; |
||||
|
||||
/* Make sure we don't read past the end. */ |
||||
if ( p >= limit ) |
||||
goto Bad; |
||||
} |
||||
|
||||
/* Get the nibble. */ |
||||
nib = ( p[0] >> phase ) & 0xF; |
||||
phase = 4 - phase; |
||||
|
||||
if ( nib == 0xE ) |
||||
sign = 1; |
||||
else if ( nib > 9 ) |
||||
break; |
||||
else |
||||
result = result * 10 + nib; |
||||
} |
||||
|
||||
/* read decimal part, if any */ |
||||
if ( nib == 0xa ) |
||||
for (;;) |
||||
{ |
||||
|
||||
/* If we entered this iteration with phase == 4, we need */ |
||||
/* to read a new byte. */ |
||||
if ( phase ) |
||||
{ |
||||
p++; |
||||
|
||||
/* Make sure we don't read past the end. */ |
||||
if ( p >= limit ) |
||||
goto Bad; |
||||
} |
||||
|
||||
/* Get the nibble. */ |
||||
nib = ( p[0] >> phase ) & 0xF; |
||||
phase = 4 - phase; |
||||
if ( nib >= 10 ) |
||||
break; |
||||
|
||||
if (divider < 10000000L) |
||||
{ |
||||
num = num * 10 + nib; |
||||
divider *= 10; |
||||
} |
||||
} |
||||
|
||||
/* read exponent, if any */ |
||||
if ( nib == 12 ) |
||||
{ |
||||
exp_sign = 1; |
||||
nib = 11; |
||||
} |
||||
|
||||
if ( nib == 11 ) |
||||
{ |
||||
exp = 0; |
||||
|
||||
for (;;) |
||||
{ |
||||
/* If we entered this iteration with phase == 4, we need */ |
||||
/* to read a new byte. */ |
||||
if ( phase ) |
||||
{ |
||||
p++; |
||||
|
||||
/* Make sure we don't read past the end. */ |
||||
if ( p >= limit ) |
||||
goto Bad; |
||||
} |
||||
|
||||
/* Get the nibble. */ |
||||
nib = ( p[0] >> phase ) & 0xF; |
||||
phase = 4 - phase; |
||||
if ( nib >= 10 ) |
||||
break; |
||||
|
||||
exp = exp * 10 + nib; |
||||
} |
||||
|
||||
if ( exp_sign ) |
||||
exp = -exp; |
||||
|
||||
power_ten += exp; |
||||
} |
||||
|
||||
/* raise to power of ten if needed */ |
||||
while ( power_ten > 0 ) |
||||
{ |
||||
result = result * 10; |
||||
num = num * 10; |
||||
|
||||
power_ten--; |
||||
} |
||||
|
||||
while ( power_ten < 0 ) |
||||
{ |
||||
result = result / 10; |
||||
divider = divider * 10; |
||||
|
||||
power_ten++; |
||||
} |
||||
|
||||
if ( num ) |
||||
result += FT_DivFix( num, divider ); |
||||
|
||||
if ( sign ) |
||||
result = -result; |
||||
|
||||
Exit: |
||||
return result; |
||||
|
||||
Bad: |
||||
result = 0; |
||||
goto Exit; |
||||
} |
||||
|
||||
|
||||
/* read a number, either integer or real */ |
||||
static FT_Long |
||||
cff_parse_num( FT_Byte** d ) |
||||
{ |
||||
return ( **d == 30 ? ( cff_parse_real ( d[0], d[1], 0 ) >> 16 ) |
||||
: cff_parse_integer( d[0], d[1] ) ); |
||||
} |
||||
|
||||
|
||||
/* reads a floating point number, either integer or real */ |
||||
static FT_Fixed |
||||
cff_parse_fixed( FT_Byte** d ) |
||||
{ |
||||
return ( **d == 30 ? cff_parse_real ( d[0], d[1], 0 ) |
||||
: cff_parse_integer( d[0], d[1] ) << 16 ); |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
cff_parse_font_matrix( CFF_Parser* parser ) |
||||
{ |
||||
CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; |
||||
FT_Matrix* matrix = &dict->font_matrix; |
||||
FT_Vector* offset = &dict->font_offset; |
||||
FT_Byte** data = parser->stack; |
||||
FT_Error error; |
||||
|
||||
|
||||
error = T2_Err_Stack_Underflow; |
||||
|
||||
if ( parser->top >= parser->stack + 6 ) |
||||
{ |
||||
matrix->xx = cff_parse_fixed( data++ ); |
||||
matrix->yx = cff_parse_fixed( data++ ); |
||||
matrix->xy = cff_parse_fixed( data++ ); |
||||
matrix->yy = cff_parse_fixed( data++ ); |
||||
offset->x = cff_parse_fixed( data++ ); |
||||
offset->y = cff_parse_fixed( data ); |
||||
error = T2_Err_Ok; |
||||
} |
||||
|
||||
return error; |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
cff_parse_font_bbox( CFF_Parser* parser ) |
||||
{ |
||||
CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; |
||||
FT_BBox* bbox = &dict->font_bbox; |
||||
FT_Byte** data = parser->stack; |
||||
FT_Error error; |
||||
|
||||
|
||||
error = T2_Err_Stack_Underflow; |
||||
|
||||
if ( parser->top >= parser->stack + 4 ) |
||||
{ |
||||
bbox->xMin = cff_parse_num( data++ ); |
||||
bbox->yMin = cff_parse_num( data++ ); |
||||
bbox->xMax = cff_parse_num( data++ ); |
||||
bbox->yMax = cff_parse_num( data ); |
||||
error = T2_Err_Ok; |
||||
} |
||||
|
||||
return error; |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
cff_parse_private_dict( CFF_Parser* parser ) |
||||
{ |
||||
CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; |
||||
FT_Byte** data = parser->stack; |
||||
FT_Error error; |
||||
|
||||
|
||||
error = T2_Err_Stack_Underflow; |
||||
|
||||
if ( parser->top >= parser->stack + 2 ) |
||||
{ |
||||
dict->private_size = cff_parse_num( data++ ); |
||||
dict->private_offset = cff_parse_num( data ); |
||||
error = T2_Err_Ok; |
||||
} |
||||
|
||||
return error; |
||||
} |
||||
|
||||
|
||||
static FT_Error |
||||
cff_parse_cid_ros( CFF_Parser* parser ) |
||||
{ |
||||
CFF_Font_Dict* dict = (CFF_Font_Dict*)parser->object; |
||||
FT_Byte** data = parser->stack; |
||||
FT_Error error; |
||||
|
||||
|
||||
error = T2_Err_Stack_Underflow; |
||||
|
||||
if ( parser->top >= parser->stack + 3 ) |
||||
{ |
||||
dict->cid_registry = (FT_UInt)cff_parse_num ( data++ ); |
||||
dict->cid_ordering = (FT_UInt)cff_parse_num ( data++ ); |
||||
dict->cid_supplement = (FT_ULong)cff_parse_num( data ); |
||||
error = T2_Err_Ok; |
||||
} |
||||
|
||||
return error; |
||||
} |
||||
|
||||
|
||||
#define CFF_FIELD_NUM( code, name ) \ |
||||
CFF_FIELD( code, name, cff_kind_num ) |
||||
#define CFF_FIELD_FIXED( code, name ) \ |
||||
CFF_FIELD( code, name, cff_kind_fixed ) |
||||
#define CFF_FIELD_STRING( code, name ) \ |
||||
CFF_FIELD( code, name, cff_kind_string ) |
||||
#define CFF_FIELD_BOOL( code, name ) \ |
||||
CFF_FIELD( code, name, cff_kind_bool ) |
||||
#define CFF_FIELD_DELTA( code, name, max ) \ |
||||
CFF_FIELD( code, name, cff_kind_delta ) |
||||
|
||||
#define CFF_FIELD_CALLBACK( code, name ) \ |
||||
{ \
|
||||
cff_kind_callback, \
|
||||
code | CFFCODE, \
|
||||
0, 0, \
|
||||
cff_parse_ ## name, \
|
||||
0, 0 \
|
||||
}, |
||||
|
||||
#undef CFF_FIELD |
||||
#define CFF_FIELD( code, name, kind ) \ |
||||
{ \
|
||||
kind, \
|
||||
code | CFFCODE, \
|
||||
FT_FIELD_OFFSET( name ), \
|
||||
FT_FIELD_SIZE( name ), \
|
||||
0, 0, 0 \
|
||||
}, |
||||
|
||||
#undef CFF_FIELD_DELTA |
||||
#define CFF_FIELD_DELTA( code, name, max ) \ |
||||
{ \
|
||||
cff_kind_delta, \
|
||||
code | CFFCODE, \
|
||||
FT_FIELD_OFFSET( name ), \
|
||||
FT_FIELD_SIZE_DELTA( name ), \
|
||||
0, \
|
||||
max, \
|
||||
FT_FIELD_OFFSET( num_ ## name ) \
|
||||
}, |
||||
|
||||
#define CFFCODE_TOPDICT 0x1000 |
||||
#define CFFCODE_PRIVATE 0x2000 |
||||
|
||||
static const CFF_Field_Handler cff_field_handlers[] = |
||||
{ |
||||
|
||||
#include FT_SOURCE_FILE(cff,cfftoken.h) |
||||
|
||||
{ 0, 0, 0, 0, 0, 0, 0 } |
||||
}; |
||||
|
||||
|
||||
FT_LOCAL_DEF FT_Error |
||||
CFF_Parser_Run( CFF_Parser* parser, |
||||
FT_Byte* start, |
||||
FT_Byte* limit ) |
||||
{ |
||||
FT_Byte* p = start; |
||||
FT_Error error = T2_Err_Ok; |
||||
|
||||
|
||||
parser->top = parser->stack; |
||||
parser->start = start; |
||||
parser->limit = limit; |
||||
parser->cursor = start; |
||||
|
||||
while ( p < limit ) |
||||
{ |
||||
FT_Byte v = *p; |
||||
|
||||
|
||||
if ( v >= 27 && v != 31 ) |
||||
{ |
||||
/* it's a number; we will push its position on the stack */ |
||||
if ( parser->top - parser->stack >= CFF_MAX_STACK_DEPTH ) |
||||
goto Stack_Overflow; |
||||
|
||||
*parser->top ++ = p; |
||||
|
||||
/* now, skip it */ |
||||
if ( v == 30 ) |
||||
{ |
||||
/* skip real number */ |
||||
p++; |
||||
for (;;) |
||||
{ |
||||
if ( p >= limit ) |
||||
goto Syntax_Error; |
||||
v = p[0] >> 4; |
||||
if ( v == 15 ) |
||||
break; |
||||
v = p[0] & 0xF; |
||||
if ( v == 15 ) |
||||
break; |
||||
p++; |
||||
} |
||||
} |
||||
else if ( v == 28 ) |
||||
p += 2; |
||||
else if ( v == 29 ) |
||||
p += 4; |
||||
else if ( v > 246 ) |
||||
p += 1; |
||||
} |
||||
else |
||||
{ |
||||
/* This is not a number, hence it's an operator. Compute its code */ |
||||
/* and look for it in our current list. */ |
||||
|
||||
FT_UInt code; |
||||
FT_UInt num_args = (FT_UInt) |
||||
( parser->top - parser->stack ); |
||||
const CFF_Field_Handler* field; |
||||
|
||||
|
||||
/* first of all, a trivial check */ |
||||
if ( num_args < 1 ) |
||||
goto Stack_Underflow; |
||||
|
||||
*parser->top = p; |
||||
code = v; |
||||
if ( v == 12 ) |
||||
{ |
||||
/* two byte operator */ |
||||
p++; |
||||
code = 0x100 | p[0]; |
||||
} |
||||
code = code | parser->object_code; |
||||
|
||||
for ( field = cff_field_handlers; field->kind; field++ ) |
||||
{ |
||||
if ( field->code == (FT_Int)code ) |
||||
{ |
||||
/* we found our field's handler; read it */ |
||||
FT_Long val; |
||||
FT_Byte* q = (FT_Byte*)parser->object + field->offset; |
||||
|
||||
switch ( field->kind ) |
||||
{ |
||||
case cff_kind_bool: |
||||
case cff_kind_string: |
||||
case cff_kind_num: |
||||
val = cff_parse_num( parser->stack ); |
||||
goto Store_Number; |
||||
|
||||
case cff_kind_fixed: |
||||
val = cff_parse_fixed( parser->stack ); |
||||
|
||||
Store_Number: |
||||
switch ( field->size ) |
||||
{ |
||||
case 1: |
||||
*(FT_Byte*)q = (FT_Byte)val; |
||||
break; |
||||
|
||||
case 2: |
||||
*(FT_Short*)q = (FT_Short)val; |
||||
break; |
||||
|
||||
case 4: |
||||
*(FT_Int32*)q = (FT_Int)val; |
||||
break; |
||||
|
||||
default: /* for 64-bit systems where long is 8 bytes */ |
||||
*(FT_Long*)q = val; |
||||
} |
||||
break; |
||||
|
||||
case cff_kind_delta: |
||||
{ |
||||
FT_Byte* qcount = (FT_Byte*)parser->object + |
||||
field->count_offset; |
||||
|
||||
FT_Byte** data = parser->stack; |
||||
|
||||
|
||||
if ( num_args > field->array_max ) |
||||
num_args = field->array_max; |
||||
|
||||
/* store count */ |
||||
*qcount = (FT_Byte)num_args; |
||||
|
||||
val = 0; |
||||
while ( num_args > 0 ) |
||||
{ |
||||
val += cff_parse_num( data++ ); |
||||
switch ( field->size ) |
||||
{ |
||||
case 1: |
||||
*(FT_Byte*)q = (FT_Byte)val; |
||||
break; |
||||
|
||||
case 2: |
||||
*(FT_Short*)q = (FT_Short)val; |
||||
break; |
||||
|
||||
case 4: |
||||
*(FT_Int32*)q = (FT_Int)val; |
||||
break; |
||||
|
||||
default: /* for 64-bit systems */ |
||||
*(FT_Long*)q = val; |
||||
} |
||||
|
||||
q += field->size; |
||||
num_args--; |
||||
} |
||||
} |
||||
break; |
||||
|
||||
default: /* callback */ |
||||
error = field->reader( parser ); |
||||
if ( error ) |
||||
goto Exit; |
||||
} |
||||
goto Found; |
||||
} |
||||
} |
||||
|
||||
/* this is an unknown operator, or it is unsupported; */ |
||||
/* we will ignore it for now. */ |
||||
|
||||
Found: |
||||
/* clear stack */ |
||||
parser->top = parser->stack; |
||||
} |
||||
p++; |
||||
} |
||||
|
||||
Exit: |
||||
return error; |
||||
|
||||
Stack_Overflow: |
||||
error = T2_Err_Invalid_Argument; |
||||
goto Exit; |
||||
|
||||
Stack_Underflow: |
||||
error = T2_Err_Invalid_Argument; |
||||
goto Exit; |
||||
|
||||
Syntax_Error: |
||||
error = T2_Err_Invalid_Argument; |
||||
goto Exit; |
||||
} |
||||
|
||||
|
||||
/* END */ |
@ -0,0 +1,67 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* cffparse.h */ |
||||
/* */ |
||||
/* CFF token stream parser (specification) */ |
||||
/* */ |
||||
/* Copyright 1996-2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
#ifndef __CFF_PARSE_H__ |
||||
#define __CFF_PARSE_H__ |
||||
|
||||
#include <ft2build.h> |
||||
#include FT_INTERNAL_CFF_TYPES_H |
||||
#include FT_INTERNAL_OBJECTS_H |
||||
|
||||
FT_BEGIN_HEADER |
||||
|
||||
#define CFF_MAX_STACK_DEPTH 96 |
||||
|
||||
#define CFF_CODE_TOPDICT 0x1000 |
||||
#define CFF_CODE_PRIVATE 0x2000 |
||||
|
||||
|
||||
|
||||
|
||||
typedef struct CFF_Parser_ |
||||
{ |
||||
FT_Byte* start; |
||||
FT_Byte* limit; |
||||
FT_Byte* cursor; |
||||
|
||||
FT_Byte* stack[CFF_MAX_STACK_DEPTH + 1]; |
||||
FT_Byte** top; |
||||
|
||||
FT_UInt object_code; |
||||
void* object; |
||||
|
||||
} CFF_Parser; |
||||
|
||||
|
||||
FT_LOCAL void |
||||
CFF_Parser_Init( CFF_Parser* parser, |
||||
FT_UInt code, |
||||
void* object ); |
||||
|
||||
FT_LOCAL FT_Error |
||||
CFF_Parser_Run( CFF_Parser* parser, |
||||
FT_Byte* start, |
||||
FT_Byte* limit ); |
||||
|
||||
|
||||
FT_END_HEADER |
||||
|
||||
#endif /* __CFF_PARSE_H__ */ |
||||
|
||||
|
||||
/* END */ |
@ -0,0 +1,97 @@ |
||||
/***************************************************************************/ |
||||
/* */ |
||||
/* cfftoken.h */ |
||||
/* */ |
||||
/* CFF token definitions */ |
||||
/* */ |
||||
/* Copyright 1996-2000 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. */ |
||||
/* */ |
||||
/***************************************************************************/ |
||||
|
||||
|
||||
#undef FT_STRUCTURE |
||||
#define FT_STRUCTURE CFF_Font_Dict |
||||
|
||||
#undef CFFCODE |
||||
#define CFFCODE CFFCODE_TOPDICT |
||||
|
||||
CFF_FIELD_STRING ( 0, version ) |
||||
CFF_FIELD_STRING ( 1, notice ) |
||||
CFF_FIELD_STRING ( 0x100, copyright ) |
||||
CFF_FIELD_STRING ( 2, full_name ) |
||||
CFF_FIELD_STRING ( 3, family_name ) |
||||
CFF_FIELD_STRING ( 4, weight ) |
||||
CFF_FIELD_BOOL ( 0x101, is_fixed_pitch ) |
||||
CFF_FIELD_FIXED ( 0x102, italic_angle ) |
||||
CFF_FIELD_NUM ( 0x103, underline_position ) |
||||
CFF_FIELD_NUM ( 0x104, underline_thickness ) |
||||
CFF_FIELD_NUM ( 0x105, paint_type ) |
||||
CFF_FIELD_NUM ( 0x106, charstring_type ) |
||||
CFF_FIELD_CALLBACK( 0x107, font_matrix ) |
||||
CFF_FIELD_NUM ( 13, unique_id ) |
||||
CFF_FIELD_CALLBACK( 5, font_bbox ) |
||||
CFF_FIELD_NUM ( 0x108, stroke_width ) |
||||
CFF_FIELD_NUM ( 15, charset_offset ) |
||||
CFF_FIELD_NUM ( 16, encoding_offset ) |
||||
CFF_FIELD_NUM ( 17, charstrings_offset ) |
||||
CFF_FIELD_CALLBACK( 18, private_dict ) |
||||
CFF_FIELD_NUM ( 0x114, synthetic_base ) |
||||
CFF_FIELD_STRING ( 0x115, postscript ) |
||||
CFF_FIELD_STRING ( 0x116, base_font_name ) |
||||
|
||||
#if 0 |
||||
CFF_FIELD_DELTA ( 0x117, base_font_blend, 16 ) |
||||
CFF_FIELD_CALLBACK( 0x118, multiple_master ) |
||||
CFF_FIELD_CALLBACK( 0x119, blend_axit_types ) |
||||
#endif |
||||
|
||||
CFF_FIELD_CALLBACK( 0x11E, cid_ros ) |
||||
CFF_FIELD_NUM ( 0x11F, cid_font_version ) |
||||
CFF_FIELD_NUM ( 0x120, cid_font_revision ) |
||||
CFF_FIELD_NUM ( 0x121, cid_font_type ) |
||||
CFF_FIELD_NUM ( 0x122, cid_count ) |
||||
CFF_FIELD_NUM ( 0x123, cid_uid_base ) |
||||
CFF_FIELD_NUM ( 0x124, cid_fd_array_offset ) |
||||
CFF_FIELD_NUM ( 0x125, cid_fd_select_offset ) |
||||
CFF_FIELD_STRING ( 0x126, cid_font_name ) |
||||
|
||||
#if 0 |
||||
CFF_FIELD_NUM ( 0x127, chameleon ) |
||||
#endif |
||||
|
||||
|
||||
#undef FT_STRUCTURE |
||||
#define FT_STRUCTURE CFF_Private |
||||
#undef CFFCODE |
||||
#define CFFCODE CFFCODE_PRIVATE |
||||
|
||||
CFF_FIELD_DELTA( 6, blue_values, 14 ) |
||||
CFF_FIELD_DELTA( 7, other_blues, 10 ) |
||||
CFF_FIELD_DELTA( 8, family_blues, 14 ) |
||||
CFF_FIELD_DELTA( 9, family_other_blues, 10 ) |
||||
CFF_FIELD_FIXED( 0x109, blue_scale ) |
||||
CFF_FIELD_NUM ( 0x10A, blue_shift ) |
||||
CFF_FIELD_NUM ( 0x10B, blue_fuzz ) |
||||
CFF_FIELD_NUM ( 10, standard_width ) |
||||
CFF_FIELD_NUM ( 11, standard_height ) |
||||
CFF_FIELD_DELTA( 0x10C, snap_widths, 13 ) |
||||
CFF_FIELD_DELTA( 0x10D, snap_heights, 13 ) |
||||
CFF_FIELD_BOOL ( 0x10E, force_bold ) |
||||
CFF_FIELD_FIXED( 0x10F, force_bold_threshold ) |
||||
CFF_FIELD_NUM ( 0x110, lenIV ) |
||||
CFF_FIELD_NUM ( 0x111, language_group ) |
||||
CFF_FIELD_FIXED( 0x112, expansion_factor ) |
||||
CFF_FIELD_NUM ( 0x113, initial_random_seed ) |
||||
CFF_FIELD_NUM ( 19, local_subrs_offset ) |
||||
CFF_FIELD_NUM ( 20, default_width ) |
||||
CFF_FIELD_NUM ( 21, nominal_width ) |
||||
|
||||
|
||||
/* END */ |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue