130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/* 230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Copyright 2011 Google Inc. All Rights Reserved. 330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * 430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Licensed under the Apache License, Version 2.0 (the "License"); 530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * you may not use this file except in compliance with the License. 630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * You may obtain a copy of the License at 730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * 830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * http://www.apache.org/licenses/LICENSE-2.0 930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * 1030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Unless required by applicable law or agreed to in writing, software 1130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * distributed under the License is distributed on an "AS IS" BASIS, 1230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * See the License for the specific language governing permissions and 1430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * limitations under the License. 1530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun */ 1630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 1730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "subsetter_impl.h" 1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <string.h> 2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <algorithm> 2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <iterator> 2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <map> 2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <set> 2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/bitmap/eblc_table.h" 2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/bitmap/ebdt_table.h" 2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/bitmap/index_sub_table.h" 2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/bitmap/index_sub_table_format1.h" 3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/bitmap/index_sub_table_format2.h" 3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/bitmap/index_sub_table_format3.h" 3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/bitmap/index_sub_table_format4.h" 3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/bitmap/index_sub_table_format5.h" 3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/core/name_table.h" 3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/tag.h" 3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/data/memory_byte_array.h" 3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/memory_input_stream.h" 3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/memory_output_stream.h" 3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined U_USING_ICU_NAMESPACE 4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun U_NAMESPACE_USE 4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace { 4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunusing namespace sfntly; 4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// The bitmap tables must be greater than 16KB to trigger bitmap subsetter. 4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunstatic const int BITMAP_SIZE_THRESHOLD = 16384; 5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid ConstructName(UChar* name_part, UnicodeString* name, int32_t name_id) { 5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun switch (name_id) { 5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kFullFontName: 5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *name = name_part; 5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun break; 5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kFontFamilyName: 5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kPreferredFamily: 5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kWWSFamilyName: { 5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun UnicodeString original = *name; 6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *name = name_part; 6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *name += original; 6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun break; 6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kFontSubfamilyName: 6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kPreferredSubfamily: 6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kWWSSubfamilyName: 6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *name += name_part; 6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun break; 6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun default: 7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // This name part is not used to construct font name (e.g. copyright). 7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Simply ignore it. 7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun break; 7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t HashCode(int32_t platform_id, int32_t encoding_id, int32_t language_id, 7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t name_id) { 7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t result = platform_id << 24 | encoding_id << 16 | language_id << 8; 7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (name_id == NameId::kFullFontName) { 8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun result |= 0xff; 8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } else if (name_id == NameId::kPreferredFamily || 8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun name_id == NameId::kPreferredSubfamily) { 8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun result |= 0xf; 8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } else if (name_id == NameId::kWWSFamilyName || 8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun name_id == NameId::kWWSSubfamilyName) { 8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun result |= 1; 8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return result; 8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool HasName(const char* font_name, Font* font) { 9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun UnicodeString font_string = UnicodeString::fromUTF8(font_name); 9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (font_string.isEmpty()) 9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun UnicodeString regular_suffix = UnicodeString::fromUTF8(" Regular"); 9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun UnicodeString alt_font_string = font_string; 9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun alt_font_string += regular_suffix; 9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun typedef std::map<int32_t, UnicodeString> NameMap; 10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun NameMap names; 10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun NameTablePtr name_table = down_cast<NameTable*>(font->GetTable(Tag::name)); 10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (name_table == NULL) { 10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (int32_t i = 0; i < name_table->NameCount(); ++i) { 10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun switch (name_table->NameId(i)) { 10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kFontFamilyName: 10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kFontSubfamilyName: 11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kFullFontName: 11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kPreferredFamily: 11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kPreferredSubfamily: 11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kWWSFamilyName: 11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case NameId::kWWSSubfamilyName: { 11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun UChar* name_part = name_table->Name(i); 11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (name_part == NULL) { 11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t hash_code = HashCode(name_table->PlatformId(i), 12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun name_table->EncodingId(i), 12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun name_table->LanguageId(i), 12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun name_table->NameId(i)); 12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ConstructName(name_part, &(names[hash_code]), name_table->NameId(i)); 12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete[] name_part; 12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun break; 12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun default: 12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun break; 12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 13230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!names.empty()) { 13330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (NameMap::iterator i = names.begin(), e = names.end(); i != e; ++i) { 13430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (i->second.caseCompare(font_string, 0) == 0 || 13530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun i->second.caseCompare(alt_font_string, 0) == 0) { 13630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return true; 13730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 13830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 13930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 14030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 14130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 14230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 14330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFont* FindFont(const char* font_name, const FontArray& font_array) { 14430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (font_array.empty() || font_array[0] == NULL) { 14530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return NULL; 14630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 14730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 14830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (font_name && strlen(font_name)) { 14930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (FontArray::const_iterator i = font_array.begin(), e = font_array.end(); 15030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun i != e; ++i) { 15130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (HasName(font_name, i->p_)) { 15230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return i->p_; 15330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 15430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 15530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 15630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 15730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return font_array[0].p_; 15830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 15930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 16030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool ResolveCompositeGlyphs(GlyphTable* glyph_table, 16130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun LocaTable* loca_table, 16230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun const unsigned int* glyph_ids, 16330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t glyph_count, 16430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerSet* glyph_id_processed) { 16530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (glyph_table == NULL || loca_table == NULL || 16630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_ids == NULL || glyph_count == 0 || glyph_id_processed == NULL) { 16730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 16830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 16930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 17030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Sort and uniquify glyph ids. 17130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerSet glyph_id_remaining; 17230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_id_remaining.insert(0); // Always include glyph id 0. 17330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (size_t i = 0; i < glyph_count; ++i) { 17430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_id_remaining.insert(glyph_ids[i]); 17530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 17630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 17730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Identify if any given glyph id maps to a composite glyph. If so, include 17830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // the glyphs referenced by that composite glyph. 17930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun while (!glyph_id_remaining.empty()) { 18030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerSet comp_glyph_id; 18130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (IntegerSet::iterator i = glyph_id_remaining.begin(), 18230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun e = glyph_id_remaining.end(); i != e; ++i) { 18330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (*i < 0 || *i >= loca_table->num_glyphs()) { 18430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Invalid glyph id, ignore. 18530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 18630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 18730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 18830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t length = loca_table->GlyphLength(*i); 18930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (length == 0) { 19030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Empty glyph, ignore. 19130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 19230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 19330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t offset = loca_table->GlyphOffset(*i); 19430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 19530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphPtr glyph; 19630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph.Attach(glyph_table->GetGlyph(offset, length)); 19730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (glyph == NULL) { 19830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Error finding glyph, ignore. 19930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 20030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 20130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 20230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (glyph->GlyphType() == GlyphType::kComposite) { 20330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Ptr<GlyphTable::CompositeGlyph> comp_glyph = 20430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun down_cast<GlyphTable::CompositeGlyph*>(glyph.p_); 20530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (int32_t j = 0; j < comp_glyph->NumGlyphs(); ++j) { 20630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t glyph_id = comp_glyph->GlyphIndex(j); 20730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (glyph_id_processed->find(glyph_id) == glyph_id_processed->end() && 20830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_id_remaining.find(glyph_id) == glyph_id_remaining.end()) { 20930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun comp_glyph_id.insert(comp_glyph->GlyphIndex(j)); 21030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 21130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 21230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 21330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 21430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_id_processed->insert(*i); 21530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 21630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 21730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_id_remaining.clear(); 21830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_id_remaining = comp_glyph_id; 21930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 22030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 22130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return true; 22230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 22330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 22430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool SetupGlyfBuilders(Font::Builder* font_builder, 22530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphTable* glyph_table, 22630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun LocaTable* loca_table, 22730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun const IntegerSet& glyph_ids) { 22830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!font_builder || !glyph_table || !loca_table) { 22930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 23030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 23130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 23230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphTableBuilderPtr glyph_table_builder = 23330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun down_cast<GlyphTable::Builder*>(font_builder->NewTableBuilder(Tag::glyf)); 23430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun LocaTableBuilderPtr loca_table_builder = 23530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun down_cast<LocaTable::Builder*>(font_builder->NewTableBuilder(Tag::loca)); 23630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (glyph_table_builder == NULL || loca_table_builder == NULL) { 23730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Out of memory. 23830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 23930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 24030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 24130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Extract glyphs and setup loca list. 24230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerList loca_list; 24330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun loca_list.resize(loca_table->num_glyphs()); 24430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun loca_list.push_back(0); 24530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t last_glyph_id = 0; 24630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t last_offset = 0; 24730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphTable::GlyphBuilderList* glyph_builders = 24830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_table_builder->GlyphBuilders(); 24930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (IntegerSet::const_iterator i = glyph_ids.begin(), e = glyph_ids.end(); 25030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun i != e; ++i) { 25130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t length = loca_table->GlyphLength(*i); 25230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t offset = loca_table->GlyphOffset(*i); 25330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 25430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphPtr glyph; 25530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph.Attach(glyph_table->GetGlyph(offset, length)); 25630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 25730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Add glyph to new glyf table. 25830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ReadableFontDataPtr data = glyph->ReadFontData(); 25930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun WritableFontDataPtr copy_data; 26030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun copy_data.Attach(WritableFontData::CreateWritableFontData(data->Length())); 26130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun data->CopyTo(copy_data); 26230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphBuilderPtr glyph_builder; 26330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_builder.Attach(glyph_table_builder->GlyphBuilder(copy_data)); 26430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_builders->push_back(glyph_builder); 26530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 26630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Configure loca list. 26730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (int32_t j = last_glyph_id + 1; j <= *i; ++j) { 26830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun loca_list[j] = last_offset; 26930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 27030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun last_offset += length; 27130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun loca_list[*i + 1] = last_offset; 27230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun last_glyph_id = *i; 27330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 27430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (int32_t j = last_glyph_id + 1; j <= loca_table->num_glyphs(); ++j) { 27530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun loca_list[j] = last_offset; 27630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 27730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun loca_table_builder->SetLocaList(&loca_list); 27830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 27930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return true; 28030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 28130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 28230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool HasOverlap(int32_t range_begin, int32_t range_end, 28330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun const IntegerSet& glyph_ids) { 28430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (range_begin == range_end) { 28530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return glyph_ids.find(range_begin) != glyph_ids.end(); 28630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } else if (range_end > range_begin) { 28730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerSet::const_iterator left = glyph_ids.lower_bound(range_begin); 28830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerSet::const_iterator right = glyph_ids.lower_bound(range_end); 28930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return right != left; 29030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 29130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 29230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 29330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 29430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Initialize builder, returns false if glyph_id subset is not covered. 29530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Not thread-safe, caller to ensure object life-time. 29630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool InitializeBitmapBuilder(EbdtTable::Builder* ebdt, EblcTable::Builder* eblc, 29730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun const IntegerSet& glyph_ids) { 29830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BitmapLocaList loca_list; 29930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BitmapSizeTableBuilderList* strikes = eblc->BitmapSizeBuilders(); 30030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 30130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Note: Do not call eblc_builder->GenerateLocaList(&loca_list) and then 30230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // ebdt_builder->SetLoca(loca_list). For fonts like SimSun, there are 30330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // >28K glyphs inside, where a typical usage will be <1K glyphs. Doing 30430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // the calls improperly will result in creation of >100K objects that 30530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // will be destroyed immediately, inducing significant slowness. 30630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerList removed_strikes; 30730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (size_t i = 0; i < strikes->size(); i++) { 30830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!HasOverlap((*strikes)[i]->StartGlyphIndex(), 30930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun (*strikes)[i]->EndGlyphIndex(), glyph_ids)) { 31030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun removed_strikes.push_back(i); 31130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 31230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 31330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 31430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IndexSubTableBuilderList* index_builders = 31530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun (*strikes)[i]->IndexSubTableBuilders(); 31630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerList removed_indexes; 31730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BitmapGlyphInfoMap info_map; 31830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (size_t j = 0; j < index_builders->size(); ++j) { 31930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if ((*index_builders)[j] == NULL) { 32030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Subtable is malformed, let's just skip it. 32130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun removed_indexes.push_back(j); 32230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 32330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 32430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t first_glyph_id = (*index_builders)[j]->first_glyph_index(); 32530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t last_glyph_id = (*index_builders)[j]->last_glyph_index(); 32630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!HasOverlap(first_glyph_id, last_glyph_id, glyph_ids)) { 32730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun removed_indexes.push_back(j); 32830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 32930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 33030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (IntegerSet::const_iterator gid = glyph_ids.begin(), 33130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun gid_end = glyph_ids.end(); 33230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun gid != gid_end; gid++) { 33330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (*gid < first_glyph_id) { 33430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 33530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 33630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (*gid > last_glyph_id) { 33730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun break; 33830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 33930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BitmapGlyphInfoPtr info; 34030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun info.Attach((*index_builders)[j]->GlyphInfo(*gid)); 34130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (info && info->length()) { // Do not include gid without bitmap 34230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun info_map[*gid] = info; 34330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 34430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 34530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 34630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!info_map.empty()) { 34730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun loca_list.push_back(info_map); 34830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } else { 34930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun removed_strikes.push_back(i); // Detected null entries. 35030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 35130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 35230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Remove unused index sub tables 35330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (IntegerList::reverse_iterator j = removed_indexes.rbegin(), 35430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun e = removed_indexes.rend(); 35530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun j != e; j++) { 35630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun index_builders->erase(index_builders->begin() + *j); 35730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 35830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 35930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (removed_strikes.size() == strikes->size() || loca_list.empty()) { 36030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 36130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 36230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 36330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (IntegerList::reverse_iterator i = removed_strikes.rbegin(), 36430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun e = removed_strikes.rend(); i != e; i++) { 36530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun strikes->erase(strikes->begin() + *i); 36630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 36730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 36830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (strikes->empty()) { // no glyph covered, can safely drop the builders. 36930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 37030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 37130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 37230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ebdt->SetLoca(&loca_list); 37330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ebdt->GlyphBuilders(); // Initialize the builder. 37430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return true; 37530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 37630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 37730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid CopyBigGlyphMetrics(BigGlyphMetrics::Builder* source, 37830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BigGlyphMetrics::Builder* target) { 37930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun target->SetHeight(static_cast<byte_t>(source->Height())); 38030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun target->SetWidth(static_cast<byte_t>(source->Width())); 38130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun target->SetHoriBearingX(static_cast<byte_t>(source->HoriBearingX())); 38230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun target->SetHoriBearingY(static_cast<byte_t>(source->HoriBearingY())); 38330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun target->SetHoriAdvance(static_cast<byte_t>(source->HoriAdvance())); 38430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun target->SetVertBearingX(static_cast<byte_t>(source->VertBearingX())); 38530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun target->SetVertBearingY(static_cast<byte_t>(source->VertBearingY())); 38630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun target->SetVertAdvance(static_cast<byte_t>(source->VertAdvance())); 38730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 38830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 38930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH IndexSubTable::Builder* 39030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunConstructIndexFormat4(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, 39130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t* image_data_offset) { 39230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IndexSubTableFormat4BuilderPtr builder4; 39330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun builder4.Attach(IndexSubTableFormat4::Builder::CreateBuilder()); 39430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun CodeOffsetPairBuilderList offset_pairs; 39530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 39630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t offset = 0; 39730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t lower_bound = b->first_glyph_index(); 39830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t upper_bound = b->last_glyph_index(); 39930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t last_gid = -1; 40030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BitmapGlyphInfoMap::const_iterator i = loca.lower_bound(lower_bound); 40130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BitmapGlyphInfoMap::const_iterator end = loca.end(); 40230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (i != end) { 40330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun last_gid = i->first; 40430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun builder4->set_first_glyph_index(last_gid); 40530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun builder4->set_image_format(b->image_format()); 40630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun builder4->set_image_data_offset(*image_data_offset); 40730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 40830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (; i != end; i++) { 40930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t gid = i->first; 41030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (gid > upper_bound) { 41130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun break; 41230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 41330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun offset_pairs.push_back( 41430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IndexSubTableFormat4::CodeOffsetPairBuilder(gid, offset)); 41530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun offset += i->second->length(); 41630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun last_gid = gid; 41730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 41830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun offset_pairs.push_back( 41930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IndexSubTableFormat4::CodeOffsetPairBuilder(-1, offset)); 42030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun builder4->set_last_glyph_index(last_gid); 42130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *image_data_offset += offset; 42230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun builder4->SetOffsetArray(offset_pairs); 42330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 42430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return builder4.Detach(); 42530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 42630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 42730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH IndexSubTable::Builder* 42830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunConstructIndexFormat5(IndexSubTable::Builder* b, const BitmapGlyphInfoMap& loca, 42930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t* image_data_offset) { 43030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IndexSubTableFormat5BuilderPtr new_builder; 43130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun new_builder.Attach(IndexSubTableFormat5::Builder::CreateBuilder()); 43230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 43330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Copy BigMetrics 43430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t image_size = 0; 43530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (b->index_format() == IndexSubTable::Format::FORMAT_2) { 43630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IndexSubTableFormat2BuilderPtr builder2 = 43730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun down_cast<IndexSubTableFormat2::Builder*>(b); 43830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun CopyBigGlyphMetrics(builder2->BigMetrics(), new_builder->BigMetrics()); 43930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun image_size = builder2->ImageSize(); 44030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } else { 44130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IndexSubTableFormat5BuilderPtr builder5 = 44230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun down_cast<IndexSubTableFormat5::Builder*>(b); 44330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BigGlyphMetricsBuilderPtr metrics_builder; 44430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun CopyBigGlyphMetrics(builder5->BigMetrics(), new_builder->BigMetrics()); 44530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun image_size = builder5->ImageSize(); 44630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 44730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 44830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerList* glyph_array = new_builder->GlyphArray(); 44930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t offset = 0; 45030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t lower_bound = b->first_glyph_index(); 45130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t upper_bound = b->last_glyph_index(); 45230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t last_gid = -1; 45330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BitmapGlyphInfoMap::const_iterator i = loca.lower_bound(lower_bound); 45430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BitmapGlyphInfoMap::const_iterator end = loca.end(); 45530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (i != end) { 45630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun last_gid = i->first; 45730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun new_builder->set_first_glyph_index(last_gid); 45830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun new_builder->set_image_format(b->image_format()); 45930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun new_builder->set_image_data_offset(*image_data_offset); 46030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun new_builder->SetImageSize(image_size); 46130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 46230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (; i != end; i++) { 46330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t gid = i->first; 46430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (gid > upper_bound) { 46530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun break; 46630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 46730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_array->push_back(gid); 46830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun offset += i->second->length(); 46930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun last_gid = gid; 47030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 47130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun new_builder->set_last_glyph_index(last_gid); 47230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *image_data_offset += offset; 47330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return new_builder.Detach(); 47430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 47530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 47630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH IndexSubTable::Builder* 47730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunSubsetIndexSubTable(IndexSubTable::Builder* builder, 47830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun const BitmapGlyphInfoMap& loca, 47930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t* image_data_offset) { 48030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun switch (builder->index_format()) { 48130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case IndexSubTable::Format::FORMAT_1: 48230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case IndexSubTable::Format::FORMAT_3: 48330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case IndexSubTable::Format::FORMAT_4: 48430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return ConstructIndexFormat4(builder, loca, image_data_offset); 48530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case IndexSubTable::Format::FORMAT_2: 48630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun case IndexSubTable::Format::FORMAT_5: 48730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return ConstructIndexFormat5(builder, loca, image_data_offset); 48830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun default: 48930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun assert(false); 49030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun break; 49130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 49230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return NULL; 49330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 49430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 49530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 49630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 49730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace sfntly { 49830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 49930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Not thread-safe, caller to ensure object life-time. 50030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid SubsetEBLC(EblcTable::Builder* eblc, const BitmapLocaList& new_loca) { 50130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BitmapSizeTableBuilderList* size_builders = eblc->BitmapSizeBuilders(); 50230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (size_builders == NULL) { 50330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return; 50430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 50530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 50630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t image_data_offset = EbdtTable::Offset::kHeaderLength; 50730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (size_t strike = 0; strike < size_builders->size(); ++strike) { 50830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IndexSubTableBuilderList* index_builders = 50930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun (*size_builders)[strike]->IndexSubTableBuilders(); 51030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (size_t index = 0; index < index_builders->size(); ++index) { 51130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IndexSubTable::Builder* new_builder_raw = 51230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun SubsetIndexSubTable((*index_builders)[index], new_loca[strike], 51330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun &image_data_offset); 51430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (NULL != new_builder_raw) { 51530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun (*index_builders)[index].Attach(new_builder_raw); 51630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 51730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 51830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 51930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 52030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 52130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// EBLC structure (from stuartg) 52230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// header 52330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// bitmapSizeTable[] 52430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// one per strike 52530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// holds strike metrics - sbitLineMetrics 52630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// holds info about indexSubTableArray 52730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// indexSubTableArray[][] 52830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// one per strike and then one per indexSubTable for that strike 52930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// holds info about the indexSubTable 53030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// the indexSubTable entries pointed to can be of different formats 53130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// indexSubTable 53230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// one per indexSubTableArray entry 53330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// tells how to get the glyphs 53430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// may hold the glyph metrics if they are uniform for all the glyphs in range 53530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Please note that the structure can also be 53630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// {indexSubTableArray[], indexSubTables[]}[] 53730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// This way is also legal and in fact how Microsoft fonts are laid out. 53830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// 53930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// There is nothing that says that the indexSubTableArray entries and/or the 54030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// indexSubTable items need to be unique. They may be shared between strikes. 54130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// 54230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// EBDT structure: 54330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// header 54430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// glyphs 54530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// amorphous blob of data 54630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// different glyphs that are only able to be figured out from the EBLC table 54730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// may hold metrics - depends on the EBLC entry that pointed to them 54830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 54930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Subsetting EBLC table (from arthurhsu) 55030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Most pages use only a fraction (hundreds or less) glyphs out of a given font 55130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// (which can have >20K glyphs for CJK). It's safe to assume that the subset 55230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// font will have sparse bitmap glyphs. So we reconstruct the EBLC table as 55330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// format 4 or 5 here. 55430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 55530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunenum BuildersToRemove { 55630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun kRemoveNone, 55730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun kRemoveBDAT, 55830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun kRemoveBDATAndEBDT, 55930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun kRemoveEBDT 56030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}; 56130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 56230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint SetupBitmapBuilders(Font* font, Font::Builder* font_builder, 56330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun const IntegerSet& glyph_ids) { 56430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!font || !font_builder) { 56530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 56630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 56730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 56830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Check if bitmap table exists. 56930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun EbdtTablePtr ebdt_table = down_cast<EbdtTable*>(font->GetTable(Tag::EBDT)); 57030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun EblcTablePtr eblc_table = down_cast<EblcTable*>(font->GetTable(Tag::EBLC)); 57130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun bool use_ebdt = (ebdt_table != NULL && eblc_table != NULL); 57230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!use_ebdt) { 57330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ebdt_table = down_cast<EbdtTable*>(font->GetTable(Tag::bdat)); 57430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun eblc_table = down_cast<EblcTable*>(font->GetTable(Tag::bloc)); 57530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (ebdt_table == NULL || eblc_table == NULL) { 57630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return kRemoveNone; 57730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 57830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 57930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 58030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // If the bitmap table's size is too small, skip subsetting. 58130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (ebdt_table->DataLength() + eblc_table->DataLength() < 58230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BITMAP_SIZE_THRESHOLD) { 58330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return use_ebdt ? kRemoveBDAT : kRemoveNone; 58430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 58530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 58630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Get the builders. 58730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun EbdtTableBuilderPtr ebdt_table_builder = down_cast<EbdtTable::Builder*>( 58830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_builder->NewTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat, 58930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ebdt_table->ReadFontData())); 59030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun EblcTableBuilderPtr eblc_table_builder = down_cast<EblcTable::Builder*>( 59130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_builder->NewTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc, 59230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun eblc_table->ReadFontData())); 59330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (ebdt_table_builder == NULL || eblc_table_builder == NULL) { 59430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Out of memory. 59530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return use_ebdt ? kRemoveBDAT : kRemoveNone; 59630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 59730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 59830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!InitializeBitmapBuilder(ebdt_table_builder, eblc_table_builder, 59930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_ids)) { 60030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Bitmap tables do not cover the glyphs in our subset. 60130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBLC : Tag::bloc); 60230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_builder->RemoveTableBuilder(use_ebdt ? Tag::EBDT : Tag::bdat); 60330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return use_ebdt ? kRemoveBDATAndEBDT : kRemoveEBDT; 60430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 60530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 60630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun BitmapLocaList new_loca; 60730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ebdt_table_builder->GenerateLocaList(&new_loca); 60830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun SubsetEBLC(eblc_table_builder, new_loca); 60930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 61030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return use_ebdt ? kRemoveBDAT : kRemoveNone; 61130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 61230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 61330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunSubsetterImpl::SubsetterImpl() { 61430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 61530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 61630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunSubsetterImpl::~SubsetterImpl() { 61730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 61830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 61930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool SubsetterImpl::LoadFont(const char* font_name, 62030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun const unsigned char* original_font, 62130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t font_size) { 62230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun MemoryInputStream mis; 62330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun mis.Attach(original_font, font_size); 62430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (factory_ == NULL) { 62530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun factory_.Attach(FontFactory::GetInstance()); 62630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 62730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 62830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun FontArray font_array; 62930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun factory_->LoadFonts(&mis, &font_array); 63030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_ = FindFont(font_name, font_array); 63130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (font_ == NULL) { 63230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 63330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 63430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 63530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return true; 63630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 63730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 63830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint SubsetterImpl::SubsetFont(const unsigned int* glyph_ids, 63930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun size_t glyph_count, 64030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun unsigned char** output_buffer) { 64130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (factory_ == NULL || font_ == NULL) { 64230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return -1; 64330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 64430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 64530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Find glyf and loca table. 64630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphTablePtr glyph_table = 64730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun down_cast<GlyphTable*>(font_->GetTable(Tag::glyf)); 64830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun LocaTablePtr loca_table = down_cast<LocaTable*>(font_->GetTable(Tag::loca)); 64930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (glyph_table == NULL || loca_table == NULL) { 65030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // We are not able to subset the font. 65130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 65230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 65330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 65430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerSet glyph_id_processed; 65530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!ResolveCompositeGlyphs(glyph_table, loca_table, 65630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_ids, glyph_count, &glyph_id_processed) || 65730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_id_processed.empty()) { 65830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 65930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 66030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 66130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun FontPtr new_font; 66230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun new_font.Attach(Subset(glyph_id_processed, glyph_table, loca_table)); 66330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (new_font == NULL) { 66430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return 0; 66530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 66630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 66730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun MemoryOutputStream output_stream; 66830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun factory_->SerializeFont(new_font, &output_stream); 66930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int length = static_cast<int>(output_stream.Size()); 67030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (length > 0) { 67130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *output_buffer = new unsigned char[length]; 67230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun memcpy(*output_buffer, output_stream.Get(), length); 67330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 67430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 67530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return length; 67630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 67730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 67830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Long comments regarding TTF tables and PDF (from stuartg) 67930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// 68030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// According to PDF spec 1.4 (section 5.8), the following tables must be 68130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// present: 68230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// head, hhea, loca, maxp, cvt, prep, glyf, hmtx, fpgm 68330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// cmap if font is used with a simple font dict and not a CIDFont dict 68430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// 68530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Other tables we need to keep for PDF rendering to support zoom in/out: 68630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// bdat, bloc, ebdt, eblc, ebsc, gasp 68730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// 68830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Special table: 68930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// CFF - if you have this table then you shouldn't have a glyf table and this 69030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// is the table with all the glyphs. Shall skip subsetting completely 69130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// since sfntly is not capable of subsetting it for now. 69230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// post - extra info here for printing on PostScript printers but maybe not 69330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// enough to outweigh the space taken by the names 69430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// 69530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Tables to break apart: 69630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// name - could throw away all but one language and one platform strings/ might 69730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// throw away some of the name entries 69830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// cmap - could strip out non-needed cmap subtables 69930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// - format 4 subtable can be subsetted as well using sfntly 70030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// 70130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Graphite tables: 70230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// silf, glat, gloc, feat - should be okay to strip out 70330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// 70430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Tables that can be discarded: 70530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// OS/2 - everything here is for layout and description of the font that is 70630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// elsewhere (some in the PDF objects) 70730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// BASE, GDEF, GSUB, GPOS, JSTF - all used for layout 70830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// kern - old style layout 70930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// DSIG - this will be invalid after subsetting 71030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// hdmx - layout 71130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// PCLT - metadata that's not needed 71230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// vmtx - layout 71330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// vhea - layout 71430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// VDMX 71530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// VORG - not used by TT/OT - used by CFF 71630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// hsty - would be surprised to see one of these - used on the Newton 71730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// AAT tables - mort, morx, feat, acnt, bsin, just, lcar, fdsc, fmtx, prop, 71830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Zapf, opbd, trak, fvar, gvar, avar, cvar 71930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// - these are all layout tables and once layout happens are not 72030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// needed anymore 72130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// LTSH - layout 72230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 72330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH 72430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFont* SubsetterImpl::Subset(const IntegerSet& glyph_ids, GlyphTable* glyf, 72530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun LocaTable* loca) { 72630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // The const is initialized here to workaround VC bug of rendering all Tag::* 72730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // as 0. These tags represents the TTF tables that we will embed in subset 72830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // font. 72930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun const int32_t TABLES_IN_SUBSET[] = { 73030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Tag::head, Tag::hhea, Tag::loca, Tag::maxp, Tag::cvt, 73130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Tag::prep, Tag::glyf, Tag::hmtx, Tag::fpgm, Tag::EBDT, 73230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Tag::EBLC, Tag::EBSC, Tag::bdat, Tag::bloc, Tag::bhed, 73330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Tag::cmap, // Keep here for future tagged PDF development. 73430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Tag::name, // Keep here due to legal concerns: copyright info inside. 73530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun }; 73630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 73730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Setup font builders we need. 73830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun FontBuilderPtr font_builder; 73930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_builder.Attach(factory_->NewFontBuilder()); 74030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerSet remove_tags; 74130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 74230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (SetupGlyfBuilders(font_builder, glyf, loca, glyph_ids)) { 74330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun remove_tags.insert(Tag::glyf); 74430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun remove_tags.insert(Tag::loca); 74530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 74630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 74730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // For old Apple bitmap fonts, they have only bdats and bhed is identical 74830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // to head. As a result, we can't remove bdat tables for those fonts. 74930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int setup_result = SetupBitmapBuilders(font_, font_builder, glyph_ids); 75030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (setup_result == kRemoveBDATAndEBDT || setup_result == kRemoveEBDT) { 75130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun remove_tags.insert(Tag::EBDT); 75230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun remove_tags.insert(Tag::EBLC); 75330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun remove_tags.insert(Tag::EBSC); 75430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 75530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 75630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (setup_result == kRemoveBDAT || setup_result == kRemoveBDATAndEBDT) { 75730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun remove_tags.insert(Tag::bdat); 75830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun remove_tags.insert(Tag::bloc); 75930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun remove_tags.insert(Tag::bhed); 76030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 76130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 76230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerSet allowed_tags; 76330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (size_t i = 0; i < sizeof(TABLES_IN_SUBSET) / sizeof(int32_t); ++i) { 76430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun allowed_tags.insert(TABLES_IN_SUBSET[i]); 76530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 76630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 76730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerSet result; 76830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun std::set_difference(allowed_tags.begin(), allowed_tags.end(), 76930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun remove_tags.begin(), remove_tags.end(), 77030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun std::inserter(result, result.end())); 77130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun allowed_tags = result; 77230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 77330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Setup remaining builders. 77430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (IntegerSet::iterator i = allowed_tags.begin(), e = allowed_tags.end(); 77530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun i != e; ++i) { 77630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Table* table = font_->GetTable(*i); 77730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (table) { 77830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_builder->NewTableBuilder(*i, table->ReadFontData()); 77930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 78030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 78130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 78230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return font_builder->Build(); 78330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 78430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 78530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} // namespace sfntly 786