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 (type == GlyphType::kSimple) { 219 glyph = new SimpleGlyph(sliced_data); 220 } else { 221 glyph = new CompositeGlyph(sliced_data); 222 } 223 return glyph.Detach(); 224 } 225 226 int32_t GlyphTable::Glyph::Padding() { 227 Initialize(); 228 return SubTable::Padding(); 229 } 230 231 int32_t GlyphTable::Glyph::GlyphType() { 232 return glyph_type_; 233 } 234 235 int32_t GlyphTable::Glyph::NumberOfContours() { 236 return number_of_contours_; 237 } 238 239 int32_t GlyphTable::Glyph::XMin() { 240 return data_->ReadShort(Offset::kXMin); 241 } 242 243 int32_t GlyphTable::Glyph::XMax() { 244 return data_->ReadShort(Offset::kXMax); 245 } 246 247 int32_t GlyphTable::Glyph::YMin() { 248 return data_->ReadShort(Offset::kYMin); 249 } 250 251 int32_t GlyphTable::Glyph::YMax() { 252 return data_->ReadShort(Offset::kYMax); 253 } 254 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 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 ******************************************************************************/ 282 GlyphTable::Glyph::Builder::~Builder() { 283 } 284 285 GlyphTable::Glyph::Builder::Builder(WritableFontData* data) 286 : SubTable::Builder(data) { 287 } 288 289 GlyphTable::Glyph::Builder::Builder(ReadableFontData* data) 290 : SubTable::Builder(data) { 291 } 292 293 CALLER_ATTACH GlyphTable::Glyph::Builder* 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* 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 319 void GlyphTable::Glyph::Builder::SubDataSet() { 320 // NOP 321 } 322 323 int32_t GlyphTable::Glyph::Builder::SubDataSizeToSerialize() { 324 return InternalReadData()->Length(); 325 } 326 327 bool GlyphTable::Glyph::Builder::SubReadyToSerialize() { 328 return true; 329 } 330 331 int32_t GlyphTable::Glyph::Builder::SubSerialize(WritableFontData* new_data) { 332 return InternalReadData()->CopyTo(new_data); 333 } 334 335 /****************************************************************************** 336 * GlyphTable::SimpleGlyph 337 ******************************************************************************/ 338 GlyphTable::SimpleGlyph::SimpleGlyph(ReadableFontData* data) 339 : GlyphTable::Glyph(data, GlyphType::kSimple), initialized_(false) { 340 } 341 342 GlyphTable::SimpleGlyph::~SimpleGlyph() { 343 } 344 345 int32_t GlyphTable::SimpleGlyph::InstructionSize() { 346 Initialize(); 347 return instruction_size_; 348 } 349 350 CALLER_ATTACH ReadableFontData* GlyphTable::SimpleGlyph::Instructions() { 351 Initialize(); 352 return down_cast<ReadableFontData*>( 353 data_->Slice(instructions_offset_, InstructionSize())); 354 } 355 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 364 int32_t GlyphTable::SimpleGlyph::XCoordinate(int32_t contour, int32_t point) { 365 Initialize(); 366 return x_coordinates_[contour_index_[contour] + point]; 367 } 368 369 int32_t GlyphTable::SimpleGlyph::YCoordinate(int32_t contour, int32_t point) { 370 Initialize(); 371 return y_coordinates_[contour_index_[contour] + point]; 372 } 373 374 bool GlyphTable::SimpleGlyph::OnCurve(int32_t contour, int32_t point) { 375 Initialize(); 376 return on_curve_[contour_index_[contour] + point]; 377 } 378 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 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 500 int32_t GlyphTable::SimpleGlyph::FlagAsInt(int32_t index) { 501 return data_->ReadUByte(flags_offset_ + index * DataSize::kBYTE); 502 } 503 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 ******************************************************************************/ 512 GlyphTable::SimpleGlyph::SimpleGlyphBuilder::~SimpleGlyphBuilder() { 513 } 514 515 GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( 516 WritableFontData* data) 517 : Glyph::Builder(data) { 518 } 519 520 GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder( 521 ReadableFontData* data) 522 : Glyph::Builder(data) { 523 } 524 525 CALLER_ATTACH FontDataTable* 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 ******************************************************************************/ 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 543 GlyphTable::CompositeGlyph::~CompositeGlyph() { 544 } 545 546 int32_t GlyphTable::CompositeGlyph::Flags(int32_t contour) { 547 return data_->ReadUShort(contour_index_[contour]); 548 } 549 550 int32_t GlyphTable::CompositeGlyph::NumGlyphs() { 551 return contour_index_.size(); 552 } 553 554 int32_t GlyphTable::CompositeGlyph::GlyphIndex(int32_t contour) { 555 return data_->ReadUShort(DataSize::kUSHORT + contour_index_[contour]); 556 } 557 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 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 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 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 607 int32_t GlyphTable::CompositeGlyph::InstructionSize() { 608 return instruction_size_; 609 } 610 611 CALLER_ATTACH ReadableFontData* GlyphTable::CompositeGlyph::Instructions() { 612 return down_cast<ReadableFontData*>( 613 data_->Slice(instructions_offset_, InstructionSize())); 614 } 615 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 ******************************************************************************/ 659 GlyphTable::CompositeGlyph::CompositeGlyphBuilder::~CompositeGlyphBuilder() { 660 } 661 662 GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( 663 WritableFontData* data) 664 : Glyph::Builder(data) { 665 } 666 667 GlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder( 668 ReadableFontData* data) 669 : Glyph::Builder(data) { 670 } 671 672 CALLER_ATTACH FontDataTable* 673 GlyphTable::CompositeGlyph::CompositeGlyphBuilder::SubBuildTable( 674 ReadableFontData* data) { 675 FontDataTablePtr table = new CompositeGlyph(data); 676 return table.Detach(); 677 } 678 679 } // namespace sfntly 680