130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/*
230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Copyright 2011 Google Inc. All Rights Reserved.
330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Licensed under the Apache License, Version 2.0 (the "License");
530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * you may not use this file except in compliance with the License.
630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * You may obtain a copy of the License at
730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *      http://www.apache.org/licenses/LICENSE-2.0
930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
1030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Unless required by applicable law or agreed to in writing, software
1130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * distributed under the License is distributed on an "AS IS" BASIS,
1230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * See the License for the specific language governing permissions and
1430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * limitations under the License.
1530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun */
1630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
1730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/font.h"
1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <stdio.h>
2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <functional>
2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <algorithm>
2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <map>
2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <string>
2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <typeinfo>
2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <iterator>
2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/data/font_input_stream.h"
2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/font_factory.h"
3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/math/fixed1616.h"
3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/math/font_math.h"
3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/exception_type.h"
3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/core/font_header_table.h"
3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/core/horizontal_device_metrics_table.h"
3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/core/horizontal_header_table.h"
3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/core/horizontal_metrics_table.h"
3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/core/maximum_profile_table.h"
3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/truetype/loca_table.h"
3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/tag.h"
4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace sfntly {
4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t SFNTVERSION_MAJOR = 1;
4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t SFNTVERSION_MINOR = 0;
4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Font class
4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFont::~Font() {}
5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool Font::HasTable(int32_t tag) {
5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  TableMap::const_iterator result = tables_.find(tag);
5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  TableMap::const_iterator end = tables_.end();
5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return (result != end);
5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunTable* Font::GetTable(int32_t tag) {
5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!HasTable(tag)) {
5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return NULL;
6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return tables_[tag];
6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst TableMap* Font::GetTableMap() {
6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return &tables_;
6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Serialize(OutputStream* os, IntegerList* table_ordering) {
6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(table_ordering);
7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  IntegerList final_table_ordering;
7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  GenerateTableOrdering(table_ordering, &final_table_ordering);
7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  TableHeaderList table_records;
7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  BuildTableHeadersForSerialization(&final_table_ordering, &table_records);
7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontOutputStream fos(os);
7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  SerializeHeader(&fos, &table_records);
7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  SerializeTables(&fos, &table_records);
7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFont::Font(int32_t sfnt_version, ByteVector* digest)
8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : sfnt_version_(sfnt_version) {
8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // non-trivial assignments that makes debugging hard if placed in
8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // initialization list
8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  digest_ = *digest;
8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::BuildTableHeadersForSerialization(IntegerList* table_ordering,
8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                             TableHeaderList* table_headers) {
8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(table_headers);
9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(table_ordering);
9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  IntegerList final_table_ordering;
9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  GenerateTableOrdering(table_ordering, &final_table_ordering);
9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t table_offset = Offset::kTableRecordBegin + num_tables() *
9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                         Offset::kTableRecordSize;
9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (IntegerList::iterator tag = final_table_ordering.begin(),
9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                             tag_end = final_table_ordering.end();
9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                             tag != tag_end; ++tag) {
9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (tables_.find(*tag) == tables_.end()) {
10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      continue;
10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    TablePtr table = tables_[*tag];
10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (table != NULL) {
10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      HeaderPtr header =
10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          new Header(*tag, table->CalculatedChecksum(), table_offset,
10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                     table->header()->length());
10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      table_headers->push_back(header);
10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      table_offset += (table->DataLength() + 3) & ~3;
10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::SerializeHeader(FontOutputStream* fos,
11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           TableHeaderList* table_headers) {
11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fos->WriteFixed(sfnt_version_);
11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fos->WriteUShort(table_headers->size());
11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t log2_of_max_power_of_2 = FontMath::Log2(table_headers->size());
11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t search_range = 2 << (log2_of_max_power_of_2 - 1 + 4);
11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fos->WriteUShort(search_range);
12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fos->WriteUShort(log2_of_max_power_of_2);
12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fos->WriteUShort((table_headers->size() * 16) - search_range);
12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  HeaderTagSortedSet sorted_headers;
12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  std::copy(table_headers->begin(),
12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun            table_headers->end(),
12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun            std::inserter(sorted_headers, sorted_headers.end()));
12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (HeaderTagSortedSet::iterator record = sorted_headers.begin(),
12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                    record_end = sorted_headers.end();
13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                    record != record_end; ++record) {
13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    fos->WriteULong((*record)->tag());
13230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    fos->WriteULong((int32_t)((*record)->checksum()));
13330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    fos->WriteULong((*record)->offset());
13430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    fos->WriteULong((*record)->length());
13530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
13630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
13730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
13830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::SerializeTables(FontOutputStream* fos,
13930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           TableHeaderList* table_headers) {
14030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(fos);
14130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(table_headers);
14230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (TableHeaderList::iterator record = table_headers->begin(),
14330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                 end_of_headers = table_headers->end();
14430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                 record != end_of_headers; ++record) {
14530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    TablePtr target_table = GetTable((*record)->tag());
14630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (target_table == NULL) {
14730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
14830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      throw IOException("Table out of sync with font header.");
14930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
15030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return;
15130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
15230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t table_size = target_table->Serialize(fos);
15330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (table_size != (*record)->length()) {
15430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      assert(false);
15530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
15630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t filler_size = ((table_size + 3) & ~3) - table_size;
15730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    for (int32_t i = 0; i < filler_size; ++i) {
15830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      fos->Write(static_cast<byte_t>(0));
15930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
16030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
16130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
16230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
16330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::GenerateTableOrdering(IntegerList* default_table_ordering,
16430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                 IntegerList* table_ordering) {
16530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(default_table_ordering);
16630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(table_ordering);
16730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  table_ordering->clear();
16830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (default_table_ordering->empty()) {
16930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    DefaultTableOrdering(default_table_ordering);
17030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
17130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
17230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  typedef std::map<int32_t, bool> Int2Bool;
17330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  typedef std::pair<int32_t, bool> Int2BoolEntry;
17430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Int2Bool tables_in_font;
17530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (TableMap::iterator table = tables_.begin(), table_end = tables_.end();
17630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                          table != table_end; ++table) {
17730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    tables_in_font.insert(Int2BoolEntry(table->first, false));
17830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
17930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (IntegerList::iterator tag = default_table_ordering->begin(),
18030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                             tag_end = default_table_ordering->end();
18130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                             tag != tag_end; ++tag) {
18230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (HasTable(*tag)) {
18330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      table_ordering->push_back(*tag);
18430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      tables_in_font[*tag] = true;
18530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
18630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
18730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (Int2Bool::iterator table = tables_in_font.begin(),
18830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                          table_end = tables_in_font.end();
18930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                          table != table_end; ++table) {
19030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (table->second == false)
19130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      table_ordering->push_back(table->first);
19230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
19330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
19430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
19530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::DefaultTableOrdering(IntegerList* default_table_ordering) {
19630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(default_table_ordering);
19730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  default_table_ordering->clear();
19830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (HasTable(Tag::CFF)) {
19930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    default_table_ordering->resize(CFF_TABLE_ORDERING_SIZE);
20030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    std::copy(CFF_TABLE_ORDERING, CFF_TABLE_ORDERING + CFF_TABLE_ORDERING_SIZE,
20130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun              default_table_ordering->begin());
20230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return;
20330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
20430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  default_table_ordering->resize(TRUE_TYPE_TABLE_ORDERING_SIZE);
20530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  std::copy(TRUE_TYPE_TABLE_ORDERING,
20630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun            TRUE_TYPE_TABLE_ORDERING + TRUE_TYPE_TABLE_ORDERING_SIZE,
20730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun            default_table_ordering->begin());
20830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
20930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
21030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
21130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Font::Builder class
21230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
21330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFont::Builder::~Builder() {}
21430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
21530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(FontFactory* factory,
21630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                          InputStream* is) {
21730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontBuilderPtr builder = new Builder(factory);
21830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder->LoadFont(is);
21930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder.Detach();
22030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
22130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
22230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
22330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FontFactory* factory,
22430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    WritableFontData* wfd,
22530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t offset_to_offset_table) {
22630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontBuilderPtr builder = new Builder(factory);
22730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder->LoadFont(wfd, offset_to_offset_table);
22830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder.Detach();
22930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
23030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
23130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
23230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FontFactory* factory) {
23330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontBuilderPtr builder = new Builder(factory);
23430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder.Detach();
23530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
23630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
23730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool Font::Builder::ReadyToBuild() {
23830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // just read in data with no manipulation
23930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (table_builders_.empty() && !data_blocks_.empty()) {
24030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return true;
24130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
24230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
24330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // TODO(stuartg): font level checks - required tables etc?
24430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (TableBuilderMap::iterator table_builder = table_builders_.begin(),
24530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                 table_builder_end = table_builders_.end();
24630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                 table_builder != table_builder_end;
24730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                 ++table_builder) {
24830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (!table_builder->second->ReadyToBuild())
24930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return false;
25030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
25130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return true;
25230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
25330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
25430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH Font* Font::Builder::Build() {
25530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontPtr font = new Font(sfnt_version_, &digest_);
25630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
25730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!table_builders_.empty()) {
25830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // Note: Different from Java. Directly use font->tables_ here to avoid
25930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    //       STL container copying.
26030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    BuildTablesFromBuilders(font, &table_builders_, &font->tables_);
26130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
26230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
26330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  table_builders_.clear();
26430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  data_blocks_.clear();
26530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return font.Detach();
26630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
26730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
26830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::SetDigest(ByteVector* digest) {
26930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  digest_.clear();
27030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  digest_ = *digest;
27130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
27230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
27330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::ClearTableBuilders() {
27430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  table_builders_.clear();
27530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
27630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
27730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool Font::Builder::HasTableBuilder(int32_t tag) {
27830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return (table_builders_.find(tag) != table_builders_.end());
27930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
28030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
28130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunTable::Builder* Font::Builder::GetTableBuilder(int32_t tag) {
28230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (HasTableBuilder(tag))
28330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return table_builders_[tag];
28430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return NULL;
28530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
28630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
28730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunTable::Builder* Font::Builder::NewTableBuilder(int32_t tag) {
28830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  HeaderPtr header = new Header(tag);
28930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  TableBuilderPtr builder;
29030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder.Attach(Table::Builder::GetBuilder(header, NULL));
29130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  table_builders_.insert(TableBuilderEntry(header->tag(), builder));
29230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder;
29330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
29430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
29530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunTable::Builder* Font::Builder::NewTableBuilder(int32_t tag,
29630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                               ReadableFontData* src_data) {
29730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(src_data);
29830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  WritableFontDataPtr data;
29930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  data.Attach(WritableFontData::CreateWritableFontData(src_data->Length()));
30030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // TODO(stuarg): take over original data instead?
30130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  src_data->CopyTo(data);
30230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
30330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  HeaderPtr header = new Header(tag, data->Length());
30430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  TableBuilderPtr builder;
30530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder.Attach(Table::Builder::GetBuilder(header, data));
30630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  table_builders_.insert(TableBuilderEntry(tag, builder));
30730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder;
30830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
30930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
31030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::RemoveTableBuilder(int32_t tag) {
31130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  TableBuilderMap::iterator target = table_builders_.find(tag);
31230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (target != table_builders_.end()) {
31330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    table_builders_.erase(target);
31430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
31530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
31630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
31730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFont::Builder::Builder(FontFactory* factory)
31830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : factory_(factory),
31930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      sfnt_version_(Fixed1616::Fixed(SFNTVERSION_MAJOR, SFNTVERSION_MINOR)) {
32030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
32130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
32230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::LoadFont(InputStream* is) {
32330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // Note: we do not throw exception here for is.  This is more of an assertion.
32430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(is);
32530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontInputStream font_is(is);
32630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  HeaderOffsetSortedSet records;
32730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ReadHeader(&font_is, &records);
32830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  LoadTableData(&records, &font_is, &data_blocks_);
32930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  BuildAllTableBuilders(&data_blocks_, &table_builders_);
33030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  font_is.Close();
33130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
33230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
33330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::LoadFont(WritableFontData* wfd,
33430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                             int32_t offset_to_offset_table) {
33530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // Note: we do not throw exception here for is.  This is more of an assertion.
33630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(wfd);
33730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  HeaderOffsetSortedSet records;
33830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ReadHeader(wfd, offset_to_offset_table, &records);
33930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  LoadTableData(&records, wfd, &data_blocks_);
34030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  BuildAllTableBuilders(&data_blocks_, &table_builders_);
34130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
34230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
34330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t Font::Builder::SfntWrapperSize() {
34430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Offset::kSfntHeaderSize +
34530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun         (Offset::kTableRecordSize * table_builders_.size());
34630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
34730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
34830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::BuildAllTableBuilders(DataBlockMap* table_data,
34930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                          TableBuilderMap* builder_map) {
35030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (DataBlockMap::iterator record = table_data->begin(),
35130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                              record_end = table_data->end();
35230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                              record != record_end; ++record) {
35330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    TableBuilderPtr builder;
35430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    builder.Attach(GetTableBuilder(record->first.p_, record->second.p_));
35530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    builder_map->insert(TableBuilderEntry(record->first->tag(), builder));
35630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
35730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  InterRelateBuilders(&table_builders_);
35830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
35930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
36030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH
36130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunTable::Builder* Font::Builder::GetTableBuilder(Header* header,
36230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                               WritableFontData* data) {
36330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Table::Builder::GetBuilder(header, data);
36430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
36530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
36630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::BuildTablesFromBuilders(Font* font,
36730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                            TableBuilderMap* builder_map,
36830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                            TableMap* table_map) {
36930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(font);
37030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  InterRelateBuilders(builder_map);
37130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
37230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // Now build all the tables.
37330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (TableBuilderMap::iterator builder = builder_map->begin(),
37430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                 builder_end = builder_map->end();
37530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                 builder != builder_end; ++builder) {
37630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    TablePtr table;
37730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (builder->second && builder->second->ReadyToBuild()) {
37830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      table.Attach(down_cast<Table*>(builder->second->Build()));
37930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
38030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (table == NULL) {
38130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      table_map->clear();
38230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
38330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      std::string builder_string = "Unable to build table - ";
38430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      char* table_name = TagToString(builder->first);
38530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      builder_string += table_name;
38630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      delete[] table_name;
38730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      throw RuntimeException(builder_string.c_str());
38830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
38930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return;
39030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
39130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    table_map->insert(TableMapEntry(table->header()->tag(), table));
39230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
39330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
39430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
39530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunstatic Table::Builder* GetBuilder(TableBuilderMap* builder_map, int32_t tag) {
39630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (builder_map) {
39730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    TableBuilderMap::iterator target = builder_map->find(tag);
39830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (target != builder_map->end()) {
39930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return target->second.p_;
40030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
40130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
40230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
40330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return NULL;
40430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
40530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
40630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) {
40730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Table::Builder* raw_head_builder = GetBuilder(builder_map, Tag::head);
40830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontHeaderTableBuilderPtr header_table_builder;
40930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (raw_head_builder != NULL) {
41030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      header_table_builder =
41130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          down_cast<FontHeaderTable::Builder*>(raw_head_builder);
41230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
41330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
41430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Table::Builder* raw_hhea_builder = GetBuilder(builder_map, Tag::hhea);
41530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  HorizontalHeaderTableBuilderPtr horizontal_header_builder;
41630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (raw_head_builder != NULL) {
41730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      horizontal_header_builder =
41830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          down_cast<HorizontalHeaderTable::Builder*>(raw_hhea_builder);
41930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
42030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
42130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Table::Builder* raw_maxp_builder = GetBuilder(builder_map, Tag::maxp);
42230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  MaximumProfileTableBuilderPtr max_profile_builder;
42330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (raw_maxp_builder != NULL) {
42430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      max_profile_builder =
42530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          down_cast<MaximumProfileTable::Builder*>(raw_maxp_builder);
42630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
42730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
42830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Table::Builder* raw_loca_builder = GetBuilder(builder_map, Tag::loca);
42930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  LocaTableBuilderPtr loca_table_builder;
43030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (raw_loca_builder != NULL) {
43130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      loca_table_builder = down_cast<LocaTable::Builder*>(raw_loca_builder);
43230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
43330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
43430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Table::Builder* raw_hmtx_builder = GetBuilder(builder_map, Tag::hmtx);
43530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  HorizontalMetricsTableBuilderPtr horizontal_metrics_builder;
43630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (raw_hmtx_builder != NULL) {
43730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      horizontal_metrics_builder =
43830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          down_cast<HorizontalMetricsTable::Builder*>(raw_hmtx_builder);
43930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
44030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
44130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SFNTLY_EXPERIMENTAL)
44230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Table::Builder* raw_hdmx_builder = GetBuilder(builder_map, Tag::hdmx);
44330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  HorizontalDeviceMetricsTableBuilderPtr hdmx_table_builder;
44430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (raw_hdmx_builder != NULL) {
44530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      hdmx_table_builder =
44630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          down_cast<HorizontalDeviceMetricsTable::Builder*>(raw_hdmx_builder);
44730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
44830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
44930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
45030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // set the inter table data required to build certain tables
45130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (horizontal_metrics_builder != NULL) {
45230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (max_profile_builder != NULL) {
45330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      horizontal_metrics_builder->SetNumGlyphs(
45430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          max_profile_builder->NumGlyphs());
45530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
45630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (horizontal_header_builder != NULL) {
45730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      horizontal_metrics_builder->SetNumberOfHMetrics(
45830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          horizontal_header_builder->NumberOfHMetrics());
45930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
46030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
46130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
46230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (loca_table_builder != NULL) {
46330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (max_profile_builder != NULL) {
46430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      loca_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs());
46530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
46630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (header_table_builder != NULL) {
46730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      loca_table_builder->set_format_version(
46830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          header_table_builder->IndexToLocFormat());
46930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
47030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
47130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
47230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SFNTLY_EXPERIMENTAL)
47330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // Note: In C++, hdmx_table_builder can be NULL in a subsetter.
47430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (max_profile_builder != NULL && hdmx_table_builder != NULL) {
47530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    hdmx_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs());
47630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
47730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
47830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
47930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
48030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::ReadHeader(FontInputStream* is,
48130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                               HeaderOffsetSortedSet* records) {
48230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(records);
48330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  sfnt_version_ = is->ReadFixed();
48430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  num_tables_ = is->ReadUShort();
48530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  search_range_ = is->ReadUShort();
48630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  entry_selector_ = is->ReadUShort();
48730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  range_shift_ = is->ReadUShort();
48830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
48930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t table_number = 0; table_number < num_tables_; ++table_number) {
49030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // Need to use temporary vars here.  C++ evaluates function parameters from
49130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // right to left and thus breaks the order of input stream.
49230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t tag = is->ReadULongAsInt();
49330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int64_t checksum = is->ReadULong();
49430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t offset = is->ReadULongAsInt();
49530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t length = is->ReadULongAsInt();
49630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    HeaderPtr table = new Header(tag, checksum, offset, length);
49730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    records->insert(table);
49830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
49930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
50030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
50130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::ReadHeader(ReadableFontData* fd,
50230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                               int32_t offset,
50330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                               HeaderOffsetSortedSet* records) {
50430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(records);
50530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  sfnt_version_ = fd->ReadFixed(offset + Offset::kSfntVersion);
50630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  num_tables_ = fd->ReadUShort(offset + Offset::kNumTables);
50730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  search_range_ = fd->ReadUShort(offset + Offset::kSearchRange);
50830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  entry_selector_ = fd->ReadUShort(offset + Offset::kEntrySelector);
50930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  range_shift_ = fd->ReadUShort(offset + Offset::kRangeShift);
51030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
51130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t table_offset = offset + Offset::kTableRecordBegin;
51230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t table_number = 0;
51330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun       table_number < num_tables_;
51430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun       table_number++, table_offset += Offset::kTableRecordSize) {
51530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t tag = fd->ReadULongAsInt(table_offset + Offset::kTableTag);
51630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int64_t checksum = fd->ReadULong(table_offset + Offset::kTableCheckSum);
51730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t offset = fd->ReadULongAsInt(table_offset + Offset::kTableOffset);
51830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t length = fd->ReadULongAsInt(table_offset + Offset::kTableLength);
51930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    HeaderPtr table = new Header(tag, checksum, offset, length);
52030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    records->insert(table);
52130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
52230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
52330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
52430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
52530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  FontInputStream* is,
52630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  DataBlockMap* table_data) {
52730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(table_data);
52830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (HeaderOffsetSortedSet::iterator table_header = headers->begin(),
52930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       table_end = headers->end();
53030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       table_header != table_end;
53130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       ++table_header) {
53230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    is->Skip((*table_header)->offset() - is->position());
53330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FontInputStream table_is(is, (*table_header)->length());
53430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    WritableFontDataPtr data;
53530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    data.Attach(
53630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        WritableFontData::CreateWritableFontData((*table_header)->length()));
53730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    data->CopyFrom(&table_is, (*table_header)->length());
53830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    table_data->insert(DataBlockEntry(*table_header, data));
53930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
54030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
54130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
54230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
54330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  WritableFontData* fd,
54430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  DataBlockMap* table_data) {
54530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (HeaderOffsetSortedSet::iterator table_header = headers->begin(),
54630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       table_end = headers->end();
54730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       table_header != table_end;
54830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       ++table_header) {
54930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FontDataPtr sliced_data;
55030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    sliced_data.Attach(
55130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        fd->Slice((*table_header)->offset(), (*table_header)->length()));
55230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    WritableFontDataPtr data = down_cast<WritableFontData*>(sliced_data.p_);
55330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    table_data->insert(DataBlockEntry(*table_header, data));
55430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
55530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
55630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
55730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}  // namespace sfntly
558