LCOV - code coverage report
Current view: directory - gfx/ots/src - cff.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 519 0 0.0 %
Date: 2012-06-02 Functions: 15 0 0.0 %

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

Generated by: LCOV version 1.7