130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/*
230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Copyright 2011 Google Inc. All Rights Reserved.
330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Licensed under the Apache License, Version 2.0 (the "License");
530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * you may not use this file except in compliance with the License.
630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * You may obtain a copy of the License at
730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *      http://www.apache.org/licenses/LICENSE-2.0
930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun *
1030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Unless required by applicable law or agreed to in writing, software
1130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * distributed under the License is distributed on an "AS IS" BASIS,
1230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * See the License for the specific language governing permissions and
1430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * limitations under the License.
1530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun */
1630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
1730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/truetype/glyph_table.h"
1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <stdlib.h>
2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/exception_type.h"
2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace sfntly {
2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * Constants
2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::SimpleGlyph::kFLAG_ONCURVE = 1;
2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::SimpleGlyph::kFLAG_XSHORT = 1 << 1;
2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::SimpleGlyph::kFLAG_YSHORT = 1 << 2;
3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::SimpleGlyph::kFLAG_REPEAT = 1 << 3;
3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::SimpleGlyph::kFLAG_XREPEATSIGN = 1 << 4;
3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::SimpleGlyph::kFLAG_YREPEATSIGN = 1 << 5;
3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_ARG_1_AND_2_ARE_WORDS = 1 << 0;
3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_ARGS_ARE_XY_VALUES = 1 << 1;
3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_ROUND_XY_TO_GRID = 1 << 2;
3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_A_SCALE = 1 << 3;
3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_RESERVED = 1 << 4;
3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_MORE_COMPONENTS = 1 << 5;
4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_AN_X_AND_Y_SCALE = 1 << 6;
4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_A_TWO_BY_TWO = 1 << 7;
4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_WE_HAVE_INSTRUCTIONS = 1 << 8;
4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_USE_MY_METRICS = 1 << 9;
4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_OVERLAP_COMPOUND = 1 << 10;
4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_SCALED_COMPONENT_OFFSET = 1 << 11;
4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t GlyphTable::CompositeGlyph::kFLAG_UNSCALED_COMPONENT_OFFSET = 1 << 12;
4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * GlyphTable class
5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::~GlyphTable() {
5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::Glyph* GlyphTable::GetGlyph(int32_t offset, int32_t length) {
5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GlyphTable::Glyph::GetGlyph(this, this->data_, offset, length);
5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::GlyphTable(Header* header, ReadableFontData* data)
5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : SubTableContainerTable(header, data) {
6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * GlyphTable::Builder class
6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::Builder::Builder(Header* header, ReadableFontData* data)
6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : SubTableContainerTable::Builder(header, data) {
6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::Builder::~Builder() {
7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::Builder::SetLoca(const IntegerList& loca) {
7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  loca_ = loca;
7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_model_changed(false);
7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  glyph_builders_.clear();
7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::Builder::GenerateLocaList(IntegerList* locas) {
7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  assert(locas);
8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  GlyphBuilderList* glyph_builders = GetGlyphBuilders();
8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  locas->push_back(0);
8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (glyph_builders->size() == 0) {
8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    locas->push_back(0);
8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  } else {
8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t total = 0;
8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    for (GlyphBuilderList::iterator b = glyph_builders->begin(),
8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                    b_end = glyph_builders->end();
8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                    b != b_end; ++b) {
8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      int32_t size = (*b)->SubDataSizeToSerialize();
9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      locas->push_back(total + size);
9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      total += size;
9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH GlyphTable::Builder*
9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    GlyphTable::Builder::CreateBuilder(Header* header, WritableFontData* data) {
9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Ptr<GlyphTable::Builder> builder;
9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder = new GlyphTable::Builder(header, data);
10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder.Detach();
10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::GlyphBuilderList* GlyphTable::Builder::GlyphBuilders() {
10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GetGlyphBuilders();
10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::Builder::SetGlyphBuilders(GlyphBuilderList* glyph_builders) {
10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  glyph_builders_ = *glyph_builders;
10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_model_changed();
11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH GlyphTable::Glyph::Builder*
11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    GlyphTable::Builder::GlyphBuilder(ReadableFontData* data) {
11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Glyph::Builder::GetBuilder(this, data);
11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH FontDataTable*
11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    GlyphTable::Builder::SubBuildTable(ReadableFontData* data) {
11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontDataTablePtr table = new GlyphTable(header(), data);
12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return table.Detach();
12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::Builder::SubDataSet() {
12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  glyph_builders_.clear();
12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_model_changed(false);
12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Builder::SubDataSizeToSerialize() {
12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (glyph_builders_.empty())
13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
13230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  bool variable = false;
13330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t size = 0;
13430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
13530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // Calculate size of each table.
13630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (GlyphBuilderList::iterator b = glyph_builders_.begin(),
13730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  end = glyph_builders_.end(); b != end; ++b) {
13830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      int32_t glyph_size = (*b)->SubDataSizeToSerialize();
13930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      size += abs(glyph_size);
14030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      variable |= glyph_size <= 0;
14130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
14230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return variable ? -size : size;
14330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
14430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
14530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool GlyphTable::Builder::SubReadyToSerialize() {
14630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return !glyph_builders_.empty();
14730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
14830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
14930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Builder::SubSerialize(WritableFontData* new_data) {
15030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t size = 0;
15130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (GlyphBuilderList::iterator b = glyph_builders_.begin(),
15230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  end = glyph_builders_.end(); b != end; ++b) {
15330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FontDataPtr data;
15430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    data.Attach(new_data->Slice(size));
15530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    size += (*b)->SubSerialize(down_cast<WritableFontData*>(data.p_));
15630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
15730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return size;
15830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
15930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
16030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::Builder::Initialize(ReadableFontData* data,
16130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                     const IntegerList& loca) {
16230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (data != NULL) {
16330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (loca_.empty()) {
16430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return;
16530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
16630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t loca_value;
16730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t last_loca_value = loca[0];
16830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    for (size_t i = 1; i < loca.size(); ++i) {
16930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      loca_value = loca[i];
17030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      GlyphBuilderPtr builder;
17130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      builder.Attach(
17230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        Glyph::Builder::GetBuilder(this,
17330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                   data,
17430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                   last_loca_value /*offset*/,
17530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                   loca_value - last_loca_value /*length*/));
17630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      glyph_builders_.push_back(builder);
17730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      last_loca_value = loca_value;
17830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
17930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
18030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
18130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
18230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::GlyphBuilderList* GlyphTable::Builder::GetGlyphBuilders() {
18330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (glyph_builders_.empty()) {
18430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (InternalReadData() && !loca_.empty()) {
18530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
18630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      throw IllegalStateException(
18730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          "Loca values not set - unable to parse glyph data.");
18830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
18930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return NULL;
19030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
19130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    Initialize(InternalReadData(), loca_);
19230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    set_model_changed();
19330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
19430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return &glyph_builders_;
19530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
19630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
19730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::Builder::Revert() {
19830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  glyph_builders_.clear();
19930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_model_changed(false);
20030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
20130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
20230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
20330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * GlyphTable::Glyph class
20430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
20530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::Glyph::~Glyph() {}
20630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
20730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH GlyphTable::Glyph*
20830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    GlyphTable::Glyph::GetGlyph(GlyphTable* table,
20930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                ReadableFontData* data,
21030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                int32_t offset,
21130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                int32_t length) {
21230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(table);
21330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t type = GlyphType(data, offset, length);
21430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  GlyphPtr glyph;
21530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
21630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ReadableFontDataPtr sliced_data;
21730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  sliced_data.Attach(down_cast<ReadableFontData*>(data->Slice(offset, length)));
21830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (type == GlyphType::kSimple) {
21930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    glyph = new SimpleGlyph(sliced_data);
22030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  } else {
22130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    glyph = new CompositeGlyph(sliced_data);
22230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
22330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return glyph.Detach();
22430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
22530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
22630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Glyph::Padding() {
22730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Initialize();
22830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return SubTable::Padding();
22930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
23030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
23130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Glyph::GlyphType() {
23230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return glyph_type_;
23330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
23430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
23530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Glyph::NumberOfContours() {
23630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return number_of_contours_;
23730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
23830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
23930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Glyph::XMin() {
24030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadShort(Offset::kXMin);
24130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
24230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
24330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Glyph::XMax() {
24430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadShort(Offset::kXMax);
24530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
24630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
24730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Glyph::YMin() {
24830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadShort(Offset::kYMin);
24930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
25030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
25130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Glyph::YMax() {
25230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadShort(Offset::kYMax);
25330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
25430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
25530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::Glyph::Glyph(ReadableFontData* data, int32_t glyph_type)
25630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : SubTable(data),
25730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      glyph_type_(glyph_type) {
25830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (data_->Length() == 0) {
25930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    number_of_contours_ = 0;
26030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  } else {
26130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // -1 if composite
26230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    number_of_contours_ = data_->ReadShort(Offset::kNumberOfContours);
26330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
26430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
26530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
26630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Glyph::GlyphType(ReadableFontData* data,
26730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                     int32_t offset,
26830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                     int32_t length) {
26930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (length == 0) {
27030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return GlyphType::kSimple;
27130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
27230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t number_of_contours = data->ReadShort(offset);
27330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (number_of_contours >= 0) {
27430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return GlyphType::kSimple;
27530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
27630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GlyphType::kComposite;
27730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
27830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
27930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
28030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * GlyphTable::Glyph::Builder class
28130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
28230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::Glyph::Builder::~Builder() {
28330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
28430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
28530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::Glyph::Builder::Builder(WritableFontData* data)
28630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : SubTable::Builder(data) {
28730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
28830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
28930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::Glyph::Builder::Builder(ReadableFontData* data)
29030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : SubTable::Builder(data) {
29130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
29230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
29330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH GlyphTable::Glyph::Builder*
29430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    GlyphTable::Glyph::Builder::GetBuilder(
29530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        GlyphTable::Builder* table_builder,
29630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        ReadableFontData* data) {
29730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GetBuilder(table_builder, data, 0, data->Length());
29830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
29930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
30030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH GlyphTable::Glyph::Builder*
30130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    GlyphTable::Glyph::Builder::GetBuilder(
30230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        GlyphTable::Builder* table_builder,
30330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        ReadableFontData* data,
30430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        int32_t offset,
30530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        int32_t length) {
30630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(table_builder);
30730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t type = Glyph::GlyphType(data, offset, length);
30830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  GlyphBuilderPtr builder;
30930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ReadableFontDataPtr sliced_data;
31030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  sliced_data.Attach(down_cast<ReadableFontData*>(data->Slice(offset, length)));
31130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (type == GlyphType::kSimple) {
31230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    builder = new SimpleGlyph::SimpleGlyphBuilder(sliced_data);
31330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  } else {
31430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    builder = new CompositeGlyph::CompositeGlyphBuilder(sliced_data);
31530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
31630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder.Detach();
31730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
31830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
31930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::Glyph::Builder::SubDataSet() {
32030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // NOP
32130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
32230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
32330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Glyph::Builder::SubDataSizeToSerialize() {
32430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return InternalReadData()->Length();
32530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
32630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
32730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool GlyphTable::Glyph::Builder::SubReadyToSerialize() {
32830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return true;
32930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
33030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
33130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::Glyph::Builder::SubSerialize(WritableFontData* new_data) {
33230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return InternalReadData()->CopyTo(new_data);
33330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
33430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
33530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
33630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * GlyphTable::SimpleGlyph
33730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
33830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::SimpleGlyph::SimpleGlyph(ReadableFontData* data)
33930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : GlyphTable::Glyph(data, GlyphType::kSimple), initialized_(false) {
34030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
34130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
34230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::SimpleGlyph::~SimpleGlyph() {
34330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
34430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
34530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::SimpleGlyph::InstructionSize() {
34630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Initialize();
34730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return instruction_size_;
34830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
34930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
35030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH ReadableFontData* GlyphTable::SimpleGlyph::Instructions() {
35130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Initialize();
35230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return down_cast<ReadableFontData*>(
35330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun             data_->Slice(instructions_offset_, InstructionSize()));
35430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
35530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
35630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::SimpleGlyph::NumberOfPoints(int32_t contour) {
35730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Initialize();
35830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (contour >= NumberOfContours()) {
35930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
36030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
36130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return contour_index_[contour + 1] - contour_index_[contour];
36230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
36330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
36430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::SimpleGlyph::XCoordinate(int32_t contour, int32_t point) {
36530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Initialize();
36630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return x_coordinates_[contour_index_[contour] + point];
36730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
36830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
36930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::SimpleGlyph::YCoordinate(int32_t contour, int32_t point) {
37030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Initialize();
37130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return y_coordinates_[contour_index_[contour] + point];
37230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
37330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
37430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool GlyphTable::SimpleGlyph::OnCurve(int32_t contour, int32_t point) {
37530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Initialize();
37630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return on_curve_[contour_index_[contour] + point];
37730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
37830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
37930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::SimpleGlyph::Initialize() {
38030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  AutoLock lock(initialization_lock_);
38130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (initialized_) {
38230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return;
38330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
38430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
38530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (ReadFontData()->Length() == 0) {
38630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    instruction_size_ = 0;
38730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    number_of_points_ = 0;
38830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    instructions_offset_ = 0;
38930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    flags_offset_ = 0;
39030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    x_coordinates_offset_ = 0;
39130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    y_coordinates_offset_ = 0;
39230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return;
39330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
39430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
39530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  instruction_size_ = data_->ReadUShort(Offset::kSimpleEndPtsOfCountours +
39630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      NumberOfContours() * DataSize::kUSHORT);
39730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  instructions_offset_ = Offset::kSimpleEndPtsOfCountours +
39830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      (NumberOfContours() + 1) * DataSize::kUSHORT;
39930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  flags_offset_ = instructions_offset_ + instruction_size_ * DataSize::kBYTE;
40030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  number_of_points_ = ContourEndPoint(NumberOfContours() - 1) + 1;
40130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  x_coordinates_.resize(number_of_points_);
40230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  y_coordinates_.resize(number_of_points_);
40330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  on_curve_.resize(number_of_points_);
40430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ParseData(false);
40530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  x_coordinates_offset_ = flags_offset_ + flag_byte_count_ * DataSize::kBYTE;
40630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  y_coordinates_offset_ = x_coordinates_offset_ + x_byte_count_ *
40730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      DataSize::kBYTE;
40830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  contour_index_.resize(NumberOfContours() + 1);
40930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  contour_index_[0] = 0;
41030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (uint32_t contour = 0; contour < contour_index_.size() - 1; ++contour) {
41130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    contour_index_[contour + 1] = ContourEndPoint(contour) + 1;
41230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
41330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ParseData(true);
41430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t non_padded_data_length =
41530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    5 * DataSize::kSHORT +
41630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    (NumberOfContours() * DataSize::kUSHORT) +
41730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    DataSize::kUSHORT +
41830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    (instruction_size_ * DataSize::kBYTE) +
41930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    (flag_byte_count_ * DataSize::kBYTE) +
42030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    (x_byte_count_ * DataSize::kBYTE) +
42130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    (y_byte_count_ * DataSize::kBYTE);
42230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_padding(DataLength() - non_padded_data_length);
42330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  initialized_ = true;
42430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
42530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
42630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::SimpleGlyph::ParseData(bool fill_arrays) {
42730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t flag = 0;
42830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t flag_repeat = 0;
42930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t flag_index = 0;
43030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t x_byte_index = 0;
43130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t y_byte_index = 0;
43230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
43330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t point_index = 0; point_index < number_of_points_;
43430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun       ++point_index) {
43530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // get the flag for the current point
43630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (flag_repeat == 0) {
43730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      flag = FlagAsInt(flag_index++);
43830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      if ((flag & kFLAG_REPEAT) == kFLAG_REPEAT) {
43930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        flag_repeat = FlagAsInt(flag_index++);
44030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      }
44130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    } else {
44230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      flag_repeat--;
44330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
44430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
44530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // on the curve?
44630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (fill_arrays) {
44730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      on_curve_[point_index] = ((flag & kFLAG_ONCURVE) == kFLAG_ONCURVE);
44830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
44930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // get the x coordinate
45030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if ((flag & kFLAG_XSHORT) == kFLAG_XSHORT) {
45130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      // single byte x coord value
45230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      if (fill_arrays) {
45330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        x_coordinates_[point_index] =
45430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun            data_->ReadUByte(x_coordinates_offset_ + x_byte_index);
45530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        x_coordinates_[point_index] *=
45630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun            ((flag & kFLAG_XREPEATSIGN) == kFLAG_XREPEATSIGN) ? 1 : -1;
45730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      }
45830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      x_byte_index++;
45930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    } else {
46030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      // double byte coord value
46130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      if (!((flag & kFLAG_XREPEATSIGN) == kFLAG_XREPEATSIGN)) {
46230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        if (fill_arrays) {
46330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          x_coordinates_[point_index] =
46430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun            data_->ReadShort(x_coordinates_offset_ + x_byte_index);
46530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        }
46630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        x_byte_index += 2;
46730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      }
46830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
46930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (fill_arrays && point_index > 0) {
47030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      x_coordinates_[point_index] += x_coordinates_[point_index - 1];
47130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
47230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
47330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // get the y coordinate
47430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if ((flag & kFLAG_YSHORT) == kFLAG_YSHORT) {
47530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      if (fill_arrays) {
47630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        y_coordinates_[point_index] =
47730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          data_->ReadUByte(y_coordinates_offset_ + y_byte_index);
47830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        y_coordinates_[point_index] *=
47930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          ((flag & kFLAG_YREPEATSIGN) == kFLAG_YREPEATSIGN) ? 1 : -1;
48030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      }
48130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      y_byte_index++;
48230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    } else {
48330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      if (!((flag & kFLAG_YREPEATSIGN) == kFLAG_YREPEATSIGN)) {
48430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        if (fill_arrays) {
48530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun          y_coordinates_[point_index] =
48630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun            data_->ReadShort(y_coordinates_offset_ + y_byte_index);
48730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        }
48830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        y_byte_index += 2;
48930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      }
49030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
49130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (fill_arrays && point_index > 0) {
49230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      y_coordinates_[point_index] += y_coordinates_[point_index - 1];
49330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
49430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
49530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  flag_byte_count_ = flag_index;
49630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  x_byte_count_ = x_byte_index;
49730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  y_byte_count_ = y_byte_index;
49830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
49930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
50030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::SimpleGlyph::FlagAsInt(int32_t index) {
50130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUByte(flags_offset_ + index * DataSize::kBYTE);
50230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
50330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
50430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::SimpleGlyph::ContourEndPoint(int32_t contour) {
50530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(contour * DataSize::kUSHORT +
50630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           Offset::kSimpleEndPtsOfCountours);
50730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
50830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
50930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
51030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * GlyphTable::SimpleGlyph::Builder
51130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
51230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::SimpleGlyph::SimpleGlyphBuilder::~SimpleGlyphBuilder() {
51330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
51430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
51530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder(
51630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    WritableFontData* data)
51730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : Glyph::Builder(data) {
51830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
51930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
52030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::SimpleGlyph::SimpleGlyphBuilder::SimpleGlyphBuilder(
52130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadableFontData* data)
52230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : Glyph::Builder(data) {
52330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
52430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
52530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH FontDataTable*
52630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    GlyphTable::SimpleGlyph::SimpleGlyphBuilder::SubBuildTable(
52730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        ReadableFontData* data) {
52830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontDataTablePtr table = new SimpleGlyph(data);
52930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return table.Detach();
53030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
53130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
53230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
53330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * GlyphTable::CompositeGlyph
53430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
53530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::CompositeGlyph::CompositeGlyph(ReadableFontData* data)
53630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : GlyphTable::Glyph(data, GlyphType::kComposite),
53730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      instruction_size_(0),
53830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      instructions_offset_(0),
53930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      initialized_(false) {
54030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Initialize();
54130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
54230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
54330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::CompositeGlyph::~CompositeGlyph() {
54430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
54530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
54630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::CompositeGlyph::Flags(int32_t contour) {
54730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(contour_index_[contour]);
54830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
54930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
55030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::CompositeGlyph::NumGlyphs() {
55130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return contour_index_.size();
55230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
55330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
55430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::CompositeGlyph::GlyphIndex(int32_t contour) {
55530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(DataSize::kUSHORT + contour_index_[contour]);
55630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
55730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
55830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::CompositeGlyph::Argument1(int32_t contour) {
55930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t index = 2 * DataSize::kUSHORT + contour_index_[contour];
56030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t contour_flags = Flags(contour);
56130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if ((contour_flags & kFLAG_ARG_1_AND_2_ARE_WORDS) ==
56230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                       kFLAG_ARG_1_AND_2_ARE_WORDS) {
56330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return data_->ReadUShort(index);
56430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
56530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadByte(index);
56630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
56730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
56830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::CompositeGlyph::Argument2(int32_t contour) {
56930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t index = 2 * DataSize::kUSHORT + contour_index_[contour];
57030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t contour_flags = Flags(contour);
57130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if ((contour_flags & kFLAG_ARG_1_AND_2_ARE_WORDS) ==
57230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                       kFLAG_ARG_1_AND_2_ARE_WORDS) {
57330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return data_->ReadUShort(index + DataSize::kUSHORT);
57430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
57530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadByte(index + DataSize::kUSHORT);
57630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
57730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
57830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::CompositeGlyph::TransformationSize(int32_t contour) {
57930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t contour_flags = Flags(contour);
58030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if ((contour_flags & kFLAG_WE_HAVE_A_SCALE) == kFLAG_WE_HAVE_A_SCALE) {
58130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return DataSize::kF2DOT14;
58230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    } else if ((contour_flags & kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) ==
58330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) {
58430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return 2 * DataSize::kF2DOT14;
58530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    } else if ((contour_flags & kFLAG_WE_HAVE_A_TWO_BY_TWO) ==
58630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                kFLAG_WE_HAVE_A_TWO_BY_TWO) {
58730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return 4 * DataSize::kF2DOT14;
58830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
58930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
59030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
59130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
59230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::CompositeGlyph::Transformation(int32_t contour,
59330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                ByteVector* transformation) {
59430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t contour_flags = Flags(contour);
59530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t index = contour_index_[contour] + 2 * DataSize::kUSHORT;
59630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if ((contour_flags & kFLAG_ARG_1_AND_2_ARE_WORDS) ==
59730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                       kFLAG_ARG_1_AND_2_ARE_WORDS) {
59830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += 2 * DataSize::kSHORT;
59930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  } else {
60030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += 2 * DataSize::kBYTE;
60130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
60230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t tsize = TransformationSize(contour);
60330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  transformation->resize(tsize);
60430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  data_->ReadBytes(index, &((*transformation)[0]), 0, tsize);
60530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
60630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
60730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t GlyphTable::CompositeGlyph::InstructionSize() {
60830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return instruction_size_;
60930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
61030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
61130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH ReadableFontData* GlyphTable::CompositeGlyph::Instructions() {
61230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return down_cast<ReadableFontData*>(
61330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun             data_->Slice(instructions_offset_, InstructionSize()));
61430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
61530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
61630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid GlyphTable::CompositeGlyph::Initialize() {
61730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  AutoLock lock(initialization_lock_);
61830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (initialized_) {
61930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return;
62030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
62130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
62230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t index = 5 * DataSize::kUSHORT;
62330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t flags = kFLAG_MORE_COMPONENTS;
62430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
62530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  while ((flags & kFLAG_MORE_COMPONENTS) == kFLAG_MORE_COMPONENTS) {
62630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    contour_index_.push_back(index);
62730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    flags = data_->ReadUShort(index);
62830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += 2 * DataSize::kUSHORT;  // flags and glyphIndex
62930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if ((flags & kFLAG_ARG_1_AND_2_ARE_WORDS) == kFLAG_ARG_1_AND_2_ARE_WORDS) {
63030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      index += 2 * DataSize::kSHORT;
63130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    } else {
63230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      index += 2 * DataSize::kBYTE;
63330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
63430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if ((flags & kFLAG_WE_HAVE_A_SCALE) == kFLAG_WE_HAVE_A_SCALE) {
63530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      index += DataSize::kF2DOT14;
63630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    } else if ((flags & kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) ==
63730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                        kFLAG_WE_HAVE_AN_X_AND_Y_SCALE) {
63830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      index += 2 * DataSize::kF2DOT14;
63930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    } else if ((flags & kFLAG_WE_HAVE_A_TWO_BY_TWO) ==
64030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                        kFLAG_WE_HAVE_A_TWO_BY_TWO) {
64130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      index += 4 * DataSize::kF2DOT14;
64230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
64330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t non_padded_data_length = index;
64430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if ((flags & kFLAG_WE_HAVE_INSTRUCTIONS) == kFLAG_WE_HAVE_INSTRUCTIONS) {
64530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      instruction_size_ = data_->ReadUShort(index);
64630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      index += DataSize::kUSHORT;
64730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      instructions_offset_ = index;
64830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      non_padded_data_length = index + (instruction_size_ * DataSize::kBYTE);
64930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
65030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    set_padding(DataLength() - non_padded_data_length);
65130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
65230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
65330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  initialized_ = true;
65430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
65530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
65630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
65730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * GlyphTable::CompositeGlyph::Builder
65830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
65930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::CompositeGlyph::CompositeGlyphBuilder::~CompositeGlyphBuilder() {
66030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
66130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
66230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder(
66330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    WritableFontData* data)
66430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : Glyph::Builder(data) {
66530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
66630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
66730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunGlyphTable::CompositeGlyph::CompositeGlyphBuilder::CompositeGlyphBuilder(
66830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadableFontData* data)
66930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : Glyph::Builder(data) {
67030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
67130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
67230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH FontDataTable*
67330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    GlyphTable::CompositeGlyph::CompositeGlyphBuilder::SubBuildTable(
67430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        ReadableFontData* data) {
67530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontDataTablePtr table = new CompositeGlyph(data);
67630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return table.Detach();
67730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
67830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
67930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}  // namespace sfntly
680