blob: e2679b79a9e222a1696584a16c49e3ee44523fc0 [file] [log] [blame]
/*
* 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/index_sub_table_format3.h"
#include "sfntly/table/bitmap/eblc_table.h"
namespace sfntly {
/******************************************************************************
* IndexSubTableFormat3 class
******************************************************************************/
IndexSubTableFormat3::~IndexSubTableFormat3() {
}
int32_t IndexSubTableFormat3::NumGlyphs() {
return last_glyph_index() - first_glyph_index() + 1;
}
int32_t IndexSubTableFormat3::GlyphStartOffset(int32_t glyph_id) {
int32_t loca = CheckGlyphRange(glyph_id);
if (loca != -1) {
return Loca(loca);
}
return -1;
}
int32_t IndexSubTableFormat3::GlyphLength(int32_t glyph_id) {
int32_t loca = CheckGlyphRange(glyph_id);
if (loca != -1) {
return Loca(glyph_id + 1) - Loca(glyph_id);
}
return 0;
}
// static
int32_t IndexSubTableFormat3::GetDataLength(ReadableFontData* data,
int32_t offset,
int32_t first,
int32_t last) {
UNREFERENCED_PARAMETER(data);
UNREFERENCED_PARAMETER(offset);
return (last - first + 1 + 1) * DataSize::kUSHORT;
}
IndexSubTableFormat3::IndexSubTableFormat3(ReadableFontData* data,
int32_t first_glyph_index,
int32_t last_glyph_index)
: IndexSubTable(data, first_glyph_index, last_glyph_index) {
}
int32_t IndexSubTableFormat3::Loca(int32_t loca) {
int32_t read_offset =
data_->ReadUShort(EblcTable::Offset::kIndexSubTable3_offsetArray +
loca * DataSize::kUSHORT);
return read_offset;
}
/******************************************************************************
* IndexSubTableFormat3::Builder class
******************************************************************************/
IndexSubTableFormat3::Builder::~Builder() {
}
int32_t IndexSubTableFormat3::Builder::NumGlyphs() {
return GetOffsetArray()->size() - 1;
}
int32_t IndexSubTableFormat3::Builder::GlyphStartOffset(int32_t glyph_id) {
int32_t loca = CheckGlyphRange(glyph_id);
if (loca == -1) {
return -1;
}
return GetOffsetArray()->at(loca);
}
int32_t IndexSubTableFormat3::Builder::GlyphLength(int32_t glyph_id) {
int32_t loca = CheckGlyphRange(glyph_id);
if (loca == -1) {
return 0;
}
IntegerList* offset_array = GetOffsetArray();
return offset_array->at(loca + 1) - offset_array->at(loca);
}
CALLER_ATTACH IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator*
IndexSubTableFormat3::Builder::GetIterator() {
Ptr<IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator> it =
new IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator(this);
return it.Detach();
}
void IndexSubTableFormat3::Builder::Revert() {
offset_array_.clear();
IndexSubTable::Builder::Revert();
}
void IndexSubTableFormat3::Builder::SetOffsetArray(
const IntegerList& offset_array) {
offset_array_.clear();
offset_array_ = offset_array;
set_model_changed();
}
// static
CALLER_ATTACH IndexSubTableFormat3::Builder*
IndexSubTableFormat3::Builder::CreateBuilder() {
IndexSubTableFormat3BuilderPtr output = new IndexSubTableFormat3::Builder();
return output.Detach();
}
// static
CALLER_ATTACH IndexSubTableFormat3::Builder*
IndexSubTableFormat3::Builder::CreateBuilder(ReadableFontData* data,
int32_t index_sub_table_offset,
int32_t first_glyph_index,
int32_t last_glyph_index) {
int32_t length = Builder::DataLength(data,
index_sub_table_offset,
first_glyph_index,
last_glyph_index);
ReadableFontDataPtr new_data;
new_data.Attach(down_cast<ReadableFontData*>(
data->Slice(index_sub_table_offset, length)));
if (new_data == NULL) {
return NULL;
}
IndexSubTableFormat3BuilderPtr output =
new IndexSubTableFormat3::Builder(new_data,
first_glyph_index,
last_glyph_index);
return output.Detach();
}
// static
CALLER_ATTACH IndexSubTableFormat3::Builder*
IndexSubTableFormat3::Builder::CreateBuilder(WritableFontData* data,
int32_t index_sub_table_offset,
int32_t first_glyph_index,
int32_t last_glyph_index) {
int32_t length = Builder::DataLength(data,
index_sub_table_offset,
first_glyph_index,
last_glyph_index);
WritableFontDataPtr new_data;
new_data.Attach(down_cast<WritableFontData*>(
data->Slice(index_sub_table_offset, length)));
IndexSubTableFormat3BuilderPtr output =
new IndexSubTableFormat3::Builder(new_data,
first_glyph_index,
last_glyph_index);
return output.Detach();
}
CALLER_ATTACH FontDataTable* IndexSubTableFormat3::Builder::SubBuildTable(
ReadableFontData* data) {
IndexSubTableFormat3Ptr output = new IndexSubTableFormat3(
data, first_glyph_index(), last_glyph_index());
return output.Detach();
}
void IndexSubTableFormat3::Builder::SubDataSet() {
Revert();
}
int32_t IndexSubTableFormat3::Builder::SubDataSizeToSerialize() {
if (offset_array_.empty()) {
return InternalReadData()->Length();
}
return EblcTable::Offset::kIndexSubHeaderLength +
offset_array_.size() * DataSize::kULONG;
}
bool IndexSubTableFormat3::Builder::SubReadyToSerialize() {
if (!offset_array_.empty()) {
return true;
}
return false;
}
int32_t IndexSubTableFormat3::Builder::SubSerialize(
WritableFontData* new_data) {
int32_t size = SerializeIndexSubHeader(new_data);
if (!model_changed()) {
if (InternalReadData() == NULL) {
return size;
}
ReadableFontDataPtr source;
WritableFontDataPtr target;
source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
EblcTable::Offset::kIndexSubTable3_offsetArray)));
target.Attach(down_cast<WritableFontData*>(new_data->Slice(
EblcTable::Offset::kIndexSubTable3_offsetArray)));
size += source->CopyTo(target);
} else {
for (IntegerList::iterator b = GetOffsetArray()->begin(),
e = GetOffsetArray()->end(); b != e; b++) {
size += new_data->WriteUShort(size, *b);
}
}
return size;
}
IndexSubTableFormat3::Builder::Builder()
: IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable3_builderDataSize,
IndexSubTable::Format::FORMAT_3) {
}
IndexSubTableFormat3::Builder::Builder(WritableFontData* data,
int32_t first_glyph_index,
int32_t last_glyph_index)
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
}
IndexSubTableFormat3::Builder::Builder(ReadableFontData* data,
int32_t first_glyph_index,
int32_t last_glyph_index)
: IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
}
IntegerList* IndexSubTableFormat3::Builder::GetOffsetArray() {
if (offset_array_.empty()) {
Initialize(InternalReadData());
set_model_changed();
}
return &offset_array_;
}
void IndexSubTableFormat3::Builder::Initialize(ReadableFontData* data) {
offset_array_.clear();
if (data) {
int32_t num_offsets = (last_glyph_index() - first_glyph_index() + 1) + 1;
for (int32_t i = 0; i < num_offsets; ++i) {
offset_array_.push_back(data->ReadUShort(
EblcTable::Offset::kIndexSubTable3_offsetArray +
i * DataSize::kUSHORT));
}
}
}
// static
int32_t IndexSubTableFormat3::Builder::DataLength(
ReadableFontData* data,
int32_t index_sub_table_offset,
int32_t first_glyph_index,
int32_t last_glyph_index) {
UNREFERENCED_PARAMETER(data);
UNREFERENCED_PARAMETER(index_sub_table_offset);
return EblcTable::Offset::kIndexSubHeaderLength +
(last_glyph_index - first_glyph_index + 1 + 1) * DataSize::kUSHORT;
}
/******************************************************************************
* IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator class
******************************************************************************/
IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
IndexSubTableFormat3::Builder* container)
: RefIterator<BitmapGlyphInfo, IndexSubTableFormat3::Builder,
IndexSubTable::Builder>(container) {
glyph_id_ = container->first_glyph_index();
}
bool IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::HasNext() {
if (glyph_id_ <= container()->last_glyph_index()) {
return true;
}
return false;
}
CALLER_ATTACH BitmapGlyphInfo*
IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::Next() {
BitmapGlyphInfoPtr output;
if (!HasNext()) {
// Note: In C++, we do not throw exception when there's no element.
return NULL;
}
output = new BitmapGlyphInfo(glyph_id_,
container()->image_data_offset(),
container()->GlyphStartOffset(glyph_id_),
container()->GlyphLength(glyph_id_),
container()->image_format());
glyph_id_++;
return output.Detach();
}
} // namespace sfntly