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/bitmap_size_table.h" 18 19 #include <stdio.h> 20 #include <stdlib.h> 21 22 #include "sfntly/math/font_math.h" 23 #include "sfntly/table/bitmap/eblc_table.h" 24 #include "sfntly/table/bitmap/index_sub_table_format1.h" 25 #include "sfntly/table/bitmap/index_sub_table_format2.h" 26 #include "sfntly/table/bitmap/index_sub_table_format3.h" 27 #include "sfntly/table/bitmap/index_sub_table_format4.h" 28 #include "sfntly/table/bitmap/index_sub_table_format5.h" 29 30 namespace sfntly { 31 /****************************************************************************** 32 * BitmapSizeTable class 33 ******************************************************************************/ 34 BitmapSizeTable::~BitmapSizeTable() { 35 } 36 37 int32_t BitmapSizeTable::IndexSubTableArrayOffset() { 38 return data_->ReadULongAsInt( 39 EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset); 40 } 41 42 int32_t BitmapSizeTable::IndexTableSize() { 43 return data_->ReadULongAsInt( 44 EblcTable::Offset::kBitmapSizeTable_indexTableSize); 45 } 46 47 int32_t BitmapSizeTable::NumberOfIndexSubTables() { 48 return NumberOfIndexSubTables(data_, 0); 49 } 50 51 int32_t BitmapSizeTable::ColorRef() { 52 return data_->ReadULongAsInt(EblcTable::Offset::kBitmapSizeTable_colorRef); 53 } 54 55 int32_t BitmapSizeTable::StartGlyphIndex() { 56 return data_->ReadUShort(EblcTable::Offset::kBitmapSizeTable_startGlyphIndex); 57 } 58 59 int32_t BitmapSizeTable::EndGlyphIndex() { 60 return data_->ReadUShort(EblcTable::Offset::kBitmapSizeTable_endGlyphIndex); 61 } 62 63 int32_t BitmapSizeTable::PpemX() { 64 return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_ppemX); 65 } 66 67 int32_t BitmapSizeTable::PpemY() { 68 return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_ppemY); 69 } 70 71 int32_t BitmapSizeTable::BitDepth() { 72 return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_bitDepth); 73 } 74 75 int32_t BitmapSizeTable::FlagsAsInt() { 76 return data_->ReadChar(EblcTable::Offset::kBitmapSizeTable_flags); 77 } 78 79 IndexSubTable* BitmapSizeTable::GetIndexSubTable(int32_t index) { 80 IndexSubTableList* subtable_list = GetIndexSubTableList(); 81 if (index >= 0 && (size_t)index < subtable_list->size()) { 82 return (*subtable_list)[index]; 83 } 84 return NULL; 85 } 86 87 int32_t BitmapSizeTable::GlyphOffset(int32_t glyph_id) { 88 IndexSubTable* subtable = SearchIndexSubTables(glyph_id); 89 if (subtable == NULL) { 90 return -1; 91 } 92 return subtable->GlyphOffset(glyph_id); 93 } 94 95 int32_t BitmapSizeTable::GlyphLength(int32_t glyph_id) { 96 IndexSubTable* subtable = SearchIndexSubTables(glyph_id); 97 if (subtable == NULL) { 98 return -1; 99 } 100 return subtable->GlyphLength(glyph_id); 101 } 102 103 CALLER_ATTACH BitmapGlyphInfo* BitmapSizeTable::GlyphInfo(int32_t glyph_id) { 104 IndexSubTable* sub_table = SearchIndexSubTables(glyph_id); 105 if (sub_table == NULL) { 106 return NULL; 107 } 108 return sub_table->GlyphInfo(glyph_id); 109 } 110 111 int32_t BitmapSizeTable::GlyphFormat(int32_t glyph_id) { 112 IndexSubTable* subtable = SearchIndexSubTables(glyph_id); 113 if (subtable == NULL) { 114 return -1; 115 } 116 return subtable->image_format(); 117 } 118 119 BitmapSizeTable::BitmapSizeTable(ReadableFontData* data, 120 ReadableFontData* master_data) 121 : SubTable(data, master_data) { 122 } 123 124 // static 125 int32_t BitmapSizeTable::NumberOfIndexSubTables(ReadableFontData* data, 126 int32_t table_offset) { 127 return data->ReadULongAsInt(table_offset + 128 EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables); 129 } 130 131 IndexSubTable* BitmapSizeTable::SearchIndexSubTables(int32_t glyph_id) { 132 // would be faster to binary search but too many size tables don't have 133 // sorted subtables 134 #if (SFNTLY_BITMAPSIZE_USE_BINARY_SEARCH) 135 return BinarySearchIndexSubTables(glyph_id); 136 #else 137 return LinearSearchIndexSubTables(glyph_id); 138 #endif 139 } 140 141 IndexSubTable* BitmapSizeTable::LinearSearchIndexSubTables(int32_t glyph_id) { 142 IndexSubTableList* subtable_list = GetIndexSubTableList(); 143 for (IndexSubTableList::iterator b = subtable_list->begin(), 144 e = subtable_list->end(); b != e; b++) { 145 if ((*b)->first_glyph_index() <= glyph_id && 146 (*b)->last_glyph_index() >= glyph_id) { 147 return *b; 148 } 149 } 150 return NULL; 151 } 152 153 IndexSubTable* BitmapSizeTable::BinarySearchIndexSubTables(int32_t glyph_id) { 154 IndexSubTableList* subtable_list = GetIndexSubTableList(); 155 int32_t index = 0; 156 int32_t bottom = 0; 157 int32_t top = subtable_list->size(); 158 while (top != bottom) { 159 index = (top + bottom) / 2; 160 IndexSubTable* subtable = (*subtable_list)[index]; 161 if (glyph_id < subtable->first_glyph_index()) { 162 // Location beow current location 163 top = index; 164 } else { 165 if (glyph_id <= subtable->last_glyph_index()) { 166 return subtable; 167 } else { 168 bottom = index + 1; 169 } 170 } 171 } 172 return NULL; 173 } 174 175 CALLER_ATTACH 176 IndexSubTable* BitmapSizeTable::CreateIndexSubTable(int32_t index) { 177 return IndexSubTable::CreateIndexSubTable(master_read_data(), 178 IndexSubTableArrayOffset(), 179 index); 180 } 181 182 IndexSubTableList* BitmapSizeTable::GetIndexSubTableList() { 183 AutoLock lock(index_subtables_lock_); 184 if (index_subtables_.empty()) { 185 for (int32_t i = 0; i < NumberOfIndexSubTables(); ++i) { 186 IndexSubTablePtr table; 187 table.Attach(CreateIndexSubTable(i)); 188 index_subtables_.push_back(table); 189 } 190 } 191 return &index_subtables_; 192 } 193 194 /****************************************************************************** 195 * BitmapSizeTable::Builder class 196 ******************************************************************************/ 197 BitmapSizeTable::Builder::~Builder() { 198 } 199 200 CALLER_ATTACH 201 FontDataTable* BitmapSizeTable::Builder::SubBuildTable(ReadableFontData* data) { 202 BitmapSizeTablePtr output = new BitmapSizeTable(data, master_read_data()); 203 return output.Detach(); 204 } 205 206 void BitmapSizeTable::Builder::SubDataSet() { 207 Revert(); 208 } 209 210 int32_t BitmapSizeTable::Builder::SubDataSizeToSerialize() { 211 IndexSubTableBuilderList* builders = IndexSubTableBuilders(); 212 if (builders->empty()) { 213 return 0; 214 } 215 int32_t size = EblcTable::Offset::kBitmapSizeTableLength; 216 bool variable = false; 217 for (IndexSubTableBuilderList::iterator b = builders->begin(), 218 e = builders->end(); b != e; b++) { 219 size += EblcTable::Offset::kIndexSubTableEntryLength; 220 int32_t sub_table_size = (*b)->SubDataSizeToSerialize(); 221 int32_t padding = FontMath::PaddingRequired(abs(sub_table_size), 222 DataSize::kULONG); 223 #if defined (SFNTLY_DEBUG_BITMAP) 224 fprintf(stderr, "subtable size=%d\n", sub_table_size); 225 #endif 226 variable = (sub_table_size > 0) ? variable : true; 227 size += abs(sub_table_size) + padding; 228 } 229 #if defined (SFNTLY_DEBUG_BITMAP) 230 fprintf(stderr, "bitmap table size=%d\n", variable ? -size : size); 231 #endif 232 return variable ? -size : size; 233 } 234 235 bool BitmapSizeTable::Builder::SubReadyToSerialize() { 236 if (IndexSubTableBuilders()->empty()) { 237 return false; 238 } 239 return true; 240 } 241 242 int32_t BitmapSizeTable::Builder::SubSerialize(WritableFontData* new_data) { 243 SetNumberOfIndexSubTables(IndexSubTableBuilders()->size()); 244 int32_t size = InternalReadData()->CopyTo(new_data); 245 return size; 246 } 247 248 CALLER_ATTACH BitmapSizeTable::Builder* 249 BitmapSizeTable::Builder::CreateBuilder(WritableFontData* data, 250 ReadableFontData* master_data) { 251 BitmapSizeTableBuilderPtr output = 252 new BitmapSizeTable::Builder(data, master_data); 253 return output.Detach(); 254 } 255 256 CALLER_ATTACH BitmapSizeTable::Builder* 257 BitmapSizeTable::Builder::CreateBuilder(ReadableFontData* data, 258 ReadableFontData* master_data) { 259 BitmapSizeTableBuilderPtr output = 260 new BitmapSizeTable::Builder(data, master_data); 261 return output.Detach(); 262 } 263 264 int32_t BitmapSizeTable::Builder::IndexSubTableArrayOffset() { 265 return InternalReadData()->ReadULongAsInt( 266 EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset); 267 } 268 269 void BitmapSizeTable::Builder::SetIndexSubTableArrayOffset(int32_t offset) { 270 InternalWriteData()->WriteULong( 271 EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset, offset); 272 } 273 274 int32_t BitmapSizeTable::Builder::IndexTableSize() { 275 return InternalReadData()->ReadULongAsInt( 276 EblcTable::Offset::kBitmapSizeTable_indexTableSize); 277 } 278 279 void BitmapSizeTable::Builder::SetIndexTableSize(int32_t size) { 280 InternalWriteData()->WriteULong( 281 EblcTable::Offset::kBitmapSizeTable_indexTableSize, size); 282 } 283 284 int32_t BitmapSizeTable::Builder::NumberOfIndexSubTables() { 285 return GetIndexSubTableBuilders()->size(); 286 } 287 288 int32_t BitmapSizeTable::Builder::ColorRef() { 289 return InternalReadData()->ReadULongAsInt( 290 EblcTable::Offset::kBitmapSizeTable_colorRef); 291 } 292 293 int32_t BitmapSizeTable::Builder::StartGlyphIndex() { 294 return InternalReadData()->ReadUShort( 295 EblcTable::Offset::kBitmapSizeTable_startGlyphIndex); 296 } 297 298 int32_t BitmapSizeTable::Builder::EndGlyphIndex() { 299 return InternalReadData()->ReadUShort( 300 EblcTable::Offset::kBitmapSizeTable_endGlyphIndex); 301 } 302 303 int32_t BitmapSizeTable::Builder::PpemX() { 304 return InternalReadData()->ReadByte( 305 EblcTable::Offset::kBitmapSizeTable_ppemX); 306 } 307 308 int32_t BitmapSizeTable::Builder::PpemY() { 309 return InternalReadData()->ReadByte( 310 EblcTable::Offset::kBitmapSizeTable_ppemY); 311 } 312 313 int32_t BitmapSizeTable::Builder::BitDepth() { 314 return InternalReadData()->ReadByte( 315 EblcTable::Offset::kBitmapSizeTable_bitDepth); 316 } 317 318 int32_t BitmapSizeTable::Builder::FlagsAsInt() { 319 return InternalReadData()->ReadChar( 320 EblcTable::Offset::kBitmapSizeTable_flags); 321 } 322 323 IndexSubTable::Builder* BitmapSizeTable::Builder::IndexSubTableBuilder( 324 int32_t index) { 325 IndexSubTableBuilderList* sub_table_list = GetIndexSubTableBuilders(); 326 return sub_table_list->at(index); 327 } 328 329 CALLER_ATTACH BitmapGlyphInfo* BitmapSizeTable::Builder::GlyphInfo( 330 int32_t glyph_id) { 331 IndexSubTable::Builder* sub_table = SearchIndexSubTables(glyph_id); 332 if (sub_table == NULL) { 333 return NULL; 334 } 335 return sub_table->GlyphInfo(glyph_id); 336 } 337 338 int32_t BitmapSizeTable::Builder::GlyphOffset(int32_t glyph_id) { 339 IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id); 340 if (subtable == NULL) { 341 return -1; 342 } 343 return subtable->GlyphOffset(glyph_id); 344 } 345 346 int32_t BitmapSizeTable::Builder::GlyphLength(int32_t glyph_id) { 347 IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id); 348 if (subtable == NULL) { 349 return -1; 350 } 351 return subtable->GlyphLength(glyph_id); 352 } 353 354 int32_t BitmapSizeTable::Builder::GlyphFormat(int32_t glyph_id) { 355 IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id); 356 if (subtable == NULL) { 357 return -1; 358 } 359 return subtable->image_format(); 360 } 361 362 IndexSubTableBuilderList* BitmapSizeTable::Builder::IndexSubTableBuilders() { 363 return GetIndexSubTableBuilders(); 364 } 365 366 CALLER_ATTACH BitmapSizeTable::Builder::BitmapGlyphInfoIterator* 367 BitmapSizeTable::Builder::GetIterator() { 368 Ptr<BitmapSizeTable::Builder::BitmapGlyphInfoIterator> output = 369 new BitmapSizeTable::Builder::BitmapGlyphInfoIterator(this); 370 return output.Detach(); 371 } 372 373 void BitmapSizeTable::Builder::GenerateLocaMap(BitmapGlyphInfoMap* output) { 374 assert(output); 375 Ptr<BitmapSizeTable::Builder::BitmapGlyphInfoIterator> it; 376 it.Attach(GetIterator()); 377 while (it->HasNext()) { 378 BitmapGlyphInfoPtr info; 379 info.Attach(it->Next()); 380 (*output)[info->glyph_id()] = info; 381 } 382 } 383 384 void BitmapSizeTable::Builder::Revert() { 385 index_sub_tables_.clear(); 386 set_model_changed(false); 387 } 388 389 BitmapSizeTable::Builder::Builder(WritableFontData* data, 390 ReadableFontData* master_data) 391 : SubTable::Builder(data, master_data) { 392 } 393 394 BitmapSizeTable::Builder::Builder(ReadableFontData* data, 395 ReadableFontData* master_data) 396 : SubTable::Builder(data, master_data) { 397 } 398 399 void BitmapSizeTable::Builder::SetNumberOfIndexSubTables(int32_t count) { 400 InternalWriteData()->WriteULong( 401 EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables, count); 402 } 403 404 IndexSubTable::Builder* BitmapSizeTable::Builder::SearchIndexSubTables( 405 int32_t glyph_id) { 406 // would be faster to binary search but too many size tables don't have 407 // sorted subtables 408 #if (SFNTLY_BITMAPSIZE_USE_BINARY_SEARCH) 409 return BinarySearchIndexSubTables(glyph_id); 410 #else 411 return LinearSearchIndexSubTables(glyph_id); 412 #endif 413 } 414 415 IndexSubTable::Builder* BitmapSizeTable::Builder::LinearSearchIndexSubTables( 416 int32_t glyph_id) { 417 IndexSubTableBuilderList* subtable_list = GetIndexSubTableBuilders(); 418 for (IndexSubTableBuilderList::iterator b = subtable_list->begin(), 419 e = subtable_list->end(); 420 b != e; b++) { 421 if ((*b)->first_glyph_index() <= glyph_id && 422 (*b)->last_glyph_index() >= glyph_id) { 423 return *b; 424 } 425 } 426 return NULL; 427 } 428 429 IndexSubTable::Builder* BitmapSizeTable::Builder::BinarySearchIndexSubTables( 430 int32_t glyph_id) { 431 IndexSubTableBuilderList* subtable_list = GetIndexSubTableBuilders(); 432 int32_t index = 0; 433 int32_t bottom = 0; 434 int32_t top = subtable_list->size(); 435 while (top != bottom) { 436 index = (top + bottom) / 2; 437 IndexSubTable::Builder* subtable = subtable_list->at(index); 438 if (glyph_id < subtable->first_glyph_index()) { 439 // Location beow current location 440 top = index; 441 } else { 442 if (glyph_id <= subtable->last_glyph_index()) { 443 return subtable; 444 } else { 445 bottom = index + 1; 446 } 447 } 448 } 449 return NULL; 450 } 451 452 IndexSubTableBuilderList* BitmapSizeTable::Builder::GetIndexSubTableBuilders() { 453 if (index_sub_tables_.empty()) { 454 Initialize(InternalReadData()); 455 set_model_changed(); 456 } 457 return &index_sub_tables_; 458 } 459 460 void BitmapSizeTable::Builder::Initialize(ReadableFontData* data) { 461 index_sub_tables_.clear(); 462 if (data) { 463 int32_t number_of_index_subtables = 464 BitmapSizeTable::NumberOfIndexSubTables(data, 0); 465 index_sub_tables_.resize(number_of_index_subtables); 466 for (int32_t i = 0; i < number_of_index_subtables; ++i) { 467 index_sub_tables_[i].Attach(CreateIndexSubTableBuilder(i)); 468 } 469 } 470 } 471 472 CALLER_ATTACH IndexSubTable::Builder* 473 BitmapSizeTable::Builder::CreateIndexSubTableBuilder(int32_t index) { 474 return IndexSubTable::Builder::CreateBuilder(master_read_data(), 475 IndexSubTableArrayOffset(), 476 index); 477 } 478 479 /****************************************************************************** 480 * BitmapSizeTable::Builder::BitmapGlyphInfoIterator class 481 ******************************************************************************/ 482 BitmapSizeTable::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator( 483 BitmapSizeTable::Builder* container) 484 : RefIterator<BitmapGlyphInfo, BitmapSizeTable::Builder>(container) { 485 sub_table_iter_ = container->IndexSubTableBuilders()->begin(); 486 sub_table_glyph_info_iter_.Attach((*sub_table_iter_)->GetIterator()); 487 } 488 489 bool BitmapSizeTable::Builder::BitmapGlyphInfoIterator::HasNext() { 490 if (sub_table_glyph_info_iter_ && HasNext(sub_table_glyph_info_iter_)) { 491 return true; 492 } 493 while (++sub_table_iter_ != container()->IndexSubTableBuilders()->end()) { 494 sub_table_glyph_info_iter_.Attach((*sub_table_iter_)->GetIterator()); 495 if (HasNext(sub_table_glyph_info_iter_)) { 496 return true; 497 } 498 } 499 return false; 500 } 501 502 CALLER_ATTACH 503 BitmapGlyphInfo* BitmapSizeTable::Builder::BitmapGlyphInfoIterator::Next() { 504 if (!HasNext()) { 505 // Note: In C++, we do not throw exception when there's no element. 506 return NULL; 507 } 508 return Next(sub_table_glyph_info_iter_); 509 } 510 511 bool BitmapSizeTable::Builder::BitmapGlyphInfoIterator::HasNext( 512 BitmapGlyphInfoIter* iterator_base) { 513 if (iterator_base) { 514 switch (iterator_base->container_base()->index_format()) { 515 case 1: { 516 IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* it = 517 down_cast<IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator*>( 518 iterator_base); 519 return it->HasNext(); 520 } 521 522 case 2: { 523 IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* it = 524 down_cast<IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator*>( 525 iterator_base); 526 return it->HasNext(); 527 } 528 529 case 3: { 530 IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator* it = 531 down_cast<IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator*>( 532 iterator_base); 533 return it->HasNext(); 534 } 535 536 case 4: { 537 IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* it = 538 down_cast<IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator*>( 539 iterator_base); 540 return it->HasNext(); 541 } 542 543 case 5: { 544 IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* it = 545 down_cast<IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator*>( 546 iterator_base); 547 return it->HasNext(); 548 } 549 550 default: 551 break; 552 } 553 } 554 return false; 555 } 556 557 CALLER_ATTACH 558 BitmapGlyphInfo* BitmapSizeTable::Builder::BitmapGlyphInfoIterator::Next( 559 BitmapGlyphInfoIter* iterator_base) { 560 if (iterator_base) { 561 switch (iterator_base->container_base()->index_format()) { 562 case 1: { 563 IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* it = 564 down_cast<IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator*>( 565 iterator_base); 566 return it->Next(); 567 } 568 569 case 2: { 570 IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* it = 571 down_cast<IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator*>( 572 iterator_base); 573 return it->Next(); 574 } 575 576 case 3: { 577 IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator* it = 578 down_cast<IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator*>( 579 iterator_base); 580 return it->Next(); 581 } 582 583 case 4: { 584 IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* it = 585 down_cast<IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator*>( 586 iterator_base); 587 return it->Next(); 588 } 589 590 case 5: { 591 IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* it = 592 down_cast<IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator*>( 593 iterator_base); 594 return it->Next(); 595 } 596 597 default: 598 break; 599 } 600 } 601 return NULL; 602 } 603 604 } // namespace sfntly 605