(gstring_subst): Correctly set temp.f.index.
[m17n/libotf.git] / src / otfopen.c
index 93228f0..54091d0 100644 (file)
@@ -457,7 +457,7 @@ read_cmap_table (OTF *otf, OTF_Stream *stream)
   char *errfmt = "cmap%s";
   void *errret = NULL;
   OTF_cmap *cmap;
-  int unicode_index = -1;
+  int unicode_bmp_index = -1, unicode_full_index = -1;
   int i;
 
   OTF_CALLOC (cmap, 1, "");
@@ -466,12 +466,27 @@ read_cmap_table (OTF *otf, OTF_Stream *stream)
   OTF_MALLOC (cmap->EncodingRecord, cmap->numTables, "");
   for (i = 0; i < cmap->numTables; i++)
     {
-      READ_USHORT (stream, cmap->EncodingRecord[i].platformID);
-      READ_USHORT (stream, cmap->EncodingRecord[i].encodingID);
+      unsigned platformID, encodingID;
+
+      READ_USHORT (stream, platformID);
+      cmap->EncodingRecord[i].platformID = platformID;
+      READ_USHORT (stream, encodingID);
+      cmap->EncodingRecord[i].encodingID = encodingID;
       READ_ULONG (stream, cmap->EncodingRecord[i].offset);
-      if (cmap->EncodingRecord[i].platformID == 3
-         && cmap->EncodingRecord[i].encodingID == 1)
-       unicode_index = i;
+      if (platformID == 0)
+       {
+         if (encodingID <= 3)
+           unicode_bmp_index = i;
+         else
+           unicode_full_index = i;
+       }
+      else if (platformID == 3)
+       {
+         if (encodingID == 1)
+           unicode_bmp_index = i;
+         else if (encodingID == 10)
+           unicode_full_index = i;
+       }
     }
   for (i = 0; i < cmap->numTables; i++)
     {
@@ -503,6 +518,36 @@ read_cmap_table (OTF *otf, OTF_Stream *stream)
          break;
 
        case 2:
+         {
+           OTF_EncodingSubtable2 *sub2;
+           int j, max_key, remaining_bytes;
+
+           OTF_MALLOC (sub2, 1, " (EncodingSubtable2)");
+           cmap->EncodingRecord[i].subtable.f.f2 = sub2;
+           for (j = 0, max_key = 0; j < 256; j++)
+             {
+               READ_USHORT (stream, sub2->subHeaderKeys[j]);
+               if (max_key < sub2->subHeaderKeys[j])
+                 max_key = sub2->subHeaderKeys[j];
+             }
+           max_key += 8;
+           sub2->subHeaderCount = max_key / 8;
+           OTF_MALLOC (sub2->subHeaders, max_key / 8, " (subHeaders)");
+           for (j = 0; j < sub2->subHeaderCount; j++)
+             {
+               READ_USHORT (stream, sub2->subHeaders[j].firstCode);
+               READ_USHORT (stream, sub2->subHeaders[j].entryCount);
+               READ_SHORT (stream, sub2->subHeaders[j].idDelta);
+               READ_USHORT (stream, sub2->subHeaders[j].idRangeOffset);
+               /* Make it offset from sub2->glyphIndexArray.  */
+               sub2->subHeaders[j].idRangeOffset -= max_key - (j * 8 + 6);
+             }
+           sub2->glyphIndexCount = (cmap->EncodingRecord[i].subtable.length
+                                    - 262 - max_key);
+           OTF_MALLOC (sub2->glyphIndexArray, sub2->glyphIndexCount,
+                       " (glyphIndexArray)");
+           READ_BYTES (stream, sub2->glyphIndexArray, sub2->glyphIndexCount);
+         }
          break;
 
        case 4:
@@ -560,12 +605,69 @@ read_cmap_table (OTF *otf, OTF_Stream *stream)
            for (j = 0; j < sub6->entryCount; j++)
              READ_USHORT (stream, sub6->glyphIdArray[j]);
          }
