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/bitmap_size_table.h"
18
19#include <stdio.h>
20#include <stdlib.h>
21
22#include "sfntly/math/font_math.h"
23#include "sfntly/table/bitmap/eblc_table.h"
24#include "sfntly/table/bitmap/index_sub_table_format1.h"
25#include "sfntly/table/bitmap/index_sub_table_format2.h"
26#include "sfntly/table/bitmap/index_sub_table_format3.h"
27#include "sfntly/table/bitmap/index_sub_table_format4.h"
28#include "sfntly/table/bitmap/index_sub_table_format5.h"
29
30namespace sfntly {
31/******************************************************************************
32 * BitmapSizeTable class
33 ******************************************************************************/
34BitmapSizeTable::~BitmapSizeTable() {
35}
36
37int32_t BitmapSizeTable::IndexSubTableArrayOffset() {
38  return data_->ReadULongAsInt(
39      EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset);
40}
41
42int32_t BitmapSizeTable::IndexTableSize() {
43  return data_->ReadULongAsInt(
44      EblcTable::Offset::kBitmapSizeTable_indexTableSize);
45}
46
47int32_t BitmapSizeTable::NumberOfIndexSubTables() {
48  return NumberOfIndexSubTables(data_, 0);
49}
50
51int32_t BitmapSizeTable::ColorRef() {
52  return data_->ReadULongAsInt(EblcTable::Offset::kBitmapSizeTable_colorRef);
53}
54
55int32_t BitmapSizeTable::StartGlyphIndex() {
56  return data_->ReadUShort(EblcTable::Offset::kBitmapSizeTable_startGlyphIndex);
57}
58
59int32_t BitmapSizeTable::EndGlyphIndex() {
60  return data_->ReadUShort(EblcTable::Offset::kBitmapSizeTable_endGlyphIndex);
61}
62
63int32_t BitmapSizeTable::PpemX() {
64  return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_ppemX);
65}
66
67int32_t BitmapSizeTable::PpemY() {
68  return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_ppemY);
69}
70
71int32_t BitmapSizeTable::BitDepth() {
72  return data_->ReadByte(EblcTable::Offset::kBitmapSizeTable_bitDepth);
73}
74
75int32_t BitmapSizeTable::FlagsAsInt() {
76  return data_->ReadChar(EblcTable::Offset::kBitmapSizeTable_flags);
77}
78
79IndexSubTable* BitmapSizeTable::GetIndexSubTable(int32_t index) {
80  IndexSubTableList* subtable_list = GetIndexSubTableList();
81  if (index >= 0 && (size_t)index < subtable_list->size()) {
82    return (*subtable_list)[index];
83  }
84  return NULL;
85}
86
87int32_t BitmapSizeTable::GlyphOffset(int32_t glyph_id) {
88  IndexSubTable* subtable = SearchIndexSubTables(glyph_id);
89  if (subtable == NULL) {
90    return -1;
91  }
92  return subtable->GlyphOffset(glyph_id);
93}
94
95int32_t BitmapSizeTable::GlyphLength(int32_t glyph_id) {
96  IndexSubTable* subtable = SearchIndexSubTables(glyph_id);
97  if (subtable == NULL) {
98    return -1;
99  }
100  return subtable->GlyphLength(glyph_id);
101}
102
103CALLER_ATTACH BitmapGlyphInfo* BitmapSizeTable::GlyphInfo(int32_t glyph_id) {
104  IndexSubTable* sub_table = SearchIndexSubTables(glyph_id);
105  if (sub_table == NULL) {
106    return NULL;
107  }
108  return sub_table->GlyphInfo(glyph_id);
109}
110
111int32_t BitmapSizeTable::GlyphFormat(int32_t glyph_id) {
112  IndexSubTable* subtable = SearchIndexSubTables(glyph_id);
113  if (subtable == NULL) {
114    return -1;
115  }
116  return subtable->image_format();
117}
118
119BitmapSizeTable::BitmapSizeTable(ReadableFontData* data,
120                                 ReadableFontData* master_data)
121    : SubTable(data, master_data) {
122}
123
124// static
125int32_t BitmapSizeTable::NumberOfIndexSubTables(ReadableFontData* data,
126                                                int32_t table_offset) {
127  return data->ReadULongAsInt(table_offset +
128      EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables);
129}
130
131IndexSubTable* BitmapSizeTable::SearchIndexSubTables(int32_t glyph_id) {
132  // would be faster to binary search but too many size tables don't have
133  // sorted subtables
134#if (SFNTLY_BITMAPSIZE_USE_BINARY_SEARCH)
135  return BinarySearchIndexSubTables(glyph_id);
136#else
137  return LinearSearchIndexSubTables(glyph_id);
138#endif
139}
140
141IndexSubTable* BitmapSizeTable::LinearSearchIndexSubTables(int32_t glyph_id) {
142  IndexSubTableList* subtable_list = GetIndexSubTableList();
143  for (IndexSubTableList::iterator b = subtable_list->begin(),
144                                   e = subtable_list->end(); b != e; b++) {
145    if ((*b)->first_glyph_index() <= glyph_id &&
146        (*b)->last_glyph_index() >= glyph_id) {
147      return *b;
148    }
149  }
150  return NULL;
151}
152
153IndexSubTable* BitmapSizeTable::BinarySearchIndexSubTables(int32_t glyph_id) {
154  IndexSubTableList* subtable_list = GetIndexSubTableList();
155  int32_t index = 0;
156  int32_t bottom = 0;
157  int32_t top = subtable_list->size();
158  while (top != bottom) {
159    index = (top + bottom) / 2;
160    IndexSubTable* subtable = (*subtable_list)[index];
161    if (glyph_id < subtable->first_glyph_index()) {
162      // Location beow current location
163      top = index;
164    } else {
165      if (glyph_id <= subtable->last_glyph_index()) {
166        return subtable;
167      } else {
168        bottom = index + 1;
169      }
170    }
171  }
172  return NULL;
173}
174
175CALLER_ATTACH
176IndexSubTable* BitmapSizeTable::CreateIndexSubTable(int32_t index) {
177  return IndexSubTable::CreateIndexSubTable(master_read_data(),
178                                            IndexSubTableArrayOffset(),
179                                            index);
180}
181
182IndexSubTableList* BitmapSizeTable::GetIndexSubTableList() {
183  AutoLock lock(index_subtables_lock_);
184  if (index_subtables_.empty()) {
185    for (int32_t i = 0; i < NumberOfIndexSubTables(); ++i) {
186      IndexSubTablePtr table;
187      table.Attach(CreateIndexSubTable(i));
188      index_subtables_.push_back(table);
189    }
190  }
191  return &index_subtables_;
192}
193
194/******************************************************************************
195 * BitmapSizeTable::Builder class
196 ******************************************************************************/
197BitmapSizeTable::Builder::~Builder() {
198}
199
200CALLER_ATTACH
201FontDataTable* BitmapSizeTable::Builder::SubBuildTable(ReadableFontData* data) {
202  BitmapSizeTablePtr output = new BitmapSizeTable(data, master_read_data());
203  return output.Detach();
204}
205
206void BitmapSizeTable::Builder::SubDataSet() {
207  Revert();
208}
209
210int32_t BitmapSizeTable::Builder::SubDataSizeToSerialize() {
211  IndexSubTableBuilderList* builders = IndexSubTableBuilders();
212  if (builders->empty()) {
213    return 0;
214  }
215  int32_t size = EblcTable::Offset::kBitmapSizeTableLength;
216  bool variable = false;
217  for (IndexSubTableBuilderList::iterator b = builders->begin(),
218                                          e = builders->end(); b != e; b++) {
219    size += EblcTable::Offset::kIndexSubTableEntryLength;
220    int32_t sub_table_size = (*b)->SubDataSizeToSerialize();
221    int32_t padding = FontMath::PaddingRequired(abs(sub_table_size),
222                                                DataSize::kULONG);
223#if defined (SFNTLY_DEBUG_BITMAP)
224    fprintf(stderr, "subtable size=%d\n", sub_table_size);
225#endif
226    variable = (sub_table_size > 0) ? variable : true;
227    size += abs(sub_table_size) + padding;
228  }
229#if defined (SFNTLY_DEBUG_BITMAP)
230  fprintf(stderr, "bitmap table size=%d\n", variable ? -size : size);
231#endif
232  return variable ? -size : size;
233}
234
235bool BitmapSizeTable::Builder::SubReadyToSerialize() {
236  if (IndexSubTableBuilders()->empty()) {
237    return false;
238  }
239  return true;
240}
241
242int32_t BitmapSizeTable::Builder::SubSerialize(WritableFontData* new_data) {
243  SetNumberOfIndexSubTables(IndexSubTableBuilders()->size());
244  int32_t size = InternalReadData()->CopyTo(new_data);
245  return size;
246}
247
248CALLER_ATTACH BitmapSizeTable::Builder*
249BitmapSizeTable::Builder::CreateBuilder(WritableFontData* data,
250                                        ReadableFontData* master_data) {
251  BitmapSizeTableBuilderPtr output =
252      new BitmapSizeTable::Builder(data, master_data);
253  return output.Detach();
254}
255
256CALLER_ATTACH BitmapSizeTable::Builder*
257BitmapSizeTable::Builder::CreateBuilder(ReadableFontData* data,
258                                        ReadableFontData* master_data) {
259  BitmapSizeTableBuilderPtr output =
260      new BitmapSizeTable::Builder(data, master_data);
261  return output.Detach();
262}
263
264int32_t BitmapSizeTable::Builder::IndexSubTableArrayOffset() {
265  return InternalReadData()->ReadULongAsInt(
266      EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset);
267}
268
269void BitmapSizeTable::Builder::SetIndexSubTableArrayOffset(int32_t offset) {
270  InternalWriteData()->WriteULong(
271      EblcTable::Offset::kBitmapSizeTable_indexSubTableArrayOffset, offset);
272}
273
274int32_t BitmapSizeTable::Builder::IndexTableSize() {
275  return InternalReadData()->ReadULongAsInt(
276      EblcTable::Offset::kBitmapSizeTable_indexTableSize);
277}
278
279void BitmapSizeTable::Builder::SetIndexTableSize(int32_t size) {
280  InternalWriteData()->WriteULong(
281      EblcTable::Offset::kBitmapSizeTable_indexTableSize, size);
282}
283
284int32_t BitmapSizeTable::Builder::NumberOfIndexSubTables() {
285  return GetIndexSubTableBuilders()->size();
286}
287
288int32_t BitmapSizeTable::Builder::ColorRef() {
289  return InternalReadData()->ReadULongAsInt(
290      EblcTable::Offset::kBitmapSizeTable_colorRef);
291}
292
293int32_t BitmapSizeTable::Builder::StartGlyphIndex() {
294  return InternalReadData()->ReadUShort(
295      EblcTable::Offset::kBitmapSizeTable_startGlyphIndex);
296}
297
298int32_t BitmapSizeTable::Builder::EndGlyphIndex() {
299  return InternalReadData()->ReadUShort(
300      EblcTable::Offset::kBitmapSizeTable_endGlyphIndex);
301}
302
303int32_t BitmapSizeTable::Builder::PpemX() {
304  return InternalReadData()->ReadByte(
305      EblcTable::Offset::kBitmapSizeTable_ppemX);
306}
307
308int32_t BitmapSizeTable::Builder::PpemY() {
309  return InternalReadData()->ReadByte(
310      EblcTable::Offset::kBitmapSizeTable_ppemY);
311}
312
313int32_t BitmapSizeTable::Builder::BitDepth() {
314  return InternalReadData()->ReadByte(
315      EblcTable::Offset::kBitmapSizeTable_bitDepth);
316}
317
318int32_t BitmapSizeTable::Builder::FlagsAsInt() {
319  return InternalReadData()->ReadChar(
320      EblcTable::Offset::kBitmapSizeTable_flags);
321}
322
323IndexSubTable::Builder* BitmapSizeTable::Builder::IndexSubTableBuilder(
324    int32_t index) {
325  IndexSubTableBuilderList* sub_table_list = GetIndexSubTableBuilders();
326  return sub_table_list->at(index);
327}
328
329CALLER_ATTACH BitmapGlyphInfo* BitmapSizeTable::Builder::GlyphInfo(
330    int32_t glyph_id) {
331  IndexSubTable::Builder* sub_table = SearchIndexSubTables(glyph_id);
332  if (sub_table == NULL) {
333    return NULL;
334  }
335  return sub_table->GlyphInfo(glyph_id);
336}
337
338int32_t BitmapSizeTable::Builder::GlyphOffset(int32_t glyph_id) {
339  IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id);
340  if (subtable == NULL) {
341    return -1;
342  }
343  return subtable->GlyphOffset(glyph_id);
344}
345
346int32_t BitmapSizeTable::Builder::GlyphLength(int32_t glyph_id) {
347  IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id);
348  if (subtable == NULL) {
349    return -1;
350  }
351  return subtable->GlyphLength(glyph_id);
352}
353
354int32_t BitmapSizeTable::Builder::GlyphFormat(int32_t glyph_id) {
355  IndexSubTable::Builder* subtable = SearchIndexSubTables(glyph_id);
356  if (subtable == NULL) {
357    return -1;
358  }
359  return subtable->image_format();
360}
361
362IndexSubTableBuilderList* BitmapSizeTable::Builder::IndexSubTableBuilders() {
363  return GetIndexSubTableBuilders();
364}
365
366CALLER_ATTACH BitmapSizeTable::Builder::BitmapGlyphInfoIterator*
367BitmapSizeTable::Builder::GetIterator() {
368  Ptr<BitmapSizeTable::Builder::BitmapGlyphInfoIterator> output =
369      new BitmapSizeTable::Builder::BitmapGlyphInfoIterator(this);
370  return output.Detach();
371}
372
373void BitmapSizeTable::Builder::GenerateLocaMap(BitmapGlyphInfoMap* output) {
374  assert(output);
375  Ptr<BitmapSizeTable::Builder::BitmapGlyphInfoIterator> it;
376  it.Attach(GetIterator());
377  while (it->HasNext()) {
378    BitmapGlyphInfoPtr info;
379    info.Attach(it->Next());
380    (*output)[info->glyph_id()] = info;
381  }
382}
383
384void BitmapSizeTable::Builder::Revert() {
385  index_sub_tables_.clear();
386  set_model_changed(false);
387}
388
389BitmapSizeTable::Builder::Builder(WritableFontData* data,
390                                  ReadableFontData* master_data)
391    : SubTable::Builder(data, master_data) {
392}
393
394BitmapSizeTable::Builder::Builder(ReadableFontData* data,
395                                  ReadableFontData* master_data)
396    : SubTable::Builder(data, master_data) {
397}
398
399void BitmapSizeTable::Builder::SetNumberOfIndexSubTables(int32_t count) {
400  InternalWriteData()->WriteULong(
401      EblcTable::Offset::kBitmapSizeTable_numberOfIndexSubTables, count);
402}
403
404IndexSubTable::Builder* BitmapSizeTable::Builder::SearchIndexSubTables(
405    int32_t glyph_id) {
406  // would be faster to binary search but too many size tables don't have
407  // sorted subtables
408#if (SFNTLY_BITMAPSIZE_USE_BINARY_SEARCH)
409  return BinarySearchIndexSubTables(glyph_id);
410#else
411  return LinearSearchIndexSubTables(glyph_id);
412#endif
413}
414
415IndexSubTable::Builder* BitmapSizeTable::Builder::LinearSearchIndexSubTables(
416    int32_t glyph_id) {
417  IndexSubTableBuilderList* subtable_list = GetIndexSubTableBuilders();
418  for (IndexSubTableBuilderList::iterator b = subtable_list->begin(),
419                                          e = subtable_list->end();
420                                          b != e; b++) {
421    if ((*b)->first_glyph_index() <= glyph_id &&
422        (*b)->last_glyph_index() >= glyph_id) {
423      return *b;
424    }
425  }
426  return NULL;
427}
428
429IndexSubTable::Builder* BitmapSizeTable::Builder::BinarySearchIndexSubTables(
430    int32_t glyph_id) {
431  IndexSubTableBuilderList* subtable_list = GetIndexSubTableBuilders();
432  int32_t index = 0;
433  int32_t bottom = 0;
434  int32_t top = subtable_list->size();
435  while (top != bottom) {
436    index = (top + bottom) / 2;
437    IndexSubTable::Builder* subtable = subtable_list->at(index);
438    if (glyph_id < subtable->first_glyph_index()) {
439      // Location beow current location
440      top = index;
441    } else {
442      if (glyph_id <= subtable->last_glyph_index()) {
443        return subtable;
444      } else {
445        bottom = index + 1;
446      }
447    }
448  }
449  return NULL;
450}
451
452IndexSubTableBuilderList* BitmapSizeTable::Builder::GetIndexSubTableBuilders() {
453  if (index_sub_tables_.empty()) {
454    Initialize(InternalReadData());
455    set_model_changed();
456  }
457  return &index_sub_tables_;
458}
459
460void BitmapSizeTable::Builder::Initialize(ReadableFontData* data) {
461  index_sub_tables_.clear();
462  if (data) {
463    int32_t number_of_index_subtables =
464        BitmapSizeTable::NumberOfIndexSubTables(data, 0);
465    index_sub_tables_.resize(number_of_index_subtables);
466    for (int32_t i = 0; i < number_of_index_subtables; ++i) {
467      index_sub_tables_[i].Attach(CreateIndexSubTableBuilder(i));
468    }
469  }
470}
471
472CALLER_ATTACH IndexSubTable::Builder*
473BitmapSizeTable::Builder::CreateIndexSubTableBuilder(int32_t index) {
474  return IndexSubTable::Builder::CreateBuilder(master_read_data(),
475                                               IndexSubTableArrayOffset(),
476                                               index);
477}
478
479/******************************************************************************
480 * BitmapSizeTable::Builder::BitmapGlyphInfoIterator class
481 ******************************************************************************/
482BitmapSizeTable::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
483    BitmapSizeTable::Builder* container)
484    : RefIterator<BitmapGlyphInfo, BitmapSizeTable::Builder>(container) {
485  sub_table_iter_ = container->IndexSubTableBuilders()->begin();
486  sub_table_glyph_info_iter_.Attach((*sub_table_iter_)->GetIterator());
487}
488
489bool BitmapSizeTable::Builder::BitmapGlyphInfoIterator::HasNext() {
490  if (sub_table_glyph_info_iter_ && HasNext(sub_table_glyph_info_iter_)) {
491    return true;
492  }
493  while (++sub_table_iter_ != container()->IndexSubTableBuilders()->end()) {
494    sub_table_glyph_info_iter_.Attach((*sub_table_iter_)->GetIterator());
495    if (HasNext(sub_table_glyph_info_iter_)) {
496      return true;
497    }
498  }
499  return false;
500}
501
502CALLER_ATTACH
503BitmapGlyphInfo* BitmapSizeTable::Builder::BitmapGlyphInfoIterator::Next() {
504  if (!HasNext()) {
505    // Note: In C++, we do not throw exception when there's no element.
506    return NULL;
507  }
508  return Next(sub_table_glyph_info_iter_);
509}
510
511bool BitmapSizeTable::Builder::BitmapGlyphInfoIterator::HasNext(
512    BitmapGlyphInfoIter* iterator_base) {
513  if (iterator_base) {
514    switch (iterator_base->container_base()->index_format()) {
515      case 1: {
516        IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* it =
517            down_cast<IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator*>(
518                iterator_base);
519        return it->HasNext();
520      }
521
522      case 2: {
523        IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* it =
524            down_cast<IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator*>(
525                iterator_base);
526        return it->HasNext();
527      }
528
529      case 3: {
530        IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator* it =
531            down_cast<IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator*>(
532                iterator_base);
533        return it->HasNext();
534      }
535
536      case 4: {
537        IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* it =
538            down_cast<IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator*>(
539                iterator_base);
540        return it->HasNext();
541      }
542
543      case 5: {
544        IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* it =
545            down_cast<IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator*>(
546                iterator_base);
547        return it->HasNext();
548      }
549
550      default:
551        break;
552    }
553  }
554  return false;
555}
556
557CALLER_ATTACH
558BitmapGlyphInfo* BitmapSizeTable::Builder::BitmapGlyphInfoIterator::Next(
559    BitmapGlyphInfoIter* iterator_base) {
560  if (iterator_base) {
561    switch (iterator_base->container_base()->index_format()) {
562      case 1: {
563        IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator* it =
564            down_cast<IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator*>(
565                iterator_base);
566        return it->Next();
567      }
568
569      case 2: {
570        IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* it =
571            down_cast<IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator*>(
572                iterator_base);
573        return it->Next();
574      }
575
576      case 3: {
577        IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator* it =
578            down_cast<IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator*>(
579                iterator_base);
580        return it->Next();
581      }
582
583      case 4: {
584        IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator* it =
585            down_cast<IndexSubTableFormat4::Builder::BitmapGlyphInfoIterator*>(
586                iterator_base);
587        return it->Next();
588      }
589
590      case 5: {
591        IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator* it =
592            down_cast<IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator*>(
593                iterator_base);
594        return it->Next();
595      }
596
597      default:
598        break;
599    }
600  }
601  return NULL;
602}
603
604}  // namespace sfntly
605