(read_anchor_array): Do not read an anchor if its
[m17n/libotf.git] / src / otfopen.c
index aacbc30..dc4a64b 100644 (file)
@@ -1,6 +1,6 @@
 /* otfopen.c -- OpenType font reader.
 
-Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009
+Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010
   National Institute of Advanced Industrial Science and Technology (AIST)
   Registration Number H15PRO167
 
@@ -27,7 +27,7 @@ write to the Free Software Foundation, Inc., 59 Temple Place, Suite
 #include <config.h>
 
 #include "otf.h"
-#include "otferror.h"
+#include "internal.h"
 
 #include FT_TRUETYPE_TABLES_H
 
@@ -57,6 +57,15 @@ write to the Free Software Foundation, Inc., 59 Temple Place, Suite
 
     (5) API miscellaneous
 */
+
+int debug_flag = -1;
+
+static void
+set_debug_flag ()
+{
+  debug_flag = getenv ("LIBOTF_DEBUG") != NULL;
+}
+
 \f
 /* (0) Stream handler
 
@@ -324,7 +333,6 @@ struct OTF_InternalData
   OTF_ApplicationData *app_data;
 };
 
-
 static OTF_MemoryRecord *
 allocate_memory_record (OTF *otf)
 {
@@ -532,7 +540,7 @@ read_cmap_uvs_table (OTF *otf, OTF_Stream *stream, OTF_Offset offset)
   READ_ULONG (stream, nRecords);
   sub14->nRecords = nRecords;
   OTF_MALLOC (sub14->Records, nRecords, "(EncodingSubtable14-Records)");
-  for (i = 0; i < sub14->nRecords; i++) 
+  for (i = 0; i < sub14->nRecords; i++)
     {
       unsigned varSelector=0, defaultUVSOffset, nonDefaultUVSOffset;
 
@@ -543,25 +551,25 @@ read_cmap_uvs_table (OTF *otf, OTF_Stream *stream, OTF_Offset offset)
       READ_ULONG (stream, nonDefaultUVSOffset);
       sub14->Records[i].nonDefaultUVSOffset = nonDefaultUVSOffset;
     }
-  for (i = 0; i < sub14->nRecords; i++) 
+  for (i = 0; i < sub14->nRecords; i++)
     {
       OTF_VariationSelectorRecord *record = &sub14->Records[i];
       unsigned defaultUVSOffset = record->defaultUVSOffset;
       unsigned nonDefaultUVSOffset = record->nonDefaultUVSOffset;
 
-      if (defaultUVSOffset) 
+      if (defaultUVSOffset)
        {
          unsigned numUnicodeValueRanges;
 
          SEEK_STREAM (stream, offset+defaultUVSOffset);
          READ_ULONG (stream, numUnicodeValueRanges);
          record->numUnicodeValueRanges = numUnicodeValueRanges;
-         OTF_MALLOC (record->unicodeValueRanges, 
+         OTF_MALLOC (record->unicodeValueRanges,
                      numUnicodeValueRanges,
                      "(EncodingSubtable14-Records-unicodeValueRanges)");
          for (j = 0; j < numUnicodeValueRanges; j++)
            {
-             OTF_UnicodeValueRange *unicodeValueRange 
+             OTF_UnicodeValueRange *unicodeValueRange
                = &record->unicodeValueRanges[j];
              unsigned startUnicodeValue;
              char additionalCount;
@@ -573,7 +581,7 @@ read_cmap_uvs_table (OTF *otf, OTF_Stream *stream, OTF_Offset offset)
                = (unsigned short) additionalCount;
            }
        }
-      if (nonDefaultUVSOffset) 
+      if (nonDefaultUVSOffset)
        {
          unsigned numUVSMappings;
 
@@ -647,7 +655,7 @@ read_cmap_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag)
       cmap->EncodingRecord[i].subtable.format = format;
       if (format == 14)
        {
-         READ_ULONG (stream, cmap->EncodingRecord[i].subtable.length);     
+         READ_ULONG (stream, cmap->EncodingRecord[i].subtable.length);
          cmap->EncodingRecord[i].subtable.language = 0;
        }
       else
@@ -734,7 +742,7 @@ read_cmap_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag)
              {
                unsigned off;
                unsigned rest = 2 * (segCount - j);
-               
+
                READ_USHORT (stream, off);
                if (off == 0)
                  sub4->segments[j].idRangeOffset = 0xFFFF;
@@ -2010,7 +2018,7 @@ read_reverse_chain1 (OTF *otf, OTF_Stream *stream, long offset,
   count = read_glyph_ids (otf, stream, &reverse_chain->Substitute, 0, -1);
   if (count <= 0)
     return -1;
-  reverse_chain->GlyphCount = count;  
+  reverse_chain->GlyphCount = count;
   return 0;
 }
 
@@ -2328,8 +2336,9 @@ read_anchor_array (OTF *otf, OTF_Stream *stream, long offset,
     }
   for (i = 0; i < array->Count; i++)
     for (j = 0; j < ClassCount; j++)
-      if (read_anchor (otf, stream, offset + array->offset,
-                      &array->AnchorRecord[i].Anchor[j]) < 0)
+      if (array->AnchorRecord[i].Anchor[j].offset > 0
+         && read_anchor (otf, stream, offset + array->offset,
+                         &array->AnchorRecord[i].Anchor[j]) < 0)
        return -1;
   RESTORE_STREAM (stream, state);
   return 0;
@@ -2429,7 +2438,7 @@ read_ligature_attach (OTF *otf, OTF_Stream *stream, long offset,
                      unsigned ClassCount, OTF_LigatureAttach *attach)
 {
   char *errfmt = "LigatureAttach%s";
-  int errret = 1;
+  int errret = -1;
   int i, j;
 
   SEEK_STREAM (stream, offset + attach->offset);
@@ -2475,8 +2484,10 @@ read_ligature_array (OTF *otf, OTF_Stream *stream, long offset,
   for (i = 0; i < array->LigatureCount; i++)
     READ_OFFSET (stream, array->LigatureAttach[i].offset);
   for (i = 0; i < array->LigatureCount; i++)
-    read_ligature_attach (otf, stream, offset + array->offset,
-                         class_count, array->LigatureAttach + i);
+    if (array->LigatureAttach[i].offset > 0
+       && read_ligature_attach (otf, stream, offset + array->offset,
+                                class_count, array->LigatureAttach + i) < 0)
+      return -1;
   RESTORE_STREAM (stream, state);
   return 0;
 }
@@ -2617,7 +2628,7 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream,
          read_coverage (otf, stream, offset, &subtable->Coverage);
          read_coverage (otf, stream, offset,
                         &subtable->u.mark_mark1.Mark2Coverage);
-         READ_UINT16 (stream, subtable->u.mark_base1.ClassCount);
+         READ_UINT16 (stream, subtable->u.mark_mark1.ClassCount);
          read_mark_array (otf, stream, offset,
                           &subtable->u.mark_mark1.Mark1Array);
          read_anchor_array (otf, stream, offset,
@@ -2799,19 +2810,34 @@ read_header_part (OTF *otf, FILE *fp, FT_Face face)
       OTF_Tag gsub_tag = OTF_tag ("GSUB");
       OTF_Tag gpos_tag = OTF_tag ("GPOS");
       OTF_Stream *stream = make_stream ("Offset Table");
+      unsigned char ttctag[4];
 
       if (! stream)
        return -1;
       internal_data->header_stream = stream;
 
-      /* Size of Offset Table is 12 bytes.  */
-      if (setup_stream (stream, fp, 0, 12) < 0)
+      /* Size of Offset Table is 12 bytes.  Size of TTC header
+        (including only the an offset of the first font) is 16.  */
+      if (setup_stream (stream, fp, 0, 16) < 0)
        return -1;
