"Werner LEMBERG" <[EMAIL PROTECTED]> wrote:

please find the attached patch, any comments are welcome.

This looks good!  Some issues:

 . Please send me a PE font for testing.

 . If possible, stay within the 80-characters-per-line limit.

 . A more detailed ChangeLog entry would simplify my life
   enormously...

Thanks for reviewing the patch! I'm attaching an updated version that should
address your concerns. Also I'm attaching font_dll.tar.bz2 which includes
wine_fnt.fon in PE format with the sources taken from the Wine project and
build.bat in case you need to rebuild the dll. Another font in PE format
I'm aware of is included with Adobe Photoshop.

Changelog:
* 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.
* src/winfonts/winfnt.c (fnt_face_get_dll_font): Add support for
loading bitmap .fon files in PE format.

--
Dmitry.

Attachment: font_dll.tar.bz2
Description: Binary data

diff -up freetype2/ChangeLog.21 freetype2/ChangeLog.21
--- freetype2/ChangeLog.21      Mon Mar 12 01:23:08 2007
+++ freetype2/ChangeLog.21      Thu Jun 14 11:46:25 2007
@@ -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'.
Only in freetype2/objs: debug_st
diff -up freetype2/src/winfonts/winfnt.c freetype2/src/winfonts/winfnt.c
--- freetype2/src/winfonts/winfnt.c     Mon Jun 11 10:18:34 2007
+++ freetype2/src/winfonts/winfnt.c     Thu Jun 14 11:50:57 2007
@@ -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,13 +372,179 @@

        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;

        FT_FRAME_EXIT();

        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 & 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 #%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;
      }
    }

diff -up freetype2/src/winfonts/winfnt.h freetype2/src/winfonts/winfnt.h
--- freetype2/src/winfonts/winfnt.h     Thu Apr 01 20:35:58 2004
+++ freetype2/src/winfonts/winfnt.h     Thu Jun 14 11:01:44 2007
@@ -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