195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu/*
295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * Copyright 2011 Google Inc. All Rights Reserved.
395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu *
495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * Licensed under the Apache License, Version 2.0 (the "License");
595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * you may not use this file except in compliance with the License.
695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * You may obtain a copy of the License at
795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu *
895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu *      http://www.apache.org/licenses/LICENSE-2.0
995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu *
1095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * Unless required by applicable law or agreed to in writing, software
1195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * distributed under the License is distributed on an "AS IS" BASIS,
1295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * See the License for the specific language governing permissions and
1495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * limitations under the License.
1595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu */
1695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
17c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu#include "sfntly/font.h"
18c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu
19f48f9495bfb5297171b933641a0a489cb86ad39bdfilimon#include <stdio.h>
20f48f9495bfb5297171b933641a0a489cb86ad39bdfilimon
2195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu#include <functional>
2295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu#include <algorithm>
2395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu#include <map>
24f48f9495bfb5297171b933641a0a489cb86ad39bdfilimon#include <string>
2595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu#include <typeinfo>
266a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu#include <iterator>
2795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
28c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu#include "sfntly/data/font_input_stream.h"
2995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu#include "sfntly/font_factory.h"
3095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu#include "sfntly/math/fixed1616.h"
3195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu#include "sfntly/math/font_math.h"
3295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu#include "sfntly/port/exception_type.h"
33584bf6606b53bda8bf0810e7c0ad57e24cacb4f1arthurhsu#include "sfntly/table/core/font_header_table.h"
349e5bf57583793d6db93bb01fd982760ad110a50farthurhsu#include "sfntly/table/core/horizontal_device_metrics_table.h"
35584bf6606b53bda8bf0810e7c0ad57e24cacb4f1arthurhsu#include "sfntly/table/core/horizontal_header_table.h"
36584bf6606b53bda8bf0810e7c0ad57e24cacb4f1arthurhsu#include "sfntly/table/core/horizontal_metrics_table.h"
37584bf6606b53bda8bf0810e7c0ad57e24cacb4f1arthurhsu#include "sfntly/table/core/maximum_profile_table.h"
38584bf6606b53bda8bf0810e7c0ad57e24cacb4f1arthurhsu#include "sfntly/table/truetype/loca_table.h"
39c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu#include "sfntly/tag.h"
4095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
4195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsunamespace sfntly {
4295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
43813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhangnamespace {
44813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang
45813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhangconst int32_t kSFNTVersionMajor = 1;
46813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhangconst int32_t kSFNTVersionMinor = 0;
47813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang
48813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhangconst int32_t kMaxTableSize = 200 * 1024 * 1024;
49813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang
50813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang}  // namespace
5195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
5295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu/******************************************************************************
5395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * Font class
5495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu ******************************************************************************/
5595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsuFont::~Font() {}
5695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
57813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhangbool Font::HasTable(int32_t tag) const {
58813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang  return tables_.find(tag) != tables_.end();
5995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
6095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
61c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuTable* Font::GetTable(int32_t tag) {
62813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang  if (!HasTable(tag))
6395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    return NULL;
6495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  return tables_[tag];
6595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
6695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
676a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsuconst TableMap* Font::GetTableMap() {
6895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  return &tables_;
6995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
7095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
71c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::Serialize(OutputStream* os, IntegerList* table_ordering) {
7295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  assert(table_ordering);
7395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  IntegerList final_table_ordering;
746a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  GenerateTableOrdering(table_ordering, &final_table_ordering);
7595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  TableHeaderList table_records;
76c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  BuildTableHeadersForSerialization(&final_table_ordering, &table_records);
7795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
7895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  FontOutputStream fos(os);
79c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  SerializeHeader(&fos, &table_records);
80c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  SerializeTables(&fos, &table_records);
81c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu}
82c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu
836a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsuFont::Font(int32_t sfnt_version, ByteVector* digest)
846a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    : sfnt_version_(sfnt_version) {
85c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  // non-trivial assignments that makes debugging hard if placed in
86c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  // initialization list
87c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  digest_ = *digest;
8895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
8995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
90c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::BuildTableHeadersForSerialization(IntegerList* table_ordering,
9195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                             TableHeaderList* table_headers) {
9295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  assert(table_headers);
9395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  assert(table_ordering);
9495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
9595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  IntegerList final_table_ordering;
966a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  GenerateTableOrdering(table_ordering, &final_table_ordering);
97c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  int32_t table_offset = Offset::kTableRecordBegin + num_tables() *
9895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                         Offset::kTableRecordSize;
9995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  for (IntegerList::iterator tag = final_table_ordering.begin(),
10095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                             tag_end = final_table_ordering.end();
10195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                             tag != tag_end; ++tag) {
1026a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    if (tables_.find(*tag) == tables_.end()) {
1036a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu      continue;
1046a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    }
10595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    TablePtr table = tables_[*tag];
10695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    if (table != NULL) {
10728258feb374913d40c347932937500210ba23d7carthurhsu      HeaderPtr header =
10828258feb374913d40c347932937500210ba23d7carthurhsu          new Header(*tag, table->CalculatedChecksum(), table_offset,
10928258feb374913d40c347932937500210ba23d7carthurhsu                     table->header()->length());
11095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu      table_headers->push_back(header);
1116a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu      table_offset += (table->DataLength() + 3) & ~3;
11295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    }
11395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
11495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
11595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
116c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::SerializeHeader(FontOutputStream* fos,
11795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                           TableHeaderList* table_headers) {
118c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  fos->WriteFixed(sfnt_version_);
119c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  fos->WriteUShort(table_headers->size());
120c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  int32_t log2_of_max_power_of_2 = FontMath::Log2(table_headers->size());
12195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  int32_t search_range = 2 << (log2_of_max_power_of_2 - 1 + 4);
122c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  fos->WriteUShort(search_range);
123c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  fos->WriteUShort(log2_of_max_power_of_2);
124c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  fos->WriteUShort((table_headers->size() * 16) - search_range);
12595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
1266a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  HeaderTagSortedSet sorted_headers;
1276a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  std::copy(table_headers->begin(),
1286a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu            table_headers->end(),
1296a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu            std::inserter(sorted_headers, sorted_headers.end()));
1306a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu
1316a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  for (HeaderTagSortedSet::iterator record = sorted_headers.begin(),
1326a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu                                    record_end = sorted_headers.end();
1336a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu                                    record != record_end; ++record) {
134c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    fos->WriteULong((*record)->tag());
135c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    fos->WriteULong((int32_t)((*record)->checksum()));
136c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    fos->WriteULong((*record)->offset());
137c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    fos->WriteULong((*record)->length());
13895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
13995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
14095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
141c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::SerializeTables(FontOutputStream* fos,
14295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                           TableHeaderList* table_headers) {
1436a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  assert(fos);
1446a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  assert(table_headers);
14595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  for (TableHeaderList::iterator record = table_headers->begin(),
14695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                 end_of_headers = table_headers->end();
14795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                 record != end_of_headers; ++record) {
148c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    TablePtr target_table = GetTable((*record)->tag());
14995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    if (target_table == NULL) {
1506a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu#if !defined (SFNTLY_NO_EXCEPTION)
15195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu      throw IOException("Table out of sync with font header.");
152fa606d4385cc0cc97f319dc25c97f46b2d44f1b9arthurhsu#endif
1536a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu      return;
15495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    }
155c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    int32_t table_size = target_table->Serialize(fos);
15674dd654d997383188b37566661cbce34a8b82154arthurhsu    if (table_size != (*record)->length()) {
15774dd654d997383188b37566661cbce34a8b82154arthurhsu      assert(false);
15874dd654d997383188b37566661cbce34a8b82154arthurhsu    }
15995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    int32_t filler_size = ((table_size + 3) & ~3) - table_size;
1606a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    for (int32_t i = 0; i < filler_size; ++i) {
1616a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu      fos->Write(static_cast<byte_t>(0));
1626a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    }
16395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
16495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
16595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
1666a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsuvoid Font::GenerateTableOrdering(IntegerList* default_table_ordering,
1676a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu                                 IntegerList* table_ordering) {
16895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  assert(default_table_ordering);
16995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  assert(table_ordering);
17095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  table_ordering->clear();
17195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  if (default_table_ordering->empty()) {
172c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    DefaultTableOrdering(default_table_ordering);
17395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
17495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
17595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  typedef std::map<int32_t, bool> Int2Bool;
17695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  typedef std::pair<int32_t, bool> Int2BoolEntry;
17795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  Int2Bool tables_in_font;
17895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  for (TableMap::iterator table = tables_.begin(), table_end = tables_.end();
17995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                          table != table_end; ++table) {
18095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    tables_in_font.insert(Int2BoolEntry(table->first, false));
18195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
18295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  for (IntegerList::iterator tag = default_table_ordering->begin(),
18395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                             tag_end = default_table_ordering->end();
18495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                             tag != tag_end; ++tag) {
185c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    if (HasTable(*tag)) {
18695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu      table_ordering->push_back(*tag);
18795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu      tables_in_font[*tag] = true;
18895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    }
18995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
19095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  for (Int2Bool::iterator table = tables_in_font.begin(),
19195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                          table_end = tables_in_font.end();
19295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                          table != table_end; ++table) {
19395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    if (table->second == false)
19495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu      table_ordering->push_back(table->first);
19595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
19695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
19795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
198c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::DefaultTableOrdering(IntegerList* default_table_ordering) {
19995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  assert(default_table_ordering);
20095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  default_table_ordering->clear();
201c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  if (HasTable(Tag::CFF)) {
20295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    default_table_ordering->resize(CFF_TABLE_ORDERING_SIZE);
20395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    std::copy(CFF_TABLE_ORDERING, CFF_TABLE_ORDERING + CFF_TABLE_ORDERING_SIZE,
20495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu              default_table_ordering->begin());
20595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    return;
20695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
20795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  default_table_ordering->resize(TRUE_TYPE_TABLE_ORDERING_SIZE);
20895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  std::copy(TRUE_TYPE_TABLE_ORDERING,
20995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu            TRUE_TYPE_TABLE_ORDERING + TRUE_TYPE_TABLE_ORDERING_SIZE,
21095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu            default_table_ordering->begin());
21195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
21295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
21395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu/******************************************************************************
21495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu * Font::Builder class
21595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu ******************************************************************************/
21695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsuFont::Builder::~Builder() {}
21795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
2186a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsuCALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(FontFactory* factory,
2196a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu                                                          InputStream* is) {
22095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  FontBuilderPtr builder = new Builder(factory);
221c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  builder->LoadFont(is);
222c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  return builder.Detach();
22395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
22495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
225c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuCALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
2266a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    FontFactory* factory,
2276a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    WritableFontData* wfd,
2286a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    int32_t offset_to_offset_table) {
22995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  FontBuilderPtr builder = new Builder(factory);
2306a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  builder->LoadFont(wfd, offset_to_offset_table);
231c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  return builder.Detach();
23295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
23395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
234c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuCALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
23595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    FontFactory* factory) {
23695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  FontBuilderPtr builder = new Builder(factory);
237c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  return builder.Detach();
23895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
23995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
240c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsubool Font::Builder::ReadyToBuild() {
24195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  // just read in data with no manipulation
24295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  if (table_builders_.empty() && !data_blocks_.empty()) {
24395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    return true;
24495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
24595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
2466a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  // TODO(stuartg): font level checks - required tables etc?
24795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  for (TableBuilderMap::iterator table_builder = table_builders_.begin(),
24895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                 table_builder_end = table_builders_.end();
24995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                 table_builder != table_builder_end;
25095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                 ++table_builder) {
251c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    if (!table_builder->second->ReadyToBuild())
25295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu      return false;
25395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
25495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  return true;
25595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
25695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
257c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuCALLER_ATTACH Font* Font::Builder::Build() {
2586a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  FontPtr font = new Font(sfnt_version_, &digest_);
2596a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu
26095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  if (!table_builders_.empty()) {
2616a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    // Note: Different from Java. Directly use font->tables_ here to avoid
2626a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    //       STL container copying.
2636a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu    BuildTablesFromBuilders(font, &table_builders_, &font->tables_);
26495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
2656a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu
26695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  table_builders_.clear();
26795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  data_blocks_.clear();
268c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  return font.Detach();
26995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
27095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
271c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::Builder::SetDigest(ByteVector* digest) {
27295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  digest_.clear();
27395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  digest_ = *digest;
27495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
27595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
2766a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsuvoid Font::Builder::ClearTableBuilders() {
27795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  table_builders_.clear();
27895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
27995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
280c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsubool Font::Builder::HasTableBuilder(int32_t tag) {
28195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  return (table_builders_.find(tag) != table_builders_.end());
28295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
28395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
284c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuTable::Builder* Font::Builder::GetTableBuilder(int32_t tag) {
285c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  if (HasTableBuilder(tag))
28695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    return table_builders_[tag];
28795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  return NULL;
28895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
28995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
290f48f9495bfb5297171b933641a0a489cb86ad39bdfilimonTable::Builder* Font::Builder::NewTableBuilder(int32_t tag) {
29128258feb374913d40c347932937500210ba23d7carthurhsu  HeaderPtr header = new Header(tag);
292f48f9495bfb5297171b933641a0a489cb86ad39bdfilimon  TableBuilderPtr builder;
2936a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  builder.Attach(Table::Builder::GetBuilder(header, NULL));
29495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  table_builders_.insert(TableBuilderEntry(header->tag(), builder));
29595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  return builder;
29695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
29795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
298f48f9495bfb5297171b933641a0a489cb86ad39bdfilimonTable::Builder* Font::Builder::NewTableBuilder(int32_t tag,
299f48f9495bfb5297171b933641a0a489cb86ad39bdfilimon                                               ReadableFontData* src_data) {
3006a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  assert(src_data);
30195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  WritableFontDataPtr data;
3026a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  data.Attach(WritableFontData::CreateWritableFontData(src_data->Length()));
303158cdcb9cf09418ba8b49f4be7be69e37aa8e9faarthurhsu  // TODO(stuarg): take over original data instead?
304158cdcb9cf09418ba8b49f4be7be69e37aa8e9faarthurhsu  src_data->CopyTo(data);
305158cdcb9cf09418ba8b49f4be7be69e37aa8e9faarthurhsu
30628258feb374913d40c347932937500210ba23d7carthurhsu  HeaderPtr header = new Header(tag, data->Length());
307f48f9495bfb5297171b933641a0a489cb86ad39bdfilimon  TableBuilderPtr builder;
3086a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  builder.Attach(Table::Builder::GetBuilder(header, data));
30995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  table_builders_.insert(TableBuilderEntry(tag, builder));
31095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  return builder;
31195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
31295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
313c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::Builder::RemoveTableBuilder(int32_t tag) {
314813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang  table_builders_.erase(tag);
31595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
31695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
317c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuFont::Builder::Builder(FontFactory* factory)
3189d49ee2650b0ffd660ff22f93ca9a6831847446farthurhsu    : factory_(factory),
319813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang      sfnt_version_(Fixed1616::Fixed(kSFNTVersionMajor, kSFNTVersionMinor)) {
320c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu}
321c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu
322c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::Builder::LoadFont(InputStream* is) {
323c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  // Note: we do not throw exception here for is.  This is more of an assertion.
324c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  assert(is);
325c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  FontInputStream font_is(is);
3266a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  HeaderOffsetSortedSet records;
327c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  ReadHeader(&font_is, &records);
328c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  LoadTableData(&records, &font_is, &data_blocks_);
329c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  BuildAllTableBuilders(&data_blocks_, &table_builders_);
330c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  font_is.Close();
331c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu}
332c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu
3336a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsuvoid Font::Builder::LoadFont(WritableFontData* wfd,
334c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu                             int32_t offset_to_offset_table) {
335c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  // Note: we do not throw exception here for is.  This is more of an assertion.
3366a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  assert(wfd);
3376a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  HeaderOffsetSortedSet records;
3386a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  ReadHeader(wfd, offset_to_offset_table, &records);
3396a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  LoadTableData(&records, wfd, &data_blocks_);
340c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  BuildAllTableBuilders(&data_blocks_, &table_builders_);
34195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
34295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
343c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuint32_t Font::Builder::SfntWrapperSize() {
34495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  return Offset::kSfntHeaderSize +
34595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu         (Offset::kTableRecordSize * table_builders_.size());
34695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
34795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
348c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::Builder::BuildAllTableBuilders(DataBlockMap* table_data,
34995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                          TableBuilderMap* builder_map) {
35095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  for (DataBlockMap::iterator record = table_data->begin(),
35195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                              record_end = table_data->end();
35295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                              record != record_end; ++record) {
35395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    TableBuilderPtr builder;
354c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    builder.Attach(GetTableBuilder(record->first.p_, record->second.p_));
35595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    builder_map->insert(TableBuilderEntry(record->first->tag(), builder));
35695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
357c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  InterRelateBuilders(&table_builders_);
35895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
35995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
3606a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsuCALLER_ATTACH
36128258feb374913d40c347932937500210ba23d7carthurhsuTable::Builder* Font::Builder::GetTableBuilder(Header* header,
3626a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu                                               WritableFontData* data) {
3636a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  return Table::Builder::GetBuilder(header, data);
36495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
36595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
3666a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsuvoid Font::Builder::BuildTablesFromBuilders(Font* font,
3676a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu                                            TableBuilderMap* builder_map,
36895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                            TableMap* table_map) {
3696a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu  UNREFERENCED_PARAMETER(font);
370c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  InterRelateBuilders(builder_map);
37195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
37295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  // Now build all the tables.
37395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  for (TableBuilderMap::iterator builder = builder_map->begin(),
37495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                 builder_end = builder_map->end();
37528258feb374913d40c347932937500210ba23d7carthurhsu                                 builder != builder_end; ++builder) {
37695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    TablePtr table;
3772f57786796743446495a41f1a1f8688b13fa1a86arthurhsu    if (builder->second && builder->second->ReadyToBuild()) {
378158cdcb9cf09418ba8b49f4be7be69e37aa8e9faarthurhsu      table.Attach(down_cast<Table*>(builder->second->Build()));
37995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    }
38095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    if (table == NULL) {
3812ac95dcf52d76634fba3f8fa81c575424f01d992arthurhsu      table_map->clear();
3826a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu#if !defined (SFNTLY_NO_EXCEPTION)
3836a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu      std::string builder_string = "Unable to build table - ";
3846a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu      char* table_name = TagToString(builder->first);
3856a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu      builder_string += table_name;
3866a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu      delete[] table_name;
38795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu      throw RuntimeException(builder_string.c_str());
388fa606d4385cc0cc97f319dc25c97f46b2d44f1b9arthurhsu#endif
3896a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu      return;
39095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    }
39195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    table_map->insert(TableMapEntry(table->header()->tag(), table));
39295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
39395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
39495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
3953eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsustatic Table::Builder* GetBuilder(TableBuilderMap* builder_map, int32_t tag) {
396083b02b10572142d9863d945a8cf52fed2df997dLei Zhang  if (!builder_map)
397083b02b10572142d9863d945a8cf52fed2df997dLei Zhang    return NULL;
3983eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu
399083b02b10572142d9863d945a8cf52fed2df997dLei Zhang  TableBuilderMap::iterator target = builder_map->find(tag);
400083b02b10572142d9863d945a8cf52fed2df997dLei Zhang  if (target == builder_map->end())
401083b02b10572142d9863d945a8cf52fed2df997dLei Zhang    return NULL;
402083b02b10572142d9863d945a8cf52fed2df997dLei Zhang
403ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang  return target->second.p_;
404ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang}
405ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang
406ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang// Like GetBuilder(), but the returned Builder must be able to support reads.
407ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhangstatic Table::Builder* GetReadBuilder(TableBuilderMap* builder_map, int32_t tag) {
408ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang  Table::Builder* builder = GetBuilder(builder_map, tag);
409083b02b10572142d9863d945a8cf52fed2df997dLei Zhang  if (!builder || !builder->InternalReadData())
410083b02b10572142d9863d945a8cf52fed2df997dLei Zhang    return NULL;
411083b02b10572142d9863d945a8cf52fed2df997dLei Zhang
412083b02b10572142d9863d945a8cf52fed2df997dLei Zhang  return builder;
4133eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu}
4143eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu
415c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) {
416ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang  Table::Builder* raw_head_builder = GetReadBuilder(builder_map, Tag::head);
4173eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  FontHeaderTableBuilderPtr header_table_builder;
4183eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  if (raw_head_builder != NULL) {
419ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang    header_table_builder =
420ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang        down_cast<FontHeaderTable::Builder*>(raw_head_builder);
4213eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  }
4223eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu
423ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang  Table::Builder* raw_hhea_builder = GetReadBuilder(builder_map, Tag::hhea);
4243eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  HorizontalHeaderTableBuilderPtr horizontal_header_builder;
4253eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  if (raw_head_builder != NULL) {
426ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang    horizontal_header_builder =
427ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang        down_cast<HorizontalHeaderTable::Builder*>(raw_hhea_builder);
4283eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  }
4293eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu
430ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang  Table::Builder* raw_maxp_builder = GetReadBuilder(builder_map, Tag::maxp);
4313eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  MaximumProfileTableBuilderPtr max_profile_builder;
4323eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  if (raw_maxp_builder != NULL) {
433ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang    max_profile_builder =
434ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang        down_cast<MaximumProfileTable::Builder*>(raw_maxp_builder);
4353eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  }
4363eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu
4373eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  Table::Builder* raw_loca_builder = GetBuilder(builder_map, Tag::loca);
4383eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  LocaTableBuilderPtr loca_table_builder;
4393eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  if (raw_loca_builder != NULL) {
440ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang    loca_table_builder = down_cast<LocaTable::Builder*>(raw_loca_builder);
4413eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  }
4423eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu
4433eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  Table::Builder* raw_hmtx_builder = GetBuilder(builder_map, Tag::hmtx);
4443eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  HorizontalMetricsTableBuilderPtr horizontal_metrics_builder;
4453eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  if (raw_hmtx_builder != NULL) {
446ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang    horizontal_metrics_builder =
447ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang        down_cast<HorizontalMetricsTable::Builder*>(raw_hmtx_builder);
4483eca5f26ef52cfef7d814f35fd52deb4c097531aarthurhsu  }
44995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
4509e5bf57583793d6db93bb01fd982760ad110a50farthurhsu#if defined (SFNTLY_EXPERIMENTAL)
4519e5bf57583793d6db93bb01fd982760ad110a50farthurhsu  Table::Builder* raw_hdmx_builder = GetBuilder(builder_map, Tag::hdmx);
4529e5bf57583793d6db93bb01fd982760ad110a50farthurhsu  HorizontalDeviceMetricsTableBuilderPtr hdmx_table_builder;
4539e5bf57583793d6db93bb01fd982760ad110a50farthurhsu  if (raw_hdmx_builder != NULL) {
454ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang    hdmx_table_builder =
455ebaa364dd0e270b6954331dc5ffb5fe4462de372Lei Zhang        down_cast<HorizontalDeviceMetricsTable::Builder*>(raw_hdmx_builder);
4569e5bf57583793d6db93bb01fd982760ad110a50farthurhsu  }
4579e5bf57583793d6db93bb01fd982760ad110a50farthurhsu#endif
4589e5bf57583793d6db93bb01fd982760ad110a50farthurhsu
45995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  // set the inter table data required to build certain tables
46095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  if (horizontal_metrics_builder != NULL) {
46195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    if (max_profile_builder != NULL) {
462c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu      horizontal_metrics_builder->SetNumGlyphs(
463c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu          max_profile_builder->NumGlyphs());
46495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    }
46595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    if (horizontal_header_builder != NULL) {
466c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu      horizontal_metrics_builder->SetNumberOfHMetrics(
467c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu          horizontal_header_builder->NumberOfHMetrics());
46895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    }
46995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
47095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
47195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  if (loca_table_builder != NULL) {
47295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    if (max_profile_builder != NULL) {
473c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu      loca_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs());
47495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    }
47595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    if (header_table_builder != NULL) {
4766a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu      loca_table_builder->set_format_version(
477c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu          header_table_builder->IndexToLocFormat());
47895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    }
47995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
4809e5bf57583793d6db93bb01fd982760ad110a50farthurhsu
4819e5bf57583793d6db93bb01fd982760ad110a50farthurhsu#if defined (SFNTLY_EXPERIMENTAL)
4829e5bf57583793d6db93bb01fd982760ad110a50farthurhsu  // Note: In C++, hdmx_table_builder can be NULL in a subsetter.
4839e5bf57583793d6db93bb01fd982760ad110a50farthurhsu  if (max_profile_builder != NULL && hdmx_table_builder != NULL) {
4849e5bf57583793d6db93bb01fd982760ad110a50farthurhsu    hdmx_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs());
4859e5bf57583793d6db93bb01fd982760ad110a50farthurhsu  }
4869e5bf57583793d6db93bb01fd982760ad110a50farthurhsu#endif
48795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
48895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
489c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::Builder::ReadHeader(FontInputStream* is,
4906a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu                               HeaderOffsetSortedSet* records) {
49195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  assert(records);
492c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  sfnt_version_ = is->ReadFixed();
493c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  num_tables_ = is->ReadUShort();
494c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  search_range_ = is->ReadUShort();
495c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  entry_selector_ = is->ReadUShort();
496c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  range_shift_ = is->ReadUShort();
49795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
49895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  for (int32_t table_number = 0; table_number < num_tables_; ++table_number) {
49995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    // Need to use temporary vars here.  C++ evaluates function parameters from
50095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    // right to left and thus breaks the order of input stream.
501c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    int32_t tag = is->ReadULongAsInt();
502c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    int64_t checksum = is->ReadULong();
503c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    int32_t offset = is->ReadULongAsInt();
504c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    int32_t length = is->ReadULongAsInt();
50528258feb374913d40c347932937500210ba23d7carthurhsu    HeaderPtr table = new Header(tag, checksum, offset, length);
50695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    records->insert(table);
50795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
50895efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
50995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
510c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsuvoid Font::Builder::ReadHeader(ReadableFontData* fd,
511c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu                               int32_t offset,
5126a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu                               HeaderOffsetSortedSet* records) {
513c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  assert(records);
514c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  sfnt_version_ = fd->ReadFixed(offset + Offset::kSfntVersion);
515c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  num_tables_ = fd->ReadUShort(offset + Offset::kNumTables);
516c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  search_range_ = fd->ReadUShort(offset + Offset::kSearchRange);
517c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  entry_selector_ = fd->ReadUShort(offset + Offset::kEntrySelector);
518c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  range_shift_ = fd->ReadUShort(offset + Offset::kRangeShift);
519c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu
520c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  int32_t table_offset = offset + Offset::kTableRecordBegin;
521c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  for (int32_t table_number = 0;
522c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu       table_number < num_tables_;
523c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu       table_number++, table_offset += Offset::kTableRecordSize) {
524c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    int32_t tag = fd->ReadULongAsInt(table_offset + Offset::kTableTag);
525c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    int64_t checksum = fd->ReadULong(table_offset + Offset::kTableCheckSum);
526c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    int32_t offset = fd->ReadULongAsInt(table_offset + Offset::kTableOffset);
527c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    int32_t length = fd->ReadULongAsInt(table_offset + Offset::kTableLength);
52828258feb374913d40c347932937500210ba23d7carthurhsu    HeaderPtr table = new Header(tag, checksum, offset, length);
529c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu    records->insert(table);
530c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu  }
531c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu}
532c143ecb4bbc4f3ccca5145dc2b17cc20ca738efearthurhsu
5336a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsuvoid Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
53495efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                  FontInputStream* is,
53595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                  DataBlockMap* table_data) {
53695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  assert(table_data);
537813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang  for (HeaderOffsetSortedSet::iterator it = headers->begin(),
5386a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu                                       table_end = headers->end();
539813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang                                       it != table_end;
540813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang                                       ++it) {
541813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    const Ptr<Header> header = *it;
542813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    is->Skip(header->offset() - is->position());
543813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    if (header->length() > kMaxTableSize)
544813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang      continue;
545813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang
546813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    FontInputStream table_is(is, header->length());
54787114756046ef50158ad5bbf357bf40e05ebdd94arthurhsu    WritableFontDataPtr data;
548813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    data.Attach(WritableFontData::CreateWritableFontData(header->length()));
549813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    data->CopyFrom(&table_is, header->length());
550813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    table_data->insert(DataBlockEntry(header, data));
55195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
55295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
55395efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
5546a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsuvoid Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
55595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                  WritableFontData* fd,
55695efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu                                  DataBlockMap* table_data) {
557813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang  for (HeaderOffsetSortedSet::iterator it = headers->begin(),
5586a2a8e7db878d1115d600c3be02e2700d8b372bcarthurhsu                                       table_end = headers->end();
559813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang                                       it != table_end;
560813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang                                       ++it) {
561813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    const Ptr<Header> header = *it;
562813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    if (header->length() > kMaxTableSize)
563813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang      continue;
564813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang
56595efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    FontDataPtr sliced_data;
566813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    sliced_data.Attach(fd->Slice(header->offset(), header->length()));
56795efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu    WritableFontDataPtr data = down_cast<WritableFontData*>(sliced_data.p_);
568813efeb18bf6205354b01a525352ebdb10eebe06Lei Zhang    table_data->insert(DataBlockEntry(header, data));
56995efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu  }
57095efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}
57195efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu
57295efcd4ba41e367b466b7206a942605bbbbb2c9arthurhsu}  // namespace sfntly
573