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_format1.h"
     18 
     19 #include "sfntly/table/bitmap/eblc_table.h"
     20 
     21 namespace sfntly {
     22 /******************************************************************************
     23  * IndexSubTableFormat1 class
     24  ******************************************************************************/
     25 // static
     26 int32_t IndexSubTableFormat1::GetDataLength(ReadableFontData* data,
     27                                             int32_t offset,
     28                                             int32_t first,
     29                                             int32_t last) {
     30   UNREFERENCED_PARAMETER(data);
     31   UNREFERENCED_PARAMETER(offset);
     32   return (last - first + 1 + 1) * DataSize::kULONG;
     33 }
     34 
     35 IndexSubTableFormat1::~IndexSubTableFormat1() {
     36 }
     37 
     38 int32_t IndexSubTableFormat1::NumGlyphs() {
     39   return last_glyph_index() - first_glyph_index() + 1;
     40 }
     41 
     42 int32_t IndexSubTableFormat1::GlyphStartOffset(int32_t glyph_id) {
     43   int32_t loca = CheckGlyphRange(glyph_id);
     44   if (loca == -1) {
     45     return -1;
     46   }
     47   return Loca(loca);
     48 }
     49 
     50 int32_t IndexSubTableFormat1::GlyphLength(int32_t glyph_id) {
     51   int32_t loca = CheckGlyphRange(glyph_id);
     52   if (loca == -1) {
     53     return -1;
     54   }
     55   return Loca(loca + 1) - Loca(loca);
     56 }
     57 
     58 IndexSubTableFormat1::IndexSubTableFormat1(ReadableFontData* data,
     59                                            int32_t first_glyph_index,
     60                                            int32_t last_glyph_index)
     61     : IndexSubTable(data, first_glyph_index, last_glyph_index) {
     62 }
     63 
     64 int32_t IndexSubTableFormat1::Loca(int32_t loca) {
     65   return image_data_offset() +
     66          data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable1_offsetArray +
     67                                loca * DataSize::kULONG);
     68 }
     69 
     70 /******************************************************************************
     71  * IndexSubTableFormat1::Builder class
     72  ******************************************************************************/
     73 IndexSubTableFormat1::Builder::~Builder() {
     74 }
     75 
     76 int32_t IndexSubTableFormat1::Builder::NumGlyphs() {
     77   return GetOffsetArray()->size() - 1;
     78 }
     79 
     80 int32_t IndexSubTableFormat1::Builder::GlyphLength(int32_t glyph_id) {
     81   int32_t loca = CheckGlyphRange(glyph_id);
     82   if (loca == -1) {
     83     return 0;
     84   }
     85   IntegerList* offset_array = GetOffsetArray();
     86   return offset_array->at(loca + 1) - offset_array->at(loca);
     87 }
     88 
     89 int32_t IndexSubTableFormat1::Builder::GlyphStartOffset(int32_t glyph_id) {
     90   int32_t loca = CheckGlyphRange(glyph_id);
     91   if (loca == -1) {
     92     return -1;
     93   }
     94   return GetOffsetArray()->at(loca);
     95 }
     96 
     97 CALLER_ATTACH IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator*
     98     IndexSubTableFormat1::Builder::GetIterator() {
     99   Ptr<IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator> it =
    100       new IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator(this);
    101   return it.Detach();
    102 }
    103 
    104 // static
    105 CALLER_ATTACH IndexSubTableFormat1::Builder*
    106 IndexSubTableFormat1::Builder::CreateBuilder() {
    107   IndexSubTableFormat1BuilderPtr output = new IndexSubTableFormat1::Builder();
    108   return output.Detach();
    109 }
    110 
    111 // static
    112 CALLER_ATTACH IndexSubTableFormat1::Builder*
    113 IndexSubTableFormat1::Builder::CreateBuilder(ReadableFontData* data,
    114                                              int32_t index_sub_table_offset,
    115                                              int32_t first_glyph_index,
    116                                              int32_t last_glyph_index) {
    117   int32_t length = Builder::DataLength(data,
    118                                        index_sub_table_offset,
    119                                        first_glyph_index,
    120                                        last_glyph_index);
    121   ReadableFontDataPtr new_data;
    122   new_data.Attach(down_cast<ReadableFontData*>(
    123       data->Slice(index_sub_table_offset, length)));
    124   if (new_data == NULL) {
    125     return NULL;
    126   }
    127   IndexSubTableFormat1BuilderPtr output =
    128       new IndexSubTableFormat1::Builder(new_data,
    129                                         first_glyph_index,
    130                                         last_glyph_index);
    131   return output.Detach();
    132 }
    133 
    134 
    135 // static
    136 CALLER_ATTACH IndexSubTableFormat1::Builder*
    137 IndexSubTableFormat1::Builder::CreateBuilder(WritableFontData* data,
    138                                              int32_t index_sub_table_offset,
    139                                              int32_t first_glyph_index,
    140                                              int32_t last_glyph_index) {
    141   int32_t length = Builder::DataLength(data,
    142                                        index_sub_table_offset,
    143                                        first_glyph_index,
    144                                        last_glyph_index);
    145   WritableFontDataPtr new_data;
    146   new_data.Attach(down_cast<WritableFontData*>(
    147       data->Slice(index_sub_table_offset, length)));
    148   IndexSubTableFormat1BuilderPtr output =
    149       new IndexSubTableFormat1::Builder(new_data,
    150                                         first_glyph_index,
    151                                         last_glyph_index);
    152   return output.Detach();
    153 }
    154 
    155 CALLER_ATTACH FontDataTable* IndexSubTableFormat1::Builder::SubBuildTable(
    156     ReadableFontData* data) {
    157   IndexSubTableFormat1Ptr output = new IndexSubTableFormat1(
    158       data, first_glyph_index(), last_glyph_index());
    159   return output.Detach();
    160 }
    161 
    162 void IndexSubTableFormat1::Builder::SubDataSet() {
    163   Revert();
    164 }
    165 
    166 int32_t IndexSubTableFormat1::Builder::SubDataSizeToSerialize() {
    167   if (offset_array_.empty()) {
    168     return InternalReadData()->Length();
    169   }
    170   return EblcTable::Offset::kIndexSubHeaderLength +
    171          offset_array_.size() * DataSize::kULONG;
    172 }
    173 
    174 bool IndexSubTableFormat1::Builder::SubReadyToSerialize() {
    175   if (!offset_array_.empty()) {
    176     return true;
    177   }
    178   return false;
    179 }
    180 
    181 int32_t IndexSubTableFormat1::Builder::SubSerialize(
    182     WritableFontData* new_data) {
    183   int32_t size = SerializeIndexSubHeader(new_data);
    184   if (!model_changed()) {
    185     if (InternalReadData() == NULL) {
    186       return size;
    187     }
    188     ReadableFontDataPtr source;
    189     WritableFontDataPtr target;
    190     source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
    191         EblcTable::Offset::kIndexSubTable1_offsetArray)));
    192     target.Attach(down_cast<WritableFontData*>(new_data->Slice(
    193         EblcTable::Offset::kIndexSubTable1_offsetArray)));
    194     size += source->CopyTo(target);
    195   } else {
    196     for (IntegerList::iterator b = GetOffsetArray()->begin(),
    197                                e = GetOffsetArray()->end(); b != e; b++) {
    198       size += new_data->WriteLong(size, *b);
    199     }
    200   }
    201   return size;
    202 }
    203 
    204 IntegerList* IndexSubTableFormat1::Builder::OffsetArray() {
    205   return GetOffsetArray();
    206 }
    207 
    208 void IndexSubTableFormat1::Builder::SetOffsetArray(
    209     const IntegerList& offset_array) {
    210   offset_array_.clear();
    211   offset_array_ = offset_array;
    212   set_model_changed();
    213 }
    214 
    215 void IndexSubTableFormat1::Builder::Revert() {
    216   offset_array_.clear();
    217   IndexSubTable::Builder::Revert();
    218 }
    219 
    220 IndexSubTableFormat1::Builder::Builder()
    221     : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable1_builderDataSize,
    222                              IndexSubTable::Format::FORMAT_1) {
    223 }
    224 
    225 IndexSubTableFormat1::Builder::Builder(WritableFontData* data,
    226                                        int32_t first_glyph_index,
    227                                        int32_t last_glyph_index)
    228     : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
    229 }
    230 
    231 IndexSubTableFormat1::Builder::Builder(ReadableFontData* data,
    232                                        int32_t first_glyph_index,
    233                                        int32_t last_glyph_index)
    234     : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
    235 }
    236 
    237 IntegerList* IndexSubTableFormat1::Builder::GetOffsetArray() {
    238   if (offset_array_.empty()) {
    239     Initialize(InternalReadData());
    240     set_model_changed();
    241   }
    242   return &offset_array_;
    243 }
    244 
    245 void IndexSubTableFormat1::Builder::Initialize(ReadableFontData* data) {
    246   offset_array_.clear();
    247   if (data) {
    248     int32_t num_offsets = (last_glyph_index() - first_glyph_index() + 1) + 1;
    249     for (int32_t i = 0; i < num_offsets; ++i) {
    250       offset_array_.push_back(data->ReadULongAsInt(
    251           EblcTable::Offset::kIndexSubTable1_offsetArray +
    252           i * DataSize::kULONG));
    253     }
    254   }
    255 }
    256 
    257 // static
    258 int32_t IndexSubTableFormat1::Builder::DataLength(
    259     ReadableFontData* data,
    260     int32_t index_sub_table_offset,
    261     int32_t first_glyph_index,
    262     int32_t last_glyph_index) {
    263   UNREFERENCED_PARAMETER(data);
    264   UNREFERENCED_PARAMETER(index_sub_table_offset);
    265   return EblcTable::Offset::kIndexSubHeaderLength +
    266          (last_glyph_index - first_glyph_index + 1 + 1) * DataSize::kULONG;
    267 }
    268 
    269 /******************************************************************************
    270  * IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator class
    271  ******************************************************************************/
    272 IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
    273     IndexSubTableFormat1::Builder* container)
    274     : RefIterator<BitmapGlyphInfo, IndexSubTableFormat1::Builder,
    275                   IndexSubTable::Builder>(container) {
    276   glyph_id_ = container->first_glyph_index();
    277 }
    278 
    279 bool IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::HasNext() {
    280   if (glyph_id_ <= container()->last_glyph_index()) {
    281     return true;
    282   }
    283   return false;
    284 }
    285 
    286 CALLER_ATTACH BitmapGlyphInfo*
    287 IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::Next() {
    288   BitmapGlyphInfoPtr output;
    289   if (!HasNext()) {
    290     // Note: In C++, we do not throw exception when there's no element.
    291     return NULL;
    292   }
    293   output = new BitmapGlyphInfo(glyph_id_,
    294                                container()->image_data_offset(),
    295                                container()->GlyphStartOffset(glyph_id_),
    296                                container()->GlyphLength(glyph_id_),
    297                                container()->image_format());
    298   glyph_id_++;
    299   return output.Detach();
    300 }
    301 
    302 }  // namespace sfntly
    303