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