+      READ_BYTES (stream, ttctag, 4);
+      if (memcmp (ttctag, "ttcf", 4) == 0)
+       {
+         /* This is a TrueType Collection file.  We extract the first font.  */
+         unsigned version, numfonts, offset;
+         READ_ULONG (stream, version);
+         READ_ULONG (stream, numfonts);
+         READ_ULONG (stream, offset); /* Offset of the first font.  */
+         if (setup_stream (stream, fp, offset, 12) < 0)
+           return -1;
+       }
+      else
+       SEEK_STREAM (stream, 0L);
       if (read_offset_table (otf, stream, &otf->offset_table) < 0)
        return -1;
-
       /* Size of each Table Directory is 16 bytes.  */
-      if (setup_stream (stream, fp, 12, 16 * otf->offset_table.numTables) < 0)
+      if (setup_stream (stream, fp, stream->pos,
+                       16 * otf->offset_table.numTables) < 0)
        return -1;
 
       OTF_CALLOC (otf->table_dirs, otf->offset_table.numTables,
@@ -2933,11 +2959,14 @@ OTF_open (const char *otf_name)
   int len = strlen (otf_name);
   const char *ext = otf_name + (len - 4);
 
+  if (debug_flag < 0)
+    set_debug_flag ();
+
   if (len < 4
       || ext[0] != '.'
-      || (ext[1] != 'O' && ext[1] != 'T' && ext[1] != 'o' && ext[1] != 't')
-      || (ext[2] != 'T' && ext[2] != 't')
-      || (ext[3] != 'F' && ext[3] != 'f'))
+      || (strncasecmp (ext + 1, "otf", 3)
+         && strncasecmp (ext + 1, "ttf", 3)
+         && strncasecmp (ext + 1, "ttc", 3)))
     OTF_ERROR (OTF_ERROR_FILE, otf_name);
   fp = fopen (otf_name, "r");
   if (! fp)
