LCOV - code coverage report
Current view: top level - gfx/ots/src - gdef.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 197 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 10 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13