Hi,

Attached is a draft of the patch to fix the face reordering problem.
I will dig the mailing list archive and add the appropriate reference
for the changelog.

In my understanding, the problem could be described as following:

1) Comparing the ftdump outputs by FreeType2 built with Carbon
framework, and that by without Carbon framework, the ordering of
the faces in a Suitcase or .dfont format is different.

For example, the faces in Helvetica.dfont are shown as:

with Carbon
-----------
Helvetica
Helvetica-Bold
Helvetica-Oblique
Helvetica-BoldOblique

without Carbon
--------------
Helvetica-BoldOblique
Helvetica-Oblique
Helvetica
Helvetica-Bold

2) Because Mac OS X bundles FreeType2 with Carbon framework,
default fontconfig cache DB assumes the face ordering is
same with QuickDraw API.

3) If an user installs yet-another FreeType2 without Carbon
framework and a client program using it, the fontfile
pathname and index obtained by fontconfig are no longer
reliable, because the face index might be different.

4) As a result, the (yet-another) FreeType2 client program
is forced to open the font file and scan all faces by themselves,
to identify the appropriate face index.

* if I'm misunderstanding the problem, please let me know.

==============================================================

What is the cause of the problem? Although I could not find
the reliable document how QuickDraw orders the faces in the
Suitcase, but it seems that QuickDraw picks the faces in the
order of the header that lists the fragmented resources.

Carbon-free FreeType2 Suitcase font driver reorders the
fragmented resources by their resource ids. If no reordering,
the different face index ordering problem seems to be solved.

Why the reordering was implemented? It was designed for
PostScript Type1 font in Suitcase format. The content of the
Type1 font is too large to store in single resource (in the
earliest architecture for Type1 in Suitcase - now it is not
essential limitation anymore), and fragmented into multiple
resources. To concatenate them properly in the restoration
of Type1 font data, the ordering of the fragmented resources
by their ids is needed. ... but it is not essential for sfnt
resource. Usually, 1 sfnt face is stored in 1 sfnt resource,
not splitted to multiple resource fragments.

Thus, I introduced a switch to enable/disable the fragmented
resources. The switch is enabled only for PostScript Type1 in
Suitcase. An internal header (ftrfork.h) is modified, but
I think there is no impact except of the rogue client using
the internal header.

Regards,
mpsuzuki


(13/12/20 14:04), Hin-Tak Leung wrote:
  Hi,

  I guess it is related with the handling of Suitcase format
  font.
  Please let me check.

  Regards,
  mpsuzuki


Thanks for the offer. If you are interested in that bit of code snipplet in 
context, or the rest
of it, it is in the middle of

https://svn.r-project.org/R/trunk/src/library/grDevices/src/cairo/cairoFns.c

I have done git svn blame, but the commit log are simply
'improve Cairo FT font detection on OS X' and "workaround Mac FT face selection 
problem".
the latter with a longer changelog/news item with reference to a bug report, 
but not helpful:

https://bugs.r-project.org/bugzilla/show_bug.cgi?id=13463

Hin-Tak


diff --git a/ChangeLog b/ChangeLog
index 0288701..c7df201 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2013-12-27  suzuki toshiya  <[email protected]>
+
+       [ftrfork] Fix the face order difference between POSIX and QuickDraw.
+
+       The fragmented resources in Suitcase and .dfont should be reordered
+       when post resource for Type1 is being restored, but reordering of
+       sfnt resources induces the different face order.  Now the ordering
+       is restricted to post resource only, to prevent the different order
+       issue (e.g. the face index in the fontconfig cache generated by
+       QuickDraw based API is incompatible with FreeType2 client without
+       QuickDraw).
+
+       * src/base/ftrfork.c (FT_Raccess_Get_DataOffsets): Add a switch
+       `sort_by_res_id' to control the fragmented resource ordering. 
+       * include/internal/ftrfork.h: Daclare new switch.
+       * src/base/ftobjs.c (IsMacResource): Enable the soring for post
+       resource, and disable the sorting for sfnt resource.
+
 2013-12-25  Werner Lemberg  <[email protected]>
 
        Fix Savannah bug #40997.
diff --git a/include/internal/ftrfork.h b/include/internal/ftrfork.h
index fbc3283..a0e583b 100644
--- a/include/internal/ftrfork.h
+++ b/include/internal/ftrfork.h
@@ -224,6 +224,13 @@ FT_BEGIN_HEADER
   /*    tag ::                                                             */
   /*      The resource tag.                                                */
   /*                                                                       */
+  /*    sort_by_res_id ::                                                  */
+  /*      A Boolean to order the fragmented resource by their ids.         */
+  /*      The fragmented resources for POST resource should be sorted      */
+  /*      to restore Type1 font properly.  For snft resource, sorting      */
+  /*      may induce the different order of the faces in comparison with   */
+  /*      that by QuickDraw API.                                           */
+  /*                                                                       */
   /* <Output>                                                              */
   /*    offsets ::                                                         */
   /*      The stream offsets for the resource data specified by `tag'.     */
