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