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/ebdt_table.h"
18 
19 #include <stdlib.h>
20 
21 #include "sfntly/table/bitmap/composite_bitmap_glyph.h"
22 #include "sfntly/table/bitmap/simple_bitmap_glyph.h"
23 
24 namespace sfntly {
25 /******************************************************************************
26  * EbdtTable class
27  ******************************************************************************/
~EbdtTable()28 EbdtTable::~EbdtTable() {
29 }
30 
Version()31 int32_t EbdtTable::Version() {
32   return data_->ReadFixed(Offset::kVersion);
33 }
34 
35 CALLER_ATTACH
Glyph(int32_t offset,int32_t length,int32_t format)36 BitmapGlyph* EbdtTable::Glyph(int32_t offset, int32_t length, int32_t format) {
37   ReadableFontDataPtr glyph_data;
38   glyph_data.Attach(down_cast<ReadableFontData*>(data_->Slice(offset, length)));
39   return BitmapGlyph::CreateGlyph(glyph_data, format);
40 }
41 
EbdtTable(Header * header,ReadableFontData * data)42 EbdtTable::EbdtTable(Header* header, ReadableFontData* data)
43     : SubTableContainerTable(header, data) {
44 }
45 
46 /******************************************************************************
47  * EbdtTable::Builder class
48  ******************************************************************************/
Builder(Header * header,WritableFontData * data)49 EbdtTable::Builder::Builder(Header* header, WritableFontData* data)
50   : SubTableContainerTable::Builder(header, data) {
51 }
52 
Builder(Header * header,ReadableFontData * data)53 EbdtTable::Builder::Builder(Header* header, ReadableFontData* data)
54   : SubTableContainerTable::Builder(header, data) {
55 }
56 
~Builder()57 EbdtTable::Builder::~Builder() {
58 }
59 
60 CALLER_ATTACH FontDataTable*
SubBuildTable(ReadableFontData * data)61     EbdtTable::Builder::SubBuildTable(ReadableFontData* data) {
62   FontDataTablePtr table = new EbdtTable(header(), data);
63   return table.Detach();
64 }
65 
SubDataSet()66 void EbdtTable::Builder::SubDataSet() {
67   Revert();
68 }
69 
SubDataSizeToSerialize()70 int32_t EbdtTable::Builder::SubDataSizeToSerialize() {
71   if (glyph_builders_.empty()) {
72     return 0;
73   }
74   bool fixed = true;
75   int32_t size = Offset::kHeaderLength;
76   for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(),
77                                         builder_end = glyph_builders_.end();
78                                         builder_map != builder_end;
79                                         builder_map++) {
80     for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(),
81                                          glyph_entry_end = builder_map->end();
82                                          glyph_entry != glyph_entry_end;
83                                          glyph_entry++) {
84       int32_t glyph_size = glyph_entry->second->SubDataSizeToSerialize();
85       size += abs(glyph_size);
86       fixed = (glyph_size <= 0) ? false : fixed;
87     }
88   }
89   return (fixed ? 1 : -1) * size;
90 }
91 
SubReadyToSerialize()92 bool EbdtTable::Builder::SubReadyToSerialize() {
93   if (glyph_builders_.empty()) {
94     return false;
95   }
96   return true;
97 }
98 
SubSerialize(WritableFontData * new_data)99 int32_t EbdtTable::Builder::SubSerialize(WritableFontData* new_data) {
100   int32_t size = 0;
101   size += new_data->WriteFixed(Offset::kVersion, kVersion);
102   for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(),
103                                         builder_end = glyph_builders_.end();
104                                         builder_map != builder_end;
105                                         builder_map++) {
106     for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(),
107                                          glyph_entry_end = builder_map->end();
108                                          glyph_entry != glyph_entry_end;
109                                          glyph_entry++) {
110       WritableFontDataPtr slice;
111       slice.Attach(down_cast<WritableFontData*>(new_data->Slice(size)));
112       size += glyph_entry->second->SubSerialize(slice);
113     }
114   }
115   return size;
116 }
117 
SetLoca(BitmapLocaList * loca_list)118 void EbdtTable::Builder::SetLoca(BitmapLocaList* loca_list) {
119   assert(loca_list);
120   Revert();
121   glyph_loca_.resize(loca_list->size());
122   std::copy(loca_list->begin(), loca_list->end(), glyph_loca_.begin());
123 }
124 
GenerateLocaList(BitmapLocaList * output)125 void EbdtTable::Builder::GenerateLocaList(BitmapLocaList* output) {
126   assert(output);
127   output->clear();
128 
129   if (glyph_builders_.empty()) {
130     if (glyph_loca_.empty()) {
131       return;
132     }
133   }
134 
135   int start_offset = Offset::kHeaderLength;
136   for (BitmapGlyphBuilderList::iterator builder_map = glyph_builders_.begin(),
137                                         builder_end = glyph_builders_.end();
138                                         builder_map != builder_end;
139                                         builder_map++) {
140     BitmapGlyphInfoMap new_loca_map;
141     int32_t glyph_offset = 0;
142     for (BitmapGlyphBuilderMap::iterator glyph_entry = builder_map->begin(),
143                                          glyph_end = builder_map->end();
144                                          glyph_entry != glyph_end;
145                                          glyph_entry++) {
146       BitmapGlyphBuilderPtr builder = glyph_entry->second;
147       int32_t size = builder->SubDataSizeToSerialize();
148       BitmapGlyphInfoPtr info = new BitmapGlyphInfo(glyph_entry->first,
149           start_offset + glyph_offset, size, builder->format());
150       new_loca_map[glyph_entry->first] = info;
151       glyph_offset += size;
152     }
153     start_offset += glyph_offset;
154     output->push_back(new_loca_map);
155   }
156 }
157 
GlyphBuilders()158 BitmapGlyphBuilderList* EbdtTable::Builder::GlyphBuilders() {
159   return GetGlyphBuilders();
160 }
161 
SetGlyphBuilders(BitmapGlyphBuilderList * glyph_builders)162 void EbdtTable::Builder::SetGlyphBuilders(
163     BitmapGlyphBuilderList* glyph_builders) {
164   glyph_builders_.clear();
165   std::copy(glyph_builders->begin(), glyph_builders->end(),
166             glyph_builders_.begin());
167   set_model_changed();
168 }
169 
Revert()170 void EbdtTable::Builder::Revert() {
171   glyph_loca_.clear();
172   glyph_builders_.clear();
173   set_model_changed(false);
174 }
175 
176 CALLER_ATTACH
CreateBuilder(Header * header,WritableFontData * data)177 EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header,
178                                                       WritableFontData* data) {
179   Ptr<EbdtTable::Builder> builder;
180   builder = new Builder(header, data);
181   return builder.Detach();
182 }
183 
184 CALLER_ATTACH
CreateBuilder(Header * header,ReadableFontData * data)185 EbdtTable::Builder* EbdtTable::Builder::CreateBuilder(Header* header,
186                                                       ReadableFontData* data) {
187   Ptr<EbdtTable::Builder> builder;
188   builder = new Builder(header, data);
189   return builder.Detach();
190 }
191 
GetGlyphBuilders()192 BitmapGlyphBuilderList* EbdtTable::Builder::GetGlyphBuilders() {
193   if (glyph_builders_.empty()) {
194     if (glyph_loca_.empty()) {
195 #if !defined (SFNTLY_NO_EXCEPTION)
196       throw IllegalStateException(
197           "Loca values not set - unable to parse glyph data.");
198 #endif
199       return NULL;
200     }
201     Initialize(InternalReadData(), &glyph_loca_, &glyph_builders_);
202     set_model_changed();
203   }
204   return &glyph_builders_;
205 }
206 
Initialize(ReadableFontData * data,BitmapLocaList * loca_list,BitmapGlyphBuilderList * output)207 void EbdtTable::Builder::Initialize(ReadableFontData* data,
208                                     BitmapLocaList* loca_list,
209                                     BitmapGlyphBuilderList* output) {
210   assert(loca_list);
211   assert(output);
212 
213   output->clear();
214   if (data) {
215     for (BitmapLocaList::iterator loca_map = loca_list->begin(),
216                                   loca_end = loca_list->end();
217                                   loca_map != loca_end; loca_map++) {
218       BitmapGlyphBuilderMap glyph_builder_map;
219       for (BitmapGlyphInfoMap::iterator entry = loca_map->begin(),
220                                         entry_end = loca_map->end();
221                                         entry != entry_end; entry++) {
222         BitmapGlyphInfoPtr info = entry->second;
223         ReadableFontDataPtr slice;
224         slice.Attach(down_cast<ReadableFontData*>(data->Slice(
225             info->offset(), info->length())));
226         BitmapGlyphBuilderPtr glyph_builder;
227         glyph_builder.Attach(BitmapGlyph::Builder::CreateGlyphBuilder(
228             slice, info->format()));
229         glyph_builder_map[entry->first] = glyph_builder;
230       }
231       output->push_back(glyph_builder_map);
232     }
233   }
234 }
235 
236 }  // namespace sfntly
237