Line data Source code
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_format5.h"
18 :
19 : #include <algorithm>
20 :
21 : #include "sfntly/table/bitmap/eblc_table.h"
22 :
23 : namespace sfntly {
24 : /******************************************************************************
25 : * IndexSubTableFormat5 class
26 : ******************************************************************************/
27 0 : IndexSubTableFormat5::~IndexSubTableFormat5() {
28 0 : }
29 :
30 0 : int32_t IndexSubTableFormat5::NumGlyphs() {
31 0 : return NumGlyphs(data_, 0);
32 : }
33 :
34 0 : int32_t IndexSubTableFormat5::GlyphStartOffset(int32_t glyph_id) {
35 0 : int32_t check = CheckGlyphRange(glyph_id);
36 0 : if (check == -1) {
37 0 : return -1;
38 : }
39 0 : int32_t loca = ReadFontData()->SearchUShort(
40 : EblcTable::Offset::kIndexSubTable5_glyphArray,
41 : DataSize::kUSHORT,
42 0 : NumGlyphs(),
43 0 : glyph_id);
44 0 : if (loca == -1) {
45 0 : return loca;
46 : }
47 0 : return loca * ImageSize();
48 : }
49 :
50 0 : int32_t IndexSubTableFormat5::GlyphLength(int32_t glyph_id) {
51 0 : int32_t check = CheckGlyphRange(glyph_id);
52 0 : if (check == -1) {
53 0 : return 0;
54 : }
55 0 : return image_size_;
56 : }
57 :
58 0 : int32_t IndexSubTableFormat5::ImageSize() {
59 0 : return data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable5_imageSize);
60 : }
61 :
62 0 : CALLER_ATTACH BigGlyphMetrics* IndexSubTableFormat5::BigMetrics() {
63 0 : ReadableFontDataPtr data;
64 0 : data.Attach(down_cast<ReadableFontData*>(data_->Slice(
65 : EblcTable::Offset::kIndexSubTable5_bigGlyphMetrics,
66 0 : BigGlyphMetrics::Offset::kMetricsLength)));
67 0 : BigGlyphMetricsPtr output = new BigGlyphMetrics(data);
68 0 : return output.Detach();
69 : }
70 :
71 0 : IndexSubTableFormat5::IndexSubTableFormat5(ReadableFontData* data,
72 : int32_t first_glyph_index,
73 0 : int32_t last_glyph_index)
74 0 : : IndexSubTable(data, first_glyph_index, last_glyph_index) {
75 0 : image_size_ = data_->ReadULongAsInt(
76 0 : EblcTable::Offset::kIndexSubTable5_imageSize);
77 0 : }
78 :
79 : // static
80 0 : int32_t IndexSubTableFormat5::NumGlyphs(ReadableFontData* data,
81 : int32_t table_offset) {
82 0 : int32_t num_glyphs = data->ReadULongAsInt(table_offset +
83 0 : EblcTable::Offset::kIndexSubTable5_numGlyphs);
84 0 : return num_glyphs;
85 : }
86 :
87 : /******************************************************************************
88 : * IndexSubTableFormat5::Builder class
89 : ******************************************************************************/
90 0 : IndexSubTableFormat5::Builder::~Builder() {
91 0 : }
92 :
93 0 : int32_t IndexSubTableFormat5::Builder::NumGlyphs() {
94 0 : return GetGlyphArray()->size();
95 : }
96 :
97 0 : int32_t IndexSubTableFormat5::Builder::GlyphLength(int32_t glyph_id) {
98 : UNREFERENCED_PARAMETER(glyph_id);
99 0 : return ImageSize();
100 : }
101 :
102 0 : int32_t IndexSubTableFormat5::Builder::GlyphStartOffset(int32_t glyph_id) {
103 0 : int32_t check = CheckGlyphRange(glyph_id);
104 0 : if (check == -1) {
105 0 : return -1;
106 : }
107 0 : IntegerList* glyph_array = GetGlyphArray();
108 : IntegerList::iterator it = std::find(glyph_array->begin(),
109 : glyph_array->end(),
110 0 : glyph_id);
111 0 : if (it == glyph_array->end()) {
112 0 : return -1;
113 : }
114 0 : return (it - glyph_array->begin()) * ImageSize();
115 : }
116 :
117 : CALLER_ATTACH IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator*
118 0 : IndexSubTableFormat5::Builder::GetIterator() {
119 : Ptr<IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator> it =
120 0 : new IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator(this);
121 0 : return it.Detach();
122 : }
123 :
124 : // static
125 : CALLER_ATTACH IndexSubTableFormat5::Builder*
126 0 : IndexSubTableFormat5::Builder::CreateBuilder() {
127 0 : IndexSubTableFormat5BuilderPtr output = new IndexSubTableFormat5::Builder();
128 0 : return output.Detach();
129 : }
130 :
131 : // static
132 : CALLER_ATTACH IndexSubTableFormat5::Builder*
133 0 : IndexSubTableFormat5::Builder::CreateBuilder(ReadableFontData* data,
134 : int32_t index_sub_table_offset,
135 : int32_t first_glyph_index,
136 : int32_t last_glyph_index) {
137 : int32_t length = Builder::DataLength(data,
138 : index_sub_table_offset,
139 : first_glyph_index,
140 0 : last_glyph_index);
141 0 : ReadableFontDataPtr new_data;
142 0 : new_data.Attach(down_cast<ReadableFontData*>(
143 0 : data->Slice(index_sub_table_offset, length)));
144 0 : if (new_data == NULL) {
145 0 : return NULL;
146 : }
147 : IndexSubTableFormat5BuilderPtr output =
148 : new IndexSubTableFormat5::Builder(new_data,
149 : first_glyph_index,
150 0 : last_glyph_index);
151 0 : return output.Detach();
152 : }
153 :
154 : // static
155 : CALLER_ATTACH IndexSubTableFormat5::Builder*
156 0 : IndexSubTableFormat5::Builder::CreateBuilder(WritableFontData* data,
157 : int32_t index_sub_table_offset,
158 : int32_t first_glyph_index,
159 : int32_t last_glyph_index) {
160 : int32_t length = Builder::DataLength(data,
161 : index_sub_table_offset,
162 : first_glyph_index,
163 0 : last_glyph_index);
164 0 : WritableFontDataPtr new_data;
165 0 : new_data.Attach(down_cast<WritableFontData*>(
166 0 : data->Slice(index_sub_table_offset, length)));
167 : IndexSubTableFormat5BuilderPtr output =
168 : new IndexSubTableFormat5::Builder(new_data,
169 : first_glyph_index,
170 0 : last_glyph_index);
171 0 : return output.Detach();
172 : }
173 :
174 0 : CALLER_ATTACH FontDataTable* IndexSubTableFormat5::Builder::SubBuildTable(
175 : ReadableFontData* data) {
176 : IndexSubTableFormat5Ptr output = new IndexSubTableFormat5(
177 0 : data, first_glyph_index(), last_glyph_index());
178 0 : return output.Detach();
179 : }
180 :
181 0 : void IndexSubTableFormat5::Builder::SubDataSet() {
182 0 : Revert();
183 0 : }
184 :
185 0 : int32_t IndexSubTableFormat5::Builder::SubDataSizeToSerialize() {
186 0 : if (glyph_array_.empty()) {
187 0 : return InternalReadData()->Length();
188 : }
189 : return EblcTable::Offset::kIndexSubTable5_builderDataSize +
190 0 : glyph_array_.size() * DataSize::kUSHORT;
191 : }
192 :
193 0 : bool IndexSubTableFormat5::Builder::SubReadyToSerialize() {
194 0 : if (!glyph_array_.empty()) {
195 0 : return true;
196 : }
197 0 : return false;
198 : }
199 :
200 0 : int32_t IndexSubTableFormat5::Builder::SubSerialize(
201 : WritableFontData* new_data) {
202 0 : int32_t size = SerializeIndexSubHeader(new_data);
203 0 : if (!model_changed()) {
204 0 : ReadableFontDataPtr source;
205 0 : WritableFontDataPtr target;
206 0 : source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
207 0 : EblcTable::Offset::kIndexSubTable5_imageSize)));
208 0 : target.Attach(down_cast<WritableFontData*>(new_data->Slice(
209 0 : EblcTable::Offset::kIndexSubTable5_imageSize)));
210 0 : size += source->CopyTo(target);
211 : } else {
212 0 : size += new_data->WriteULong(EblcTable::Offset::kIndexSubTable5_imageSize,
213 0 : ImageSize());
214 0 : WritableFontDataPtr slice;
215 0 : slice.Attach(down_cast<WritableFontData*>(new_data->Slice(size)));
216 0 : size += BigMetrics()->SubSerialize(slice);
217 0 : size += new_data->WriteULong(size, glyph_array_.size());
218 0 : for (IntegerList::iterator b = glyph_array_.begin(), e = glyph_array_.end();
219 : b != e; b++) {
220 0 : size += new_data->WriteUShort(size, *b);
221 : }
222 : }
223 0 : return size;
224 : }
225 :
226 0 : int32_t IndexSubTableFormat5::Builder::ImageSize() {
227 0 : return InternalReadData()->ReadULongAsInt(
228 0 : EblcTable::Offset::kIndexSubTable5_imageSize);
229 : }
230 :
231 0 : void IndexSubTableFormat5::Builder::SetImageSize(int32_t image_size) {
232 0 : InternalWriteData()->WriteULong(
233 0 : EblcTable::Offset::kIndexSubTable5_imageSize, image_size);
234 0 : }
235 :
236 0 : BigGlyphMetrics::Builder* IndexSubTableFormat5::Builder::BigMetrics() {
237 0 : if (metrics_ == NULL) {
238 0 : WritableFontDataPtr data;
239 0 : data.Attach(down_cast<WritableFontData*>(InternalWriteData()->Slice(
240 : EblcTable::Offset::kIndexSubTable5_bigGlyphMetrics,
241 0 : BigGlyphMetrics::Offset::kMetricsLength)));
242 0 : metrics_ = new BigGlyphMetrics::Builder(data);
243 0 : set_model_changed();
244 : }
245 0 : return metrics_;
246 : }
247 :
248 0 : IntegerList* IndexSubTableFormat5::Builder::GlyphArray() {
249 0 : return GetGlyphArray();
250 : }
251 :
252 0 : void IndexSubTableFormat5::Builder::SetGlyphArray(const IntegerList& v) {
253 0 : glyph_array_.clear();
254 0 : glyph_array_ = v;
255 0 : set_model_changed();
256 0 : }
257 :
258 0 : void IndexSubTableFormat5::Builder::Revert() {
259 0 : glyph_array_.clear();
260 0 : IndexSubTable::Builder::Revert();
261 0 : }
262 :
263 0 : IndexSubTableFormat5::Builder::Builder()
264 : : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable5_builderDataSize,
265 0 : IndexSubTable::Format::FORMAT_5) {
266 0 : }
267 :
268 0 : IndexSubTableFormat5::Builder::Builder(WritableFontData* data,
269 : int32_t first_glyph_index,
270 0 : int32_t last_glyph_index)
271 0 : : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
272 0 : }
273 :
274 0 : IndexSubTableFormat5::Builder::Builder(ReadableFontData* data,
275 : int32_t first_glyph_index,
276 0 : int32_t last_glyph_index)
277 0 : : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
278 0 : }
279 :
280 0 : IntegerList* IndexSubTableFormat5::Builder::GetGlyphArray() {
281 0 : if (glyph_array_.empty()) {
282 0 : Initialize(InternalReadData());
283 0 : set_model_changed();
284 : }
285 0 : return &glyph_array_;
286 : }
287 :
288 0 : void IndexSubTableFormat5::Builder::Initialize(ReadableFontData* data) {
289 0 : glyph_array_.clear();
290 0 : if (data) {
291 0 : int32_t num_glyphs = IndexSubTableFormat5::NumGlyphs(data, 0);
292 0 : for (int32_t i = 0; i < num_glyphs; ++i) {
293 0 : glyph_array_.push_back(data->ReadUShort(
294 0 : EblcTable::Offset::kIndexSubTable5_glyphArray +
295 0 : i * DataSize::kUSHORT));
296 : }
297 : }
298 0 : }
299 :
300 : // static
301 0 : int32_t IndexSubTableFormat5::Builder::DataLength(
302 : ReadableFontData* data,
303 : int32_t index_sub_table_offset,
304 : int32_t first_glyph_index,
305 : int32_t last_glyph_index) {
306 : int32_t num_glyphs = IndexSubTableFormat5::NumGlyphs(data,
307 0 : index_sub_table_offset);
308 : UNREFERENCED_PARAMETER(first_glyph_index);
309 : UNREFERENCED_PARAMETER(last_glyph_index);
310 0 : return EblcTable::Offset::kIndexSubTable5_glyphArray +
311 0 : num_glyphs * DataSize::kUSHORT;
312 : }
313 :
314 : /******************************************************************************
315 : * IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator class
316 : ******************************************************************************/
317 0 : IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
318 0 : IndexSubTableFormat5::Builder* container)
319 : : RefIterator<BitmapGlyphInfo, IndexSubTableFormat5::Builder,
320 : IndexSubTable::Builder>(container),
321 0 : offset_index_(0) {
322 0 : }
323 :
324 0 : bool IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator::HasNext() {
325 0 : if (offset_index_ < (int32_t)(container()->GetGlyphArray()->size())) {
326 0 : return true;
327 : }
328 0 : return false;
329 : }
330 :
331 : CALLER_ATTACH BitmapGlyphInfo*
332 0 : IndexSubTableFormat5::Builder::BitmapGlyphInfoIterator::Next() {
333 0 : BitmapGlyphInfoPtr output;
334 0 : if (!HasNext()) {
335 : // Note: In C++, we do not throw exception when there's no element.
336 0 : return NULL;
337 : }
338 0 : output = new BitmapGlyphInfo(container()->GetGlyphArray()->at(offset_index_),
339 0 : container()->image_data_offset(),
340 0 : offset_index_ * container()->ImageSize(),
341 0 : container()->ImageSize(),
342 0 : container()->image_format());
343 0 : offset_index_++;
344 0 : return output.Detach();
345 : }
346 :
347 : } // namespace sfntly
|