1 /* 2 * Copyright 2011 Google Inc. All Rights Reserved. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #include "sfntly/table/bitmap/ebdt_table.h" 18 19 #include <stdlib.h> 20 21 #include "sfntly/table/bitmap/composite_bitmap_glyph.h" 22 #include "sfntly/table/bitmap/simple_bitmap_glyph.h" 23 24 namespace sfntly { 25 /****************************************************************************** 26 * EbdtTable class 27 ******************************************************************************/ 28 EbdtTable::~EbdtTable() { 29 } 30 31 int32_t EbdtTable::Version() { 32 return data_->ReadFixed(Offset::kVersion); 33 } 34 35 CALLER_ATTACH 36 BitmapGlyph* EbdtTable::Glyph(int32_t offset, int32_t length, int32_t format) { 37 ReadableFontDataPtr glyph_data; 38 glyph_data.Attach(down_cast<ReadableFontData*>(data_->Slice(offset, length))); 39 return BitmapGlyph::CreateGlyph(glyph_data, format); 40 } 41 42 EbdtTable::EbdtTable(Header* header, ReadableFontData* data) 43 : SubTableContainerTable(header, data) { 44 } 45 46 /****************************************************************************** 47 * EbdtTable::Builder class 48 ******************************************************************************/ 49 EbdtTable::Builder::Builder(Header* header, WritableFontData* data) 50 : SubTableContainerTable::Builder(header, data) { 51 } 52 53 EbdtTable::Builder::Builder(Header* header, ReadableFontData* data) 54 : SubTableContainerTable::Builder(header, data) { 55 } 56 57 EbdtTable::Builder::~Builder() { 58 } 59 60 CALLER_ATTACH FontDataTable* 61 EbdtTable::Builder::SubBuildTable(ReadableFontData* data) { 62 FontDataTablePtr table = new EbdtTable(header(), data); 63 return table.Detach(); 64 } 65 66 void EbdtTable::Builder::SubDataSet() { 67 Revert(); 68 } 69 70 int32_t EbdtTable::Builder::SubDataSizeToSerialize() { 71 if (glyph_builders_.empty()) { 72 return 0; 73 } 74 bool fixed = true; 75 int32_t size = Offset::kHeaderLength; 76 for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(), 77 builder_end = glyph_builders_.end(); 78 builder_map != builder_end; 79 builder_map++) { 80 for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(), 81 glyph_entry_end = builder_map->end(); 82 glyph_entry != glyph_entry_end; 83 glyph_entry++) { 84 int32_t glyph_size = glyph_entry->second->SubDataSizeToSerialize(); 85 size += abs(glyph_size); 86 fixed = (glyph_size <= 0) ? false : fixed; 87 } 88 } 89 return (fixed ? 1 : -1) * size; 90 } 91 92 bool EbdtTable::Builder::SubReadyToSerialize() { 93 if (glyph_builders_.empty()) { 94 return false; 95 } 96 return true; 97 } 98 99 int32_t EbdtTable::Builder::SubSerialize(WritableFontData* new_data) { 100 int32_t size = 0; 101 size += new_data->WriteFixed(Offset::kVersion, kVersion); 102 for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(), 103 builder_end = glyph_builders_.end(); 104 builder_map != builder_end; 105 builder_map++) { 106 for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(), 107 glyph_entry_end = builder_map->end(); 108 glyph_entry != glyph_entry_end; 109 glyph_entry++) { 110 WritableFontDataPtr slice; 111 slice.Attach(down_cast<WritableFontData*>(new_data->Slice(size))); 112 size += glyph_entry->second->SubSerialize(slice); 113 } 114 } 115 return size; 116 } 117 118 void EbdtTable::Builder::SetLoca(BitmapLocaList* loca_list) { 119 assert(loca_list); 120 Revert(); 121 glyph_loca_.resize(loca_list->size()); 122 std::copy(loca_list->begin(), loca_list->end(), glyph_loca_.begin()); 123 } 124 125 void EbdtTable::Builder::GenerateLocaList(BitmapLocaList* output) { 126 assert(output); 127 output->clear(); 128 129 if (glyph_builders_.empty()) { 130 if (glyph_loca_.empty()) { 131 return; 132 } 133 } 134 135 int start_offset = Offset::kHeaderLength; 136 for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(), 137 builder_end = glyph_builders_.end(); 138 builder_map != builder_end; 139 builder_map++) { 140 BitmapGlyphInfoMap new_loca_map; 141 int32_t glyph_offset = 0; 142 for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(), 143 glyph_end = builder_map->end(); 144 glyph_entry != glyph_end; 145 glyph_entry++) { 146 BitmapGlyphBuilderPtr builder = glyph_entry->second; 147 int32_t size = builder->SubDataSizeToSerialize(); 148 BitmapGlyphInfoPtr info = new BitmapGlyphInfo(glyph_entry->first, 149 start_offset + glyph_offset, size, builder->format()); 150 new_loca_map[glyph_entry->first] = info; 151 glyph_offset += size; 152 } 153 start_offset += glyph_offset; 154 output->push_back(new_loca_map); 155 } 156 } 157 158 BitmapGlyphBuilderList* EbdtTable::Builder::GlyphBuilders() { 159 return GetGlyphBuilders(); 160 } 161 162 void EbdtTable::Builder::SetGlyphBuilders( 163 BitmapGlyphBuilderList* glyph_builders) { 164 glyph_builders_.clear(); 165 std::copy(glyph_builders->begin(), glyph_builders->end(), 166 glyph_builders_.begin()); 167 set_model_changed(); 168 } 169 170 void EbdtTable::Builder::Revert() { 171 glyph_loca_.clear(); 172 glyph_builders_.clear(); 173 set_model_changed(false); 174 } 175 176 CALLER_ATTACH 177 EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header, 178 WritableFontData* data) { 179 Ptr<EbdtTable::Builder> builder; 180 builder = new Builder(header, data); 181 return builder.Detach(); 182 } 183 184 CALLER_ATTACH 185 EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header, 186 ReadableFontData* data) { 187 Ptr<EbdtTable::Builder> builder; 188 builder = new Builder(header, data); 189 return builder.Detach(); 190 } 191 192 BitmapGlyphBuilderList* EbdtTable::Builder::GetGlyphBuilders() { 193 if (glyph_builders_.empty()) { 194 if (glyph_loca_.empty()) { 195 #if !defined (SFNTLY_NO_EXCEPTION) 196 throw IllegalStateException( 197 "Loca values not set - unable to parse glyph data."); 198 #endif 199 return NULL; 200 } 201 Initialize(InternalReadData(), &glyph_loca_, &glyph_builders_); 202 set_model_changed(); 203 } 204 return &glyph_builders_; 205 } 206 207 void EbdtTable::Builder::Initialize(ReadableFontData* data, 208 BitmapLocaList* loca_list, 209 BitmapGlyphBuilderList* output) { 210 assert(loca_list); 211 assert(output); 212 213 output->clear(); 214 if (data) { 215 for (BitmapLocaList::iterator loca_map = loca_list->begin(), 216 loca_end = loca_list->end(); 217 loca_map != loca_end; loca_map++) { 218 BitmapGlyphBuilderMap glyph_builder_map; 219 for (BitmapGlyphInfoMap::iterator entry = loca_map->begin(), 220 entry_end = loca_map->end(); 221 entry != entry_end; entry++) { 222 BitmapGlyphInfoPtr info = entry->second; 223 ReadableFontDataPtr slice; 224 slice.Attach(down_cast<ReadableFontData*>(data->Slice( 225 info->offset(), info->length()))); 226 BitmapGlyphBuilderPtr glyph_builder; 227 glyph_builder.Attach(BitmapGlyph::Builder::CreateGlyphBuilder( 228 slice, info->format())); 229 glyph_builder_map[entry->first] = glyph_builder; 230 } 231 output->push_back(glyph_builder_map); 232 } 233 } 234 } 235 236 } // namespace sfntly 237