@@ -2983,13 +3012,16 @@ OTF_open_ft_face (FT_Face face)
   OTF *otf;
   OTF_InternalData *internal_data;
 
+  if (debug_flag < 0)
+    set_debug_flag ();
+
   if (! FT_IS_SFNT (face))
     OTF_ERROR (OTF_ERROR_FILE, (char *) face->family_name);
   otf = calloc (1, sizeof (OTF));
   if (! otf)
     OTF_ERROR (OTF_ERROR_MEMORY, "body allocation");
   otf->filename = NULL;
-  
+
   internal_data = calloc (1, sizeof (OTF_InternalData));
   if (! internal_data)
     OTF_ERROR (OTF_ERROR_MEMORY, " (InternalData");
@@ -3149,6 +3181,8 @@ OTF_check_features (OTF *otf, int gsubp,
 
   if (OTF_get_features (otf, gsubp) < 0)
     {
+      if (gsubp ? ! otf->gsub : ! otf->gpos)
+       return 0;
       for (i = 0; i < n_features; i++)
        {
          OTF_Tag feature = features[i];
@@ -3158,7 +3192,6 @@ OTF_check_features (OTF *otf, int gsubp,
          if ((((unsigned) feature) & 0x80000000) == 0)
            return -1;
        }
-      return 1;
     }
   if (gsubp)
     {
@@ -3180,8 +3213,10 @@ OTF_check_features (OTF *otf, int gsubp,
       for (i = 0; i < Script->LangSysCount && ! LangSys; i++)
        if (Script->LangSysRecord[i].LangSysTag == language)
          LangSys = Script->LangSys + i;
+      if (! LangSys)
+       return 0;
     }
-  if (! LangSys)
+  else
     LangSys = &Script->DefaultLangSys;
   for (j = 0; j < n_features; j++)
     {
@@ -3270,7 +3305,7 @@ OTF_get_data (OTF *otf, char *id)
 {
   OTF_InternalData *internal_data = (OTF_InternalData *) otf->internal_data;
   OTF_ApplicationData *app_data = internal_data->app_data;
-  
+
   for (; app_data; app_data = app_data->next)
     if (strcmp (app_data->id, id) == 0)
       return app_data->data;