• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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