1 /*
2 * Copyright 2011 Google Inc. All Rights Reserved.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #include "sfntly/table/bitmap/index_sub_table_format1.h"
18
19 #include "sfntly/table/bitmap/eblc_table.h"
20
21 namespace sfntly {
22 /******************************************************************************
23 * IndexSubTableFormat1 class
24 ******************************************************************************/
25 // static
GetDataLength(ReadableFontData * data,int32_t offset,int32_t first,int32_t last)26 int32_t IndexSubTableFormat1::GetDataLength(ReadableFontData* data,
27 int32_t offset,
28 int32_t first,
29 int32_t last) {
30 UNREFERENCED_PARAMETER(data);
31 UNREFERENCED_PARAMETER(offset);
32 return (last - first + 1 + 1) * DataSize::kULONG;
33 }
34
~IndexSubTableFormat1()35 IndexSubTableFormat1::~IndexSubTableFormat1() {
36 }
37
NumGlyphs()38 int32_t IndexSubTableFormat1::NumGlyphs() {
39 return last_glyph_index() - first_glyph_index() + 1;
40 }
41
GlyphStartOffset(int32_t glyph_id)42 int32_t IndexSubTableFormat1::GlyphStartOffset(int32_t glyph_id) {
43 int32_t loca = CheckGlyphRange(glyph_id);
44 if (loca == -1) {
45 return -1;
46 }
47 return Loca(loca);
48 }
49
GlyphLength(int32_t glyph_id)50 int32_t IndexSubTableFormat1::GlyphLength(int32_t glyph_id) {
51 int32_t loca = CheckGlyphRange(glyph_id);
52 if (loca == -1) {
53 return -1;
54 }
55 return Loca(loca + 1) - Loca(loca);
56 }
57
IndexSubTableFormat1(ReadableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)58 IndexSubTableFormat1::IndexSubTableFormat1(ReadableFontData* data,
59 int32_t first_glyph_index,
60 int32_t last_glyph_index)
61 : IndexSubTable(data, first_glyph_index, last_glyph_index) {
62 }
63
Loca(int32_t loca)64 int32_t IndexSubTableFormat1::Loca(int32_t loca) {
65 return image_data_offset() +
66 data_->ReadULongAsInt(EblcTable::Offset::kIndexSubTable1_offsetArray +
67 loca * DataSize::kULONG);
68 }
69
70 /******************************************************************************
71 * IndexSubTableFormat1::Builder class
72 ******************************************************************************/
~Builder()73 IndexSubTableFormat1::Builder::~Builder() {
74 }
75
NumGlyphs()76 int32_t IndexSubTableFormat1::Builder::NumGlyphs() {
77 return GetOffsetArray()->size() - 1;
78 }
79
GlyphLength(int32_t glyph_id)80 int32_t IndexSubTableFormat1::Builder::GlyphLength(int32_t glyph_id) {
81 int32_t loca = CheckGlyphRange(glyph_id);
82 if (loca == -1) {
83 return 0;
84 }
85 IntegerList* offset_array = GetOffsetArray();
86 return offset_array->at(loca + 1) - offset_array->at(loca);
87 }
88
GlyphStartOffset(int32_t glyph_id)89 int32_t IndexSubTableFormat1::Builder::GlyphStartOffset(int32_t glyph_id) {
90 int32_t loca = CheckGlyphRange(glyph_id);
91 if (loca == -1) {
92 return -1;
93 }
94 return GetOffsetArray()->at(loca);
95 }
96
97 CALLER_ATTACH IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator*
GetIterator()98 IndexSubTableFormat1::Builder::GetIterator() {
99 Ptr<IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator> it =
100 new IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator(this);
101 return it.Detach();
102 }
103
104 // static
105 CALLER_ATTACH IndexSubTableFormat1::Builder*
CreateBuilder()106 IndexSubTableFormat1::Builder::CreateBuilder() {
107 IndexSubTableFormat1BuilderPtr output = new IndexSubTableFormat1::Builder();
108 return output.Detach();
109 }
110
111 // static
112 CALLER_ATTACH IndexSubTableFormat1::Builder*
CreateBuilder(ReadableFontData * data,int32_t index_sub_table_offset,int32_t first_glyph_index,int32_t last_glyph_index)113 IndexSubTableFormat1::Builder::CreateBuilder(ReadableFontData* data,
114 int32_t index_sub_table_offset,
115 int32_t first_glyph_index,
116 int32_t last_glyph_index) {
117 int32_t length = Builder::DataLength(data,
118 index_sub_table_offset,
119 first_glyph_index,
120 last_glyph_index);
121 ReadableFontDataPtr new_data;
122 new_data.Attach(down_cast<ReadableFontData*>(
123 data->Slice(index_sub_table_offset, length)));
124 if (new_data == NULL) {
125 return NULL;
126 }
127 IndexSubTableFormat1BuilderPtr output =
128 new IndexSubTableFormat1::Builder(new_data,
129 first_glyph_index,
130 last_glyph_index);
131 return output.Detach();
132 }
133
134
135 // static
136 CALLER_ATTACH IndexSubTableFormat1::Builder*
CreateBuilder(WritableFontData * data,int32_t index_sub_table_offset,int32_t first_glyph_index,int32_t last_glyph_index)137 IndexSubTableFormat1::Builder::CreateBuilder(WritableFontData* data,
138 int32_t index_sub_table_offset,
139 int32_t first_glyph_index,
140 int32_t last_glyph_index) {
141 int32_t length = Builder::DataLength(data,
142 index_sub_table_offset,
143 first_glyph_index,
144 last_glyph_index);
145 WritableFontDataPtr new_data;
146 new_data.Attach(down_cast<WritableFontData*>(
147 data->Slice(index_sub_table_offset, length)));
148 IndexSubTableFormat1BuilderPtr output =
149 new IndexSubTableFormat1::Builder(new_data,
150 first_glyph_index,
151 last_glyph_index);
152 return output.Detach();
153 }
154
SubBuildTable(ReadableFontData * data)155 CALLER_ATTACH FontDataTable* IndexSubTableFormat1::Builder::SubBuildTable(
156 ReadableFontData* data) {
157 IndexSubTableFormat1Ptr output = new IndexSubTableFormat1(
158 data, first_glyph_index(), last_glyph_index());
159 return output.Detach();
160 }
161
SubDataSet()162 void IndexSubTableFormat1::Builder::SubDataSet() {
163 Revert();
164 }
165
SubDataSizeToSerialize()166 int32_t IndexSubTableFormat1::Builder::SubDataSizeToSerialize() {
167 if (offset_array_.empty()) {
168 return InternalReadData()->Length();
169 }
170 return EblcTable::Offset::kIndexSubHeaderLength +
171 offset_array_.size() * DataSize::kULONG;
172 }
173
SubReadyToSerialize()174 bool IndexSubTableFormat1::Builder::SubReadyToSerialize() {
175 if (!offset_array_.empty()) {
176 return true;
177 }
178 return false;
179 }
180
SubSerialize(WritableFontData * new_data)181 int32_t IndexSubTableFormat1::Builder::SubSerialize(
182 WritableFontData* new_data) {
183 int32_t size = SerializeIndexSubHeader(new_data);
184 if (!model_changed()) {
185 if (InternalReadData() == NULL) {
186 return size;
187 }
188 ReadableFontDataPtr source;
189 WritableFontDataPtr target;
190 source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
191 EblcTable::Offset::kIndexSubTable1_offsetArray)));
192 target.Attach(down_cast<WritableFontData*>(new_data->Slice(
193 EblcTable::Offset::kIndexSubTable1_offsetArray)));
194 size += source->CopyTo(target);
195 } else {
196 for (IntegerList::iterator b = GetOffsetArray()->begin(),
197 e = GetOffsetArray()->end(); b != e; b++) {
198 size += new_data->WriteLong(size, *b);
199 }
200 }
201 return size;
202 }
203
OffsetArray()204 IntegerList* IndexSubTableFormat1::Builder::OffsetArray() {
205 return GetOffsetArray();
206 }
207
SetOffsetArray(const IntegerList & offset_array)208 void IndexSubTableFormat1::Builder::SetOffsetArray(
209 const IntegerList& offset_array) {
210 offset_array_.clear();
211 offset_array_ = offset_array;
212 set_model_changed();
213 }
214
Revert()215 void IndexSubTableFormat1::Builder::Revert() {
216 offset_array_.clear();
217 IndexSubTable::Builder::Revert();
218 }
219
Builder()220 IndexSubTableFormat1::Builder::Builder()
221 : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable1_builderDataSize,
222 IndexSubTable::Format::FORMAT_1) {
223 }
224
Builder(WritableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)225 IndexSubTableFormat1::Builder::Builder(WritableFontData* data,
226 int32_t first_glyph_index,
227 int32_t last_glyph_index)
228 : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
229 }
230
Builder(ReadableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)231 IndexSubTableFormat1::Builder::Builder(ReadableFontData* data,
232 int32_t first_glyph_index,
233 int32_t last_glyph_index)
234 : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
235 }
236
GetOffsetArray()237 IntegerList* IndexSubTableFormat1::Builder::GetOffsetArray() {
238 if (offset_array_.empty()) {
239 Initialize(InternalReadData());
240 set_model_changed();
241 }
242 return &offset_array_;
243 }
244
Initialize(ReadableFontData * data)245 void IndexSubTableFormat1::Builder::Initialize(ReadableFontData* data) {
246 offset_array_.clear();
247 if (data) {
248 int32_t num_offsets = (last_glyph_index() - first_glyph_index() + 1) + 1;
249 for (int32_t i = 0; i < num_offsets; ++i) {
250 offset_array_.push_back(data->ReadULongAsInt(
251 EblcTable::Offset::kIndexSubTable1_offsetArray +
252 i * DataSize::kULONG));
253 }
254 }
255 }
256
257 // static
DataLength(ReadableFontData * data,int32_t index_sub_table_offset,int32_t first_glyph_index,int32_t last_glyph_index)258 int32_t IndexSubTableFormat1::Builder::DataLength(
259 ReadableFontData* data,
260 int32_t index_sub_table_offset,
261 int32_t first_glyph_index,
262 int32_t last_glyph_index) {
263 UNREFERENCED_PARAMETER(data);
264 UNREFERENCED_PARAMETER(index_sub_table_offset);
265 return EblcTable::Offset::kIndexSubHeaderLength +
266 (last_glyph_index - first_glyph_index + 1 + 1) * DataSize::kULONG;
267 }
268
269 /******************************************************************************
270 * IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator class
271 ******************************************************************************/
BitmapGlyphInfoIterator(IndexSubTableFormat1::Builder * container)272 IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
273 IndexSubTableFormat1::Builder* container)
274 : RefIterator<BitmapGlyphInfo, IndexSubTableFormat1::Builder,
275 IndexSubTable::Builder>(container) {
276 glyph_id_ = container->first_glyph_index();
277 }
278
HasNext()279 bool IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::HasNext() {
280 if (glyph_id_ <= container()->last_glyph_index()) {
281 return true;
282 }
283 return false;
284 }
285
286 CALLER_ATTACH BitmapGlyphInfo*
Next()287 IndexSubTableFormat1::Builder::BitmapGlyphInfoIterator::Next() {
288 BitmapGlyphInfoPtr output;
289 if (!HasNext()) {
290 // Note: In C++, we do not throw exception when there's no element.
291 return NULL;
292 }
293 output = new BitmapGlyphInfo(glyph_id_,
294 container()->image_data_offset(),
295 container()->GlyphStartOffset(glyph_id_),
296 container()->GlyphLength(glyph_id_),
297 container()->image_format());
298 glyph_id_++;
299 return output.Detach();
300 }
301
302 } // namespace sfntly
303