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 "subtly/font_info.h" 1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <stdio.h> 2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <set> 2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <map> 2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "subtly/character_predicate.h" 2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/tag.h" 2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/font.h" 2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/font_factory.h" 2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/core/cmap_table.h" 3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/truetype/loca_table.h" 3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/truetype/glyph_table.h" 3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/core/maximum_profile_table.h" 3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/type.h" 3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/refcount.h" 3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace subtly { 3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunusing namespace sfntly; 3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/****************************************************************************** 3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * GlyphId class 4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/ 4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphId::GlyphId(int32_t glyph_id, FontId font_id) 4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun : glyph_id_(glyph_id), 4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_id_(font_id) { 4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool GlyphId::operator==(const GlyphId& other) const { 4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return glyph_id_ == other.glyph_id(); 4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool GlyphId::operator<(const GlyphId& other) const { 5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return glyph_id_ < other.glyph_id(); 5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/****************************************************************************** 5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * FontInfo class 5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/ 5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFontInfo::FontInfo() 5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun : chars_to_glyph_ids_(new CharacterMap), 5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun resolved_glyph_ids_(new GlyphIdSet), 6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fonts_(new FontIdMap) { 6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFontInfo::FontInfo(CharacterMap* chars_to_glyph_ids, 6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphIdSet* resolved_glyph_ids, 6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun FontIdMap* fonts) { 6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun chars_to_glyph_ids_ = new CharacterMap(chars_to_glyph_ids->begin(), 6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun chars_to_glyph_ids->end()); 6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun resolved_glyph_ids_ = new GlyphIdSet(resolved_glyph_ids->begin(), 6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun resolved_glyph_ids->end()); 7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fonts_ = new FontIdMap(fonts->begin(), fonts->end()); 7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFontInfo::~FontInfo() { 7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete chars_to_glyph_ids_; 7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete resolved_glyph_ids_; 7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete fonts_; 7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFontDataTable* FontInfo::GetTable(FontId font_id, int32_t tag) { 8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!fonts_) 8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return NULL; 8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun FontIdMap::iterator it = fonts_->find(font_id); 8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (it == fonts_->end()) 8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return NULL; 8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return it->second->GetTable(tag); 8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst TableMap* FontInfo::GetTableMap(FontId font_id) { 8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!fonts_) 9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return NULL; 9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun FontIdMap::iterator it = fonts_->find(font_id); 9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (it == fonts_->end()) 9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return NULL; 9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return it->second->GetTableMap(); 9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontInfo::set_chars_to_glyph_ids(CharacterMap* chars_to_glyph_ids) { 9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *chars_to_glyph_ids_ = *chars_to_glyph_ids; 9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontInfo::set_resolved_glyph_ids(GlyphIdSet* resolved_glyph_ids) { 10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *resolved_glyph_ids_ = *resolved_glyph_ids; 10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontInfo::set_fonts(FontIdMap* fonts) { 10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *fonts_ = *fonts; 10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/****************************************************************************** 11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * FontSourcedInfoBuilder class 11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/ 11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFontSourcedInfoBuilder::FontSourcedInfoBuilder(Font* font, FontId font_id) 11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun : font_(font), 11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_id_(font_id), 11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun predicate_(NULL) { 11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Initialize(); 11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFontSourcedInfoBuilder::FontSourcedInfoBuilder(Font* font, 12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun FontId font_id, 12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun CharacterPredicate* predicate) 12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun : font_(font), 12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_id_(font_id), 12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun predicate_(predicate) { 12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Initialize(); 12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid FontSourcedInfoBuilder::Initialize() { 12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Ptr<CMapTable> cmap_table = down_cast<CMapTable*>(font_->GetTable(Tag::cmap)); 13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // We prefer Windows BMP format 4 cmaps. 13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun cmap_.Attach(cmap_table->GetCMap(CMapTable::WINDOWS_BMP)); 13230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // But if none is found, 13330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!cmap_) { 13430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return; 13530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 13630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun loca_table_ = down_cast<LocaTable*>(font_->GetTable(Tag::loca)); 13730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph_table_ = down_cast<GlyphTable*>(font_->GetTable(Tag::glyf)); 13830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 13930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 14030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH FontInfo* FontSourcedInfoBuilder::GetFontInfo() { 14130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun CharacterMap* chars_to_glyph_ids = new CharacterMap; 14230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun bool success = GetCharacterMap(chars_to_glyph_ids); 14330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!success) { 14430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete chars_to_glyph_ids; 14530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SUBTLY_DEBUG) 14630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fprintf(stderr, "Error creating character map.\n"); 14730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 14830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return NULL; 14930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 15030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphIdSet* resolved_glyph_ids = new GlyphIdSet; 15130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun success = ResolveCompositeGlyphs(chars_to_glyph_ids, resolved_glyph_ids); 15230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!success) { 15330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete chars_to_glyph_ids; 15430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete resolved_glyph_ids; 15530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SUBTLY_DEBUG) 15630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fprintf(stderr, "Error resolving composite glyphs.\n"); 15730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 15830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return NULL; 15930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 16030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Ptr<FontInfo> font_info = new FontInfo; 16130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_info->set_chars_to_glyph_ids(chars_to_glyph_ids); 16230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_info->set_resolved_glyph_ids(resolved_glyph_ids); 16330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun FontIdMap* font_id_map = new FontIdMap; 16430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_id_map->insert(std::make_pair(font_id_, font_)); 16530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun font_info->set_fonts(font_id_map); 16630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete chars_to_glyph_ids; 16730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete resolved_glyph_ids; 16830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete font_id_map; 16930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return font_info.Detach(); 17030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 17130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 17230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool FontSourcedInfoBuilder::GetCharacterMap(CharacterMap* chars_to_glyph_ids) { 17330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!cmap_ || !chars_to_glyph_ids) 17430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 17530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun chars_to_glyph_ids->clear(); 17630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun CMapTable::CMap::CharacterIterator* character_iterator = cmap_->Iterator(); 17730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!character_iterator) 17830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 17930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun while (character_iterator->HasNext()) { 18030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t character = character_iterator->Next(); 18130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!predicate_ || (*predicate_)(character)) { 18230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun chars_to_glyph_ids->insert 18330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun (std::make_pair(character, 18430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphId(cmap_->GlyphId(character), font_id_))); 18530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 18630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 18730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete character_iterator; 18830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return true; 18930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 19030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun 19130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool 19230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFontSourcedInfoBuilder::ResolveCompositeGlyphs(CharacterMap* chars_to_glyph_ids, 19330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphIdSet* resolved_glyph_ids) { 19430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (!chars_to_glyph_ids || !resolved_glyph_ids) 19530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return false; 19630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun resolved_glyph_ids->clear(); 19730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun resolved_glyph_ids->insert(GlyphId(0, font_id_)); 19830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun IntegerSet* unresolved_glyph_ids = new IntegerSet; 19930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Since composite glyph elements might themselves be composite, we would need 20030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // to recursively resolve the elements too. To avoid the recursion we 20130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // create two sets, |unresolved_glyph_ids| for the unresolved glyphs, 20230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // initially containing all the ids and |resolved_glyph_ids|, initially empty. 20330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // We'll remove glyph ids from |unresolved_glyph_ids| until it is empty and, 20430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // if the glyph is composite, add its elements to the unresolved set. 20530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (CharacterMap::iterator it = chars_to_glyph_ids->begin(), 20630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun e = chars_to_glyph_ids->end(); it != e; ++it) { 20730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun unresolved_glyph_ids->insert(it->second.glyph_id()); 20830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 20930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // As long as there are unresolved glyph ids. 21030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun while (!unresolved_glyph_ids->empty()) { 21130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Get the corresponding glyph. 21230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t glyph_id = *(unresolved_glyph_ids->begin()); 21330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun unresolved_glyph_ids->erase(unresolved_glyph_ids->begin()); 21430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (glyph_id < 0 || glyph_id > loca_table_->num_glyphs()) { 21530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SUBTLY_DEBUG) 21630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fprintf(stderr, "%d larger than %d or smaller than 0\n", glyph_id, 21730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun loca_table_->num_glyphs()); 21830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 21930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 22030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 22130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t length = loca_table_->GlyphLength(glyph_id); 22230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (length == 0) { 22330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SUBTLY_DEBUG) 22430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fprintf(stderr, "Zero length glyph %d\n", glyph_id); 22530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 22630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 22730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 22830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t offset = loca_table_->GlyphOffset(glyph_id); 22930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun GlyphPtr glyph; 23030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun glyph.Attach(glyph_table_->GetGlyph(offset, length)); 23130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (glyph == NULL) { 23230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SUBTLY_DEBUG) 23330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun fprintf(stderr, "GetGlyph returned NULL for %d\n", glyph_id); 23430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif 23530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun continue; 23630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 23730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // Mark the glyph as resolved. 23830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun resolved_glyph_ids->insert(GlyphId(glyph_id, font_id_)); 23930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun // If it is composite, add all its components to the unresolved glyph set. 24030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (glyph->GlyphType() == GlyphType::kComposite) { 24130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun Ptr<GlyphTable::CompositeGlyph> composite_glyph = 24230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun down_cast<GlyphTable::CompositeGlyph*>(glyph.p_); 24330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t num_glyphs = composite_glyph->NumGlyphs(); 24430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun for (int32_t i = 0; i < num_glyphs; ++i) { 24530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun int32_t glyph_id = composite_glyph->GlyphIndex(i); 24630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun if (resolved_glyph_ids->find(GlyphId(glyph_id, -1)) 24730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun == resolved_glyph_ids->end()) { 24830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun unresolved_glyph_ids->insert(glyph_id); 24930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 25030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 25130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 25230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun } 25330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun delete unresolved_glyph_ids; 25430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun return true; 25530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 25630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun} 257