1464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/*
2464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Copyright 2011 Google Inc. All Rights Reserved.
3464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *
4464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Licensed under the Apache License, Version 2.0 (the "License");
5464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * you may not use this file except in compliance with the License.
6464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * You may obtain a copy of the License at
7464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *
8464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *      http://www.apache.org/licenses/LICENSE-2.0
9464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com *
10464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * Unless required by applicable law or agreed to in writing, software
11464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * distributed under the License is distributed on an "AS IS" BASIS,
12464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * See the License for the specific language governing permissions and
14464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * limitations under the License.
15464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com */
16464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1779fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com// type.h needs to be included first because of building issues on Windows
1879fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com// Type aliases we delcare are defined in other headers and make the build
1979fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com// fail otherwise.
20ba91573e890c0871c6949e480a365bc85d408e77dfilimon@google.com#include "sfntly/port/type.h"
2179fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com#include "sfntly/table/core/cmap_table.h"
22464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
23bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#include <stdio.h>
24bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#include <stdlib.h>
25bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
26bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#include <utility>
276b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com
28464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/font.h"
29bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#include "sfntly/math/font_math.h"
30464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com#include "sfntly/port/endian.h"
31bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#include "sfntly/port/exception_type.h"
32bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#include "sfntly/table/core/name_table.h"
33464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
34464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comnamespace sfntly {
35464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
36464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comconst int32_t CMapTable::NOTDEF = 0;
37464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
38bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapId CMapTable::WINDOWS_BMP = {
39bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  PlatformId::kWindows,
40bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  WindowsEncodingId::kUnicodeUCS2
41bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com};
42bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapId CMapTable::WINDOWS_UCS4 = {
43bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  PlatformId::kWindows,
44bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  WindowsEncodingId::kUnicodeUCS4
45bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com};
46bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapId CMapTable::MAC_ROMAN = {
47bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  PlatformId::kWindows,
48bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  MacintoshEncodingId::kRoman
49bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com};
50bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
51464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/******************************************************************************
52464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * CMapTable class
53464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ******************************************************************************/
54bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapTable(Header* header, ReadableFontData* data)
55bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  : SubTableContainerTable(header, data) {
56bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
57bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
58464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comCMapTable::~CMapTable() {}
59464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
60bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCALLER_ATTACH CMapTable::CMap* CMapTable::GetCMap(const int32_t index) {
61bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (index < 0 || index > NumCMaps()) {
62bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#ifndef SFNTLY_NO_EXCEPTION
63bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    throw IndexOutOfBoundException("Requested CMap index is out of bounds.");
64bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#else
65bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    return NULL;
66bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
67bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
68bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  int32_t platform_id = PlatformId(index);
69bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  int32_t encoding_id = EncodingId(index);
70bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  CMapId cmap_id = NewCMapId(platform_id, encoding_id);
71bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  int32_t offset_ = Offset(index);
72bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  Ptr<FontDataTable::Builder> cmap_builder =
73bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      (CMap::Builder::GetBuilder(data_, offset_, cmap_id));
74bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (!cmap_builder) {
75bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#ifndef SFNTLY_NO_EXCEPTION
76bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    throw NoSuchElementException("Cannot find builder for requested CMap.");
77bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#else
78bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    return NULL;
79bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
80bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
8179fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com  return down_cast<CMapTable::CMap*>(cmap_builder->Build());
82bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
83bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
84bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCALLER_ATTACH CMapTable::CMap* CMapTable::GetCMap(const int32_t platform_id,
85bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                                  const int32_t encoding_id) {
86bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return GetCMap(NewCMapId(platform_id, encoding_id));
87bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
88bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
89bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCALLER_ATTACH CMapTable::CMap*
90bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::GetCMap(const CMapTable::CMapId cmap_id) {
91abb68accf47583a130eba5578baa89b4257e5679dfilimon@google.com  CMapIdFilter id_filter(cmap_id);
92abb68accf47583a130eba5578baa89b4257e5679dfilimon@google.com  CMapIterator cmap_iterator(this, &id_filter);
93bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  // There can only be one cmap with a particular CMapId
94bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (cmap_iterator.HasNext()) {
95bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    Ptr<CMapTable::CMap> cmap;
96bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    cmap.Attach(cmap_iterator.Next());
97bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    return cmap.Detach();
98bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
99bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#ifndef SFNTLY_NO_EXCEPTION
100bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  throw NoSuchElementException();
101bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#else
102bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return NULL;
103bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
104bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
105bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
106246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::Version() {
107246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data_->ReadUShort(Offset::kVersion);
108464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
109464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
110246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::NumCMaps() {
111246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data_->ReadUShort(Offset::kNumTables);
112464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
113464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
114246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCMapTable::CMapId CMapTable::GetCMapId(int32_t index) {
115bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return NewCMapId(PlatformId(index), EncodingId(index));
116464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
117464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
118246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::PlatformId(int32_t index) {
119246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data_->ReadUShort(Offset::kEncodingRecordPlatformId +
120246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           OffsetForEncodingRecord(index));
121464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
122464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
123246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::EncodingId(int32_t index) {
124246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data_->ReadUShort(Offset::kEncodingRecordEncodingId +
125246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           OffsetForEncodingRecord(index));
126464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
127464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
128246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::Offset(int32_t index) {
129246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data_->ReadULongAsInt(Offset::kEncodingRecordOffset +
130246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                               OffsetForEncodingRecord(index));
131464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
132464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
133246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::OffsetForEncodingRecord(int32_t index) {
134246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return Offset::kEncodingRecordStart + index * Offset::kEncodingRecordSize;
135464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
136464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
137bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapId CMapTable::NewCMapId(int32_t platform_id,
138bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                       int32_t encoding_id) {
139bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  CMapId result;
140bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  result.platform_id = platform_id;
141bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  result.encoding_id = encoding_id;
142bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return result;
143464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
144464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
145bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapId CMapTable::NewCMapId(const CMapId& obj) {
146bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  CMapId result;
147bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  result.platform_id = obj.platform_id;
148bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  result.encoding_id = obj.encoding_id;
149bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return result;
150464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
151464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
152bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com/******************************************************************************
153bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com * CMapTable::CMapIterator class
154bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com ******************************************************************************/
155bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapIterator::CMapIterator(CMapTable* table,
156bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                      const CMapFilter* filter)
157bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    : table_index_(0), filter_(filter), table_(table) {
158464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
159464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
160bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.combool CMapTable::CMapIterator::HasNext() {
161bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (!filter_) {
162bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    if (table_index_ < table_->NumCMaps()) {
163bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      return true;
164bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    }
165bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    return false;
166bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
167bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
168bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  for (; table_index_ < table_->NumCMaps(); ++table_index_) {
169bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    if (filter_->accept(table_->GetCMapId(table_index_))) {
170bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      return true;
171bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    }
172bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
173bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return false;
174464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
175464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
176bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCALLER_ATTACH CMapTable::CMap* CMapTable::CMapIterator::Next() {
177bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (!HasNext()) {
178bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#ifndef SFNTLY_NO_EXCEPTION
179bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    throw NoSuchElementException();
180bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#else
181bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    return NULL;
182bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
183bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
184bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  CMapPtr next_cmap;
185bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  next_cmap.Attach(table_->GetCMap(table_index_++));
186bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (next_cmap == NULL) {
187bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#ifndef SFNTLY_NO_EXCEPTION
188bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    throw NoSuchElementException("Error during the creation of the CMap");
189bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#else
190bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    return NULL;
191bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
192bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
193bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return next_cmap.Detach();
194464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
195464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
196bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com/******************************************************************************
197bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com * CMapTable::CMapId class
198bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com ******************************************************************************/
199464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
200464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/******************************************************************************
201464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * CMapTable::CMapIdComparator class
202464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ******************************************************************************/
203464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
204464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.combool CMapTable::CMapIdComparator::operator()(const CMapId& lhs,
205bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                             const CMapId& rhs) const {
206bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return ((lhs.platform_id << 8 | lhs.encoding_id) >
207bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      (rhs.platform_id << 8 | rhs.encoding_id));
208bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
209bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
210bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com/******************************************************************************
211bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com * CMapTable::CMapIdFilter class
212bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com ******************************************************************************/
213bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapIdFilter::CMapIdFilter(const CMapId wanted_id)
214bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    : wanted_id_(wanted_id),
215bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      comparator_(NULL) {
216bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
217bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
218bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapIdFilter::CMapIdFilter(const CMapId wanted_id,
219bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                      const CMapIdComparator* comparator)
220bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    : wanted_id_(wanted_id),
221bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      comparator_(comparator) {
222bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
223bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
224bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.combool CMapTable::CMapIdFilter::accept(const CMapId& cmap_id) const {
225bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (!comparator_)
226bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    return wanted_id_ == cmap_id;
227bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return (*comparator_)(wanted_id_, cmap_id);
228464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
229464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
230464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/******************************************************************************
231464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * CMapTable::CMap class
232464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ******************************************************************************/
233464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.comCMapTable::CMap::CMap(ReadableFontData* data, int32_t format,
234464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                      const CMapId& cmap_id)
235464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    : SubTable(data), format_(format), cmap_id_(cmap_id) {
236464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
237464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
238246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCMapTable::CMap::~CMap() {
239246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
240464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
241464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/******************************************************************************
242464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * CMapTable::CMap::Builder class
243464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ******************************************************************************/
244246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCMapTable::CMap::Builder::~Builder() {
245246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
246246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
247246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH CMapTable::CMap::Builder*
248bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    CMapTable::CMap::Builder::GetBuilder(ReadableFontData* data, int32_t offset,
249b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                         const CMapId& cmap_id) {
250246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  // NOT IMPLEMENTED: Java enum value validation
251246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t format = data->ReadUShort(offset);
252246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  CMapBuilderPtr builder;
253246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  switch (format) {
254246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    case CMapFormat::kFormat0:
255bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      builder.Attach(CMapFormat0::Builder::NewInstance(data, offset, cmap_id));
256246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com      break;
257246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    case CMapFormat::kFormat2:
258bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#if defined (SFNTLY_DEBUG_CMAP)
259bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      fprintf(stderr, "Requesting Format2 builder, but it's unsupported; "
260bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com              "returning NULL\n");
261bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
262bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      break;
263bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    case CMapFormat::kFormat4:
264a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      builder.Attach(CMapFormat4::Builder::NewInstance(data, offset, cmap_id));
265246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com      break;
266246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    default:
267bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#ifdef SFNTLY_DEBUG_CMAP
268bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      fprintf(stderr, "Unknown builder format requested\n");
269bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
270bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      break;
271bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
272bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return builder.Detach();
273bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
274bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
275bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCALLER_ATTACH CMapTable::CMap::Builder*
276bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMap::Builder::GetBuilder(int32_t format, const CMapId& cmap_id) {
277bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  Ptr<CMapTable::CMap::Builder> builder;
278bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  switch (format) {
279bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    case CMapFormat::kFormat0:
280bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      builder.Attach(CMapFormat0::Builder::NewInstance(cmap_id));
281bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      break;
282bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    case CMapFormat::kFormat2:
283bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#if defined (SFNTLY_DEBUG_CMAP)
284bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      fprintf(stderr, "Requesting Format2 builder, but it's unsupported; "
285bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com              "returning NULL\n");
286bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
287bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      break;
288bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    case CMapFormat::kFormat4:
289a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      builder.Attach(CMapFormat4::Builder::NewInstance(cmap_id));
290bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      break;
291bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    default:
292bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#ifdef SFNTLY_DEBUG_CMAP
293bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      fprintf(stderr, "Unknown builder format requested\n");
294bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
295246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com      break;
296246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  }
297246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return builder.Detach();
298246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
299246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
300b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCMapTable::CMap::Builder::Builder(ReadableFontData* data,
301b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                  int32_t format,
3026b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com                                  const CMapId& cmap_id)
303b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    : SubTable::Builder(data),
304246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com      format_(format),
305bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      cmap_id_(cmap_id),
306bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      language_(0) {
307464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
308464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
309b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCMapTable::CMap::Builder::Builder(WritableFontData* data,
310b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                  int32_t format,
3116b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com                                  const CMapId& cmap_id)
312b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    : SubTable::Builder(data),
313246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com      format_(format),
314bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      cmap_id_(cmap_id),
315bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      language_(0) {
316464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
317464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
318246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMap::Builder::SubSerialize(WritableFontData* new_data) {
319246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return InternalReadData()->CopyTo(new_data);
320464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
321464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
322246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool CMapTable::CMap::Builder::SubReadyToSerialize() {
323464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return true;
324464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
325464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
326246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMap::Builder::SubDataSizeToSerialize() {
327bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  ReadableFontDataPtr read_data = InternalReadData();
328bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (!read_data)
329bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    return 0;
330bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return read_data->Length();
331464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
332464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
333246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid CMapTable::CMap::Builder::SubDataSet() {
334464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  // NOP
335464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
336464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
337464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/******************************************************************************
338246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com * CMapTable::CMapFormat0
339464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ******************************************************************************/
340246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCMapTable::CMapFormat0::~CMapFormat0() {
341464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
342464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
343246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMapFormat0::Language() {
344246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return 0;
345246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
346464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
347246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMapFormat0::GlyphId(int32_t character) {
348464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (character < 0 || character > 255) {
349464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return CMapTable::NOTDEF;
350464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
351bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return data_->ReadUByte(character + Offset::kFormat0GlyphIdArray);
352464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
353464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
354246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCMapTable::CMapFormat0::CMapFormat0(ReadableFontData* data,
355246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                                    const CMapId& cmap_id)
356246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    : CMap(data, CMapFormat::kFormat0, cmap_id) {
357464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
358464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
35979fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.comCMapTable::CMap::CharacterIterator* CMapTable::CMapFormat0::Iterator() {
36079fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com  return new CMapTable::CMapFormat0::CharacterIterator(0, 0xff);
361bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
362bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
363bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
364bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com/******************************************************************************
365bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com * CMapTable::CMapFormat0::CharacterIterator
366bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com ******************************************************************************/
367bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapFormat0::CharacterIterator::CharacterIterator(int32_t start,
368bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                                             int32_t end)
369bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    : character_(start),
370bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    max_character_(end) {
371bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
372bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
373bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapFormat0::CharacterIterator::~CharacterIterator() {}
374bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
375bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.combool CMapTable::CMapFormat0::CharacterIterator::HasNext() {
376bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return character_ < max_character_;
377bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
378bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
379bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comint32_t CMapTable::CMapFormat0::CharacterIterator::Next() {
380bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (HasNext())
381bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    return character_++;
382bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#ifndef SFNTLY_NO_EXCEPTION
383bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  throw NoSuchElementException("No more characters to iterate.");
384bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
385bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return -1;
386bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
387bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
388246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com/******************************************************************************
389246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com * CMapTable::CMapFormat0::Builder
390246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ******************************************************************************/
391bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com// static
392bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCALLER_ATTACH CMapTable::CMapFormat0::Builder*
393bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapFormat0::Builder::NewInstance(WritableFontData* data,
394bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                             int32_t offset,
395bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                             const CMapId& cmap_id) {
396bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  WritableFontDataPtr wdata;
397bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (data) {
398bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    wdata.Attach(down_cast<WritableFontData*>(
399bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com        data->Slice(offset,
400bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                    data->ReadUShort(offset + Offset::kFormat0Length))));
401bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
402bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return new Builder(wdata, CMapFormat::kFormat0, cmap_id);
403bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
404bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
405bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com// static
406bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCALLER_ATTACH CMapTable::CMapFormat0::Builder*
407bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapFormat0::Builder::NewInstance(ReadableFontData* data,
408bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                             int32_t offset,
409bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                             const CMapId& cmap_id) {
410bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  ReadableFontDataPtr rdata;
411bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (data) {
412bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    rdata.Attach(down_cast<ReadableFontData*>(
413bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com        data->Slice(offset,
414bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                    data->ReadUShort(offset + Offset::kFormat0Length))));
415bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
416bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return new Builder(rdata, CMapFormat::kFormat0, cmap_id);
417464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
418464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
419bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com// static
420bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCALLER_ATTACH CMapTable::CMapFormat0::Builder*
421bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapFormat0::Builder::NewInstance(const CMapId& cmap_id) {
422bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return new Builder(cmap_id);
423bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
424bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
425bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com// Always call NewInstance instead of the constructor for creating a new builder
426bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com// object! This refactoring avoids memory leaks when slicing the font data.
427bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapFormat0::Builder::Builder(WritableFontData* data, int32_t offset,
428b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                         const CMapId& cmap_id)
429bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    : CMapTable::CMap::Builder(data, CMapFormat::kFormat0, cmap_id) {
430bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  UNREFERENCED_PARAMETER(offset);
431bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
432bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
433bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapFormat0::Builder::Builder(
434bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    ReadableFontData* data,
435bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    int32_t offset,
436bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    const CMapId& cmap_id)
437bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    : CMapTable::CMap::Builder(data, CMapFormat::kFormat0, cmap_id) {
438bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  UNREFERENCED_PARAMETER(offset);
439bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
440bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
44179fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.comCMapTable::CMapFormat0::Builder::Builder(const CMapId& cmap_id)
442bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    : CMap::Builder(reinterpret_cast<ReadableFontData*>(NULL),
443bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                    CMapFormat::kFormat0,
444bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                    cmap_id) {
445464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
446464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
447246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCMapTable::CMapFormat0::Builder::~Builder() {
448246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
449464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
450246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH FontDataTable*
451246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    CMapTable::CMapFormat0::Builder::SubBuildTable(ReadableFontData* data) {
452246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  FontDataTablePtr table = new CMapFormat0(data, cmap_id());
453246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return table.Detach();
454464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
455464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
456464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/******************************************************************************
457246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com * CMapTable::CMapFormat2
458464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ******************************************************************************/
459246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCMapTable::CMapFormat2::~CMapFormat2() {
460464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
461464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
462246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMapFormat2::Language() {
463246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return 0;
464464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
465464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
466246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMapFormat2::GlyphId(int32_t character) {
467464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (character > 0xffff) {
468464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return CMapTable::NOTDEF;
469464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
470464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
471246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  uint32_t c = ToBE32(character);
472464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  byte_t high_byte = (c >> 8) & 0xff;
473464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  byte_t low_byte = c & 0xff;
474246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t offset = SubHeaderOffset(high_byte);
475464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
476464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (offset == 0) {
477464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    low_byte = high_byte;
478464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    high_byte = 0;
479464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
480464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
481246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t first_code = FirstCode(high_byte);
482246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t entry_count = EntryCount(high_byte);
483464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
484464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (low_byte < first_code || low_byte >= first_code + entry_count) {
485464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return CMapTable::NOTDEF;
486464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
487464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
488246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t id_range_offset = IdRangeOffset(high_byte);
489464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
490464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  // position of idRangeOffset + value of idRangeOffset + index for low byte
491464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  // = firstcode
492464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  int32_t p_location = (offset + Offset::kFormat2SubHeader_idRangeOffset) +
4936b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com      id_range_offset +
4946b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com      (low_byte - first_code) * DataSize::kUSHORT;
495246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int p = data_->ReadUShort(p_location);
496464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (p == 0) {
497464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return CMapTable::NOTDEF;
498464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
499464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
500464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (offset == 0) {
501464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return p;
502464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
503246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int id_delta = IdDelta(high_byte);
504464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  return (p + id_delta) % 65536;
505464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
506464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
507246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMapFormat2::BytesConsumed(int32_t character) {
508246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  uint32_t c = ToBE32(character);
509246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t high_byte = (c >> 8) & 0xff;
510246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t offset = SubHeaderOffset(high_byte);
511246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return (offset == 0) ? 1 : 2;
512246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
513246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
514246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCMapTable::CMapFormat2::CMapFormat2(ReadableFontData* data,
515246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                                    const CMapId& cmap_id)
516246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    : CMap(data, CMapFormat::kFormat2, cmap_id) {
517246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
518246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
519246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMapFormat2::SubHeaderOffset(int32_t sub_header_index) {
520246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data_->ReadUShort(Offset::kFormat2SubHeaderKeys +
521246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           sub_header_index * DataSize::kUSHORT);
522246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
523246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
524246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMapFormat2::FirstCode(int32_t sub_header_index) {
525246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t sub_header_offset = SubHeaderOffset(sub_header_index);
526246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data_->ReadUShort(sub_header_offset +
527246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           Offset::kFormat2SubHeaderKeys +
528246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           Offset::kFormat2SubHeader_firstCode);
529246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
530246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
531246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMapFormat2::EntryCount(int32_t sub_header_index) {
532246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t sub_header_offset = SubHeaderOffset(sub_header_index);
533246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data_->ReadUShort(sub_header_offset +
534246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           Offset::kFormat2SubHeaderKeys +
535246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           Offset::kFormat2SubHeader_entryCount);
536246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
537246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
538246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMapFormat2::IdRangeOffset(int32_t sub_header_index) {
539246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t sub_header_offset = SubHeaderOffset(sub_header_index);
540246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data_->ReadUShort(sub_header_offset +
541246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           Offset::kFormat2SubHeaderKeys +
542246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           Offset::kFormat2SubHeader_idRangeOffset);
543246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
544246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
545246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::CMapFormat2::IdDelta(int32_t sub_header_index) {
546246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t sub_header_offset = SubHeaderOffset(sub_header_index);
547246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data_->ReadUShort(sub_header_offset +
548246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           Offset::kFormat2SubHeaderKeys +
549246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                           Offset::kFormat2SubHeader_idDelta);
550464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
551464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
55279fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.comCMapTable::CMap::CharacterIterator* CMapTable::CMapFormat2::Iterator() {
55379fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com  // UNIMPLEMENTED
55479fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com  return NULL;
55579fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com}
55679fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com
557246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com/******************************************************************************
558246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com * CMapTable::CMapFormat2::Builder
559246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com ******************************************************************************/
560b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCMapTable::CMapFormat2::Builder::Builder(WritableFontData* data,
561b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                         int32_t offset,
562b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                         const CMapId& cmap_id)
563b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    : CMapTable::CMap::Builder(data ? down_cast<WritableFontData*>(
564246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                                   data->Slice(offset, data->ReadUShort(
5656b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com                                       offset + Offset::kFormat0Length)))
5666b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com                               : reinterpret_cast<WritableFontData*>(NULL),
567464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                               CMapFormat::kFormat2, cmap_id) {
568464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix.
569464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
570464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
571b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCMapTable::CMapFormat2::Builder::Builder(ReadableFontData* data,
572b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                         int32_t offset,
573b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                         const CMapId& cmap_id)
574b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    : CMapTable::CMap::Builder(data ? down_cast<ReadableFontData*>(
575246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com                                   data->Slice(offset, data->ReadUShort(
5766b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com                                       offset + Offset::kFormat0Length)))
5776b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com                               : reinterpret_cast<ReadableFontData*>(NULL),
578464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com                               CMapFormat::kFormat2, cmap_id) {
579464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  // TODO(arthurhsu): FIXIT: heavy lifting and leak, need fix.
580464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
581464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
582246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCMapTable::CMapFormat2::Builder::~Builder() {
583246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
584464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
585246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH FontDataTable*
586246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    CMapTable::CMapFormat2::Builder::SubBuildTable(ReadableFontData* data) {
587246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  FontDataTablePtr table = new CMapFormat2(data, cmap_id());
588246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return table.Detach();
589464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
590464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
591464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com/******************************************************************************
592a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com * CMapTable::CMapFormat4
593a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com ******************************************************************************/
594a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::CMapFormat4(ReadableFontData* data,
595a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                    const CMapId& cmap_id)
5967bb24d45ed7d04c85f27ecdc3866153a8350ed44dfilimon@google.com    : CMap(data, CMapFormat::kFormat4, cmap_id),
597a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      seg_count_(SegCount(data)),
598a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      start_code_offset_(StartCodeOffset(seg_count_)),
599a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      id_delta_offset_(IdDeltaOffset(seg_count_)),
600a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      glyph_id_array_offset_(GlyphIdArrayOffset(seg_count_)) {
601a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
602a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
603a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::~CMapFormat4() {
604a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
605a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
606a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::GlyphId(int32_t character) {
607a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t segment = data_->SearchUShort(StartCodeOffset(seg_count_),
608a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                        DataSize::kUSHORT,
609a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                        Offset::kFormat4EndCount,
610a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                        DataSize::kUSHORT,
611a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                        seg_count_,
612a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                        character);
613a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (segment == -1) {
614a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return CMapTable::NOTDEF;
615a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
616a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t start_code = StartCode(segment);
617a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return RetrieveGlyphId(segment, start_code, character);
618a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
619a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
620a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::RetrieveGlyphId(int32_t segment,
621a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                                int32_t start_code,
622a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                                int32_t character) {
623a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (character < start_code) {
624a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return CMapTable::NOTDEF;
625a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
626a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t id_range_offset = IdRangeOffset(segment);
627a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (id_range_offset == 0) {
628a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return (character + IdDelta(segment)) % 65536;
629a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
630a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return data_->ReadUShort(id_range_offset +
631a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                           IdRangeOffsetLocation(segment) +
632a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                           2 * (character - start_code));
633a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
634a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
635a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::seg_count() {
636a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return seg_count_;
637a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
638a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
639a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::Length() {
640a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return Length(data_);
641a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
642a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
643a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::StartCode(int32_t segment) {
644a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (!IsValidIndex(segment)) {
645a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return -1;
646a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
647a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return StartCode(data_.p_, seg_count_, segment);
648a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
649a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
650a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
651a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::Language(ReadableFontData* data) {
652a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t language = data->ReadUShort(Offset::kFormat4Language);
653a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return language;
654a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
655a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
656a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
657a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::Length(ReadableFontData* data) {
658a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t length = data->ReadUShort(Offset::kFormat4Length);
659a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return length;
660a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
661a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
662a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
663a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::SegCount(ReadableFontData* data) {
664a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t seg_count = data->ReadUShort(Offset::kFormat4SegCountX2) / 2;
665a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return seg_count;
666a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
667a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
668a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
669a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::StartCode(ReadableFontData* data,
670a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                          int32_t seg_count,
671a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                          int32_t index) {
672a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t start_code = data->ReadUShort(StartCodeOffset(seg_count) +
673a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                        index * DataSize::kUSHORT);
674a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return start_code;
675a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
676a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
677a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
678a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::StartCodeOffset(int32_t seg_count) {
679a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t start_code_offset = Offset::kFormat4EndCount +
680a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      (seg_count + 1) * DataSize::kUSHORT;
681a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return start_code_offset;
682a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
683a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
684a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
685a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::EndCode(ReadableFontData* data,
686a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                        int32_t seg_count,
687a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                        int32_t index) {
688ce2471a4cd4a9d39f3e761bfe6739fb454bf0dc3dfilimon@google.com  UNREFERENCED_PARAMETER(seg_count);
689a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t end_code = data->ReadUShort(Offset::kFormat4EndCount +
690a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                      index * DataSize::kUSHORT);
691a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return end_code;
692a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
693a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
694a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
695a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::IdDelta(ReadableFontData* data,
696a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                        int32_t seg_count,
697a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                        int32_t index) {
698a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t id_delta = data->ReadUShort(IdDeltaOffset(seg_count) +
699a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                      index * DataSize::kUSHORT);
700a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return id_delta;
701a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
702a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
703a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
704a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::IdDeltaOffset(int32_t seg_count) {
705a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t id_delta_offset =
706a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      Offset::kFormat4EndCount + (2 * seg_count + 1) * DataSize::kUSHORT;
707a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return id_delta_offset;
708a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
709a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
710a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
711a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::IdRangeOffset(ReadableFontData* data,
712a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                              int32_t seg_count,
713a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                              int32_t index) {
714a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t id_range_offset =
715a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      data->ReadUShort(IdRangeOffsetOffset(seg_count)
716a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                       + index * DataSize::kUSHORT);
717a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return id_range_offset;
718a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
719a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
720a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
721a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::IdRangeOffsetOffset(int32_t seg_count) {
722a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t id_range_offset_offset =
723a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      Offset::kFormat4EndCount + (2 * seg_count + 1) * DataSize::kUSHORT +
724a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      seg_count * DataSize::kSHORT;
725a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return id_range_offset_offset;
726a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
727a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
728a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
729a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::GlyphIdArrayOffset(int32_t seg_count) {
730a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t glyph_id_array_offset =
731a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      Offset::kFormat4EndCount + (3 * seg_count + 1) * DataSize::kUSHORT +
732a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      seg_count * DataSize::kSHORT;
733a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return glyph_id_array_offset;
734a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
735a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
736a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::EndCode(int32_t segment) {
737a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (IsValidIndex(segment)) {
738a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return EndCode(data_, seg_count_, segment);
739a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
740a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#if defined (SFNTLY_NO_EXCEPTION)
741a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return -1;
742a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#else
743a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  throw IllegalArgumentException();
744a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#endif
745a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
746a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
747a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.combool CMapTable::CMapFormat4::IsValidIndex(int32_t segment) {
748a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (segment < 0 || segment >= seg_count_) {
749a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#if defined (SFNTLY_NO_EXCEPTION)
750a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return false;
751a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#else
752a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    throw IllegalArgumentException();
753a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#endif
754a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
755a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return true;
756a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
757a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
758a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::IdDelta(int32_t segment) {
759a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (IsValidIndex(segment))
760a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return IdDelta(data_, seg_count_, segment);
761a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return -1;
762a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
763a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
764a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::IdRangeOffset(int32_t segment) {
765a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (IsValidIndex(segment))
766a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return data_->ReadUShort(IdRangeOffsetLocation(segment));
767a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return -1;
768a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
769a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
770a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::IdRangeOffsetLocation(int32_t segment) {
771a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (IsValidIndex(segment))
772a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return IdRangeOffsetOffset(seg_count_) + segment * DataSize::kUSHORT;
773a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return -1;
774a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
775a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
776a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::GlyphIdArray(int32_t index) {
777a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return data_->ReadUShort(glyph_id_array_offset_ + index * DataSize::kUSHORT);
778a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
779a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
780a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::Language() {
781a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return Language(data_);
782a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
783a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
784a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
785a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMap::CharacterIterator* CMapTable::CMapFormat4::Iterator() {
786a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return new CharacterIterator(this);
787a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
788a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
789a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com/******************************************************************************
790a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com * CMapTable::CMapFormat4::CharacterIterator class
791a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com ******************************************************************************/
792a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::CharacterIterator::CharacterIterator(
793a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    CMapFormat4* parent)
794a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    : parent_(parent),
795a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      segment_index_(0),
796a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      first_char_in_segment_(-1),
797a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      last_char_in_segment_(-1),
798a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      next_char_(-1),
799a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      next_char_set_(false) {
800a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
801a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
802a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.combool CMapTable::CMapFormat4::CharacterIterator::HasNext() {
803a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (next_char_set_)
804a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return true;
805a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  while (segment_index_ < parent_->seg_count_) {
806a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    if (first_char_in_segment_ < 0) {
807a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      first_char_in_segment_ = parent_->StartCode(segment_index_);
808a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      last_char_in_segment_ = parent_->EndCode(segment_index_);
809a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      next_char_ = first_char_in_segment_;
810a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      next_char_set_ = true;
811a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      return true;
812a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    }
813a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    if (next_char_ < last_char_in_segment_) {
814a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      next_char_++;
815a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      next_char_set_ = true;
816a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      return true;
817a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    }
818a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    segment_index_++;
819a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    first_char_in_segment_ = -1;
820a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
821a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return false;
822a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
823a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
824a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::CharacterIterator::Next() {
825a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (!next_char_set_) {
826a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    if (!HasNext()) {
827a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#if defined (SFNTLY_NO_EXCEPTION)
828a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      return -1;
829a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#else
830a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      throw NoSuchElementException("No more characters to iterate.");
831a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#endif
832a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    }
833a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
834a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  next_char_set_ = false;
835a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return next_char_;
836a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
837a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
838a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com/******************************************************************************
839a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com * CMapTable::CMapFormat4::Builder::Segment class
840a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com ******************************************************************************/
841a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Segment::Segment() {}
842a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
843a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Segment::Segment(Segment* other)
844a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    : start_count_(other->start_count_),
845a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      end_count_(other->end_count_),
846a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      id_delta_(other->id_delta_),
847a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      id_range_offset_(other->id_range_offset_) {
848a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
849a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
850a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Segment::Segment(int32_t start_count,
851a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                                  int32_t end_count,
852a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                                  int32_t id_delta,
853a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                                  int32_t id_range_offset)
854a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    : start_count_(start_count),
855a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      end_count_(end_count),
856a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      id_delta_(id_delta),
857a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      id_range_offset_(id_range_offset) {
858a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
859a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
860a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Segment::~Segment() {}
861a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
862a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::Builder::Segment::start_count() {
863a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return start_count_;
864a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
865a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
866a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comvoid
867a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Segment::set_start_count(int32_t start_count) {
868a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  start_count_ = start_count;
869a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
870a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
871a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::Builder::Segment::end_count() {
872a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return end_count_;
873a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
874a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
875a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comvoid
876a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Segment::set_end_count(int32_t end_count) {
877a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  end_count_ = end_count;
878a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
879a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
880a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::Builder::Segment::id_delta() {
881a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return id_delta_;
882a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
883a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
884a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comvoid
885a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Segment::set_id_delta(int32_t id_delta) {
886a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  id_delta_ = id_delta;
887a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
888a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
889a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::Builder::Segment::id_range_offset() {
890a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return id_range_offset_;
891a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
892a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
893a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comvoid
894a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Segment::
895a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comset_id_range_offset(int32_t id_range_offset) {
896a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  id_range_offset_ = id_range_offset;
897a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
898a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
899a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com// static
900a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCALLER_ATTACH SegmentList*
901a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Segment::DeepCopy(SegmentList* original) {
902a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  SegmentList* list = new SegmentList;
903a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  for (SegmentList::iterator it = original->begin(),
904a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com           e = original->end(); it != e; ++it) {
905a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    list->push_back(*it);
906a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
907a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return list;
908a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
909a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
910a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com/******************************************************************************
911a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com * CMapTable::CMapFormat4::Builder class
912a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com ******************************************************************************/
913a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCALLER_ATTACH CMapTable::CMapFormat4::Builder*
914a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::NewInstance(ReadableFontData* data,
915a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                             int32_t offset,
916a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                             const CMapId& cmap_id) {
917a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  ReadableFontDataPtr rdata;
918a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (data) {
919a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    rdata.Attach
920a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com        (down_cast<ReadableFontData*>
921a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com         (data->Slice(offset,
922a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                      data->ReadUShort(offset + Offset::kFormat4Length))));
923a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
924a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return new Builder(rdata, CMapFormat::kFormat4, cmap_id);
925a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
926a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
927a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCALLER_ATTACH CMapTable::CMapFormat4::Builder*
928a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::NewInstance(WritableFontData* data,
929a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                             int32_t offset,
930a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                             const CMapId& cmap_id) {
931a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  WritableFontDataPtr wdata;
932a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (data) {
933a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    wdata.Attach
934a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com        (down_cast<WritableFontData*>
935a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com         (data->Slice(offset,
936a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                      data->ReadUShort(offset + Offset::kFormat4Length))));
937a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
938a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return new Builder(wdata, CMapFormat::kFormat4, cmap_id);
939a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
940a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
941a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCALLER_ATTACH CMapTable::CMapFormat4::Builder*
942a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::NewInstance(const CMapId& cmap_id) {
943a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return new Builder(cmap_id);
944a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
945a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
946a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Builder(ReadableFontData* data, int32_t offset,
947a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                         const CMapId& cmap_id)
948a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    : CMap::Builder(data, CMapFormat::kFormat4, cmap_id) {
949ce2471a4cd4a9d39f3e761bfe6739fb454bf0dc3dfilimon@google.com  UNREFERENCED_PARAMETER(offset);
950a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
951a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
952a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Builder(WritableFontData* data, int32_t offset,
953a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                         const CMapId& cmap_id)
954a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    : CMap::Builder(data, CMapFormat::kFormat4, cmap_id) {
955ce2471a4cd4a9d39f3e761bfe6739fb454bf0dc3dfilimon@google.com  UNREFERENCED_PARAMETER(offset);
956a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
957a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
958a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Builder(SegmentList* segments,
959a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                         IntegerList* glyph_id_array,
960a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                         const CMapId& cmap_id)
961a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    : CMap::Builder(reinterpret_cast<ReadableFontData*>(NULL),
962a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                    CMapFormat::kFormat4, cmap_id),
963a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      segments_(segments->begin(), segments->end()),
964a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      glyph_id_array_(glyph_id_array->begin(), glyph_id_array->end()) {
965a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  set_model_changed();
966a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
967a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
968a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::Builder(const CMapId& cmap_id)
969a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    : CMap::Builder(reinterpret_cast<ReadableFontData*>(NULL),
970a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                    CMapFormat::kFormat4, cmap_id) {
971a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
972a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
973a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::~Builder() {}
974a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
975a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comvoid CMapTable::CMapFormat4::Builder::Initialize(ReadableFontData* data) {
976a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (data == NULL || data->Length() == 0)
977a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return;
978a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
979a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  // build segments
980a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t seg_count = CMapFormat4::SegCount(data);
981a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  for (int32_t index = 0; index < seg_count; ++index) {
982a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    Ptr<Segment> segment = new Segment;
983a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    segment->set_start_count(CMapFormat4::StartCode(data, seg_count, index));
984a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#if defined SFNTLY_DEBUG_CMAP
985a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    fprintf(stderr, "Segment %d; start %d\n", index, segment->start_count());
986a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#endif
987a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    segment->set_end_count(CMapFormat4::EndCode(data, seg_count, index));
988a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    segment->set_id_delta(CMapFormat4::IdDelta(data, seg_count, index));
989a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    segment->set_id_range_offset(CMapFormat4::IdRangeOffset(data,
990a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                                           seg_count,
991a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com                                                           index));
992a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    segments_.push_back(segment);
993a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
994a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
995a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  // build glyph id array
996a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t glyph_id_array_offset = CMapFormat4::GlyphIdArrayOffset(seg_count);
997a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t glyph_id_array_length =
998a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      (CMapFormat4::Length(data) - glyph_id_array_offset)
999a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      / DataSize::kUSHORT;
1000a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  fprintf(stderr, "id array size %d\n", glyph_id_array_length);
1001a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  for (int32_t i = 0; i < glyph_id_array_length; i += DataSize::kUSHORT) {
1002a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    glyph_id_array_.push_back(data->ReadUShort(glyph_id_array_offset + i));
1003a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1004a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
1005a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1006a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comSegmentList* CMapTable::CMapFormat4::Builder::segments() {
1007a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (segments_.empty()) {
1008a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    Initialize(InternalReadData());
1009a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    set_model_changed();
1010a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1011a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return &segments_;
1012a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
1013a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1014a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comvoid CMapTable::CMapFormat4::Builder::set_segments(SegmentList* segments) {
1015a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  segments_.assign(segments->begin(), segments->end());
1016a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  set_model_changed();
1017a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
1018a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1019a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comIntegerList* CMapTable::CMapFormat4::Builder::glyph_id_array() {
1020a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (glyph_id_array_.empty()) {
1021a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    Initialize(InternalReadData());
1022a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    set_model_changed();
1023a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1024a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return &glyph_id_array_;
1025a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
1026a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1027a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comvoid CMapTable::CMapFormat4::Builder::
1028a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comset_glyph_id_array(IntegerList* glyph_id_array) {
1029a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  glyph_id_array_.assign(glyph_id_array->begin(), glyph_id_array->end());
1030a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  set_model_changed();
1031a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
1032a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1033a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCALLER_ATTACH FontDataTable*
1034a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::SubBuildTable(ReadableFontData* data) {
1035a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  FontDataTablePtr table = new CMapFormat4(data, cmap_id());
1036a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return table.Detach();
1037a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
1038a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1039a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comvoid CMapTable::CMapFormat4::Builder::SubDataSet() {
1040a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  segments_.clear();
1041a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  glyph_id_array_.clear();
1042a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  set_model_changed();
1043a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
1044a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1045a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t CMapTable::CMapFormat4::Builder::SubDataSizeToSerialize() {
1046a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (!model_changed()) {
1047a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return CMap::Builder::SubDataSizeToSerialize();
1048a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1049a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t size = Offset::kFormat4FixedSize + segments_.size()
1050a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      * (3 * DataSize::kUSHORT + DataSize::kSHORT)
1051a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com      + glyph_id_array_.size() * DataSize::kSHORT;
1052a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return size;
1053a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
1054a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1055a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.combool CMapTable::CMapFormat4::Builder::SubReadyToSerialize() {
1056a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (!model_changed()) {
1057a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return CMap::Builder::SubReadyToSerialize();
1058a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1059a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (!segments()->empty()) {
1060a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return true;
1061a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1062a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return false;
1063a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
1064a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1065a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comint32_t
1066a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.comCMapTable::CMapFormat4::Builder::SubSerialize(WritableFontData* new_data) {
1067a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  if (!model_changed()) {
1068a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    return CMap::Builder::SubSerialize(new_data);
1069a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1070a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t index = 0;
1071a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  index += new_data->WriteUShort(index, CMapFormat::kFormat4);
1072a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  index += DataSize::kUSHORT;  // length - write this at the end
1073a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  index += new_data->WriteUShort(index, language());
1074a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1075a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t seg_count = segments_.size();
1076a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  index += new_data->WriteUShort(index, seg_count * 2);
1077a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t log2_seg_count = FontMath::Log2(seg_count);
1078a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t search_range = 1 << (log2_seg_count + 1);
1079a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  index += new_data->WriteUShort(index, search_range);
1080a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t entry_selector = log2_seg_count;
1081a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  index += new_data->WriteUShort(index, entry_selector);
1082a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  int32_t range_shift = 2 * seg_count - search_range;
1083a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  index += new_data->WriteUShort(index, range_shift);
1084a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1085a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  for (int32_t i = 0; i < seg_count; ++i) {
1086a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    index += new_data->WriteUShort(index, segments_[i]->end_count());
1087a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1088a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  index += new_data->WriteUShort(index, 0);  // reserved ushort
1089a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  for (int32_t i = 0; i < seg_count; ++i) {
1090a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#if defined SFNTLY_DEBUG_CMAP
1091a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    fprintf(stderr, "Segment %d; start %d\n", i, segments_[i]->start_count());
1092a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#endif
1093a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    index += new_data->WriteUShort(index, segments_[i]->start_count());
1094a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1095a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  for (int32_t i = 0; i < seg_count; ++i) {
1096a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    index += new_data->WriteShort(index, segments_[i]->id_delta());
1097a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1098a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  for (int32_t i = 0; i < seg_count; ++i) {
1099a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    index += new_data->WriteUShort(index, segments_[i]->id_range_offset());
1100a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1101a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1102a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#if defined SFNTLY_DEBUG_CMAP
1103a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  fprintf(stderr, "Glyph id array size %lu\n", glyph_id_array_.size());
1104a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com#endif
1105a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  for (size_t i = 0; i < glyph_id_array_.size(); ++i) {
1106a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    index += new_data->WriteUShort(index, glyph_id_array_[i]);
1107a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  }
1108a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1109a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  new_data->WriteUShort(Offset::kFormat4Length, index);
1110a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com  return index;
1111a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com}
1112a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com
1113a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com/******************************************************************************
1114464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com * CMapTable::Builder class
1115464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com ******************************************************************************/
1116b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCMapTable::Builder::Builder(Header* header, WritableFontData* data)
1117a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    : SubTableContainerTable::Builder(header, data), version_(0) {
1118464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
1119464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1120b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCMapTable::Builder::Builder(Header* header, ReadableFontData* data)
1121a8be98eb7c7b56644732b866346cf8b852592170dfilimon@google.com    : SubTableContainerTable::Builder(header, data), version_(0) {
1122464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
1123464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1124246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCMapTable::Builder::~Builder() {
1125246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com}
1126246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com
1127246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::Builder::SubSerialize(WritableFontData* new_data) {
1128246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  int32_t size = new_data->WriteUShort(CMapTable::Offset::kVersion,
11296b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com                                       version_);
1130246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  size += new_data->WriteUShort(CMapTable::Offset::kNumTables,
1131bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                GetCMapBuilders()->size());
11326b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com
11336b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  int32_t index_offset = size;
1134bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  size += GetCMapBuilders()->size() * CMapTable::Offset::kEncodingRecordSize;
1135bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  for (CMapBuilderMap::iterator it = GetCMapBuilders()->begin(),
1136bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com           e = GetCMapBuilders()->end(); it != e; ++it) {
11376b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com    CMapBuilderPtr b = it->second;
11386b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com    // header entry
1139246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    index_offset += new_data->WriteUShort(index_offset, b->platform_id());
1140246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    index_offset += new_data->WriteUShort(index_offset, b->encoding_id());
1141246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    index_offset += new_data->WriteULong(index_offset, size);
11426b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com
11436b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com    // cmap
11446b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com    FontDataPtr slice;
1145246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    slice.Attach(new_data->Slice(size));
1146246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    size += b->SubSerialize(down_cast<WritableFontData*>(slice.p_));
11476b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  }
11486b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  return size;
1149464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
1150464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1151246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.combool CMapTable::Builder::SubReadyToSerialize() {
1152bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (GetCMapBuilders()->empty())
11536b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com    return false;
11546b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com
11556b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  // check each table
1156bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  for (CMapBuilderMap::iterator it = GetCMapBuilders()->begin(),
1157bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com           e = GetCMapBuilders()->end(); it != e; ++it) {
1158246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    if (!it->second->SubReadyToSerialize())
11596b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com      return false;
11606b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  }
11616b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  return true;
1162464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
1163464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1164246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::Builder::SubDataSizeToSerialize() {
1165bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (GetCMapBuilders()->empty())
11666b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com    return 0;
11676b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com
11686b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  bool variable = false;
11696b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  int32_t size = CMapTable::Offset::kEncodingRecordStart +
1170bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      GetCMapBuilders()->size() * CMapTable::Offset::kEncodingRecordSize;
11716b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com
11726b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  // calculate size of each table
1173bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  for (CMapBuilderMap::iterator it = GetCMapBuilders()->begin(),
1174bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com           e = GetCMapBuilders()->end(); it != e; ++it) {
1175246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    int32_t cmap_size = it->second->SubDataSizeToSerialize();
11766b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com    size += abs(cmap_size);
11776b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com    variable |= cmap_size <= 0;
11786b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  }
11796b5ae74df6b2ff199c63923219c9a18bd9c4d931arthurhsu@google.com  return variable ? -size : size;
1180464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
1181464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1182246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comvoid CMapTable::Builder::SubDataSet() {
1183bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  GetCMapBuilders()->clear();
1184bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  Table::Builder::set_model_changed();
1185464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
1186464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1187246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comCALLER_ATTACH FontDataTable*
1188246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com    CMapTable::Builder::SubBuildTable(ReadableFontData* data) {
1189464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  FontDataTablePtr table = new CMapTable(header(), data);
1190246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return table.Detach();
1191464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
1192464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1193b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCALLER_ATTACH CMapTable::Builder*
1194b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    CMapTable::Builder::CreateBuilder(Header* header,
1195b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                      WritableFontData* data) {
1196b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  Ptr<CMapTable::Builder> builder;
1197b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  builder = new CMapTable::Builder(header, data);
1198b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  return builder.Detach();
1199b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com}
1200b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com
1201bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com// static
1202b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.comCALLER_ATTACH CMapTable::CMap::Builder*
1203b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    CMapTable::Builder::CMapBuilder(ReadableFontData* data, int32_t index) {
1204b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  if (index < 0 || index > NumCMaps(data)) {
1205b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#if !defined (SFNTLY_NO_EXCEPTION)
1206b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com    throw IndexOutOfBoundException(
1207b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com              "CMap table is outside of the bounds of the known tables.");
1208b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com#endif
1209464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return NULL;
1210b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  }
1211464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1212b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  int32_t platform_id = data->ReadUShort(Offset::kEncodingRecordPlatformId +
1213b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                         OffsetForEncodingRecord(index));
1214b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  int32_t encoding_id = data->ReadUShort(Offset::kEncodingRecordEncodingId +
1215b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                         OffsetForEncodingRecord(index));
1216b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com  int32_t offset = data->ReadULongAsInt(Offset::kEncodingRecordOffset +
1217b54cce09c1fc2b09e2adae43d7eb017b47b0cccfarthurhsu@google.com                                        OffsetForEncodingRecord(index));
1218bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return CMap::Builder::GetBuilder(data, offset,
1219bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com                                   NewCMapId(platform_id, encoding_id));
1220464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
1221464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1222bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com// static
1223246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.comint32_t CMapTable::Builder::NumCMaps(ReadableFontData* data) {
1224464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  if (data == NULL) {
1225464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com    return 0;
1226464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com  }
1227246300f7fab1f2539c3207ce5ec28cc355465be8arthurhsu@google.com  return data->ReadUShort(Offset::kNumTables);
1228464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}
1229464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com
1230bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comint32_t CMapTable::Builder::NumCMaps() {
1231bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return GetCMapBuilders()->size();
1232bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
1233bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
1234bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comvoid CMapTable::Builder::Initialize(ReadableFontData* data) {
1235bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  int32_t num_cmaps = NumCMaps(data);
1236bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  for (int32_t i = 0; i < num_cmaps; ++i) {
123779fe62d80f2ab09a217c5948a9adbcd019f4455ddfilimon@google.com    CMapTable::CMap::Builder* cmap_builder = CMapBuilder(data, i);
1238bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    if (!cmap_builder)
1239bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com      continue;
1240bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    cmap_builders_[cmap_builder->cmap_id()] = cmap_builder;
1241bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
1242bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
1243bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
1244bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMap::Builder* CMapTable::Builder::NewCMapBuilder(
1245bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    const CMapId& cmap_id,
1246bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    ReadableFontData* data) {
1247bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  Ptr<WritableFontData> wfd;
1248bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  wfd.Attach(WritableFontData::CreateWritableFontData(data->Size()));
1249bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  data->CopyTo(wfd.p_);
1250bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  CMapTable::CMapBuilderPtr builder;
1251bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  builder.Attach(CMap::Builder::GetBuilder(wfd.p_, 0, cmap_id));
1252bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  CMapBuilderMap* cmap_builders = CMapTable::Builder::GetCMapBuilders();
1253bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  cmap_builders->insert(std::make_pair(cmap_id, builder.p_));
1254bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return builder.Detach();
1255bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
1256bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
1257bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMap::Builder*
1258bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::Builder::NewCMapBuilder(int32_t format, const CMapId& cmap_id) {
1259bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  Ptr<CMapTable::CMap::Builder> cmap_builder;
1260bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  cmap_builder.Attach(CMap::Builder::GetBuilder(format, cmap_id));
1261bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  CMapBuilderMap* cmap_builders = CMapTable::Builder::GetCMapBuilders();
1262bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  cmap_builders->insert(std::make_pair(cmap_id, cmap_builder.p_));
1263bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return cmap_builder.Detach();
1264bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
1265bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
1266bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMap::Builder*
1267bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::Builder::CMapBuilder(const CMapId& cmap_id) {
1268bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  CMapBuilderMap* cmap_builders = this->GetCMapBuilders();
1269bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  CMapBuilderMap::iterator builder = cmap_builders->find(cmap_id);
1270bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (builder != cmap_builders->end())
1271bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    return builder->second;
1272bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#ifndef SFNTLY_NO_EXCEPTION
1273bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  throw NoSuchElementException("No builder found for cmap_id");
1274bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#else
1275bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return NULL;
1276bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com#endif
1277bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
1278bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
1279bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.comCMapTable::CMapBuilderMap* CMapTable::Builder::GetCMapBuilders() {
1280bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  if (cmap_builders_.empty()) {
1281bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    Initialize(InternalReadData());
1282bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com    set_model_changed();
1283bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  }
1284bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com  return &cmap_builders_;
1285bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com}
1286bb035e4061737ef1ac7ee3e1263c443b55c123e9dfilimon@google.com
1287464987db923362e596195f9eebd34fc508c9a41arthurhsu@google.com}  // namespace sfntly
1288