|
|
|
@ -113,14 +113,21 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
fnt_font_done( FNT_Font font, |
|
|
|
|
FT_Stream stream ) |
|
|
|
|
fnt_font_done( FNT_Face face ) |
|
|
|
|
{ |
|
|
|
|
FT_Memory memory = FT_FACE( face )->memory; |
|
|
|
|
FT_Stream stream = FT_FACE( face )->stream; |
|
|
|
|
FNT_Font font = face->font; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( !font ) |
|
|
|
|
return; |
|
|
|
|
|
|
|
|
|
if ( font->fnt_frame ) |
|
|
|
|
FT_FRAME_RELEASE( font->fnt_frame ); |
|
|
|
|
|
|
|
|
|
font->fnt_size = 0; |
|
|
|
|
font->fnt_frame = 0; |
|
|
|
|
FT_FREE( font ); |
|
|
|
|
face->font = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -164,11 +171,7 @@ |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* small fixup -- some fonts have the `pixel_width' field set to 0 */ |
|
|
|
|
if ( header->pixel_width == 0 ) |
|
|
|
|
header->pixel_width = header->pixel_height; |
|
|
|
|
|
|
|
|
|
/* this is a FNT file/table, we now extract its frame */ |
|
|
|
|
/* this is a FNT file/table; extract its frame */ |
|
|
|
|
if ( FT_STREAM_SEEK( font->offset ) || |
|
|
|
|
FT_FRAME_EXTRACT( header->file_size, font->fnt_frame ) ) |
|
|
|
|
goto Exit; |
|
|
|
@ -178,25 +181,9 @@ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void |
|
|
|
|
fnt_face_done_fonts( FNT_Face face ) |
|
|
|
|
{ |
|
|
|
|
FT_Memory memory = FT_FACE( face )->memory; |
|
|
|
|
FT_Stream stream = FT_FACE( face )->stream; |
|
|
|
|
FNT_Font cur = face->fonts; |
|
|
|
|
FNT_Font limit = cur + face->num_fonts; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for ( ; cur < limit; cur++ ) |
|
|
|
|
fnt_font_done( cur, stream ); |
|
|
|
|
|
|
|
|
|
FT_FREE( face->fonts ); |
|
|
|
|
face->num_fonts = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static FT_Error |
|
|
|
|
fnt_face_get_dll_fonts( FNT_Face face ) |
|
|
|
|
fnt_face_get_dll_font( FNT_Face face, |
|
|
|
|
FT_Int face_index ) |
|
|
|
|
{ |
|
|
|
|
FT_Error error; |
|
|
|
|
FT_Stream stream = FT_FACE( face )->stream; |
|
|
|
@ -204,10 +191,9 @@ |
|
|
|
|
WinMZ_HeaderRec mz_header; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
face->fonts = 0; |
|
|
|
|
face->num_fonts = 0; |
|
|
|
|
face->font = 0; |
|
|
|
|
|
|
|
|
|
/* does it begin with a MZ header? */ |
|
|
|
|
/* does it begin with an MZ header? */ |
|
|
|
|
if ( FT_STREAM_SEEK( 0 ) || |
|
|
|
|
FT_STREAM_READ_FIELDS( winmz_header_fields, &mz_header ) ) |
|
|
|
|
goto Exit; |
|
|
|
@ -215,7 +201,7 @@ |
|
|
|
|
error = FNT_Err_Unknown_File_Format; |
|
|
|
|
if ( mz_header.magic == WINFNT_MZ_MAGIC ) |
|
|
|
|
{ |
|
|
|
|
/* yes, now look for a NE header in the file */ |
|
|
|
|
/* yes, now look for an NE header in the file */ |
|
|
|
|
WinNE_HeaderRec ne_header; |
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -226,16 +212,15 @@ |
|
|
|
|
error = FNT_Err_Unknown_File_Format; |
|
|
|
|
if ( ne_header.magic == WINFNT_NE_MAGIC ) |
|
|
|
|
{ |
|
|
|
|
/* good, now look in the resource table for each FNT resource */ |
|
|
|
|
FT_ULong res_offset = mz_header.lfanew + |
|
|
|
|
ne_header.resource_tab_offset; |
|
|
|
|
|
|
|
|
|
/* good, now look into the resource table for each FNT resource */ |
|
|
|
|
FT_ULong res_offset = mz_header.lfanew + |
|
|
|
|
ne_header.resource_tab_offset; |
|
|
|
|
FT_UShort size_shift; |
|
|
|
|
FT_UShort font_count = 0; |
|
|
|
|
FT_ULong font_offset = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( FT_STREAM_SEEK( res_offset ) || |
|
|
|
|
if ( FT_STREAM_SEEK( res_offset ) || |
|
|
|
|
FT_FRAME_ENTER( ne_header.rname_tab_offset - |
|
|
|
|
ne_header.resource_tab_offset ) ) |
|
|
|
|
goto Exit; |
|
|
|
@ -253,7 +238,7 @@ |
|
|
|
|
|
|
|
|
|
count = FT_GET_USHORT_LE(); |
|
|
|
|
|
|
|
|
|
if ( type_id == 0x8008 ) |
|
|
|
|
if ( type_id == 0x8008U ) |
|
|
|
|
{ |
|
|
|
|
font_count = count; |
|
|
|
|
font_offset = (FT_ULong)( FT_STREAM_POS() + 4 + |
|
|
|
@ -263,6 +248,7 @@ |
|
|
|
|
|
|
|
|
|
stream->cursor += 4 + count * 12; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
FT_FRAME_EXIT(); |
|
|
|
|
|
|
|
|
|
if ( !font_count || !font_offset ) |
|
|
|
@ -272,50 +258,36 @@ |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ( FT_STREAM_SEEK( font_offset ) || |
|
|
|
|
FT_NEW_ARRAY( face->fonts, font_count ) ) |
|
|
|
|
goto Exit; |
|
|
|
|
face->root.num_faces = font_count; |
|
|
|
|
|
|
|
|
|
face->num_fonts = font_count; |
|
|
|
|
|
|
|
|
|
if ( FT_FRAME_ENTER( (FT_Long)font_count * 12 ) ) |
|
|
|
|
if ( face_index >= font_count ) |
|
|
|
|
{ |
|
|
|
|
error = FNT_Err_Bad_Argument; |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* now read the offset and position of each FNT font */ |
|
|
|
|
{ |
|
|
|
|
FNT_Font cur = face->fonts; |
|
|
|
|
FNT_Font limit = cur + font_count; |
|
|
|
|
if ( FT_NEW( face->font ) ) |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
if ( FT_STREAM_SEEK( font_offset + face_index * 12 ) || |
|
|
|
|
FT_FRAME_ENTER( 12 ) ) |
|
|
|
|
goto Fail; |
|
|
|
|
|
|
|
|
|
for ( ; cur < limit; cur++ ) |
|
|
|
|
{ |
|
|
|
|
cur->offset = (FT_ULong)FT_GET_USHORT_LE() << size_shift; |
|
|
|
|
cur->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift; |
|
|
|
|
cur->size_shift = size_shift; |
|
|
|
|
stream->cursor += 8; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
FT_FRAME_EXIT(); |
|
|
|
|
face->font->offset = (FT_ULong)FT_GET_USHORT_LE() << size_shift; |
|
|
|
|
face->font->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift; |
|
|
|
|
face->font->size_shift = size_shift; |
|
|
|
|
|
|
|
|
|
/* finally, try to load each font there */ |
|
|
|
|
{ |
|
|
|
|
FNT_Font cur = face->fonts; |
|
|
|
|
FNT_Font limit = cur + font_count; |
|
|
|
|
stream->cursor += 8; |
|
|
|
|
|
|
|
|
|
FT_FRAME_EXIT(); |
|
|
|
|
|
|
|
|
|
for ( ; cur < limit; cur++ ) |
|
|
|
|
{ |
|
|
|
|
error = fnt_font_load( cur, stream ); |
|
|
|
|
if ( error ) |
|
|
|
|
goto Fail; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
error = fnt_font_load( face->font, stream ); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Fail: |
|
|
|
|
if ( error ) |
|
|
|
|
fnt_face_done_fonts( face ); |
|
|
|
|
fnt_font_done( face ); |
|
|
|
|
|
|
|
|
|
Exit: |
|
|
|
|
return error; |
|
|
|
@ -335,7 +307,7 @@ |
|
|
|
|
fnt_cmap_init( FNT_CMap cmap ) |
|
|
|
|
{ |
|
|
|
|
FNT_Face face = (FNT_Face)FT_CMAP_FACE( cmap ); |
|
|
|
|
FNT_Font font = face->fonts; |
|
|
|
|
FNT_Font font = face->font; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cmap->first = (FT_UInt32) font->header.first_char; |
|
|
|
@ -354,8 +326,8 @@ |
|
|
|
|
|
|
|
|
|
char_code -= cmap->first; |
|
|
|
|
if ( char_code < cmap->count ) |
|
|
|
|
gindex = char_code + 1; |
|
|
|
|
|
|
|
|
|
gindex = char_code + 1; /* we artificially increase the glyph index; */ |
|
|
|
|
/* FNT_Load_Glyph reverts to the right one */ |
|
|
|
|
return gindex; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -408,7 +380,7 @@ |
|
|
|
|
FT_Memory memory = FT_FACE_MEMORY( face ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fnt_face_done_fonts( face ); |
|
|
|
|
fnt_font_done( face ); |
|
|
|
|
|
|
|
|
|
FT_FREE( face->root.available_sizes ); |
|
|
|
|
face->root.num_fixed_sizes = 0; |
|
|
|
@ -427,23 +399,22 @@ |
|
|
|
|
|
|
|
|
|
FT_UNUSED( num_params ); |
|
|
|
|
FT_UNUSED( params ); |
|
|
|
|
FT_UNUSED( face_index ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* try to load several fonts from a DLL */ |
|
|
|
|
error = fnt_face_get_dll_fonts( face ); |
|
|
|
|
/* try to load font from a DLL */ |
|
|
|
|
error = fnt_face_get_dll_font( face, face_index ); |
|
|
|
|
if ( error ) |
|
|
|
|
{ |
|
|
|
|
/* this didn't work, now try to load a single FNT font */ |
|
|
|
|
/* this didn't work; try to load a single FNT font */ |
|
|
|
|
FNT_Font font; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( FT_NEW( face->fonts ) ) |
|
|
|
|
if ( FT_NEW( face->font ) ) |
|
|
|
|
goto Exit; |
|
|
|
|
|
|
|
|
|
face->num_fonts = 1; |
|
|
|
|
font = face->fonts; |
|
|
|
|
face->root.num_faces = 1; |
|
|
|
|
|
|
|
|
|
font = face->font; |
|
|
|
|
font->offset = 0; |
|
|
|
|
font->fnt_size = stream->size; |
|
|
|
|
|
|
|
|
@ -452,43 +423,45 @@ |
|
|
|
|
goto Fail; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* all right, one or more fonts were loaded; we now need to */ |
|
|
|
|
/* fill the root FT_Face fields with relevant information */ |
|
|
|
|
/* we now need to fill the root FT_Face fields */ |
|
|
|
|
/* with relevant information */ |
|
|
|
|
{ |
|
|
|
|
FT_Face root = FT_FACE( face ); |
|
|
|
|
FNT_Font fonts = face->fonts; |
|
|
|
|
FNT_Font limit = fonts + face->num_fonts; |
|
|
|
|
FNT_Font cur; |
|
|
|
|
FT_Face root = FT_FACE( face ); |
|
|
|
|
FNT_Font font = face->font; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
root->num_faces = 1; |
|
|
|
|
root->face_flags = FT_FACE_FLAG_FIXED_SIZES | |
|
|
|
|
FT_FACE_FLAG_HORIZONTAL; |
|
|
|
|
|
|
|
|
|
if ( fonts->header.avg_width == fonts->header.max_width ) |
|
|
|
|
if ( font->header.avg_width == font->header.max_width ) |
|
|
|
|
root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; |
|
|
|
|
|
|
|
|
|
if ( fonts->header.italic ) |
|
|
|
|
if ( font->header.italic ) |
|
|
|
|
root->style_flags |= FT_STYLE_FLAG_ITALIC; |
|
|
|
|
|
|
|
|
|
if ( fonts->header.weight >= 800 ) |
|
|
|
|
if ( font->header.weight >= 800 ) |
|
|
|
|
root->style_flags |= FT_STYLE_FLAG_BOLD; |
|
|
|
|
|
|
|
|
|
/* Setup the `fixed_sizes' array */ |
|
|
|
|
if ( FT_NEW_ARRAY( root->available_sizes, face->num_fonts ) ) |
|
|
|
|
/* set up the `fixed_sizes' array */ |
|
|
|
|
if ( FT_NEW_ARRAY( root->available_sizes, 1 ) ) |
|
|
|
|
goto Fail; |
|
|
|
|
|
|
|
|
|
root->num_fixed_sizes = face->num_fonts; |
|
|
|
|
root->num_fixed_sizes = 1; |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
FT_Bitmap_Size* size = root->available_sizes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for ( cur = fonts; cur < limit; cur++, size++ ) |
|
|
|
|
{ |
|
|
|
|
size->width = cur->header.pixel_width; |
|
|
|
|
size->height = cur->header.pixel_height; |
|
|
|
|
} |
|
|
|
|
FT_Bitmap_Size* bsize = root->available_sizes; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bsize->width = font->header.avg_width; |
|
|
|
|
bsize->height = |
|
|
|
|
font->header.pixel_height + font->header.external_leading; |
|
|
|
|
bsize->size = font->header.nominal_point_size << 6; |
|
|
|
|
bsize->x_ppem =
|
|
|
|
|
(FT_Pos)( ( font->header.horizontal_resolution * bsize->size + 36 ) |
|
|
|
|
/ 72 ); |
|
|
|
|
bsize->y_ppem = |
|
|
|
|
(FT_Pos)( ( font->header.vertical_resolution* bsize->size + 36 ) |
|
|
|
|
/ 72 ); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
@ -513,11 +486,13 @@ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* setup remaining flags */ |
|
|
|
|
root->num_glyphs = fonts->header.last_char - |
|
|
|
|
fonts->header.first_char + 1; |
|
|
|
|
|
|
|
|
|
root->family_name = (FT_String*)fonts->fnt_frame + |
|
|
|
|
fonts->header.face_name_offset; |
|
|
|
|
/* reserve one slot for the .notdef glyph at index 0 */ |
|
|
|
|
root->num_glyphs = font->header.last_char - |
|
|
|
|
font->header.first_char + 1 + 1; |
|
|
|
|
|
|
|
|
|
root->family_name = (FT_String*)font->fnt_frame + |
|
|
|
|
font->header.face_name_offset; |
|
|
|
|
root->style_name = (char *)"Regular"; |
|
|
|
|
|
|
|
|
|
if ( root->style_flags & FT_STYLE_FLAG_BOLD ) |
|
|
|
@ -541,80 +516,58 @@ |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static FT_Error |
|
|
|
|
FNT_Size_Set_Pixels( FNT_Size size ) |
|
|
|
|
FNT_Size_Set_Pixels( FT_Size size ) |
|
|
|
|
{ |
|
|
|
|
/* look up a font corresponding to the current pixel size */ |
|
|
|
|
FNT_Face face = (FNT_Face)FT_SIZE_FACE( size ); |
|
|
|
|
FNT_Font cur = face->fonts; |
|
|
|
|
FNT_Font limit = cur + face->num_fonts; |
|
|
|
|
FNT_Font hit; |
|
|
|
|
|
|
|
|
|
FNT_Face face = (FNT_Face)FT_SIZE_FACE( size ); |
|
|
|
|
FT_Face root = FT_FACE( face ); |
|
|
|
|
|
|
|
|
|
size->font = 0; |
|
|
|
|
hit = 0; |
|
|
|
|
|
|
|
|
|
for ( ; cur < limit; cur++ ) |
|
|
|
|
if ( size->metrics.y_ppem == root->available_sizes->height ) |
|
|
|
|
{ |
|
|
|
|
if ( cur->header.pixel_height == size->root.metrics.y_ppem ) |
|
|
|
|
{ |
|
|
|
|
hit = cur; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
FNT_Font font = face->font; |
|
|
|
|
|
|
|
|
|
/* try to find a better hit */ |
|
|
|
|
for ( ; cur < limit; cur++ ) |
|
|
|
|
{ |
|
|
|
|
if ( cur->header.pixel_height == size->root.metrics.y_ppem && |
|
|
|
|
cur->header.pixel_width == size->root.metrics.x_ppem ) |
|
|
|
|
{ |
|
|
|
|
hit = cur; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ( hit ) { |
|
|
|
|
size->font = hit; |
|
|
|
|
size->root.metrics.ascender = hit->header.ascent * 64; |
|
|
|
|
size->root.metrics.descender = ( hit->header.pixel_height - |
|
|
|
|
hit->header.ascent ) * 64; |
|
|
|
|
size->root.metrics.height = hit->header.pixel_height * 64; |
|
|
|
|
size->root.metrics.max_advance = hit->header.max_width * 64; |
|
|
|
|
} |
|
|
|
|
size->metrics.ascender = font->header.ascent * 64; |
|
|
|
|
size->metrics.descender = ( font->header.pixel_height - |
|
|
|
|
font->header.ascent ) * 64; |
|
|
|
|
size->metrics.height = font->header.pixel_height * 64; |
|
|
|
|
size->metrics.max_advance = font->header.max_width * 64; |
|
|
|
|
|
|
|
|
|
return ( size->font ? FNT_Err_Ok : FNT_Err_Invalid_Pixel_Size ); |
|
|
|
|
return FNT_Err_Ok; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
return FNT_Err_Invalid_Pixel_Size; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static FT_Error |
|
|
|
|
FNT_Load_Glyph( FT_GlyphSlot slot, |
|
|
|
|
FNT_Size size, |
|
|
|
|
FT_Size size, |
|
|
|
|
FT_UInt glyph_index, |
|
|
|
|
FT_Int32 load_flags ) |
|
|
|
|
{ |
|
|
|
|
FNT_Font font = size->font; |
|
|
|
|
FT_Error error = 0; |
|
|
|
|
FNT_Face face = (FNT_Face)FT_SIZE_FACE( size ); |
|
|
|
|
FNT_Font font = face->font; |
|
|
|
|
FT_Error error = FNT_Err_Ok; |
|
|
|
|
FT_Byte* p; |
|
|
|
|
FT_Int len; |
|
|
|
|
FT_Bitmap* bitmap = &slot->bitmap; |
|
|
|
|
FT_ULong offset; |
|
|
|
|
FT_Bool new_format; |
|
|
|
|
|
|
|
|
|
FT_UNUSED( slot ); |
|
|
|
|
FT_UNUSED( load_flags ); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if ( !font ) |
|
|
|
|
if ( !face || !font ) |
|
|
|
|
{ |
|
|
|
|
error = FNT_Err_Invalid_Argument; |
|
|
|
|
goto Exit; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if ( glyph_index > 0 ) |
|
|
|
|
glyph_index--; |
|
|
|
|
glyph_index--; /* revert to real index */ |
|
|
|
|
else |
|
|
|
|
glyph_index = font->header.default_char; |
|
|
|
|
glyph_index -= font->header.first_char; |
|
|
|
|
glyph_index = font->header.default_char; /* the .notdef glyph */ |
|
|
|
|
|
|
|
|
|
new_format = FT_BOOL( font->header.version == 0x300 ); |
|
|
|
|
len = new_format ? 6 : 4; |
|
|
|
@ -699,7 +652,7 @@ |
|
|
|
|
}, |
|
|
|
|
|
|
|
|
|
sizeof( FNT_FaceRec ), |
|
|
|
|
sizeof( FNT_SizeRec ), |
|
|
|
|
sizeof( FT_SizeRec ), |
|
|
|
|
sizeof( FT_GlyphSlotRec ), |
|
|
|
|
|
|
|
|
|
(FT_Face_InitFunc) FNT_Face_Init, |
|
|
|
|