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