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/index_sub_table.h"
     18 
     19 #include "sfntly/table/bitmap/eblc_table.h"
     20 #include "sfntly/table/bitmap/index_sub_table_format1.h"
     21 #include "sfntly/table/bitmap/index_sub_table_format2.h"
     22 #include "sfntly/table/bitmap/index_sub_table_format3.h"
     23 #include "sfntly/table/bitmap/index_sub_table_format4.h"
     24 #include "sfntly/table/bitmap/index_sub_table_format5.h"
     25 
     26 namespace sfntly {
     27 /******************************************************************************
     28  * IndexSubTable class
     29  ******************************************************************************/
     30 CALLER_ATTACH BitmapGlyphInfo* IndexSubTable::GlyphInfo(int32_t glyph_id) {
     31   int32_t loca = CheckGlyphRange(glyph_id);
     32   if (loca == -1) {
     33     return NULL;
     34   }
     35   if (GlyphStartOffset(glyph_id) == -1) {
     36     return NULL;
     37   }
     38   BitmapGlyphInfoPtr output = new BitmapGlyphInfo(glyph_id,
     39                                                   image_data_offset(),
     40                                                   GlyphStartOffset(glyph_id),
     41                                                   GlyphLength(glyph_id),
     42                                                   image_format());
     43   return output.Detach();
     44 }
     45 
     46 int32_t IndexSubTable::GlyphOffset(int32_t glyph_id) {
     47   int32_t glyph_start_offset = GlyphStartOffset(glyph_id);
     48   if (glyph_start_offset == -1) {
     49     return -1;
     50   }
     51   return image_data_offset() + glyph_start_offset;
     52 }
     53 
     54 // static
     55 CALLER_ATTACH IndexSubTable*
     56     IndexSubTable::CreateIndexSubTable(ReadableFontData* data,
     57                                        int32_t offset_to_index_sub_table_array,
     58                                        int32_t array_index) {
     59   IndexSubTableBuilderPtr builder;
     60   builder.Attach(IndexSubTable::Builder::CreateBuilder(
     61       data, offset_to_index_sub_table_array, array_index));
     62   return down_cast<IndexSubTable*>(builder->Build());
     63 }
     64 
     65 IndexSubTable::IndexSubTable(ReadableFontData* data,
     66                              int32_t first_glyph_index,
     67                              int32_t last_glyph_index)
     68     : SubTable(data),
     69       first_glyph_index_(first_glyph_index),
     70       last_glyph_index_(last_glyph_index) {
     71   index_format_ =
     72       data_->ReadUShort(EblcTable::Offset::kIndexSubHeader_indexFormat);
     73   image_format_ =
     74       data_->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat);
     75   image_data_offset_ =
     76       data_->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset);
     77 }
     78 
     79 int32_t IndexSubTable::CheckGlyphRange(int32_t glyph_id) {
     80   return CheckGlyphRange(glyph_id, first_glyph_index(), last_glyph_index());
     81 }
     82 
     83 // static
     84 int32_t IndexSubTable::CheckGlyphRange(int32_t glyph_id,
     85                                        int32_t first_glyph_id,
     86                                        int32_t last_glyph_id) {
     87   if (glyph_id < first_glyph_id || glyph_id > last_glyph_id) {
     88 #if !defined (SFNTLY_NO_EXCEPTION)
     89     throw IndexOutOfBoundException("Glyph ID is outside of the allowed range.");
     90 #endif
     91     return -1;
     92   }
     93   return glyph_id - first_glyph_id;
     94 }
     95 
     96 /******************************************************************************
     97  * IndexSubTable::Builder class
     98  ******************************************************************************/
     99 IndexSubTable::Builder::~Builder() {
    100 }
    101 
    102 void IndexSubTable::Builder::Revert() {
    103   set_model_changed(false);
    104   Initialize(InternalReadData());
    105 }
    106 
    107 CALLER_ATTACH BitmapGlyphInfo* IndexSubTable::Builder::GlyphInfo(
    108     int32_t glyph_id) {
    109   BitmapGlyphInfoPtr glyph_info =
    110       new BitmapGlyphInfo(glyph_id,
    111                           image_data_offset(),
    112                           GlyphStartOffset(glyph_id),
    113                           GlyphLength(glyph_id),
    114                           image_format());
    115   return glyph_info.Detach();
    116 }
    117 
    118 int32_t IndexSubTable::Builder::GlyphOffset(int32_t glyph_id) {
    119   return image_data_offset() + GlyphStartOffset(glyph_id);
    120 }
    121 
    122 // static
    123 CALLER_ATTACH IndexSubTable::Builder*
    124 IndexSubTable::Builder::CreateBuilder(int32_t index_format) {
    125   switch (index_format) {
    126     case Format::FORMAT_1:
    127       return IndexSubTableFormat1::Builder::CreateBuilder();
    128     case Format::FORMAT_2:
    129       return IndexSubTableFormat2::Builder::CreateBuilder();
    130     case Format::FORMAT_3:
    131       return IndexSubTableFormat3::Builder::CreateBuilder();
    132     case Format::FORMAT_4:
    133       return IndexSubTableFormat4::Builder::CreateBuilder();
    134     case Format::FORMAT_5:
    135       return IndexSubTableFormat5::Builder::CreateBuilder();
    136     default:
    137 #if !defined (SFNTLY_NO_EXCEPTION)
    138       throw IllegalArgumentException("Invalid index subtable format");
    139 #endif
    140       return NULL;
    141   }
    142 }
    143 
    144 // static
    145 CALLER_ATTACH IndexSubTable::Builder*
    146 IndexSubTable::Builder::CreateBuilder(ReadableFontData* data,
    147     int32_t offset_to_index_sub_table_array, int32_t array_index) {
    148   int32_t index_sub_table_entry_offset =
    149       offset_to_index_sub_table_array +
    150       array_index * EblcTable::Offset::kIndexSubTableEntryLength;
    151   int32_t first_glyph_index =
    152       data->ReadUShort(index_sub_table_entry_offset +
    153                        EblcTable::Offset::kIndexSubTableEntry_firstGlyphIndex);
    154   int32_t last_glyph_index =
    155       data->ReadUShort(index_sub_table_entry_offset +
    156                        EblcTable::Offset::kIndexSubTableEntry_lastGlyphIndex);
    157   int32_t additional_offset_to_index_subtable = data->ReadULongAsInt(
    158       index_sub_table_entry_offset +
    159       EblcTable::Offset::kIndexSubTableEntry_additionalOffsetToIndexSubTable);
    160   int32_t index_sub_table_offset = offset_to_index_sub_table_array +
    161                                    additional_offset_to_index_subtable;
    162   int32_t index_format = data->ReadUShort(index_sub_table_offset);
    163   switch (index_format) {
    164     case 1:
    165       return IndexSubTableFormat1::Builder::CreateBuilder(
    166           data, index_sub_table_offset, first_glyph_index, last_glyph_index);
    167     case 2:
    168       return IndexSubTableFormat2::Builder::CreateBuilder(
    169           data, index_sub_table_offset, first_glyph_index, last_glyph_index);
    170     case 3:
    171       return IndexSubTableFormat3::Builder::CreateBuilder(
    172           data, index_sub_table_offset, first_glyph_index, last_glyph_index);
    173     case 4:
    174       return IndexSubTableFormat4::Builder::CreateBuilder(
    175           data, index_sub_table_offset, first_glyph_index, last_glyph_index);
    176     case 5:
    177       return IndexSubTableFormat5::Builder::CreateBuilder(
    178           data, index_sub_table_offset, first_glyph_index, last_glyph_index);
    179     default:
    180       // Unknown format and unable to process.
    181 #if !defined (SFNTLY_NO_EXCEPTION)
    182       throw IllegalArgumentException("Invalid Index Subtable Format");
    183 #endif
    184       break;
    185   }
    186   return NULL;
    187 }
    188 
    189 CALLER_ATTACH
    190 FontDataTable* IndexSubTable::Builder::SubBuildTable(ReadableFontData* data) {
    191   UNREFERENCED_PARAMETER(data);
    192   return NULL;
    193 }
    194 
    195 void IndexSubTable::Builder::SubDataSet() {
    196   // NOP
    197 }
    198 
    199 int32_t IndexSubTable::Builder::SubDataSizeToSerialize() {
    200   return 0;
    201 }
    202 
    203 bool IndexSubTable::Builder::SubReadyToSerialize() {
    204   return false;
    205 }
    206 
    207 int32_t IndexSubTable::Builder::SubSerialize(WritableFontData* new_data) {
    208   UNREFERENCED_PARAMETER(new_data);
    209   return 0;
    210 }
    211 
    212 IndexSubTable::Builder::Builder(int32_t data_size, int32_t index_format)
    213     : SubTable::Builder(data_size),
    214       first_glyph_index_(0),
    215       last_glyph_index_(0),
    216       index_format_(index_format),
    217       image_format_(0),
    218       image_data_offset_(0) {
    219 }
    220 
    221 IndexSubTable::Builder::Builder(int32_t index_format,
    222                                 int32_t image_format,
    223                                 int32_t image_data_offset,
    224                                 int32_t data_size)
    225     : SubTable::Builder(data_size),
    226       first_glyph_index_(0),
    227       last_glyph_index_(0),
    228       index_format_(index_format),
    229       image_format_(image_format),
    230       image_data_offset_(image_data_offset) {
    231 }
    232 
    233 IndexSubTable::Builder::Builder(WritableFontData* data,
    234                                 int32_t first_glyph_index,
    235                                 int32_t last_glyph_index)
    236     : SubTable::Builder(data),
    237       first_glyph_index_(first_glyph_index),
    238       last_glyph_index_(last_glyph_index) {
    239   Initialize(data);
    240 }
    241 
    242 IndexSubTable::Builder::Builder(ReadableFontData* data,
    243                                 int32_t first_glyph_index,
    244                                 int32_t last_glyph_index)
    245     : SubTable::Builder(data),
    246       first_glyph_index_(first_glyph_index),
    247       last_glyph_index_(last_glyph_index) {
    248   Initialize(data);
    249 }
    250 
    251 int32_t IndexSubTable::Builder::CheckGlyphRange(int32_t glyph_id) {
    252   return IndexSubTable::CheckGlyphRange(glyph_id,
    253                                         first_glyph_index(),
    254                                         last_glyph_index());
    255 }
    256 
    257 int32_t IndexSubTable::Builder::SerializeIndexSubHeader(
    258     WritableFontData* data) {
    259   int32_t size =
    260       data->WriteUShort(EblcTable::Offset::kIndexSubHeader_indexFormat,
    261                         index_format());
    262   size += data->WriteUShort(EblcTable::Offset::kIndexSubHeader_imageFormat,
    263                             image_format());
    264   size += data->WriteULong(EblcTable::Offset::kIndexSubHeader_imageDataOffset,
    265                            image_data_offset());
    266   return size;
    267 }
    268 
    269 void IndexSubTable::Builder::Initialize(ReadableFontData* data) {
    270   index_format_ =
    271       data->ReadUShort(EblcTable::Offset::kIndexSubHeader_indexFormat);
    272   image_format_ =
    273       data->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat);
    274   image_data_offset_ =
    275       data->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset);
    276 }
    277 
    278 }  // namespace sfntly
    279