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
Freetype-devel@nongnu.org
http://lists.nongnu.org/mailman/listinfo/freetype-devel

Reply via email to