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