gfx/ots/src/gdef.cc

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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.
     5 #include "gdef.h"
     7 #include <limits>
     8 #include <vector>
    10 #include "gpos.h"
    11 #include "gsub.h"
    12 #include "layout.h"
    13 #include "maxp.h"
    15 // GDEF - The Glyph Definition Table
    16 // http://www.microsoft.com/typography/otspec/gdef.htm
    18 #define TABLE_NAME "GDEF"
    20 namespace {
    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;
    31 bool ParseGlyphClassDefTable(ots::OpenTypeFile *file, const uint8_t *data,
    32                              size_t length, const uint16_t num_glyphs) {
    33   return ots::ParseClassDefTable(file, data, length, num_glyphs,
    34                                  kMaxGlyphClassDefValue);
    35 }
    37 bool ParseAttachListTable(ots::OpenTypeFile *file, const uint8_t *data,
    38                           size_t length, const uint16_t num_glyphs) {
    39   ots::Buffer subtable(data, length);
    41   uint16_t offset_coverage = 0;
    42   uint16_t glyph_count = 0;
    43   if (!subtable.ReadU16(&offset_coverage) ||
    44       !subtable.ReadU16(&glyph_count)) {
    45     return OTS_FAILURE_MSG("Failed to read gdef header");
    46   }
    47   const unsigned attach_points_end =
    48       2 * static_cast<unsigned>(glyph_count) + 4;
    49   if (attach_points_end > std::numeric_limits<uint16_t>::max()) {
    50     return OTS_FAILURE_MSG("Bad glyph count in gdef");
    51   }
    52   if (offset_coverage == 0 || offset_coverage >= length ||
    53       offset_coverage < attach_points_end) {
    54     return OTS_FAILURE_MSG("Bad coverage offset %d", offset_coverage);
    55   }
    56   if (glyph_count > num_glyphs) {
    57     return OTS_FAILURE_MSG("Bad glyph count %u", glyph_count);
    58   }
    60   std::vector<uint16_t> attach_points;
    61   attach_points.resize(glyph_count);
    62   for (unsigned i = 0; i < glyph_count; ++i) {
    63     if (!subtable.ReadU16(&attach_points[i])) {
    64       return OTS_FAILURE_MSG("Can't read attachment point %d", i);
    65     }
    66     if (attach_points[i] >= length ||
    67         attach_points[i] < attach_points_end) {
    68       return OTS_FAILURE_MSG("Bad attachment point %d of %d", i, attach_points[i]);
    69     }
    70   }
    72   // Parse coverage table
    73   if (!ots::ParseCoverageTable(file, data + offset_coverage,
    74                                length - offset_coverage, num_glyphs)) {
    75     return OTS_FAILURE_MSG("Bad coverage table");
    76   }
    78   // Parse attach point table
    79   for (unsigned i = 0; i < attach_points.size(); ++i) {
    80     subtable.set_offset(attach_points[i]);
    81     uint16_t point_count = 0;
    82     if (!subtable.ReadU16(&point_count)) {
    83       return OTS_FAILURE_MSG("Can't read point count %d", i);
    84     }
    85     if (point_count == 0) {
    86       return OTS_FAILURE_MSG("zero point count %d", i);
    87     }
    88     uint16_t last_point_index = 0;
    89     uint16_t point_index = 0;
    90     for (unsigned j = 0; j < point_count; ++j) {
    91       if (!subtable.ReadU16(&point_index)) {
    92         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       if (last_point_index != 0 && last_point_index >= point_index) {
    96         return OTS_FAILURE_MSG("bad contour indeces: %u >= %u",
    97                     last_point_index, point_index);
    98       }
    99       last_point_index = point_index;
   100     }
   101   }
   102   return true;
   103 }
   105 bool ParseLigCaretListTable(ots::OpenTypeFile *file, const uint8_t *data,
   106                             size_t length, const uint16_t num_glyphs) {
   107   ots::Buffer subtable(data, length);
   108   uint16_t offset_coverage = 0;
   109   uint16_t lig_glyph_count = 0;
   110   if (!subtable.ReadU16(&offset_coverage) ||
   111       !subtable.ReadU16(&lig_glyph_count)) {
   112     return OTS_FAILURE_MSG("Can't read caret structure");
   113   }
   114   const unsigned lig_glyphs_end =
   115       2 * static_cast<unsigned>(lig_glyph_count) + 4;
   116   if (lig_glyphs_end > std::numeric_limits<uint16_t>::max()) {
   117     return OTS_FAILURE_MSG("Bad caret structure");
   118   }
   119   if (offset_coverage == 0 || offset_coverage >= length ||
   120       offset_coverage < lig_glyphs_end) {
   121     return OTS_FAILURE_MSG("Bad caret coverate offset %d", offset_coverage);
   122   }
   123   if (lig_glyph_count > num_glyphs) {
   124     return OTS_FAILURE_MSG("bad ligature glyph count: %u", lig_glyph_count);
   125   }
   127   std::vector<uint16_t> lig_glyphs;
   128   lig_glyphs.resize(lig_glyph_count);
   129   for (unsigned i = 0; i < lig_glyph_count; ++i) {
   130     if (!subtable.ReadU16(&lig_glyphs[i])) {
   131       return OTS_FAILURE_MSG("Can't read ligature glyph location %d", i);
   132     }
   133     if (lig_glyphs[i] >= length || lig_glyphs[i] < lig_glyphs_end) {
   134       return OTS_FAILURE_MSG("Bad ligature glyph location %d in glyph %d", lig_glyphs[i], i);
   135     }
   136   }
   138   // Parse coverage table
   139   if (!ots::ParseCoverageTable(file, data + offset_coverage,
   140                                length - offset_coverage, num_glyphs)) {
   141     return OTS_FAILURE_MSG("Can't parse caret coverage table");
   142   }
   144   // Parse ligature glyph table
   145   for (unsigned i = 0; i < lig_glyphs.size(); ++i) {
   146     subtable.set_offset(lig_glyphs[i]);
   147     uint16_t caret_count = 0;
   148     if (!subtable.ReadU16(&caret_count)) {
   149       return OTS_FAILURE_MSG("Can't read caret count for glyph %d", i);
   150     }
   151     if (caret_count == 0) {
   152       return OTS_FAILURE_MSG("bad caret value count: %u", caret_count);
   153     }
   155     std::vector<uint16_t> caret_value_offsets;
   156     caret_value_offsets.resize(caret_count);
   157     unsigned caret_value_offsets_end = 2 * static_cast<unsigned>(caret_count) + 2;
   158     for (unsigned j = 0; j < caret_count; ++j) {
   159       if (!subtable.ReadU16(&caret_value_offsets[j])) {
   160         return OTS_FAILURE_MSG("Can't read caret offset %d for glyph %d", j, i);
   161       }
   162       if (caret_value_offsets[j] >= length || caret_value_offsets[j] < caret_value_offsets_end) {
   163         return OTS_FAILURE_MSG("Bad caret offset %d for caret %d glyph %d", caret_value_offsets[j], j, i);
   164       }
   165     }
   167     // Parse caret values table
   168     for (unsigned j = 0; j < caret_count; ++j) {
   169       subtable.set_offset(lig_glyphs[i] + caret_value_offsets[j]);
   170       uint16_t caret_format = 0;
   171       if (!subtable.ReadU16(&caret_format)) {
   172         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       if (caret_format == 0 || caret_format > kMaxCaretValueFormat) {
   178         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       if (!subtable.Skip(2)) {
   183         return OTS_FAILURE_MSG("Bad caret value table structure %d in glyph %d", j, i);
   184       }
   185     }
   186   }
   187   return true;
   188 }
   190 bool ParseMarkAttachClassDefTable(ots::OpenTypeFile *file, const uint8_t *data,
   191                                   size_t length, const uint16_t num_glyphs) {
   192   return ots::ParseClassDefTable(file, data, length, num_glyphs, kMaxClassDefValue);
   193 }
   195 bool ParseMarkGlyphSetsDefTable(ots::OpenTypeFile *file, const uint8_t *data,
   196                                 size_t length, const uint16_t num_glyphs) {
   197   ots::Buffer subtable(data, length);
   198   uint16_t format = 0;
   199   uint16_t mark_set_count = 0;
   200   if (!subtable.ReadU16(&format) ||
   201       !subtable.ReadU16(&mark_set_count)) {
   202     return OTS_FAILURE_MSG("Can' read mark glyph table structure");
   203   }
   204   if (format != 1) {
   205     return OTS_FAILURE_MSG("bad mark glyph set table format: %u", format);
   206   }
   208   const unsigned mark_sets_end = 2 * static_cast<unsigned>(mark_set_count) + 4;
   209   if (mark_sets_end > std::numeric_limits<uint16_t>::max()) {
   210     return OTS_FAILURE_MSG("Bad mark_set %d", mark_sets_end);
   211   }
   212   for (unsigned i = 0; i < mark_set_count; ++i) {
   213     uint32_t offset_coverage = 0;
   214     if (!subtable.ReadU32(&offset_coverage)) {
   215       return OTS_FAILURE_MSG("Can't read covrage location for mark set %d", i);
   216     }
   217     if (offset_coverage >= length ||
   218         offset_coverage < mark_sets_end) {
   219       return OTS_FAILURE_MSG("Bad coverage location %d for mark set %d", offset_coverage, i);
   220     }
   221     if (!ots::ParseCoverageTable(file, data + offset_coverage,
   222                                  length - offset_coverage, num_glyphs)) {
   223       return OTS_FAILURE_MSG("Failed to parse coverage table for mark set %d", i);
   224     }
   225   }
   226   file->gdef->num_mark_glyph_sets = mark_set_count;
   227   return true;
   228 }
   230 }  // namespace
   232 #define DROP_THIS_TABLE(msg_) \
   233   do { \
   234     file->gdef->data = 0; \
   235     file->gdef->length = 0; \
   236     OTS_FAILURE_MSG(msg_ ", table discarded"); \
   237   } while (0)
   239 namespace ots {
   241 bool ots_gdef_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
   242   // Grab the number of glyphs in the file from the maxp table to check
   243   // GlyphIDs in GDEF table.
   244   if (!file->maxp) {
   245     return OTS_FAILURE_MSG("No maxp table in font, needed by GDEF");
   246   }
   247   const uint16_t num_glyphs = file->maxp->num_glyphs;
   249   Buffer table(data, length);
   251   OpenTypeGDEF *gdef = new OpenTypeGDEF;
   252   file->gdef = gdef;
   254   uint32_t version = 0;
   255   if (!table.ReadU32(&version)) {
   256     DROP_THIS_TABLE("Incomplete table");
   257     return true;
   258   }
   259   if (version < 0x00010000 || version == 0x00010001) {
   260     DROP_THIS_TABLE("Bad version");
   261     return true;
   262   }
   264   if (version >= 0x00010002) {
   265     gdef->version_2 = true;
   266   }
   268   uint16_t offset_glyph_class_def = 0;
   269   uint16_t offset_attach_list = 0;
   270   uint16_t offset_lig_caret_list = 0;
   271   uint16_t offset_mark_attach_class_def = 0;
   272   if (!table.ReadU16(&offset_glyph_class_def) ||
   273       !table.ReadU16(&offset_attach_list) ||
   274       !table.ReadU16(&offset_lig_caret_list) ||
   275       !table.ReadU16(&offset_mark_attach_class_def)) {
   276     DROP_THIS_TABLE("Incomplete table");
   277     return true;
   278   }
   279   uint16_t offset_mark_glyph_sets_def = 0;
   280   if (gdef->version_2) {
   281     if (!table.ReadU16(&offset_mark_glyph_sets_def)) {
   282       DROP_THIS_TABLE("Incomplete table");
   283       return true;
   284     }
   285   }
   287   unsigned gdef_header_end = 4 + 4 * 2;
   288   if (gdef->version_2)
   289     gdef_header_end += 2;
   291   // Parse subtables
   292   if (offset_glyph_class_def) {
   293     if (offset_glyph_class_def >= length ||
   294         offset_glyph_class_def < gdef_header_end) {
   295       DROP_THIS_TABLE("Invalid offset to glyph classes");
   296       return true;
   297     }
   298     if (!ParseGlyphClassDefTable(file, data + offset_glyph_class_def,
   299                                  length - offset_glyph_class_def,
   300                                  num_glyphs)) {
   301       DROP_THIS_TABLE("Invalid glyph classes");
   302       return true;
   303     }
   304     gdef->has_glyph_class_def = true;
   305   }
   307   if (offset_attach_list) {
   308     if (offset_attach_list >= length ||
   309         offset_attach_list < gdef_header_end) {
   310       DROP_THIS_TABLE("Invalid offset to attachment list");
   311       return true;
   312     }
   313     if (!ParseAttachListTable(file, data + offset_attach_list,
   314                               length - offset_attach_list,
   315                               num_glyphs)) {
   316       DROP_THIS_TABLE("Invalid attachment list");
   317       return true;
   318     }
   319   }
   321   if (offset_lig_caret_list) {
   322     if (offset_lig_caret_list >= length ||
   323         offset_lig_caret_list < gdef_header_end) {
   324       DROP_THIS_TABLE("Invalid offset to ligature caret list");
   325       return true;
   326     }
   327     if (!ParseLigCaretListTable(file, data + offset_lig_caret_list,
   328                               length - offset_lig_caret_list,
   329                               num_glyphs)) {
   330       DROP_THIS_TABLE("Invalid ligature caret list");
   331       return true;
   332     }
   333   }
   335   if (offset_mark_attach_class_def) {
   336     if (offset_mark_attach_class_def >= length ||
   337         offset_mark_attach_class_def < gdef_header_end) {
   338       return OTS_FAILURE_MSG("Invalid offset to mark attachment list");
   339     }
   340     if (!ParseMarkAttachClassDefTable(file,
   341                                       data + offset_mark_attach_class_def,
   342                                       length - offset_mark_attach_class_def,
   343                                       num_glyphs)) {
   344       DROP_THIS_TABLE("Invalid mark attachment list");
   345       return true;
   346     }
   347     gdef->has_mark_attachment_class_def = true;
   348   }
   350   if (offset_mark_glyph_sets_def) {
   351     if (offset_mark_glyph_sets_def >= length ||
   352         offset_mark_glyph_sets_def < gdef_header_end) {
   353       return OTS_FAILURE_MSG("invalid offset to mark glyph sets");
   354     }
   355     if (!ParseMarkGlyphSetsDefTable(file,
   356                                     data + offset_mark_glyph_sets_def,
   357                                     length - offset_mark_glyph_sets_def,
   358                                     num_glyphs)) {
   359       DROP_THIS_TABLE("Invalid mark glyph sets");
   360       return true;
   361     }
   362     gdef->has_mark_glyph_sets_def = true;
   363   }
   364   gdef->data = data;
   365   gdef->length = length;
   366   return true;
   367 }
   369 bool ots_gdef_should_serialise(OpenTypeFile *file) {
   370   return file->gdef != NULL && file->gdef->data != NULL;
   371 }
   373 bool ots_gdef_serialise(OTSStream *out, OpenTypeFile *file) {
   374   if (!out->Write(file->gdef->data, file->gdef->length)) {
   375     return OTS_FAILURE_MSG("Failed to write GDEF table");
   376   }
   378   return true;
   379 }
   381 void ots_gdef_free(OpenTypeFile *file) {
   382   delete file->gdef;
   383 }
   385 }  // namespace ots

mercurial