LCOV - code coverage report
Current view: top level - gfx/ots/src - vdmx.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 100 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 "vdmx.h"
       6             : 
       7             : // VDMX - Vertical Device Metrics
       8             : // http://www.microsoft.com/typography/otspec/vdmx.htm
       9             : 
      10             : #define TABLE_NAME "VDMX"
      11             : 
      12             : #define DROP_THIS_TABLE(...) \
      13             :   do { \
      14             :     OTS_FAILURE_MSG_(font->file, TABLE_NAME ": " __VA_ARGS__); \
      15             :     OTS_FAILURE_MSG("Table discarded"); \
      16             :     delete font->vdmx; \
      17             :     font->vdmx = 0; \
      18             :   } while (0)
      19             : 
      20             : namespace ots {
      21             : 
      22           0 : bool ots_vdmx_parse(Font *font, const uint8_t *data, size_t length) {
      23           0 :   Buffer table(data, length);
      24           0 :   font->vdmx = new OpenTypeVDMX;
      25           0 :   OpenTypeVDMX * const vdmx = font->vdmx;
      26             : 
      27           0 :   if (!table.ReadU16(&vdmx->version) ||
      28           0 :       !table.ReadU16(&vdmx->num_recs) ||
      29           0 :       !table.ReadU16(&vdmx->num_ratios)) {
      30           0 :     return OTS_FAILURE_MSG("Failed to read table header");
      31             :   }
      32             : 
      33           0 :   if (vdmx->version > 1) {
      34           0 :     DROP_THIS_TABLE("bad version: %u", vdmx->version);
      35           0 :     return true;  // continue transcoding
      36             :   }
      37             : 
      38           0 :   vdmx->rat_ranges.reserve(vdmx->num_ratios);
      39           0 :   for (unsigned i = 0; i < vdmx->num_ratios; ++i) {
      40             :     OpenTypeVDMXRatioRecord rec;
      41             : 
      42           0 :     if (!table.ReadU8(&rec.charset) ||
      43           0 :         !table.ReadU8(&rec.x_ratio) ||
      44           0 :         !table.ReadU8(&rec.y_start_ratio) ||
      45           0 :         !table.ReadU8(&rec.y_end_ratio)) {
      46           0 :       return OTS_FAILURE_MSG("Failed to read ratio header %d", i);
      47             :     }
      48             : 
      49           0 :     if (rec.charset > 1) {
      50           0 :       DROP_THIS_TABLE("bad charset: %u", rec.charset);
      51           0 :       return true;
      52             :     }
      53             : 
      54           0 :     if (rec.y_start_ratio > rec.y_end_ratio) {
      55           0 :       DROP_THIS_TABLE("bad y ratio");
      56           0 :       return true;
      57             :     }
      58             : 
      59             :     // All values set to zero signal the default grouping to use;
      60             :     // if present, this must be the last Ratio group in the table.
      61           0 :     if ((i < vdmx->num_ratios - 1u) &&
      62           0 :         (rec.x_ratio == 0) &&
      63           0 :         (rec.y_start_ratio == 0) &&
      64           0 :         (rec.y_end_ratio == 0)) {
      65             :       // workaround for fonts which have 2 or more {0, 0, 0} terminators.
      66           0 :       DROP_THIS_TABLE("superfluous terminator found");
      67           0 :       return true;
      68             :     }
      69             : 
      70           0 :     vdmx->rat_ranges.push_back(rec);
      71             :   }
      72             : 
      73           0 :   vdmx->offsets.reserve(vdmx->num_ratios);
      74           0 :   const size_t current_offset = table.offset();
      75             :   // current_offset is less than (2 bytes * 3) + (4 bytes * USHRT_MAX) = 256k.
      76           0 :   for (unsigned i = 0; i < vdmx->num_ratios; ++i) {
      77             :     uint16_t offset;
      78           0 :     if (!table.ReadU16(&offset)) {
      79           0 :       return OTS_FAILURE_MSG("Failed to read ratio offset %d", i);
      80             :     }
      81           0 :     if (current_offset + offset >= length) {  // thus doesn't overflow.
      82           0 :       return OTS_FAILURE_MSG("Bad ratio offset %d for ration %d", offset, i);
      83             :     }
      84             : 
      85           0 :     vdmx->offsets.push_back(offset);
      86             :   }
      87             : 
      88           0 :   vdmx->groups.reserve(vdmx->num_recs);
      89           0 :   for (unsigned i = 0; i < vdmx->num_recs; ++i) {
      90           0 :     OpenTypeVDMXGroup group;
      91           0 :     if (!table.ReadU16(&group.recs) ||
      92           0 :         !table.ReadU8(&group.startsz) ||
      93           0 :         !table.ReadU8(&group.endsz)) {
      94           0 :       return OTS_FAILURE_MSG("Failed to read record header %d", i);
      95             :     }
      96           0 :     group.entries.reserve(group.recs);
      97           0 :     for (unsigned j = 0; j < group.recs; ++j) {
      98             :       OpenTypeVDMXVTable vt;
      99           0 :       if (!table.ReadU16(&vt.y_pel_height) ||
     100           0 :           !table.ReadS16(&vt.y_max) ||
     101           0 :           !table.ReadS16(&vt.y_min)) {
     102           0 :         return OTS_FAILURE_MSG("Failed to read reacord %d group %d", i, j);
     103             :       }
     104           0 :       if (vt.y_max < vt.y_min) {
     105           0 :         DROP_THIS_TABLE("bad y min/max");
     106           0 :         return true;
     107             :       }
     108             : 
     109             :       // This table must appear in sorted order (sorted by yPelHeight),
     110             :       // but need not be continuous.
     111           0 :       if ((j != 0) && (group.entries[j - 1].y_pel_height >= vt.y_pel_height)) {
     112           0 :         DROP_THIS_TABLE("the table is not sorted");
     113           0 :         return true;
     114             :       }
     115             : 
     116           0 :       group.entries.push_back(vt);
     117             :     }
     118           0 :     vdmx->groups.push_back(group);
     119             :   }
     120             : 
     121           0 :   return true;
     122             : }
     123             : 
     124           0 : bool ots_vdmx_should_serialise(Font *font) {
     125           0 :   if (!font->glyf) return false;  // this table is not for CFF fonts.
     126           0 :   return font->vdmx != NULL;
     127             : }
     128             : 
     129           0 : bool ots_vdmx_serialise(OTSStream *out, Font *font) {
     130           0 :   OpenTypeVDMX * const vdmx = font->vdmx;
     131             : 
     132           0 :   if (!out->WriteU16(vdmx->version) ||
     133           0 :       !out->WriteU16(vdmx->num_recs) ||
     134           0 :       !out->WriteU16(vdmx->num_ratios)) {
     135           0 :     return OTS_FAILURE_MSG("Failed to write table header");
     136             :   }
     137             : 
     138           0 :   for (unsigned i = 0; i < vdmx->rat_ranges.size(); ++i) {
     139           0 :     const OpenTypeVDMXRatioRecord& rec = vdmx->rat_ranges[i];
     140           0 :     if (!out->Write(&rec.charset, 1) ||
     141           0 :         !out->Write(&rec.x_ratio, 1) ||
     142           0 :         !out->Write(&rec.y_start_ratio, 1) ||
     143           0 :         !out->Write(&rec.y_end_ratio, 1)) {
     144           0 :       return OTS_FAILURE_MSG("Failed to write ratio %d", i);
     145             :     }
     146             :   }
     147             : 
     148           0 :   for (unsigned i = 0; i < vdmx->offsets.size(); ++i) {
     149           0 :     if (!out->WriteU16(vdmx->offsets[i])) {
     150           0 :       return OTS_FAILURE_MSG("Failed to write ratio offset %d", i);
     151             :     }
     152             :   }
     153             : 
     154           0 :   for (unsigned i = 0; i < vdmx->groups.size(); ++i) {
     155           0 :     const OpenTypeVDMXGroup& group = vdmx->groups[i];
     156           0 :     if (!out->WriteU16(group.recs) ||
     157           0 :         !out->Write(&group.startsz, 1) ||
     158           0 :         !out->Write(&group.endsz, 1)) {
     159           0 :       return OTS_FAILURE_MSG("Failed to write group %d", i);
     160             :     }
     161           0 :     for (unsigned j = 0; j < group.entries.size(); ++j) {
     162           0 :       const OpenTypeVDMXVTable& vt = group.entries[j];
     163           0 :       if (!out->WriteU16(vt.y_pel_height) ||
     164           0 :           !out->WriteS16(vt.y_max) ||
     165           0 :           !out->WriteS16(vt.y_min)) {
     166           0 :         return OTS_FAILURE_MSG("Failed to write group %d entry %d", i, j);
     167             :       }
     168             :     }
     169             :   }
     170             : 
     171           0 :   return true;
     172             : }
     173             : 
     174           0 : void ots_vdmx_reuse(Font *font, Font *other) {
     175           0 :   font->vdmx = other->vdmx;
     176           0 :   font->vdmx_reused = true;
     177           0 : }
     178             : 
     179           0 : void ots_vdmx_free(Font *font) {
     180           0 :   delete font->vdmx;
     181           0 : }
     182             : 
     183             : }  // namespace ots
     184             : 
     185             : #undef TABLE_NAME
     186             : #undef DROP_THIS_TABLE

Generated by: LCOV version 1.13