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_format2.h" 18 19#include "sfntly/table/bitmap/eblc_table.h" 20 21namespace sfntly { 22/****************************************************************************** 23 * IndexSubTableFormat2 class 24 ******************************************************************************/ 25IndexSubTableFormat2::~IndexSubTableFormat2() { 26} 27 28int32_t IndexSubTableFormat2::ImageSize() { 29 return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize); 30} 31 32CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat2::BigMetrics() { 33 ReadableFontDataPtr slice; 34 slice.Attach(down_cast<ReadableFontData*>( 35 data_->Slice(EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics, 36 BigGlyphMetrics::Offset::kMetricsLength))); 37 BigGlyphMetricsPtr output = new BigGlyphMetrics(slice); 38 return output.Detach(); 39} 40 41int32_t IndexSubTableFormat2::NumGlyphs() { 42 return last_glyph_index() - first_glyph_index() + 1; 43} 44 45int32_t IndexSubTableFormat2::GlyphStartOffset(int32_t glyph_id) { 46 int32_t loca = CheckGlyphRange(glyph_id); 47 if (loca == -1) { 48 return -1; 49 } 50 return loca * image_size_; 51} 52 53int32_t IndexSubTableFormat2::GlyphLength(int32_t glyph_id) { 54 if (CheckGlyphRange(glyph_id) == -1) { 55 return 0; 56 } 57 return image_size_; 58} 59 60IndexSubTableFormat2::IndexSubTableFormat2(ReadableFontData* data, 61 int32_t first, 62 int32_t last) 63 : IndexSubTable(data, first, last) { 64 image_size_ = 65 data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize); 66} 67 68/****************************************************************************** 69 * IndexSubTableFormat2::Builder class 70 ******************************************************************************/ 71IndexSubTableFormat2::Builder::~Builder() { 72} 73 74int32_t IndexSubTableFormat2::Builder::NumGlyphs() { 75 return last_glyph_index() - first_glyph_index() + 1; 76} 77 78int32_t IndexSubTableFormat2::Builder::GlyphStartOffset(int32_t glyph_id) { 79 int32_t loca = CheckGlyphRange(glyph_id); 80 if (loca == -1) { 81 return -1; 82 } 83 return loca * ImageSize(); 84} 85 86int32_t IndexSubTableFormat2::Builder::GlyphLength(int32_t glyph_id) { 87 int32_t loca = CheckGlyphRange(glyph_id); 88 if (loca == -1) { 89 return 0; 90 } 91 return ImageSize(); 92} 93 94CALLER_ATTACH IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator* 95 IndexSubTableFormat2::Builder::GetIterator() { 96 Ptr<IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator> it = 97 new IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator(this); 98 return it.Detach(); 99} 100 101int32_t IndexSubTableFormat2::Builder::ImageSize() { 102 return InternalReadData()->ReadULongAsInt( 103 EblcTable::Offset::kIndexSubTable2_imageSize); 104} 105 106void IndexSubTableFormat2::Builder::SetImageSize(int32_t image_size) { 107 InternalWriteData()->WriteULong(EblcTable::Offset::kIndexSubTable2_imageSize, 108 image_size); 109} 110 111BigGlyphMetrics::Builder* IndexSubTableFormat2::Builder::BigMetrics() { 112 if (metrics_ == NULL) { 113 WritableFontDataPtr data; 114 data.Attach(down_cast<WritableFontData*>(InternalWriteData()->Slice( 115 EblcTable::Offset::kIndexSubTable2_bigGlyphMetrics, 116 BigGlyphMetrics::Offset::kMetricsLength))); 117 metrics_ = new BigGlyphMetrics::Builder(data); 118 } 119 return metrics_; 120} 121 122// static 123CALLER_ATTACH IndexSubTableFormat2::Builder* 124IndexSubTableFormat2::Builder::CreateBuilder() { 125 IndexSubTableFormat2BuilderPtr output = new IndexSubTableFormat2::Builder(); 126 return output.Detach(); 127} 128 129// static 130CALLER_ATTACH IndexSubTableFormat2::Builder* 131IndexSubTableFormat2::Builder::CreateBuilder(ReadableFontData* data, 132 int32_t index_sub_table_offset, 133 int32_t first_glyph_index, 134 int32_t last_glyph_index) { 135 int32_t length = Builder::DataLength(data, 136 index_sub_table_offset, 137 first_glyph_index, 138 last_glyph_index); 139 ReadableFontDataPtr new_data; 140 new_data.Attach(down_cast<ReadableFontData*>( 141 data->Slice(index_sub_table_offset, length))); 142 if (new_data == NULL) { 143 return NULL; 144 } 145 IndexSubTableFormat2BuilderPtr output = 146 new IndexSubTableFormat2::Builder(new_data, 147 first_glyph_index, 148 last_glyph_index); 149 return output.Detach(); 150} 151 152// static 153CALLER_ATTACH IndexSubTableFormat2::Builder* 154IndexSubTableFormat2::Builder::CreateBuilder(WritableFontData* data, 155 int32_t index_sub_table_offset, 156 int32_t first_glyph_index, 157 int32_t last_glyph_index) { 158 int32_t length = Builder::DataLength(data, 159 index_sub_table_offset, 160 first_glyph_index, 161 last_glyph_index); 162 WritableFontDataPtr new_data; 163 new_data.Attach(down_cast<WritableFontData*>( 164 data->Slice(index_sub_table_offset, length))); 165 IndexSubTableFormat2BuilderPtr output = 166 new IndexSubTableFormat2::Builder(new_data, 167 first_glyph_index, 168 last_glyph_index); 169 return output.Detach(); 170} 171 172CALLER_ATTACH FontDataTable* IndexSubTableFormat2::Builder::SubBuildTable( 173 ReadableFontData* data) { 174 IndexSubTableFormat2Ptr output = new IndexSubTableFormat2( 175 data, first_glyph_index(), last_glyph_index()); 176 return output.Detach(); 177} 178 179void IndexSubTableFormat2::Builder::SubDataSet() { 180 Revert(); 181} 182 183int32_t IndexSubTableFormat2::Builder::SubDataSizeToSerialize() { 184 return EblcTable::Offset::kIndexSubTable2Length; 185} 186 187bool IndexSubTableFormat2::Builder::SubReadyToSerialize() { 188 return true; 189} 190 191int32_t IndexSubTableFormat2::Builder::SubSerialize( 192 WritableFontData* new_data) { 193 int32_t size = SerializeIndexSubHeader(new_data); 194 if (metrics_ == NULL) { 195 ReadableFontDataPtr source; 196 WritableFontDataPtr target; 197 source.Attach(down_cast<ReadableFontData*>( 198 InternalReadData()->Slice(size))); 199 target.Attach(down_cast<WritableFontData*>(new_data->Slice(size))); 200 size += source->CopyTo(target); 201 } else { 202 WritableFontDataPtr slice; 203 size += new_data->WriteLong(EblcTable::Offset::kIndexSubTable2_imageSize, 204 ImageSize()); 205 slice.Attach(down_cast<WritableFontData*>(new_data->Slice(size))); 206 size += metrics_->SubSerialize(slice); 207 } 208 return size; 209} 210 211IndexSubTableFormat2::Builder::Builder() 212 : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable3_builderDataSize, 213 IndexSubTable::Format::FORMAT_2) { 214 metrics_.Attach(BigGlyphMetrics::Builder::CreateBuilder()); 215} 216 217IndexSubTableFormat2::Builder::Builder(WritableFontData* data, 218 int32_t first_glyph_index, 219 int32_t last_glyph_index) 220 : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { 221} 222 223IndexSubTableFormat2::Builder::Builder(ReadableFontData* data, 224 int32_t first_glyph_index, 225 int32_t last_glyph_index) 226 : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) { 227} 228 229// static 230int32_t IndexSubTableFormat2::Builder::DataLength( 231 ReadableFontData* data, 232 int32_t index_sub_table_offset, 233 int32_t first_glyph_index, 234 int32_t last_glyph_index) { 235 UNREFERENCED_PARAMETER(data); 236 UNREFERENCED_PARAMETER(index_sub_table_offset); 237 UNREFERENCED_PARAMETER(first_glyph_index); 238 UNREFERENCED_PARAMETER(last_glyph_index); 239 return EblcTable::Offset::kIndexSubTable2Length; 240} 241 242/****************************************************************************** 243 * IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator class 244 ******************************************************************************/ 245IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator( 246 IndexSubTableFormat2::Builder* container) 247 : RefIterator<BitmapGlyphInfo, IndexSubTableFormat2::Builder, 248 IndexSubTable::Builder>(container) { 249 glyph_id_ = container->first_glyph_index(); 250} 251 252bool IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::HasNext() { 253 if (glyph_id_ <= container()->last_glyph_index()) { 254 return true; 255 } 256 return false; 257} 258 259CALLER_ATTACH BitmapGlyphInfo* 260IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::Next() { 261 BitmapGlyphInfoPtr output; 262 if (!HasNext()) { 263 // Note: In C++, we do not throw exception when there's no element. 264 return NULL; 265 } 266 output = new BitmapGlyphInfo(glyph_id_, 267 container()->image_data_offset(), 268 container()->GlyphStartOffset(glyph_id_), 269 container()->GlyphLength(glyph_id_), 270 container()->image_format()); 271 glyph_id_++; 272 return output.Detach(); 273} 274 275} // namespace sfntly 276