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

          Line data    Source code
       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 "hdmx.h"
       6             : #include "head.h"
       7             : #include "maxp.h"
       8             : 
       9             : // hdmx - Horizontal Device Metrics
      10             : // http://www.microsoft.com/typography/otspec/hdmx.htm
      11             : 
      12             : #define TABLE_NAME "hdmx"
      13             : 
      14             : #define DROP_THIS_TABLE(...) \
      15             :   do { \
      16             :     OTS_FAILURE_MSG_(font->file, TABLE_NAME ": " __VA_ARGS__); \
      17             :     OTS_FAILURE_MSG("Table discarded"); \
      18             :     delete font->hdmx; \
      19             :     font->hdmx = 0; \
      20             :   } while (0)
      21             : 
      22             : namespace ots {
      23             : 
      24           0 : bool ots_hdmx_parse(Font *font, const uint8_t *data, size_t length) {
      25           0 :   Buffer table(data, length);
      26           0 :   font->hdmx = new OpenTypeHDMX;
      27           0 :   OpenTypeHDMX * const hdmx = font->hdmx;
      28             : 
      29           0 :   if (!font->head || !font->maxp) {
      30           0 :     return OTS_FAILURE_MSG("Missing maxp or head tables in font, needed by hdmx");
      31             :   }
      32             : 
      33           0 :   if ((font->head->flags & 0x14) == 0) {
      34             :     // http://www.microsoft.com/typography/otspec/recom.htm
      35           0 :     DROP_THIS_TABLE("the table should not be present when bit 2 and 4 of the "
      36             :                     "head->flags are not set");
      37           0 :     return true;
      38             :   }
      39             : 
      40             :   int16_t num_recs;
      41           0 :   if (!table.ReadU16(&hdmx->version) ||
      42           0 :       !table.ReadS16(&num_recs) ||
      43           0 :       !table.ReadS32(&hdmx->size_device_record)) {
      44           0 :     return OTS_FAILURE_MSG("Failed to read hdmx header");
      45             :   }
      46           0 :   if (hdmx->version != 0) {
      47           0 :     DROP_THIS_TABLE("bad version: %u", hdmx->version);
      48           0 :     return true;
      49             :   }
      50           0 :   if (num_recs <= 0) {
      51           0 :     DROP_THIS_TABLE("bad num_recs: %d", num_recs);
      52           0 :     return true;
      53             :   }
      54           0 :   const int32_t actual_size_device_record = font->maxp->num_glyphs + 2;
      55           0 :   if (hdmx->size_device_record < actual_size_device_record) {
      56           0 :     DROP_THIS_TABLE("bad hdmx->size_device_record: %d", hdmx->size_device_record);
      57           0 :     return true;
      58             :   }
      59             : 
      60           0 :   hdmx->pad_len = hdmx->size_device_record - actual_size_device_record;
      61           0 :   if (hdmx->pad_len > 3) {
      62           0 :     return OTS_FAILURE_MSG("Bad padding %d", hdmx->pad_len);
      63             :   }
      64             : 
      65           0 :   uint8_t last_pixel_size = 0;
      66           0 :   hdmx->records.reserve(num_recs);
      67           0 :   for (int i = 0; i < num_recs; ++i) {
      68           0 :     OpenTypeHDMXDeviceRecord rec;
      69             : 
      70           0 :     if (!table.ReadU8(&rec.pixel_size) ||
      71           0 :         !table.ReadU8(&rec.max_width)) {
      72           0 :       return OTS_FAILURE_MSG("Failed to read hdmx record %d", i);
      73             :     }
      74           0 :     if ((i != 0) &&
      75           0 :         (rec.pixel_size <= last_pixel_size)) {
      76           0 :       DROP_THIS_TABLE("records are not sorted");
      77           0 :       return true;
      78             :     }
      79           0 :     last_pixel_size = rec.pixel_size;
      80             : 
      81           0 :     rec.widths.reserve(font->maxp->num_glyphs);
      82           0 :     for (unsigned j = 0; j < font->maxp->num_glyphs; ++j) {
      83             :       uint8_t width;
      84           0 :       if (!table.ReadU8(&width)) {
      85           0 :         return OTS_FAILURE_MSG("Failed to read glyph width %d in record %d", j, i);
      86             :       }
      87           0 :       rec.widths.push_back(width);
      88             :     }
      89             : 
      90           0 :     if ((hdmx->pad_len > 0) &&
      91           0 :         !table.Skip(hdmx->pad_len)) {
      92           0 :       return OTS_FAILURE_MSG("Failed to skip padding %d", hdmx->pad_len);
      93             :     }
      94             : 
      95           0 :     hdmx->records.push_back(rec);
      96             :   }
      97             : 
      98           0 :   return true;
      99             : }
     100             : 
     101           0 : bool ots_hdmx_should_serialise(Font *font) {
     102           0 :   if (!font->hdmx) return false;
     103           0 :   if (!font->glyf) return false;  // this table is not for CFF fonts.
     104           0 :   return true;
     105             : }
     106             : 
     107           0 : bool ots_hdmx_serialise(OTSStream *out, Font *font) {
     108           0 :   OpenTypeHDMX * const hdmx = font->hdmx;
     109             : 
     110           0 :   const int16_t num_recs = static_cast<int16_t>(hdmx->records.size());
     111           0 :   if (hdmx->records.size() >
     112           0 :           static_cast<size_t>(std::numeric_limits<int16_t>::max()) ||
     113           0 :       !out->WriteU16(hdmx->version) ||
     114           0 :       !out->WriteS16(num_recs) ||
     115           0 :       !out->WriteS32(hdmx->size_device_record)) {
     116           0 :     return OTS_FAILURE_MSG("Failed to write hdmx header");
     117             :   }
     118             : 
     119           0 :   for (int16_t i = 0; i < num_recs; ++i) {
     120           0 :     const OpenTypeHDMXDeviceRecord& rec = hdmx->records[i];
     121           0 :     if (!out->Write(&rec.pixel_size, 1) ||
     122           0 :         !out->Write(&rec.max_width, 1) ||
     123           0 :         !out->Write(&rec.widths[0], rec.widths.size())) {
     124           0 :       return OTS_FAILURE_MSG("Failed to write hdmx record %d", i);
     125             :     }
     126           0 :     if ((hdmx->pad_len > 0) &&
     127           0 :         !out->Write((const uint8_t *)"\x00\x00\x00", hdmx->pad_len)) {
     128           0 :       return OTS_FAILURE_MSG("Failed to write hdmx padding of length %d", hdmx->pad_len);
     129             :     }
     130             :   }
     131             : 
     132           0 :   return true;
     133             : }
     134             : 
     135           0 : void ots_hdmx_reuse(Font *font, Font *other) {
     136           0 :   font->hdmx = other->hdmx;
     137           0 :   font->hdmx_reused = true;
     138           0 : }
     139             : 
     140           0 : void ots_hdmx_free(Font *font) {
     141           0 :   delete font->hdmx;
     142           0 : }
     143             : 
     144             : }  // namespace ots
     145             : 
     146             : #undef TABLE_NAME
     147             : #undef DROP_THIS_TABLE

Generated by: LCOV version 1.13