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