LCOV - code coverage report
Current view: top level - gfx/ots/src - post.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 "post.h"
       6             : 
       7             : #include "maxp.h"
       8             : 
       9             : // post - PostScript
      10             : // http://www.microsoft.com/typography/otspec/post.htm
      11             : 
      12             : #define TABLE_NAME "post"
      13             : 
      14             : namespace ots {
      15             : 
      16           0 : bool ots_post_parse(Font *font, const uint8_t *data, size_t length) {
      17           0 :   Buffer table(data, length);
      18             : 
      19           0 :   OpenTypePOST *post = new OpenTypePOST;
      20           0 :   font->post = post;
      21             : 
      22           0 :   if (!table.ReadU32(&post->version) ||
      23           0 :       !table.ReadU32(&post->italic_angle) ||
      24           0 :       !table.ReadS16(&post->underline) ||
      25           0 :       !table.ReadS16(&post->underline_thickness) ||
      26           0 :       !table.ReadU32(&post->is_fixed_pitch)) {
      27           0 :     return OTS_FAILURE_MSG("Failed to read post header");
      28             :   }
      29             : 
      30           0 :   if (post->underline_thickness < 0) {
      31           0 :     post->underline_thickness = 1;
      32             :   }
      33             : 
      34           0 :   if (post->version == 0x00010000) {
      35           0 :     return true;
      36           0 :   } else if (post->version == 0x00030000) {
      37           0 :     return true;
      38           0 :   } else if (post->version != 0x00020000) {
      39             :     // 0x00025000 is deprecated. We don't accept it.
      40           0 :     return OTS_FAILURE_MSG("Bad post version %x", post->version);
      41             :   }
      42             : 
      43             :   // We have a version 2 table with a list of Pascal strings at the end
      44             : 
      45             :   // We don't care about the memory usage fields. We'll set all these to zero
      46             :   // when serialising
      47           0 :   if (!table.Skip(16)) {
      48           0 :     return OTS_FAILURE_MSG("Failed to skip memory usage in post table");
      49             :   }
      50             : 
      51           0 :   uint16_t num_glyphs = 0;
      52           0 :   if (!table.ReadU16(&num_glyphs)) {
      53           0 :     return OTS_FAILURE_MSG("Failed to read number of glyphs");
      54             :   }
      55             : 
      56           0 :   if (!font->maxp) {
      57           0 :     return OTS_FAILURE_MSG("No maxp table required by post table");
      58             :   }
      59             : 
      60           0 :   if (num_glyphs == 0) {
      61           0 :     if (font->maxp->num_glyphs > 258) {
      62           0 :       return OTS_FAILURE_MSG("Can't have no glyphs in the post table if there are more than 256 glyphs in the font");
      63             :     }
      64           0 :     OTS_WARNING("table version is 1, but no glyf names are found");
      65             :     // workaround for fonts in http://www.fontsquirrel.com/fontface
      66             :     // (e.g., yataghan.ttf).
      67           0 :     post->version = 0x00010000;
      68           0 :     return true;
      69             :   }
      70             : 
      71           0 :   if (num_glyphs != font->maxp->num_glyphs) {
      72             :     // Note: Fixedsys500c.ttf seems to have inconsistent num_glyphs values.
      73           0 :     return OTS_FAILURE_MSG("Bad number of glyphs in post table %d", num_glyphs);
      74             :   }
      75             : 
      76           0 :   post->glyph_name_index.resize(num_glyphs);
      77           0 :   for (unsigned i = 0; i < num_glyphs; ++i) {
      78           0 :     if (!table.ReadU16(&post->glyph_name_index[i])) {
      79           0 :       return OTS_FAILURE_MSG("Failed to read post information for glyph %d", i);
      80             :     }
      81             :     // Note: A strict interpretation of the specification requires name indexes
      82             :     // are less than 32768. This, however, excludes fonts like unifont.ttf
      83             :     // which cover all of unicode.
      84             :   }
      85             : 
      86             :   // Now we have an array of Pascal strings. We have to check that they are all
      87             :   // valid and read them in.
      88           0 :   const size_t strings_offset = table.offset();
      89           0 :   const uint8_t *strings = data + strings_offset;
      90           0 :   const uint8_t *strings_end = data + length;
      91             : 
      92             :   for (;;) {
      93           0 :     if (strings == strings_end) break;
      94           0 :     const unsigned string_length = *strings;
      95           0 :     if (strings + 1 + string_length > strings_end) {
      96           0 :       return OTS_FAILURE_MSG("Bad string length %d", string_length);
      97             :     }
      98           0 :     if (std::memchr(strings + 1, '\0', string_length)) {
      99           0 :       return OTS_FAILURE_MSG("Bad string of length %d", string_length);
     100             :     }
     101           0 :     post->names.push_back(
     102           0 :         std::string(reinterpret_cast<const char*>(strings + 1), string_length));
     103           0 :     strings += 1 + string_length;
     104           0 :   }
     105           0 :   const unsigned num_strings = post->names.size();
     106             : 
     107             :   // check that all the references are within bounds
     108           0 :   for (unsigned i = 0; i < num_glyphs; ++i) {
     109           0 :     unsigned offset = post->glyph_name_index[i];
     110           0 :     if (offset < 258) {
     111           0 :       continue;
     112             :     }
     113             : 
     114           0 :     offset -= 258;
     115           0 :     if (offset >= num_strings) {
     116           0 :       return OTS_FAILURE_MSG("Bad string index %d", offset);
     117             :     }
     118             :   }
     119             : 
     120           0 :   return true;
     121             : }
     122             : 
     123           0 : bool ots_post_should_serialise(Font *font) {
     124           0 :   return font->post != NULL;
     125             : }
     126             : 
     127           0 : bool ots_post_serialise(OTSStream *out, Font *font) {
     128           0 :   const OpenTypePOST *post = font->post;
     129             : 
     130             :   // OpenType with CFF glyphs must have v3 post table.
     131           0 :   if (post && font->cff && post->version != 0x00030000) {
     132           0 :     return OTS_FAILURE_MSG("Bad post version %x", post->version);
     133             :   }
     134             : 
     135           0 :   if (!out->WriteU32(post->version) ||
     136           0 :       !out->WriteU32(post->italic_angle) ||
     137           0 :       !out->WriteS16(post->underline) ||
     138           0 :       !out->WriteS16(post->underline_thickness) ||
     139           0 :       !out->WriteU32(post->is_fixed_pitch) ||
     140           0 :       !out->WriteU32(0) ||
     141           0 :       !out->WriteU32(0) ||
     142           0 :       !out->WriteU32(0) ||
     143           0 :       !out->WriteU32(0)) {
     144           0 :     return OTS_FAILURE_MSG("Failed to write post header");
     145             :   }
     146             : 
     147           0 :   if (post->version != 0x00020000) {
     148           0 :     return true;  // v1.0 and v3.0 does not have glyph names.
     149             :   }
     150             : 
     151             :   const uint16_t num_indexes =
     152           0 :       static_cast<uint16_t>(post->glyph_name_index.size());
     153           0 :   if (num_indexes != post->glyph_name_index.size() ||
     154           0 :       !out->WriteU16(num_indexes)) {
     155           0 :     return OTS_FAILURE_MSG("Failed to write number of indices");
     156             :   }
     157             : 
     158           0 :   for (uint16_t i = 0; i < num_indexes; ++i) {
     159           0 :     if (!out->WriteU16(post->glyph_name_index[i])) {
     160           0 :       return OTS_FAILURE_MSG("Failed to write name index %d", i);
     161             :     }
     162             :   }
     163             : 
     164             :   // Now we just have to write out the strings in the correct order
     165           0 :   for (unsigned i = 0; i < post->names.size(); ++i) {
     166           0 :     const std::string& s = post->names[i];
     167           0 :     const uint8_t string_length = static_cast<uint8_t>(s.size());
     168           0 :     if (string_length != s.size() ||
     169           0 :         !out->Write(&string_length, 1)) {
     170           0 :       return OTS_FAILURE_MSG("Failed to write string %d", i);
     171             :     }
     172             :     // Some ttf fonts (e.g., frank.ttf on Windows Vista) have zero-length name.
     173             :     // We allow them.
     174           0 :     if (string_length > 0 && !out->Write(s.data(), string_length)) {
     175           0 :       return OTS_FAILURE_MSG("Failed to write string length for string %d", i);
     176             :     }
     177             :   }
     178             : 
     179           0 :   return true;
     180             : }
     181             : 
     182           0 : void ots_post_reuse(Font *font, Font *other) {
     183           0 :   font->post = other->post;
     184           0 :   font->post_reused = true;
     185           0 : }
     186             : 
     187           0 : void ots_post_free(Font *font) {
     188           0 :   delete font->post;
     189           0 : }
     190             : 
     191             : }  // namespace ots
     192             : 
     193             : #undef TABLE_NAME

Generated by: LCOV version 1.13