summaryrefslogtreecommitdiffstats
path: root/third_party
diff options
context:
space:
mode:
authorarthurhsu@chromium.org <arthurhsu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-02 03:44:36 +0000
committerarthurhsu@chromium.org <arthurhsu@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-02 03:44:36 +0000
commit8177b1f2a2a5d46c96adfd0b4a1a12a3f6ad871c (patch)
treed3bcb3bfe35f5b2b498dc5570c07d578c255363e /third_party
parent7c57b67ae0a835ed4d4beb2f20a8baf24d780e49 (diff)
downloadchromium_src-8177b1f2a2a5d46c96adfd0b4a1a12a3f6ad871c.zip
chromium_src-8177b1f2a2a5d46c96adfd0b4a1a12a3f6ad871c.tar.gz
chromium_src-8177b1f2a2a5d46c96adfd0b4a1a12a3f6ad871c.tar.bz2
Handle composite glyphs correctly in font subsetter.
BUG=90764 TEST=none Review URL: http://codereview.chromium.org/7535002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@95041 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'third_party')
-rw-r--r--third_party/sfntly/src/subsetter/subsetter_impl.cc100
-rw-r--r--third_party/sfntly/src/subsetter/subsetter_impl.h6
2 files changed, 76 insertions, 30 deletions
diff --git a/third_party/sfntly/src/subsetter/subsetter_impl.cc b/third_party/sfntly/src/subsetter/subsetter_impl.cc
index 290ae9f..92ab14c 100644
--- a/third_party/sfntly/src/subsetter/subsetter_impl.cc
+++ b/third_party/sfntly/src/subsetter/subsetter_impl.cc
@@ -102,8 +102,14 @@ int SubsetterImpl::SubsetFont(const unsigned int* glyph_ids,
return -1;
}
+ IntegerSet glyph_id_processed;
+ if (!ResolveCompositeGlyphs(glyph_ids, glyph_count, &glyph_id_processed) ||
+ glyph_id_processed.empty()) {
+ return 0;
+ }
+
FontPtr new_font;
- new_font.attach(Subset(glyph_ids, glyph_count));
+ new_font.attach(Subset(glyph_id_processed));
if (new_font == NULL) {
return 0;
}
@@ -182,10 +188,11 @@ bool SubsetterImpl::HasName(const char* font_name, Font* font) {
return false;
}
-CALLER_ATTACH Font* SubsetterImpl::Subset(const unsigned int* glyph_ids,
- size_t glyph_count) {
- if (glyph_ids == NULL || glyph_count == 0) {
- return NULL;
+bool SubsetterImpl::ResolveCompositeGlyphs(const unsigned int* glyph_ids,
+ size_t glyph_count,
+ IntegerSet* glyph_id_processed) {
+ if (glyph_ids == NULL || glyph_count == 0 || glyph_id_processed == NULL) {
+ return false;
}
// Find glyf and loca table.
@@ -193,9 +200,66 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const unsigned int* glyph_ids,
LocaTablePtr loca_table = down_cast<LocaTable*>(font_->table(Tag::loca));
if (glyph_table == NULL || loca_table == NULL) {
// The font is invalid.
- return NULL;
+ return false;
+ }
+
+ // Sort and uniquify glyph ids.
+ IntegerSet glyph_id_remaining;
+ glyph_id_remaining.insert(0); // Always include glyph id 0.
+ for (size_t i = 0; i < glyph_count; ++i) {
+ glyph_id_remaining.insert(glyph_ids[i]);
}
+ // Identify if any given glyph id maps to a composite glyph. If so, include
+ // the glyphs referenced by that composite glyph.
+ while (!glyph_id_remaining.empty()) {
+ IntegerSet comp_glyph_id;
+ for (IntegerSet::iterator i = glyph_id_remaining.begin(),
+ e = glyph_id_remaining.end(); i != e; ++i) {
+ if (*i < 0 || *i >= loca_table->numGlyphs()) {
+ // Invalid glyph id, ignore.
+ continue;
+ }
+
+ int32_t length = loca_table->glyphLength(*i);
+ if (length == 0) {
+ // Empty glyph, ignore.
+ continue;
+ }
+ int32_t offset = loca_table->glyphOffset(*i);
+
+ GlyphPtr glyph;
+ glyph.attach(glyph_table->glyph(offset, length));
+ if (glyph == NULL) {
+ // Error finding glyph, ignore.
+ continue;
+ }
+
+ if (glyph->glyphType() == GlyphType::kComposite) {
+ Ptr<GlyphTable::CompositeGlyph> comp_glyph =
+ down_cast<GlyphTable::CompositeGlyph*>(glyph.p_);
+ for (int32_t j = 0; j < comp_glyph->numGlyphs(); ++j) {
+ int32_t glyph_id = comp_glyph->glyphIndex(j);
+ if (glyph_id_processed->find(glyph_id) == glyph_id_processed->end() &&
+ glyph_id_remaining.find(glyph_id) == glyph_id_remaining.end()) {
+ comp_glyph_id.insert(comp_glyph->glyphIndex(j));
+ }
+ }
+ }
+
+ glyph_id_processed->insert(*i);
+ }
+
+ glyph_id_remaining.clear();
+ glyph_id_remaining = comp_glyph_id;
+ }
+}
+
+CALLER_ATTACH Font* SubsetterImpl::Subset(const IntegerSet& glyph_ids) {
+ // The tables are already checked in ResolveCompositeGlyphs().
+ GlyphTablePtr glyph_table = down_cast<GlyphTable*>(font_->table(Tag::glyf));
+ LocaTablePtr loca_table = down_cast<LocaTable*>(font_->table(Tag::loca));
+
// Setup font builders we need.
FontBuilderPtr font_builder;
font_builder.attach(factory_->newFontBuilder());
@@ -211,13 +275,6 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const unsigned int* glyph_ids,
return NULL;
}
- // Sort and uniquify glyph ids.
- IntegerSet glyph_id_set;
- glyph_id_set.insert(0); // Always include glyph id 0.
- for (size_t i = 0; i < glyph_count; ++i) {
- glyph_id_set.insert(glyph_ids[i]);
- }
-
// Extract glyphs and setup loca list.
IntegerList loca_list;
loca_list.resize(loca_table->numGlyphs());
@@ -226,26 +283,13 @@ CALLER_ATTACH Font* SubsetterImpl::Subset(const unsigned int* glyph_ids,
int32_t last_offset = 0;
GlyphTable::GlyphBuilderList* glyph_builders =
glyph_table_builder->glyphBuilders();
- for (IntegerSet::iterator i = glyph_id_set.begin(), e = glyph_id_set.end();
- i != e; ++i) {
- if (*i < 0 || *i >= loca_table->numGlyphs()) {
- // Invalid glyph id, ignore.
- continue;
- }
-
+ for (IntegerSet::const_iterator i = glyph_ids.begin(), e = glyph_ids.end();
+ i != e; ++i) {
int32_t length = loca_table->glyphLength(*i);
- if (length == 0) {
- // Empty glyph, ignore.
- continue;
- }
int32_t offset = loca_table->glyphOffset(*i);
GlyphPtr glyph;
glyph.attach(glyph_table->glyph(offset, length));
- if (glyph == NULL) {
- // Error finding glyph, ignore.
- continue;
- }
// Add glyph to new glyf table.
ReadableFontDataPtr data = glyph->readFontData();
diff --git a/third_party/sfntly/src/subsetter/subsetter_impl.h b/third_party/sfntly/src/subsetter/subsetter_impl.h
index 7994689..7f27250 100644
--- a/third_party/sfntly/src/subsetter/subsetter_impl.h
+++ b/third_party/sfntly/src/subsetter/subsetter_impl.h
@@ -59,8 +59,10 @@ class SubsetterImpl {
private:
Font* FindFont(const char* font_name, const FontArray& font_array);
bool HasName(const char* font_name, Font* font);
- CALLER_ATTACH Font* Subset(const unsigned int* glyph_ids,
- size_t glyph_count);
+ bool ResolveCompositeGlyphs(const unsigned int* glyph_ids,
+ size_t glyph_count,
+ IntegerSet* glyph_id_processed);
+ CALLER_ATTACH Font* Subset(const IntegerSet& glyph_ids);
FontFactoryPtr factory_;
FontPtr font_;