Copyright years udpated.
[m17n/libotf.git] / src / otfopen.c
index aacbc30..229bd40 100644 (file)
@@ -1,6 +1,6 @@
 /* otfopen.c -- OpenType font reader.
 
 /* 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
 
   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 <config.h>
 
 #include "otf.h"
-#include "otferror.h"
+#include "internal.h"
 
 #include FT_TRUETYPE_TABLES_H
 
 
 #include FT_TRUETYPE_TABLES_H
 
@@ -57,6 +57,15 @@ write to the Free Software Foundation, Inc., 59 Temple Place, Suite
 
     (5) API miscellaneous
 */
 
     (5) API miscellaneous
 */
+
+int debug_flag = -1;
+
+static void
+set_debug_flag ()
+{
+  debug_flag = getenv ("LIBOTF_DEBUG") != NULL;
+}
+
 \f
 /* (0) Stream handler
 
 \f
 /* (0) Stream handler
 
@@ -324,7 +333,6 @@ struct OTF_InternalData
   OTF_ApplicationData *app_data;
 };
 
   OTF_ApplicationData *app_data;
 };
 
-
 static OTF_MemoryRecord *
 allocate_memory_record (OTF *otf)
 {
 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)");
   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;
 
     {
       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;
     }
       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;
 
     {
       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;
        {
          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++)
            {
                      numUnicodeValueRanges,
                      "(EncodingSubtable14-Records-unicodeValueRanges)");
          for (j = 0; j < numUnicodeValueRanges; j++)
            {
-             OTF_UnicodeValueRange *unicodeValueRange 
+             OTF_UnicodeValueRange *unicodeValueRange
                = &record->unicodeValueRanges[j];
              unsigned startUnicodeValue;
              char additionalCount;
                = &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;
            }
        }
                = (unsigned short) additionalCount;
            }
        }
-      if (nonDefaultUVSOffset) 
+      if (nonDefaultUVSOffset)
        {
          unsigned numUVSMappings;
 
        {
          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)
        {
       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
          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);
              {
                unsigned off;
                unsigned rest = 2 * (segCount - j);
-               
+
                READ_USHORT (stream, off);
                if (off == 0)
                  sub4->segments[j].idRangeOffset = 0xFFFF;
                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;
   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;
 }
 
   return 0;
 }
 
@@ -2799,19 +2807,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");
       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;
 
 
       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;
        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;
       if (read_offset_table (otf, stream, &otf->offset_table) < 0)
        return -1;
-
       /* Size of each Table Directory is 16 bytes.  */
       /* 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,
        return -1;
 
       OTF_CALLOC (otf->table_dirs, otf->offset_table.numTables,
@@ -2933,11 +2956,14 @@ OTF_open (const char *otf_name)
   int len = strlen (otf_name);
   const char *ext = otf_name + (len - 4);
 
   int len = strlen (otf_name);
   const char *ext = otf_name + (len - 4);
 
+  if (debug_flag < 0)
+    set_debug_flag ();
+
   if (len < 4
       || ext[0] != '.'
   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)
     OTF_ERROR (OTF_ERROR_FILE, otf_name);
   fp = fopen (otf_name, "r");
   if (! fp)
@@ -2983,13 +3009,16 @@ OTF_open_ft_face (FT_Face face)
   OTF *otf;
   OTF_InternalData *internal_data;
 
   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;
   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");
   internal_data = calloc (1, sizeof (OTF_InternalData));
   if (! internal_data)
     OTF_ERROR (OTF_ERROR_MEMORY, " (InternalData");
@@ -3270,7 +3299,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;
 {
   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;
   for (; app_data; app_data = app_data->next)
     if (strcmp (app_data->id, id) == 0)
       return app_data->data;