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