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
26 namespace sfntly {
27 /******************************************************************************
28 * IndexSubTable class
29 ******************************************************************************/
GlyphInfo(int32_t glyph_id)30 CALLER_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
GlyphOffset(int32_t glyph_id)46 int32_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
55 CALLER_ATTACH IndexSubTable*
CreateIndexSubTable(ReadableFontData * data,int32_t offset_to_index_sub_table_array,int32_t array_index)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
IndexSubTable(ReadableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)65 IndexSubTable::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
CheckGlyphRange(int32_t glyph_id)79 int32_t IndexSubTable::CheckGlyphRange(int32_t glyph_id) {
80 return CheckGlyphRange(glyph_id, first_glyph_index(), last_glyph_index());
81 }
82
83 // static
CheckGlyphRange(int32_t glyph_id,int32_t first_glyph_id,int32_t last_glyph_id)84 int32_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 ******************************************************************************/
~Builder()99 IndexSubTable::Builder::~Builder() {
100 }
101
Revert()102 void IndexSubTable::Builder::Revert() {
103 set_model_changed(false);
104 Initialize(InternalReadData());
105 }
106
GlyphInfo(int32_t glyph_id)107 CALLER_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
GlyphOffset(int32_t glyph_id)118 int32_t IndexSubTable::Builder::GlyphOffset(int32_t glyph_id) {
119 return image_data_offset() + GlyphStartOffset(glyph_id);
120 }
121
122 // static
123 CALLER_ATTACH IndexSubTable::Builder*
CreateBuilder(int32_t index_format)124 IndexSubTable::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
145 CALLER_ATTACH IndexSubTable::Builder*
CreateBuilder(ReadableFontData * data,int32_t offset_to_index_sub_table_array,int32_t array_index)146 IndexSubTable::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
189 CALLER_ATTACH
SubBuildTable(ReadableFontData * data)190 FontDataTable* IndexSubTable::Builder::SubBuildTable(ReadableFontData* data) {
191 UNREFERENCED_PARAMETER(data);
192 return NULL;
193 }
194
SubDataSet()195 void IndexSubTable::Builder::SubDataSet() {
196 // NOP
197 }
198
SubDataSizeToSerialize()199 int32_t IndexSubTable::Builder::SubDataSizeToSerialize() {
200 return 0;
201 }
202
SubReadyToSerialize()203 bool IndexSubTable::Builder::SubReadyToSerialize() {
204 return false;
205 }
206
SubSerialize(WritableFontData * new_data)207 int32_t IndexSubTable::Builder::SubSerialize(WritableFontData* new_data) {
208 UNREFERENCED_PARAMETER(new_data);
209 return 0;
210 }
211
Builder(int32_t data_size,int32_t index_format)212 IndexSubTable::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
Builder(int32_t index_format,int32_t image_format,int32_t image_data_offset,int32_t data_size)221 IndexSubTable::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
Builder(WritableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)233 IndexSubTable::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
Builder(ReadableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)242 IndexSubTable::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
CheckGlyphRange(int32_t glyph_id)251 int32_t IndexSubTable::Builder::CheckGlyphRange(int32_t glyph_id) {
252 return IndexSubTable::CheckGlyphRange(glyph_id,
253 first_glyph_index(),
254 last_glyph_index());
255 }
256
SerializeIndexSubHeader(WritableFontData * data)257 int32_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
Initialize(ReadableFontData * data)269 void 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