Home | History | Annotate | Download | only in truetype
      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/truetype/loca_table.h"
     18 #include "sfntly/port/exception_type.h"
     19 
     20 namespace sfntly {
     21 /******************************************************************************
     22  * LocaTable class
     23  ******************************************************************************/
     24 LocaTable::~LocaTable() {}
     25 
     26 int32_t LocaTable::GlyphOffset(int32_t glyph_id) {
     27   if (glyph_id < 0 || glyph_id >= num_glyphs_) {
     28 #if !defined (SFNTLY_NO_EXCEPTION)
     29     throw IndexOutOfBoundException("Glyph ID is out of bounds.");
     30 #endif
     31     return 0;
     32   }
     33   return Loca(glyph_id);
     34 }
     35 
     36 int32_t LocaTable::GlyphLength(int32_t glyph_id) {
     37   if (glyph_id < 0 || glyph_id >= num_glyphs_) {
     38 #if !defined (SFNTLY_NO_EXCEPTION)
     39     throw IndexOutOfBoundException("Glyph ID is out of bounds.");
     40 #endif
     41     return 0;
     42   }
     43   return Loca(glyph_id + 1) - Loca(glyph_id);
     44 }
     45 
     46 int32_t LocaTable::NumLocas() {
     47   return num_glyphs_ + 1;
     48 }
     49 
     50 int32_t LocaTable::Loca(int32_t index) {
     51   if (index > num_glyphs_) {
     52 #if !defined (SFNTLY_NO_EXCEPTION)
     53     throw IndexOutOfBoundException();
     54 #endif
     55     return 0;
     56   }
     57   if (format_version_ == IndexToLocFormat::kShortOffset) {
     58     return 2 * data_->ReadUShort(index * DataSize::kUSHORT);
     59   }
     60   return data_->ReadULongAsInt(index * DataSize::kULONG);
     61 }
     62 
     63 LocaTable::LocaTable(Header* header,
     64                      ReadableFontData* data,
     65                      int32_t format_version,
     66                      int32_t num_glyphs)
     67     : Table(header, data),
     68       format_version_(format_version),
     69       num_glyphs_(num_glyphs) {
     70 }
     71 
     72 /******************************************************************************
     73  * LocaTable::Iterator class
     74  ******************************************************************************/
     75 LocaTable::LocaIterator::LocaIterator(LocaTable* table)
     76     : PODIterator<int32_t, LocaTable>(table), index_(-1) {
     77 }
     78 
     79 bool LocaTable::LocaIterator::HasNext() {
     80   return index_ <= container()->num_glyphs_;
     81 }
     82 
     83 int32_t LocaTable::LocaIterator::Next() {
     84   return container()->Loca(index_++);
     85 }
     86 
     87 /******************************************************************************
     88  * LocaTable::Builder class
     89  ******************************************************************************/
     90 LocaTable::Builder::Builder(Header* header, WritableFontData* data)
     91     : Table::Builder(header, data),
     92       format_version_(IndexToLocFormat::kLongOffset),
     93       num_glyphs_(-1) {
     94 }
     95 
     96 LocaTable::Builder::Builder(Header* header, ReadableFontData* data)
     97     : Table::Builder(header, data),
     98       format_version_(IndexToLocFormat::kLongOffset),
     99       num_glyphs_(-1) {
    100 }
    101 
    102 LocaTable::Builder::~Builder() {}
    103 
    104 CALLER_ATTACH
    105 LocaTable::Builder* LocaTable::Builder::CreateBuilder(Header* header,
    106                                                       WritableFontData* data) {
    107   Ptr<LocaTable::Builder> builder;
    108   builder = new LocaTable::Builder(header, data);
    109   return builder.Detach();
    110 }
    111 
    112 IntegerList* LocaTable::Builder::LocaList() {
    113   return GetLocaList();
    114 }
    115 
    116 void LocaTable::Builder::SetLocaList(IntegerList* list) {
    117   loca_.clear();
    118   if (list) {
    119     loca_ = *list;
    120     set_model_changed();
    121   }
    122 }
    123 
    124 int32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) {
    125   if (CheckGlyphRange(glyph_id) == -1) {
    126     return 0;
    127   }
    128   return GetLocaList()->at(glyph_id);
    129 }
    130 
    131 int32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) {
    132   if (CheckGlyphRange(glyph_id) == -1) {
    133     return 0;
    134   }
    135   return GetLocaList()->at(glyph_id + 1) - GetLocaList()->at(glyph_id);
    136 }
    137 
    138 void LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) {
    139   num_glyphs_ = num_glyphs;
    140 }
    141 
    142 int32_t LocaTable::Builder::NumGlyphs() {
    143   return LastGlyphIndex() - 1;
    144 }
    145 
    146 void LocaTable::Builder::Revert() {
    147   loca_.clear();
    148   set_model_changed(false);
    149 }
    150 
    151 int32_t LocaTable::Builder::NumLocas() {
    152   return GetLocaList()->size();
    153 }
    154 
    155 int32_t LocaTable::Builder::Loca(int32_t index) {
    156   return GetLocaList()->at(index);
    157 }
    158 
    159 CALLER_ATTACH
    160 FontDataTable* LocaTable::Builder::SubBuildTable(ReadableFontData* data) {
    161   FontDataTablePtr table =
    162       new LocaTable(header(), data, format_version_, num_glyphs_);
    163   return table.Detach();
    164 }
    165 
    166 void LocaTable::Builder::SubDataSet() {
    167   Initialize(InternalReadData());
    168 }
    169 
    170 int32_t LocaTable::Builder::SubDataSizeToSerialize() {
    171   if (loca_.empty()) {
    172     return 0;
    173   }
    174   if (format_version_ == IndexToLocFormat::kLongOffset) {
    175     return loca_.size() * DataSize::kULONG;
    176   }
    177   return loca_.size() * DataSize::kUSHORT;
    178 }
    179 
    180 bool LocaTable::Builder::SubReadyToSerialize() {
    181   return !loca_.empty();
    182 }
    183 
    184 int32_t LocaTable::Builder::SubSerialize(WritableFontData* new_data) {
    185   int32_t size = 0;
    186   for (IntegerList::iterator l = loca_.begin(), end = loca_.end();
    187                              l != end; ++l) {
    188     if (format_version_ == IndexToLocFormat::kLongOffset) {
    189       size += new_data->WriteULong(size, *l);
    190     } else {
    191       size += new_data->WriteUShort(size, *l / 2);
    192     }
    193   }
    194   num_glyphs_ = loca_.size() - 1;
    195   return size;
    196 }
    197 
    198 void LocaTable::Builder::Initialize(ReadableFontData* data) {
    199   ClearLoca(false);
    200   if (data) {
    201     if (NumGlyphs() < 0) {
    202 #if !defined (SFNTLY_NO_EXCEPTION)
    203       throw IllegalStateException("numglyphs not set on LocaTable Builder.");
    204 #endif
    205       return;
    206     }
    207     LocaTablePtr table =
    208         new LocaTable(header(), data, format_version_, num_glyphs_);
    209     Ptr<LocaTable::LocaIterator> loca_iter =
    210         new LocaTable::LocaIterator(table);
    211     while (loca_iter->HasNext()) {
    212       loca_.push_back(loca_iter->Next());
    213     }
    214   }
    215 }
    216 
    217 int32_t LocaTable::Builder::CheckGlyphRange(int32_t glyph_id) {
    218   if (glyph_id < 0 || glyph_id > LastGlyphIndex()) {
    219 #if !defined (SFNTLY_NO_EXCEPTION)
    220     throw IndexOutOfBoundsException("Glyph ID is outside of the allowed range");
    221 #endif
    222     return -1;
    223   }
    224   return glyph_id;
    225 }
    226 
    227 int32_t LocaTable::Builder::LastGlyphIndex() {
    228   return !loca_.empty() ? loca_.size() - 2 : num_glyphs_ - 1;
    229 }
    230 
    231 IntegerList* LocaTable::Builder::GetLocaList() {
    232   if (loca_.empty()) {
    233     Initialize(InternalReadData());
    234     set_model_changed();
    235   }
    236   return &loca_;
    237 }
    238 
    239 void LocaTable::Builder::ClearLoca(bool nullify) {
    240   // Note: in C++ port, nullify is not used at all.
    241   UNREFERENCED_PARAMETER(nullify);
    242   loca_.clear();
    243   set_model_changed(false);
    244 }
    245 
    246 }  // namespace sfntly
    247