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 30namespace sfntly { 31/****************************************************************************** 32 * BitmapSizeTable class 33 ******************************************************************************/ 34BitmapSizeTable::~BitmapSizeTable() { 35} 36 37int32_t BitmapSizeTable::IndexSubTableArrayOffset() { 38 return data_->ReadULongAsInt( 39 EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset); 40} 41 42int32_t BitmapSizeTable::IndexTableSize() { 43 return data_->ReadULongAsInt( 44 EblcTable::Offset::kBitmapSizeTable_indexTableSize); 45} 46 47int32_t BitmapSizeTable::NumberOfIndexSubTables() { 48 return NumberOfIndexSubTables(data_, 0); 49} 50 51int32_t BitmapSizeTable::ColorRef() { 52 return data_->ReadULongAsInt(EblcTable::Offset::kBitmapSizeTable_colorRef); 53} 54 55int32_t BitmapSizeTable::StartGlyphIndex() { 56 return data_->ReadUShort(EblcTable::Offset::kBitmapSizeTable_startGlyphIndex); 57} 58 59int32_t BitmapSizeTable::EndGlyphIndex() { 60 return data_->ReadUShort(EblcTable::Offset::kBitmapSizeTable_endGlyphIndex); 61} 62 63int32_t BitmapSizeTable::PpemX() { 64 return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_ppemX); 65} 66 67int32_t BitmapSizeTable::PpemY() { 68 return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_ppemY); 69} 70 71int32_t BitmapSizeTable::BitDepth() { 72 return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_bitDepth); 73} 74 75int32_t BitmapSizeTable::FlagsAsInt() { 76 return data_->ReadChar(EblcTable::Offset::kBitmapSizeTable_flags); 77} 78 79IndexSubTable* 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 87int32_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 95int32_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 103CALLER_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 111int32_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 119BitmapSizeTable::BitmapSizeTable(ReadableFontData* data, 120 ReadableFontData* master_data) 121 : SubTable(data, master_data) { 122} 123 124// static 125int32_t BitmapSizeTable::NumberOfIndexSubTables(ReadableFontData* data, 126 int32_t table_offset) { 127 return data->ReadULongAsInt(table_offset + 128 EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables); 129} 130 131IndexSubTable* 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 141IndexSubTable* 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 153IndexSubTable* 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 175CALLER_ATTACH 176IndexSubTable* BitmapSizeTable::CreateIndexSubTable(int32_t index) { 177 return IndexSubTable::CreateIndexSubTable(master_read_data(), 178 IndexSubTableArrayOffset(), 179 index); 180} 181 182IndexSubTableList* 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 ******************************************************************************/ 197BitmapSizeTable::Builder::~Builder() { 198} 199 200CALLER_ATTACH 201FontDataTable* BitmapSizeTable::Builder::SubBuildTable(ReadableFontData* data) { 202 BitmapSizeTablePtr output = new BitmapSizeTable(data, master_read_data()); 203 return output.Detach(); 204} 205 206void BitmapSizeTable::Builder::SubDataSet() { 207 Revert(); 208} 209 210int32_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 235bool BitmapSizeTable::Builder::SubReadyToSerialize() { 236 if (IndexSubTableBuilders()->empty()) { 237 return false; 238 } 239 return true; 240} 241 242int32_t BitmapSizeTable::Builder::SubSerialize(WritableFontData* new_data) { 243 SetNumberOfIndexSubTables(IndexSubTableBuilders()->size()); 244 int32_t size = InternalReadData()->CopyTo(new_data); 245 return size; 246} 247 248CALLER_ATTACH BitmapSizeTable::Builder* 249BitmapSizeTable::Builder::CreateBuilder(WritableFontData* data, 250 ReadableFontData* master_data) { 251 BitmapSizeTableBuilderPtr output = 252 new BitmapSizeTable::Builder(data, master_data); 253 return output.Detach(); 254} 255 256CALLER_ATTACH BitmapSizeTable::Builder* 257BitmapSizeTable::Builder::CreateBuilder(ReadableFontData* data, 258 ReadableFontData* master_data) { 259 BitmapSizeTableBuilderPtr output = 260 new BitmapSizeTable::Builder(data, master_data); 261 return output.Detach(); 262} 263 264int32_t BitmapSizeTable::Builder::IndexSubTableArrayOffset() { 265 return InternalReadData()->ReadULongAsInt( 266 EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset); 267} 268 269void BitmapSizeTable::Builder::SetIndexSubTableArrayOffset(int32_t offset) { 270 InternalWriteData()->WriteULong( 271 EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset, offset); 272} 273 274int32_t BitmapSizeTable::Builder::IndexTableSize() { 275 return InternalReadData()->ReadULongAsInt( 276 EblcTable::Offset::kBitmapSizeTable_indexTableSize); 277} 278 279void BitmapSizeTable::Builder::SetIndexTableSize(int32_t size) { 280 InternalWriteData()->WriteULong( 281 EblcTable::Offset::kBitmapSizeTable_indexTableSize, size); 282} 283 284int32_t BitmapSizeTable::Builder::NumberOfIndexSubTables() { 285 return GetIndexSubTableBuilders()->size(); 286} 287 288int32_t BitmapSizeTable::Builder::ColorRef() { 289 return InternalReadData()->ReadULongAsInt( 290 EblcTable::Offset::kBitmapSizeTable_colorRef); 291} 292 293int32_t BitmapSizeTable::Builder::StartGlyphIndex() { 294 return InternalReadData()->ReadUShort( 295 EblcTable::Offset::kBitmapSizeTable_startGlyphIndex); 296} 297 298int32_t BitmapSizeTable::Builder::EndGlyphIndex() { 299 return InternalReadData()->ReadUShort( 300 EblcTable::Offset::kBitmapSizeTable_endGlyphIndex); 301} 302 303int32_t BitmapSizeTable::Builder::PpemX() { 304 return InternalReadData()->ReadByte( 305 EblcTable::Offset::kBitmapSizeTable_ppemX); 306} 307 308int32_t BitmapSizeTable::Builder::PpemY() { 309 return InternalReadData()->ReadByte( 310 EblcTable::Offset::kBitmapSizeTable_ppemY); 311} 312 313int32_t BitmapSizeTable::Builder::BitDepth() { 314 return InternalReadData()->ReadByte( 315 EblcTable::Offset::kBitmapSizeTable_bitDepth); 316} 317 318int32_t BitmapSizeTable::Builder::FlagsAsInt() { 319 return InternalReadData()->ReadChar( 320 EblcTable::Offset::kBitmapSizeTable_flags); 321} 322 323IndexSubTable::Builder* BitmapSizeTable::Builder::IndexSubTableBuilder( 324 int32_t index) { 325 IndexSubTableBuilderList* sub_table_list = GetIndexSubTableBuilders(); 326 return sub_table_list->at(index); 327} 328 329CALLER_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 338int32_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 346int32_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 354int32_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 362IndexSubTableBuilderList* BitmapSizeTable::Builder::IndexSubTableBuilders() { 363 return GetIndexSubTableBuilders(); 364} 365 366CALLER_ATTACH BitmapSizeTable::Builder::BitmapGlyphInfoIterator* 367BitmapSizeTable::Builder::GetIterator() { 368 Ptr<BitmapSizeTable::Builder::BitmapGlyphInfoIterator> output = 369 new BitmapSizeTable::Builder::BitmapGlyphInfoIterator(this); 370 return output.Detach(); 371} 372 373void 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 384void BitmapSizeTable::Builder::Revert() { 385 index_sub_tables_.clear(); 386 set_model_changed(false); 387} 388 389BitmapSizeTable::Builder::Builder(WritableFontData* data, 390 ReadableFontData* master_data) 391 : SubTable::Builder(data, master_data) { 392} 393 394BitmapSizeTable::Builder::Builder(ReadableFontData* data, 395 ReadableFontData* master_data) 396 : SubTable::Builder(data, master_data) { 397} 398 399void BitmapSizeTable::Builder::SetNumberOfIndexSubTables(int32_t count) { 400 InternalWriteData()->WriteULong( 401 EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables, count); 402} 403 404IndexSubTable::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 415IndexSubTable::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 429IndexSubTable::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 452IndexSubTableBuilderList* BitmapSizeTable::Builder::GetIndexSubTableBuilders() { 453 if (index_sub_tables_.empty()) { 454 Initialize(InternalReadData()); 455 set_model_changed(); 456 } 457 return &index_sub_tables_; 458} 459 460void 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 472CALLER_ATTACH IndexSubTable::Builder* 473BitmapSizeTable::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 ******************************************************************************/ 482BitmapSizeTable::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 489bool 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 502CALLER_ATTACH 503BitmapGlyphInfo* 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 511bool 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 557CALLER_ATTACH 558BitmapGlyphInfo* 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