gfx/ots/src/metrics.cc

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 "metrics.h"
     7 #include "head.h"
     8 #include "maxp.h"
    10 // OpenType horizontal and vertical common header format
    11 // http://www.microsoft.com/typography/otspec/hhea.htm
    12 // http://www.microsoft.com/typography/otspec/vhea.htm
    14 #define TABLE_NAME "metrics" // XXX: use individual table names
    16 namespace ots {
    18 bool ParseMetricsHeader(OpenTypeFile *file, Buffer *table,
    19                         OpenTypeMetricsHeader *header) {
    20   if (!table->ReadS16(&header->ascent) ||
    21       !table->ReadS16(&header->descent) ||
    22       !table->ReadS16(&header->linegap) ||
    23       !table->ReadU16(&header->adv_width_max) ||
    24       !table->ReadS16(&header->min_sb1) ||
    25       !table->ReadS16(&header->min_sb2) ||
    26       !table->ReadS16(&header->max_extent) ||
    27       !table->ReadS16(&header->caret_slope_rise) ||
    28       !table->ReadS16(&header->caret_slope_run) ||
    29       !table->ReadS16(&header->caret_offset)) {
    30     return OTS_FAILURE_MSG("Failed to read metrics header");
    31   }
    33   if (header->ascent < 0) {
    34     OTS_WARNING("bad ascent: %d", header->ascent);
    35     header->ascent = 0;
    36   }
    37   if (header->linegap < 0) {
    38     OTS_WARNING("bad linegap: %d", header->linegap);
    39     header->linegap = 0;
    40   }
    42   if (!file->head) {
    43     return OTS_FAILURE_MSG("Missing head font table");
    44   }
    46   // if the font is non-slanted, caret_offset should be zero.
    47   if (!(file->head->mac_style & 2) &&
    48       (header->caret_offset != 0)) {
    49     OTS_WARNING("bad caret offset: %d", header->caret_offset);
    50     header->caret_offset = 0;
    51   }
    53   // skip the reserved bytes
    54   if (!table->Skip(8)) {
    55     return OTS_FAILURE_MSG("Failed to skip reserverd bytes");
    56   }
    58   int16_t data_format;
    59   if (!table->ReadS16(&data_format)) {
    60     return OTS_FAILURE_MSG("Failed to read data format");
    61   }
    62   if (data_format) {
    63     return OTS_FAILURE_MSG("Bad data format %d", data_format);
    64   }
    66   if (!table->ReadU16(&header->num_metrics)) {
    67     return OTS_FAILURE_MSG("Failed to read number of metrics");
    68   }
    70   if (!file->maxp) {
    71     return OTS_FAILURE_MSG("Missing maxp font table");
    72   }
    74   if (header->num_metrics > file->maxp->num_glyphs) {
    75     return OTS_FAILURE_MSG("Bad number of metrics %d", header->num_metrics);
    76   }
    78   return true;
    79 }
    81 bool SerialiseMetricsHeader(const ots::OpenTypeFile *file,
    82                             OTSStream *out,
    83                             const OpenTypeMetricsHeader *header) {
    84   if (!out->WriteU32(header->version) ||
    85       !out->WriteS16(header->ascent) ||
    86       !out->WriteS16(header->descent) ||
    87       !out->WriteS16(header->linegap) ||
    88       !out->WriteU16(header->adv_width_max) ||
    89       !out->WriteS16(header->min_sb1) ||
    90       !out->WriteS16(header->min_sb2) ||
    91       !out->WriteS16(header->max_extent) ||
    92       !out->WriteS16(header->caret_slope_rise) ||
    93       !out->WriteS16(header->caret_slope_run) ||
    94       !out->WriteS16(header->caret_offset) ||
    95       !out->WriteR64(0) ||  // reserved
    96       !out->WriteS16(0) ||  // metric data format
    97       !out->WriteU16(header->num_metrics)) {
    98     return OTS_FAILURE_MSG("Failed to write metrics");
    99   }
   101   return true;
   102 }
   104 bool ParseMetricsTable(const ots::OpenTypeFile *file,
   105                        Buffer *table,
   106                        const uint16_t num_glyphs,
   107                        const OpenTypeMetricsHeader *header,
   108                        OpenTypeMetricsTable *metrics) {
   109   // |num_metrics| is a uint16_t, so it's bounded < 65536. This limits that
   110   // amount of memory that we'll allocate for this to a sane amount.
   111   const unsigned num_metrics = header->num_metrics;
   113   if (num_metrics > num_glyphs) {
   114     return OTS_FAILURE_MSG("Bad number of metrics %d", num_metrics);
   115   }
   116   if (!num_metrics) {
   117     return OTS_FAILURE_MSG("No metrics!");
   118   }
   119   const unsigned num_sbs = num_glyphs - num_metrics;
   121   metrics->entries.reserve(num_metrics);
   122   for (unsigned i = 0; i < num_metrics; ++i) {
   123     uint16_t adv = 0;
   124     int16_t sb = 0;
   125     if (!table->ReadU16(&adv) || !table->ReadS16(&sb)) {
   126       return OTS_FAILURE_MSG("Failed to read metric %d", i);
   127     }
   129     // Since so many fonts don't have proper value on |adv| and |sb|,
   130     // we should not call ots_failure() here. For example, about 20% of fonts
   131     // in http://www.princexml.com/fonts/ (200+ fonts) fails these tests.
   132     if (adv > header->adv_width_max) {
   133       OTS_WARNING("bad adv: %u > %u", adv, header->adv_width_max);
   134       adv = header->adv_width_max;
   135     }
   137     if (sb < header->min_sb1) {
   138       OTS_WARNING("bad sb: %d < %d", sb, header->min_sb1);
   139       sb = header->min_sb1;
   140     }
   142     metrics->entries.push_back(std::make_pair(adv, sb));
   143   }
   145   metrics->sbs.reserve(num_sbs);
   146   for (unsigned i = 0; i < num_sbs; ++i) {
   147     int16_t sb;
   148     if (!table->ReadS16(&sb)) {
   149       // Some Japanese fonts (e.g., mona.ttf) fail this test.
   150       return OTS_FAILURE_MSG("Failed to read side bearing %d", i + num_metrics);
   151     }
   153     if (sb < header->min_sb1) {
   154       // The same as above. Three fonts in http://www.fontsquirrel.com/fontface
   155       // (e.g., Notice2Std.otf) have weird lsb values.
   156       OTS_WARNING("bad lsb: %d < %d", sb, header->min_sb1);
   157       sb = header->min_sb1;
   158     }
   160     metrics->sbs.push_back(sb);
   161   }
   163   return true;
   164 }
   166 bool SerialiseMetricsTable(const ots::OpenTypeFile *file,
   167                            OTSStream *out,
   168                            const OpenTypeMetricsTable *metrics) {
   169   for (unsigned i = 0; i < metrics->entries.size(); ++i) {
   170     if (!out->WriteU16(metrics->entries[i].first) ||
   171         !out->WriteS16(metrics->entries[i].second)) {
   172       return OTS_FAILURE_MSG("Failed to write metric %d", i);
   173     }
   174   }
   176   for (unsigned i = 0; i < metrics->sbs.size(); ++i) {
   177     if (!out->WriteS16(metrics->sbs[i])) {
   178       return OTS_FAILURE_MSG("Failed to write side bearing %ld", i + metrics->entries.size());
   179     }
   180   }
   182   return true;
   183 }
   185 }  // namespace ots

mercurial