+         break;
+
+       case 8:
+         {
+           OTF_EncodingSubtable8 *sub8;
+           int j;
+
+           OTF_MALLOC (sub8, 1, " (EncodingSubtable8)");
+           cmap->EncodingRecord[i].subtable.f.f8 = sub8;
+           for (j = 0; j < 8192; j++)
+             READ_BYTES (stream, sub8->is32, 8192);
+           READ_ULONG (stream, sub8->nGroups);
+           OTF_MALLOC (sub8->Groups, sub8->nGroups, " (Groups)");
+           for (j = 0; j < sub8->nGroups; j++)
+             {
+               READ_ULONG (stream, sub8->Groups[i].startCharCode);
+               READ_ULONG (stream, sub8->Groups[i].endCharCode);
+               READ_ULONG (stream, sub8->Groups[i].startGlyphID);
+             }
+         }
+         break;
+
+       case 10:
+         {
+           OTF_EncodingSubtable10 *sub10;
+           int j;
+
+           OTF_MALLOC (sub10, 1, " (EncodingSubtable10)");
+           cmap->EncodingRecord[i].subtable.f.f10 = sub10;
+           READ_ULONG (stream, sub10->startCharCode);
+           READ_ULONG (stream, sub10->numChars);
+           OTF_MALLOC (sub10->glyphs, sub10->numChars, " (GlyphCount)");
+           for (j = 0; j < sub10->numChars; j++)
+             READ_USHORT (stream, sub10->glyphs[j]);
+         }
+         break;
+
+       case 12:
+         {
+           OTF_EncodingSubtable12 *sub12;
+           int j;
+
+           OTF_MALLOC (sub12, 1, " (EncodingSubtable12)");
+           cmap->EncodingRecord[i].subtable.f.f12 = sub12;
+           READ_ULONG (stream, sub12->nGroups);
+           OTF_MALLOC (sub12->Groups, sub12->nGroups, " (Groups)");
+           for (j = 0; j < sub12->nGroups; j++)
+             {
+               READ_ULONG (stream, sub12->Groups[i].startCharCode);
+               READ_ULONG (stream, sub12->Groups[i].endCharCode);
+               READ_ULONG (stream, sub12->Groups[i].startGlyphID);
+             }
+         }
+         break;
+
+       default:
+         OTF_ERROR (OTF_ERROR_TABLE, " (invalid Subtable format)");
        }
     }
 
-  if (unicode_index >= 0)
+  if (unicode_bmp_index >= 0)
     {
-      OTF_EncodingRecord *rec = cmap->EncodingRecord + unicode_index;
+      OTF_EncodingRecord *rec = cmap->EncodingRecord + unicode_bmp_index;
       OTF_GlyphID glyph_id, max_glyph_id = 0;
 
       OTF_CALLOC (cmap->unicode_table, 0x10000, "");
@@ -1278,7 +1380,7 @@ read_class_set_list (OTF *otf, OTF_Stream *stream, long offset,
   READ_UINT16 (stream, count);
   if (! count)
     OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
-  OTF_MALLOC (*set, count, "");
+  OTF_CALLOC (*set, count, "");
   for (i = 0; i < count; i++)
     /* Offset can be zero.  */
     READ_OFFSET (stream, (*set)[i].offset);
@@ -1894,7 +1996,7 @@ read_value_record (OTF *otf, OTF_Stream *stream, long offset,
 
   if (bit & OTF_XPlacement)
     READ_INT16 (stream, value_record->XPlacement);
-  if (bit & OTF_XPlacement)
+  if (bit & OTF_YPlacement)
     READ_INT16 (stream, value_record->YPlacement);
   if (bit & OTF_XAdvance)
     READ_INT16 (stream, value_record->XAdvance);
@@ -2140,9 +2242,16 @@ read_ligature_attach (OTF *otf, OTF_Stream *stream, long offset,
     }
   for (i = 0; i < attach->ComponentCount; i++)
     for (j = 0; j < ClassCount; j++)
-      if (read_anchor (otf, stream, offset + attach->offset,
-                      &attach->ComponentRecord[i].LigatureAnchor[j]) < 0)
-       return -1;
+      {
+       if (attach->ComponentRecord[i].LigatureAnchor[j].offset)
+         {
+           if (read_anchor (otf, stream, offset + attach->offset,
+                            &attach->ComponentRecord[i].LigatureAnchor[j]) < 0)
+             return -1;
+         }
+       else
+         attach->ComponentRecord[i].LigatureAnchor[j].AnchorFormat = 0;
+      }
   return 0;
 }
 
@@ -2596,7 +2705,15 @@ OTF_open (char *otf_name)
   void *errret = NULL;
   OTF *otf;
   OTF_InternalData *internal_data;
-
+  int len = strlen (otf_name);
+  const char *ext = otf_name + (len - 4);
+
+  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'))
+    OTF_ERROR (OTF_ERROR_FILE, otf_name);
   fp = fopen (otf_name, "r");
   if (! fp)
     OTF_ERROR (OTF_ERROR_FILE, otf_name);