Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: third_party/sfntly/src/subsetter/subsetter_impl.cc

Issue 7381004: Add sfntly library for font subsetting used in print preview. (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: Update sfntly version to the one clang friendly Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « third_party/sfntly/src/subsetter/subsetter_impl.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "third_party/sfntly/src/subsetter/subsetter_impl.h"
18
19 #include <string.h>
20
21 #include <map>
22 #include <set>
23
24 #include "third_party/sfntly/src/sfntly/glyph_table.h"
25 #include "third_party/sfntly/src/sfntly/loca_table.h"
26 #include "third_party/sfntly/src/sfntly/name_table.h"
27 #include "third_party/sfntly/src/sfntly/tag.h"
28 #include "third_party/sfntly/src/sfntly/data/memory_byte_array.h"
29 #include "third_party/sfntly/src/sfntly/port/memory_output_stream.h"
30
31 namespace sfntly {
32
33 void ConstructName(UChar* name_part, UnicodeString* name, int32_t name_id) {
34 switch(name_id) {
35 case NameId::kFullFontName:
36 *name = name_part;
37 break;
38 case NameId::kFontFamilyName:
39 case NameId::kPreferredFamily:
40 case NameId::kWWSFamilyName: {
41 UnicodeString original = *name;
42 *name = name_part;
43 *name += original;
44 break;
45 }
46 case NameId::kFontSubfamilyName:
47 case NameId::kPreferredSubfamily:
48 case NameId::kWWSSubfamilyName:
49 *name += name_part;
50 break;
51 default:
52 // This name part is not used to construct font name (e.g. copyright).
53 // Simply ignore it.
54 break;
55 }
56 }
57
58 int32_t HashCode(int32_t platform_id, int32_t encoding_id, int32_t language_id,
59 int32_t name_id) {
60 int32_t result = platform_id << 24 | encoding_id << 16 | language_id << 8;
61 if (name_id == NameId::kFullFontName) {
62 result |= 0xff;
63 } else if (name_id == NameId::kPreferredFamily ||
64 name_id == NameId::kPreferredSubfamily) {
65 result |= 0xf;
66 } else if (name_id == NameId::kWWSFamilyName ||
67 name_id == NameId::kWWSSubfamilyName) {
68 result |= 1;
69 }
70 return result;
71 }
72
73 SubsetterImpl::SubsetterImpl() {
74 }
75
76 SubsetterImpl::~SubsetterImpl() {
77 }
78
79 bool SubsetterImpl::LoadFont(const char* font_name,
80 const unsigned char* original_font,
81 size_t font_size) {
82 ByteArrayPtr raw_font =
83 new MemoryByteArray((byte_t*)original_font, font_size);
84 if (factory_ == NULL) {
85 factory_.attach(FontFactory::getInstance());
86 }
87
88 FontArray font_array;
89 factory_->loadFonts(raw_font, &font_array);
90 font_ = FindFont(font_name, font_array);
91 if (font_ == NULL) {
92 return false;
93 }
94
95 return true;
96 }
97
98 int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids,
99 size_t glyph_count,
100 unsigned char** output_buffer) {
101 if (factory_ == NULL || font_ == NULL) {
102 return -1;
103 }
104
105 FontPtr new_font;
106 new_font.attach(Subset(glyph_ids, glyph_count));
107 if (new_font == NULL) {
108 return 0;
109 }
110
111 MemoryOutputStream output_stream;
112 factory_->serializeFont(new_font, &output_stream);
113 int length = static_cast<int>(output_stream.size());
114 if (length > 0) {
115 *output_buffer = new unsigned char[length];
116 memcpy(*output_buffer, output_stream.get(), length);
117 }
118
119 return length;
120 }
121
122 Font* SubsetterImpl::FindFont(const char* font_name,
123 const FontArray& font_array) {
124 if (font_array.empty() || font_array[0] == NULL) {
125 return NULL;
126 }
127
128 if (font_name && strlen(font_name)) {
129 for (FontArray::const_iterator b = font_array.begin(), e = font_array.end();
130 b != e; ++b) {
131 if (HasName(font_name, (*b).p_)) {
132 return (*b).p_;
133 }
134 }
135 }
136
137 return font_array[0].p_;
138 }
139
140 bool SubsetterImpl::HasName(const char* font_name, Font* font) {
141 UnicodeString font_string = UnicodeString::fromUTF8(font_name);
142 if (font_string.isEmpty())
143 return false;
144 UnicodeString regular_suffix = UnicodeString::fromUTF8(" Regular");
145 UnicodeString alt_font_string = font_string;
146 alt_font_string += regular_suffix;
147
148 typedef std::map<int32_t, UnicodeString> NameMap;
149 NameMap names;
150 NameTablePtr name_table = down_cast<NameTable*>(font->table(Tag::name));
151
152 for (int32_t i = 0; i < name_table->nameCount(); ++i) {
153 switch(name_table->nameId(i)) {
154 case NameId::kFontFamilyName:
155 case NameId::kFontSubfamilyName:
156 case NameId::kFullFontName:
157 case NameId::kPreferredFamily:
158 case NameId::kPreferredSubfamily:
159 case NameId::kWWSFamilyName:
160 case NameId::kWWSSubfamilyName: {
161 int32_t hash_code = HashCode(name_table->platformId(i),
162 name_table->encodingId(i),
163 name_table->languageId(i),
164 name_table->nameId(i));
165 UChar* name_part = name_table->name(i);
166 ConstructName(name_part, &(names[hash_code]), name_table->nameId(i));
167 break;
168 }
169 default:
170 break;
171 }
172 }
173
174 if (!names.empty()) {
175 for (NameMap::iterator b = names.begin(), e = names.end(); b != e; ++b) {
176 if (b->second.caseCompare(font_string, 0) == 0 ||
177 b->second.caseCompare(alt_font_string, 0) == 0) {
178 return true;
179 }
180 }
181 }
182 return false;
183 }
184
185 CALLER_ATTACH Font* SubsetterImpl::Subset(const unsigned int* glyph_ids,
186 size_t glyph_count) {
187 if (glyph_ids == NULL || glyph_count == 0) {
188 return NULL;
189 }
190
191 // Find glyf and loca table.
192 GlyphTablePtr glyph_table = down_cast<GlyphTable*>(font_->table(Tag::glyf));
193 LocaTablePtr loca_table = down_cast<LocaTable*>(font_->table(Tag::loca));
194 if (glyph_table == NULL || loca_table == NULL) {
195 // The font is invalid.
196 return NULL;
197 }
198
199 // Setup font builders we need.
200 FontBuilderPtr font_builder;
201 font_builder.attach(factory_->newFontBuilder());
202
203 GlyphTableBuilderPtr glyph_table_builder;
204 glyph_table_builder.attach(down_cast<GlyphTable::Builder*>(
205 font_builder->newTableBuilder(Tag::glyf)));
206 LocaTableBuilderPtr loca_table_builder;
207 loca_table_builder.attach(down_cast<LocaTable::Builder*>(
208 font_builder->newTableBuilder(Tag::loca)));
209 if (glyph_table_builder == NULL || loca_table_builder == NULL) {
210 // Out of memory.
211 return NULL;
212 }
213
214 // Sort and uniquify glyph ids.
215 IntegerSet glyph_id_set;
216 glyph_id_set.insert(0); // Always include glyph id 0.
217 for (size_t i = 0; i < glyph_count; ++i) {
218 glyph_id_set.insert(glyph_ids[i]);
219 }
220
221 // Extract glyphs and setup loca list.
222 IntegerList loca_list;
223 loca_list.resize(loca_table->numGlyphs());
224 loca_list.push_back(0);
225 int32_t last_glyph_id = 0;
226 int32_t last_offset = 0;
227 GlyphTable::GlyphBuilderList* glyph_builders =
228 glyph_table_builder->glyphBuilders();
229 for (IntegerSet::iterator i = glyph_id_set.begin(), e = glyph_id_set.end();
230 i != e; ++i) {
231 if (*i < 0 || *i >= loca_table->numGlyphs()) {
232 // Invalid glyph id, ignore.
233 continue;
234 }
235
236 int32_t length = loca_table->glyphLength(*i);
237 if (length == 0) {
238 // Empty glyph, ignore.
239 continue;
240 }
241 int32_t offset = loca_table->glyphOffset(*i);
242
243 GlyphPtr glyph;
244 glyph.attach(glyph_table->glyph(offset, length));
245 if (glyph == NULL) {
246 // Error finding glyph, ignore.
247 continue;
248 }
249
250 // Add glyph to new glyf table.
251 ReadableFontDataPtr data = glyph->readFontData();
252 WritableFontDataPtr copy_data;
253 copy_data.attach(font_builder->getNewData(data->length()));
254 data->copyTo(copy_data);
255 GlyphBuilderPtr glyph_builder;
256 glyph_builder.attach(glyph_table_builder->glyphBuilder(copy_data));
257 glyph_builders->push_back(glyph_builder);
258
259 // Configure loca list.
260 for (int32_t j = last_glyph_id + 1; j <= *i; ++j) {
261 loca_list[j] = last_offset;
262 }
263 last_offset += length;
264 loca_list[*i + 1] = last_offset;
265 last_glyph_id = *i;
266 }
267 for (int32_t j = last_glyph_id + 1; j <= loca_table->numGlyphs(); ++j) {
268 loca_list[j] = last_offset;
269 }
270 loca_table_builder->setLocaList(&loca_list);
271
272 // Setup remaining builders.
273 for (TableMap::iterator i = font_->tables()->begin(),
274 e = font_->tables()->end(); i != e; ++i) {
275 // We already build the builder for glyph and loca.
276 if (i->first != Tag::glyf && i->first != Tag::loca) {
277 // The newTableBuilder() call will alter internal state of font_builder
278 // AND the reference count of returned object. Therefore we need to
279 // dereference it.
280 TableBuilderPtr dereference;
281 dereference.attach(
282 font_builder->newTableBuilder(i->first, i->second->readFontData()));
283 }
284 }
285
286 return font_builder->build();
287 }
288
289 } // namespace sfntly
OLDNEW
« no previous file with comments | « third_party/sfntly/src/subsetter/subsetter_impl.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698