Home | History | Annotate | Download | only in bitmap
      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