Line data Source code
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/eblc_table.h"
18 :
19 : #include <stdio.h>
20 : #include <stdlib.h>
21 :
22 : #include "sfntly/math/font_math.h"
23 :
24 : namespace sfntly {
25 : /******************************************************************************
26 : * EblcTable class
27 : ******************************************************************************/
28 0 : int32_t EblcTable::Version() {
29 0 : return data_->ReadFixed(Offset::kVersion);
30 : }
31 :
32 0 : int32_t EblcTable::NumSizes() {
33 0 : return data_->ReadULongAsInt(Offset::kNumSizes);
34 : }
35 :
36 0 : BitmapSizeTable* EblcTable::GetBitmapSizeTable(int32_t index) {
37 0 : if (index < 0 || index > NumSizes()) {
38 : #if !defined (SFNTLY_NO_EXCEPTION)
39 : throw IndexOutOfBoundException(
40 : "Size table index is outside the range of tables.");
41 : #endif
42 0 : return NULL;
43 : }
44 0 : BitmapSizeTableList* bitmap_size_table_list = GetBitmapSizeTableList();
45 0 : if (bitmap_size_table_list) {
46 0 : return (*bitmap_size_table_list)[index];
47 : }
48 0 : return NULL;
49 : }
50 :
51 0 : EblcTable::EblcTable(Header* header, ReadableFontData* data)
52 0 : : SubTableContainerTable(header, data) {
53 0 : }
54 :
55 0 : BitmapSizeTableList* EblcTable::GetBitmapSizeTableList() {
56 0 : AutoLock lock(bitmap_size_table_lock_);
57 0 : if (bitmap_size_table_.empty()) {
58 0 : CreateBitmapSizeTable(data_, NumSizes(), &bitmap_size_table_);
59 : }
60 0 : return &bitmap_size_table_;
61 : }
62 :
63 : // static
64 0 : void EblcTable::CreateBitmapSizeTable(ReadableFontData* data,
65 : int32_t num_sizes,
66 : BitmapSizeTableList* output) {
67 0 : assert(data);
68 0 : assert(output);
69 0 : for (int32_t i = 0; i < num_sizes; ++i) {
70 0 : ReadableFontDataPtr new_data;
71 0 : new_data.Attach(down_cast<ReadableFontData*>(
72 : data->Slice(Offset::kBitmapSizeTableArrayStart +
73 0 : i * Offset::kBitmapSizeTableLength,
74 0 : Offset::kBitmapSizeTableLength)));
75 0 : BitmapSizeTableBuilderPtr size_builder;
76 0 : size_builder.Attach(
77 0 : BitmapSizeTable::Builder::CreateBuilder(new_data, data));
78 0 : BitmapSizeTablePtr size;
79 0 : size.Attach(down_cast<BitmapSizeTable*>(size_builder->Build()));
80 0 : output->push_back(size);
81 : }
82 0 : }
83 :
84 : /******************************************************************************
85 : * EblcTable::Builder class
86 : ******************************************************************************/
87 0 : EblcTable::Builder::Builder(Header* header, WritableFontData* data)
88 0 : : SubTableContainerTable::Builder(header, data) {
89 0 : }
90 :
91 0 : EblcTable::Builder::Builder(Header* header, ReadableFontData* data)
92 0 : : SubTableContainerTable::Builder(header, data) {
93 0 : }
94 :
95 0 : EblcTable::Builder::~Builder() {
96 0 : }
97 :
98 0 : int32_t EblcTable::Builder::SubSerialize(WritableFontData* new_data) {
99 : // header
100 0 : int32_t size = new_data->WriteFixed(0, kVersion);
101 0 : size += new_data->WriteULong(size, size_table_builders_.size());
102 :
103 : // calculate the offsets
104 : // offset to the start of the size table array
105 0 : int32_t size_table_start_offset = size;
106 : // walking offset in the size table array
107 0 : int32_t size_table_offset = size_table_start_offset;
108 : // offset to the start of the whole index subtable block
109 0 : int32_t sub_table_block_start_offset = size_table_offset +
110 0 : size_table_builders_.size() * Offset::kBitmapSizeTableLength;
111 : // walking offset in the index subtable
112 : // points to the start of the current subtable block
113 0 : int32_t current_sub_table_block_start_offset = sub_table_block_start_offset;
114 :
115 : #if defined (SFNTLY_DEBUG_BITMAP)
116 : int32_t size_index = 0;
117 : #endif
118 0 : for (BitmapSizeTableBuilderList::iterator
119 0 : size_builder = size_table_builders_.begin(),
120 0 : size_builder_end = size_table_builders_.end();
121 : size_builder != size_builder_end; size_builder++) {
122 0 : (*size_builder)->SetIndexSubTableArrayOffset(
123 0 : current_sub_table_block_start_offset);
124 : IndexSubTableBuilderList* index_sub_table_builder_list =
125 0 : (*size_builder)->IndexSubTableBuilders();
126 :
127 : // walking offset within the current subTable array
128 0 : int32_t index_sub_table_array_offset = current_sub_table_block_start_offset;
129 : // walking offset within the subTable entries
130 0 : int32_t index_sub_table_offset = index_sub_table_array_offset +
131 0 : index_sub_table_builder_list->size() * Offset::kIndexSubHeaderLength;
132 :
133 : #if defined (SFNTLY_DEBUG_BITMAP)
134 : fprintf(stderr, "size %d: sizeTable=%x, current subTable Block=%x, ",
135 : size_index, size_table_offset,
136 : current_sub_table_block_start_offset);
137 : fprintf(stderr, "index subTableStart=%x\n", index_sub_table_offset);
138 : size_index++;
139 : int32_t sub_table_index = 0;
140 : #endif
141 0 : for (IndexSubTableBuilderList::iterator
142 0 : index_sub_table_builder = index_sub_table_builder_list->begin(),
143 0 : index_sub_table_builder_end = index_sub_table_builder_list->end();
144 : index_sub_table_builder != index_sub_table_builder_end;
145 : index_sub_table_builder++) {
146 : #if defined (SFNTLY_DEBUG_BITMAP)
147 : fprintf(stderr, "\tsubTableIndex %d: format=%x, ", sub_table_index,
148 : (*index_sub_table_builder)->index_format());
149 : fprintf(stderr, "indexSubTableArrayOffset=%x, indexSubTableOffset=%x\n",
150 : index_sub_table_array_offset, index_sub_table_offset);
151 : sub_table_index++;
152 : #endif
153 : // array entry
154 0 : index_sub_table_array_offset += new_data->WriteUShort(
155 : index_sub_table_array_offset,
156 0 : (*index_sub_table_builder)->first_glyph_index());
157 0 : index_sub_table_array_offset += new_data->WriteUShort(
158 : index_sub_table_array_offset,
159 0 : (*index_sub_table_builder)->last_glyph_index());
160 0 : index_sub_table_array_offset += new_data->WriteULong(
161 : index_sub_table_array_offset,
162 0 : index_sub_table_offset - current_sub_table_block_start_offset);
163 :
164 : // index sub table
165 0 : WritableFontDataPtr slice_index_sub_table;
166 0 : slice_index_sub_table.Attach(down_cast<WritableFontData*>(
167 0 : new_data->Slice(index_sub_table_offset)));
168 : int32_t current_sub_table_size =
169 0 : (*index_sub_table_builder)->SubSerialize(slice_index_sub_table);
170 : int32_t padding = FontMath::PaddingRequired(current_sub_table_size,
171 0 : DataSize::kULONG);
172 : #if defined (SFNTLY_DEBUG_BITMAP)
173 : fprintf(stderr, "\t\tsubTableSize = %x, padding = %x\n",
174 : current_sub_table_size, padding);
175 : #endif
176 0 : index_sub_table_offset += current_sub_table_size;
177 0 : index_sub_table_offset +=
178 0 : new_data->WritePadding(index_sub_table_offset, padding);
179 : }
180 :
181 : // serialize size table
182 0 : (*size_builder)->SetIndexTableSize(
183 0 : index_sub_table_offset - current_sub_table_block_start_offset);
184 0 : WritableFontDataPtr slice_size_table;
185 0 : slice_size_table.Attach(down_cast<WritableFontData*>(
186 0 : new_data->Slice(size_table_offset)));
187 0 : size_table_offset += (*size_builder)->SubSerialize(slice_size_table);
188 :
189 0 : current_sub_table_block_start_offset = index_sub_table_offset;
190 : }
191 0 : return size + current_sub_table_block_start_offset;
192 : }
193 :
194 0 : bool EblcTable::Builder::SubReadyToSerialize() {
195 0 : if (size_table_builders_.empty()) {
196 0 : return false;
197 : }
198 0 : for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(),
199 0 : e = size_table_builders_.end();
200 : b != e; b++) {
201 0 : if (!(*b)->SubReadyToSerialize()) {
202 0 : return false;
203 : }
204 : }
205 0 : return true;
206 : }
207 :
208 0 : int32_t EblcTable::Builder::SubDataSizeToSerialize() {
209 0 : if (size_table_builders_.empty()) {
210 0 : return 0;
211 : }
212 0 : int32_t size = Offset::kHeaderLength;
213 0 : bool variable = false;
214 : #if defined (SFNTLY_DEBUG_BITMAP)
215 : size_t size_index = 0;
216 : #endif
217 0 : for (BitmapSizeTableBuilderList::iterator b = size_table_builders_.begin(),
218 0 : e = size_table_builders_.end();
219 : b != e; b++) {
220 0 : int32_t size_builder_size = (*b)->SubDataSizeToSerialize();
221 : #if defined (SFNTLY_DEBUG_BITMAP)
222 : fprintf(stderr, "sizeIndex = %d, sizeBuilderSize=0x%x (%d)\n",
223 : size_index++, size_builder_size, size_builder_size);
224 : #endif
225 0 : variable = size_builder_size > 0 ? variable : true;
226 0 : size += abs(size_builder_size);
227 : }
228 : #if defined (SFNTLY_DEBUG_BITMAP)
229 : fprintf(stderr, "eblc size=%d\n", size);
230 : #endif
231 0 : return variable ? -size : size;
232 : }
233 :
234 0 : void EblcTable::Builder::SubDataSet() {
235 0 : Revert();
236 0 : }
237 :
238 0 : BitmapSizeTableBuilderList* EblcTable::Builder::BitmapSizeBuilders() {
239 0 : return GetSizeList();
240 : }
241 :
242 0 : void EblcTable::Builder::Revert() {
243 0 : size_table_builders_.clear();
244 0 : set_model_changed(false);
245 0 : }
246 :
247 0 : void EblcTable::Builder::GenerateLocaList(BitmapLocaList* output) {
248 0 : assert(output);
249 0 : BitmapSizeTableBuilderList* size_builder_list = GetSizeList();
250 0 : output->clear();
251 : #if defined (SFNTLY_DEBUG_BITMAP)
252 : int32_t size_index = 0;
253 : #endif
254 0 : for (BitmapSizeTableBuilderList::iterator b = size_builder_list->begin(),
255 0 : e = size_builder_list->end();
256 : b != e; b++) {
257 : #if defined (SFNTLY_DEBUG_BITMAP)
258 : fprintf(stderr, "size table = %d\n", size_index++);
259 : #endif
260 0 : BitmapGlyphInfoMap loca_map;
261 0 : (*b)->GenerateLocaMap(&loca_map);
262 0 : output->push_back(loca_map);
263 : }
264 0 : }
265 :
266 : CALLER_ATTACH
267 0 : FontDataTable* EblcTable::Builder::SubBuildTable(ReadableFontData* data) {
268 0 : Ptr<EblcTable> new_table = new EblcTable(header(), data);
269 0 : return new_table.Detach();
270 : }
271 :
272 : // static
273 : CALLER_ATTACH EblcTable::Builder*
274 0 : EblcTable::Builder::CreateBuilder(Header* header, WritableFontData* data) {
275 0 : Ptr<EblcTable::Builder> new_builder = new EblcTable::Builder(header, data);
276 0 : return new_builder.Detach();
277 : }
278 :
279 : // static
280 : CALLER_ATTACH EblcTable::Builder*
281 0 : EblcTable::Builder::CreateBuilder(Header* header, ReadableFontData* data) {
282 0 : Ptr<EblcTable::Builder> new_builder = new EblcTable::Builder(header, data);
283 0 : return new_builder.Detach();
284 : }
285 :
286 0 : BitmapSizeTableBuilderList* EblcTable::Builder::GetSizeList() {
287 0 : if (size_table_builders_.empty()) {
288 0 : Initialize(InternalReadData(), &size_table_builders_);
289 0 : set_model_changed();
290 : }
291 0 : return &size_table_builders_;
292 : }
293 :
294 0 : void EblcTable::Builder::Initialize(ReadableFontData* data,
295 : BitmapSizeTableBuilderList* output) {
296 0 : assert(output);
297 0 : if (data) {
298 0 : int32_t num_sizes = data->ReadULongAsInt(Offset::kNumSizes);
299 0 : for (int32_t i = 0; i < num_sizes; ++i) {
300 0 : ReadableFontDataPtr new_data;
301 0 : new_data.Attach(down_cast<ReadableFontData*>(
302 : data->Slice(Offset::kBitmapSizeTableArrayStart +
303 0 : i * Offset::kBitmapSizeTableLength,
304 0 : Offset::kBitmapSizeTableLength)));
305 0 : BitmapSizeTableBuilderPtr size_builder;
306 0 : size_builder.Attach(BitmapSizeTable::Builder::CreateBuilder(
307 0 : new_data, data));
308 0 : output->push_back(size_builder);
309 : }
310 : }
311 0 : }
312 :
313 : } // namespace sfntly
|