Hello,
please find the attached patch, any comments are welcome.
Changelog:
Add support for loading bitmap .fon files in PE format.
Thanks.
--
Dmitry.
diff -upr freetype2/ChangeLog.21 freetype2/ChangeLog.21
--- freetype2/ChangeLog.21 2007-03-12 15:24:39.000000000 +0800
+++ freetype2/ChangeLog.21 2007-06-13 17:09:16.000000000 +0900
@@ -6391,7 +6391,7 @@
* include/freetype/internal/fnttypes.h (WinFNT_HeaderRec): Increase
size of `reserved2' to avoid memory overwrites.
-2003-01-08 Huw Dawies <[EMAIL PROTECTED]>
+2003-01-08 Huw Davies <[EMAIL PROTECTED]>
* src/winfonts/winfnt.c (winfnt_header_fields): Read 16 bytes into
`reserved2', not `reserved'.
diff -upr freetype2/src/winfonts/winfnt.c freetype2/src/winfonts/winfnt.c
--- freetype2/src/winfonts/winfnt.c 2007-06-13 17:05:55.000000000 +0900
+++ freetype2/src/winfonts/winfnt.c 2007-06-13 17:49:33.000000000 +0900
@@ -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,81 @@
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
@@ -213,6 +290,7 @@
/* yes, now look for an NE header in the file */
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 ) )
@@ -228,6 +306,7 @@
FT_UShort font_count = 0;
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 -
@@ -293,7 +372,6 @@
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;
stream->cursor += 8;
@@ -301,6 +379,149 @@
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 %u\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_dir;
+ }
+
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+
+Found_rsrc_dir:
+
+ 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 & 0x80000000 ) /* DataIsDirectory */ )
+ {
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ dir_entry1.offset &= ~0x80000000;
+
+ 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 & 0x80000000 ) /* DataIsDirectory */ )
+ {
+ error = FNT_Err_Invalid_File_Format;
+ goto Exit;
+ }
+
+ dir_entry2.offset &= ~0x80000000;
+
+ 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 & 0x80000000 /* 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 ID %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 );
+ }
+
+ face->root.num_faces++;
+ }
+ }
+ }
+ }
+ }
+
+ if ( face_index >= face->root.num_faces )
+ {
+ error = FNT_Err_Bad_Argument;
+ goto Exit;
+ }
}
Fail:
diff -upr freetype2/src/winfonts/winfnt.h freetype2/src/winfonts/winfnt.h
--- freetype2/src/winfonts/winfnt.h 2004-04-02 05:35:57.000000000 +0900
+++ freetype2/src/winfonts/winfnt.h 2007-06-13 17:09:16.000000000 +0900
@@ -46,6 +46,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 +127,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;
_______________________________________________
Freetype-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/freetype-devel