LCOV - code coverage report
Current view: top level - gfx/sfntly/cpp/src/sfntly/table/core - name_table.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 392 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 87 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2011 Google Inc. All Rights Reserved.
       3             :  *
       4             :  * Licensed under the Apache License, Version 2.0 (the "License");
       5             :  * you may not use this file except in compliance with the License.
       6             :  * You may obtain a copy of the License at
       7             :  *
       8             :  *      http://www.apache.org/licenses/LICENSE-2.0
       9             :  *
      10             :  * Unless required by applicable law or agreed to in writing, software
      11             :  * distributed under the License is distributed on an "AS IS" BASIS,
      12             :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      13             :  * See the License for the specific language governing permissions and
      14             :  * limitations under the License.
      15             :  */
      16             : 
      17             : #include "sfntly/table/core/name_table.h"
      18             : 
      19             : #include <stdio.h>
      20             : #include <string.h>
      21             : 
      22             : #include <unicode/unistr.h>
      23             : 
      24             : #include "sfntly/font.h"
      25             : #include "sfntly/port/exception_type.h"
      26             : 
      27             : namespace sfntly {
      28             : /******************************************************************************
      29             :  * NameTable::NameEntryId class
      30             :  ******************************************************************************/
      31           0 : NameTable::NameEntryId::NameEntryId()
      32             :     : platform_id_(0),
      33             :       encoding_id_(0),
      34             :       language_id_(0),
      35           0 :       name_id_(0) {
      36           0 : }
      37             : 
      38           0 : NameTable::NameEntryId::NameEntryId(int32_t platform_id,
      39             :                                     int32_t encoding_id,
      40             :                                     int32_t language_id,
      41           0 :                                     int32_t name_id)
      42             :     : platform_id_(platform_id),
      43             :       encoding_id_(encoding_id),
      44             :       language_id_(language_id),
      45           0 :       name_id_(name_id) {
      46           0 : }
      47             : 
      48           0 : NameTable::NameEntryId::NameEntryId(const NameTable::NameEntryId& rhs) {
      49           0 :   *this = rhs;
      50           0 : }
      51             : 
      52             : const NameTable::NameEntryId&
      53           0 :     NameTable::NameEntryId::operator=(const NameTable::NameEntryId& rhs) const {
      54           0 :   platform_id_ = rhs.platform_id_;
      55           0 :   encoding_id_ = rhs.encoding_id_;
      56           0 :   language_id_ = rhs.language_id_;
      57           0 :   name_id_ = rhs.name_id_;
      58           0 :   return *this;
      59             : }
      60             : 
      61           0 : bool NameTable::NameEntryId::operator==(const NameEntryId& rhs) const {
      62           0 :   return platform_id_ == rhs.platform_id_ &&
      63           0 :          encoding_id_ == rhs.encoding_id_ &&
      64           0 :          language_id_ == rhs.language_id_ &&
      65           0 :          name_id_ == rhs.name_id_;
      66             : }
      67             : 
      68           0 : bool NameTable::NameEntryId::operator<(const NameEntryId& rhs) const {
      69           0 :   if (platform_id_ != rhs.platform_id_) return platform_id_ < rhs.platform_id_;
      70           0 :   if (encoding_id_ != rhs.encoding_id_) return encoding_id_ < rhs.encoding_id_;
      71           0 :   if (language_id_ != rhs.language_id_) return language_id_ < rhs.language_id_;
      72           0 :   return name_id_ < rhs.name_id_;
      73             : }
      74             : 
      75             : /******************************************************************************
      76             :  * NameTable::NameEntry class
      77             :  ******************************************************************************/
      78           0 : NameTable::NameEntry::NameEntry() {
      79           0 :   Init(0, 0, 0, 0, NULL);
      80           0 : }
      81             : 
      82           0 : NameTable::NameEntry::NameEntry(const NameEntryId& name_entry_id,
      83           0 :                                 const ByteVector& name_bytes) {
      84           0 :   Init(name_entry_id.platform_id(),
      85             :        name_entry_id.encoding_id(),
      86             :        name_entry_id.language_id(),
      87             :        name_entry_id.name_id(),
      88           0 :        &name_bytes);
      89           0 : }
      90             : 
      91           0 : NameTable::NameEntry::NameEntry(int32_t platform_id,
      92             :                                 int32_t encoding_id,
      93             :                                 int32_t language_id,
      94             :                                 int32_t name_id,
      95           0 :                                 const ByteVector& name_bytes) {
      96           0 :   Init(platform_id, encoding_id, language_id, name_id, &name_bytes);
      97           0 : }
      98             : 
      99           0 : NameTable::NameEntry::~NameEntry() {}
     100             : 
     101           0 : ByteVector* NameTable::NameEntry::NameAsBytes() {
     102           0 :   return &name_bytes_;
     103             : }
     104             : 
     105           0 : int32_t NameTable::NameEntry::NameBytesLength() {
     106           0 :   return name_bytes_.size();
     107             : }
     108             : 
     109           0 : UChar* NameTable::NameEntry::Name() {
     110           0 :   return NameTable::ConvertFromNameBytes(&name_bytes_,
     111             :                                          platform_id(),
     112           0 :                                          encoding_id());
     113             : }
     114             : 
     115           0 : bool NameTable::NameEntry::operator==(const NameEntry& rhs) const {
     116           0 :   return (name_entry_id_ == rhs.name_entry_id_ &&
     117           0 :           name_bytes_ == rhs.name_bytes_);
     118             : }
     119             : 
     120           0 : void NameTable::NameEntry::Init(int32_t platform_id,
     121             :                                 int32_t encoding_id,
     122             :                                 int32_t language_id,
     123             :                                 int32_t name_id,
     124             :                                 const ByteVector* name_bytes) {
     125           0 :   name_entry_id_ = NameEntryId(platform_id, encoding_id, language_id, name_id);
     126           0 :   if (name_bytes) {
     127           0 :     name_bytes_ = *name_bytes;
     128             :   } else {
     129           0 :     name_bytes_.clear();
     130             :   }
     131           0 : }
     132             : 
     133             : /******************************************************************************
     134             :  * NameTable::NameEntryBuilder class
     135             :  ******************************************************************************/
     136           0 : NameTable::NameEntryBuilder::NameEntryBuilder() {
     137           0 :   Init(0, 0, 0, 0, NULL);
     138           0 : }
     139             : 
     140           0 : NameTable::NameEntryBuilder::NameEntryBuilder(const NameEntryId& name_entry_id,
     141           0 :                                               const ByteVector& name_bytes) {
     142           0 :   Init(name_entry_id.platform_id(),
     143             :        name_entry_id.encoding_id(),
     144             :        name_entry_id.language_id(),
     145             :        name_entry_id.name_id(),
     146           0 :        &name_bytes);
     147           0 : }
     148             : 
     149           0 : NameTable::NameEntryBuilder::NameEntryBuilder(
     150           0 :     const NameEntryId& name_entry_id) {
     151           0 :   Init(name_entry_id.platform_id(),
     152             :        name_entry_id.encoding_id(),
     153             :        name_entry_id.language_id(),
     154             :        name_entry_id.name_id(),
     155           0 :        NULL);
     156           0 : }
     157             : 
     158           0 : NameTable::NameEntryBuilder::NameEntryBuilder(NameEntry* b) {
     159           0 :   Init(b->platform_id(),
     160             :        b->encoding_id(),
     161             :        b->language_id(),
     162             :        b->name_id(),
     163           0 :        b->NameAsBytes());
     164           0 : }
     165             : 
     166           0 : NameTable::NameEntryBuilder::~NameEntryBuilder() {}
     167             : 
     168           0 : void NameTable::NameEntryBuilder::SetName(const UChar* name) {
     169           0 :   if (name == NULL) {
     170           0 :     name_entry_->name_bytes_.clear();
     171           0 :     return;
     172             :   }
     173           0 :   NameTable::ConvertToNameBytes(name,
     174             :                                 name_entry_->platform_id(),
     175             :                                 name_entry_->encoding_id(),
     176           0 :                                 &name_entry_->name_bytes_);
     177             : }
     178             : 
     179           0 : void NameTable::NameEntryBuilder::SetName(const ByteVector& name_bytes) {
     180           0 :   name_entry_->name_bytes_.clear();
     181             :   std::copy(name_bytes.begin(),
     182             :             name_bytes.end(),
     183           0 :             name_entry_->name_bytes_.begin());
     184           0 : }
     185             : 
     186           0 : void NameTable::NameEntryBuilder::SetName(const ByteVector& name_bytes,
     187             :                                           int32_t offset,
     188             :                                           int32_t length) {
     189           0 :   name_entry_->name_bytes_.clear();
     190           0 :   std::copy(name_bytes.begin() + offset,
     191           0 :             name_bytes.begin() + offset + length,
     192           0 :             name_entry_->name_bytes_.begin());
     193           0 : }
     194             : 
     195           0 : void NameTable::NameEntryBuilder::Init(int32_t platform_id,
     196             :                                        int32_t encoding_id,
     197             :                                        int32_t language_id,
     198             :                                        int32_t name_id,
     199             :                                        const ByteVector* name_bytes) {
     200           0 :   name_entry_ = new NameEntry();
     201           0 :   name_entry_->Init(platform_id, encoding_id, language_id, name_id, name_bytes);
     202           0 : }
     203             : 
     204             : /******************************************************************************
     205             :  * NameTable::NameEntryFilterInPlace class (C++ port only)
     206             :  ******************************************************************************/
     207           0 : NameTable::NameEntryFilterInPlace::NameEntryFilterInPlace(int32_t platform_id,
     208             :                                                           int32_t encoding_id,
     209             :                                                           int32_t language_id,
     210           0 :                                                           int32_t name_id)
     211             :     : platform_id_(platform_id),
     212             :       encoding_id_(encoding_id),
     213             :       language_id_(language_id),
     214           0 :       name_id_(name_id) {
     215           0 : }
     216             : 
     217           0 : bool NameTable::NameEntryFilterInPlace::Accept(int32_t platform_id,
     218             :                                                int32_t encoding_id,
     219             :                                                int32_t language_id,
     220             :                                                int32_t name_id) {
     221           0 :   return (platform_id_ == platform_id &&
     222           0 :           encoding_id_ == encoding_id &&
     223           0 :           language_id_ == language_id &&
     224           0 :           name_id_ == name_id);
     225             : }
     226             : 
     227             : /******************************************************************************
     228             :  * NameTable::NameEntryIterator class
     229             :  ******************************************************************************/
     230           0 : NameTable::NameEntryIterator::NameEntryIterator(NameTable* table)
     231             :     : RefIterator<NameEntry, NameTable>(table),
     232             :       name_index_(0),
     233           0 :       filter_(NULL) {
     234           0 : }
     235             : 
     236           0 : NameTable::NameEntryIterator::NameEntryIterator(NameTable* table,
     237           0 :                                                 NameEntryFilter* filter)
     238             :     : RefIterator<NameEntry, NameTable>(table),
     239             :       name_index_(0),
     240           0 :       filter_(filter) {
     241           0 : }
     242             : 
     243           0 : bool NameTable::NameEntryIterator::HasNext() {
     244           0 :   if (!filter_) {
     245           0 :     if (name_index_ < container()->NameCount()) {
     246           0 :       return true;
     247             :     }
     248           0 :     return false;
     249             :   }
     250           0 :   for (; name_index_ < container()->NameCount(); ++name_index_) {
     251           0 :     if (filter_->Accept(container()->PlatformId(name_index_),
     252           0 :                         container()->EncodingId(name_index_),
     253           0 :                         container()->LanguageId(name_index_),
     254           0 :                         container()->NameId(name_index_))) {
     255           0 :       return true;
     256             :     }
     257             :   }
     258           0 :   return false;
     259             : }
     260             : 
     261           0 : CALLER_ATTACH NameTable::NameEntry* NameTable::NameEntryIterator::Next() {
     262           0 :   if (!HasNext())
     263           0 :     return NULL;
     264           0 :   return container()->GetNameEntry(name_index_++);
     265             : }
     266             : 
     267             : /******************************************************************************
     268             :  * NameTable::Builder class
     269             :  ******************************************************************************/
     270           0 : NameTable::Builder::Builder(Header* header, WritableFontData* data)
     271           0 :     : SubTableContainerTable::Builder(header, data) {
     272           0 : }
     273             : 
     274           0 : NameTable::Builder::Builder(Header* header, ReadableFontData* data)
     275           0 :     : SubTableContainerTable::Builder(header, data) {
     276           0 : }
     277             : 
     278             : CALLER_ATTACH NameTable::Builder*
     279           0 :     NameTable::Builder::CreateBuilder(Header* header,
     280             :                                       WritableFontData* data) {
     281           0 :   Ptr<NameTable::Builder> builder;
     282           0 :   builder = new NameTable::Builder(header, data);
     283           0 :   return builder.Detach();
     284             : }
     285             : 
     286           0 : void NameTable::Builder::RevertNames() {
     287           0 :   name_entry_map_.clear();
     288           0 :   set_model_changed(false);
     289           0 : }
     290             : 
     291           0 : int32_t NameTable::Builder::BuilderCount() {
     292           0 :   GetNameBuilders();  // Ensure name_entry_map_ is built.
     293           0 :   return (int32_t)name_entry_map_.size();
     294             : }
     295             : 
     296           0 : bool NameTable::Builder::Has(int32_t platform_id,
     297             :                              int32_t encoding_id,
     298             :                              int32_t language_id,
     299             :                              int32_t name_id) {
     300           0 :   NameEntryId probe(platform_id, encoding_id, language_id, name_id);
     301           0 :   GetNameBuilders();  // Ensure name_entry_map_ is built.
     302           0 :   return (name_entry_map_.find(probe) != name_entry_map_.end());
     303             : }
     304             : 
     305             : CALLER_ATTACH NameTable::NameEntryBuilder*
     306           0 :     NameTable::Builder::NameBuilder(int32_t platform_id,
     307             :                                     int32_t encoding_id,
     308             :                                     int32_t language_id,
     309             :                                     int32_t name_id) {
     310           0 :   NameEntryId probe(platform_id, encoding_id, language_id, name_id);
     311           0 :   NameEntryBuilderMap builders;
     312           0 :   GetNameBuilders();  // Ensure name_entry_map_ is built.
     313           0 :   if (name_entry_map_.find(probe) != name_entry_map_.end()) {
     314           0 :     return name_entry_map_[probe];
     315             :   }
     316           0 :   NameEntryBuilderPtr builder = new NameEntryBuilder(probe);
     317           0 :   name_entry_map_[probe] = builder;
     318           0 :   return builder.Detach();
     319             : }
     320             : 
     321           0 : bool NameTable::Builder::Remove(int32_t platform_id,
     322             :                                 int32_t encoding_id,
     323             :                                 int32_t language_id,
     324             :                                 int32_t name_id) {
     325           0 :   NameEntryId probe(platform_id, encoding_id, language_id, name_id);
     326           0 :   GetNameBuilders();  // Ensure name_entry_map_ is built.
     327           0 :   NameEntryBuilderMap::iterator position = name_entry_map_.find(probe);
     328           0 :   if (position != name_entry_map_.end()) {
     329           0 :     name_entry_map_.erase(position);
     330           0 :     return true;
     331             :   }
     332           0 :   return false;
     333             : }
     334             : 
     335             : CALLER_ATTACH FontDataTable*
     336           0 :     NameTable::Builder::SubBuildTable(ReadableFontData* data) {
     337           0 :   FontDataTablePtr table = new NameTable(header(), data);
     338           0 :   return table.Detach();
     339             : }
     340             : 
     341           0 : void NameTable::Builder::SubDataSet() {
     342           0 :   name_entry_map_.clear();
     343           0 :   set_model_changed(false);
     344           0 : }
     345             : 
     346           0 : int32_t NameTable::Builder::SubDataSizeToSerialize() {
     347           0 :   if (name_entry_map_.empty()) {
     348           0 :     return 0;
     349             :   }
     350             : 
     351           0 :   int32_t size = NameTable::Offset::kNameRecordStart +
     352           0 :                  name_entry_map_.size() * NameTable::Offset::kNameRecordSize;
     353           0 :   for (NameEntryBuilderMap::iterator b = name_entry_map_.begin(),
     354           0 :                                      end = name_entry_map_.end();
     355             :                                      b != end; ++b) {
     356           0 :     NameEntryBuilderPtr p = b->second;
     357           0 :     NameEntry* entry = p->name_entry();
     358           0 :     size += entry->NameBytesLength();
     359             :   }
     360           0 :   return size;
     361             : }
     362             : 
     363           0 : bool NameTable::Builder::SubReadyToSerialize() {
     364           0 :   return !name_entry_map_.empty();
     365             : }
     366             : 
     367           0 : int32_t NameTable::Builder::SubSerialize(WritableFontData* new_data) {
     368             :   int32_t string_table_start_offset =
     369           0 :       NameTable::Offset::kNameRecordStart +
     370           0 :       name_entry_map_.size() * NameTable::Offset::kNameRecordSize;
     371             : 
     372             :   // Header
     373           0 :   new_data->WriteUShort(NameTable::Offset::kFormat, 0);
     374           0 :   new_data->WriteUShort(NameTable::Offset::kCount, name_entry_map_.size());
     375             :   new_data->WriteUShort(NameTable::Offset::kStringOffset,
     376           0 :                         string_table_start_offset);
     377           0 :   int32_t name_record_offset = NameTable::Offset::kNameRecordStart;
     378           0 :   int32_t string_offset = 0;
     379             :   // Note: we offered operator< in NameEntryId, which will be used by std::less,
     380             :   //       and therefore our map will act like TreeMap in Java to provide
     381             :   //       sorted key set.
     382           0 :   for (NameEntryBuilderMap::iterator b = name_entry_map_.begin(),
     383           0 :                                      end = name_entry_map_.end();
     384             :                                      b != end; ++b) {
     385           0 :     new_data->WriteUShort(
     386             :         name_record_offset + NameTable::Offset::kNameRecordPlatformId,
     387           0 :         b->first.platform_id());
     388           0 :     new_data->WriteUShort(
     389             :         name_record_offset + NameTable::Offset::kNameRecordEncodingId,
     390           0 :         b->first.encoding_id());
     391           0 :     new_data->WriteUShort(
     392             :         name_record_offset + NameTable::Offset::kNameRecordLanguageId,
     393           0 :         b->first.language_id());
     394           0 :     new_data->WriteUShort(
     395             :         name_record_offset + NameTable::Offset::kNameRecordNameId,
     396           0 :         b->first.name_id());
     397           0 :     NameEntry* builder_entry = b->second->name_entry();
     398           0 :     new_data->WriteUShort(
     399             :         name_record_offset + NameTable::Offset::kNameRecordStringLength,
     400           0 :         builder_entry->NameBytesLength());
     401           0 :     new_data->WriteUShort(
     402             :         name_record_offset + NameTable::Offset::kNameRecordStringOffset,
     403           0 :         string_offset);
     404           0 :     name_record_offset += NameTable::Offset::kNameRecordSize;
     405           0 :     string_offset += new_data->WriteBytes(
     406             :         string_offset + string_table_start_offset,
     407           0 :         builder_entry->NameAsBytes());
     408             :   }
     409             : 
     410           0 :   return string_offset + string_table_start_offset;
     411             : }
     412             : 
     413           0 : void NameTable::Builder::Initialize(ReadableFontData* data) {
     414           0 :   if (data) {
     415           0 :     NameTablePtr table = new NameTable(header(), data);
     416           0 :     Ptr<NameEntryIterator> name_iter;
     417           0 :     name_iter.Attach(table->Iterator());
     418           0 :     while (name_iter->HasNext()) {
     419           0 :       NameEntryPtr name_entry;
     420           0 :       name_entry.Attach(name_iter->Next());
     421           0 :       NameEntryBuilderPtr name_entry_builder = new NameEntryBuilder(name_entry);
     422           0 :       NameEntry* builder_entry = name_entry_builder->name_entry();
     423           0 :       NameEntryId probe = builder_entry->name_entry_id();
     424           0 :       name_entry_map_[probe] = name_entry_builder;
     425             :     }
     426             :   }
     427           0 : }
     428             : 
     429           0 : NameTable::NameEntryBuilderMap* NameTable::Builder::GetNameBuilders() {
     430           0 :   if (name_entry_map_.empty()) {
     431           0 :     Initialize(InternalReadData());
     432             :   }
     433           0 :   set_model_changed();
     434           0 :   return &name_entry_map_;
     435             : }
     436             : 
     437             : /******************************************************************************
     438             :  * NameTable class
     439             :  ******************************************************************************/
     440           0 : NameTable::~NameTable() {}
     441             : 
     442           0 : int32_t NameTable::Format() {
     443           0 :   return data_->ReadUShort(Offset::kFormat);
     444             : }
     445             : 
     446           0 : int32_t NameTable::NameCount() {
     447           0 :   return data_->ReadUShort(Offset::kCount);
     448             : }
     449             : 
     450           0 : int32_t NameTable::PlatformId(int32_t index) {
     451           0 :   return data_->ReadUShort(Offset::kNameRecordPlatformId +
     452           0 :                            OffsetForNameRecord(index));
     453             : }
     454             : 
     455           0 : int32_t NameTable::EncodingId(int32_t index) {
     456           0 :   return data_->ReadUShort(Offset::kNameRecordEncodingId +
     457           0 :                            OffsetForNameRecord(index));
     458             : }
     459             : 
     460           0 : int32_t NameTable::LanguageId(int32_t index) {
     461           0 :   return data_->ReadUShort(Offset::kNameRecordLanguageId +
     462           0 :                            OffsetForNameRecord(index));
     463             : }
     464             : 
     465           0 : int32_t NameTable::NameId(int32_t index) {
     466           0 :   return data_->ReadUShort(Offset::kNameRecordNameId +
     467           0 :                            OffsetForNameRecord(index));
     468             : }
     469             : 
     470           0 : void NameTable::NameAsBytes(int32_t index, ByteVector* b) {
     471           0 :   assert(b);
     472           0 :   b->clear();
     473             : 
     474           0 :   int32_t length = NameLength(index);
     475           0 :   if (length <= 0)
     476           0 :     return;
     477             : 
     478           0 :   b->resize(length);
     479           0 :   data_->ReadBytes(NameOffset(index), &((*b)[0]), 0, length);
     480             : }
     481             : 
     482           0 : void NameTable::NameAsBytes(int32_t platform_id,
     483             :                             int32_t encoding_id,
     484             :                             int32_t language_id,
     485             :                             int32_t name_id,
     486             :                             ByteVector* b) {
     487           0 :   assert(b);
     488           0 :   NameEntryPtr entry;
     489           0 :   entry.Attach(GetNameEntry(platform_id, encoding_id, language_id, name_id));
     490           0 :   if (entry) {
     491           0 :     ByteVector* name = entry->NameAsBytes();
     492           0 :     std::copy(name->begin(), name->end(), b->begin());
     493             :   }
     494           0 : }
     495             : 
     496           0 : UChar* NameTable::Name(int32_t index) {
     497           0 :   ByteVector b;
     498           0 :   NameAsBytes(index, &b);
     499           0 :   return ConvertFromNameBytes(&b, PlatformId(index), EncodingId(index));
     500             : }
     501             : 
     502           0 : UChar* NameTable::Name(int32_t platform_id,
     503             :                        int32_t encoding_id,
     504             :                        int32_t language_id,
     505             :                        int32_t name_id) {
     506           0 :   NameEntryPtr entry;
     507           0 :   entry.Attach(GetNameEntry(platform_id, encoding_id, language_id, name_id));
     508           0 :   if (entry) {
     509           0 :     return entry->Name();
     510             :   }
     511           0 :   return NULL;
     512             : }
     513             : 
     514           0 : CALLER_ATTACH NameTable::NameEntry* NameTable::GetNameEntry(int32_t index) {
     515           0 :   ByteVector b;
     516           0 :   NameAsBytes(index, &b);
     517           0 :   NameEntryPtr instance = new NameEntry(PlatformId(index),
     518           0 :                                         EncodingId(index),
     519           0 :                                         LanguageId(index),
     520           0 :                                         NameId(index), b);
     521           0 :   return instance.Detach();
     522             : }
     523             : 
     524           0 : CALLER_ATTACH NameTable::NameEntry* NameTable::GetNameEntry(int32_t platform_id,
     525             :                                                             int32_t encoding_id,
     526             :                                                             int32_t language_id,
     527             :                                                             int32_t name_id) {
     528             :   NameTable::NameEntryFilterInPlace
     529           0 :       filter(platform_id, encoding_id, language_id, name_id);
     530           0 :   Ptr<NameTable::NameEntryIterator> name_entry_iter;
     531           0 :   name_entry_iter.Attach(Iterator(&filter));
     532           0 :   NameEntryPtr result;
     533           0 :   if (name_entry_iter->HasNext()) {
     534           0 :     result = name_entry_iter->Next();
     535             :   }
     536           0 :   return result;
     537             : }
     538             : 
     539           0 : CALLER_ATTACH NameTable::NameEntryIterator* NameTable::Iterator() {
     540           0 :   Ptr<NameEntryIterator> output = new NameTable::NameEntryIterator(this);
     541           0 :   return output.Detach();
     542             : }
     543             : 
     544             : CALLER_ATTACH
     545           0 : NameTable::NameEntryIterator* NameTable::Iterator(NameEntryFilter* filter) {
     546             :   Ptr<NameEntryIterator> output =
     547           0 :       new NameTable::NameEntryIterator(this, filter);
     548           0 :   return output.Detach();
     549             : }
     550             : 
     551           0 : NameTable::NameTable(Header* header, ReadableFontData* data)
     552           0 :     : SubTableContainerTable(header, data) {}
     553             : 
     554           0 : int32_t NameTable::StringOffset() {
     555           0 :   return data_->ReadUShort(Offset::kStringOffset);
     556             : }
     557             : 
     558           0 : int32_t NameTable::OffsetForNameRecord(int32_t index) {
     559           0 :   return Offset::kNameRecordStart + index * Offset::kNameRecordSize;
     560             : }
     561             : 
     562           0 : int32_t NameTable::NameLength(int32_t index) {
     563           0 :   return data_->ReadUShort(Offset::kNameRecordStringLength +
     564           0 :                            OffsetForNameRecord(index));
     565             : }
     566             : 
     567           0 : int32_t NameTable::NameOffset(int32_t index) {
     568           0 :   return data_->ReadUShort(Offset::kNameRecordStringOffset +
     569           0 :                            OffsetForNameRecord(index)) + StringOffset();
     570             : }
     571             : 
     572           0 : const char* NameTable::GetEncodingName(int32_t platform_id,
     573             :                                        int32_t encoding_id) {
     574           0 :   switch (platform_id) {
     575             :     case PlatformId::kUnicode:
     576           0 :       return "UTF-16BE";
     577             :     case PlatformId::kMacintosh:
     578           0 :       switch (encoding_id) {
     579             :         case MacintoshEncodingId::kRoman:
     580           0 :           return "MacRoman";
     581             :         case MacintoshEncodingId::kJapanese:
     582           0 :           return "Shift-JIS";
     583             :         case MacintoshEncodingId::kChineseTraditional:
     584           0 :           return "Big5";
     585             :         case MacintoshEncodingId::kKorean:
     586           0 :           return "EUC-KR";
     587             :         case MacintoshEncodingId::kArabic:
     588           0 :           return "MacArabic";
     589             :         case MacintoshEncodingId::kHebrew:
     590           0 :           return "MacHebrew";
     591             :         case MacintoshEncodingId::kGreek:
     592           0 :           return "MacGreek";
     593             :         case MacintoshEncodingId::kRussian:
     594           0 :           return "MacCyrillic";
     595             :         case MacintoshEncodingId::kRSymbol:
     596           0 :           return "MacSymbol";
     597             :         case MacintoshEncodingId::kThai:
     598           0 :           return "MacThai";
     599             :         case MacintoshEncodingId::kChineseSimplified:
     600           0 :           return "EUC-CN";
     601             :         default:  // Note: unknown/unconfirmed cases are not ported.
     602           0 :           break;
     603             :       }
     604           0 :       break;
     605             :     case PlatformId::kISO:
     606           0 :       break;
     607             :     case PlatformId::kWindows:
     608           0 :       switch (encoding_id) {
     609             :         case WindowsEncodingId::kSymbol:
     610             :         case WindowsEncodingId::kUnicodeUCS2:
     611           0 :           return "UTF-16BE";
     612             :         case WindowsEncodingId::kShiftJIS:
     613           0 :           return "windows-933";
     614             :         case WindowsEncodingId::kPRC:
     615           0 :           return "windows-936";
     616             :         case WindowsEncodingId::kBig5:
     617           0 :           return "windows-950";
     618             :         case WindowsEncodingId::kWansung:
     619           0 :           return "windows-949";
     620             :         case WindowsEncodingId::kJohab:
     621           0 :           return "ms1361";
     622             :         case WindowsEncodingId::kUnicodeUCS4:
     623           0 :           return "UCS-4";
     624             :       }
     625           0 :       break;
     626             :     case PlatformId::kCustom:
     627           0 :       break;
     628             :     default:
     629           0 :       break;
     630             :   }
     631           0 :   return NULL;
     632             : }
     633             : 
     634           0 : UConverter* NameTable::GetCharset(int32_t platform_id, int32_t encoding_id) {
     635           0 :   UErrorCode error_code = U_ZERO_ERROR;
     636           0 :   UConverter* conv = ucnv_open(GetEncodingName(platform_id, encoding_id),
     637           0 :                                &error_code);
     638           0 :   if (U_SUCCESS(error_code)) {
     639           0 :     return conv;
     640             :   }
     641             : 
     642           0 :   if (conv) {
     643           0 :     ucnv_close(conv);
     644             :   }
     645           0 :   return NULL;
     646             : }
     647             : 
     648           0 : void NameTable::ConvertToNameBytes(const UChar* name,
     649             :                                    int32_t platform_id,
     650             :                                    int32_t encoding_id,
     651             :                                    ByteVector* b) {
     652           0 :   assert(b);
     653           0 :   assert(name);
     654           0 :   b->clear();
     655           0 :   UConverter* cs = GetCharset(platform_id, encoding_id);
     656           0 :   if (cs == NULL) {
     657           0 :     return;
     658             :   }
     659             : 
     660             :   // Preflight to get buffer size.
     661           0 :   UErrorCode error_code = U_ZERO_ERROR;
     662           0 :   int32_t length = ucnv_fromUChars(cs, NULL, 0, name, -1, &error_code);
     663           0 :   b->resize(length + 4);  // The longest termination "\0" is 4 bytes.
     664           0 :   memset(&((*b)[0]), 0, length + 4);
     665           0 :   error_code = U_ZERO_ERROR;
     666           0 :   ucnv_fromUChars(cs,
     667           0 :                   reinterpret_cast<char*>(&((*b)[0])),
     668             :                   length + 4,
     669             :                   name,
     670             :                   -1,
     671           0 :                   &error_code);
     672           0 :   if (!U_SUCCESS(error_code)) {
     673           0 :     b->clear();
     674             :   }
     675           0 :   ucnv_close(cs);
     676             : }
     677             : 
     678           0 : UChar* NameTable::ConvertFromNameBytes(ByteVector* name_bytes,
     679             :                                        int32_t platform_id,
     680             :                                        int32_t encoding_id) {
     681           0 :   if (name_bytes == NULL || name_bytes->size() == 0) {
     682           0 :     return NULL;
     683             :   }
     684           0 :   UConverter* cs = GetCharset(platform_id, encoding_id);
     685           0 :   UErrorCode error_code = U_ZERO_ERROR;
     686           0 :   if (cs == NULL) {
     687           0 :     char buffer[11] = {0};
     688             : #if defined (WIN32)
     689             :     _itoa_s(platform_id, buffer, 16);
     690             : #else
     691           0 :     snprintf(buffer, sizeof(buffer), "%x", platform_id);
     692             : #endif
     693           0 :     UChar* result = new UChar[12];
     694           0 :     memset(result, 0, sizeof(UChar) * 12);
     695           0 :     cs = ucnv_open("utf-8", &error_code);
     696           0 :     if (U_SUCCESS(error_code)) {
     697           0 :       ucnv_toUChars(cs, result, 12, buffer, 11, &error_code);
     698           0 :       ucnv_close(cs);
     699           0 :       if (U_SUCCESS(error_code)) {
     700           0 :         return result;
     701             :       }
     702             :     }
     703           0 :     delete[] result;
     704           0 :     return NULL;
     705             :   }
     706             : 
     707             :   // No preflight needed here, we will be bigger.
     708           0 :   UChar* output_buffer = new UChar[name_bytes->size() + 1];
     709           0 :   memset(output_buffer, 0, sizeof(UChar) * (name_bytes->size() + 1));
     710           0 :   int32_t length = ucnv_toUChars(cs,
     711             :                                  output_buffer,
     712           0 :                                  name_bytes->size(),
     713           0 :                                  reinterpret_cast<char*>(&((*name_bytes)[0])),
     714           0 :                                  name_bytes->size(),
     715           0 :                                  &error_code);
     716           0 :   ucnv_close(cs);
     717           0 :   if (length > 0) {
     718           0 :     return output_buffer;
     719             :   }
     720             : 
     721           0 :   delete[] output_buffer;
     722           0 :   return NULL;
     723             : }
     724             : 
     725             : }  // namespace sfntly

Generated by: LCOV version 1.13