gfx/ots/src/cff.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
     2 // Use of this source code is governed by a BSD-style license that can be
     3 // found in the LICENSE file.
     5 #include "cff.h"
     7 #include <cstring>
     8 #include <utility>
     9 #include <vector>
    11 #include "cff_type2_charstring.h"
    13 // CFF - PostScript font program (Compact Font Format) table
    14 // http://www.microsoft.com/typography/otspec/cff.htm
    15 // http://www.microsoft.com/typography/otspec/cffspec.htm
    17 #define TABLE_NAME "CFF"
    19 namespace {
    21 enum DICT_OPERAND_TYPE {
    22   DICT_OPERAND_INTEGER,
    23   DICT_OPERAND_REAL,
    24   DICT_OPERATOR,
    25 };
    27 enum DICT_DATA_TYPE {
    28   DICT_DATA_TOPLEVEL,
    29   DICT_DATA_FDARRAY,
    30 };
    32 enum FONT_FORMAT {
    33   FORMAT_UNKNOWN,
    34   FORMAT_CID_KEYED,
    35   FORMAT_OTHER,  // Including synthetic fonts
    36 };
    38 // see Appendix. A
    39 const size_t kNStdString = 390;
    41 bool ReadOffset(ots::Buffer *table, uint8_t off_size, uint32_t *offset) {
    42   if (off_size > 4) {
    43     return OTS_FAILURE();
    44   }
    46   uint32_t tmp32 = 0;
    47   for (unsigned i = 0; i < off_size; ++i) {
    48     uint8_t tmp8 = 0;
    49     if (!table->ReadU8(&tmp8)) {
    50       return OTS_FAILURE();
    51     }
    52     tmp32 <<= 8;
    53     tmp32 += tmp8;
    54   }
    55   *offset = tmp32;
    56   return true;
    57 }
    59 bool ParseIndex(ots::Buffer *table, ots::CFFIndex *index) {
    60   index->off_size = 0;
    61   index->offsets.clear();
    63   if (!table->ReadU16(&(index->count))) {
    64     return OTS_FAILURE();
    65   }
    66   if (index->count == 0) {
    67     // An empty INDEX.
    68     index->offset_to_next = table->offset();
    69     return true;
    70   }
    72   if (!table->ReadU8(&(index->off_size))) {
    73     return OTS_FAILURE();
    74   }
    75   if ((index->off_size == 0) ||
    76       (index->off_size > 4)) {
    77     return OTS_FAILURE();
    78   }
    80   const size_t array_size = (index->count + 1) * index->off_size;
    81   // less than ((64k + 1) * 4), thus does not overflow.
    82   const size_t object_data_offset = table->offset() + array_size;
    83   // does not overflow too, since offset() <= 1GB.
    85   if (object_data_offset >= table->length()) {
    86     return OTS_FAILURE();
    87   }
    89   for (unsigned i = 0; i <= index->count; ++i) {  // '<=' is not a typo.
    90     uint32_t rel_offset = 0;
    91     if (!ReadOffset(table, index->off_size, &rel_offset)) {
    92       return OTS_FAILURE();
    93     }
    94     if (rel_offset < 1) {
    95       return OTS_FAILURE();
    96     }
    97     if (i == 0 && rel_offset != 1) {
    98       return OTS_FAILURE();
    99     }
   101     if (rel_offset > table->length()) {
   102       return OTS_FAILURE();
   103     }
   105     // does not underflow.
   106     if (object_data_offset > table->length() - (rel_offset - 1)) {
   107       return OTS_FAILURE();
   108     }
   110     index->offsets.push_back(
   111         object_data_offset + (rel_offset - 1));  // less than length(), 1GB.
   112   }
   114   for (unsigned i = 1; i < index->offsets.size(); ++i) {
   115     // We allow consecutive identical offsets here for zero-length strings.
   116     // See http://crbug.com/69341 for more details.
   117     if (index->offsets[i] < index->offsets[i - 1]) {
   118       return OTS_FAILURE();
   119     }
   120   }
   122   index->offset_to_next = index->offsets.back();
   123   return true;
   124 }
   126 bool ParseNameData(
   127     ots::Buffer *table, const ots::CFFIndex &index, std::string* out_name) {
   128   uint8_t name[256] = {0};
   129   if (index.offsets.size() == 0) {  // just in case.
   130     return OTS_FAILURE();
   131   }
   132   for (unsigned i = 1; i < index.offsets.size(); ++i) {
   133     const size_t length = index.offsets[i] - index.offsets[i - 1];
   134     // font names should be no longer than 127 characters.
   135     if (length > 127) {
   136       return OTS_FAILURE();
   137     }
   139     table->set_offset(index.offsets[i - 1]);
   140     if (!table->Read(name, length)) {
   141       return OTS_FAILURE();
   142     }
   144     for (size_t j = 0; j < length; ++j) {
   145       // setting the first byte to NUL is allowed.
   146       if (j == 0 && name[j] == 0) continue;
   147       // non-ASCII characters are not recommended (except the first character).
   148       if (name[j] < 33 || name[j] > 126) {
   149         return OTS_FAILURE();
   150       }
   151       // [, ], ... are not allowed.
   152       if (std::strchr("[](){}<>/% ", name[j])) {
   153         return OTS_FAILURE();
   154       }
   155     }
   156   }
   158   *out_name = reinterpret_cast<char *>(name);
   159   return true;
   160 }
   162 bool CheckOffset(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand,
   163                  size_t table_length) {
   164   if (operand.second != DICT_OPERAND_INTEGER) {
   165     return OTS_FAILURE();
   166   }
   167   if (operand.first >= table_length) {
   168     return OTS_FAILURE();
   169   }
   170   return true;
   171 }
   173 bool CheckSid(const std::pair<uint32_t, DICT_OPERAND_TYPE>& operand,
   174               size_t sid_max) {
   175   if (operand.second != DICT_OPERAND_INTEGER) {
   176     return OTS_FAILURE();
   177   }
   178   if (operand.first > sid_max) {
   179     return OTS_FAILURE();
   180   }
   181   return true;
   182 }
   184 bool ParseDictDataBcd(
   185     ots::Buffer *table,
   186     std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
   187   bool read_decimal_point = false;
   188   bool read_e = false;
   190   uint8_t nibble = 0;
   191   size_t count = 0;
   192   while (true) {
   193     if (!table->ReadU8(&nibble)) {
   194       return OTS_FAILURE();
   195     }
   196     if ((nibble & 0xf0) == 0xf0) {
   197       if ((nibble & 0xf) == 0xf) {
   198         // TODO(yusukes): would be better to store actual double value,
   199         // rather than the dummy integer.
   200         operands->push_back(std::make_pair(static_cast<uint32_t>(0),
   201                                            DICT_OPERAND_REAL));
   202         return true;
   203       }
   204       return OTS_FAILURE();
   205     }
   206     if ((nibble & 0x0f) == 0x0f) {
   207       operands->push_back(std::make_pair(static_cast<uint32_t>(0),
   208                                          DICT_OPERAND_REAL));
   209       return true;
   210     }
   212     // check number format
   213     uint8_t nibbles[2];
   214     nibbles[0] = (nibble & 0xf0) >> 8;
   215     nibbles[1] = (nibble & 0x0f);
   216     for (unsigned i = 0; i < 2; ++i) {
   217       if (nibbles[i] == 0xd) {  // reserved number
   218         return OTS_FAILURE();
   219       }
   220       if ((nibbles[i] == 0xe) &&  // minus
   221           ((count > 0) || (i > 0))) {
   222         return OTS_FAILURE();  // minus sign should be the first character.
   223       }
   224       if (nibbles[i] == 0xa) {  // decimal point
   225         if (!read_decimal_point) {
   226           read_decimal_point = true;
   227         } else {
   228           return OTS_FAILURE();  // two or more points.
   229         }
   230       }
   231       if ((nibbles[i] == 0xb) ||  // E+
   232           (nibbles[i] == 0xc)) {  // E-
   233         if (!read_e) {
   234           read_e = true;
   235         } else {
   236           return OTS_FAILURE();  // two or more E's.
   237         }
   238       }
   239     }
   240     ++count;
   241   }
   242 }
   244 bool ParseDictDataEscapedOperator(
   245     ots::Buffer *table,
   246     std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
   247   uint8_t op = 0;
   248   if (!table->ReadU8(&op)) {
   249     return OTS_FAILURE();
   250   }
   252   if ((op <= 14) ||
   253       (op >= 17 && op <= 23) ||
   254       (op >= 30 && op <= 38)) {
   255     operands->push_back(std::make_pair((12U << 8) + op, DICT_OPERATOR));
   256     return true;
   257   }
   259   // reserved area.
   260   return OTS_FAILURE();
   261 }
   263 bool ParseDictDataNumber(
   264     ots::Buffer *table, uint8_t b0,
   265     std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
   266   uint8_t b1 = 0;
   267   uint8_t b2 = 0;
   268   uint8_t b3 = 0;
   269   uint8_t b4 = 0;
   271   switch (b0) {
   272     case 28:  // shortint
   273       if (!table->ReadU8(&b1) ||
   274           !table->ReadU8(&b2)) {
   275         return OTS_FAILURE();
   276       }
   277       operands->push_back(std::make_pair(
   278           static_cast<uint32_t>((b1 << 8) + b2), DICT_OPERAND_INTEGER));
   279       return true;
   281     case 29:  // longint
   282       if (!table->ReadU8(&b1) ||
   283           !table->ReadU8(&b2) ||
   284           !table->ReadU8(&b3) ||
   285           !table->ReadU8(&b4)) {
   286         return OTS_FAILURE();
   287       }
   288       operands->push_back(std::make_pair(
   289           static_cast<uint32_t>((b1 << 24) + (b2 << 16) + (b3 << 8) + b4),
   290           DICT_OPERAND_INTEGER));
   291       return true;
   293     case 30:  // binary coded decimal
   294       return ParseDictDataBcd(table, operands);
   296     default:
   297       break;
   298   }
   300   uint32_t result;
   301   if (b0 >=32 && b0 <=246) {
   302     result = b0 - 139;
   303   } else if (b0 >=247 && b0 <= 250) {
   304     if (!table->ReadU8(&b1)) {
   305       return OTS_FAILURE();
   306     }
   307     result = (b0 - 247) * 256 + b1 + 108;
   308   } else if (b0 >= 251 && b0 <= 254) {
   309     if (!table->ReadU8(&b1)) {
   310       return OTS_FAILURE();
   311     }
   312     result = -(b0 - 251) * 256 + b1 - 108;
   313   } else {
   314     return OTS_FAILURE();
   315   }
   317   operands->push_back(std::make_pair(result, DICT_OPERAND_INTEGER));
   318   return true;
   319 }
   321 bool ParseDictDataReadNext(
   322     ots::Buffer *table,
   323     std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > *operands) {
   324   uint8_t op = 0;
   325   if (!table->ReadU8(&op)) {
   326     return OTS_FAILURE();
   327   }
   328   if (op <= 21) {
   329     if (op == 12) {
   330       return ParseDictDataEscapedOperator(table, operands);
   331     }
   332     operands->push_back(std::make_pair(
   333         static_cast<uint32_t>(op), DICT_OPERATOR));
   334     return true;
   335   } else if (op <= 27 || op == 31 || op == 255) {
   336     // reserved area.
   337     return OTS_FAILURE();
   338   }
   340   return ParseDictDataNumber(table, op, operands);
   341 }
   343 bool ParsePrivateDictData(
   344     const uint8_t *data,
   345     size_t table_length, size_t offset, size_t dict_length,
   346     DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) {
   347   ots::Buffer table(data + offset, dict_length);
   348   std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands;
   350   // Since a Private DICT for FDArray might not have a Local Subr (e.g. Hiragino
   351   // Kaku Gothic Std W8), we create an empty Local Subr here to match the size
   352   // of FDArray the size of |local_subrs_per_font|.
   353   if (type == DICT_DATA_FDARRAY) {
   354     out_cff->local_subrs_per_font.push_back(new ots::CFFIndex);
   355   }
   357   while (table.offset() < dict_length) {
   358     if (!ParseDictDataReadNext(&table, &operands)) {
   359       return OTS_FAILURE();
   360     }
   361     if (operands.empty()) {
   362       return OTS_FAILURE();
   363     }
   364     if (operands.size() > 48) {
   365       // An operator may be preceded by up to a maximum of 48 operands.
   366       return OTS_FAILURE();
   367     }
   368     if (operands.back().second != DICT_OPERATOR) {
   369       continue;
   370     }
   372     // got operator
   373     const uint32_t op = operands.back().first;
   374     operands.pop_back();
   376     switch (op) {
   377       // array
   378       case 6:  // BlueValues
   379       case 7:  // OtherBlues
   380       case 8:  // FamilyBlues
   381       case 9:  // FamilyOtherBlues
   382       case (12U << 8) + 12:  // StemSnapH (delta)
   383       case (12U << 8) + 13:  // StemSnapV (delta)
   384         if (operands.empty()) {
   385           return OTS_FAILURE();
   386         }
   387         break;
   389       // number
   390       case 10:  // StdHW
   391       case 11:  // StdVW
   392       case 20:  // defaultWidthX
   393       case 21:  // nominalWidthX
   394       case (12U << 8) + 9:   // BlueScale
   395       case (12U << 8) + 10:  // BlueShift
   396       case (12U << 8) + 11:  // BlueFuzz
   397       case (12U << 8) + 17:  // LanguageGroup
   398       case (12U << 8) + 18:  // ExpansionFactor
   399       case (12U << 8) + 19:  // initialRandomSeed
   400         if (operands.size() != 1) {
   401           return OTS_FAILURE();
   402         }
   403         break;
   405       // Local Subrs INDEX, offset(self)
   406       case 19: {
   407         if (operands.size() != 1) {
   408           return OTS_FAILURE();
   409         }
   410         if (operands.back().second != DICT_OPERAND_INTEGER) {
   411           return OTS_FAILURE();
   412         }
   413         if (operands.back().first >= 1024 * 1024 * 1024) {
   414           return OTS_FAILURE();
   415         }
   416         if (operands.back().first + offset >= table_length) {
   417           return OTS_FAILURE();
   418         }
   419         // parse "16. Local Subrs INDEX"
   420         ots::Buffer cff_table(data, table_length);
   421         cff_table.set_offset(operands.back().first + offset);
   422         ots::CFFIndex *local_subrs_index = NULL;
   423         if (type == DICT_DATA_FDARRAY) {
   424           if (out_cff->local_subrs_per_font.empty()) {
   425             return OTS_FAILURE();  // not reached.
   426           }
   427           local_subrs_index = out_cff->local_subrs_per_font.back();
   428         } else { // type == DICT_DATA_TOPLEVEL
   429           if (out_cff->local_subrs) {
   430             return OTS_FAILURE();  // two or more local_subrs?
   431           }
   432           local_subrs_index = new ots::CFFIndex;
   433           out_cff->local_subrs = local_subrs_index;
   434         }
   435         if (!ParseIndex(&cff_table, local_subrs_index)) {
   436           return OTS_FAILURE();
   437         }
   438         break;
   439       }
   441       // boolean
   442       case (12U << 8) + 14:  // ForceBold
   443         if (operands.size() != 1) {
   444           return OTS_FAILURE();
   445         }
   446         if (operands.back().second != DICT_OPERAND_INTEGER) {
   447           return OTS_FAILURE();
   448         }
   449         if (operands.back().first >= 2) {
   450           return OTS_FAILURE();
   451         }
   452         break;
   454       default:
   455         return OTS_FAILURE();
   456     }
   457     operands.clear();
   458   }
   460   return true;
   461 }
   463 bool ParseDictData(const uint8_t *data, size_t table_length,
   464                    const ots::CFFIndex &index, size_t sid_max,
   465                    DICT_DATA_TYPE type, ots::OpenTypeCFF *out_cff) {
   466   for (unsigned i = 1; i < index.offsets.size(); ++i) {
   467     if (type == DICT_DATA_TOPLEVEL) {
   468       out_cff->char_strings_array.push_back(new ots::CFFIndex);
   469     }
   470     size_t dict_length = index.offsets[i] - index.offsets[i - 1];
   471     ots::Buffer table(data + index.offsets[i - 1], dict_length);
   473     std::vector<std::pair<uint32_t, DICT_OPERAND_TYPE> > operands;
   475     FONT_FORMAT font_format = FORMAT_UNKNOWN;
   476     bool have_ros = false;
   477     size_t glyphs = 0;
   478     size_t charset_offset = 0;
   480     while (table.offset() < dict_length) {
   481       if (!ParseDictDataReadNext(&table, &operands)) {
   482         return OTS_FAILURE();
   483       }
   484       if (operands.empty()) {
   485         return OTS_FAILURE();
   486       }
   487       if (operands.size() > 48) {
   488         // An operator may be preceded by up to a maximum of 48 operands.
   489         return OTS_FAILURE();
   490       }
   491       if (operands.back().second != DICT_OPERATOR) continue;
   493       // got operator
   494       const uint32_t op = operands.back().first;
   495       operands.pop_back();
   497       switch (op) {
   498         // SID
   499         case 0:   // version
   500         case 1:   // Notice
   501         case 2:   // Copyright
   502         case 3:   // FullName
   503         case 4:   // FamilyName
   504         case (12U << 8) + 0:   // Copyright
   505         case (12U << 8) + 21:  // PostScript
   506         case (12U << 8) + 22:  // BaseFontName
   507         case (12U << 8) + 38:  // FontName
   508           if (operands.size() != 1) {
   509             return OTS_FAILURE();
   510           }
   511           if (!CheckSid(operands.back(), sid_max)) {
   512             return OTS_FAILURE();
   513           }
   514           break;
   516         // array
   517         case 5:   // FontBBox
   518         case 14:  // XUID
   519         case (12U << 8) + 7:   // FontMatrix
   520         case (12U << 8) + 23:  // BaseFontBlend (delta)
   521           if (operands.empty()) {
   522             return OTS_FAILURE();
   523           }
   524           break;
   526         // number
   527         case 13:  // UniqueID
   528         case (12U << 8) + 2:   // ItalicAngle
   529         case (12U << 8) + 3:   // UnderlinePosition
   530         case (12U << 8) + 4:   // UnderlineThickness
   531         case (12U << 8) + 5:   // PaintType
   532         case (12U << 8) + 8:   // StrokeWidth
   533         case (12U << 8) + 20:  // SyntheticBase
   534           if (operands.size() != 1) {
   535             return OTS_FAILURE();
   536           }
   537           break;
   538         case (12U << 8) + 31:  // CIDFontVersion
   539         case (12U << 8) + 32:  // CIDFontRevision
   540         case (12U << 8) + 33:  // CIDFontType
   541         case (12U << 8) + 34:  // CIDCount
   542         case (12U << 8) + 35:  // UIDBase
   543           if (operands.size() != 1) {
   544             return OTS_FAILURE();
   545           }
   546           if (font_format != FORMAT_CID_KEYED) {
   547             return OTS_FAILURE();
   548           }
   549           break;
   550         case (12U << 8) + 6:   // CharstringType
   551           if (operands.size() != 1) {
   552             return OTS_FAILURE();
   553           }
   554           if(operands.back().second != DICT_OPERAND_INTEGER) {
   555             return OTS_FAILURE();
   556           }
   557           if (operands.back().first != 2) {
   558             // We only support the "Type 2 Charstring Format."
   559             // TODO(yusukes): Support Type 1 format? Is that still in use?
   560             return OTS_FAILURE();
   561           }
   562           break;
   564         // boolean
   565         case (12U << 8) + 1:   // isFixedPitch
   566           if (operands.size() != 1) {
   567             return OTS_FAILURE();
   568           }
   569           if (operands.back().second != DICT_OPERAND_INTEGER) {
   570             return OTS_FAILURE();
   571           }
   572           if (operands.back().first >= 2) {
   573             return OTS_FAILURE();
   574           }
   575           break;
   577         // offset(0)
   578         case 15:  // charset
   579           if (operands.size() != 1) {
   580             return OTS_FAILURE();
   581           }
   582           if (operands.back().first <= 2) {
   583             // predefined charset, ISOAdobe, Expert or ExpertSubset, is used.
   584             break;
   585           }
   586           if (!CheckOffset(operands.back(), table_length)) {
   587             return OTS_FAILURE();
   588           }
   589           if (charset_offset) {
   590             return OTS_FAILURE();  // multiple charset tables?
   591           }
   592           charset_offset = operands.back().first;
   593           break;
   595         case 16: {  // Encoding
   596           if (operands.size() != 1) {
   597             return OTS_FAILURE();
   598           }
   599           if (operands.back().first <= 1) {
   600             break;  // predefined encoding, "Standard" or "Expert", is used.
   601           }
   602           if (!CheckOffset(operands.back(), table_length)) {
   603             return OTS_FAILURE();
   604           }
   606           // parse sub dictionary INDEX.
   607           ots::Buffer cff_table(data, table_length);
   608           cff_table.set_offset(operands.back().first);
   609           uint8_t format = 0;
   610           if (!cff_table.ReadU8(&format)) {
   611             return OTS_FAILURE();
   612           }
   613           if (format & 0x80) {
   614             // supplemental encoding is not supported at the moment.
   615             return OTS_FAILURE();
   616           }
   617           // TODO(yusukes): support & parse supplemental encoding tables.
   618           break;
   619         }
   621         case 17: {  // CharStrings
   622           if (type != DICT_DATA_TOPLEVEL) {
   623             return OTS_FAILURE();
   624           }
   625           if (operands.size() != 1) {
   626             return OTS_FAILURE();
   627           }
   628           if (!CheckOffset(operands.back(), table_length)) {
   629             return OTS_FAILURE();
   630           }
   631           // parse "14. CharStrings INDEX"
   632           ots::Buffer cff_table(data, table_length);
   633           cff_table.set_offset(operands.back().first);
   634           ots::CFFIndex *charstring_index = out_cff->char_strings_array.back();
   635           if (!ParseIndex(&cff_table, charstring_index)) {
   636             return OTS_FAILURE();
   637           }
   638           if (charstring_index->count < 2) {
   639             return OTS_FAILURE();
   640           }
   641           if (glyphs) {
   642             return OTS_FAILURE();  // multiple charstring tables?
   643           }
   644           glyphs = charstring_index->count;
   645           break;
   646         }
   648         case (12U << 8) + 36: {  // FDArray
   649           if (type != DICT_DATA_TOPLEVEL) {
   650             return OTS_FAILURE();
   651           }
   652           if (operands.size() != 1) {
   653             return OTS_FAILURE();
   654           }
   655           if (!CheckOffset(operands.back(), table_length)) {
   656             return OTS_FAILURE();
   657           }
   659           // parse sub dictionary INDEX.
   660           ots::Buffer cff_table(data, table_length);
   661           cff_table.set_offset(operands.back().first);
   662           ots::CFFIndex sub_dict_index;
   663           if (!ParseIndex(&cff_table, &sub_dict_index)) {
   664             return OTS_FAILURE();
   665           }
   666           if (!ParseDictData(data, table_length,
   667                              sub_dict_index, sid_max, DICT_DATA_FDARRAY,
   668                              out_cff)) {
   669             return OTS_FAILURE();
   670           }
   671           if (out_cff->font_dict_length != 0) {
   672             return OTS_FAILURE();  // two or more FDArray found.
   673           }
   674           out_cff->font_dict_length = sub_dict_index.count;
   675           break;
   676         }
   678         case (12U << 8) + 37: {  // FDSelect
   679           if (type != DICT_DATA_TOPLEVEL) {
   680             return OTS_FAILURE();
   681           }
   682           if (operands.size() != 1) {
   683             return OTS_FAILURE();
   684           }
   685           if (!CheckOffset(operands.back(), table_length)) {
   686             return OTS_FAILURE();
   687           }
   689           // parse FDSelect data structure
   690           ots::Buffer cff_table(data, table_length);
   691           cff_table.set_offset(operands.back().first);
   692           uint8_t format = 0;
   693           if (!cff_table.ReadU8(&format)) {
   694             return OTS_FAILURE();
   695           }
   696           if (format == 0) {
   697             for (size_t j = 0; j < glyphs; ++j) {
   698               uint8_t fd_index = 0;
   699               if (!cff_table.ReadU8(&fd_index)) {
   700                 return OTS_FAILURE();
   701               }
   702               (out_cff->fd_select)[j] = fd_index;
   703             }
   704           } else if (format == 3) {
   705             uint16_t n_ranges = 0;
   706             if (!cff_table.ReadU16(&n_ranges)) {
   707               return OTS_FAILURE();
   708             }
   709             if (n_ranges == 0) {
   710               return OTS_FAILURE();
   711             }
   713             uint16_t last_gid = 0;
   714             uint8_t fd_index = 0;
   715             for (unsigned j = 0; j < n_ranges; ++j) {
   716               uint16_t first = 0;  // GID
   717               if (!cff_table.ReadU16(&first)) {
   718                 return OTS_FAILURE();
   719               }
   721               // Sanity checks.
   722               if ((j == 0) && (first != 0)) {
   723                 return OTS_FAILURE();
   724               }
   725               if ((j != 0) && (last_gid >= first)) {
   726                 return OTS_FAILURE();  // not increasing order.
   727               }
   729               // Copy the mapping to |out_cff->fd_select|.
   730               if (j != 0) {
   731                 for (uint16_t k = last_gid; k < first; ++k) {
   732                   if (!out_cff->fd_select.insert(
   733                           std::make_pair(k, fd_index)).second) {
   734                     return OTS_FAILURE();
   735                   }
   736                 }
   737               }
   739               if (!cff_table.ReadU8(&fd_index)) {
   740                 return OTS_FAILURE();
   741               }
   742               last_gid = first;
   743               // TODO(yusukes): check GID?
   744             }
   745             uint16_t sentinel = 0;
   746             if (!cff_table.ReadU16(&sentinel)) {
   747               return OTS_FAILURE();
   748             }
   749             if (last_gid >= sentinel) {
   750               return OTS_FAILURE();
   751             }
   752             for (uint16_t k = last_gid; k < sentinel; ++k) {
   753               if (!out_cff->fd_select.insert(
   754                       std::make_pair(k, fd_index)).second) {
   755                 return OTS_FAILURE();
   756               }
   757             }
   758           } else {
   759             // unknown format
   760             return OTS_FAILURE();
   761           }
   762           break;
   763         }
   765         // Private DICT (2 * number)
   766         case 18: {
   767           if (operands.size() != 2) {
   768             return OTS_FAILURE();
   769           }
   770           if (operands.back().second != DICT_OPERAND_INTEGER) {
   771             return OTS_FAILURE();
   772           }
   773           const uint32_t private_offset = operands.back().first;
   774           operands.pop_back();
   775           if (operands.back().second != DICT_OPERAND_INTEGER) {
   776             return OTS_FAILURE();
   777           }
   778           const uint32_t private_length = operands.back().first;
   779           if (private_offset > table_length) {
   780             return OTS_FAILURE();
   781           }
   782           if (private_length >= table_length) {
   783             return OTS_FAILURE();
   784           }
   785           if (private_length + private_offset > table_length) {
   786             return OTS_FAILURE();
   787           }
   788           // parse "15. Private DICT Data"
   789           if (!ParsePrivateDictData(data, table_length,
   790                                     private_offset, private_length,
   791                                     type, out_cff)) {
   792             return OTS_FAILURE();
   793           }
   794           break;
   795         }
   797         // ROS
   798         case (12U << 8) + 30:
   799           if (font_format != FORMAT_UNKNOWN) {
   800             return OTS_FAILURE();
   801           }
   802           font_format = FORMAT_CID_KEYED;
   803           if (operands.size() != 3) {
   804             return OTS_FAILURE();
   805           }
   806           // check SIDs
   807           operands.pop_back();  // ignore the first number.
   808           if (!CheckSid(operands.back(), sid_max)) {
   809             return OTS_FAILURE();
   810           }
   811           operands.pop_back();
   812           if (!CheckSid(operands.back(), sid_max)) {
   813             return OTS_FAILURE();
   814           }
   815           if (have_ros) {
   816             return OTS_FAILURE();  // multiple ROS tables?
   817           }
   818           have_ros = true;
   819           break;
   821         default:
   822           return OTS_FAILURE();
   823       }
   824       operands.clear();
   826       if (font_format == FORMAT_UNKNOWN) {
   827         font_format = FORMAT_OTHER;
   828       }
   829     }
   831     // parse "13. Charsets"
   832     if (charset_offset) {
   833       ots::Buffer cff_table(data, table_length);
   834       cff_table.set_offset(charset_offset);
   835       uint8_t format = 0;
   836       if (!cff_table.ReadU8(&format)) {
   837         return OTS_FAILURE();
   838       }
   839       switch (format) {
   840         case 0:
   841           for (unsigned j = 1 /* .notdef is omitted */; j < glyphs; ++j) {
   842             uint16_t sid = 0;
   843             if (!cff_table.ReadU16(&sid)) {
   844               return OTS_FAILURE();
   845             }
   846             if (!have_ros && (sid > sid_max)) {
   847               return OTS_FAILURE();
   848             }
   849             // TODO(yusukes): check CIDs when have_ros is true.
   850           }
   851           break;
   853         case 1:
   854         case 2: {
   855           uint32_t total = 1;  // .notdef is omitted.
   856           while (total < glyphs) {
   857             uint16_t sid = 0;
   858             if (!cff_table.ReadU16(&sid)) {
   859               return OTS_FAILURE();
   860             }
   861             if (!have_ros && (sid > sid_max)) {
   862               return OTS_FAILURE();
   863             }
   864             // TODO(yusukes): check CIDs when have_ros is true.
   866             if (format == 1) {
   867               uint8_t left = 0;
   868               if (!cff_table.ReadU8(&left)) {
   869                 return OTS_FAILURE();
   870               }
   871               total += (left + 1);
   872             } else {
   873               uint16_t left = 0;
   874               if (!cff_table.ReadU16(&left)) {
   875                 return OTS_FAILURE();
   876               }
   877               total += (left + 1);
   878             }
   879           }
   880           break;
   881         }
   883         default:
   884           return OTS_FAILURE();
   885       }
   886     }
   887   }
   888   return true;
   889 }
   891 }  // namespace
   893 namespace ots {
   895 bool ots_cff_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
   896   Buffer table(data, length);
   898   file->cff = new OpenTypeCFF;
   899   file->cff->data = data;
   900   file->cff->length = length;
   901   file->cff->font_dict_length = 0;
   902   file->cff->local_subrs = NULL;
   904   // parse "6. Header" in the Adobe Compact Font Format Specification
   905   uint8_t major = 0;
   906   uint8_t minor = 0;
   907   uint8_t hdr_size = 0;
   908   uint8_t off_size = 0;
   909   if (!table.ReadU8(&major)) {
   910     return OTS_FAILURE();
   911   }
   912   if (!table.ReadU8(&minor)) {
   913     return OTS_FAILURE();
   914   }
   915   if (!table.ReadU8(&hdr_size)) {
   916     return OTS_FAILURE();
   917   }
   918   if (!table.ReadU8(&off_size)) {
   919     return OTS_FAILURE();
   920   }
   921   if ((off_size == 0) || (off_size > 4)) {
   922     return OTS_FAILURE();
   923   }
   925   if ((major != 1) ||
   926       (minor != 0) ||
   927       (hdr_size != 4)) {
   928     return OTS_FAILURE();
   929   }
   930   if (hdr_size >= length) {
   931     return OTS_FAILURE();
   932   }
   934   // parse "7. Name INDEX"
   935   table.set_offset(hdr_size);
   936   CFFIndex name_index;
   937   if (!ParseIndex(&table, &name_index)) {
   938     return OTS_FAILURE();
   939   }
   940   if (!ParseNameData(&table, name_index, &(file->cff->name))) {
   941     return OTS_FAILURE();
   942   }
   944   // parse "8. Top DICT INDEX"
   945   table.set_offset(name_index.offset_to_next);
   946   CFFIndex top_dict_index;
   947   if (!ParseIndex(&table, &top_dict_index)) {
   948     return OTS_FAILURE();
   949   }
   950   if (name_index.count != top_dict_index.count) {
   951     return OTS_FAILURE();
   952   }
   954   // parse "10. String INDEX"
   955   table.set_offset(top_dict_index.offset_to_next);
   956   CFFIndex string_index;
   957   if (!ParseIndex(&table, &string_index)) {
   958     return OTS_FAILURE();
   959   }
   960   if (string_index.count >= 65000 - kNStdString) {
   961     return OTS_FAILURE();
   962   }
   964   const size_t sid_max = string_index.count + kNStdString;
   965   // string_index.count == 0 is allowed.
   967   // parse "9. Top DICT Data"
   968   if (!ParseDictData(data, length, top_dict_index,
   969                      sid_max, DICT_DATA_TOPLEVEL, file->cff)) {
   970     return OTS_FAILURE();
   971   }
   973   // parse "16. Global Subrs INDEX"
   974   table.set_offset(string_index.offset_to_next);
   975   CFFIndex global_subrs_index;
   976   if (!ParseIndex(&table, &global_subrs_index)) {
   977     return OTS_FAILURE();
   978   }
   980   // Check if all fd_index in FDSelect are valid.
   981   std::map<uint16_t, uint8_t>::const_iterator iter;
   982   std::map<uint16_t, uint8_t>::const_iterator end = file->cff->fd_select.end();
   983   for (iter = file->cff->fd_select.begin(); iter != end; ++iter) {
   984     if (iter->second >= file->cff->font_dict_length) {
   985       return OTS_FAILURE();
   986     }
   987   }
   989   // Check if all charstrings (font hinting code for each glyph) are valid.
   990   for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) {
   991     if (!ValidateType2CharStringIndex(*(file->cff->char_strings_array.at(i)),
   992                                       global_subrs_index,
   993                                       file->cff->fd_select,
   994                                       file->cff->local_subrs_per_font,
   995                                       file->cff->local_subrs,
   996                                       &table)) {
   997       return OTS_FAILURE();
   998     }
   999   }
  1001   return true;
  1004 bool ots_cff_should_serialise(OpenTypeFile *file) {
  1005   return file->cff != NULL;
  1008 bool ots_cff_serialise(OTSStream *out, OpenTypeFile *file) {
  1009   // TODO(yusukes): would be better to transcode the data,
  1010   //                rather than simple memcpy.
  1011   if (!out->Write(file->cff->data, file->cff->length)) {
  1012     return OTS_FAILURE();
  1014   return true;
  1017 void ots_cff_free(OpenTypeFile *file) {
  1018   if (file->cff) {
  1019     for (size_t i = 0; i < file->cff->char_strings_array.size(); ++i) {
  1020       delete (file->cff->char_strings_array)[i];
  1022     for (size_t i = 0; i < file->cff->local_subrs_per_font.size(); ++i) {
  1023       delete (file->cff->local_subrs_per_font)[i];
  1025     delete file->cff->local_subrs;
  1026     delete file->cff;
  1030 }  // namespace ots

mercurial