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/loca_table.h"
1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/exception_type.h"
1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace sfntly {
2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * LocaTable class
2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunLocaTable::~LocaTable() {}
2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::GlyphOffset(int32_t glyph_id) {
2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (glyph_id < 0 || glyph_id >= num_glyphs_) {
2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IndexOutOfBoundException("Glyph ID is out of bounds.");
3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Loca(glyph_id);
3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::GlyphLength(int32_t glyph_id) {
3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (glyph_id < 0 || glyph_id >= num_glyphs_) {
3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IndexOutOfBoundException("Glyph ID is out of bounds.");
4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Loca(glyph_id + 1) - Loca(glyph_id);
4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::NumLocas() {
4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return num_glyphs_ + 1;
4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::Loca(int32_t index) {
5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (index > num_glyphs_) {
5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IndexOutOfBoundException();
5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (format_version_ == IndexToLocFormat::kShortOffset) {
5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 2 * data_->ReadUShort(index * DataSize::kUSHORT);
5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadULongAsInt(index * DataSize::kULONG);
6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunLocaTable::LocaTable(Header* header,
6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                     ReadableFontData* data,
6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                     int32_t format_version,
6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                     int32_t num_glyphs)
6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : Table(header, data),
6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      format_version_(format_version),
6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      num_glyphs_(num_glyphs) {
7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * LocaTable::Iterator class
7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunLocaTable::LocaIterator::LocaIterator(LocaTable* table)
7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : PODIterator<int32_t, LocaTable>(table), index_(-1) {
7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool LocaTable::LocaIterator::HasNext() {
8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return index_ <= container()->num_glyphs_;
8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::LocaIterator::Next() {
8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return container()->Loca(index_++);
8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * LocaTable::Builder class
8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunLocaTable::Builder::Builder(Header* header, WritableFontData* data)
9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : Table::Builder(header, data),
9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      format_version_(IndexToLocFormat::kLongOffset),
9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      num_glyphs_(-1) {
9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunLocaTable::Builder::Builder(Header* header, ReadableFontData* data)
9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : Table::Builder(header, data),
9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      format_version_(IndexToLocFormat::kLongOffset),
9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      num_glyphs_(-1) {
10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunLocaTable::Builder::~Builder() {}
10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH
10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunLocaTable::Builder* LocaTable::Builder::CreateBuilder(Header* header,
10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                      WritableFontData* data) {
10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Ptr<LocaTable::Builder> builder;
10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder = new LocaTable::Builder(header, data);
10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder.Detach();
11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunIntegerList* LocaTable::Builder::LocaList() {
11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GetLocaList();
11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid LocaTable::Builder::SetLocaList(IntegerList* list) {
11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  loca_.clear();
11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (list) {
11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    loca_ = *list;
12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    set_model_changed();
12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::Builder::GlyphOffset(int32_t glyph_id) {
12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (CheckGlyphRange(glyph_id) == -1) {
12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GetLocaList()->at(glyph_id);
12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::Builder::GlyphLength(int32_t glyph_id) {
13230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (CheckGlyphRange(glyph_id) == -1) {
13330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
13430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
13530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GetLocaList()->at(glyph_id + 1) - GetLocaList()->at(glyph_id);
13630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
13730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
13830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid LocaTable::Builder::SetNumGlyphs(int32_t num_glyphs) {
13930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  num_glyphs_ = num_glyphs;
14030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
14130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
14230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::Builder::NumGlyphs() {
14330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return LastGlyphIndex() - 1;
14430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
14530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
14630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid LocaTable::Builder::Revert() {
14730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  loca_.clear();
14830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_model_changed(false);
14930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
15030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
15130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::Builder::NumLocas() {
15230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GetLocaList()->size();
15330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
15430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
15530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::Builder::Loca(int32_t index) {
15630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GetLocaList()->at(index);
15730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
15830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
15930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH
16030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunFontDataTable* LocaTable::Builder::SubBuildTable(ReadableFontData* data) {
16130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontDataTablePtr table =
16230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      new LocaTable(header(), data, format_version_, num_glyphs_);
16330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return table.Detach();
16430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
16530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
16630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid LocaTable::Builder::SubDataSet() {
16730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Initialize(InternalReadData());
16830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
16930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
17030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::Builder::SubDataSizeToSerialize() {
17130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (loca_.empty()) {
17230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
17330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
17430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (format_version_ == IndexToLocFormat::kLongOffset) {
17530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return loca_.size() * DataSize::kULONG;
17630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
17730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return loca_.size() * DataSize::kUSHORT;
17830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
17930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
18030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool LocaTable::Builder::SubReadyToSerialize() {
18130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return !loca_.empty();
18230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
18330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
18430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::Builder::SubSerialize(WritableFontData* new_data) {
18530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t size = 0;
18630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (IntegerList::iterator l = loca_.begin(), end = loca_.end();
18730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                             l != end; ++l) {
18830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (format_version_ == IndexToLocFormat::kLongOffset) {
18930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      size += new_data->WriteULong(size, *l);
19030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    } else {
19130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      size += new_data->WriteUShort(size, *l / 2);
19230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
19330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
19430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  num_glyphs_ = loca_.size() - 1;
19530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return size;
19630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
19730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
19830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid LocaTable::Builder::Initialize(ReadableFontData* data) {
19930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ClearLoca(false);
20030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (data) {
20130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (NumGlyphs() < 0) {
20230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
20330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      throw IllegalStateException("numglyphs not set on LocaTable Builder.");
20430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
20530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return;
20630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
20730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    LocaTablePtr table =
20830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        new LocaTable(header(), data, format_version_, num_glyphs_);
20930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    Ptr<LocaTable::LocaIterator> loca_iter =
21030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        new LocaTable::LocaIterator(table);
21130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    while (loca_iter->HasNext()) {
21230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      loca_.push_back(loca_iter->Next());
21330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
21430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
21530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
21630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
21730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::Builder::CheckGlyphRange(int32_t glyph_id) {
21830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (glyph_id < 0 || glyph_id > LastGlyphIndex()) {
21930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
22030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IndexOutOfBoundsException("Glyph ID is outside of the allowed range");
22130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
22230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return -1;
22330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
22430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return glyph_id;
22530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
22630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
22730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t LocaTable::Builder::LastGlyphIndex() {
22830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return !loca_.empty() ? loca_.size() - 2 : num_glyphs_ - 1;
22930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
23030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
23130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunIntegerList* LocaTable::Builder::GetLocaList() {
23230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (loca_.empty()) {
23330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    Initialize(InternalReadData());
23430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    set_model_changed();
23530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
23630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return &loca_;
23730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
23830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
23930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid LocaTable::Builder::ClearLoca(bool nullify) {
24030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // Note: in C++ port, nullify is not used at all.
24130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(nullify);
24230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  loca_.clear();
24330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_model_changed(false);
24430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
24530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
24630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}  // namespace sfntly
247