Line data Source code
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_format4.h"
18 :
19 : #include "sfntly/table/bitmap/eblc_table.h"
20 :
21 : namespace sfntly {
22 : /******************************************************************************
23 : * IndexSubTableFormat4 class
24 : ******************************************************************************/
25 0 : IndexSubTableFormat4::~IndexSubTableFormat4() {
26 0 : }
27 :
28 0 : int32_t IndexSubTableFormat4::NumGlyphs() {
29 0 : return IndexSubTableFormat4::NumGlyphs(data_, 0);
30 : }
31 :
32 0 : int32_t IndexSubTableFormat4::GlyphStartOffset(int32_t glyph_id) {
33 0 : int32_t loca = CheckGlyphRange(glyph_id);
34 0 : if (loca == -1) {
35 0 : return -1;
36 : }
37 0 : int32_t pair_index = FindCodeOffsetPair(glyph_id);
38 0 : if (pair_index < 0) {
39 0 : return -1;
40 : }
41 0 : return data_->ReadUShort(EblcTable::Offset::kIndexSubTable4_glyphArray +
42 : pair_index *
43 : EblcTable::Offset::kCodeOffsetPairLength +
44 0 : EblcTable::Offset::kCodeOffsetPair_offset);
45 : }
46 :
47 0 : int32_t IndexSubTableFormat4::GlyphLength(int32_t glyph_id) {
48 0 : int32_t loca = CheckGlyphRange(glyph_id);
49 0 : if (loca == -1) {
50 0 : return -1;
51 : }
52 :
53 0 : int32_t pair_index = FindCodeOffsetPair(glyph_id);
54 0 : if (pair_index < 0) {
55 0 : return -1;
56 : }
57 0 : return data_->ReadUShort(
58 0 : EblcTable::Offset::kIndexSubTable4_glyphArray +
59 : (pair_index + 1) * EblcTable::Offset::kCodeOffsetPairLength +
60 0 : EblcTable::Offset::kCodeOffsetPair_offset) -
61 0 : data_->ReadUShort(
62 0 : EblcTable::Offset::kIndexSubTable4_glyphArray +
63 : (pair_index) * EblcTable::Offset::kCodeOffsetPairLength +
64 0 : EblcTable::Offset::kCodeOffsetPair_offset);
65 : }
66 :
67 0 : IndexSubTableFormat4::IndexSubTableFormat4(ReadableFontData* data,
68 : int32_t first,
69 0 : int32_t last)
70 0 : : IndexSubTable(data, first, last) {
71 0 : }
72 :
73 0 : int32_t IndexSubTableFormat4::FindCodeOffsetPair(int32_t glyph_id) {
74 0 : return data_->SearchUShort(EblcTable::Offset::kIndexSubTable4_glyphArray,
75 : EblcTable::Offset::kCodeOffsetPairLength,
76 0 : NumGlyphs(),
77 0 : glyph_id);
78 : }
79 :
80 0 : int32_t IndexSubTableFormat4::NumGlyphs(ReadableFontData* data,
81 : int32_t table_offset) {
82 0 : int32_t num_glyphs = data->ReadULongAsInt(table_offset +
83 0 : EblcTable::Offset::kIndexSubTable4_numGlyphs);
84 0 : return num_glyphs;
85 : }
86 :
87 : /******************************************************************************
88 : * IndexSubTableFormat4::CodeOffsetPair related class
89 : ******************************************************************************/
90 0 : IndexSubTableFormat4::CodeOffsetPair::CodeOffsetPair(int32_t glyph_code,
91 0 : int32_t offset)
92 0 : : glyph_code_(glyph_code), offset_(offset) {
93 0 : }
94 :
95 0 : IndexSubTableFormat4::CodeOffsetPairBuilder::CodeOffsetPairBuilder()
96 0 : : CodeOffsetPair(0, 0) {
97 0 : }
98 :
99 0 : IndexSubTableFormat4::CodeOffsetPairBuilder::CodeOffsetPairBuilder(
100 0 : int32_t glyph_code, int32_t offset)
101 0 : : CodeOffsetPair(glyph_code, offset) {
102 0 : }
103 :
104 0 : bool IndexSubTableFormat4::CodeOffsetPairGlyphCodeComparator::operator()(
105 : const CodeOffsetPair& lhs, const CodeOffsetPair& rhs) {
106 0 : return lhs.glyph_code() < rhs.glyph_code();
107 : }
108 :
109 : /******************************************************************************
110 : * IndexSubTableFormat4::Builder class
111 : ******************************************************************************/
112 0 : IndexSubTableFormat4::Builder::~Builder() {
113 0 : }
114 :
115 0 : int32_t IndexSubTableFormat4::Builder::NumGlyphs() {
116 0 : return GetOffsetArray()->size() - 1;
117 : }
118 :
119 0 : int32_t IndexSubTableFormat4::Builder::GlyphLength(int32_t glyph_id) {
120 0 : int32_t loca = CheckGlyphRange(glyph_id);
121 0 : if (loca == -1) {
122 0 : return 0;
123 : }
124 0 : int32_t pair_index = FindCodeOffsetPair(glyph_id);
125 0 : if (pair_index == -1) {
126 0 : return 0;
127 : }
128 0 : return GetOffsetArray()->at(pair_index + 1).offset() -
129 0 : GetOffsetArray()->at(pair_index).offset();
130 : }
131 :
132 0 : int32_t IndexSubTableFormat4::Builder::GlyphStartOffset(int32_t glyph_id) {
133 0 : int32_t loca = CheckGlyphRange(glyph_id);
134 0 : if (loca == -1) {
135 0 : return -1;
136 : }
137 0 : int32_t pair_index = FindCodeOffsetPair(glyph_id);
138 0 : if (pair_index == -1) {
139 0 : return -1;
140 : }
141 0 : return GetOffsetArray()->at(pair_index).offset();
142 : }
143 :
144 : CALLER_ATTACH IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator*
145 0 : IndexSubTableFormat4::Builder::GetIterator() {
146 : Ptr<IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator> it =
147 0 : new IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator(this);
148 0 : return it.Detach();
149 : }
150 :
151 : // static
152 : CALLER_ATTACH IndexSubTableFormat4::Builder*
153 0 : IndexSubTableFormat4::Builder::CreateBuilder() {
154 0 : IndexSubTableFormat4BuilderPtr output = new IndexSubTableFormat4::Builder();
155 0 : return output.Detach();
156 : }
157 :
158 : // static
159 : CALLER_ATTACH IndexSubTableFormat4::Builder*
160 0 : IndexSubTableFormat4::Builder::CreateBuilder(ReadableFontData* data,
161 : int32_t index_sub_table_offset,
162 : int32_t first_glyph_index,
163 : int32_t last_glyph_index) {
164 : int32_t length = Builder::DataLength(data,
165 : index_sub_table_offset,
166 : first_glyph_index,
167 0 : last_glyph_index);
168 0 : ReadableFontDataPtr new_data;
169 0 : new_data.Attach(down_cast<ReadableFontData*>(
170 0 : data->Slice(index_sub_table_offset, length)));
171 0 : if (new_data == NULL) {
172 0 : return NULL;
173 : }
174 : IndexSubTableFormat4BuilderPtr output =
175 : new IndexSubTableFormat4::Builder(new_data,
176 : first_glyph_index,
177 0 : last_glyph_index);
178 0 : return output.Detach();
179 : }
180 :
181 : // static
182 : CALLER_ATTACH IndexSubTableFormat4::Builder*
183 0 : IndexSubTableFormat4::Builder::CreateBuilder(WritableFontData* data,
184 : int32_t index_sub_table_offset,
185 : int32_t first_glyph_index,
186 : int32_t last_glyph_index) {
187 : int32_t length = Builder::DataLength(data,
188 : index_sub_table_offset,
189 : first_glyph_index,
190 0 : last_glyph_index);
191 0 : WritableFontDataPtr new_data;
192 0 : new_data.Attach(down_cast<WritableFontData*>(
193 0 : data->Slice(index_sub_table_offset, length)));
194 : IndexSubTableFormat4BuilderPtr output =
195 : new IndexSubTableFormat4::Builder(new_data,
196 : first_glyph_index,
197 0 : last_glyph_index);
198 0 : return output.Detach();
199 : }
200 :
201 0 : CALLER_ATTACH FontDataTable* IndexSubTableFormat4::Builder::SubBuildTable(
202 : ReadableFontData* data) {
203 : IndexSubTableFormat4Ptr output = new IndexSubTableFormat4(
204 0 : data, first_glyph_index(), last_glyph_index());
205 0 : return output.Detach();
206 : }
207 :
208 0 : void IndexSubTableFormat4::Builder::SubDataSet() {
209 0 : Revert();
210 0 : }
211 :
212 0 : int32_t IndexSubTableFormat4::Builder::SubDataSizeToSerialize() {
213 0 : if (offset_pair_array_.empty()) {
214 0 : return InternalReadData()->Length();
215 : }
216 : return EblcTable::Offset::kIndexSubHeaderLength + DataSize::kULONG +
217 0 : GetOffsetArray()->size() *
218 0 : EblcTable::Offset::kIndexSubTable4_codeOffsetPairLength;
219 : }
220 :
221 0 : bool IndexSubTableFormat4::Builder::SubReadyToSerialize() {
222 0 : if (!offset_pair_array_.empty()) {
223 0 : return true;
224 : }
225 0 : return false;
226 : }
227 :
228 0 : int32_t IndexSubTableFormat4::Builder::SubSerialize(
229 : WritableFontData* new_data) {
230 0 : int32_t size = SerializeIndexSubHeader(new_data);
231 0 : if (!model_changed()) {
232 0 : if (InternalReadData() == NULL) {
233 0 : return size;
234 : }
235 0 : ReadableFontDataPtr source;
236 0 : WritableFontDataPtr target;
237 0 : source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
238 0 : EblcTable::Offset::kIndexSubTable4_glyphArray)));
239 0 : target.Attach(down_cast<WritableFontData*>(new_data->Slice(
240 0 : EblcTable::Offset::kIndexSubTable4_glyphArray)));
241 0 : size += source->CopyTo(target);
242 : } else {
243 0 : size += new_data->WriteLong(size, offset_pair_array_.size() - 1);
244 0 : for (std::vector<CodeOffsetPairBuilder>::iterator
245 0 : b = GetOffsetArray()->begin(), e = GetOffsetArray()->end();
246 : b != e; b++) {
247 0 : size += new_data->WriteUShort(size, b->glyph_code());
248 0 : size += new_data->WriteUShort(size, b->offset());
249 : }
250 : }
251 0 : return size;
252 : }
253 :
254 0 : void IndexSubTableFormat4::Builder::Revert() {
255 0 : offset_pair_array_.clear();
256 0 : IndexSubTable::Builder::Revert();
257 0 : }
258 :
259 0 : void IndexSubTableFormat4::Builder::SetOffsetArray(
260 : const std::vector<CodeOffsetPairBuilder>& pair_array) {
261 0 : offset_pair_array_.clear();
262 0 : offset_pair_array_ = pair_array;
263 0 : set_model_changed();
264 0 : }
265 :
266 0 : IndexSubTableFormat4::Builder::Builder()
267 : : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable4_builderDataSize,
268 0 : Format::FORMAT_4) {
269 0 : }
270 :
271 0 : IndexSubTableFormat4::Builder::Builder(WritableFontData* data,
272 : int32_t first_glyph_index,
273 0 : int32_t last_glyph_index)
274 0 : : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
275 0 : }
276 :
277 0 : IndexSubTableFormat4::Builder::Builder(ReadableFontData* data,
278 : int32_t first_glyph_index,
279 0 : int32_t last_glyph_index)
280 0 : : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
281 0 : }
282 :
283 : std::vector<IndexSubTableFormat4::CodeOffsetPairBuilder>*
284 0 : IndexSubTableFormat4::Builder::GetOffsetArray() {
285 0 : if (offset_pair_array_.empty()) {
286 0 : Initialize(InternalReadData());
287 0 : set_model_changed();
288 : }
289 0 : return &offset_pair_array_;
290 : }
291 :
292 0 : void IndexSubTableFormat4::Builder::Initialize(ReadableFontData* data) {
293 0 : offset_pair_array_.clear();
294 0 : if (data) {
295 0 : int32_t num_pairs = IndexSubTableFormat4::NumGlyphs(data, 0) + 1;
296 0 : int32_t offset = EblcTable::Offset::kIndexSubTable4_glyphArray;
297 0 : for (int32_t i = 0; i < num_pairs; ++i) {
298 : int32_t glyph_code = data->ReadUShort(offset +
299 0 : EblcTable::Offset::kIndexSubTable4_codeOffsetPair_glyphCode);
300 0 : int32_t glyph_offset = data->ReadUShort(offset +
301 0 : EblcTable::Offset::kIndexSubTable4_codeOffsetPair_offset);
302 0 : offset += EblcTable::Offset::kIndexSubTable4_codeOffsetPairLength;
303 0 : CodeOffsetPairBuilder pair_builder(glyph_code, glyph_offset);
304 0 : offset_pair_array_.push_back(pair_builder);
305 : }
306 : }
307 0 : }
308 :
309 0 : int32_t IndexSubTableFormat4::Builder::FindCodeOffsetPair(int32_t glyph_id) {
310 0 : std::vector<CodeOffsetPairBuilder>* pair_list = GetOffsetArray();
311 0 : int32_t location = 0;
312 0 : int32_t bottom = 0;
313 0 : int32_t top = pair_list->size();
314 0 : while (top != bottom) {
315 0 : location = (top + bottom) / 2;
316 0 : CodeOffsetPairBuilder* pair = &(pair_list->at(location));
317 0 : if (glyph_id < pair->glyph_code()) {
318 : // location is below current location
319 0 : top = location;
320 0 : } else if (glyph_id > pair->glyph_code()) {
321 : // location is above current location
322 0 : bottom = location + 1;
323 : } else {
324 0 : return location;
325 : }
326 : }
327 0 : return -1;
328 : }
329 :
330 : // static
331 0 : int32_t IndexSubTableFormat4::Builder::DataLength(
332 : ReadableFontData* data,
333 : int32_t index_sub_table_offset,
334 : int32_t first_glyph_index,
335 : int32_t last_glyph_index) {
336 : int32_t num_glyphs = IndexSubTableFormat4::NumGlyphs(data,
337 0 : index_sub_table_offset);
338 : UNREFERENCED_PARAMETER(first_glyph_index);
339 : UNREFERENCED_PARAMETER(last_glyph_index);
340 0 : return EblcTable::Offset::kIndexSubTable4_glyphArray +
341 0 : num_glyphs * EblcTable::Offset::kIndexSubTable4_codeOffsetPair_offset;
342 : }
343 :
344 :
345 : /******************************************************************************
346 : * IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator class
347 : ******************************************************************************/
348 0 : IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
349 0 : IndexSubTableFormat4::Builder* container)
350 : : RefIterator<BitmapGlyphInfo, IndexSubTableFormat4::Builder,
351 : IndexSubTable::Builder>(container),
352 0 : code_offset_pair_index_(0) {
353 0 : }
354 :
355 0 : bool IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator::HasNext() {
356 0 : if (code_offset_pair_index_ <
357 0 : (int32_t)(container()->GetOffsetArray()->size() - 1)) {
358 0 : return true;
359 : }
360 0 : return false;
361 : }
362 :
363 : CALLER_ATTACH BitmapGlyphInfo*
364 0 : IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator::Next() {
365 0 : BitmapGlyphInfoPtr output;
366 0 : if (!HasNext()) {
367 : // Note: In C++, we do not throw exception when there's no element.
368 0 : return NULL;
369 : }
370 : std::vector<CodeOffsetPairBuilder>* offset_array =
371 0 : container()->GetOffsetArray();
372 0 : int32_t offset = offset_array->at(code_offset_pair_index_).offset();
373 0 : int32_t next_offset = offset_array->at(code_offset_pair_index_ + 1).offset();
374 0 : int32_t glyph_code = offset_array->at(code_offset_pair_index_).glyph_code();
375 : output = new BitmapGlyphInfo(glyph_code,
376 0 : container()->image_data_offset(),
377 : offset,
378 : next_offset - offset,
379 0 : container()->image_format());
380 0 : code_offset_pair_index_++;
381 0 : return output.Detach();
382 : }
383 :
384 : } // namespace sfntly
|