* src/winfonts/winfnt.h: Add necessary structures for PE resource

parsing.
(WinPE32_HeaderRec): New structure.
(WinPE32_SectionRec): New structure.
(WinPE_RsrcDirRec): New structure.
(WinPE_RsrcDirEntryRec): New structure.
(WinPE_RsrcDataEntryRec): New structure.
(FNT_FontRec): Remove unused `size_shift' field.

* src/winfonts/winfnt.c (fnt_face_get_dll_font): Add support for
loading bitmap .fon files in PE format.
This commit is contained in:
Werner Lemberg 2007-06-16 07:59:39 +00:00
parent 08a645d833
commit ab1604bd6b
5 changed files with 337 additions and 6 deletions

View File

@ -1,3 +1,17 @@
2006-06-16 Dmitry Timoshkov <dmitry@codeweavers.com>
* src/winfonts/winfnt.h: Add necessary structures for PE resource
parsing.
(WinPE32_HeaderRec): New structure.
(WinPE32_SectionRec): New structure.
(WinPE_RsrcDirRec): New structure.
(WinPE_RsrcDirEntryRec): New structure.
(WinPE_RsrcDataEntryRec): New structure.
(FNT_FontRec): Remove unused `size_shift' field.
* src/winfonts/winfnt.c (fnt_face_get_dll_font): Add support for
loading bitmap .fon files in PE format.
2006-06-15 Dmitry Timoshkov <dmitry@codeweavers.com>
* builds/win32/ftdebug.c: Unify debug level handling with other

View File

@ -6391,7 +6391,7 @@
* include/freetype/internal/fnttypes.h (WinFNT_HeaderRec): Increase
size of `reserved2' to avoid memory overwrites.
2003-01-08 Huw Dawies <huw@codeweavers.com>
2003-01-08 Huw Davies <huw@codeweavers.com>
* src/winfonts/winfnt.c (winfnt_header_fields): Read 16 bytes into
`reserved2', not `reserved'.

View File

@ -32,6 +32,9 @@ CHANGES BETWEEN 2.3.5 and 2.3.4
out whether a given TrueType font uses patented bytecode
instructions.
- Support for Windows FON files in PE format has been contributed
by Dmitry Timoshkov.
III. MISCELLANEOUS

View File

