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/eblc_table.h"
     18 
     19 #include <stdio.h>
     20 #include <stdlib.h>
     21 
     22 #include "sfntly/math/font_math.h"
     23 
     24 namespace sfntly {
     25 /******************************************************************************
     26  * EblcTable class
     27  ******************************************************************************/
     28 int32_t EblcTable::Version() {
     29   return data_->ReadFixed(Offset::kVersion);
     30 }
     31 
     32 int32_t EblcTable::NumSizes() {
     33   return data_->ReadULongAsInt(Offset::kNumSizes);
     34 }
     35 
     36 BitmapSizeTable* EblcTable::GetBitmapSizeTable(int32_t index) {
     37   if (index < 0 || index > NumSizes()) {
     38 #if !defined (SFNTLY_NO_EXCEPTION)
     39     throw IndexOutOfBoundException(
     40         "Size table index is outside the range of tables.");
     41 #endif
     42     return NULL;
     43   }
     44   BitmapSizeTableList* bitmap_size_table_list = GetBitmapSizeTableList();
     45   if (bitmap_size_table_list) {
     46     return (*bitmap_size_table_list)[index];
     47   }
     48   return NULL;
     49 }
     50 
     51 EblcTable::EblcTable(Header* header, ReadableFontData* data)
     52     : SubTableContainerTable(header, data) {
     53 }
     54 
     55 BitmapSizeTableList* EblcTable::GetBitmapSizeTableList() {
     56   AutoLock lock(bitmap_size_table_lock_);
     57   if (bitmap_size_table_.empty()) {
     58     CreateBitmapSizeTable(data_, NumSizes(), &bitmap_size_table_);
     59   }
     60   return &bitmap_size_table_;
     61 }
     62 
     63 // static
     64 void EblcTable::CreateBitmapSizeTable(ReadableFontData* data,
     65                                       int32_t num_sizes,
     66                                       BitmapSizeTableList* output) {
     67   assert(data);
     68   assert(output);
     69   for (int32_t i = 0; i < num_sizes; ++i) {
     70     ReadableFontDataPtr new_data;
     71     new_data.Attach(down_cast<ReadableFontData*>(
     72         data->Slice(Offset::kBitmapSizeTableArrayStart +
     73                     i * Offset::kBitmapSizeTableLength,
     74                     Offset::kBitmapSizeTableLength)));
     75     BitmapSizeTableBuilderPtr size_builder;
     76     size_builder.Attach(
     77         BitmapSizeTable::Builder::CreateBuilder(new_data, data));
     78     BitmapSizeTablePtr size;
     79     size.Attach(down_cast<BitmapSizeTable*>(size_builder->Build()));
     80     output->push_back(size);
     81   }
     82 }
     83 
     84 /******************************************************************************
     85  * EblcTable::Builder class
     86  ******************************************************************************/
     87 EblcTable::Builder::Builder(Header* header, WritableFontData* data)
     88     : SubTableContainerTable::Builder(header, data) {
     89 }
     90 
     91 EblcTable::Builder::Builder(Header* header, ReadableFontData* data)
     92     : SubTableContainerTable::Builder(header, data) {
     93 }
     94 
     95 EblcTable::Builder::~Builder() {
     96 }
     97 
     98 int32_t EblcTable::Builder::SubSerialize(WritableFontData* new_data) {
     99   // header
    100   int32_t size = new_data->WriteFixed(0, kVersion);
    101   size += new_data->WriteULong(size, size_table_builders_.size());
    102 
    103   // calculate the offsets
    104   // offset to the start of the size table array
    105   int32_t size_table_start_offset = size;
    106   // walking offset in the size table array
    107   int32_t size_table_offset = size_table_start_offset;
    108   // offset to the start of the whole index subtable block
    109   int32_t sub_table_block_start_offset = size_table_offset +
    110       size_table_builders_.size() * Offset::kBitmapSizeTableLength;
    111   // walking offset in the index subtable
    112   // points to the start of the current subtable block
    113   int32_t current_sub_table_block_start_offset = sub_table_block_start_offset;
    114 
    115 #if defined (SFNTLY_DEBUG_BITMAP)
    116   int32_t size_index = 0;
    117 #endif
    118   for (BitmapSizeTableBuilderList::iterator
    119            size_builder = size_table_builders_.begin(),
    120            size_builder_end = size_table_builders_.end();
    121        size_builder != size_builder_end; size_builder++) {
    122     (*size_builder)->SetIndexSubTableArrayOffset(
    123         current_sub_table_block_start_offset);
    124     IndexSubTableBuilderList* index_sub_table_builder_list =
    125         (*size_builder)->IndexSubTableBuilders();
    126 
    127     // walking offset within the current subTable array
    128     int32_t index_sub_table_array_offset = current_sub_table_block_start_offset;
    129     // walking offset within the subTable entries
    130     int32_t index_sub_table_offset = index_sub_table_array_offset +
    131         index_sub_table_builder_list->size() * Offset::kIndexSubHeaderLength;
    132 
    133 #if defined (SFNTLY_DEBUG_BITMAP)
    134     fprintf(stderr, "size %d: sizeTable=%x, current subTable Block=%x, ",
    135             size_index, size_table_offset,
    136             current_sub_table_block_start_offset);
    137     fprintf(stderr, "index subTableStart=%x\n", index_sub_table_offset);
    138     size_index++;
    139     int32_t sub_table_index = 0;
    140 #endif
    141     for (IndexSubTableBuilderList::iterator
    142              index_sub_table_builder = index_sub_table_builder_list->begin(),
    143              index_sub_table_builder_end = index_sub_table_builder_list->end();
    144          index_sub_table_builder != index_sub_table_builder_end;
    145          index_sub_table_builder++) {
    146 #if defined (SFNTLY_DEBUG_BITMAP)
    147       fprintf(stderr, "\tsubTableIndex %d: format=%x, ", sub_table_index,
    148               (*index_sub_table_builder)->index_format());
    149       fprintf(stderr, "indexSubTableArrayOffset=%x, indexSubTableOffset=%x\n",
    150               index_sub_table_array_offset, index_sub_table_offset);
    151       sub_table_index++;
    152 #endif
    153       // array entry
    154       index_sub_table_array_offset += new_data->WriteUShort(
    155           index_sub_table_array_offset,
    156           (*index_sub_table_builder)->first_glyph_index());
    157       index_sub_table_array_offset += new_data->WriteUShort(
    158           index_sub_table_array_offset,
    159           (*index_sub_table_builder)->last_glyph_index());
    160       index_sub_table_array_offset += new_data->WriteULong(
    161           index_sub_table_array_offset,
    162           index_sub_table_offset - current_sub_table_block_start_offset);
    163 
    164       // index sub table
    165       WritableFontDataPtr slice_index_sub_table;
    166       slice_index_sub_table.Attach(down_cast<WritableFontData*>(
    167           new_data->Slice(index_sub_table_offset)));
    168       int32_t current_sub_table_size =
    169           (*index_sub_table_builder)->SubSerialize(slice_index_sub_table);
    170       int32_t padding = FontMath::PaddingRequired(current_sub_table_size,
    171                                                   DataSize::kULONG);
    172 #if defined (SFNTLY_DEBUG_BITMAP)
    173       fprintf(stderr, "\t\tsubTableSize = %x, padding = %x\n",
    174               current_sub_table_size, padding);
    175 #endif
    176       index_sub_table_offset += current_sub_table_size;
    177       index_sub_table_offset +=
    178           new_data->WritePadding(index_sub_table_offset, padding);
    179     }
    180 
    181     // serialize size table
    182     (*size_builder)->SetIndexTableSize(
    183         index_sub_table_offset - current_sub_table_block_start_offset);
    184     WritableFontDataPtr slice_size_table;
    185     slice_size_table.Attach(down_cast<WritableFontData*>(
    186         new_data->Slice(size_table_offset)));
    187     size_table_offset += (*size_builder)->SubSerialize(slice_size_table);
    188 
    189     current_sub_table_block_start_offset = index_sub_table_offset;
    190   }
    191   return size + current_sub_table_block_start_offset;
    192 }
    193 
    194 bool EblcTable::Builder::SubReadyToSerialize() {
    195   if (size_table_builders_.empty()) {
    196     return false;
    197   }
    198   for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(),
    199                                             e = size_table_builders_.end();
    200                                             b != e; b++) {
    201     if (!(*b)->SubReadyToSerialize()) {
    202       return false;
    203     }
    204   }
    205   return true;
    206 }
    207 
    208 int32_t EblcTable::Builder::SubDataSizeToSerialize() {
    209   if (size_table_builders_.empty()) {
    210     return 0;
    211   }
    212   int32_t size = Offset::kHeaderLength;
    213   bool variable = false;
    214 #if defined (SFNTLY_DEBUG_BITMAP)
    215   size_t size_index = 0;
    216 #endif
    217   for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(),
    218                                             e = size_table_builders_.end();
    219                                             b != e; b++) {
    220     int32_t size_builder_size = (*b)->SubDataSizeToSerialize();
    221 #if defined (SFNTLY_DEBUG_BITMAP)
    222     fprintf(stderr, "sizeIndex = %d, sizeBuilderSize=0x%x (%d)\n",
    223             size_index++, size_builder_size, size_builder_size);
    224 #endif
    225     variable = size_builder_size > 0 ? variable : true;
    226     size += abs(size_builder_size);
    227   }
    228 #if defined (SFNTLY_DEBUG_BITMAP)
    229   fprintf(stderr, "eblc size=%d\n", size);
    230 #endif
    231   return variable ? -size : size;
    232 }
    233 
    234 void EblcTable::Builder::SubDataSet() {
    235   Revert();
    236 }
    237 
    238 BitmapSizeTableBuilderList* EblcTable::Builder::BitmapSizeBuilders() {
    239   return GetSizeList();
    240 }
    241 
    242 void EblcTable::Builder::Revert() {
    243   size_table_builders_.clear();
    244   set_model_changed(false);
    245 }
    246 
    247 void EblcTable::Builder::GenerateLocaList(BitmapLocaList* output) {
    248   assert(output);
    249   BitmapSizeTableBuilderList* size_builder_list = GetSizeList();
    250   output->clear();
    251 #if defined (SFNTLY_DEBUG_BITMAP)
    252   int32_t size_index = 0;
    253 #endif
    254   for (BitmapSizeTableBuilderList::iterator b = size_builder_list->begin(),
    255                                             e = size_builder_list->end();
    256                                             b != e; b++) {
    257 #if defined (SFNTLY_DEBUG_BITMAP)
    258     fprintf(stderr, "size table = %d\n", size_index++);
    259 #endif
    260     BitmapGlyphInfoMap loca_map;
    261     (*b)->GenerateLocaMap(&loca_map);
    262     output->push_back(loca_map);
    263   }
    264 }
    265 
    266 CALLER_ATTACH
    267 FontDataTable* EblcTable::Builder::SubBuildTable(ReadableFontData* data) {
    268   Ptr<EblcTable> new_table = new EblcTable(header(), data);
    269   return new_table.Detach();
    270 }
    271 
    272 // static
    273 CALLER_ATTACH EblcTable::Builder*
    274     EblcTable::Builder::CreateBuilder(Header* header, WritableFontData* data) {
    275   Ptr<EblcTable::Builder> new_builder = new EblcTable::Builder(header, data);
    276   return new_builder.Detach();
    277 }
    278 
    279 // static
    280 CALLER_ATTACH EblcTable::Builder*
    281     EblcTable::Builder::CreateBuilder(Header* header, ReadableFontData* data) {
    282   Ptr<EblcTable::Builder> new_builder = new EblcTable::Builder(header, data);
    283   return new_builder.Detach();
    284 }
    285 
    286 BitmapSizeTableBuilderList* EblcTable::Builder::GetSizeList() {
    287   if (size_table_builders_.empty()) {
    288     Initialize(InternalReadData(), &size_table_builders_);
    289     set_model_changed();
    290   }
    291   return &size_table_builders_;
    292 }
    293 
    294 void EblcTable::Builder::Initialize(ReadableFontData* data,
    295                                     BitmapSizeTableBuilderList* output) {
    296   assert(output);
    297   if (data) {
    298     int32_t num_sizes = data->ReadULongAsInt(Offset::kNumSizes);
    299     for (int32_t i = 0; i < num_sizes; ++i) {
    300       ReadableFontDataPtr new_data;
    301       new_data.Attach(down_cast<ReadableFontData*>(
    302           data->Slice(Offset::kBitmapSizeTableArrayStart +
    303                       i * Offset::kBitmapSizeTableLength,
    304                       Offset::kBitmapSizeTableLength)));
    305       BitmapSizeTableBuilderPtr size_builder;
    306       size_builder.Attach(BitmapSizeTable::Builder::CreateBuilder(
    307           new_data, data));
    308       output->push_back(size_builder);
    309     }
    310   }
    311 }
    312 
    313 }  // namespace sfntly
    314