LCOV - code coverage report
Current view: directory - gfx/ots/src - kern.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 105 0 0.0 %
Date: 2012-06-02 Functions: 4 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 "kern.h"
       6                 : 
       7                 : // kern - Kerning
       8                 : // http://www.microsoft.com/opentype/otspec/kern.htm
       9                 : 
      10                 : #define DROP_THIS_TABLE \
      11                 :   do { delete file->kern; file->kern = 0; } while (0)
      12                 : 
      13                 : namespace ots {
      14                 : 
      15               0 : bool ots_kern_parse(OpenTypeFile *file, const uint8_t *data, size_t length) {
      16               0 :   Buffer table(data, length);
      17                 : 
      18               0 :   OpenTypeKERN *kern = new OpenTypeKERN;
      19               0 :   file->kern = kern;
      20                 : 
      21               0 :   uint16_t num_tables = 0;
      22               0 :   if (!table.ReadU16(&kern->version) ||
      23               0 :       !table.ReadU16(&num_tables)) {
      24               0 :     return OTS_FAILURE();
      25                 :   }
      26                 : 
      27               0 :   if (kern->version > 0) {
      28               0 :     DROP_THIS_TABLE;
      29               0 :     return true;
      30                 :   }
      31                 : 
      32               0 :   if (num_tables == 0) {
      33                 :     OTS_WARNING("num_tables is zero");
      34               0 :     DROP_THIS_TABLE;
      35               0 :     return true;
      36                 :   }
      37                 : 
      38               0 :   kern->subtables.reserve(num_tables);
      39               0 :   for (unsigned i = 0; i < num_tables; ++i) {
      40               0 :     OpenTypeKERNFormat0 subtable;
      41               0 :     uint16_t sub_length = 0;
      42                 : 
      43               0 :     if (!table.ReadU16(&subtable.version) ||
      44               0 :         !table.ReadU16(&sub_length)) {
      45               0 :       return OTS_FAILURE();
      46                 :     }
      47                 : 
      48               0 :     if (subtable.version > 0) {
      49                 :       OTS_WARNING("Bad subtable version: %d", subtable.version);
      50               0 :       continue;
      51                 :     }
      52                 : 
      53               0 :     const size_t current_offset = table.offset();
      54               0 :     if (current_offset - 4 + sub_length > length) {
      55               0 :       return OTS_FAILURE();
      56                 :     }
      57                 : 
      58               0 :     if (!table.ReadU16(&subtable.coverage)) {
      59               0 :       return OTS_FAILURE();
      60                 :     }
      61                 : 
      62               0 :     if (!(subtable.coverage & 0x1)) {
      63                 :       OTS_WARNING(
      64                 :           "We don't support vertical data as the renderer doesn't support it.");
      65               0 :       continue;
      66                 :     }
      67               0 :     if (subtable.coverage & 0xF0) {
      68                 :       OTS_WARNING("Reserved fields should zero-filled.");
      69               0 :       DROP_THIS_TABLE;
      70               0 :       return true;
      71                 :     }
      72               0 :     const uint32_t format = (subtable.coverage & 0xFF00) >> 8;
      73               0 :     if (format != 0) {
      74                 :       OTS_WARNING("Format %d is not supported.", format);
      75               0 :       continue;
      76                 :     }
      77                 : 
      78                 :     // Parse the format 0 field.
      79               0 :     uint16_t num_pairs = 0;
      80               0 :     if (!table.ReadU16(&num_pairs) ||
      81               0 :         !table.ReadU16(&subtable.search_range) ||
      82               0 :         !table.ReadU16(&subtable.entry_selector) ||
      83               0 :         !table.ReadU16(&subtable.range_shift)) {
      84               0 :       return OTS_FAILURE();
      85                 :     }
      86                 : 
      87               0 :     if (!num_pairs) {
      88                 :       OTS_WARNING("Zero length subtable is found.");
      89               0 :       DROP_THIS_TABLE;
      90               0 :       return true;
      91                 :     }
      92                 : 
      93                 :     // Sanity checks for search_range, entry_selector, and range_shift. See the
      94                 :     // comment in ots.cc for details.
      95               0 :     const size_t kFormat0PairSize = 6;  // left, right, and value. 2 bytes each.
      96               0 :     if (num_pairs > (65536 / kFormat0PairSize)) {
      97                 :       // Some fonts (e.g. calibri.ttf, pykes_peak_zero.ttf) have pairs >= 10923.
      98                 :       OTS_WARNING("Too large subtable.");
      99               0 :       DROP_THIS_TABLE;
     100               0 :       return true;
     101                 :     }
     102               0 :     unsigned max_pow2 = 0;
     103               0 :     while (1u << (max_pow2 + 1) <= num_pairs) {
     104               0 :       ++max_pow2;
     105                 :     }
     106               0 :     const uint16_t expected_search_range = (1u << max_pow2) * kFormat0PairSize;
     107               0 :     if (subtable.search_range != expected_search_range) {
     108                 :       OTS_WARNING("bad search range");
     109               0 :       subtable.search_range = expected_search_range;
     110                 :     }
     111               0 :     if (subtable.entry_selector != max_pow2) {
     112               0 :       return OTS_FAILURE();
     113                 :     }
     114                 :     const uint32_t expected_range_shift
     115               0 :         = kFormat0PairSize * num_pairs - subtable.search_range;
     116               0 :     if (subtable.range_shift != expected_range_shift) {
     117                 :       OTS_WARNING("bad range shift");
     118               0 :       subtable.range_shift = expected_range_shift;
     119                 :     }
     120                 : 
     121                 :     // Read kerning pairs.
     122               0 :     subtable.pairs.reserve(num_pairs);
     123               0 :     uint32_t last_pair = 0;
     124               0 :     for (unsigned j = 0; j < num_pairs; ++j) {
     125                 :       OpenTypeKERNFormat0Pair kerning_pair;
     126               0 :       if (!table.ReadU16(&kerning_pair.left) ||
     127               0 :           !table.ReadU16(&kerning_pair.right) ||
     128               0 :           !table.ReadS16(&kerning_pair.value)) {
     129               0 :         return OTS_FAILURE();
     130                 :       }
     131                 :       const uint32_t current_pair
     132               0 :           = (kerning_pair.left << 16) + kerning_pair.right;
     133               0 :       if (j != 0 && current_pair <= last_pair) {
     134                 :         OTS_WARNING("Kerning pairs are not sorted.");
     135                 :         // Many free fonts don't follow this rule, so we don't call OTS_FAILURE
     136                 :         // in order to support these fonts.
     137               0 :         DROP_THIS_TABLE;
     138               0 :         return true;
     139                 :       }
     140               0 :       last_pair = current_pair;
     141               0 :       subtable.pairs.push_back(kerning_pair);
     142                 :     }
     143                 : 
     144               0 :     kern->subtables.push_back(subtable);
     145                 :   }
     146                 : 
     147               0 :   if (!kern->subtables.size()) {
     148                 :     OTS_WARNING("All subtables are removed.");
     149               0 :     DROP_THIS_TABLE;
     150               0 :     return true;
     151                 :   }
     152                 : 
     153               0 :   return true;
     154                 : }
     155                 : 
     156               0 : bool ots_kern_should_serialise(OpenTypeFile *file) {
     157               0 :   if (!file->glyf) return false;  // this table is not for CFF fonts.
     158               0 :   return file->kern != NULL;
     159                 : }
     160                 : 
     161               0 : bool ots_kern_serialise(OTSStream *out, OpenTypeFile *file) {
     162               0 :   const OpenTypeKERN *kern = file->kern;
     163                 : 
     164               0 :   if (!out->WriteU16(kern->version) ||
     165               0 :       !out->WriteU16(kern->subtables.size())) {
     166               0 :     return OTS_FAILURE();
     167                 :   }
     168                 : 
     169               0 :   for (unsigned i = 0; i < kern->subtables.size(); ++i) {
     170               0 :     const uint16_t length = 14 + (6 * kern->subtables[i].pairs.size());
     171               0 :     if (!out->WriteU16(kern->subtables[i].version) ||
     172               0 :         !out->WriteU16(length) ||
     173               0 :         !out->WriteU16(kern->subtables[i].coverage) ||
     174               0 :         !out->WriteU16(kern->subtables[i].pairs.size()) ||
     175               0 :         !out->WriteU16(kern->subtables[i].search_range) ||
     176               0 :         !out->WriteU16(kern->subtables[i].entry_selector) ||
     177               0 :         !out->WriteU16(kern->subtables[i].range_shift)) {
     178               0 :       return OTS_FAILURE();
     179                 :     }
     180               0 :     for (unsigned j = 0; j < kern->subtables[i].pairs.size(); ++j) {
     181               0 :       if (!out->WriteU16(kern->subtables[i].pairs[j].left) ||
     182               0 :           !out->WriteU16(kern->subtables[i].pairs[j].right) ||
     183               0 :           !out->WriteS16(kern->subtables[i].pairs[j].value)) {
     184               0 :         return OTS_FAILURE();
     185                 :       }
     186                 :     }
     187                 :   }
     188                 : 
     189               0 :   return true;
     190                 : }
     191                 : 
     192               0 : void ots_kern_free(OpenTypeFile *file) {
     193               0 :   delete file->kern;
     194               0 : }
     195                 : 
     196                 : }  // namespace ots

Generated by: LCOV version 1.7