@@ -246,6 +253,7 @@ FT_BEGIN_HEADER
                               FT_Long     map_offset,
                               FT_Long     rdata_pos,
                               FT_Long     tag,
+                              FT_Bool     sort_by_res_id,
                               FT_Long   **offsets,
                               FT_Long    *count );
 
diff --git a/src/base/ftobjs.c b/src/base/ftobjs.c
index bd0c66e..bed0389 100644
--- a/src/base/ftobjs.c
+++ b/src/base/ftobjs.c
@@ -1801,9 +1801,10 @@
     if ( error )
       return error;
 
+    /* POST resources must be sorted to concatenate properly */
     error = FT_Raccess_Get_DataOffsets( library, stream,
                                         map_offset, rdara_pos,
-                                        TTAG_POST,
+                                        TTAG_POST, TRUE,
                                         &data_offsets, &count );
     if ( !error )
     {
@@ -1816,9 +1817,11 @@
       return error;
     }
 
+    /* sfnt resources should not be sorted to preserve the face order by
+       QuickDraw API */
     error = FT_Raccess_Get_DataOffsets( library, stream,
                                         map_offset, rdara_pos,
-                                        TTAG_sfnt,
+                                        TTAG_sfnt, FALSE,
                                         &data_offsets, &count );
     if ( !error )
     {
diff --git a/src/base/ftrfork.c b/src/base/ftrfork.c
index 8049117..87ac6fb 100644
--- a/src/base/ftrfork.c
+++ b/src/base/ftrfork.c
@@ -151,6 +151,7 @@
                               FT_Long     map_offset,
                               FT_Long     rdata_pos,
                               FT_Long     tag,
+                              FT_Bool     sort_by_res_id,
                               FT_Long   **offsets,
                               FT_Long    *count )
   {
@@ -163,6 +164,7 @@
     FT_RFork_Ref  *ref = NULL;
 
 
+    FT_TRACE3(( "\n" ));
     error = FT_Stream_Seek( stream, map_offset );
     if ( error )
       return error;
@@ -183,6 +185,8 @@
                   (char)( 0xff & ( tag_internal >> 16 ) ),
                   (char)( 0xff & ( tag_internal >>  8 ) ),
                   (char)( 0xff & ( tag_internal >>  0 ) ) ));
+      FT_TRACE3(( "             : subcount=%d, suboffset=0x%04x\n",
+                  subcnt, rpos ));
 
       if ( tag_internal == tag )
       {
@@ -208,11 +212,22 @@
             goto Exit;
 
           ref[j].offset = temp & 0xFFFFFFL;
+          FT_TRACE3(( "             [%d]: resouce_id=0x%04x, offset=0x%08x\n",
+                       j, ref[j].res_id, ref[j].offset ));
         }
 
-        ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),
-                  ( int(*)(const void*, const void*) )
-                  ft_raccess_sort_ref_by_id );
+        if (sort_by_res_id)
+        {
+          ft_qsort( ref, *count, sizeof ( FT_RFork_Ref ),
+                    ( int(*)(const void*, const void*) )
+                    ft_raccess_sort_ref_by_id );
+
+          FT_TRACE3(( "             -- sort resources by their ids --\n" ));
+          for ( j = 0; j < *count; ++ j ) {
+            FT_TRACE3(( "             [%d]: resouce_id=0x%04x, 
offset=0x%08x\n",
+                         j, ref[j].res_id, ref[j].offset ));
+          }
+        }
 
         if ( FT_NEW_ARRAY( offsets_internal, *count ) )
           goto Exit;
_______________________________________________
Freetype-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/freetype-devel

Reply via email to