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.h" 18 19#include "sfntly/table/bitmap/eblc_table.h" 20#include "sfntly/table/bitmap/index_sub_table_format1.h" 21#include "sfntly/table/bitmap/index_sub_table_format2.h" 22#include "sfntly/table/bitmap/index_sub_table_format3.h" 23#include "sfntly/table/bitmap/index_sub_table_format4.h" 24#include "sfntly/table/bitmap/index_sub_table_format5.h" 25 26namespace sfntly { 27/****************************************************************************** 28 * IndexSubTable class 29 ******************************************************************************/ 30CALLER_ATTACH BitmapGlyphInfo* IndexSubTable::GlyphInfo(int32_t glyph_id) { 31 int32_t loca = CheckGlyphRange(glyph_id); 32 if (loca == -1) { 33 return NULL; 34 } 35 if (GlyphStartOffset(glyph_id) == -1) { 36 return NULL; 37 } 38 BitmapGlyphInfoPtr output = new BitmapGlyphInfo(glyph_id, 39 image_data_offset(), 40 GlyphStartOffset(glyph_id), 41 GlyphLength(glyph_id), 42 image_format()); 43 return output.Detach(); 44} 45 46int32_t IndexSubTable::GlyphOffset(int32_t glyph_id) { 47 int32_t glyph_start_offset = GlyphStartOffset(glyph_id); 48 if (glyph_start_offset == -1) { 49 return -1; 50 } 51 return image_data_offset() + glyph_start_offset; 52} 53 54// static 55CALLER_ATTACH IndexSubTable* 56 IndexSubTable::CreateIndexSubTable(ReadableFontData* data, 57 int32_t offset_to_index_sub_table_array, 58 int32_t array_index) { 59 IndexSubTableBuilderPtr builder; 60 builder.Attach(IndexSubTable::Builder::CreateBuilder( 61 data, offset_to_index_sub_table_array, array_index)); 62 return down_cast<IndexSubTable*>(builder->Build()); 63} 64 65IndexSubTable::IndexSubTable(ReadableFontData* data, 66 int32_t first_glyph_index, 67 int32_t last_glyph_index) 68 : SubTable(data), 69 first_glyph_index_(first_glyph_index), 70 last_glyph_index_(last_glyph_index) { 71 index_format_ = 72 data_->ReadUShort(EblcTable::Offset::kIndexSubHeader_indexFormat); 73 image_format_ = 74 data_->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat); 75 image_data_offset_ = 76 data_->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset); 77} 78 79int32_t IndexSubTable::CheckGlyphRange(int32_t glyph_id) { 80 return CheckGlyphRange(glyph_id, first_glyph_index(), last_glyph_index()); 81} 82 83// static 84int32_t IndexSubTable::CheckGlyphRange(int32_t glyph_id, 85 int32_t first_glyph_id, 86 int32_t last_glyph_id) { 87 if (glyph_id < first_glyph_id || glyph_id > last_glyph_id) { 88#if !defined (SFNTLY_NO_EXCEPTION) 89 throw IndexOutOfBoundException("Glyph ID is outside of the allowed range."); 90#endif 91 return -1; 92 } 93 return glyph_id - first_glyph_id; 94} 95 96/****************************************************************************** 97 * IndexSubTable::Builder class 98 ******************************************************************************/ 99IndexSubTable::Builder::~Builder() { 100} 101 102void IndexSubTable::Builder::Revert() { 103 set_model_changed(false); 104 Initialize(InternalReadData()); 105} 106 107CALLER_ATTACH BitmapGlyphInfo* IndexSubTable::Builder::GlyphInfo( 108 int32_t glyph_id) { 109 BitmapGlyphInfoPtr glyph_info = 110 new BitmapGlyphInfo(glyph_id, 111 image_data_offset(), 112 GlyphStartOffset(glyph_id), 113 GlyphLength(glyph_id), 114 image_format()); 115 return glyph_info.Detach(); 116} 117 118int32_t IndexSubTable::Builder::GlyphOffset(int32_t glyph_id) { 119 return image_data_offset() + GlyphStartOffset(glyph_id); 120} 121 122// static 123CALLER_ATTACH IndexSubTable::Builder* 124IndexSubTable::Builder::CreateBuilder(int32_t index_format) { 125 switch (index_format) { 126 case Format::FORMAT_1: 127 return IndexSubTableFormat1::Builder::CreateBuilder(); 128 case Format::FORMAT_2: 129 return IndexSubTableFormat2::Builder::CreateBuilder(); 130 case Format::FORMAT_3: 131 return IndexSubTableFormat3::Builder::CreateBuilder(); 132 case Format::FORMAT_4: 133 return IndexSubTableFormat4::Builder::CreateBuilder(); 134 case Format::FORMAT_5: 135 return IndexSubTableFormat5::Builder::CreateBuilder(); 136 default: 137#if !defined (SFNTLY_NO_EXCEPTION) 138 throw IllegalArgumentException("Invalid index subtable format"); 139#endif 140 return NULL; 141 } 142} 143 144// static 145CALLER_ATTACH IndexSubTable::Builder* 146IndexSubTable::Builder::CreateBuilder(ReadableFontData* data, 147 int32_t offset_to_index_sub_table_array, int32_t array_index) { 148 int32_t index_sub_table_entry_offset = 149 offset_to_index_sub_table_array + 150 array_index * EblcTable::Offset::kIndexSubTableEntryLength; 151 int32_t first_glyph_index = 152 data->ReadUShort(index_sub_table_entry_offset + 153 EblcTable::Offset::kIndexSubTableEntry_firstGlyphIndex); 154 int32_t last_glyph_index = 155 data->ReadUShort(index_sub_table_entry_offset + 156 EblcTable::Offset::kIndexSubTableEntry_lastGlyphIndex); 157 int32_t additional_offset_to_index_subtable = data->ReadULongAsInt( 158 index_sub_table_entry_offset + 159 EblcTable::Offset::kIndexSubTableEntry_additionalOffsetToIndexSubTable); 160 int32_t index_sub_table_offset = offset_to_index_sub_table_array + 161 additional_offset_to_index_subtable; 162 int32_t index_format = data->ReadUShort(index_sub_table_offset); 163 switch (index_format) { 164 case 1: 165 return IndexSubTableFormat1::Builder::CreateBuilder( 166 data, index_sub_table_offset, first_glyph_index, last_glyph_index); 167 case 2: 168 return IndexSubTableFormat2::Builder::CreateBuilder( 169 data, index_sub_table_offset, first_glyph_index, last_glyph_index); 170 case 3: 171 return IndexSubTableFormat3::Builder::CreateBuilder( 172 data, index_sub_table_offset, first_glyph_index, last_glyph_index); 173 case 4: 174 return IndexSubTableFormat4::Builder::CreateBuilder( 175 data, index_sub_table_offset, first_glyph_index, last_glyph_index); 176 case 5: 177 return IndexSubTableFormat5::Builder::CreateBuilder( 178 data, index_sub_table_offset, first_glyph_index, last_glyph_index); 179 default: 180 // Unknown format and unable to process. 181#if !defined (SFNTLY_NO_EXCEPTION) 182 throw IllegalArgumentException("Invalid Index Subtable Format"); 183#endif 184 break; 185 } 186 return NULL; 187} 188 189CALLER_ATTACH 190FontDataTable* IndexSubTable::Builder::SubBuildTable(ReadableFontData* data) { 191 UNREFERENCED_PARAMETER(data); 192 return NULL; 193} 194 195void IndexSubTable::Builder::SubDataSet() { 196 // NOP 197} 198 199int32_t IndexSubTable::Builder::SubDataSizeToSerialize() { 200 return 0; 201} 202 203bool IndexSubTable::Builder::SubReadyToSerialize() { 204 return false; 205} 206 207int32_t IndexSubTable::Builder::SubSerialize(WritableFontData* new_data) { 208 UNREFERENCED_PARAMETER(new_data); 209 return 0; 210} 211 212IndexSubTable::Builder::Builder(int32_t data_size, int32_t index_format) 213 : SubTable::Builder(data_size), 214 first_glyph_index_(0), 215 last_glyph_index_(0), 216 index_format_(index_format), 217 image_format_(0), 218 image_data_offset_(0) { 219} 220 221IndexSubTable::Builder::Builder(int32_t index_format, 222 int32_t image_format, 223 int32_t image_data_offset, 224 int32_t data_size) 225 : SubTable::Builder(data_size), 226 first_glyph_index_(0), 227 last_glyph_index_(0), 228 index_format_(index_format), 229 image_format_(image_format), 230 image_data_offset_(image_data_offset) { 231} 232 233IndexSubTable::Builder::Builder(WritableFontData* data, 234 int32_t first_glyph_index, 235 int32_t last_glyph_index) 236 : SubTable::Builder(data), 237 first_glyph_index_(first_glyph_index), 238 last_glyph_index_(last_glyph_index) { 239 Initialize(data); 240} 241 242IndexSubTable::Builder::Builder(ReadableFontData* data, 243 int32_t first_glyph_index, 244 int32_t last_glyph_index) 245 : SubTable::Builder(data), 246 first_glyph_index_(first_glyph_index), 247 last_glyph_index_(last_glyph_index) { 248 Initialize(data); 249} 250 251int32_t IndexSubTable::Builder::CheckGlyphRange(int32_t glyph_id) { 252 return IndexSubTable::CheckGlyphRange(glyph_id, 253 first_glyph_index(), 254 last_glyph_index()); 255} 256 257int32_t IndexSubTable::Builder::SerializeIndexSubHeader( 258 WritableFontData* data) { 259 int32_t size = 260 data->WriteUShort(EblcTable::Offset::kIndexSubHeader_indexFormat, 261 index_format()); 262 size += data->WriteUShort(EblcTable::Offset::kIndexSubHeader_imageFormat, 263 image_format()); 264 size += data->WriteULong(EblcTable::Offset::kIndexSubHeader_imageDataOffset, 265 image_data_offset()); 266 return size; 267} 268 269void IndexSubTable::Builder::Initialize(ReadableFontData* data) { 270 index_format_ = 271 data->ReadUShort(EblcTable::Offset::kIndexSubHeader_indexFormat); 272 image_format_ = 273 data->ReadUShort(EblcTable::Offset::kIndexSubHeader_imageFormat); 274 image_data_offset_ = 275 data->ReadULongAsInt(EblcTable::Offset::kIndexSubHeader_imageDataOffset); 276} 277 278} // namespace sfntly 279