LCOV - code coverage report
Current view: top level - gfx/sfntly/cpp/src/sfntly - font.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 313 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 44 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/font.h"
      18             : 
      19             : #include <stdio.h>
      20             : 
      21             : #include <functional>
      22             : #include <algorithm>
      23             : #include <map>
      24             : #include <string>
      25             : #include <typeinfo>
      26             : #include <iterator>
      27             : 
      28             : #include "sfntly/data/font_input_stream.h"
      29             : #include "sfntly/font_factory.h"
      30             : #include "sfntly/math/fixed1616.h"
      31             : #include "sfntly/math/font_math.h"
      32             : #include "sfntly/port/exception_type.h"
      33             : #include "sfntly/table/core/font_header_table.h"
      34             : #include "sfntly/table/core/horizontal_device_metrics_table.h"
      35             : #include "sfntly/table/core/horizontal_header_table.h"
      36             : #include "sfntly/table/core/horizontal_metrics_table.h"
      37             : #include "sfntly/table/core/maximum_profile_table.h"
      38             : #include "sfntly/table/truetype/loca_table.h"
      39             : #include "sfntly/tag.h"
      40             : 
      41             : namespace sfntly {
      42             : 
      43             : namespace {
      44             : 
      45             : const int32_t kSFNTVersionMajor = 1;
      46             : const int32_t kSFNTVersionMinor = 0;
      47             : 
      48             : const int32_t kMaxTableSize = 200 * 1024 * 1024;
      49             : 
      50             : }  // namespace
      51             : 
      52             : /******************************************************************************
      53             :  * Font class
      54             :  ******************************************************************************/
      55           0 : Font::~Font() {}
      56             : 
      57           0 : bool Font::HasTable(int32_t tag) const {
      58           0 :   return tables_.find(tag) != tables_.end();
      59             : }
      60             : 
      61           0 : Table* Font::GetTable(int32_t tag) {
      62           0 :   if (!HasTable(tag))
      63           0 :     return NULL;
      64           0 :   return tables_[tag];
      65             : }
      66             : 
      67           0 : const TableMap* Font::GetTableMap() {
      68           0 :   return &tables_;
      69             : }
      70             : 
      71           0 : void Font::Serialize(OutputStream* os, IntegerList* table_ordering) {
      72           0 :   assert(table_ordering);
      73           0 :   IntegerList final_table_ordering;
      74           0 :   GenerateTableOrdering(table_ordering, &final_table_ordering);
      75           0 :   TableHeaderList table_records;
      76           0 :   BuildTableHeadersForSerialization(&final_table_ordering, &table_records);
      77             : 
      78           0 :   FontOutputStream fos(os);
      79           0 :   SerializeHeader(&fos, &table_records);
      80           0 :   SerializeTables(&fos, &table_records);
      81           0 : }
      82             : 
      83           0 : Font::Font(int32_t sfnt_version, ByteVector* digest)
      84           0 :     : sfnt_version_(sfnt_version) {
      85             :   // non-trivial assignments that makes debugging hard if placed in
      86             :   // initialization list
      87           0 :   digest_ = *digest;
      88           0 : }
      89             : 
      90           0 : void Font::BuildTableHeadersForSerialization(IntegerList* table_ordering,
      91             :                                              TableHeaderList* table_headers) {
      92           0 :   assert(table_headers);
      93           0 :   assert(table_ordering);
      94             : 
      95           0 :   IntegerList final_table_ordering;
      96           0 :   GenerateTableOrdering(table_ordering, &final_table_ordering);
      97           0 :   int32_t table_offset = Offset::kTableRecordBegin + num_tables() *
      98           0 :                          Offset::kTableRecordSize;
      99           0 :   for (IntegerList::iterator tag = final_table_ordering.begin(),
     100           0 :                              tag_end = final_table_ordering.end();
     101             :                              tag != tag_end; ++tag) {
     102           0 :     if (tables_.find(*tag) == tables_.end()) {
     103           0 :       continue;
     104             :     }
     105           0 :     TablePtr table = tables_[*tag];
     106           0 :     if (table != NULL) {
     107             :       HeaderPtr header =
     108           0 :           new Header(*tag, table->CalculatedChecksum(), table_offset,
     109           0 :                      table->header()->length());
     110           0 :       table_headers->push_back(header);
     111           0 :       table_offset += (table->DataLength() + 3) & ~3;
     112             :     }
     113             :   }
     114           0 : }
     115             : 
     116           0 : void Font::SerializeHeader(FontOutputStream* fos,
     117             :                            TableHeaderList* table_headers) {
     118           0 :   fos->WriteFixed(sfnt_version_);
     119           0 :   fos->WriteUShort(table_headers->size());
     120           0 :   int32_t log2_of_max_power_of_2 = FontMath::Log2(table_headers->size());
     121           0 :   int32_t search_range = 2 << (log2_of_max_power_of_2 - 1 + 4);
     122           0 :   fos->WriteUShort(search_range);
     123           0 :   fos->WriteUShort(log2_of_max_power_of_2);
     124           0 :   fos->WriteUShort((table_headers->size() * 16) - search_range);
     125             : 
     126           0 :   HeaderTagSortedSet sorted_headers;
     127             :   std::copy(table_headers->begin(),
     128             :             table_headers->end(),
     129           0 :             std::inserter(sorted_headers, sorted_headers.end()));
     130             : 
     131           0 :   for (HeaderTagSortedSet::iterator record = sorted_headers.begin(),
     132           0 :                                     record_end = sorted_headers.end();
     133             :                                     record != record_end; ++record) {
     134           0 :     fos->WriteULong((*record)->tag());
     135           0 :     fos->WriteULong((int32_t)((*record)->checksum()));
     136           0 :     fos->WriteULong((*record)->offset());
     137           0 :     fos->WriteULong((*record)->length());
     138             :   }
     139           0 : }
     140             : 
     141           0 : void Font::SerializeTables(FontOutputStream* fos,
     142             :                            TableHeaderList* table_headers) {
     143           0 :   assert(fos);
     144           0 :   assert(table_headers);
     145           0 :   for (TableHeaderList::iterator record = table_headers->begin(),
     146           0 :                                  end_of_headers = table_headers->end();
     147             :                                  record != end_of_headers; ++record) {
     148           0 :     TablePtr target_table = GetTable((*record)->tag());
     149           0 :     if (target_table == NULL) {
     150             : #if !defined (SFNTLY_NO_EXCEPTION)
     151             :       throw IOException("Table out of sync with font header.");
     152             : #endif
     153           0 :       return;
     154             :     }
     155           0 :     int32_t table_size = target_table->Serialize(fos);
     156           0 :     if (table_size != (*record)->length()) {
     157           0 :       assert(false);
     158             :     }
     159           0 :     int32_t filler_size = ((table_size + 3) & ~3) - table_size;
     160           0 :     for (int32_t i = 0; i < filler_size; ++i) {
     161           0 :       fos->Write(static_cast<byte_t>(0));
     162             :     }
     163             :   }
     164             : }
     165             : 
     166           0 : void Font::GenerateTableOrdering(IntegerList* default_table_ordering,
     167             :                                  IntegerList* table_ordering) {
     168           0 :   assert(default_table_ordering);
     169           0 :   assert(table_ordering);
     170           0 :   table_ordering->clear();
     171           0 :   if (default_table_ordering->empty()) {
     172           0 :     DefaultTableOrdering(default_table_ordering);
     173             :   }
     174             : 
     175             :   typedef std::map<int32_t, bool> Int2Bool;
     176             :   typedef std::pair<int32_t, bool> Int2BoolEntry;
     177           0 :   Int2Bool tables_in_font;
     178           0 :   for (TableMap::iterator table = tables_.begin(), table_end = tables_.end();
     179             :                           table != table_end; ++table) {
     180           0 :     tables_in_font.insert(Int2BoolEntry(table->first, false));
     181             :   }
     182           0 :   for (IntegerList::iterator tag = default_table_ordering->begin(),
     183           0 :                              tag_end = default_table_ordering->end();
     184             :                              tag != tag_end; ++tag) {
     185           0 :     if (HasTable(*tag)) {
     186           0 :       table_ordering->push_back(*tag);
     187           0 :       tables_in_font[*tag] = true;
     188             :     }
     189             :   }
     190           0 :   for (Int2Bool::iterator table = tables_in_font.begin(),
     191           0 :                           table_end = tables_in_font.end();
     192             :                           table != table_end; ++table) {
     193           0 :     if (table->second == false)
     194           0 :       table_ordering->push_back(table->first);
     195             :   }
     196           0 : }
     197             : 
     198           0 : void Font::DefaultTableOrdering(IntegerList* default_table_ordering) {
     199           0 :   assert(default_table_ordering);
     200           0 :   default_table_ordering->clear();
     201           0 :   if (HasTable(Tag::CFF)) {
     202           0 :     default_table_ordering->resize(CFF_TABLE_ORDERING_SIZE);
     203           0 :     std::copy(CFF_TABLE_ORDERING, CFF_TABLE_ORDERING + CFF_TABLE_ORDERING_SIZE,
     204           0 :               default_table_ordering->begin());
     205           0 :     return;
     206             :   }
     207           0 :   default_table_ordering->resize(TRUE_TYPE_TABLE_ORDERING_SIZE);
     208             :   std::copy(TRUE_TYPE_TABLE_ORDERING,
     209           0 :             TRUE_TYPE_TABLE_ORDERING + TRUE_TYPE_TABLE_ORDERING_SIZE,
     210           0 :             default_table_ordering->begin());
     211             : }
     212             : 
     213             : /******************************************************************************
     214             :  * Font::Builder class
     215             :  ******************************************************************************/
     216           0 : Font::Builder::~Builder() {}
     217             : 
     218           0 : CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(FontFactory* factory,
     219             :                                                           InputStream* is) {
     220           0 :   FontBuilderPtr builder = new Builder(factory);
     221           0 :   builder->LoadFont(is);
     222           0 :   return builder.Detach();
     223             : }
     224             : 
     225           0 : CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
     226             :     FontFactory* factory,
     227             :     WritableFontData* wfd,
     228             :     int32_t offset_to_offset_table) {
     229           0 :   FontBuilderPtr builder = new Builder(factory);
     230           0 :   builder->LoadFont(wfd, offset_to_offset_table);
     231           0 :   return builder.Detach();
     232             : }
     233             : 
     234           0 : CALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
     235             :     FontFactory* factory) {
     236           0 :   FontBuilderPtr builder = new Builder(factory);
     237           0 :   return builder.Detach();
     238             : }
     239             : 
     240           0 : bool Font::Builder::ReadyToBuild() {
     241             :   // just read in data with no manipulation
     242           0 :   if (table_builders_.empty() && !data_blocks_.empty()) {
     243           0 :     return true;
     244             :   }
     245             : 
     246             :   // TODO(stuartg): font level checks - required tables etc?
     247           0 :   for (TableBuilderMap::iterator table_builder = table_builders_.begin(),
     248           0 :                                  table_builder_end = table_builders_.end();
     249             :                                  table_builder != table_builder_end;
     250             :                                  ++table_builder) {
     251           0 :     if (!table_builder->second->ReadyToBuild())
     252           0 :       return false;
     253             :   }
     254           0 :   return true;
     255             : }
     256             : 
     257           0 : CALLER_ATTACH Font* Font::Builder::Build() {
     258           0 :   FontPtr font = new Font(sfnt_version_, &digest_);
     259             : 
     260           0 :   if (!table_builders_.empty()) {
     261             :     // Note: Different from Java. Directly use font->tables_ here to avoid
     262             :     //       STL container copying.
     263           0 :     BuildTablesFromBuilders(font, &table_builders_, &font->tables_);
     264             :   }
     265             : 
     266           0 :   table_builders_.clear();
     267           0 :   data_blocks_.clear();
     268           0 :   return font.Detach();
     269             : }
     270             : 
     271           0 : void Font::Builder::SetDigest(ByteVector* digest) {
     272           0 :   digest_.clear();
     273           0 :   digest_ = *digest;
     274           0 : }
     275             : 
     276           0 : void Font::Builder::ClearTableBuilders() {
     277           0 :   table_builders_.clear();
     278           0 : }
     279             : 
     280           0 : bool Font::Builder::HasTableBuilder(int32_t tag) {
     281           0 :   return (table_builders_.find(tag) != table_builders_.end());
     282             : }
     283             : 
     284           0 : Table::Builder* Font::Builder::GetTableBuilder(int32_t tag) {
     285           0 :   if (HasTableBuilder(tag))
     286           0 :     return table_builders_[tag];
     287           0 :   return NULL;
     288             : }
     289             : 
     290           0 : Table::Builder* Font::Builder::NewTableBuilder(int32_t tag) {
     291           0 :   HeaderPtr header = new Header(tag);
     292           0 :   TableBuilderPtr builder;
     293           0 :   builder.Attach(Table::Builder::GetBuilder(header, NULL));
     294           0 :   table_builders_.insert(TableBuilderEntry(header->tag(), builder));
     295           0 :   return builder;
     296             : }
     297             : 
     298           0 : Table::Builder* Font::Builder::NewTableBuilder(int32_t tag,
     299             :                                                ReadableFontData* src_data) {
     300           0 :   assert(src_data);
     301           0 :   WritableFontDataPtr data;
     302           0 :   data.Attach(WritableFontData::CreateWritableFontData(src_data->Length()));
     303             :   // TODO(stuarg): take over original data instead?
     304           0 :   src_data->CopyTo(data);
     305             : 
     306           0 :   HeaderPtr header = new Header(tag, data->Length());
     307           0 :   TableBuilderPtr builder;
     308           0 :   builder.Attach(Table::Builder::GetBuilder(header, data));
     309           0 :   table_builders_.insert(TableBuilderEntry(tag, builder));
     310           0 :   return builder;
     311             : }
     312             : 
     313           0 : void Font::Builder::RemoveTableBuilder(int32_t tag) {
     314           0 :   table_builders_.erase(tag);
     315           0 : }
     316             : 
     317           0 : Font::Builder::Builder(FontFactory* factory)
     318             :     : factory_(factory),
     319           0 :       sfnt_version_(Fixed1616::Fixed(kSFNTVersionMajor, kSFNTVersionMinor)) {
     320           0 : }
     321             : 
     322           0 : void Font::Builder::LoadFont(InputStream* is) {
     323             :   // Note: we do not throw exception here for is.  This is more of an assertion.
     324           0 :   assert(is);
     325           0 :   FontInputStream font_is(is);
     326           0 :   HeaderOffsetSortedSet records;
     327           0 :   ReadHeader(&font_is, &records);
     328           0 :   LoadTableData(&records, &font_is, &data_blocks_);
     329           0 :   BuildAllTableBuilders(&data_blocks_, &table_builders_);
     330           0 :   font_is.Close();
     331           0 : }
     332             : 
     333           0 : void Font::Builder::LoadFont(WritableFontData* wfd,
     334             :                              int32_t offset_to_offset_table) {
     335             :   // Note: we do not throw exception here for is.  This is more of an assertion.
     336           0 :   assert(wfd);
     337           0 :   HeaderOffsetSortedSet records;
     338           0 :   ReadHeader(wfd, offset_to_offset_table, &records);
     339           0 :   LoadTableData(&records, wfd, &data_blocks_);
     340           0 :   BuildAllTableBuilders(&data_blocks_, &table_builders_);
     341           0 : }
     342             : 
     343           0 : int32_t Font::Builder::SfntWrapperSize() {
     344           0 :   return Offset::kSfntHeaderSize +
     345           0 :          (Offset::kTableRecordSize * table_builders_.size());
     346             : }
     347             : 
     348           0 : void Font::Builder::BuildAllTableBuilders(DataBlockMap* table_data,
     349             :                                           TableBuilderMap* builder_map) {
     350           0 :   for (DataBlockMap::iterator record = table_data->begin(),
     351           0 :                               record_end = table_data->end();
     352             :                               record != record_end; ++record) {
     353           0 :     TableBuilderPtr builder;
     354           0 :     builder.Attach(GetTableBuilder(record->first.p_, record->second.p_));
     355           0 :     builder_map->insert(TableBuilderEntry(record->first->tag(), builder));
     356             :   }
     357           0 :   InterRelateBuilders(&table_builders_);
     358           0 : }
     359             : 
     360             : CALLER_ATTACH
     361           0 : Table::Builder* Font::Builder::GetTableBuilder(Header* header,
     362             :                                                WritableFontData* data) {
     363           0 :   return Table::Builder::GetBuilder(header, data);
     364             : }
     365             : 
     366           0 : void Font::Builder::BuildTablesFromBuilders(Font* font,
     367             :                                             TableBuilderMap* builder_map,
     368             :                                             TableMap* table_map) {
     369             :   UNREFERENCED_PARAMETER(font);
     370           0 :   InterRelateBuilders(builder_map);
     371             : 
     372             :   // Now build all the tables.
     373           0 :   for (TableBuilderMap::iterator builder = builder_map->begin(),
     374           0 :                                  builder_end = builder_map->end();
     375             :                                  builder != builder_end; ++builder) {
     376           0 :     TablePtr table;
     377           0 :     if (builder->second && builder->second->ReadyToBuild()) {
     378           0 :       table.Attach(down_cast<Table*>(builder->second->Build()));
     379             :     }
     380           0 :     if (table == NULL) {
     381           0 :       table_map->clear();
     382             : #if !defined (SFNTLY_NO_EXCEPTION)
     383             :       std::string builder_string = "Unable to build table - ";
     384             :       char* table_name = TagToString(builder->first);
     385             :       builder_string += table_name;
     386             :       delete[] table_name;
     387             :       throw RuntimeException(builder_string.c_str());
     388             : #endif
     389           0 :       return;
     390             :     }
     391           0 :     table_map->insert(TableMapEntry(table->header()->tag(), table));
     392             :   }
     393             : }
     394             : 
     395           0 : static Table::Builder* GetBuilder(TableBuilderMap* builder_map, int32_t tag) {
     396           0 :   if (!builder_map)
     397           0 :     return NULL;
     398             : 
     399           0 :   TableBuilderMap::iterator target = builder_map->find(tag);
     400           0 :   if (target == builder_map->end())
     401           0 :     return NULL;
     402             : 
     403           0 :   return target->second.p_;
     404             : }
     405             : 
     406             : // Like GetBuilder(), but the returned Builder must be able to support reads.
     407           0 : static Table::Builder* GetReadBuilder(TableBuilderMap* builder_map, int32_t tag) {
     408           0 :   Table::Builder* builder = GetBuilder(builder_map, tag);
     409           0 :   if (!builder || !builder->InternalReadData())
     410           0 :     return NULL;
     411             : 
     412           0 :   return builder;
     413             : }
     414             : 
     415           0 : void Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) {
     416           0 :   Table::Builder* raw_head_builder = GetReadBuilder(builder_map, Tag::head);
     417           0 :   FontHeaderTableBuilderPtr header_table_builder;
     418           0 :   if (raw_head_builder != NULL) {
     419           0 :     header_table_builder =
     420           0 :         down_cast<FontHeaderTable::Builder*>(raw_head_builder);
     421             :   }
     422             : 
     423           0 :   Table::Builder* raw_hhea_builder = GetReadBuilder(builder_map, Tag::hhea);
     424           0 :   HorizontalHeaderTableBuilderPtr horizontal_header_builder;
     425           0 :   if (raw_head_builder != NULL) {
     426           0 :     horizontal_header_builder =
     427           0 :         down_cast<HorizontalHeaderTable::Builder*>(raw_hhea_builder);
     428             :   }
     429             : 
     430           0 :   Table::Builder* raw_maxp_builder = GetReadBuilder(builder_map, Tag::maxp);
     431           0 :   MaximumProfileTableBuilderPtr max_profile_builder;
     432           0 :   if (raw_maxp_builder != NULL) {
     433           0 :     max_profile_builder =
     434           0 :         down_cast<MaximumProfileTable::Builder*>(raw_maxp_builder);
     435             :   }
     436             : 
     437           0 :   Table::Builder* raw_loca_builder = GetBuilder(builder_map, Tag::loca);
     438           0 :   LocaTableBuilderPtr loca_table_builder;
     439           0 :   if (raw_loca_builder != NULL) {
     440           0 :     loca_table_builder = down_cast<LocaTable::Builder*>(raw_loca_builder);
     441             :   }
     442             : 
     443           0 :   Table::Builder* raw_hmtx_builder = GetBuilder(builder_map, Tag::hmtx);
     444           0 :   HorizontalMetricsTableBuilderPtr horizontal_metrics_builder;
     445           0 :   if (raw_hmtx_builder != NULL) {
     446           0 :     horizontal_metrics_builder =
     447           0 :         down_cast<HorizontalMetricsTable::Builder*>(raw_hmtx_builder);
     448             :   }
     449             : 
     450             : #if defined (SFNTLY_EXPERIMENTAL)
     451             :   Table::Builder* raw_hdmx_builder = GetBuilder(builder_map, Tag::hdmx);
     452             :   HorizontalDeviceMetricsTableBuilderPtr hdmx_table_builder;
     453             :   if (raw_hdmx_builder != NULL) {
     454             :     hdmx_table_builder =
     455             :         down_cast<HorizontalDeviceMetricsTable::Builder*>(raw_hdmx_builder);
     456             :   }
     457             : #endif
     458             : 
     459             :   // set the inter table data required to build certain tables
     460           0 :   if (horizontal_metrics_builder != NULL) {
     461           0 :     if (max_profile_builder != NULL) {
     462           0 :       horizontal_metrics_builder->SetNumGlyphs(
     463           0 :           max_profile_builder->NumGlyphs());
     464             :     }
     465           0 :     if (horizontal_header_builder != NULL) {
     466           0 :       horizontal_metrics_builder->SetNumberOfHMetrics(
     467           0 :           horizontal_header_builder->NumberOfHMetrics());
     468             :     }
     469             :   }
     470             : 
     471           0 :   if (loca_table_builder != NULL) {
     472           0 :     if (max_profile_builder != NULL) {
     473           0 :       loca_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs());
     474             :     }
     475           0 :     if (header_table_builder != NULL) {
     476           0 :       loca_table_builder->set_format_version(
     477           0 :           header_table_builder->IndexToLocFormat());
     478             :     }
     479             :   }
     480             : 
     481             : #if defined (SFNTLY_EXPERIMENTAL)
     482             :   // Note: In C++, hdmx_table_builder can be NULL in a subsetter.
     483             :   if (max_profile_builder != NULL && hdmx_table_builder != NULL) {
     484             :     hdmx_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs());
     485             :   }
     486             : #endif
     487           0 : }
     488             : 
     489           0 : void Font::Builder::ReadHeader(FontInputStream* is,
     490             :                                HeaderOffsetSortedSet* records) {
     491           0 :   assert(records);
     492           0 :   sfnt_version_ = is->ReadFixed();
     493           0 :   num_tables_ = is->ReadUShort();
     494           0 :   search_range_ = is->ReadUShort();
     495           0 :   entry_selector_ = is->ReadUShort();
     496           0 :   range_shift_ = is->ReadUShort();
     497             : 
     498           0 :   for (int32_t table_number = 0; table_number < num_tables_; ++table_number) {
     499             :     // Need to use temporary vars here.  C++ evaluates function parameters from
     500             :     // right to left and thus breaks the order of input stream.
     501           0 :     int32_t tag = is->ReadULongAsInt();
     502           0 :     int64_t checksum = is->ReadULong();
     503           0 :     int32_t offset = is->ReadULongAsInt();
     504           0 :     int32_t length = is->ReadULongAsInt();
     505           0 :     HeaderPtr table = new Header(tag, checksum, offset, length);
     506           0 :     records->insert(table);
     507             :   }
     508           0 : }
     509             : 
     510           0 : void Font::Builder::ReadHeader(ReadableFontData* fd,
     511             :                                int32_t offset,
     512             :                                HeaderOffsetSortedSet* records) {
     513           0 :   assert(records);
     514           0 :   sfnt_version_ = fd->ReadFixed(offset + Offset::kSfntVersion);
     515           0 :   num_tables_ = fd->ReadUShort(offset + Offset::kNumTables);
     516           0 :   search_range_ = fd->ReadUShort(offset + Offset::kSearchRange);
     517           0 :   entry_selector_ = fd->ReadUShort(offset + Offset::kEntrySelector);
     518           0 :   range_shift_ = fd->ReadUShort(offset + Offset::kRangeShift);
     519             : 
     520           0 :   int32_t table_offset = offset + Offset::kTableRecordBegin;
     521           0 :   for (int32_t table_number = 0;
     522           0 :        table_number < num_tables_;
     523           0 :        table_number++, table_offset += Offset::kTableRecordSize) {
     524           0 :     int32_t tag = fd->ReadULongAsInt(table_offset + Offset::kTableTag);
     525           0 :     int64_t checksum = fd->ReadULong(table_offset + Offset::kTableCheckSum);
     526           0 :     int32_t offset = fd->ReadULongAsInt(table_offset + Offset::kTableOffset);
     527           0 :     int32_t length = fd->ReadULongAsInt(table_offset + Offset::kTableLength);
     528           0 :     HeaderPtr table = new Header(tag, checksum, offset, length);
     529           0 :     records->insert(table);
     530             :   }
     531           0 : }
     532             : 
     533           0 : void Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
     534             :                                   FontInputStream* is,
     535             :                                   DataBlockMap* table_data) {
     536           0 :   assert(table_data);
     537           0 :   for (HeaderOffsetSortedSet::iterator it = headers->begin(),
     538           0 :                                        table_end = headers->end();
     539             :                                        it != table_end;
     540             :                                        ++it) {
     541           0 :     const Ptr<Header> header = *it;
     542           0 :     is->Skip(header->offset() - is->position());
     543           0 :     if (header->length() > kMaxTableSize)
     544           0 :       continue;
     545             : 
     546           0 :     FontInputStream table_is(is, header->length());
     547           0 :     WritableFontDataPtr data;
     548           0 :     data.Attach(WritableFontData::CreateWritableFontData(header->length()));
     549           0 :     data->CopyFrom(&table_is, header->length());
     550           0 :     table_data->insert(DataBlockEntry(header, data));
     551             :   }
     552           0 : }
     553             : 
     554           0 : void Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
     555             :                                   WritableFontData* fd,
     556             :                                   DataBlockMap* table_data) {
     557           0 :   for (HeaderOffsetSortedSet::iterator it = headers->begin(),
     558           0 :                                        table_end = headers->end();
     559             :                                        it != table_end;
     560             :                                        ++it) {
     561           0 :     const Ptr<Header> header = *it;
     562           0 :     if (header->length() > kMaxTableSize)
     563           0 :       continue;
     564             : 
     565           0 :     FontDataPtr sliced_data;
     566           0 :     sliced_data.Attach(fd->Slice(header->offset(), header->length()));
     567           0 :     WritableFontDataPtr data = down_cast<WritableFontData*>(sliced_data.p_);
     568           0 :     table_data->insert(DataBlockEntry(header, data));
     569             :   }
     570           0 : }
     571             : 
     572             : }  // namespace sfntly

Generated by: LCOV version 1.13