| /* |
| * 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_format2.h" |
| |
| #include "sfntly/table/bitmap/eblc_table.h" |
| |
| namespace sfntly { |
| /****************************************************************************** |
| * IndexSubTableFormat2 class |
| ******************************************************************************/ |
| IndexSubTableFormat2::~IndexSubTableFormat2() { |
| } |
| |
| int32_t IndexSubTableFormat2::ImageSize() { |
| return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize); |
| } |
| |
| CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat2::BigMetrics() { |
| ReadableFontDataPtr slice; |
| slice.Attach(down_cast<ReadableFontData*>( |
| data_->Slice(EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics, |
| BigGlyphMetrics::Offset::kMetricsLength))); |
| BigGlyphMetricsPtr output = new BigGlyphMetrics(slice); |
| return output.Detach(); |
| } |
| |
| int32_t IndexSubTableFormat2::NumGlyphs() { |
| return last_glyph_index() - first_glyph_index() + 1; |
| } |
| |
| int32_t IndexSubTableFormat2::GlyphStartOffset(int32_t glyph_id) { |
| int32_t loca = CheckGlyphRange(glyph_id); |
| if (loca == -1) { |
| return -1; |
| } |
| return loca * image_size_; |
| } |
| |
| int32_t IndexSubTableFormat2::GlyphLength(int32_t glyph_id) { |
| if (CheckGlyphRange(glyph_id) == -1) { |
| return 0; |
| } |
| return image_size_; |
| } |
| |
| IndexSubTableFormat2::IndexSubTableFormat2(ReadableFontData* data, |
| int32_t first, |
| int32_t last) |
| : IndexSubTable(data, first, last) { |
| image_size_ = |
| data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize); |
| } |
| |
| /****************************************************************************** |
| * IndexSubTableFormat2::Builder class |
| ******************************************************************************/ |
| IndexSubTableFormat2::Builder::~Builder() { |
| } |
| |
| int32_t IndexSubTableFormat2::Builder::NumGlyphs() { |
| return last_glyph_index() - first_glyph_index() + 1; |
| } |
| |
| int32_t IndexSubTableFormat2::Builder::GlyphStartOffset(int32_t glyph_id) { |
| int32_t loca = CheckGlyphRange(glyph_id); |
| if (loca == -1) { |
| return -1; |
| } |
| return loca * ImageSize(); |
| } |
| |
| int32_t IndexSubTableFormat2::Builder::GlyphLength(int32_t glyph_id) { |
| int32_t loca = CheckGlyphRange(glyph_id); |
| if (loca == -1) { |
| return 0; |
| } |
| return ImageSize(); |
| } |
| |
| CALLER_ATTACH IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* |
| IndexSubTableFormat2::Builder::GetIterator() { |
| Ptr<IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator> it = |
| new IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator(this); |
| return it.Detach(); |
| } |
| |
| int32_t IndexSubTableFormat2::Builder::ImageSize() { |
| return InternalReadData()->ReadULongAsInt( |
| EblcTable::Offset::kIndexSubTable2_imageSize); |
| } |
| |
| void IndexSubTableFormat2::Builder::SetImageSize(int32_t image_size) { |
| InternalWriteData()->WriteULong(EblcTable::Offset::kIndexSubTable2_imageSize, |
| image_size); |
| } |
| |
| BigGlyphMetrics::Builder* IndexSubTableFormat2::Builder::BigMetrics() { |
| if (metrics_ == NULL) { |
| WritableFontDataPtr data; |
| data.Attach(down_cast<WritableFontData*>(InternalWriteData()->Slice( |
| EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics, |
| BigGlyphMetrics::Offset::kMetricsLength))); |
| metrics_ = new BigGlyphMetrics::Builder(data); |
| } |
| return metrics_; |
| } |
| |
| // static |
| CALLER_ATTACH IndexSubTableFormat2::Builder* |
| IndexSubTableFormat2::Builder::CreateBuilder() { |
| IndexSubTableFormat2BuilderPtr output = new IndexSubTableFormat2::Builder(); |
| return output.Detach(); |
| } |
| |
| // static |
| CALLER_ATTACH IndexSubTableFormat2::Builder* |
| IndexSubTableFormat2::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; |
| } |
| IndexSubTableFormat2BuilderPtr output = |
| new IndexSubTableFormat2::Builder(new_data, |
| first_glyph_index, |
| last_glyph_index); |
| return output.Detach(); |
| } |
| |
| // static |
| CALLER_ATTACH IndexSubTableFormat2::Builder* |
| IndexSubTableFormat2::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))); |
| IndexSubTableFormat2BuilderPtr output = |
| new IndexSubTableFormat2::Builder(new_data, |
| first_glyph_index, |
| last_glyph_index); |
| return output.Detach(); |
| } |
| |
| CALLER_ATTACH FontDataTable* IndexSubTableFormat2::Builder::SubBuildTable( |
| ReadableFontData* data) { |
| IndexSubTableFormat2Ptr output = new IndexSubTableFormat2( |
| data, first_glyph_index(), last_glyph_index()); |
| return output.Detach(); |
| } |
| |
| void IndexSubTableFormat2::Builder::SubDataSet() { |
| Revert(); |
| } |
| |
| int32_t IndexSubTableFormat2::Builder::SubDataSizeToSerialize() { |
| return EblcTable::Offset::kIndexSubTable2Length; |
| } |
| |
| bool IndexSubTableFormat2::Builder::SubReadyToSerialize() { |
| return true; |
| } |
| |
| int32_t IndexSubTableFormat2::Builder::SubSerialize( |
| WritableFontData* new_data) { |
| int32_t size = SerializeIndexSubHeader(new_data); |
| if (metrics_ == NULL) { |
| ReadableFontDataPtr source; |
| WritableFontDataPtr target; |
| source.Attach(down_cast<ReadableFontData*>( |
| InternalReadData()->Slice(size))); |
| target.Attach(down_cast<WritableFontData*>(new_data->Slice(size))); |
| size += source->CopyTo(target); |
| } else { |
| WritableFontDataPtr slice; |
| size += new_data->WriteLong(EblcTable::Offset::kIndexSubTable2_imageSize, |
| ImageSize()); |
| slice.Attach(down_cast<WritableFontData*>(new_data->Slice(size))); |
| size += metrics_->SubSerialize(slice); |
| } |
| return size; |
| } |
| |
| IndexSubTableFormat2::Builder::Builder() |
| : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable3_builderDataSize, |
| IndexSubTable::Format::FORMAT_2) { |
| metrics_.Attach(BigGlyphMetrics::Builder::CreateBuilder()); |
| } |
| |
| IndexSubTableFormat2::Builder::Builder(WritableFontData* data, |
| int32_t first_glyph_index, |
| int32_t last_glyph_index) |
| : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { |
| } |
| |
| IndexSubTableFormat2::Builder::Builder(ReadableFontData* data, |
| int32_t first_glyph_index, |
| int32_t last_glyph_index) |
| : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { |
| } |
| |
| // static |
| int32_t IndexSubTableFormat2::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); |
| UNREFERENCED_PARAMETER(first_glyph_index); |
| UNREFERENCED_PARAMETER(last_glyph_index); |
| return EblcTable::Offset::kIndexSubTable2Length; |
| } |
| |
| /****************************************************************************** |
| * IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator class |
| ******************************************************************************/ |
| IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator( |
| IndexSubTableFormat2::Builder* container) |
| : RefIterator<BitmapGlyphInfo, IndexSubTableFormat2::Builder, |
| IndexSubTable::Builder>(container) { |
| glyph_id_ = container->first_glyph_index(); |
| } |
| |
| bool IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::HasNext() { |
| if (glyph_id_ <= container()->last_glyph_index()) { |
| return true; |
| } |
| return false; |
| } |
| |
| CALLER_ATTACH BitmapGlyphInfo* |
| IndexSubTableFormat2::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 |