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/truetype/glyph_table.h"
18 :
19 : #include <stdlib.h>
20 :
21 : #include "sfntly/port/exception_type.h"
22 :
23 : namespace sfntly {
24 : /******************************************************************************
25 : * Constants
26 : ******************************************************************************/
27 : const int32_t GlyphTable::SimpleGlyph::kFLAG_ONCURVE = 1;
28 : const int32_t GlyphTable::SimpleGlyph::kFLAG_XSHORT = 1 << 1;
29 : const int32_t GlyphTable::SimpleGlyph::kFLAG_YSHORT = 1 << 2;
30 : const int32_t GlyphTable::SimpleGlyph::kFLAG_REPEAT = 1 << 3;
31 : const int32_t GlyphTable::SimpleGlyph::kFLAG_XREPEATSIGN = 1 << 4;
32 : const int32_t GlyphTable::SimpleGlyph::kFLAG_YREPEATSIGN = 1 << 5;
33 :
34 : const int32_t GlyphTable::CompositeGlyph::kFLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0;
35 : const int32_t GlyphTable::CompositeGlyph::kFLAG_ARGS_ARE_XY_VALUES = 1 << 1;
36 : const int32_t GlyphTable::CompositeGlyph::kFLAG_ROUND_XY_TO_GRID = 1 << 2;
37 : const int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_A_SCALE = 1 << 3;
38 : const int32_t GlyphTable::CompositeGlyph::kFLAG_RESERVED = 1 << 4;
39 : const int32_t GlyphTable::CompositeGlyph::kFLAG_MORE_COMPONENTS = 1 << 5;
40 : const int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6;
41 : const int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7;
42 : const int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_INSTRUCTIONS = 1 << 8;
43 : const int32_t GlyphTable::CompositeGlyph::kFLAG_USE_MY_METRICS = 1 << 9;
44 : const int32_t GlyphTable::CompositeGlyph::kFLAG_OVERLAP_COMPOUND = 1 << 10;
45 : const int32_t GlyphTable::CompositeGlyph::kFLAG_SCALED_COMPONENT_OFFSET = 1 << 11;
46 : const int32_t GlyphTable::CompositeGlyph::kFLAG_UNSCALED_COMPONENT_OFFSET = 1 << 12;
47 :
48 : /******************************************************************************
49 : * GlyphTable class
50 : ******************************************************************************/
51 0 : GlyphTable::~GlyphTable() {
52 0 : }
53 :
54 0 : GlyphTable::Glyph* GlyphTable::GetGlyph(int32_t offset, int32_t length) {
55 0 : return GlyphTable::Glyph::GetGlyph(this, this->data_, offset, length);
56 : }
57 :
58 0 : GlyphTable::GlyphTable(Header* header, ReadableFontData* data)
59 0 : : SubTableContainerTable(header, data) {
60 0 : }
61 :
62 : /******************************************************************************
63 : * GlyphTable::Builder class
64 : ******************************************************************************/
65 0 : GlyphTable::Builder::Builder(Header* header, ReadableFontData* data)
66 0 : : SubTableContainerTable::Builder(header, data) {
67 0 : }
68 :
69 0 : GlyphTable::Builder::~Builder() {
70 0 : }
71 :
72 0 : void GlyphTable::Builder::SetLoca(const IntegerList& loca) {
73 0 : loca_ = loca;
74 0 : set_model_changed(false);
75 0 : glyph_builders_.clear();
76 0 : }
77 :
78 0 : void GlyphTable::Builder::GenerateLocaList(IntegerList* locas) {
79 0 : assert(locas);
80 0 : GlyphBuilderList* glyph_builders = GetGlyphBuilders();
81 0 : locas->push_back(0);
82 0 : if (glyph_builders->size() == 0) {
83 0 : locas->push_back(0);
84 : } else {
85 0 : int32_t total = 0;
86 0 : for (GlyphBuilderList::iterator b = glyph_builders->begin(),
87 0 : b_end = glyph_builders->end();
88 : b != b_end; ++b) {
89 0 : int32_t size = (*b)->SubDataSizeToSerialize();
90 0 : locas->push_back(total + size);
91 0 : total += size;
92 : }
93 : }
94 0 : }
95 :
96 : CALLER_ATTACH GlyphTable::Builder*
97 0 : GlyphTable::Builder::CreateBuilder(Header* header, WritableFontData* data) {
98 0 : Ptr<GlyphTable::Builder> builder;
99 0 : builder = new GlyphTable::Builder(header, data);
100 0 : return builder.Detach();
101 : }
102 :
103 0 : GlyphTable::GlyphBuilderList* GlyphTable::Builder::GlyphBuilders() {
104 0 : return GetGlyphBuilders();
105 : }
106 :
107 0 : void GlyphTable::Builder::SetGlyphBuilders(GlyphBuilderList* glyph_builders) {
108 0 : glyph_builders_ = *glyph_builders;
109 0 : set_model_changed();
110 0 : }
111 :
112 : CALLER_ATTACH GlyphTable::Glyph::Builder*
113 0 : GlyphTable::Builder::GlyphBuilder(ReadableFontData* data) {
114 0 : return Glyph::Builder::GetBuilder(this, data);
115 : }
116 :
117 : CALLER_ATTACH FontDataTable*
118 0 : GlyphTable::Builder::SubBuildTable(ReadableFontData* data) {
119 0 : FontDataTablePtr table = new GlyphTable(header(), data);
120 0 : return table.Detach();
121 : }
122 :
123 0 : void GlyphTable::Builder::SubDataSet() {
124 0 : glyph_builders_.clear();
125 0 : set_model_changed(false);
126 0 : }
127 :
128 0 : int32_t GlyphTable::Builder::SubDataSizeToSerialize() {
129 0 : if (glyph_builders_.empty())
130 0 : return 0;
131 :
132 0 : bool variable = false;
133 0 : int32_t size = 0;
134 :
135 : // Calculate size of each table.
136 0 : for (GlyphBuilderList::iterator b = glyph_builders_.begin(),
137 0 : end = glyph_builders_.end(); b != end; ++b) {
138 0 : int32_t glyph_size = (*b)->SubDataSizeToSerialize();
139 0 : size += abs(glyph_size);
140 0 : variable |= glyph_size <= 0;
141 : }
142 0 : return variable ? -size : size;
143 : }
144 :
145 0 : bool GlyphTable::Builder::SubReadyToSerialize() {
146 0 : return !glyph_builders_.empty();
147 : }
148 :
149 0 : int32_t GlyphTable::Builder::SubSerialize(WritableFontData* new_data) {
150 0 : int32_t size = 0;
151 0 : for (GlyphBuilderList::iterator b = glyph_builders_.begin(),
152 0 : end = glyph_builders_.end(); b != end; ++b) {
153 0 : FontDataPtr data;
154 0 : data.Attach(new_data->Slice(size));
155 0 : size += (*b)->SubSerialize(down_cast<WritableFontData*>(data.p_));
156 : }
157 0 : return size;
158 : }
159 :
160 0 : void GlyphTable::Builder::Initialize(ReadableFontData* data,
161 : const IntegerList& loca) {
162 0 : if (data != NULL) {
163 0 : if (loca_.empty()) {
164 0 : return;
165 : }
166 : int32_t loca_value;
167 0 : int32_t last_loca_value = loca[0];
168 0 : for (size_t i = 1; i < loca.size(); ++i) {
169 0 : loca_value = loca[i];
170 0 : GlyphBuilderPtr builder;
171 0 : builder.Attach(
172 : Glyph::Builder::GetBuilder(this,
173 : data,
174 : last_loca_value /*offset*/,
175 0 : loca_value - last_loca_value /*length*/));
176 0 : glyph_builders_.push_back(builder);
177 0 : last_loca_value = loca_value;
178 : }
179 : }
180 : }
181 :
182 0 : GlyphTable::GlyphBuilderList* GlyphTable::Builder::GetGlyphBuilders() {
183 0 : if (glyph_builders_.empty()) {
184 0 : if (InternalReadData() && !loca_.empty()) {
185 : #if !defined (SFNTLY_NO_EXCEPTION)
186 : throw IllegalStateException(
187 : "Loca values not set - unable to parse glyph data.");
188 : #endif
189 0 : return NULL;
190 : }
191 0 : Initialize(InternalReadData(), loca_);
192 0 : set_model_changed();
193 : }
194 0 : return &glyph_builders_;
195 : }
196 :
197 0 : void GlyphTable::Builder::Revert() {
198 0 : glyph_builders_.clear();
199 0 : set_model_changed(false);
200 0 : }
201 :
202 : /******************************************************************************
203 : * GlyphTable::Glyph class
204 : ******************************************************************************/
205 0 : GlyphTable::Glyph::~Glyph() {}
206 :
207 : CALLER_ATTACH GlyphTable::Glyph*
208 0 : GlyphTable::Glyph::GetGlyph(GlyphTable* table,
209 : ReadableFontData* data,
210 : int32_t offset,
211 : int32_t length) {
212 : UNREFERENCED_PARAMETER(table);
213 0 : int32_t type = GlyphType(data, offset, length);
214 0 : GlyphPtr glyph;
215 :
216 0 : ReadableFontDataPtr sliced_data;
217 0 : sliced_data.Attach(down_cast<ReadableFontData*>(data->Slice(offset, length)));
218 0 : if (sliced_data) {
219 0 : if (type == GlyphType::kSimple)
220 0 : glyph = new SimpleGlyph(sliced_data);
221 : else
222 0 : glyph = new CompositeGlyph(sliced_data);
223 : }
224 0 : return glyph.Detach();
225 : }
226 :
227 0 : int32_t GlyphTable::Glyph::Padding() {
228 0 : Initialize();
229 0 : return SubTable::Padding();
230 : }
231 :
232 0 : int32_t GlyphTable::Glyph::GlyphType() {
233 0 : return glyph_type_;
234 : }
235 :
236 0 : int32_t GlyphTable::Glyph::NumberOfContours() {
237 0 : return number_of_contours_;
238 : }
239 :
240 0 : int32_t GlyphTable::Glyph::XMin() {
241 0 : return data_->ReadShort(Offset::kXMin);
242 : }
243 :
244 0 : int32_t GlyphTable::Glyph::XMax() {
245 0 : return data_->ReadShort(Offset::kXMax);
246 : }
247 :
248 0 : int32_t GlyphTable::Glyph::YMin() {
249 0 : return data_->ReadShort(Offset::kYMin);
250 : }
251 :
252 0 : int32_t GlyphTable::Glyph::YMax() {
253 0 : return data_->ReadShort(Offset::kYMax);
254 : }
255 :
256 0 : GlyphTable::Glyph::Glyph(ReadableFontData* data, int32_t glyph_type)
257 : : SubTable(data),
258 0 : glyph_type_(glyph_type) {
259 0 : if (data_->Length() == 0) {
260 0 : number_of_contours_ = 0;
261 : } else {
262 : // -1 if composite
263 0 : number_of_contours_ = data_->ReadShort(Offset::kNumberOfContours);
264 : }
265 0 : }
266 :
267 0 : int32_t GlyphTable::Glyph::GlyphType(ReadableFontData* data,
268 : int32_t offset,
269 : int32_t length) {
270 0 : if (length == 0) {
271 0 : return GlyphType::kSimple;
272 : }
273 0 : int32_t number_of_contours = data->ReadShort(offset);
274 0 : if (number_of_contours >= 0) {
275 0 : return GlyphType::kSimple;
276 : }
277 0 : return GlyphType::kComposite;
278 : }
279 :
280 : /******************************************************************************
281 : * GlyphTable::Glyph::Builder class
282 : ******************************************************************************/
283 0 : GlyphTable::Glyph::Builder::~Builder() {
284 0 : }
285 :
286 0 : GlyphTable::Glyph::Builder::Builder(WritableFontData* data)
287 0 : : SubTable::Builder(data) {
288 0 : }
289 :
290 0 : GlyphTable::Glyph::Builder::Builder(ReadableFontData* data)
291 0 : : SubTable::Builder(data) {
292 0 : }
293 :
294 : CALLER_ATTACH GlyphTable::Glyph::Builder*
295 0 : GlyphTable::Glyph::Builder::GetBuilder(
296 : GlyphTable::Builder* table_builder,
297 : ReadableFontData* data) {
298 0 : return GetBuilder(table_builder, data, 0, data->Length());
299 : }
300 :
301 : CALLER_ATTACH GlyphTable::Glyph::Builder*
302 0 : GlyphTable::Glyph::Builder::GetBuilder(
303 : GlyphTable::Builder* table_builder,
304 : ReadableFontData* data,
305 : int32_t offset,
306 : int32_t length) {
307 : UNREFERENCED_PARAMETER(table_builder);
308 0 : int32_t type = Glyph::GlyphType(data, offset, length);
309 0 : GlyphBuilderPtr builder;
310 0 : ReadableFontDataPtr sliced_data;
311 0 : sliced_data.Attach(down_cast<ReadableFontData*>(data->Slice(offset, length)));
312 0 : if (type == GlyphType::kSimple) {
313 0 : builder = new SimpleGlyph::SimpleGlyphBuilder(sliced_data);
314 : } else {
315 0 : builder = new CompositeGlyph::CompositeGlyphBuilder(sliced_data);
316 : }
317 0 : return builder.Detach();
318 : }
319 :
320 0 : void GlyphTable::Glyph::Builder::SubDataSet() {
321 : // NOP
322 0 : }
323 :
324 0 : int32_t GlyphTable::Glyph::Builder::SubDataSizeToSerialize() {
325 0 : return InternalReadData()->Length();
326 : }
327 :
328 0 : bool GlyphTable::Glyph::Builder::SubReadyToSerialize() {
329 0 : return true;
330 : }
331 :
332 0 : int32_t GlyphTable::Glyph::Builder::SubSerialize(WritableFontData* new_data) {
333 0 : return InternalReadData()->CopyTo(new_data);
334 : }
335 :
336 : /******************************************************************************
337 : * GlyphTable::SimpleGlyph
338 : ******************************************************************************/
339 0 : GlyphTable::SimpleGlyph::SimpleGlyph(ReadableFontData* data)
340 0 : : GlyphTable::Glyph(data, GlyphType::kSimple), initialized_(false) {
341 0 : }
342 :
343 0 : GlyphTable::SimpleGlyph::~SimpleGlyph() {
344 0 : }
345 :
346 0 : int32_t GlyphTable::SimpleGlyph::InstructionSize() {
347 0 : Initialize();
348 0 : return instruction_size_;
349 : }
350 :
351 0 : CALLER_ATTACH ReadableFontData* GlyphTable::SimpleGlyph::Instructions() {
352 0 : Initialize();
353 0 : return down_cast<ReadableFontData*>(
354 0 : data_->Slice(instructions_offset_, InstructionSize()));
355 : }
356 :
357 0 : int32_t GlyphTable::SimpleGlyph::NumberOfPoints(int32_t contour) {
358 0 : Initialize();
359 0 : if (contour >= NumberOfContours()) {
360 0 : return 0;
361 : }
362 0 : return contour_index_[contour + 1] - contour_index_[contour];
363 : }
364 :
365 0 : int32_t GlyphTable::SimpleGlyph::XCoordinate(int32_t contour, int32_t point) {
366 0 : Initialize();
367 0 : return x_coordinates_[contour_index_[contour] + point];
368 : }
369 :
370 0 : int32_t GlyphTable::SimpleGlyph::YCoordinate(int32_t contour, int32_t point) {
371 0 : Initialize();
372 0 : return y_coordinates_[contour_index_[contour] + point];
373 : }
374 :
375 0 : bool GlyphTable::SimpleGlyph::OnCurve(int32_t contour, int32_t point) {
376 0 : Initialize();
377 0 : return on_curve_[contour_index_[contour] + point];
378 : }
379 :
380 0 : void GlyphTable::SimpleGlyph::Initialize() {
381 0 : AutoLock lock(initialization_lock_);
382 0 : if (initialized_) {
383 0 : return;
384 : }
385 :
386 0 : if (ReadFontData()->Length() == 0) {
387 0 : instruction_size_ = 0;
388 0 : number_of_points_ = 0;
389 0 : instructions_offset_ = 0;
390 0 : flags_offset_ = 0;
391 0 : x_coordinates_offset_ = 0;
392 0 : y_coordinates_offset_ = 0;
393 0 : return;
394 : }
395 :
396 0 : instruction_size_ = data_->ReadUShort(Offset::kSimpleEndPtsOfCountours +
397 0 : NumberOfContours() * DataSize::kUSHORT);
398 0 : instructions_offset_ = Offset::kSimpleEndPtsOfCountours +
399 0 : (NumberOfContours() + 1) * DataSize::kUSHORT;
400 0 : flags_offset_ = instructions_offset_ + instruction_size_ * DataSize::kBYTE;
401 0 : number_of_points_ = ContourEndPoint(NumberOfContours() - 1) + 1;
402 0 : x_coordinates_.resize(number_of_points_);
403 0 : y_coordinates_.resize(number_of_points_);
404 0 : on_curve_.resize(number_of_points_);
405 0 : ParseData(false);
406 0 : x_coordinates_offset_ = flags_offset_ + flag_byte_count_ * DataSize::kBYTE;
407 0 : y_coordinates_offset_ = x_coordinates_offset_ + x_byte_count_ *
408 : DataSize::kBYTE;
409 0 : contour_index_.resize(NumberOfContours() + 1);
410 0 : contour_index_[0] = 0;
411 0 : for (uint32_t contour = 0; contour < contour_index_.size() - 1; ++contour) {
412 0 : contour_index_[contour + 1] = ContourEndPoint(contour) + 1;
413 : }
414 0 : ParseData(true);
415 : int32_t non_padded_data_length =
416 0 : 5 * DataSize::kSHORT +
417 0 : (NumberOfContours() * DataSize::kUSHORT) +
418 0 : DataSize::kUSHORT +
419 0 : (instruction_size_ * DataSize::kBYTE) +
420 0 : (flag_byte_count_ * DataSize::kBYTE) +
421 0 : (x_byte_count_ * DataSize::kBYTE) +
422 0 : (y_byte_count_ * DataSize::kBYTE);
423 0 : set_padding(DataLength() - non_padded_data_length);
424 0 : initialized_ = true;
425 : }
426 :
427 0 : void GlyphTable::SimpleGlyph::ParseData(bool fill_arrays) {
428 0 : int32_t flag = 0;
429 0 : int32_t flag_repeat = 0;
430 0 : int32_t flag_index = 0;
431 0 : int32_t x_byte_index = 0;
432 0 : int32_t y_byte_index = 0;
433 :
434 0 : for (int32_t point_index = 0; point_index < number_of_points_;
435 : ++point_index) {
436 : // get the flag for the current point
437 0 : if (flag_repeat == 0) {
438 0 : flag = FlagAsInt(flag_index++);
439 0 : if ((flag & kFLAG_REPEAT) == kFLAG_REPEAT) {
440 0 : flag_repeat = FlagAsInt(flag_index++);
441 : }
442 : } else {
443 0 : flag_repeat--;
444 : }
445 :
446 : // on the curve?
447 0 : if (fill_arrays) {
448 0 : on_curve_[point_index] = ((flag & kFLAG_ONCURVE) == kFLAG_ONCURVE);
449 : }
450 : // get the x coordinate
451 0 : if ((flag & kFLAG_XSHORT) == kFLAG_XSHORT) {
452 : // single byte x coord value
453 0 : if (fill_arrays) {
454 0 : x_coordinates_[point_index] =
455 0 : data_->ReadUByte(x_coordinates_offset_ + x_byte_index);
456 0 : x_coordinates_[point_index] *=
457 0 : ((flag & kFLAG_XREPEATSIGN) == kFLAG_XREPEATSIGN) ? 1 : -1;
458 : }
459 0 : x_byte_index++;
460 : } else {
461 : // double byte coord value
462 0 : if (!((flag & kFLAG_XREPEATSIGN) == kFLAG_XREPEATSIGN)) {
463 0 : if (fill_arrays) {
464 0 : x_coordinates_[point_index] =
465 0 : data_->ReadShort(x_coordinates_offset_ + x_byte_index);
466 : }
467 0 : x_byte_index += 2;
468 : }
469 : }
470 0 : if (fill_arrays && point_index > 0) {
471 0 : x_coordinates_[point_index] += x_coordinates_[point_index - 1];
472 : }
473 :
474 : // get the y coordinate
475 0 : if ((flag & kFLAG_YSHORT) == kFLAG_YSHORT) {
476 0 : if (fill_arrays) {
477 0 : y_coordinates_[point_index] =
478 0 : data_->ReadUByte(y_coordinates_offset_ + y_byte_index);
479 0 : y_coordinates_[point_index] *=
480 0 : ((flag & kFLAG_YREPEATSIGN) == kFLAG_YREPEATSIGN) ? 1 : -1;
481 : }
482 0 : y_byte_index++;
483 : } else {
484 0 : if (!((flag & kFLAG_YREPEATSIGN) == kFLAG_YREPEATSIGN)) {
485 0 : if (fill_arrays) {
486 0 : y_coordinates_[point_index] =
487 0 : data_->ReadShort(y_coordinates_offset_ + y_byte_index);
488 : }
489 0 : y_byte_index += 2;
490 : }
491 : }
492 0 : if (fill_arrays && point_index > 0) {
493 0 : y_coordinates_[point_index] += y_coordinates_[point_index - 1];
494 : }
495 : }
496 0 : flag_byte_count_ = flag_index;
497 0 : x_byte_count_ = x_byte_index;
498 0 : y_byte_count_ = y_byte_index;
499 0 : }
500 :
501 0 : int32_t GlyphTable::SimpleGlyph::FlagAsInt(int32_t index) {
502 0 : return data_->ReadUByte(flags_offset_ + index * DataSize::kBYTE);
503 : }
504 :
505 0 : int32_t GlyphTable::SimpleGlyph::ContourEndPoint(int32_t contour) {
506 0 : return data_->ReadUShort(contour * DataSize::kUSHORT +
507 0 : Offset::kSimpleEndPtsOfCountours);
508 : }
509 :
510 : /******************************************************************************
511 : * GlyphTable::SimpleGlyph::Builder
512 : ******************************************************************************/
513 0 : GlyphTable::SimpleGlyph::SimpleGlyphBuilder::~SimpleGlyphBuilder() {
514 0 : }
515 :
516 0 : GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder(
517 0 : WritableFontData* data)
518 0 : : Glyph::Builder(data) {
519 0 : }
520 :
521 0 : GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder(
522 0 : ReadableFontData* data)
523 0 : : Glyph::Builder(data) {
524 0 : }
525 :
526 : CALLER_ATTACH FontDataTable*
527 0 : GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SubBuildTable(
528 : ReadableFontData* data) {
529 0 : FontDataTablePtr table = new SimpleGlyph(data);
530 0 : return table.Detach();
531 : }
532 :
533 : /******************************************************************************
534 : * GlyphTable::CompositeGlyph
535 : ******************************************************************************/
536 0 : GlyphTable::CompositeGlyph::CompositeGlyph(ReadableFontData* data)
537 : : GlyphTable::Glyph(data, GlyphType::kComposite),
538 : instruction_size_(0),
539 : instructions_offset_(0),
540 0 : initialized_(false) {
541 0 : Initialize();
542 0 : }
543 :
544 0 : GlyphTable::CompositeGlyph::~CompositeGlyph() {
545 0 : }
546 :
547 0 : int32_t GlyphTable::CompositeGlyph::Flags(int32_t contour) {
548 0 : return data_->ReadUShort(contour_index_[contour]);
549 : }
550 :
551 0 : int32_t GlyphTable::CompositeGlyph::NumGlyphs() {
552 0 : return contour_index_.size();
553 : }
554 :
555 0 : int32_t GlyphTable::CompositeGlyph::GlyphIndex(int32_t contour) {
556 0 : return data_->ReadUShort(DataSize::kUSHORT + contour_index_[contour]);
557 : }
558 :
559 0 : int32_t GlyphTable::CompositeGlyph::Argument1(int32_t contour) {
560 0 : int32_t index = 2 * DataSize::kUSHORT + contour_index_[contour];
561 0 : int32_t contour_flags = Flags(contour);
562 0 : if ((contour_flags & kFLAG_ARG_1_AND_2_ARE_WORDS) ==
563 : kFLAG_ARG_1_AND_2_ARE_WORDS) {
564 0 : return data_->ReadUShort(index);
565 : }
566 0 : return data_->ReadByte(index);
567 : }
568 :
569 0 : int32_t GlyphTable::CompositeGlyph::Argument2(int32_t contour) {
570 0 : int32_t index = 2 * DataSize::kUSHORT + contour_index_[contour];
571 0 : int32_t contour_flags = Flags(contour);
572 0 : if ((contour_flags & kFLAG_ARG_1_AND_2_ARE_WORDS) ==
573 : kFLAG_ARG_1_AND_2_ARE_WORDS) {
574 0 : return data_->ReadUShort(index + DataSize::kUSHORT);
575 : }
576 0 : return data_->ReadByte(index + DataSize::kUSHORT);
577 : }
578 :
579 0 : int32_t GlyphTable::CompositeGlyph::TransformationSize(int32_t contour) {
580 0 : int32_t contour_flags = Flags(contour);
581 0 : if ((contour_flags & kFLAG_WE_HAVE_A_SCALE) == kFLAG_WE_HAVE_A_SCALE) {
582 0 : return DataSize::kF2DOT14;
583 0 : } else if ((contour_flags & kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) ==
584 : kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) {
585 0 : return 2 * DataSize::kF2DOT14;
586 0 : } else if ((contour_flags & kFLAG_WE_HAVE_A_TWO_BY_TWO) ==
587 : kFLAG_WE_HAVE_A_TWO_BY_TWO) {
588 0 : return 4 * DataSize::kF2DOT14;
589 : }
590 0 : return 0;
591 : }
592 :
593 0 : void GlyphTable::CompositeGlyph::Transformation(int32_t contour,
594 : ByteVector* transformation) {
595 0 : int32_t contour_flags = Flags(contour);
596 0 : int32_t index = contour_index_[contour] + 2 * DataSize::kUSHORT;
597 0 : if ((contour_flags & kFLAG_ARG_1_AND_2_ARE_WORDS) ==
598 : kFLAG_ARG_1_AND_2_ARE_WORDS) {
599 0 : index += 2 * DataSize::kSHORT;
600 : } else {
601 0 : index += 2 * DataSize::kBYTE;
602 : }
603 0 : int32_t tsize = TransformationSize(contour);
604 0 : transformation->resize(tsize);
605 0 : data_->ReadBytes(index, &((*transformation)[0]), 0, tsize);
606 0 : }
607 :
608 0 : int32_t GlyphTable::CompositeGlyph::InstructionSize() {
609 0 : return instruction_size_;
610 : }
611 :
612 0 : CALLER_ATTACH ReadableFontData* GlyphTable::CompositeGlyph::Instructions() {
613 0 : return down_cast<ReadableFontData*>(
614 0 : data_->Slice(instructions_offset_, InstructionSize()));
615 : }
616 :
617 0 : void GlyphTable::CompositeGlyph::Initialize() {
618 0 : AutoLock lock(initialization_lock_);
619 0 : if (initialized_) {
620 0 : return;
621 : }
622 :
623 0 : int32_t index = 5 * DataSize::kUSHORT;
624 0 : int32_t flags = kFLAG_MORE_COMPONENTS;
625 :
626 0 : while ((flags & kFLAG_MORE_COMPONENTS) == kFLAG_MORE_COMPONENTS) {
627 0 : contour_index_.push_back(index);
628 0 : flags = data_->ReadUShort(index);
629 0 : index += 2 * DataSize::kUSHORT; // flags and glyphIndex
630 0 : if ((flags & kFLAG_ARG_1_AND_2_ARE_WORDS) == kFLAG_ARG_1_AND_2_ARE_WORDS) {
631 0 : index += 2 * DataSize::kSHORT;
632 : } else {
633 0 : index += 2 * DataSize::kBYTE;
634 : }
635 0 : if ((flags & kFLAG_WE_HAVE_A_SCALE) == kFLAG_WE_HAVE_A_SCALE) {
636 0 : index += DataSize::kF2DOT14;
637 0 : } else if ((flags & kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) ==
638 : kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) {
639 0 : index += 2 * DataSize::kF2DOT14;
640 0 : } else if ((flags & kFLAG_WE_HAVE_A_TWO_BY_TWO) ==
641 : kFLAG_WE_HAVE_A_TWO_BY_TWO) {
642 0 : index += 4 * DataSize::kF2DOT14;
643 : }
644 0 : int32_t non_padded_data_length = index;
645 0 : if ((flags & kFLAG_WE_HAVE_INSTRUCTIONS) == kFLAG_WE_HAVE_INSTRUCTIONS) {
646 0 : instruction_size_ = data_->ReadUShort(index);
647 0 : index += DataSize::kUSHORT;
648 0 : instructions_offset_ = index;
649 0 : non_padded_data_length = index + (instruction_size_ * DataSize::kBYTE);
650 : }
651 0 : set_padding(DataLength() - non_padded_data_length);
652 : }
653 :
654 0 : initialized_ = true;
655 : }
656 :
657 : /******************************************************************************
658 : * GlyphTable::CompositeGlyph::Builder
659 : ******************************************************************************/
660 0 : GlyphTable::CompositeGlyph::CompositeGlyphBuilder::~CompositeGlyphBuilder() {
661 0 : }
662 :
663 0 : GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder(
664 0 : WritableFontData* data)
665 0 : : Glyph::Builder(data) {
666 0 : }
667 :
668 0 : GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder(
669 0 : ReadableFontData* data)
670 0 : : Glyph::Builder(data) {
671 0 : }
672 :
673 : CALLER_ATTACH FontDataTable*
674 0 : GlyphTable::CompositeGlyph::CompositeGlyphBuilder::SubBuildTable(
675 : ReadableFontData* data) {
676 0 : FontDataTablePtr table = new CompositeGlyph(data);
677 0 : return table.Detach();
678 : }
679 :
680 : } // namespace sfntly
|