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_format3.h"
18
19 #include "sfntly/table/bitmap/eblc_table.h"
20
21 namespace sfntly {
22 /******************************************************************************
23 * IndexSubTableFormat3 class
24 ******************************************************************************/
~IndexSubTableFormat3()25 IndexSubTableFormat3::~IndexSubTableFormat3() {
26 }
27
NumGlyphs()28 int32_t IndexSubTableFormat3::NumGlyphs() {
29 return last_glyph_index() - first_glyph_index() + 1;
30 }
31
GlyphStartOffset(int32_t glyph_id)32 int32_t IndexSubTableFormat3::GlyphStartOffset(int32_t glyph_id) {
33 int32_t loca = CheckGlyphRange(glyph_id);
34 if (loca != -1) {
35 return Loca(loca);
36 }
37 return -1;
38 }
39
GlyphLength(int32_t glyph_id)40 int32_t IndexSubTableFormat3::GlyphLength(int32_t glyph_id) {
41 int32_t loca = CheckGlyphRange(glyph_id);
42 if (loca != -1) {
43 return Loca(glyph_id + 1) - Loca(glyph_id);
44 }
45 return 0;
46 }
47
48 // static
GetDataLength(ReadableFontData * data,int32_t offset,int32_t first,int32_t last)49 int32_t IndexSubTableFormat3::GetDataLength(ReadableFontData* data,
50 int32_t offset,
51 int32_t first,
52 int32_t last) {
53 UNREFERENCED_PARAMETER(data);
54 UNREFERENCED_PARAMETER(offset);
55 return (last - first + 1 + 1) * DataSize::kUSHORT;
56 }
57
IndexSubTableFormat3(ReadableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)58 IndexSubTableFormat3::IndexSubTableFormat3(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 IndexSubTableFormat3::Loca(int32_t loca) {
65 int32_t read_offset =
66 data_->ReadUShort(EblcTable::Offset::kIndexSubTable3_offsetArray +
67 loca * DataSize::kUSHORT);
68 return read_offset;
69 }
70
71 /******************************************************************************
72 * IndexSubTableFormat3::Builder class
73 ******************************************************************************/
~Builder()74 IndexSubTableFormat3::Builder::~Builder() {
75 }
76
NumGlyphs()77 int32_t IndexSubTableFormat3::Builder::NumGlyphs() {
78 return GetOffsetArray()->size() - 1;
79 }
80
GlyphStartOffset(int32_t glyph_id)81 int32_t IndexSubTableFormat3::Builder::GlyphStartOffset(int32_t glyph_id) {
82 int32_t loca = CheckGlyphRange(glyph_id);
83 if (loca == -1) {
84 return -1;
85 }
86 return GetOffsetArray()->at(loca);
87 }
88
GlyphLength(int32_t glyph_id)89 int32_t IndexSubTableFormat3::Builder::GlyphLength(int32_t glyph_id) {
90 int32_t loca = CheckGlyphRange(glyph_id);
91 if (loca == -1) {
92 return 0;
93 }
94 IntegerList* offset_array = GetOffsetArray();
95 return offset_array->at(loca + 1) - offset_array->at(loca);
96 }
97
98 CALLER_ATTACH IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator*
GetIterator()99 IndexSubTableFormat3::Builder::GetIterator() {
100 Ptr<IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator> it =
101 new IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator(this);
102 return it.Detach();
103 }
104
Revert()105 void IndexSubTableFormat3::Builder::Revert() {
106 offset_array_.clear();
107 IndexSubTable::Builder::Revert();
108 }
109
SetOffsetArray(const IntegerList & offset_array)110 void IndexSubTableFormat3::Builder::SetOffsetArray(
111 const IntegerList& offset_array) {
112 offset_array_.clear();
113 offset_array_ = offset_array;
114 set_model_changed();
115 }
116
117 // static
118 CALLER_ATTACH IndexSubTableFormat3::Builder*
CreateBuilder()119 IndexSubTableFormat3::Builder::CreateBuilder() {
120 IndexSubTableFormat3BuilderPtr output = new IndexSubTableFormat3::Builder();
121 return output.Detach();
122 }
123
124 // static
125 CALLER_ATTACH IndexSubTableFormat3::Builder*
CreateBuilder(ReadableFontData * data,int32_t index_sub_table_offset,int32_t first_glyph_index,int32_t last_glyph_index)126 IndexSubTableFormat3::Builder::CreateBuilder(ReadableFontData* data,
127 int32_t index_sub_table_offset,
128 int32_t first_glyph_index,
129 int32_t last_glyph_index) {
130 int32_t length = Builder::DataLength(data,
131 index_sub_table_offset,
132 first_glyph_index,
133 last_glyph_index);
134 ReadableFontDataPtr new_data;
135 new_data.Attach(down_cast<ReadableFontData*>(
136 data->Slice(index_sub_table_offset, length)));
137 if (new_data == NULL) {
138 return NULL;
139 }
140 IndexSubTableFormat3BuilderPtr output =
141 new IndexSubTableFormat3::Builder(new_data,
142 first_glyph_index,
143 last_glyph_index);
144 return output.Detach();
145 }
146
147 // static
148 CALLER_ATTACH IndexSubTableFormat3::Builder*
CreateBuilder(WritableFontData * data,int32_t index_sub_table_offset,int32_t first_glyph_index,int32_t last_glyph_index)149 IndexSubTableFormat3::Builder::CreateBuilder(WritableFontData* data,
150 int32_t index_sub_table_offset,
151 int32_t first_glyph_index,
152 int32_t last_glyph_index) {
153 int32_t length = Builder::DataLength(data,
154 index_sub_table_offset,
155 first_glyph_index,
156 last_glyph_index);
157 WritableFontDataPtr new_data;
158 new_data.Attach(down_cast<WritableFontData*>(
159 data->Slice(index_sub_table_offset, length)));
160 IndexSubTableFormat3BuilderPtr output =
161 new IndexSubTableFormat3::Builder(new_data,
162 first_glyph_index,
163 last_glyph_index);
164 return output.Detach();
165 }
166
SubBuildTable(ReadableFontData * data)167 CALLER_ATTACH FontDataTable* IndexSubTableFormat3::Builder::SubBuildTable(
168 ReadableFontData* data) {
169 IndexSubTableFormat3Ptr output = new IndexSubTableFormat3(
170 data, first_glyph_index(), last_glyph_index());
171 return output.Detach();
172 }
173
SubDataSet()174 void IndexSubTableFormat3::Builder::SubDataSet() {
175 Revert();
176 }
177
SubDataSizeToSerialize()178 int32_t IndexSubTableFormat3::Builder::SubDataSizeToSerialize() {
179 if (offset_array_.empty()) {
180 return InternalReadData()->Length();
181 }
182 return EblcTable::Offset::kIndexSubHeaderLength +
183 offset_array_.size() * DataSize::kULONG;
184 }
185
SubReadyToSerialize()186 bool IndexSubTableFormat3::Builder::SubReadyToSerialize() {
187 if (!offset_array_.empty()) {
188 return true;
189 }
190 return false;
191 }
192
SubSerialize(WritableFontData * new_data)193 int32_t IndexSubTableFormat3::Builder::SubSerialize(
194 WritableFontData* new_data) {
195 int32_t size = SerializeIndexSubHeader(new_data);
196 if (!model_changed()) {
197 if (InternalReadData() == NULL) {
198 return size;
199 }
200 ReadableFontDataPtr source;
201 WritableFontDataPtr target;
202 source.Attach(down_cast<ReadableFontData*>(InternalReadData()->Slice(
203 EblcTable::Offset::kIndexSubTable3_offsetArray)));
204 target.Attach(down_cast<WritableFontData*>(new_data->Slice(
205 EblcTable::Offset::kIndexSubTable3_offsetArray)));
206 size += source->CopyTo(target);
207 } else {
208 for (IntegerList::iterator b = GetOffsetArray()->begin(),
209 e = GetOffsetArray()->end(); b != e; b++) {
210 size += new_data->WriteUShort(size, *b);
211 }
212 }
213 return size;
214 }
215
Builder()216 IndexSubTableFormat3::Builder::Builder()
217 : IndexSubTable::Builder(EblcTable::Offset::kIndexSubTable3_builderDataSize,
218 IndexSubTable::Format::FORMAT_3) {
219 }
220
Builder(WritableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)221 IndexSubTableFormat3::Builder::Builder(WritableFontData* data,
222 int32_t first_glyph_index,
223 int32_t last_glyph_index)
224 : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
225 }
226
Builder(ReadableFontData * data,int32_t first_glyph_index,int32_t last_glyph_index)227 IndexSubTableFormat3::Builder::Builder(ReadableFontData* data,
228 int32_t first_glyph_index,
229 int32_t last_glyph_index)
230 : IndexSubTable::Builder(data, first_glyph_index, last_glyph_index) {
231 }
232
GetOffsetArray()233 IntegerList* IndexSubTableFormat3::Builder::GetOffsetArray() {
234 if (offset_array_.empty()) {
235 Initialize(InternalReadData());
236 set_model_changed();
237 }
238 return &offset_array_;
239 }
240
Initialize(ReadableFontData * data)241 void IndexSubTableFormat3::Builder::Initialize(ReadableFontData* data) {
242 offset_array_.clear();
243 if (data) {
244 int32_t num_offsets = (last_glyph_index() - first_glyph_index() + 1) + 1;
245 for (int32_t i = 0; i < num_offsets; ++i) {
246 offset_array_.push_back(data->ReadUShort(
247 EblcTable::Offset::kIndexSubTable3_offsetArray +
248 i * DataSize::kUSHORT));
249 }
250 }
251 }
252
253 // static
DataLength(ReadableFontData * data,int32_t index_sub_table_offset,int32_t first_glyph_index,int32_t last_glyph_index)254 int32_t IndexSubTableFormat3::Builder::DataLength(
255 ReadableFontData* data,
256 int32_t index_sub_table_offset,
257 int32_t first_glyph_index,
258 int32_t last_glyph_index) {
259 UNREFERENCED_PARAMETER(data);
260 UNREFERENCED_PARAMETER(index_sub_table_offset);
261 return EblcTable::Offset::kIndexSubHeaderLength +
262 (last_glyph_index - first_glyph_index + 1 + 1) * DataSize::kUSHORT;
263 }
264
265 /******************************************************************************
266 * IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator class
267 ******************************************************************************/
BitmapGlyphInfoIterator(IndexSubTableFormat3::Builder * container)268 IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::BitmapGlyphInfoIterator(
269 IndexSubTableFormat3::Builder* container)
270 : RefIterator<BitmapGlyphInfo, IndexSubTableFormat3::Builder,
271 IndexSubTable::Builder>(container) {
272 glyph_id_ = container->first_glyph_index();
273 }
274
HasNext()275 bool IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::HasNext() {
276 if (glyph_id_ <= container()->last_glyph_index()) {
277 return true;
278 }
279 return false;
280 }
281
282 CALLER_ATTACH BitmapGlyphInfo*
Next()283 IndexSubTableFormat3::Builder::BitmapGlyphInfoIterator::Next() {
284 BitmapGlyphInfoPtr output;
285 if (!HasNext()) {
286 // Note: In C++, we do not throw exception when there's no element.
287 return NULL;
288 }
289 output = new BitmapGlyphInfo(glyph_id_,
290 container()->image_data_offset(),
291 container()->GlyphStartOffset(glyph_id_),
292 container()->GlyphLength(glyph_id_),
293 container()->image_format());
294 glyph_id_++;
295 return output.Detach();
296 }
297
298 } // namespace sfntly
299