@ -6,6 +6,8 @@
/* */
/* Copyright 1996-2001, 2002, 2003, 2004, 2006, 2007 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* Copyright 2003 Huw D M Davies for Codeweavers */
/* Copyright 2007 Dmitry Timoshkov for Codeweavers */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
@ -62,6 +64,80 @@
FT_FRAME_END
};
static const FT_Frame_Field winpe32_header_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE WinPE32_HeaderRec
FT_FRAME_START( 248 ),
FT_FRAME_ULONG_LE ( magic ), /* PE00 */
FT_FRAME_USHORT_LE ( machine ), /* 0x014c - i386 */
FT_FRAME_USHORT_LE ( number_of_sections ),
FT_FRAME_SKIP_BYTES( 12 ),
FT_FRAME_USHORT_LE ( size_of_optional_header ),
FT_FRAME_SKIP_BYTES( 2 ),
FT_FRAME_USHORT_LE ( magic32 ), /* 0x10b */
FT_FRAME_SKIP_BYTES( 110 ),
FT_FRAME_ULONG_LE ( rsrc_virtual_address ),
FT_FRAME_ULONG_LE ( rsrc_size ),
FT_FRAME_SKIP_BYTES( 104 ),
FT_FRAME_END
};
static const FT_Frame_Field winpe32_section_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE WinPE32_SectionRec
FT_FRAME_START( 40 ),
FT_FRAME_BYTES ( name, 8 ),
FT_FRAME_SKIP_BYTES( 4 ),
FT_FRAME_ULONG_LE ( virtual_address ),
FT_FRAME_ULONG_LE ( size_of_raw_data ),
FT_FRAME_ULONG_LE ( pointer_to_raw_data ),
FT_FRAME_SKIP_BYTES( 16 ),
FT_FRAME_END
};
static const FT_Frame_Field winpe_rsrc_dir_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE WinPE_RsrcDirRec
FT_FRAME_START( 16 ),
FT_FRAME_ULONG_LE ( characteristics ),
FT_FRAME_ULONG_LE ( time_date_stamp ),
FT_FRAME_USHORT_LE( major_version ),
FT_FRAME_USHORT_LE( minor_version ),
FT_FRAME_USHORT_LE( number_of_named_entries ),
FT_FRAME_USHORT_LE( number_of_id_entries ),
FT_FRAME_END
};
static const FT_Frame_Field winpe_rsrc_dir_entry_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE WinPE_RsrcDirEntryRec
FT_FRAME_START( 8 ),
FT_FRAME_ULONG_LE( name ),
FT_FRAME_ULONG_LE( offset ),
FT_FRAME_END
};
static const FT_Frame_Field winpe_rsrc_data_entry_fields[] =
{
#undef FT_STRUCTURE
#define FT_STRUCTURE WinPE_RsrcDataEntryRec
FT_FRAME_START( 16 ),
FT_FRAME_ULONG_LE( offset_to_data ),
FT_FRAME_ULONG_LE( size ),
FT_FRAME_ULONG_LE( code_page ),
FT_FRAME_ULONG_LE( reserved ),
FT_FRAME_END
};
static const FT_Frame_Field winfnt_header_fields[] =
{
#undef FT_STRUCTURE
@ -214,6 +290,8 @@
WinNE_HeaderRec ne_header;
FT_TRACE2(( "MZ signature found\n" ));
if ( FT_STREAM_SEEK( mz_header.lfanew ) ||
FT_STREAM_READ_FIELDS( winne_header_fields, &ne_header ) )
goto Exit;
@ -229,6 +307,8 @@
FT_ULong font_offset = 0;
FT_TRACE2(( "NE signature found\n" ));
if ( FT_STREAM_SEEK( res_offset ) ||
FT_FRAME_ENTER( ne_header.rname_tab_offset -
ne_header.resource_tab_offset ) )
@ -291,9 +371,8 @@
FT_FRAME_ENTER( 12 ) )
goto Fail;
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;
face->font->offset = (FT_ULong)FT_GET_USHORT_LE() << size_shift;
face->font->fnt_size = (FT_ULong)FT_GET_USHORT_LE() << size_shift;
stream->cursor += 8;
@ -301,6 +380,181 @@
error = fnt_font_load( face->font, stream );
}
else if ( ne_header.magic == WINFNT_PE_MAGIC )
{
WinPE32_HeaderRec pe32_header;
WinPE32_SectionRec pe32_section;
WinPE_RsrcDirRec root_dir, name_dir, lang_dir;
WinPE_RsrcDirEntryRec dir_entry1, dir_entry2, dir_entry3;
WinPE_RsrcDataEntryRec data_entry;
FT_Long root_dir_offset, name_dir_offset, lang_dir_offset;
FT_UShort i, j, k;
FT_TRACE2(( "PE signature found\n" ));
if ( FT_STREAM_SEEK( mz_header.lfanew ) ||
FT_STREAM_READ_FIELDS( winpe32_header_fields, &pe32_header ) )
goto Exit;
FT_TRACE2(( "magic %04lx, machine %02x, number_of_sections %u, "
"size_of_optional_header %02x\n"
"magic32 %02x, rsrc_virtual_address %04lx, "
"rsrc_size %04lx\n",
pe32_header.magic, pe32_header.machine,
pe32_header.number_of_sections,
pe32_header.size_of_optional_header,
pe32_header.magic32, pe32_header.rsrc_virtual_address,
pe32_header.rsrc_size ));
if ( pe32_header.magic != WINFNT_PE_MAGIC /* check full signature */ ||
pe32_header.machine != 0x014c /* i386 */ ||
pe32_header.size_of_optional_header != 0xe0 /* FIXME */ ||
pe32_header.magic32 != 0x10b )
{
error = FNT_Err_Invalid_File_Format;
goto Exit;
}
face->root.num_faces = 0;
for ( i = 0; i < pe32_header.number_of_sections; i++ )
{
if ( FT_STREAM_READ_FIELDS( winpe32_section_fields,
&pe32_section ) )
goto Exit;
FT_TRACE2(( "name %.8s, va %04lx, size %04lx, offset %04lx\n",
pe32_section.name, pe32_section.virtual_address,
pe32_section.size_of_raw_data,
pe32_section.pointer_to_raw_data ));
if ( pe32_header.rsrc_virtual_address ==
pe32_section.virtual_address )
goto Found_rsrc_section;
}
error = FNT_Err_Invalid_File_Format;
goto Exit;
Found_rsrc_section:
FT_TRACE2(( "found resources section %.8s\n", pe32_section.name ));
if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data ) ||
FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &root_dir ) )
goto Exit;
root_dir_offset = pe32_section.pointer_to_raw_data;
for ( i = 0; i < root_dir.number_of_named_entries +
root_dir.number_of_id_entries; i++ )
{
if ( FT_STREAM_SEEK( root_dir_offset + 16 + i * 8 ) ||
FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
&dir_entry1 ) )
goto Exit;
if ( !(dir_entry1.offset & 0x80000000UL ) /* DataIsDirectory */ )
{
error = FNT_Err_Invalid_File_Format;
goto Exit;
}
dir_entry1.offset &= ~0x80000000UL;
name_dir_offset = pe32_section.pointer_to_raw_data +
dir_entry1.offset;
if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data +
dir_entry1.offset ) ||
FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &name_dir ) )
goto Exit;
for ( j = 0; j < name_dir.number_of_named_entries +
name_dir.number_of_id_entries; j++ )
{
if ( FT_STREAM_SEEK( name_dir_offset + 16 + j * 8 ) ||
FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
&dir_entry2 ) )
goto Exit;
if ( !(dir_entry2.offset & 0x80000000UL ) /* DataIsDirectory */ )
{
error = FNT_Err_Invalid_File_Format;
goto Exit;
}
dir_entry2.offset &= ~0x80000000UL;
lang_dir_offset = pe32_section.pointer_to_raw_data +
dir_entry2.offset;
if ( FT_STREAM_SEEK( pe32_section.pointer_to_raw_data +
dir_entry2.offset ) ||
FT_STREAM_READ_FIELDS( winpe_rsrc_dir_fields, &lang_dir ) )
goto Exit;
for ( k = 0; k < lang_dir.number_of_named_entries +
lang_dir.number_of_id_entries; k++ )
{
if ( FT_STREAM_SEEK( lang_dir_offset + 16 + k * 8 ) ||
FT_STREAM_READ_FIELDS( winpe_rsrc_dir_entry_fields,
&dir_entry3 ) )
goto Exit;
if ( dir_entry2.offset & 0x80000000UL /* DataIsDirectory */ )
{
error = FNT_Err_Invalid_File_Format;
goto Exit;
}
if ( dir_entry1.name == 8 /* RT_FONT */ )
{
if ( FT_STREAM_SEEK( root_dir_offset + dir_entry3.offset ) ||
FT_STREAM_READ_FIELDS( winpe_rsrc_data_entry_fields,
&data_entry ) )
goto Exit;
FT_TRACE2(( "found font #%lu, offset %04lx, "
"size %04lx, cp %lu\n",
dir_entry2.name,
pe32_section.pointer_to_raw_data +
data_entry.offset_to_data -
pe32_section.virtual_address,
data_entry.size, data_entry.code_page ));
if ( face_index == face->root.num_faces )
{
if ( FT_NEW( face->font ) )
goto Exit;
face->font->offset = pe32_section.pointer_to_raw_data +
data_entry.offset_to_data -
pe32_section.virtual_address;
face->font->fnt_size = data_entry.size;
error = fnt_font_load( face->font, stream );
if ( error )
FT_TRACE2(( "font #%lu load error %d\n",
dir_entry2.name, error ));
else
FT_TRACE2(( "font #%lu successfully loaded\n",
dir_entry2.name ));
}
face->root.num_faces++;
}
}
}
}
}
if ( face_index >= face->root.num_faces )
{
error = FNT_Err_Bad_Argument;
goto Exit;
}
}
Fail:

