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// type.h needs to be included first because of building issues on Windows
1830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Type aliases we delcare are defined in other headers and make the build
1930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// fail otherwise.
2030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/type.h"
2130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/core/cmap_table.h"
2230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <stdio.h>
2430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <stdlib.h>
2530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include <utility>
2730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
2830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/font.h"
2930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/math/font_math.h"
3030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/endian.h"
3130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/port/exception_type.h"
3230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#include "sfntly/table/core/name_table.h"
3330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunnamespace sfntly {
3530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunconst int32_t CMapTable::NOTDEF = 0;
3730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
3830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapId CMapTable::WINDOWS_BMP = {
3930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  PlatformId::kWindows,
4030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  WindowsEncodingId::kUnicodeUCS2
4130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun};
4230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapId CMapTable::WINDOWS_UCS4 = {
4330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  PlatformId::kWindows,
4430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  WindowsEncodingId::kUnicodeUCS4
4530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun};
4630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapId CMapTable::MAC_ROMAN = {
4730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  PlatformId::kWindows,
4830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  MacintoshEncodingId::kRoman
4930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun};
5030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
5230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable class
5330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
5430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapTable(Header* header, ReadableFontData* data)
5530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  : SubTableContainerTable(header, data) {
5630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
5730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
5830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::~CMapTable() {}
5930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
6030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMap* CMapTable::GetCMap(const int32_t index) {
6130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (index < 0 || index > NumCMaps()) {
6230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#ifndef SFNTLY_NO_EXCEPTION
6330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IndexOutOfBoundException("Requested CMap index is out of bounds.");
6430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else
6530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return NULL;
6630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
6730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
6830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t platform_id = PlatformId(index);
6930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t encoding_id = EncodingId(index);
7030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapId cmap_id = NewCMapId(platform_id, encoding_id);
7130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t offset_ = Offset(index);
7230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Ptr<FontDataTable::Builder> cmap_builder =
7330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      (CMap::Builder::GetBuilder(data_, offset_, cmap_id));
7430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!cmap_builder) {
7530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#ifndef SFNTLY_NO_EXCEPTION
7630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw NoSuchElementException("Cannot find builder for requested CMap.");
7730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else
7830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return NULL;
7930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
8030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
8130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return down_cast<CMapTable::CMap*>(cmap_builder->Build());
8230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
8330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
8430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMap* CMapTable::GetCMap(const int32_t platform_id,
8530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                  const int32_t encoding_id) {
8630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GetCMap(NewCMapId(platform_id, encoding_id));
8730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
8830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
8930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMap*
9030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::GetCMap(const CMapTable::CMapId cmap_id) {
9130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapIdFilter id_filter(cmap_id);
9230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapIterator cmap_iterator(this, &id_filter);
9330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // There can only be one cmap with a particular CMapId
9430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (cmap_iterator.HasNext()) {
9530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    Ptr<CMapTable::CMap> cmap;
9630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    cmap.Attach(cmap_iterator.Next());
9730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return cmap.Detach();
9830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
9930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#ifndef SFNTLY_NO_EXCEPTION
10030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  throw NoSuchElementException();
10130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else
10230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return NULL;
10330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
10430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
10530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
10630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::Version() {
10730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(Offset::kVersion);
10830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
10930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
11030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::NumCMaps() {
11130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(Offset::kNumTables);
11230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
11330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
11430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapId CMapTable::GetCMapId(int32_t index) {
11530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return NewCMapId(PlatformId(index), EncodingId(index));
11630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
11730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
11830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::PlatformId(int32_t index) {
11930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(Offset::kEncodingRecordPlatformId +
12030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           OffsetForEncodingRecord(index));
12130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
12230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
12330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::EncodingId(int32_t index) {
12430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(Offset::kEncodingRecordEncodingId +
12530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           OffsetForEncodingRecord(index));
12630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
12730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
12830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::Offset(int32_t index) {
12930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadULongAsInt(Offset::kEncodingRecordOffset +
13030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                               OffsetForEncodingRecord(index));
13130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
13230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
13330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::OffsetForEncodingRecord(int32_t index) {
13430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Offset::kEncodingRecordStart + index * Offset::kEncodingRecordSize;
13530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
13630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
13730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapId CMapTable::NewCMapId(int32_t platform_id,
13830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       int32_t encoding_id) {
13930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapId result;
14030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  result.platform_id = platform_id;
14130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  result.encoding_id = encoding_id;
14230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return result;
14330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
14430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
14530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapId CMapTable::NewCMapId(const CMapId& obj) {
14630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapId result;
14730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  result.platform_id = obj.platform_id;
14830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  result.encoding_id = obj.encoding_id;
14930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return result;
15030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
15130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
15230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
15330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapIterator class
15430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
15530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapIterator::CMapIterator(CMapTable* table,
15630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                      const CMapFilter* filter)
15730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : table_index_(0), filter_(filter), table_(table) {
15830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
15930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
16030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool CMapTable::CMapIterator::HasNext() {
16130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!filter_) {
16230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (table_index_ < table_->NumCMaps()) {
16330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return true;
16430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
16530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return false;
16630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
16730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
16830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (; table_index_ < table_->NumCMaps(); ++table_index_) {
16930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (filter_->accept(table_->GetCMapId(table_index_))) {
17030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return true;
17130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
17230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
17330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return false;
17430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
17530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
17630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMap* CMapTable::CMapIterator::Next() {
17730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!HasNext()) {
17830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#ifndef SFNTLY_NO_EXCEPTION
17930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw NoSuchElementException();
18030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else
18130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return NULL;
18230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
18330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
18430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapPtr next_cmap;
18530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  next_cmap.Attach(table_->GetCMap(table_index_++));
18630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (next_cmap == NULL) {
18730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#ifndef SFNTLY_NO_EXCEPTION
18830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw NoSuchElementException("Error during the creation of the CMap");
18930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else
19030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return NULL;
19130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
19230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
19330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return next_cmap.Detach();
19430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
19530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
19630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
19730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapId class
19830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
19930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
20030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
20130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapIdComparator class
20230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
20330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
20430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool CMapTable::CMapIdComparator::operator()(const CMapId& lhs,
20530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                             const CMapId& rhs) const {
20630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return ((lhs.platform_id << 8 | lhs.encoding_id) >
20730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      (rhs.platform_id << 8 | rhs.encoding_id));
20830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
20930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
21030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
21130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapIdFilter class
21230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
21330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapIdFilter::CMapIdFilter(const CMapId wanted_id)
21430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : wanted_id_(wanted_id),
21530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      comparator_(NULL) {
21630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
21730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
21830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapIdFilter::CMapIdFilter(const CMapId wanted_id,
21930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                      const CMapIdComparator* comparator)
22030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : wanted_id_(wanted_id),
22130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      comparator_(comparator) {
22230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
22330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
22430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool CMapTable::CMapIdFilter::accept(const CMapId& cmap_id) const {
22530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!comparator_)
22630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return wanted_id_ == cmap_id;
22730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return (*comparator_)(wanted_id_, cmap_id);
22830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
22930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
23030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
23130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMap class
23230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
23330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::CMap(ReadableFontData* data, int32_t format,
23430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                      const CMapId& cmap_id)
23530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : SubTable(data), format_(format), cmap_id_(cmap_id) {
23630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
23730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
23830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::~CMap() {
23930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
24030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
24130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
24230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMap::Builder class
24330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
24430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::Builder::~Builder() {
24530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
24630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
24730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMap::Builder*
24830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    CMapTable::CMap::Builder::GetBuilder(ReadableFontData* data, int32_t offset,
24930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         const CMapId& cmap_id) {
25030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // NOT IMPLEMENTED: Java enum value validation
25130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t format = data->ReadUShort(offset);
25230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapBuilderPtr builder;
25330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  switch (format) {
25430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    case CMapFormat::kFormat0:
25530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      builder.Attach(CMapFormat0::Builder::NewInstance(data, offset, cmap_id));
25630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      break;
25730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    case CMapFormat::kFormat2:
25830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SFNTLY_DEBUG_CMAP)
25930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      fprintf(stderr, "Requesting Format2 builder, but it's unsupported; "
26030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun              "returning NULL\n");
26130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
26230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      break;
26330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    case CMapFormat::kFormat4:
26430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      builder.Attach(CMapFormat4::Builder::NewInstance(data, offset, cmap_id));
26530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      break;
26630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    default:
26730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#ifdef SFNTLY_DEBUG_CMAP
26830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      fprintf(stderr, "Unknown builder format requested\n");
26930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
27030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      break;
27130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
27230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder.Detach();
27330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
27430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
27530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMap::Builder*
27630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::Builder::GetBuilder(int32_t format, const CMapId& cmap_id) {
27730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Ptr<CMapTable::CMap::Builder> builder;
27830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  switch (format) {
27930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    case CMapFormat::kFormat0:
28030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      builder.Attach(CMapFormat0::Builder::NewInstance(cmap_id));
28130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      break;
28230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    case CMapFormat::kFormat2:
28330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SFNTLY_DEBUG_CMAP)
28430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      fprintf(stderr, "Requesting Format2 builder, but it's unsupported; "
28530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun              "returning NULL\n");
28630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
28730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      break;
28830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    case CMapFormat::kFormat4:
28930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      builder.Attach(CMapFormat4::Builder::NewInstance(cmap_id));
29030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      break;
29130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    default:
29230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#ifdef SFNTLY_DEBUG_CMAP
29330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      fprintf(stderr, "Unknown builder format requested\n");
29430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
29530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      break;
29630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
29730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder.Detach();
29830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
29930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
30030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::Builder::Builder(ReadableFontData* data,
30130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  int32_t format,
30230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  const CMapId& cmap_id)
30330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : SubTable::Builder(data),
30430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      format_(format),
30530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      cmap_id_(cmap_id),
30630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      language_(0) {
30730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
30830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
30930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::Builder::Builder(WritableFontData* data,
31030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  int32_t format,
31130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                  const CMapId& cmap_id)
31230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : SubTable::Builder(data),
31330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      format_(format),
31430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      cmap_id_(cmap_id),
31530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      language_(0) {
31630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
31730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
31830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMap::Builder::SubSerialize(WritableFontData* new_data) {
31930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return InternalReadData()->CopyTo(new_data);
32030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
32130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
32230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool CMapTable::CMap::Builder::SubReadyToSerialize() {
32330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return true;
32430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
32530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
32630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMap::Builder::SubDataSizeToSerialize() {
32730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ReadableFontDataPtr read_data = InternalReadData();
32830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!read_data)
32930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
33030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return read_data->Length();
33130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
33230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
33330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid CMapTable::CMap::Builder::SubDataSet() {
33430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // NOP
33530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
33630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
33730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
33830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapFormat0
33930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
34030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::~CMapFormat0() {
34130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
34230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
34330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat0::Language() {
34430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return 0;
34530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
34630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
34730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat0::GlyphId(int32_t character) {
34830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (character < 0 || character > 255) {
34930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return CMapTable::NOTDEF;
35030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
35130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUByte(character + Offset::kFormat0GlyphIdArray);
35230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
35330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
35430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data,
35530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                    const CMapId& cmap_id)
35630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMap(data, CMapFormat::kFormat0, cmap_id) {
35730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
35830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
35930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::CharacterIterator* CMapTable::CMapFormat0::Iterator() {
36030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return new CMapTable::CMapFormat0::CharacterIterator(0, 0xff);
36130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
36230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
36330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
36430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
36530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapFormat0::CharacterIterator
36630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
36730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::CharacterIterator::CharacterIterator(int32_t start,
36830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                             int32_t end)
36930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : character_(start),
37030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    max_character_(end) {
37130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
37230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
37330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::CharacterIterator::~CharacterIterator() {}
37430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
37530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool CMapTable::CMapFormat0::CharacterIterator::HasNext() {
37630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return character_ < max_character_;
37730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
37830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
37930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat0::CharacterIterator::Next() {
38030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (HasNext())
38130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return character_++;
38230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#ifndef SFNTLY_NO_EXCEPTION
38330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  throw NoSuchElementException("No more characters to iterate.");
38430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
38530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return -1;
38630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
38730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
38830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
38930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapFormat0::Builder
39030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
39130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
39230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMapFormat0::Builder*
39330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::Builder::NewInstance(WritableFontData* data,
39430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                             int32_t offset,
39530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                             const CMapId& cmap_id) {
39630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  WritableFontDataPtr wdata;
39730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (data) {
39830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    wdata.Attach(down_cast<WritableFontData*>(
39930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        data->Slice(offset,
40030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                    data->ReadUShort(offset + Offset::kFormat0Length))));
40130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
40230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return new Builder(wdata, CMapFormat::kFormat0, cmap_id);
40330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
40430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
40530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
40630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMapFormat0::Builder*
40730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::Builder::NewInstance(ReadableFontData* data,
40830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                             int32_t offset,
40930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                             const CMapId& cmap_id) {
41030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ReadableFontDataPtr rdata;
41130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (data) {
41230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    rdata.Attach(down_cast<ReadableFontData*>(
41330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        data->Slice(offset,
41430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                    data->ReadUShort(offset + Offset::kFormat0Length))));
41530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
41630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return new Builder(rdata, CMapFormat::kFormat0, cmap_id);
41730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
41830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
41930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
42030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMapFormat0::Builder*
42130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::Builder::NewInstance(const CMapId& cmap_id) {
42230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return new Builder(cmap_id);
42330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
42430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
42530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// Always call NewInstance instead of the constructor for creating a new builder
42630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// object! This refactoring avoids memory leaks when slicing the font data.
42730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::Builder::Builder(WritableFontData* data, int32_t offset,
42830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         const CMapId& cmap_id)
42930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMapTable::CMap::Builder(data, CMapFormat::kFormat0, cmap_id) {
43030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(offset);
43130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
43230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
43330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::Builder::Builder(
43430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadableFontData* data,
43530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t offset,
43630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    const CMapId& cmap_id)
43730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMapTable::CMap::Builder(data, CMapFormat::kFormat0, cmap_id) {
43830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(offset);
43930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
44030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
44130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::Builder::Builder(const CMapId& cmap_id)
44230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMap::Builder(reinterpret_cast<ReadableFontData*>(NULL),
44330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                    CMapFormat::kFormat0,
44430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                    cmap_id) {
44530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
44630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
44730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat0::Builder::~Builder() {
44830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
44930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
45030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH FontDataTable*
45130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    CMapTable::CMapFormat0::Builder::SubBuildTable(ReadableFontData* data) {
45230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontDataTablePtr table = new CMapFormat0(data, cmap_id());
45330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return table.Detach();
45430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
45530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
45630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
45730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapFormat2
45830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
45930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat2::~CMapFormat2() {
46030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
46130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
46230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat2::Language() {
46330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return 0;
46430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
46530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
46630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat2::GlyphId(int32_t character) {
46730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (character > 0xffff) {
46830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return CMapTable::NOTDEF;
46930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
47030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
47130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  uint32_t c = ToBE32(character);
47230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  byte_t high_byte = (c >> 8) & 0xff;
47330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  byte_t low_byte = c & 0xff;
47430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t offset = SubHeaderOffset(high_byte);
47530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
47630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (offset == 0) {
47730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    low_byte = high_byte;
47830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    high_byte = 0;
47930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
48030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
48130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t first_code = FirstCode(high_byte);
48230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t entry_count = EntryCount(high_byte);
48330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
48430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (low_byte < first_code || low_byte >= first_code + entry_count) {
48530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return CMapTable::NOTDEF;
48630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
48730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
48830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t id_range_offset = IdRangeOffset(high_byte);
48930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
49030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // position of idRangeOffset + value of idRangeOffset + index for low byte
49130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // = firstcode
49230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t p_location = (offset + Offset::kFormat2SubHeader_idRangeOffset) +
49330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      id_range_offset +
49430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      (low_byte - first_code) * DataSize::kUSHORT;
49530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int p = data_->ReadUShort(p_location);
49630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (p == 0) {
49730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return CMapTable::NOTDEF;
49830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
49930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
50030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (offset == 0) {
50130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return p;
50230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
50330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int id_delta = IdDelta(high_byte);
50430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return (p + id_delta) % 65536;
50530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
50630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
50730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat2::BytesConsumed(int32_t character) {
50830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  uint32_t c = ToBE32(character);
50930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t high_byte = (c >> 8) & 0xff;
51030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t offset = SubHeaderOffset(high_byte);
51130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return (offset == 0) ? 1 : 2;
51230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
51330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
51430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat2::CMapFormat2(ReadableFontData* data,
51530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                    const CMapId& cmap_id)
51630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMap(data, CMapFormat::kFormat2, cmap_id) {
51730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
51830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
51930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat2::SubHeaderOffset(int32_t sub_header_index) {
52030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(Offset::kFormat2SubHeaderKeys +
52130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           sub_header_index * DataSize::kUSHORT);
52230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
52330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
52430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat2::FirstCode(int32_t sub_header_index) {
52530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t sub_header_offset = SubHeaderOffset(sub_header_index);
52630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(sub_header_offset +
52730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           Offset::kFormat2SubHeaderKeys +
52830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           Offset::kFormat2SubHeader_firstCode);
52930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
53030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
53130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat2::EntryCount(int32_t sub_header_index) {
53230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t sub_header_offset = SubHeaderOffset(sub_header_index);
53330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(sub_header_offset +
53430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           Offset::kFormat2SubHeaderKeys +
53530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           Offset::kFormat2SubHeader_entryCount);
53630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
53730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
53830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat2::IdRangeOffset(int32_t sub_header_index) {
53930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t sub_header_offset = SubHeaderOffset(sub_header_index);
54030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(sub_header_offset +
54130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           Offset::kFormat2SubHeaderKeys +
54230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           Offset::kFormat2SubHeader_idRangeOffset);
54330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
54430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
54530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat2::IdDelta(int32_t sub_header_index) {
54630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t sub_header_offset = SubHeaderOffset(sub_header_index);
54730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(sub_header_offset +
54830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           Offset::kFormat2SubHeaderKeys +
54930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           Offset::kFormat2SubHeader_idDelta);
55030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
55130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
55230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::CharacterIterator* CMapTable::CMapFormat2::Iterator() {
55330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // UNIMPLEMENTED
55430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return NULL;
55530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
55630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
55730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
55830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapFormat2::Builder
55930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
56030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat2::Builder::Builder(WritableFontData* data,
56130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         int32_t offset,
56230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         const CMapId& cmap_id)
56330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMapTable::CMap::Builder(data ? down_cast<WritableFontData*>(
56430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                   data->Slice(offset, data->ReadUShort(
56530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       offset + Offset::kFormat0Length)))
56630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                               : reinterpret_cast<WritableFontData*>(NULL),
56730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                               CMapFormat::kFormat2, cmap_id) {
56830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix.
56930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
57030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
57130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat2::Builder::Builder(ReadableFontData* data,
57230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         int32_t offset,
57330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         const CMapId& cmap_id)
57430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMapTable::CMap::Builder(data ? down_cast<ReadableFontData*>(
57530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                   data->Slice(offset, data->ReadUShort(
57630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       offset + Offset::kFormat0Length)))
57730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                               : reinterpret_cast<ReadableFontData*>(NULL),
57830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                               CMapFormat::kFormat2, cmap_id) {
57930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix.
58030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
58130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
58230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat2::Builder::~Builder() {
58330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
58430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
58530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH FontDataTable*
58630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    CMapTable::CMapFormat2::Builder::SubBuildTable(ReadableFontData* data) {
58730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontDataTablePtr table = new CMapFormat2(data, cmap_id());
58830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return table.Detach();
58930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
59030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
59130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
59230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapFormat4
59330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
59430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::CMapFormat4(ReadableFontData* data,
59530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                    const CMapId& cmap_id)
59630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMap(data, CMapFormat::kFormat4, cmap_id),
59730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      seg_count_(SegCount(data)),
59830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      start_code_offset_(StartCodeOffset(seg_count_)),
59930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      id_delta_offset_(IdDeltaOffset(seg_count_)),
60030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      glyph_id_array_offset_(GlyphIdArrayOffset(seg_count_)) {
60130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
60230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
60330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::~CMapFormat4() {
60430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
60530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
60630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::GlyphId(int32_t character) {
60730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t segment = data_->SearchUShort(StartCodeOffset(seg_count_),
60830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        DataSize::kUSHORT,
60930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        Offset::kFormat4EndCount,
61030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        DataSize::kUSHORT,
61130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        seg_count_,
61230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        character);
61330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (segment == -1) {
61430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return CMapTable::NOTDEF;
61530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
61630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t start_code = StartCode(segment);
61730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return RetrieveGlyphId(segment, start_code, character);
61830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
61930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
62030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::RetrieveGlyphId(int32_t segment,
62130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                int32_t start_code,
62230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                int32_t character) {
62330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (character < start_code) {
62430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return CMapTable::NOTDEF;
62530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
62630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t id_range_offset = IdRangeOffset(segment);
62730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (id_range_offset == 0) {
62830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return (character + IdDelta(segment)) % 65536;
62930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
63030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(id_range_offset +
63130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           IdRangeOffsetLocation(segment) +
63230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                           2 * (character - start_code));
63330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
63430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
63530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::seg_count() {
63630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return seg_count_;
63730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
63830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
63930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::Length() {
64030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Length(data_);
64130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
64230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
64330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::StartCode(int32_t segment) {
64430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!IsValidIndex(segment)) {
64530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return -1;
64630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
64730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return StartCode(data_.p_, seg_count_, segment);
64830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
64930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
65030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
65130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::Language(ReadableFontData* data) {
65230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t language = data->ReadUShort(Offset::kFormat4Language);
65330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return language;
65430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
65530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
65630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
65730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::Length(ReadableFontData* data) {
65830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t length = data->ReadUShort(Offset::kFormat4Length);
65930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return length;
66030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
66130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
66230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
66330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::SegCount(ReadableFontData* data) {
66430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t seg_count = data->ReadUShort(Offset::kFormat4SegCountX2) / 2;
66530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return seg_count;
66630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
66730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
66830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
66930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::StartCode(ReadableFontData* data,
67030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                          int32_t seg_count,
67130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                          int32_t index) {
67230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t start_code = data->ReadUShort(StartCodeOffset(seg_count) +
67330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        index * DataSize::kUSHORT);
67430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return start_code;
67530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
67630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
67730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
67830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::StartCodeOffset(int32_t seg_count) {
67930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t start_code_offset = Offset::kFormat4EndCount +
68030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      (seg_count + 1) * DataSize::kUSHORT;
68130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return start_code_offset;
68230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
68330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
68430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
68530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::EndCode(ReadableFontData* data,
68630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        int32_t seg_count,
68730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        int32_t index) {
68830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(seg_count);
68930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t end_code = data->ReadUShort(Offset::kFormat4EndCount +
69030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                      index * DataSize::kUSHORT);
69130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return end_code;
69230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
69330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
69430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
69530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::IdDelta(ReadableFontData* data,
69630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        int32_t seg_count,
69730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        int32_t index) {
69830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t id_delta = data->ReadUShort(IdDeltaOffset(seg_count) +
69930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                      index * DataSize::kUSHORT);
70030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return id_delta;
70130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
70230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
70330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
70430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::IdDeltaOffset(int32_t seg_count) {
70530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t id_delta_offset =
70630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      Offset::kFormat4EndCount + (2 * seg_count + 1) * DataSize::kUSHORT;
70730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return id_delta_offset;
70830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
70930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
71030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
71130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::IdRangeOffset(ReadableFontData* data,
71230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                              int32_t seg_count,
71330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                              int32_t index) {
71430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t id_range_offset =
71530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      data->ReadUShort(IdRangeOffsetOffset(seg_count)
71630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                       + index * DataSize::kUSHORT);
71730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return id_range_offset;
71830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
71930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
72030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
72130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::IdRangeOffsetOffset(int32_t seg_count) {
72230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t id_range_offset_offset =
72330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      Offset::kFormat4EndCount + (2 * seg_count + 1) * DataSize::kUSHORT +
72430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      seg_count * DataSize::kSHORT;
72530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return id_range_offset_offset;
72630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
72730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
72830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
72930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::GlyphIdArrayOffset(int32_t seg_count) {
73030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t glyph_id_array_offset =
73130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      Offset::kFormat4EndCount + (3 * seg_count + 1) * DataSize::kUSHORT +
73230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      seg_count * DataSize::kSHORT;
73330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return glyph_id_array_offset;
73430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
73530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
73630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::EndCode(int32_t segment) {
73730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (IsValidIndex(segment)) {
73830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return EndCode(data_, seg_count_, segment);
73930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
74030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SFNTLY_NO_EXCEPTION)
74130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return -1;
74230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else
74330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  throw IllegalArgumentException();
74430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
74530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
74630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
74730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool CMapTable::CMapFormat4::IsValidIndex(int32_t segment) {
74830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (segment < 0 || segment >= seg_count_) {
74930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SFNTLY_NO_EXCEPTION)
75030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return false;
75130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else
75230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IllegalArgumentException();
75330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
75430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
75530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return true;
75630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
75730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
75830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::IdDelta(int32_t segment) {
75930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (IsValidIndex(segment))
76030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return IdDelta(data_, seg_count_, segment);
76130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return -1;
76230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
76330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
76430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::IdRangeOffset(int32_t segment) {
76530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (IsValidIndex(segment))
76630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return data_->ReadUShort(IdRangeOffsetLocation(segment));
76730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return -1;
76830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
76930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
77030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::IdRangeOffsetLocation(int32_t segment) {
77130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (IsValidIndex(segment))
77230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return IdRangeOffsetOffset(seg_count_) + segment * DataSize::kUSHORT;
77330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return -1;
77430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
77530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
77630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::GlyphIdArray(int32_t index) {
77730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data_->ReadUShort(glyph_id_array_offset_ + index * DataSize::kUSHORT);
77830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
77930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
78030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::Language() {
78130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return Language(data_);
78230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
78330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
78430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
78530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::CharacterIterator* CMapTable::CMapFormat4::Iterator() {
78630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return new CharacterIterator(this);
78730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
78830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
78930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
79030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapFormat4::CharacterIterator class
79130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
79230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::CharacterIterator::CharacterIterator(
79330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    CMapFormat4* parent)
79430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : parent_(parent),
79530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      segment_index_(0),
79630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      first_char_in_segment_(-1),
79730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      last_char_in_segment_(-1),
79830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      next_char_(-1),
79930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      next_char_set_(false) {
80030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
80130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
80230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool CMapTable::CMapFormat4::CharacterIterator::HasNext() {
80330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (next_char_set_)
80430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return true;
80530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  while (segment_index_ < parent_->seg_count_) {
80630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (first_char_in_segment_ < 0) {
80730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      first_char_in_segment_ = parent_->StartCode(segment_index_);
80830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      last_char_in_segment_ = parent_->EndCode(segment_index_);
80930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      next_char_ = first_char_in_segment_;
81030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      next_char_set_ = true;
81130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return true;
81230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
81330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (next_char_ < last_char_in_segment_) {
81430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      next_char_++;
81530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      next_char_set_ = true;
81630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return true;
81730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
81830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    segment_index_++;
81930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    first_char_in_segment_ = -1;
82030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
82130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return false;
82230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
82330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
82430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::CharacterIterator::Next() {
82530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!next_char_set_) {
82630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (!HasNext()) {
82730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined (SFNTLY_NO_EXCEPTION)
82830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return -1;
82930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else
83030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      throw NoSuchElementException("No more characters to iterate.");
83130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
83230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    }
83330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
83430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  next_char_set_ = false;
83530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return next_char_;
83630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
83730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
83830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
83930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapFormat4::Builder::Segment class
84030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
84130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Segment::Segment() {}
84230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
84330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Segment::Segment(Segment* other)
84430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : start_count_(other->start_count_),
84530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      end_count_(other->end_count_),
84630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      id_delta_(other->id_delta_),
84730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      id_range_offset_(other->id_range_offset_) {
84830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
84930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
85030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Segment::Segment(int32_t start_count,
85130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                  int32_t end_count,
85230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                  int32_t id_delta,
85330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                  int32_t id_range_offset)
85430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : start_count_(start_count),
85530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      end_count_(end_count),
85630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      id_delta_(id_delta),
85730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      id_range_offset_(id_range_offset) {
85830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
85930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
86030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Segment::~Segment() {}
86130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
86230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::Builder::Segment::start_count() {
86330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return start_count_;
86430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
86530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
86630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid
86730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Segment::set_start_count(int32_t start_count) {
86830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  start_count_ = start_count;
86930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
87030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
87130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::Builder::Segment::end_count() {
87230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return end_count_;
87330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
87430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
87530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid
87630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Segment::set_end_count(int32_t end_count) {
87730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  end_count_ = end_count;
87830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
87930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
88030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::Builder::Segment::id_delta() {
88130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return id_delta_;
88230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
88330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
88430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid
88530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Segment::set_id_delta(int32_t id_delta) {
88630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  id_delta_ = id_delta;
88730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
88830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
88930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::Builder::Segment::id_range_offset() {
89030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return id_range_offset_;
89130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
89230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
89330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid
89430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Segment::
89530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunset_id_range_offset(int32_t id_range_offset) {
89630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  id_range_offset_ = id_range_offset;
89730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
89830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
89930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
90030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH SegmentList*
90130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Segment::DeepCopy(SegmentList* original) {
90230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  SegmentList* list = new SegmentList;
90330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (SegmentList::iterator it = original->begin(),
90430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun           e = original->end(); it != e; ++it) {
90530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    list->push_back(*it);
90630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
90730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return list;
90830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
90930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
91030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
91130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::CMapFormat4::Builder class
91230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
91330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMapFormat4::Builder*
91430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::NewInstance(ReadableFontData* data,
91530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                             int32_t offset,
91630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                             const CMapId& cmap_id) {
91730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  ReadableFontDataPtr rdata;
91830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (data) {
91930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    rdata.Attach
92030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        (down_cast<ReadableFontData*>
92130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun         (data->Slice(offset,
92230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                      data->ReadUShort(offset + Offset::kFormat4Length))));
92330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
92430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return new Builder(rdata, CMapFormat::kFormat4, cmap_id);
92530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
92630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
92730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMapFormat4::Builder*
92830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::NewInstance(WritableFontData* data,
92930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                             int32_t offset,
93030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                             const CMapId& cmap_id) {
93130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  WritableFontDataPtr wdata;
93230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (data) {
93330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    wdata.Attach
93430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun        (down_cast<WritableFontData*>
93530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun         (data->Slice(offset,
93630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                      data->ReadUShort(offset + Offset::kFormat4Length))));
93730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
93830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return new Builder(wdata, CMapFormat::kFormat4, cmap_id);
93930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
94030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
94130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMapFormat4::Builder*
94230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::NewInstance(const CMapId& cmap_id) {
94330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return new Builder(cmap_id);
94430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
94530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
94630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Builder(ReadableFontData* data, int32_t offset,
94730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         const CMapId& cmap_id)
94830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMap::Builder(data, CMapFormat::kFormat4, cmap_id) {
94930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(offset);
95030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
95130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
95230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Builder(WritableFontData* data, int32_t offset,
95330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         const CMapId& cmap_id)
95430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMap::Builder(data, CMapFormat::kFormat4, cmap_id) {
95530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  UNREFERENCED_PARAMETER(offset);
95630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
95730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
95830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Builder(SegmentList* segments,
95930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         IntegerList* glyph_id_array,
96030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         const CMapId& cmap_id)
96130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMap::Builder(reinterpret_cast<ReadableFontData*>(NULL),
96230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                    CMapFormat::kFormat4, cmap_id),
96330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      segments_(segments->begin(), segments->end()),
96430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      glyph_id_array_(glyph_id_array->begin(), glyph_id_array->end()) {
96530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_model_changed();
96630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
96730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
96830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::Builder(const CMapId& cmap_id)
96930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : CMap::Builder(reinterpret_cast<ReadableFontData*>(NULL),
97030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                    CMapFormat::kFormat4, cmap_id) {
97130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
97230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
97330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::~Builder() {}
97430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
97530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid CMapTable::CMapFormat4::Builder::Initialize(ReadableFontData* data) {
97630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (data == NULL || data->Length() == 0)
97730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return;
97830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
97930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // build segments
98030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t seg_count = CMapFormat4::SegCount(data);
98130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t index = 0; index < seg_count; ++index) {
98230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    Ptr<Segment> segment = new Segment;
98330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    segment->set_start_count(CMapFormat4::StartCode(data, seg_count, index));
98430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined SFNTLY_DEBUG_CMAP
98530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    fprintf(stderr, "Segment %d; start %d\n", index, segment->start_count());
98630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
98730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    segment->set_end_count(CMapFormat4::EndCode(data, seg_count, index));
98830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    segment->set_id_delta(CMapFormat4::IdDelta(data, seg_count, index));
98930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    segment->set_id_range_offset(CMapFormat4::IdRangeOffset(data,
99030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                           seg_count,
99130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                                           index));
99230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    segments_.push_back(segment);
99330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
99430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
99530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // build glyph id array
99630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t glyph_id_array_offset = CMapFormat4::GlyphIdArrayOffset(seg_count);
99730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t glyph_id_array_length =
99830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      (CMapFormat4::Length(data) - glyph_id_array_offset)
99930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      / DataSize::kUSHORT;
100030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fprintf(stderr, "id array size %d\n", glyph_id_array_length);
100130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t i = 0; i < glyph_id_array_length; i += DataSize::kUSHORT) {
100230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    glyph_id_array_.push_back(data->ReadUShort(glyph_id_array_offset + i));
100330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
100430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
100530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
100630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunSegmentList* CMapTable::CMapFormat4::Builder::segments() {
100730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (segments_.empty()) {
100830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    Initialize(InternalReadData());
100930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    set_model_changed();
101030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
101130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return &segments_;
101230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
101330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
101430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid CMapTable::CMapFormat4::Builder::set_segments(SegmentList* segments) {
101530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  segments_.assign(segments->begin(), segments->end());
101630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_model_changed();
101730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
101830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
101930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunIntegerList* CMapTable::CMapFormat4::Builder::glyph_id_array() {
102030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (glyph_id_array_.empty()) {
102130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    Initialize(InternalReadData());
102230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    set_model_changed();
102330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
102430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return &glyph_id_array_;
102530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
102630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
102730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid CMapTable::CMapFormat4::Builder::
102830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunset_glyph_id_array(IntegerList* glyph_id_array) {
102930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  glyph_id_array_.assign(glyph_id_array->begin(), glyph_id_array->end());
103030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_model_changed();
103130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
103230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
103330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH FontDataTable*
103430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::SubBuildTable(ReadableFontData* data) {
103530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontDataTablePtr table = new CMapFormat4(data, cmap_id());
103630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return table.Detach();
103730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
103830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
103930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid CMapTable::CMapFormat4::Builder::SubDataSet() {
104030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  segments_.clear();
104130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  glyph_id_array_.clear();
104230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  set_model_changed();
104330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
104430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
104530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::CMapFormat4::Builder::SubDataSizeToSerialize() {
104630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!model_changed()) {
104730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return CMap::Builder::SubDataSizeToSerialize();
104830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
104930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t size = Offset::kFormat4FixedSize + segments_.size()
105030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      * (3 * DataSize::kUSHORT + DataSize::kSHORT)
105130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      + glyph_id_array_.size() * DataSize::kSHORT;
105230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return size;
105330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
105430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
105530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool CMapTable::CMapFormat4::Builder::SubReadyToSerialize() {
105630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!model_changed()) {
105730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return CMap::Builder::SubReadyToSerialize();
105830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
105930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!segments()->empty()) {
106030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return true;
106130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
106230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return false;
106330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
106430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
106530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t
106630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapFormat4::Builder::SubSerialize(WritableFontData* new_data) {
106730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (!model_changed()) {
106830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return CMap::Builder::SubSerialize(new_data);
106930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
107030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t index = 0;
107130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  index += new_data->WriteUShort(index, CMapFormat::kFormat4);
107230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  index += DataSize::kUSHORT;  // length - write this at the end
107330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  index += new_data->WriteUShort(index, language());
107430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
107530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t seg_count = segments_.size();
107630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  index += new_data->WriteUShort(index, seg_count * 2);
107730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t log2_seg_count = FontMath::Log2(seg_count);
107830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t search_range = 1 << (log2_seg_count + 1);
107930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  index += new_data->WriteUShort(index, search_range);
108030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t entry_selector = log2_seg_count;
108130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  index += new_data->WriteUShort(index, entry_selector);
108230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t range_shift = 2 * seg_count - search_range;
108330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  index += new_data->WriteUShort(index, range_shift);
108430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
108530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t i = 0; i < seg_count; ++i) {
108630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += new_data->WriteUShort(index, segments_[i]->end_count());
108730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
108830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  index += new_data->WriteUShort(index, 0);  // reserved ushort
108930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t i = 0; i < seg_count; ++i) {
109030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined SFNTLY_DEBUG_CMAP
109130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    fprintf(stderr, "Segment %d; start %d\n", i, segments_[i]->start_count());
109230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
109330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += new_data->WriteUShort(index, segments_[i]->start_count());
109430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
109530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t i = 0; i < seg_count; ++i) {
109630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += new_data->WriteShort(index, segments_[i]->id_delta());
109730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
109830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t i = 0; i < seg_count; ++i) {
109930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += new_data->WriteUShort(index, segments_[i]->id_range_offset());
110030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
110130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
110230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if defined SFNTLY_DEBUG_CMAP
110330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  fprintf(stderr, "Glyph id array size %lu\n", glyph_id_array_.size());
110430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
110530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (size_t i = 0; i < glyph_id_array_.size(); ++i) {
110630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index += new_data->WriteUShort(index, glyph_id_array_[i]);
110730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
110830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
110930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  new_data->WriteUShort(Offset::kFormat4Length, index);
111030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return index;
111130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
111230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
111330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun/******************************************************************************
111430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun * CMapTable::Builder class
111530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun ******************************************************************************/
111630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::Builder::Builder(Header* header, WritableFontData* data)
111730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : SubTableContainerTable::Builder(header, data), version_(0) {
111830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
111930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
112030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::Builder::Builder(Header* header, ReadableFontData* data)
112130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    : SubTableContainerTable::Builder(header, data), version_(0) {
112230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
112330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
112430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::Builder::~Builder() {
112530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
112630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
112730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::Builder::SubSerialize(WritableFontData* new_data) {
112830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t size = new_data->WriteUShort(CMapTable::Offset::kVersion,
112930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                       version_);
113030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  size += new_data->WriteUShort(CMapTable::Offset::kNumTables,
113130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                GetCMapBuilders()->size());
113230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
113330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t index_offset = size;
113430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  size += GetCMapBuilders()->size() * CMapTable::Offset::kEncodingRecordSize;
113530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (CMapBuilderMap::iterator it = GetCMapBuilders()->begin(),
113630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun           e = GetCMapBuilders()->end(); it != e; ++it) {
113730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    CMapBuilderPtr b = it->second;
113830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // header entry
113930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index_offset += new_data->WriteUShort(index_offset, b->platform_id());
114030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index_offset += new_data->WriteUShort(index_offset, b->encoding_id());
114130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    index_offset += new_data->WriteULong(index_offset, size);
114230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
114330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    // cmap
114430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    FontDataPtr slice;
114530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    slice.Attach(new_data->Slice(size));
114630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    size += b->SubSerialize(down_cast<WritableFontData*>(slice.p_));
114730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
114830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return size;
114930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
115030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
115130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunbool CMapTable::Builder::SubReadyToSerialize() {
115230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (GetCMapBuilders()->empty())
115330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return false;
115430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
115530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // check each table
115630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (CMapBuilderMap::iterator it = GetCMapBuilders()->begin(),
115730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun           e = GetCMapBuilders()->end(); it != e; ++it) {
115830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (!it->second->SubReadyToSerialize())
115930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      return false;
116030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
116130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return true;
116230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
116330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
116430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::Builder::SubDataSizeToSerialize() {
116530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (GetCMapBuilders()->empty())
116630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
116730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
116830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  bool variable = false;
116930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t size = CMapTable::Offset::kEncodingRecordStart +
117030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      GetCMapBuilders()->size() * CMapTable::Offset::kEncodingRecordSize;
117130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
117230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  // calculate size of each table
117330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (CMapBuilderMap::iterator it = GetCMapBuilders()->begin(),
117430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun           e = GetCMapBuilders()->end(); it != e; ++it) {
117530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    int32_t cmap_size = it->second->SubDataSizeToSerialize();
117630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    size += abs(cmap_size);
117730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    variable |= cmap_size <= 0;
117830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
117930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return variable ? -size : size;
118030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
118130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
118230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid CMapTable::Builder::SubDataSet() {
118330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  GetCMapBuilders()->clear();
118430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Table::Builder::set_model_changed();
118530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
118630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
118730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH FontDataTable*
118830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    CMapTable::Builder::SubBuildTable(ReadableFontData* data) {
118930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  FontDataTablePtr table = new CMapTable(header(), data);
119030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return table.Detach();
119130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
119230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
119330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::Builder*
119430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    CMapTable::Builder::CreateBuilder(Header* header,
119530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                      WritableFontData* data) {
119630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Ptr<CMapTable::Builder> builder;
119730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder = new CMapTable::Builder(header, data);
119830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder.Detach();
119930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
120030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
120130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
120230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCALLER_ATTACH CMapTable::CMap::Builder*
120330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    CMapTable::Builder::CMapBuilder(ReadableFontData* data, int32_t index) {
120430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (index < 0 || index > NumCMaps(data)) {
120530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#if !defined (SFNTLY_NO_EXCEPTION)
120630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    throw IndexOutOfBoundException(
120730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun              "CMap table is outside of the bounds of the known tables.");
120830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
120930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return NULL;
121030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
121130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
121230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t platform_id = data->ReadUShort(Offset::kEncodingRecordPlatformId +
121330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         OffsetForEncodingRecord(index));
121430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t encoding_id = data->ReadUShort(Offset::kEncodingRecordEncodingId +
121530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                         OffsetForEncodingRecord(index));
121630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t offset = data->ReadULongAsInt(Offset::kEncodingRecordOffset +
121730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                        OffsetForEncodingRecord(index));
121830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return CMap::Builder::GetBuilder(data, offset,
121930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun                                   NewCMapId(platform_id, encoding_id));
122030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
122130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
122230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun// static
122330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::Builder::NumCMaps(ReadableFontData* data) {
122430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (data == NULL) {
122530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return 0;
122630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
122730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return data->ReadUShort(Offset::kNumTables);
122830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
122930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
123030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunint32_t CMapTable::Builder::NumCMaps() {
123130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return GetCMapBuilders()->size();
123230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
123330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
123430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurunvoid CMapTable::Builder::Initialize(ReadableFontData* data) {
123530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  int32_t num_cmaps = NumCMaps(data);
123630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  for (int32_t i = 0; i < num_cmaps; ++i) {
123730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    CMapTable::CMap::Builder* cmap_builder = CMapBuilder(data, i);
123830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    if (!cmap_builder)
123930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun      continue;
124030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    cmap_builders_[cmap_builder->cmap_id()] = cmap_builder;
124130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
124230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
124330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
124430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::Builder* CMapTable::Builder::NewCMapBuilder(
124530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    const CMapId& cmap_id,
124630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    ReadableFontData* data) {
124730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Ptr<WritableFontData> wfd;
124830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  wfd.Attach(WritableFontData::CreateWritableFontData(data->Size()));
124930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  data->CopyTo(wfd.p_);
125030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapTable::CMapBuilderPtr builder;
125130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  builder.Attach(CMap::Builder::GetBuilder(wfd.p_, 0, cmap_id));
125230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapBuilderMap* cmap_builders = CMapTable::Builder::GetCMapBuilders();
125330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  cmap_builders->insert(std::make_pair(cmap_id, builder.p_));
125430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return builder.Detach();
125530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
125630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
125730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::Builder*
125830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::Builder::NewCMapBuilder(int32_t format, const CMapId& cmap_id) {
125930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  Ptr<CMapTable::CMap::Builder> cmap_builder;
126030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  cmap_builder.Attach(CMap::Builder::GetBuilder(format, cmap_id));
126130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapBuilderMap* cmap_builders = CMapTable::Builder::GetCMapBuilders();
126230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  cmap_builders->insert(std::make_pair(cmap_id, cmap_builder.p_));
126330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return cmap_builder.Detach();
126430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
126530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
126630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMap::Builder*
126730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::Builder::CMapBuilder(const CMapId& cmap_id) {
126830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapBuilderMap* cmap_builders = this->GetCMapBuilders();
126930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  CMapBuilderMap::iterator builder = cmap_builders->find(cmap_id);
127030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (builder != cmap_builders->end())
127130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    return builder->second;
127230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#ifndef SFNTLY_NO_EXCEPTION
127330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  throw NoSuchElementException("No builder found for cmap_id");
127430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#else
127530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return NULL;
127630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun#endif
127730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
127830d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
127930d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim GurunCMapTable::CMapBuilderMap* CMapTable::Builder::GetCMapBuilders() {
128030d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  if (cmap_builders_.empty()) {
128130d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    Initialize(InternalReadData());
128230d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun    set_model_changed();
128330d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  }
128430d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun  return &cmap_builders_;
128530d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}
128630d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun
128730d4e1f3d81ad9f7a1aa14ce6d2ceb5df56c15cdSelim Gurun}  // namespace sfntly
1288