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

          Line data    Source code
       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.
       4             : 
       5             : #include "name.h"
       6             : 
       7             : #include <algorithm>
       8             : #include <cstring>
       9             : 
      10             : // name - Naming Table
      11             : // http://www.microsoft.com/typography/otspec/name.htm
      12             : 
      13             : #define TABLE_NAME "name"
      14             : 
      15             : namespace {
      16             : 
      17           0 : bool ValidInPsName(char c) {
      18           0 :   return (c > 0x20 && c < 0x7f && !std::strchr("[](){}<>/%", c));
      19             : }
      20             : 
      21           0 : bool CheckPsNameAscii(const std::string& name) {
      22           0 :   for (unsigned i = 0; i < name.size(); ++i) {
      23           0 :     if (!ValidInPsName(name[i])) {
      24           0 :       return false;
      25             :     }
      26             :   }
      27           0 :   return true;
      28             : }
      29             : 
      30           0 : bool CheckPsNameUtf16Be(const std::string& name) {
      31           0 :   if ((name.size() & 1) != 0)
      32           0 :     return false;
      33             : 
      34           0 :   for (unsigned i = 0; i < name.size(); i += 2) {
      35           0 :     if (name[i] != 0) {
      36           0 :       return false;
      37             :     }
      38           0 :     if (!ValidInPsName(name[i+1])) {
      39           0 :       return false;
      40             :     }
      41             :   }
      42           0 :   return true;
      43             : }
      44             : 
      45           0 : void AssignToUtf16BeFromAscii(std::string* target,
      46             :                               const std::string& source) {
      47           0 :   target->resize(source.size() * 2);
      48           0 :   for (unsigned i = 0, j = 0; i < source.size(); i++) {
      49           0 :     (*target)[j++] = '\0';
      50           0 :     (*target)[j++] = source[i];
      51             :   }
      52           0 : }
      53             : 
      54             : }  // namespace
      55             : 
      56             : 
      57             : namespace ots {
      58             : 
      59           0 : bool ots_name_parse(Font *font, const uint8_t* data, size_t length) {
      60           0 :   Buffer table(data, length);
      61             : 
      62           0 :   OpenTypeNAME* name = new OpenTypeNAME;
      63           0 :   font->name = name;
      64             : 
      65           0 :   uint16_t format = 0;
      66           0 :   if (!table.ReadU16(&format) || format > 1) {
      67           0 :     return OTS_FAILURE_MSG("Failed to read name table format or bad format %d", format);
      68             :   }
      69             : 
      70           0 :   uint16_t count = 0;
      71           0 :   if (!table.ReadU16(&count)) {
      72           0 :     return OTS_FAILURE_MSG("Failed to read name count");
      73             :   }
      74             : 
      75           0 :   uint16_t string_offset = 0;
      76           0 :   if (!table.ReadU16(&string_offset) || string_offset > length) {
      77           0 :     return OTS_FAILURE_MSG("Failed to read strings offset");
      78             :   }
      79           0 :   const char* string_base = reinterpret_cast<const char*>(data) +
      80           0 :       string_offset;
      81             : 
      82           0 :   bool sort_required = false;
      83             : 
      84             :   // Read all the names, discarding any with invalid IDs,
      85             :   // and any where the offset/length would be outside the table.
      86             :   // A stricter alternative would be to reject the font if there
      87             :   // are invalid name records, but it's not clear that is necessary.
      88           0 :   for (unsigned i = 0; i < count; ++i) {
      89           0 :     NameRecord rec;
      90           0 :     uint16_t name_length, name_offset = 0;
      91           0 :     if (!table.ReadU16(&rec.platform_id) ||
      92           0 :         !table.ReadU16(&rec.encoding_id) ||
      93           0 :         !table.ReadU16(&rec.language_id) ||
      94           0 :         !table.ReadU16(&rec.name_id) ||
      95           0 :         !table.ReadU16(&name_length) ||
      96           0 :         !table.ReadU16(&name_offset)) {
      97           0 :       return OTS_FAILURE_MSG("Failed to read name entry %d", i);
      98             :     }
      99             :     // check platform & encoding, discard names with unknown values
     100           0 :     switch (rec.platform_id) {
     101             :       case 0:  // Unicode
     102           0 :         if (rec.encoding_id > 6) {
     103           0 :           continue;
     104             :         }
     105           0 :         break;
     106             :       case 1:  // Macintosh
     107           0 :         if (rec.encoding_id > 32) {
     108           0 :           continue;
     109             :         }
     110           0 :         break;
     111             :       case 2:  // ISO
     112           0 :         if (rec.encoding_id > 2) {
     113           0 :           continue;
     114             :         }
     115           0 :         break;
     116             :       case 3:  // Windows: IDs 7 to 9 are "reserved"
     117           0 :         if (rec.encoding_id > 6 && rec.encoding_id != 10) {
     118           0 :           continue;
     119             :         }
     120           0 :         break;
     121             :       case 4:  // Custom (OTF Windows NT compatibility)
     122           0 :         if (rec.encoding_id > 255) {
     123           0 :           continue;
     124             :         }
     125           0 :         break;
     126             :       default:  // unknown platform
     127           0 :         continue;
     128             :     }
     129             : 
     130           0 :     const unsigned name_end = static_cast<unsigned>(string_offset) +
     131           0 :         name_offset + name_length;
     132           0 :     if (name_end > length) {
     133           0 :       continue;
     134             :     }
     135           0 :     rec.text.resize(name_length);
     136           0 :     rec.text.assign(string_base + name_offset, name_length);
     137             : 
     138           0 :     if (rec.name_id == 6) {
     139             :       // PostScript name: check that it is valid, if not then discard it
     140           0 :       if (rec.platform_id == 1) {
     141           0 :         if (!CheckPsNameAscii(rec.text)) {
     142           0 :           continue;
     143             :         }
     144           0 :       } else if (rec.platform_id == 0 || rec.platform_id == 3) {
     145           0 :         if (!CheckPsNameUtf16Be(rec.text)) {
     146           0 :           continue;
     147             :         }
     148             :       }
     149             :     }
     150             : 
     151           0 :     if (!name->names.empty() && !(name->names.back() < rec)) {
     152           0 :       OTS_WARNING("name records are not sorted.");
     153           0 :       sort_required = true;
     154             :     }
     155             : 
     156           0 :     name->names.push_back(rec);
     157             :   }
     158             : 
     159           0 :   if (format == 1) {
     160             :     // extended name table format with language tags
     161             :     uint16_t lang_tag_count;
     162           0 :     if (!table.ReadU16(&lang_tag_count)) {
     163           0 :       return OTS_FAILURE_MSG("Failed to read language tag count");
     164             :     }
     165           0 :     for (unsigned i = 0; i < lang_tag_count; ++i) {
     166           0 :       uint16_t tag_length = 0;
     167           0 :       uint16_t tag_offset = 0;
     168           0 :       if (!table.ReadU16(&tag_length) || !table.ReadU16(&tag_offset)) {
     169           0 :         return OTS_FAILURE_MSG("Faile to read tag length or offset");
     170             :       }
     171           0 :       const unsigned tag_end = static_cast<unsigned>(string_offset) +
     172           0 :           tag_offset + tag_length;
     173           0 :       if (tag_end > length) {
     174           0 :         return OTS_FAILURE_MSG("bad end of tag %d > %ld for name entry %d", tag_end, length, i);
     175             :       }
     176           0 :       std::string tag(string_base + tag_offset, tag_length);
     177           0 :       name->lang_tags.push_back(tag);
     178             :     }
     179             :   }
     180             : 
     181           0 :   if (table.offset() > string_offset) {
     182             :     // the string storage apparently overlapped the name/tag records;
     183             :     // consider this font to be badly broken
     184           0 :     return OTS_FAILURE_MSG("Bad table offset %ld > %d", table.offset(), string_offset);
     185             :   }
     186             : 
     187             :   // check existence of required name strings (synthesize if necessary)
     188             :   //  [0 - copyright - skip]
     189             :   //   1 - family
     190             :   //   2 - subfamily
     191             :   //  [3 - unique ID - skip]
     192             :   //   4 - full name
     193             :   //   5 - version
     194             :   //   6 - postscript name
     195             :   static const uint16_t kStdNameCount = 7;
     196             :   static const char* kStdNames[kStdNameCount] = {
     197             :     NULL,
     198             :     "OTS derived font",
     199             :     "Unspecified",
     200             :     NULL,
     201             :     "OTS derived font",
     202             :     "1.000",
     203             :     "OTS-derived-font"
     204             :   };
     205             : 
     206             :   // scan the names to check whether the required "standard" ones are present;
     207             :   // if not, we'll add our fixed versions here
     208           0 :   bool mac_name[kStdNameCount] = { 0 };
     209           0 :   bool win_name[kStdNameCount] = { 0 };
     210           0 :   for (std::vector<NameRecord>::iterator name_iter = name->names.begin();
     211           0 :        name_iter != name->names.end(); ++name_iter) {
     212           0 :     const uint16_t id = name_iter->name_id;
     213           0 :     if (id >= kStdNameCount || kStdNames[id] == NULL) {
     214           0 :       continue;
     215             :     }
     216           0 :     if (name_iter->platform_id == 1) {
     217           0 :       mac_name[id] = true;
     218           0 :       continue;
     219             :     }
     220           0 :     if (name_iter->platform_id == 3) {
     221           0 :       win_name[id] = true;
     222           0 :       continue;
     223             :     }
     224             :   }
     225             : 
     226           0 :   for (uint16_t i = 0; i < kStdNameCount; ++i) {
     227           0 :     if (kStdNames[i] == NULL) {
     228           0 :       continue;
     229             :     }
     230           0 :     if (!mac_name[i] && !win_name[i]) {
     231             :       NameRecord mac_rec(1 /* platform_id */, 0 /* encoding_id */,
     232           0 :                          0 /* language_id */ , i /* name_id */);
     233           0 :       mac_rec.text.assign(kStdNames[i]);
     234             : 
     235             :       NameRecord win_rec(3 /* platform_id */, 1 /* encoding_id */,
     236           0 :                          1033 /* language_id */ , i /* name_id */);
     237           0 :       AssignToUtf16BeFromAscii(&win_rec.text, std::string(kStdNames[i]));
     238             : 
     239           0 :       name->names.push_back(mac_rec);
     240           0 :       name->names.push_back(win_rec);
     241           0 :       sort_required = true;
     242             :     }
     243             :   }
     244             : 
     245           0 :   if (sort_required) {
     246           0 :     std::sort(name->names.begin(), name->names.end());
     247             :   }
     248             : 
     249           0 :   return true;
     250             : }
     251             : 
     252           0 : bool ots_name_should_serialise(Font *font) {
     253           0 :   return font->name != NULL;
     254             : }
     255             : 
     256           0 : bool ots_name_serialise(OTSStream* out, Font *font) {
     257           0 :   const OpenTypeNAME* name = font->name;
     258             : 
     259           0 :   uint16_t name_count = static_cast<uint16_t>(name->names.size());
     260           0 :   uint16_t lang_tag_count = static_cast<uint16_t>(name->lang_tags.size());
     261           0 :   uint16_t format = 0;
     262           0 :   size_t string_offset = 6 + name_count * 12;
     263             : 
     264           0 :   if (name->lang_tags.size() > 0) {
     265             :     // lang tags require a format-1 name table
     266           0 :     format = 1;
     267           0 :     string_offset += 2 + lang_tag_count * 4;
     268             :   }
     269           0 :   if (string_offset > 0xffff) {
     270           0 :     return OTS_FAILURE_MSG("Bad string offset %ld", string_offset);
     271             :   }
     272           0 :   if (!out->WriteU16(format) ||
     273           0 :       !out->WriteU16(name_count) ||
     274           0 :       !out->WriteU16(static_cast<uint16_t>(string_offset))) {
     275           0 :     return OTS_FAILURE_MSG("Failed to write name header");
     276             :   }
     277             : 
     278           0 :   std::string string_data;
     279           0 :   for (std::vector<NameRecord>::const_iterator name_iter = name->names.begin();
     280           0 :        name_iter != name->names.end(); ++name_iter) {
     281           0 :     const NameRecord& rec = *name_iter;
     282           0 :     if (string_data.size() + rec.text.size() >
     283           0 :             std::numeric_limits<uint16_t>::max() ||
     284           0 :         !out->WriteU16(rec.platform_id) ||
     285           0 :         !out->WriteU16(rec.encoding_id) ||
     286           0 :         !out->WriteU16(rec.language_id) ||
     287           0 :         !out->WriteU16(rec.name_id) ||
     288           0 :         !out->WriteU16(static_cast<uint16_t>(rec.text.size())) ||
     289           0 :         !out->WriteU16(static_cast<uint16_t>(string_data.size())) ) {
     290           0 :       return OTS_FAILURE_MSG("Faile to write name entry");
     291             :     }
     292           0 :     string_data.append(rec.text);
     293             :   }
     294             : 
     295           0 :   if (format == 1) {
     296           0 :     if (!out->WriteU16(lang_tag_count)) {
     297           0 :       return OTS_FAILURE_MSG("Faile to write language tag count");
     298             :     }
     299           0 :     for (std::vector<std::string>::const_iterator tag_iter =
     300           0 :              name->lang_tags.begin();
     301           0 :          tag_iter != name->lang_tags.end(); ++tag_iter) {
     302           0 :       if (string_data.size() + tag_iter->size() >
     303           0 :               std::numeric_limits<uint16_t>::max() ||
     304           0 :           !out->WriteU16(static_cast<uint16_t>(tag_iter->size())) ||
     305           0 :           !out->WriteU16(static_cast<uint16_t>(string_data.size()))) {
     306           0 :         return OTS_FAILURE_MSG("Failed to write string");
     307             :       }
     308           0 :       string_data.append(*tag_iter);
     309             :     }
     310             :   }
     311             : 
     312           0 :   if (!out->Write(string_data.data(), string_data.size())) {
     313           0 :     return OTS_FAILURE_MSG("Faile to write string data");
     314             :   }
     315             : 
     316           0 :   return true;
     317             : }
     318             : 
     319           0 : void ots_name_reuse(Font *font, Font *other) {
     320           0 :   font->name = other->name;
     321           0 :   font->name_reused = true;
     322           0 : }
     323             : 
     324           0 : void ots_name_free(Font *font) {
     325           0 :   delete font->name;
     326           0 : }
     327             : 
     328             : }  // namespace
     329             : 
     330             : #undef TABLE_NAME

Generated by: LCOV version 1.13