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

       1                 : // Copyright (c) 2011 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 "gdef.h"
       6                 : 
       7                 : #include <limits>
       8                 : #include <vector>
       9                 : 
      10                 : #include "gpos.h"
      11                 : #include "gsub.h"
      12                 : #include "layout.h"
      13                 : #include "maxp.h"
      14                 : 
      15                 : // GDEF - The Glyph Definition Table
      16                 : // http://www.microsoft.com/typography/otspec/gdef.htm
      17                 : 
      18                 : namespace {
      19                 : 
      20                 : // The maximum class value in class definition tables.
      21                 : const uint16_t kMaxClassDefValue = 0xFFFF;
      22                 : // The maximum class value in the glyph class definision table.
      23                 : const uint16_t kMaxGlyphClassDefValue = 4;
      24                 : // The maximum format number of caret value tables.
      25                 : // We don't support format 3 for now. See the comment in
      26                 : // ParseLigCaretListTable() for the reason.
      27                 : const uint16_t kMaxCaretValueFormat = 2;
      28                 : 
      29               0 : bool ParseGlyphClassDefTable(ots::OpenTypeFile *file, const uint8_t *data,
      30                 :                              size_t length, const uint16_t num_glyphs) {
      31                 :   return ots::ParseClassDefTable(data, length, num_glyphs,
      32               0 :                                  kMaxGlyphClassDefValue);
      33                 : }
      34                 : 
      35               0 : bool ParseAttachListTable(ots::OpenTypeFile *file, const uint8_t *data,
      36                 :                           size_t length, const uint16_t num_glyphs) {
      37               0 :   ots::Buffer subtable(data, length);
      38                 : 
      39               0 :   uint16_t offset_coverage = 0;
      40               0 :   uint16_t glyph_count = 0;
      41               0 :   if (!subtable.ReadU16(&offset_coverage) ||
      42               0 :       !subtable.ReadU16(&glyph_count)) {
      43               0 :     return OTS_FAILURE();
      44                 :   }
      45                 :   const unsigned attach_points_end =
      46               0 :       2 * static_cast<unsigned>(glyph_count) + 4;
      47               0 :   if (attach_points_end > std::numeric_limits<uint16_t>::max()) {
      48               0 :     return OTS_FAILURE();
      49                 :   }
      50               0 :   if (offset_coverage == 0 || offset_coverage >= length ||
      51                 :       offset_coverage < attach_points_end) {
      52               0 :     return OTS_FAILURE();
      53                 :   }
      54               0 :   if (glyph_count > num_glyphs) {
      55                 :     OTS_WARNING("bad glyph count: %u", glyph_count);
      56               0 :     return OTS_FAILURE();
      57                 :   }
      58                 : 
      59               0 :   std::vector<uint16_t> attach_points;
      60               0 :   attach_points.resize(glyph_count);
      61               0 :   for (unsigned i = 0; i < glyph_count; ++i) {
      62               0 :     if (!subtable.ReadU16(&attach_points[i])) {
      63               0 :       return OTS_FAILURE();
      64                 :     }
      65               0 :     if (attach_points[i] >= length ||
      66               0 :         attach_points[i] < attach_points_end) {
      67               0 :       return OTS_FAILURE();
      68                 :     }
      69                 :   }
      70                 : 
      71                 :   // Parse coverage table
      72               0 :   if (!ots::ParseCoverageTable(data + offset_coverage,
      73               0 :                                length - offset_coverage, num_glyphs)) {
      74               0 :     return OTS_FAILURE();
      75                 :   }
      76                 : 
      77                 :   // Parse attach point table
      78               0 :   for (unsigned i = 0; i < attach_points.size(); ++i) {
      79               0 :     subtable.set_offset(attach_points[i]);
      80               0 :     uint16_t point_count = 0;
      81               0 :     if (!subtable.ReadU16(&point_count)) {
      82               0 :       return OTS_FAILURE();
      83                 :     }
      84               0 :     if (point_count == 0) {
      85               0 :       return OTS_FAILURE();
      86                 :     }
      87               0 :     uint16_t last_point_index = 0;
      88               0 :     uint16_t point_index = 0;
      89               0 :     for (unsigned j = 0; j < point_count; ++j) {
      90               0 :       if (!subtable.ReadU16(&point_index)) {
      91               0 :         return OTS_FAILURE();
      92                 :       }
      93                 :       // Contour point indeces are in increasing numerical order
      94               0 :       if (last_point_index != 0 && last_point_index >= point_index) {
      95                 :         OTS_WARNING("bad contour indeces: %u >= %u",
      96                 :                     last_point_index, point_index);
      97               0 :         return OTS_FAILURE();
      98                 :       }
      99               0 :       last_point_index = point_index;
     100                 :     }
     101                 :   }
     102               0 :   return true;
     103                 : }
     104                 : 
     105               0 : bool ParseLigCaretListTable(ots::OpenTypeFile *file, const uint8_t *data,
     106                 :                             size_t length, const uint16_t num_glyphs) {
     107               0 :   ots::Buffer subtable(data, length);
     108               0 :   uint16_t offset_coverage = 0;
     109               0 :   uint16_t lig_glyph_count = 0;
     110               0 :   if (!subtable.ReadU16(&offset_coverage) ||
     111               0 :       !subtable.ReadU16(&lig_glyph_count)) {
     112               0 :     return OTS_FAILURE();
     113                 :   }
     114                 :   const unsigned lig_glyphs_end =
     115               0 :       2 * static_cast<unsigned>(lig_glyph_count) + 4;
     116               0 :   if (lig_glyphs_end > std::numeric_limits<uint16_t>::max()) {
     117               0 :     return OTS_FAILURE();
     118                 :   }
     119               0 :   if (offset_coverage == 0 || offset_coverage >= length ||
     120                 :       offset_coverage < lig_glyphs_end) {
     121               0 :     return OTS_FAILURE();
     122                 :   }
     123               0 :   if (lig_glyph_count > num_glyphs) {
     124                 :     OTS_WARNING("bad ligature glyph count: %u", lig_glyph_count);
     125               0 :     return OTS_FAILURE();
     126                 :   }
     127                 : 
     128               0 :   std::vector<uint16_t> lig_glyphs;
     129               0 :   lig_glyphs.resize(lig_glyph_count);
     130               0 :   for (unsigned i = 0; i < lig_glyph_count; ++i) {
     131               0 :     if (!subtable.ReadU16(&lig_glyphs[i])) {
     132               0 :       return OTS_FAILURE();
     133                 :     }
     134               0 :     if (lig_glyphs[i] >= length || lig_glyphs[i] < lig_glyphs_end) {
     135               0 :       return OTS_FAILURE();
     136                 :     }
     137                 :   }
     138                 : 
     139                 :   // Parse coverage table
     140               0 :   if (!ots::ParseCoverageTable(data + offset_coverage,
     141               0 :                                length - offset_coverage, num_glyphs)) {
     142               0 :     return OTS_FAILURE();
     143                 :   }
     144                 : 
     145                 :   // Parse ligature glyph table
     146               0 :   for (unsigned i = 0; i < lig_glyphs.size(); ++i) {
     147               0 :     subtable.set_offset(lig_glyphs[i]);
     148               0 :     uint16_t caret_count = 0;
     149               0 :     if (!subtable.ReadU16(&caret_count)) {
     150               0 :       return OTS_FAILURE();
     151                 :     }
     152               0 :     if (caret_count == 0) {
     153                 :       OTS_WARNING("bad caret value count: %u", caret_count);
     154               0 :       return OTS_FAILURE();
     155                 :     }
     156                 : 
     157               0 :     std::vector<uint16_t> caret_values;
     158               0 :     caret_values.resize(caret_count);
     159               0 :     uint16_t last_offset_caret = 0;
     160               0 :     unsigned caret_values_end = 2 * static_cast<unsigned>(caret_count) + 2;
     161               0 :     for (unsigned j = 0; j < caret_count; ++j) {
     162               0 :       if (!subtable.ReadU16(&caret_values[j])) {
     163               0 :         return OTS_FAILURE();
     164                 :       }
     165               0 :       if (caret_values[j] >= length || caret_values[j] < caret_values_end) {
     166               0 :         return OTS_FAILURE();
     167                 :       }
     168                 :       // Caret offsets are in increasing coordinate order
     169               0 :       if (last_offset_caret != 0 && last_offset_caret >= caret_values[j]) {
     170                 :         OTS_WARNING("offset isn't in increasing coordinate order: %u >= %u",
     171                 :                     last_offset_caret, caret_values[j]);
     172               0 :         return OTS_FAILURE();
     173                 :       }
     174               0 :       last_offset_caret = caret_values[j];
     175                 :     }
     176                 : 
     177                 :     // Parse caret values table
     178               0 :     for (unsigned j = 0; j < caret_count; ++j) {
     179               0 :       subtable.set_offset(lig_glyphs[i] + caret_values[j]);
     180               0 :       uint16_t caret_format = 0;
     181               0 :       if (!subtable.ReadU16(&caret_format)) {
     182               0 :         return OTS_FAILURE();
     183                 :       }
     184                 :       // TODO(bashi): We only support caret value format 1 and 2 for now
     185                 :       // because there are no fonts which contain caret value format 3
     186                 :       // as far as we investigated.
     187               0 :       if (caret_format == 0 || caret_format > kMaxCaretValueFormat) {
     188                 :         OTS_WARNING("bad caret value format: %u", caret_format);
     189               0 :         return OTS_FAILURE();
     190                 :       }
     191                 :       // CaretValueFormats contain a 2-byte field which could be
     192                 :       // arbitrary value.
     193               0 :       if (!subtable.Skip(2)) {
     194               0 :         return OTS_FAILURE();
     195                 :       }
     196                 :     }
     197                 :   }
     198               0 :   return true;
     199                 : }
     200                 : 
     201               0 : bool ParseMarkAttachClassDefTable(ots::OpenTypeFile *file, const uint8_t *data,
     202                 :                                   size_t length, const uint16_t num_glyphs) {
     203               0 :   return ots::ParseClassDefTable(data, length, num_glyphs, kMaxClassDefValue);
     204                 : }
     205                 : 
     206               0 : bool ParseMarkGlyphSetsDefTable(ots::OpenTypeFile *file, const uint8_t *data,
     207                 :                                 size_t length, const uint16_t num_glyphs) {
     208               0 :   ots::Buffer subtable(data, length);
     209               0 :   uint16_t format = 0;
     210               0 :   uint16_t mark_set_count = 0;
     211               0 :   if (!subtable.ReadU16(&format) ||
     212               0 :       !subtable.ReadU16(&mark_set_count)) {
     213               0 :     return OTS_FAILURE();
     214                 :   }
     215               0 :   if (format != 1) {
     216                 :     OTS_WARNING("bad mark glyph set table format: %u", format);
     217               0 :     return OTS_FAILURE();
     218                 :   }
     219                 : 
     220               0 :   const unsigned mark_sets_end = 2 * static_cast<unsigned>(mark_set_count) + 4;
     221               0 :   if (mark_sets_end > std::numeric_limits<uint16_t>::max()) {
     222               0 :     return OTS_FAILURE();
     223                 :   }
     224               0 :   for (unsigned i = 0; i < mark_set_count; ++i) {
     225               0 :     uint32_t offset_coverage = 0;
     226               0 :     if (!subtable.ReadU32(&offset_coverage)) {
     227               0 :       return OTS_FAILURE();
     228                 :     }
     229               0 :     if (offset_coverage >= length ||
     230                 :         offset_coverage < mark_sets_end) {
     231               0 :       return OTS_FAILURE();
     232                 :     }
     233               0 :     if (!ots::ParseCoverageTable(data + offset_coverage,
     234               0 :                                  length - offset_coverage, num_glyphs)) {
     235               0 :       return OTS_FAILURE();
     236                 :     }
     237                 :   }
     238               0 :   file->gdef->num_mark_glyph_sets = mark_set_count;
     239               0 :   return true;
     240                 : }
     241                 : 
     242                 : }  // namespace
     243                 : 
     244                 : #define DROP_THIS_TABLE \
     245                 :   do { file->gdef->data = 0; file->gdef->length = 0; } while (0)
     246                 : 
     247                 : namespace ots {
     248                 : 
     249               0 : bool ots_gdef_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
     250                 :   // Grab the number of glyphs in the file from the maxp table to check
     251                 :   // GlyphIDs in GDEF table.
     252               0 :   if (!file->maxp) {
     253               0 :     return OTS_FAILURE();
     254                 :   }
     255               0 :   const uint16_t num_glyphs = file->maxp->num_glyphs;
     256                 : 
     257               0 :   Buffer table(data, length);
     258                 : 
     259               0 :   OpenTypeGDEF *gdef = new OpenTypeGDEF;
     260               0 :   file->gdef = gdef;
     261                 : 
     262               0 :   uint32_t version = 0;
     263               0 :   if (!table.ReadU32(&version)) {
     264               0 :     return OTS_FAILURE();
     265                 :   }
     266               0 :   if (version < 0x00010000 || version == 0x00010001) {
     267                 :     OTS_WARNING("bad GDEF version");
     268               0 :     DROP_THIS_TABLE;
     269               0 :     return true;
     270                 :   }
     271                 : 
     272               0 :   if (version >= 0x00010002) {
     273               0 :     gdef->version_2 = true;
     274                 :   }
     275                 : 
     276               0 :   uint16_t offset_glyph_class_def = 0;
     277               0 :   uint16_t offset_attach_list = 0;
     278               0 :   uint16_t offset_lig_caret_list = 0;
     279               0 :   uint16_t offset_mark_attach_class_def = 0;
     280               0 :   if (!table.ReadU16(&offset_glyph_class_def) ||
     281               0 :       !table.ReadU16(&offset_attach_list) ||
     282               0 :       !table.ReadU16(&offset_lig_caret_list) ||
     283               0 :       !table.ReadU16(&offset_mark_attach_class_def)) {
     284               0 :     return OTS_FAILURE();
     285                 :   }
     286               0 :   uint16_t offset_mark_glyph_sets_def = 0;
     287               0 :   if (gdef->version_2) {
     288               0 :     if (!table.ReadU16(&offset_mark_glyph_sets_def)) {
     289               0 :       return OTS_FAILURE();
     290                 :     }
     291                 :   }
     292                 : 
     293               0 :   unsigned gdef_header_end = 8;
     294               0 :   if (gdef->version_2)
     295               0 :     gdef_header_end += 2;
     296                 : 
     297                 :   // Parse subtables
     298               0 :   if (offset_glyph_class_def) {
     299               0 :     if (offset_glyph_class_def >= length ||
     300                 :         offset_glyph_class_def < gdef_header_end) {
     301               0 :       return OTS_FAILURE();
     302                 :     }
     303               0 :     if (!ParseGlyphClassDefTable(file, data + offset_glyph_class_def,
     304                 :                                  length - offset_glyph_class_def,
     305               0 :                                  num_glyphs)) {
     306               0 :       DROP_THIS_TABLE;
     307               0 :       return true;
     308                 :     }
     309               0 :     gdef->has_glyph_class_def = true;
     310                 :   }
     311                 : 
     312               0 :   if (offset_attach_list) {
     313               0 :     if (offset_attach_list >= length ||
     314                 :         offset_attach_list < gdef_header_end) {
     315               0 :       return OTS_FAILURE();
     316                 :     }
     317               0 :     if (!ParseAttachListTable(file, data + offset_attach_list,
     318                 :                               length - offset_attach_list,
     319               0 :                               num_glyphs)) {
     320               0 :       DROP_THIS_TABLE;
     321               0 :       return true;
     322                 :     }
     323                 :   }
     324                 : 
     325               0 :   if (offset_lig_caret_list) {
     326               0 :     if (offset_lig_caret_list >= length ||
     327                 :         offset_lig_caret_list < gdef_header_end) {
     328               0 :       return OTS_FAILURE();
     329                 :     }
     330               0 :     if (!ParseLigCaretListTable(file, data + offset_lig_caret_list,
     331                 :                               length - offset_lig_caret_list,
     332               0 :                               num_glyphs)) {
     333               0 :       DROP_THIS_TABLE;
     334               0 :       return true;
     335                 :     }
     336                 :   }
     337                 : 
     338               0 :   if (offset_mark_attach_class_def) {
     339               0 :     if (offset_mark_attach_class_def >= length ||
     340                 :         offset_mark_attach_class_def < gdef_header_end) {
     341               0 :       return OTS_FAILURE();
     342                 :     }
     343               0 :     if (!ParseMarkAttachClassDefTable(file,
     344                 :                                       data + offset_mark_attach_class_def,
     345                 :                                       length - offset_mark_attach_class_def,
     346               0 :                                       num_glyphs)) {
     347               0 :       DROP_THIS_TABLE;
     348               0 :       return true;
     349                 :     }
     350               0 :     gdef->has_mark_attachment_class_def = true;
     351                 :   }
     352                 : 
     353               0 :   if (offset_mark_glyph_sets_def) {
     354               0 :     if (offset_mark_glyph_sets_def >= length ||
     355                 :         offset_mark_glyph_sets_def < gdef_header_end) {
     356               0 :       return OTS_FAILURE();
     357                 :     }
     358               0 :     if (!ParseMarkGlyphSetsDefTable(file,
     359                 :                                     data + offset_mark_glyph_sets_def,
     360                 :                                     length - offset_mark_glyph_sets_def,
     361               0 :                                     num_glyphs)) {
     362               0 :       DROP_THIS_TABLE;
     363               0 :       return true;
     364                 :     }
     365               0 :     gdef->has_mark_glyph_sets_def = true;
     366                 :   }
     367               0 :   gdef->data = data;
     368               0 :   gdef->length = length;
     369               0 :   return true;
     370                 : }
     371                 : 
     372               0 : bool ots_gdef_should_serialise(OpenTypeFile *file) {
     373                 :   const bool needed_tables_dropped =
     374                 :       (file->gsub && file->gsub->data == NULL) ||
     375               0 :       (file->gpos && file->gpos->data == NULL);
     376                 :   return file->gdef != NULL && file->gdef->data != NULL &&
     377               0 :       !needed_tables_dropped;
     378                 : }
     379                 : 
     380               0 : bool ots_gdef_serialise(OTSStream *out, OpenTypeFile *file) {
     381               0 :   if (!out->Write(file->gdef->data, file->gdef->length)) {
     382               0 :     return OTS_FAILURE();
     383                 :   }
     384                 : 
     385               0 :   return true;
     386                 : }
     387                 : 
     388               0 : void ots_gdef_free(OpenTypeFile *file) {
     389               0 :   delete file->gdef;
     390               0 : }
     391                 : 
     392                 : }  // namespace ots
     393                 : 

Generated by: LCOV version 1.7