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