summaryrefslogtreecommitdiff
path: root/sfntly/table/bitmap/eblc_table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sfntly/table/bitmap/eblc_table.cc')
-rw-r--r--sfntly/table/bitmap/eblc_table.cc313
1 files changed, 313 insertions, 0 deletions
diff --git a/sfntly/table/bitmap/eblc_table.cc b/sfntly/table/bitmap/eblc_table.cc
new file mode 100644
index 0000000..0ad2764
--- /dev/null
+++ b/sfntly/table/bitmap/eblc_table.cc
@@ -0,0 +1,313 @@
+/*
+ * Copyright 2011 Google Inc. All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "sfntly/table/bitmap/eblc_table.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "sfntly/math/font_math.h"
+
+namespace sfntly {
+/******************************************************************************
+ * EblcTable class
+ ******************************************************************************/
+int32_t EblcTable::Version() {
+ return data_->ReadFixed(Offset::kVersion);
+}
+
+int32_t EblcTable::NumSizes() {
+ return data_->ReadULongAsInt(Offset::kNumSizes);
+}
+
+BitmapSizeTable* EblcTable::GetBitmapSizeTable(int32_t index) {
+ if (index < 0 || index > NumSizes()) {
+#if !defined (SFNTLY_NO_EXCEPTION)
+ throw IndexOutOfBoundException(
+ "Size table index is outside the range of tables.");
+#endif
+ return NULL;
+ }
+ BitmapSizeTableList* bitmap_size_table_list = GetBitmapSizeTableList();
+ if (bitmap_size_table_list) {
+ return (*bitmap_size_table_list)[index];
+ }
+ return NULL;
+}
+
+EblcTable::EblcTable(Header* header, ReadableFontData* data)
+ : SubTableContainerTable(header, data) {
+}
+
+BitmapSizeTableList* EblcTable::GetBitmapSizeTableList() {
+ AutoLock lock(bitmap_size_table_lock_);
+ if (bitmap_size_table_.empty()) {
+ CreateBitmapSizeTable(data_, NumSizes(), &bitmap_size_table_);
+ }
+ return &bitmap_size_table_;
+}
+
+// static
+void EblcTable::CreateBitmapSizeTable(ReadableFontData* data,
+ int32_t num_sizes,
+ BitmapSizeTableList* output) {
+ assert(data);
+ assert(output);
+ for (int32_t i = 0; i < num_sizes; ++i) {
+ ReadableFontDataPtr new_data;
+ new_data.Attach(down_cast<ReadableFontData*>(
+ data->Slice(Offset::kBitmapSizeTableArrayStart +
+ i * Offset::kBitmapSizeTableLength,
+ Offset::kBitmapSizeTableLength)));
+ BitmapSizeTableBuilderPtr size_builder;
+ size_builder.Attach(
+ BitmapSizeTable::Builder::CreateBuilder(new_data, data));
+ BitmapSizeTablePtr size;
+ size.Attach(down_cast<BitmapSizeTable*>(size_builder->Build()));
+ output->push_back(size);
+ }
+}
+
+/******************************************************************************
+ * EblcTable::Builder class
+ ******************************************************************************/
+EblcTable::Builder::Builder(Header* header, WritableFontData* data)
+ : SubTableContainerTable::Builder(header, data) {
+}
+
+EblcTable::Builder::Builder(Header* header, ReadableFontData* data)
+ : SubTableContainerTable::Builder(header, data) {
+}
+
+EblcTable::Builder::~Builder() {
+}
+
+int32_t EblcTable::Builder::SubSerialize(WritableFontData* new_data) {
+ // header
+ int32_t size = new_data->WriteFixed(0, kVersion);
+ size += new_data->WriteULong(size, size_table_builders_.size());
+
+ // calculate the offsets
+ // offset to the start of the size table array
+ int32_t size_table_start_offset = size;
+ // walking offset in the size table array
+ int32_t size_table_offset = size_table_start_offset;
+ // offset to the start of the whole index subtable block
+ int32_t sub_table_block_start_offset = size_table_offset +
+ size_table_builders_.size() * Offset::kBitmapSizeTableLength;
+ // walking offset in the index subtable
+ // points to the start of the current subtable block
+ int32_t current_sub_table_block_start_offset = sub_table_block_start_offset;
+
+#if defined (SFNTLY_DEBUG_BITMAP)
+ int32_t size_index = 0;
+#endif
+ for (BitmapSizeTableBuilderList::iterator
+ size_builder = size_table_builders_.begin(),
+ size_builder_end = size_table_builders_.end();
+ size_builder != size_builder_end; size_builder++) {
+ (*size_builder)->SetIndexSubTableArrayOffset(
+ current_sub_table_block_start_offset);
+ IndexSubTableBuilderList* index_sub_table_builder_list =
+ (*size_builder)->IndexSubTableBuilders();
+
+ // walking offset within the current subTable array
+ int32_t index_sub_table_array_offset = current_sub_table_block_start_offset;
+ // walking offset within the subTable entries
+ int32_t index_sub_table_offset = index_sub_table_array_offset +
+ index_sub_table_builder_list->size() * Offset::kIndexSubHeaderLength;
+
+#if defined (SFNTLY_DEBUG_BITMAP)
+ fprintf(stderr, "size %d: sizeTable=%x, current subTable Block=%x, ",
+ size_index, size_table_offset,
+ current_sub_table_block_start_offset);
+ fprintf(stderr, "index subTableStart=%x\n", index_sub_table_offset);
+ size_index++;
+ int32_t sub_table_index = 0;
+#endif
+ for (IndexSubTableBuilderList::iterator
+ index_sub_table_builder = index_sub_table_builder_list->begin(),
+ index_sub_table_builder_end = index_sub_table_builder_list->end();
+ index_sub_table_builder != index_sub_table_builder_end;
+ index_sub_table_builder++) {
+#if defined (SFNTLY_DEBUG_BITMAP)
+ fprintf(stderr, "\tsubTableIndex %d: format=%x, ", sub_table_index,
+ (*index_sub_table_builder)->index_format());
+ fprintf(stderr, "indexSubTableArrayOffset=%x, indexSubTableOffset=%x\n",
+ index_sub_table_array_offset, index_sub_table_offset);
+ sub_table_index++;
+#endif
+ // array entry
+ index_sub_table_array_offset += new_data->WriteUShort(
+ index_sub_table_array_offset,
+ (*index_sub_table_builder)->first_glyph_index());
+ index_sub_table_array_offset += new_data->WriteUShort(
+ index_sub_table_array_offset,
+ (*index_sub_table_builder)->last_glyph_index());
+ index_sub_table_array_offset += new_data->WriteULong(
+ index_sub_table_array_offset,
+ index_sub_table_offset - current_sub_table_block_start_offset);
+
+ // index sub table
+ WritableFontDataPtr slice_index_sub_table;
+ slice_index_sub_table.Attach(down_cast<WritableFontData*>(
+ new_data->Slice(index_sub_table_offset)));
+ int32_t current_sub_table_size =
+ (*index_sub_table_builder)->SubSerialize(slice_index_sub_table);
+ int32_t padding = FontMath::PaddingRequired(current_sub_table_size,
+ DataSize::kULONG);
+#if defined (SFNTLY_DEBUG_BITMAP)
+ fprintf(stderr, "\t\tsubTableSize = %x, padding = %x\n",
+ current_sub_table_size, padding);
+#endif
+ index_sub_table_offset += current_sub_table_size;
+ index_sub_table_offset +=
+ new_data->WritePadding(index_sub_table_offset, padding);
+ }
+
+ // serialize size table
+ (*size_builder)->SetIndexTableSize(
+ index_sub_table_offset - current_sub_table_block_start_offset);
+ WritableFontDataPtr slice_size_table;
+ slice_size_table.Attach(down_cast<WritableFontData*>(
+ new_data->Slice(size_table_offset)));
+ size_table_offset += (*size_builder)->SubSerialize(slice_size_table);
+
+ current_sub_table_block_start_offset = index_sub_table_offset;
+ }
+ return size + current_sub_table_block_start_offset;
+}
+
+bool EblcTable::Builder::SubReadyToSerialize() {
+ if (size_table_builders_.empty()) {
+ return false;
+ }
+ for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(),
+ e = size_table_builders_.end();
+ b != e; b++) {
+ if (!(*b)->SubReadyToSerialize()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+int32_t EblcTable::Builder::SubDataSizeToSerialize() {
+ if (size_table_builders_.empty()) {
+ return 0;
+ }
+ int32_t size = Offset::kHeaderLength;
+ bool variable = false;
+#if defined (SFNTLY_DEBUG_BITMAP)
+ size_t size_index = 0;
+#endif
+ for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(),
+ e = size_table_builders_.end();
+ b != e; b++) {
+ int32_t size_builder_size = (*b)->SubDataSizeToSerialize();
+#if defined (SFNTLY_DEBUG_BITMAP)
+ fprintf(stderr, "sizeIndex = %d, sizeBuilderSize=0x%x (%d)\n",
+ size_index++, size_builder_size, size_builder_size);
+#endif
+ variable = size_builder_size > 0 ? variable : true;
+ size += abs(size_builder_size);
+ }
+#if defined (SFNTLY_DEBUG_BITMAP)
+ fprintf(stderr, "eblc size=%d\n", size);
+#endif
+ return variable ? -size : size;
+}
+
+void EblcTable::Builder::SubDataSet() {
+ Revert();
+}
+
+BitmapSizeTableBuilderList* EblcTable::Builder::BitmapSizeBuilders() {
+ return GetSizeList();
+}
+
+void EblcTable::Builder::Revert() {
+ size_table_builders_.clear();
+ set_model_changed(false);
+}
+
+void EblcTable::Builder::GenerateLocaList(BitmapLocaList* output) {
+ assert(output);
+ BitmapSizeTableBuilderList* size_builder_list = GetSizeList();
+ output->clear();
+#if defined (SFNTLY_DEBUG_BITMAP)
+ int32_t size_index = 0;
+#endif
+ for (BitmapSizeTableBuilderList::iterator b = size_builder_list->begin(),
+ e = size_builder_list->end();
+ b != e; b++) {
+#if defined (SFNTLY_DEBUG_BITMAP)
+ fprintf(stderr, "size table = %d\n", size_index++);
+#endif
+ BitmapGlyphInfoMap loca_map;
+ (*b)->GenerateLocaMap(&loca_map);
+ output->push_back(loca_map);
+ }
+}
+
+CALLER_ATTACH
+FontDataTable* EblcTable::Builder::SubBuildTable(ReadableFontData* data) {
+ Ptr<EblcTable> new_table = new EblcTable(header(), data);
+ return new_table.Detach();
+}
+
+// static
+CALLER_ATTACH EblcTable::Builder*
+ EblcTable::Builder::CreateBuilder(Header* header, WritableFontData* data) {
+ Ptr<EblcTable::Builder> new_builder = new EblcTable::Builder(header, data);
+ return new_builder.Detach();
+}
+
+// static
+CALLER_ATTACH EblcTable::Builder*
+ EblcTable::Builder::CreateBuilder(Header* header, ReadableFontData* data) {
+ Ptr<EblcTable::Builder> new_builder = new EblcTable::Builder(header, data);
+ return new_builder.Detach();
+}
+
+BitmapSizeTableBuilderList* EblcTable::Builder::GetSizeList() {
+ if (size_table_builders_.empty()) {
+ Initialize(InternalReadData(), &size_table_builders_);
+ set_model_changed();
+ }
+ return &size_table_builders_;
+}
+
+void EblcTable::Builder::Initialize(ReadableFontData* data,
+ BitmapSizeTableBuilderList* output) {
+ assert(output);
+ if (data) {
+ int32_t num_sizes = data->ReadULongAsInt(Offset::kNumSizes);
+ for (int32_t i = 0; i < num_sizes; ++i) {
+ ReadableFontDataPtr new_data;
+ new_data.Attach(down_cast<ReadableFontData*>(
+ data->Slice(Offset::kBitmapSizeTableArrayStart +
+ i * Offset::kBitmapSizeTableLength,
+ Offset::kBitmapSizeTableLength)));
+ BitmapSizeTableBuilderPtr size_builder;
+ size_builder.Attach(BitmapSizeTable::Builder::CreateBuilder(
+ new_data, data));
+ output->push_back(size_builder);
+ }
+ }
+}
+
+} // namespace sfntly