Home | History | Annotate | Download | only in truetype
      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