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
21 namespace sfntly {
22 /******************************************************************************
23 * IndexSubTableFormat2 class
24 ******************************************************************************/
~IndexSubTableFormat2()25 IndexSubTableFormat2::~IndexSubTableFormat2() {
26 }
27
ImageSize()28 int32_t IndexSubTableFormat2::ImageSize() {
29 return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable2_imageSize);
30 }
31
BigMetrics()32 CALLER_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
NumGlyphs()41 int32_t IndexSubTableFormat2::NumGlyphs() {
42 return last_glyph_index() - first_glyph_index() + 1;
43 }
44
GlyphStartOffset(int32_t glyph_id)45 int32_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
GlyphLength(int32_t glyph_id)53 int32_t IndexSubTableFormat2::GlyphLength(int32_t glyph_id) {
54 if (CheckGlyphRange(glyph_id) == -1) {
55 return 0;
56 }
57 return image_size_;
58 }
59
IndexSubTableFormat2(ReadableFontData * data,int32_t first,int32_t last)60 IndexSubTableFormat2::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 ******************************************************************************/
~Builder()71 IndexSubTableFormat2::Builder::~Builder() {
72 }
73
NumGlyphs()74 int32_t IndexSubTableFormat2::Builder::NumGlyphs() {
75 return last_glyph_index() - first_glyph_index() + 1;
76 }
77
GlyphStartOffset(int32_t glyph_id)78 int32_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
GlyphLength(int32_t glyph_id)86 int32_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
94 CALLER_ATTACH IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator*
GetIterator()95 IndexSubTableFormat2::Builder::GetIterator() {
96 Ptr<IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator> it =
97 new IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator(this);
98 return it.Detach();
99 }
100
ImageSize()101 int32_t IndexSubTableFormat2::Builder::ImageSize() {
102 return InternalReadData()->ReadULongAsInt(
103 EblcTable::Offset::kIndexSubTable2_imageSize);
104 }
105
SetImageSize(int32_t image_size)106 void IndexSubTableFormat2::Builder::SetImageSize(int32_t image_size) {
107 InternalWriteData()->WriteULong(EblcTable::Offset::kIndexSubTable2_imageSize,
108 image_size);
109 }
110
BigMetrics()111 BigGlyphMetrics::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
123 CALLER_ATTACH IndexSubTableFormat2::Builder*
CreateBuilder()124 IndexSubTableFormat2::Builder::CreateBuilder() {
125 IndexSubTableFormat2BuilderPtr output = new IndexSubTableFormat2::Builder();
126 return output.Detach();
127 }
128
129 // static
130 CALLER_ATTACH IndexSubTableFormat2::Builder*
CreateBuilder(ReadableFontData * data,int32_t index_sub_table_offset,int32_t first_glyph_index,int32_t last_glyph_index)131 IndexSubTableFormat2::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
153 CALLER_ATTACH IndexSubTableFormat2::Builder*
CreateBuilder(WritableFontData * data,int32_t index_sub_table_offset,int32_t first_glyph_index,int32_t last_glyph_index)154 IndexSubTableFormat2::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
SubBuildTable(ReadableFontData * data)172 CALLER_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
SubDataSet()179 void IndexSubTableFormat2::Builder::SubDataSet() {
180 Revert();
181 }
182
SubDataSizeToSerialize()183 int32_t IndexSubTableFormat2::Builder::SubDataSizeToSerialize() {
184 return EblcTable::Offset::kIndexSubTable2Length;
185 }
186
SubReadyToSerialize()187 bool IndexSubTableFormat2::Builder::SubReadyToSerialize() {
188 return true;
189 }
190
SubSerialize(WritableFontData * new_data)191 int32_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
Builder()211 IndexSubTableFormat2::Builder::Builder()
212 : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable3_builderDataSize,
213 IndexSubTable::Format::FORMAT_2) {
214 metrics_.Attach(BigGlyphMetrics::Builder::CreateBuilder());
215 }
216
Builder(WritableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)217 IndexSubTableFormat2::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
Builder(ReadableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)223 IndexSubTableFormat2::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
DataLength(ReadableFontData * data,int32_t index_sub_table_offset,int32_t first_glyph_index,int32_t last_glyph_index)230 int32_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 ******************************************************************************/
BitmapGlyphInfoIterator(IndexSubTableFormat2::Builder * container)245 IndexSubTableFormat2::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
HasNext()252 bool IndexSubTableFormat2::Builder::BitmapGlyphInfoIterator::HasNext() {
253 if (glyph_id_ <= container()->last_glyph_index()) {
254 return true;
255 }
256 return false;
257 }
258
259 CALLER_ATTACH BitmapGlyphInfo*
Next()260 IndexSubTableFormat2::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