1464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/*
2464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Copyright 2011 Google Inc. All Rights Reserved.
3464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *
4464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Licensed under the Apache License, Version 2.0 (the "License");
5464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * you may not use this file except in compliance with the License.
6464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * You may obtain a copy of the License at
7464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *
8464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *      http://www.apache.org/licenses/LICENSE-2.0
9464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *
10464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Unless required by applicable law or agreed to in writing, software
11464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * distributed under the License is distributed on an "AS IS" BASIS,
12464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * See the License for the specific language governing permissions and
14464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * limitations under the License.
15464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com */
16464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
17246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com#include "sfntly/font.h"
18246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
196c4f92bcc799598f6fcba4b3c7d4d549da9a8491dfilimon@google.com#include <stdio.h>
206c4f92bcc799598f6fcba4b3c7d4d549da9a8491dfilimon@google.com
21464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include <functional>
22464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include <algorithm>
23464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include <map>
246c4f92bcc799598f6fcba4b3c7d4d549da9a8491dfilimon@google.com#include <string>
25464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include <typeinfo>
26b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#include <iterator>
27464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
28246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com#include "sfntly/data/font_input_stream.h"
29464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/font_factory.h"
30464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/math/fixed1616.h"
31464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/math/font_math.h"
32464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/port/exception_type.h"
335af34fd773f8cfee82321393504f558ddf67c628arthurhsu@google.com#include "sfntly/table/core/font_header_table.h"
34a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com#include "sfntly/table/core/horizontal_device_metrics_table.h"
355af34fd773f8cfee82321393504f558ddf67c628arthurhsu@google.com#include "sfntly/table/core/horizontal_header_table.h"
365af34fd773f8cfee82321393504f558ddf67c628arthurhsu@google.com#include "sfntly/table/core/horizontal_metrics_table.h"
375af34fd773f8cfee82321393504f558ddf67c628arthurhsu@google.com#include "sfntly/table/core/maximum_profile_table.h"
385af34fd773f8cfee82321393504f558ddf67c628arthurhsu@google.com#include "sfntly/table/truetype/loca_table.h"
39246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com#include "sfntly/tag.h"
40464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
41464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comnamespace sfntly {
42464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
43a70737a5b6ca5cd32e1a47adb847e1d016e1502barthurhsu@google.comconst int32_t SFNTVERSION_MAJOR = 1;
44a70737a5b6ca5cd32e1a47adb847e1d016e1502barthurhsu@google.comconst int32_t SFNTVERSION_MINOR = 0;
45464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
46464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/******************************************************************************
47464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Font class
48464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ******************************************************************************/
49464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comFont::~Font() {}
50464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
51246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool Font::HasTable(int32_t tag) {
52464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  TableMap::const_iterator result = tables_.find(tag);
53464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  TableMap::const_iterator end = tables_.end();
54464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return (result != end);
55464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
56464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
57246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comTable* Font::GetTable(int32_t tag) {
58246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  if (!HasTable(tag)) {
59464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return NULL;
60464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
61464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return tables_[tag];
62464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
63464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
64b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comconst TableMap* Font::GetTableMap() {
65464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return &tables_;
66464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
67464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
68246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::Serialize(OutputStream* os, IntegerList* table_ordering) {
69464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(table_ordering);
70464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  IntegerList final_table_ordering;
71b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  GenerateTableOrdering(table_ordering, &final_table_ordering);
72464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  TableHeaderList table_records;
73246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  BuildTableHeadersForSerialization(&final_table_ordering, &table_records);
74464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
75464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  FontOutputStream fos(os);
76246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  SerializeHeader(&fos, &table_records);
77246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  SerializeTables(&fos, &table_records);
78246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
79246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
80b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comFont::Font(int32_t sfnt_version, ByteVector* digest)
81b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    : sfnt_version_(sfnt_version) {
82246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  // non-trivial assignments that makes debugging hard if placed in
83246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  // initialization list
84246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  digest_ = *digest;
85464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
86464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
87246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::BuildTableHeadersForSerialization(IntegerList* table_ordering,
88464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                             TableHeaderList* table_headers) {
89464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(table_headers);
90464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(table_ordering);
91464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
92464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  IntegerList final_table_ordering;
93b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  GenerateTableOrdering(table_ordering, &final_table_ordering);
94246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t table_offset = Offset::kTableRecordBegin + num_tables() *
95464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                         Offset::kTableRecordSize;
96464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  for (IntegerList::iterator tag = final_table_ordering.begin(),
97464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                             tag_end = final_table_ordering.end();
98464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                             tag != tag_end; ++tag) {
99b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    if (tables_.find(*tag) == tables_.end()) {
100b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com      continue;
101b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    }
102464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    TablePtr table = tables_[*tag];
103464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    if (table != NULL) {
1046b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com      HeaderPtr header =
1056b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com          new Header(*tag, table->CalculatedChecksum(), table_offset,
1066b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com                     table->header()->length());
107464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com      table_headers->push_back(header);
108b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com      table_offset += (table->DataLength() + 3) & ~3;
109464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
110464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
111464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
112464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
113246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::SerializeHeader(FontOutputStream* fos,
114464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                           TableHeaderList* table_headers) {
115246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  fos->WriteFixed(sfnt_version_);
116246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  fos->WriteUShort(table_headers->size());
117246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t log2_of_max_power_of_2 = FontMath::Log2(table_headers->size());
118464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t search_range = 2 << (log2_of_max_power_of_2 - 1 + 4);
119246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  fos->WriteUShort(search_range);
120246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  fos->WriteUShort(log2_of_max_power_of_2);
121246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  fos->WriteUShort((table_headers->size() * 16) - search_range);
122464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
123b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  HeaderTagSortedSet sorted_headers;
124b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  std::copy(table_headers->begin(),
125b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com            table_headers->end(),
126b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com            std::inserter(sorted_headers, sorted_headers.end()));
127b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com
128b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  for (HeaderTagSortedSet::iterator record = sorted_headers.begin(),
129b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                    record_end = sorted_headers.end();
130b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                    record != record_end; ++record) {
131246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    fos->WriteULong((*record)->tag());
132246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    fos->WriteULong((int32_t)((*record)->checksum()));
133246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    fos->WriteULong((*record)->offset());
134246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    fos->WriteULong((*record)->length());
135464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
136464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
137464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
138246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::SerializeTables(FontOutputStream* fos,
139464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                           TableHeaderList* table_headers) {
140b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  assert(fos);
141b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  assert(table_headers);
142464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  for (TableHeaderList::iterator record = table_headers->begin(),
143464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                 end_of_headers = table_headers->end();
144464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                 record != end_of_headers; ++record) {
145246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    TablePtr target_table = GetTable((*record)->tag());
146464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    if (target_table == NULL) {
147b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
148464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com      throw IOException("Table out of sync with font header.");
1490e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif
150b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com      return;
151464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
152246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    int32_t table_size = target_table->Serialize(fos);
153ed8406cf320973d04bbe348c681090b1feba3d68arthurhsu@google.com    if (table_size != (*record)->length()) {
154ed8406cf320973d04bbe348c681090b1feba3d68arthurhsu@google.com      assert(false);
155ed8406cf320973d04bbe348c681090b1feba3d68arthurhsu@google.com    }
156464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    int32_t filler_size = ((table_size + 3) & ~3) - table_size;
157b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    for (int32_t i = 0; i < filler_size; ++i) {
158b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com      fos->Write(static_cast<byte_t>(0));
159b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    }
160464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
161464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
162464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
163b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comvoid Font::GenerateTableOrdering(IntegerList* default_table_ordering,
164b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                 IntegerList* table_ordering) {
165464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(default_table_ordering);
166464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(table_ordering);
167464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  table_ordering->clear();
168464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (default_table_ordering->empty()) {
169246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    DefaultTableOrdering(default_table_ordering);
170464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
171464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
172464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  typedef std::map<int32_t, bool> Int2Bool;
173464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  typedef std::pair<int32_t, bool> Int2BoolEntry;
174464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  Int2Bool tables_in_font;
175464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  for (TableMap::iterator table = tables_.begin(), table_end = tables_.end();
176464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                          table != table_end; ++table) {
177464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    tables_in_font.insert(Int2BoolEntry(table->first, false));
178464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
179464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  for (IntegerList::iterator tag = default_table_ordering->begin(),
180464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                             tag_end = default_table_ordering->end();
181464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                             tag != tag_end; ++tag) {
182246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    if (HasTable(*tag)) {
183464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com      table_ordering->push_back(*tag);
184464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com      tables_in_font[*tag] = true;
185464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
186464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
187464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  for (Int2Bool::iterator table = tables_in_font.begin(),
188464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                          table_end = tables_in_font.end();
189464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                          table != table_end; ++table) {
190464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    if (table->second == false)
191464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com      table_ordering->push_back(table->first);
192464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
193464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
194464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
195246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::DefaultTableOrdering(IntegerList* default_table_ordering) {
196464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(default_table_ordering);
197464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  default_table_ordering->clear();
198246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  if (HasTable(Tag::CFF)) {
199464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    default_table_ordering->resize(CFF_TABLE_ORDERING_SIZE);
200464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    std::copy(CFF_TABLE_ORDERING, CFF_TABLE_ORDERING + CFF_TABLE_ORDERING_SIZE,
201464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com              default_table_ordering->begin());
202464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return;
203464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
204464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  default_table_ordering->resize(TRUE_TYPE_TABLE_ORDERING_SIZE);
205464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  std::copy(TRUE_TYPE_TABLE_ORDERING,
206464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com            TRUE_TYPE_TABLE_ORDERING + TRUE_TYPE_TABLE_ORDERING_SIZE,
207464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com            default_table_ordering->begin());
208464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
209464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
210464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/******************************************************************************
211464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Font::Builder class
212464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ******************************************************************************/
213464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comFont::Builder::~Builder() {}
214464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
215b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(FontFactory* factory,
216b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                                          InputStream* is) {
217464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  FontBuilderPtr builder = new Builder(factory);
218246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  builder->LoadFont(is);
219246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return builder.Detach();
220464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
221464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
222246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
223b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    FontFactory* factory,
224b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    WritableFontData* wfd,
225b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    int32_t offset_to_offset_table) {
226464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  FontBuilderPtr builder = new Builder(factory);
227b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  builder->LoadFont(wfd, offset_to_offset_table);
228246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return builder.Detach();
229464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
230464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
231246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH Font::Builder* Font::Builder::GetOTFBuilder(
232464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    FontFactory* factory) {
233464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  FontBuilderPtr builder = new Builder(factory);
234246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return builder.Detach();
235464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
236464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
237246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool Font::Builder::ReadyToBuild() {
238464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  // just read in data with no manipulation
239464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (table_builders_.empty() && !data_blocks_.empty()) {
240464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return true;
241464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
242464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
243b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  // TODO(stuartg): font level checks - required tables etc?
244464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  for (TableBuilderMap::iterator table_builder = table_builders_.begin(),
245464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                 table_builder_end = table_builders_.end();
246464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                 table_builder != table_builder_end;
247464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                 ++table_builder) {
248246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    if (!table_builder->second->ReadyToBuild())
249464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com      return false;
250464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
251464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return true;
252464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
253464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
254246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH Font* Font::Builder::Build() {
255b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  FontPtr font = new Font(sfnt_version_, &digest_);
256b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com
257464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (!table_builders_.empty()) {
258b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    // Note: Different from Java. Directly use font->tables_ here to avoid
259b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    //       STL container copying.
260b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    BuildTablesFromBuilders(font, &table_builders_, &font->tables_);
261464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
262b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com
263464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  table_builders_.clear();
264464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  data_blocks_.clear();
265246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return font.Detach();
266464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
267464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
268246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::Builder::SetDigest(ByteVector* digest) {
269464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  digest_.clear();
270464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  digest_ = *digest;
271464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
272464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
273b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comvoid Font::Builder::ClearTableBuilders() {
274464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  table_builders_.clear();
275464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
276464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
277246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool Font::Builder::HasTableBuilder(int32_t tag) {
278464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return (table_builders_.find(tag) != table_builders_.end());
279464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
280464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
281246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comTable::Builder* Font::Builder::GetTableBuilder(int32_t tag) {
282246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  if (HasTableBuilder(tag))
283464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return table_builders_[tag];
284464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return NULL;
285464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
286464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
2876c4f92bcc799598f6fcba4b3c7d4d549da9a8491dfilimon@google.comTable::Builder* Font::Builder::NewTableBuilder(int32_t tag) {
2886b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com  HeaderPtr header = new Header(tag);
2896c4f92bcc799598f6fcba4b3c7d4d549da9a8491dfilimon@google.com  TableBuilderPtr builder;
290b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  builder.Attach(Table::Builder::GetBuilder(header, NULL));
291464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  table_builders_.insert(TableBuilderEntry(header->tag(), builder));
292464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return builder;
293464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
294464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
2956c4f92bcc799598f6fcba4b3c7d4d549da9a8491dfilimon@google.comTable::Builder* Font::Builder::NewTableBuilder(int32_t tag,
2966c4f92bcc799598f6fcba4b3c7d4d549da9a8491dfilimon@google.com                                               ReadableFontData* src_data) {
297b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  assert(src_data);
298464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  WritableFontDataPtr data;
299b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  data.Attach(WritableFontData::CreateWritableFontData(src_data->Length()));
300333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com  // TODO(stuarg): take over original data instead?
301333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com  src_data->CopyTo(data);
302333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com
3036b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com  HeaderPtr header = new Header(tag, data->Length());
3046c4f92bcc799598f6fcba4b3c7d4d549da9a8491dfilimon@google.com  TableBuilderPtr builder;
305b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  builder.Attach(Table::Builder::GetBuilder(header, data));
306464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  table_builders_.insert(TableBuilderEntry(tag, builder));
307464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return builder;
308464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
309464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
310246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::Builder::RemoveTableBuilder(int32_t tag) {
311464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  TableBuilderMap::iterator target = table_builders_.find(tag);
312464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (target != table_builders_.end()) {
313464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    table_builders_.erase(target);
314464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
315464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
316464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
317246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comFont::Builder::Builder(FontFactory* factory)
318a70737a5b6ca5cd32e1a47adb847e1d016e1502barthurhsu@google.com    : factory_(factory),
319a70737a5b6ca5cd32e1a47adb847e1d016e1502barthurhsu@google.com      sfnt_version_(Fixed1616::Fixed(SFNTVERSION_MAJOR, SFNTVERSION_MINOR)) {
320246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
321246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
322246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::Builder::LoadFont(InputStream* is) {
323246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  // Note: we do not throw exception here for is.  This is more of an assertion.
324246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  assert(is);
325246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  FontInputStream font_is(is);
326b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  HeaderOffsetSortedSet records;
327246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  ReadHeader(&font_is, &records);
328246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  LoadTableData(&records, &font_is, &data_blocks_);
329246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  BuildAllTableBuilders(&data_blocks_, &table_builders_);
330246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  font_is.Close();
331246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
332246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
333b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comvoid Font::Builder::LoadFont(WritableFontData* wfd,
334246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                             int32_t offset_to_offset_table) {
335246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  // Note: we do not throw exception here for is.  This is more of an assertion.
336b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  assert(wfd);
337b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  HeaderOffsetSortedSet records;
338b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  ReadHeader(wfd, offset_to_offset_table, &records);
339b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  LoadTableData(&records, wfd, &data_blocks_);
340246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  BuildAllTableBuilders(&data_blocks_, &table_builders_);
341464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
342464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
343246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t Font::Builder::SfntWrapperSize() {
344464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return Offset::kSfntHeaderSize +
345464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com         (Offset::kTableRecordSize * table_builders_.size());
346464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
347464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
348246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::Builder::BuildAllTableBuilders(DataBlockMap* table_data,
349464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                          TableBuilderMap* builder_map) {
350464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  for (DataBlockMap::iterator record = table_data->begin(),
351464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                              record_end = table_data->end();
352464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                              record != record_end; ++record) {
353464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    TableBuilderPtr builder;
354246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    builder.Attach(GetTableBuilder(record->first.p_, record->second.p_));
355464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    builder_map->insert(TableBuilderEntry(record->first->tag(), builder));
356464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
357246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  InterRelateBuilders(&table_builders_);
358464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
359464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
360b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCALLER_ATTACH
3616b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.comTable::Builder* Font::Builder::GetTableBuilder(Header* header,
362b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                               WritableFontData* data) {
363b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  return Table::Builder::GetBuilder(header, data);
364464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
365464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
366b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comvoid Font::Builder::BuildTablesFromBuilders(Font* font,
367b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                            TableBuilderMap* builder_map,
368464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                            TableMap* table_map) {
369b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  UNREFERENCED_PARAMETER(font);
370246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  InterRelateBuilders(builder_map);
371464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
372464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  // Now build all the tables.
373464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  for (TableBuilderMap::iterator builder = builder_map->begin(),
374464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                 builder_end = builder_map->end();
3756b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com                                 builder != builder_end; ++builder) {
376464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    TablePtr table;
377bd74f6c542ef6b6d279edf08d6d7e5952bc4980earthurhsu@google.com    if (builder->second && builder->second->ReadyToBuild()) {
378333edd91cb32d6acfd0307ba2ae8f60baed75ff4arthurhsu@google.com      table.Attach(down_cast<Table*>(builder->second->Build()));
379464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
380464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    if (table == NULL) {
3813daf7a5c855b0640e2dd3904abe378e76a43829darthurhsu@google.com      table_map->clear();
382b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
383b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com      std::string builder_string = "Unable to build table - ";
384b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com      char* table_name = TagToString(builder->first);
385b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com      builder_string += table_name;
386b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com      delete[] table_name;
387464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com      throw RuntimeException(builder_string.c_str());
3880e411afcef9fc211b3f8f70d31bc1dfa4c0f85d3arthurhsu@google.com#endif
389b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com      return;
390464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
391464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    table_map->insert(TableMapEntry(table->header()->tag(), table));
392464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
393464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
394464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
395335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.comstatic Table::Builder* GetBuilder(TableBuilderMap* builder_map, int32_t tag) {
396335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  if (builder_map) {
397335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com    TableBuilderMap::iterator target = builder_map->find(tag);
398335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com    if (target != builder_map->end()) {
399335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com      return target->second.p_;
400335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com    }
401335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  }
402335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com
403335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  return NULL;
404335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com}
405335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com
406246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::Builder::InterRelateBuilders(TableBuilderMap* builder_map) {
407335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  Table::Builder* raw_head_builder = GetBuilder(builder_map, Tag::head);
408335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  FontHeaderTableBuilderPtr header_table_builder;
409335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  if (raw_head_builder != NULL) {
410335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com      header_table_builder =
411335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com          down_cast<FontHeaderTable::Builder*>(raw_head_builder);
412335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  }
413335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com
414335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  Table::Builder* raw_hhea_builder = GetBuilder(builder_map, Tag::hhea);
415335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  HorizontalHeaderTableBuilderPtr horizontal_header_builder;
416335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  if (raw_head_builder != NULL) {
417335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com      horizontal_header_builder =
418335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com          down_cast<HorizontalHeaderTable::Builder*>(raw_hhea_builder);
419335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  }
420335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com
421335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  Table::Builder* raw_maxp_builder = GetBuilder(builder_map, Tag::maxp);
422335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  MaximumProfileTableBuilderPtr max_profile_builder;
423335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  if (raw_maxp_builder != NULL) {
424335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com      max_profile_builder =
425335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com          down_cast<MaximumProfileTable::Builder*>(raw_maxp_builder);
426335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  }
427335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com
428335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  Table::Builder* raw_loca_builder = GetBuilder(builder_map, Tag::loca);
429335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  LocaTableBuilderPtr loca_table_builder;
430335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  if (raw_loca_builder != NULL) {
431335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com      loca_table_builder = down_cast<LocaTable::Builder*>(raw_loca_builder);
432335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  }
433335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com
434335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  Table::Builder* raw_hmtx_builder = GetBuilder(builder_map, Tag::hmtx);
435335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  HorizontalMetricsTableBuilderPtr horizontal_metrics_builder;
436335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  if (raw_hmtx_builder != NULL) {
437335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com      horizontal_metrics_builder =
438335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com          down_cast<HorizontalMetricsTable::Builder*>(raw_hmtx_builder);
439335643ef4bbe8029047fec80feaa5912a05b84f0arthurhsu@google.com  }
440464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
441a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com#if defined (SFNTLY_EXPERIMENTAL)
442a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com  Table::Builder* raw_hdmx_builder = GetBuilder(builder_map, Tag::hdmx);
443a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com  HorizontalDeviceMetricsTableBuilderPtr hdmx_table_builder;
444a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com  if (raw_hdmx_builder != NULL) {
445a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com      hdmx_table_builder =
446a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com          down_cast<HorizontalDeviceMetricsTable::Builder*>(raw_hdmx_builder);
447a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com  }
448a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com#endif
449a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com
450464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  // set the inter table data required to build certain tables
451464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (horizontal_metrics_builder != NULL) {
452464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    if (max_profile_builder != NULL) {
453246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com      horizontal_metrics_builder->SetNumGlyphs(
454246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com          max_profile_builder->NumGlyphs());
455464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
456464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    if (horizontal_header_builder != NULL) {
457246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com      horizontal_metrics_builder->SetNumberOfHMetrics(
458246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com          horizontal_header_builder->NumberOfHMetrics());
459464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
460464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
461464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
462464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (loca_table_builder != NULL) {
463464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    if (max_profile_builder != NULL) {
464246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com      loca_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs());
465464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
466464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    if (header_table_builder != NULL) {
467b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com      loca_table_builder->set_format_version(
468246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com          header_table_builder->IndexToLocFormat());
469464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    }
470464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
471a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com
472a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com#if defined (SFNTLY_EXPERIMENTAL)
473a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com  // Note: In C++, hdmx_table_builder can be NULL in a subsetter.
474a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com  if (max_profile_builder != NULL && hdmx_table_builder != NULL) {
475a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com    hdmx_table_builder->SetNumGlyphs(max_profile_builder->NumGlyphs());
476a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com  }
477a7acde600e171e08e75138318308de83f38b3097arthurhsu@google.com#endif
478464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
479464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
480246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::Builder::ReadHeader(FontInputStream* is,
481b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                               HeaderOffsetSortedSet* records) {
482464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(records);
483246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  sfnt_version_ = is->ReadFixed();
484246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  num_tables_ = is->ReadUShort();
485246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  search_range_ = is->ReadUShort();
486246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  entry_selector_ = is->ReadUShort();
487246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  range_shift_ = is->ReadUShort();
488464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
489464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  for (int32_t table_number = 0; table_number < num_tables_; ++table_number) {
490464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    // Need to use temporary vars here.  C++ evaluates function parameters from
491464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    // right to left and thus breaks the order of input stream.
492246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    int32_t tag = is->ReadULongAsInt();
493246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    int64_t checksum = is->ReadULong();
494246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    int32_t offset = is->ReadULongAsInt();
495246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    int32_t length = is->ReadULongAsInt();
4966b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com    HeaderPtr table = new Header(tag, checksum, offset, length);
497464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    records->insert(table);
498464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
499464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
500464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
501246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid Font::Builder::ReadHeader(ReadableFontData* fd,
502246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                               int32_t offset,
503b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                               HeaderOffsetSortedSet* records) {
504246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  assert(records);
505246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  sfnt_version_ = fd->ReadFixed(offset + Offset::kSfntVersion);
506246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  num_tables_ = fd->ReadUShort(offset + Offset::kNumTables);
507246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  search_range_ = fd->ReadUShort(offset + Offset::kSearchRange);
508246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  entry_selector_ = fd->ReadUShort(offset + Offset::kEntrySelector);
509246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  range_shift_ = fd->ReadUShort(offset + Offset::kRangeShift);
510246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
511246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t table_offset = offset + Offset::kTableRecordBegin;
512246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  for (int32_t table_number = 0;
513246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com       table_number < num_tables_;
514246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com       table_number++, table_offset += Offset::kTableRecordSize) {
515246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    int32_t tag = fd->ReadULongAsInt(table_offset + Offset::kTableTag);
516246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    int64_t checksum = fd->ReadULong(table_offset + Offset::kTableCheckSum);
517246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    int32_t offset = fd->ReadULongAsInt(table_offset + Offset::kTableOffset);
518246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    int32_t length = fd->ReadULongAsInt(table_offset + Offset::kTableLength);
5196b8e073e978eed96605da6f92d6db740a39864baarthurhsu@google.com    HeaderPtr table = new Header(tag, checksum, offset, length);
520246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    records->insert(table);
521246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  }
522246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
523246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
524b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comvoid Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
525464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                  FontInputStream* is,
526464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                  DataBlockMap* table_data) {
527464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  assert(table_data);
528b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  for (HeaderOffsetSortedSet::iterator table_header = headers->begin(),
529b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                       table_end = headers->end();
530b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                       table_header != table_end;
531b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                       ++table_header) {
532246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    is->Skip((*table_header)->offset() - is->position());
533464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    FontInputStream table_is(is, (*table_header)->length());
534c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com    WritableFontDataPtr data;
535c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com    data.Attach(
536c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com        WritableFontData::CreateWritableFontData((*table_header)->length()));
537c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com    data->CopyFrom(&table_is, (*table_header)->length());
538464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    table_data->insert(DataBlockEntry(*table_header, data));
539464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
540464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
541464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
542b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comvoid Font::Builder::LoadTableData(HeaderOffsetSortedSet* headers,
543464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                  WritableFontData* fd,
544464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                                  DataBlockMap* table_data) {
545b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  for (HeaderOffsetSortedSet::iterator table_header = headers->begin(),
546b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                       table_end = headers->end();
547b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                       table_header != table_end;
548b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                       ++table_header) {
549464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    FontDataPtr sliced_data;
550c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com    sliced_data.Attach(
551c10c3d53cd1401f158e89697b7fe019b6828fa00arthurhsu@google.com        fd->Slice((*table_header)->offset(), (*table_header)->length()));
552464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    WritableFontDataPtr data = down_cast<WritableFontData*>(sliced_data.p_);
553464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    table_data->insert(DataBlockEntry(*table_header, data));
554464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
555464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
556464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
557464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}  // namespace sfntly
558