View File

@ -4,8 +4,9 @@
/* */
/* FreeType font driver for Windows FNT/FON files */
/* */
/* Copyright 1996-2001, 2002, 2003, 2004 by */
/* Copyright 1996-2001, 2002, 2003, 2004, 2007 by */
/* David Turner, Robert Wilhelm, and Werner Lemberg. */
/* Copyright 2007 Dmitry Timoshkov for Codeweavers */
/* */
/* This file is part of the FreeType project, and may only be used, */
/* modified, and distributed under the terms of the FreeType project */
@ -46,6 +47,65 @@ FT_BEGIN_HEADER
} WinNE_HeaderRec;
typedef struct WinPE32_HeaderRec_
{
FT_ULong magic;
FT_UShort machine;
FT_UShort number_of_sections;
/* skipped content */
FT_UShort size_of_optional_header;
/* skipped content */
FT_UShort magic32;
/* skipped content */
FT_ULong rsrc_virtual_address;
FT_ULong rsrc_size;
/* skipped content */
} WinPE32_HeaderRec;
typedef struct WinPE32_SectionRec_
{
FT_Byte name[8];
/* skipped content */
FT_ULong virtual_address;
FT_ULong size_of_raw_data;
FT_ULong pointer_to_raw_data;
/* skipped content */
} WinPE32_SectionRec;
typedef struct WinPE_RsrcDirRec_
{
FT_ULong characteristics;
FT_ULong time_date_stamp;
FT_UShort major_version;
FT_UShort minor_version;
FT_UShort number_of_named_entries;
FT_UShort number_of_id_entries;
} WinPE_RsrcDirRec;
typedef struct WinPE_RsrcDirEntryRec_
{
FT_ULong name;
FT_ULong offset;
} WinPE_RsrcDirEntryRec;
typedef struct WinPE_RsrcDataEntryRec_
{
FT_ULong offset_to_data;
FT_ULong size;
FT_ULong code_page;
FT_ULong reserved;
} WinPE_RsrcDataEntryRec;
typedef struct WinNameInfoRec_
{
FT_UShort offset;
@ -68,12 +128,12 @@ FT_BEGIN_HEADER
#define WINFNT_MZ_MAGIC 0x5A4D
#define WINFNT_NE_MAGIC 0x454E
#define WINFNT_PE_MAGIC 0x4550
typedef struct FNT_FontRec_
{
FT_ULong offset;
FT_Int size_shift;
FT_WinFNT_HeaderRec header;