sfntly的C++版本提供的samples并不完善,输入的限制多,裁剪出来的新字体过大。如果需要达到和java版的sfnt tool一样的功能需要参考java库添加代码。
首先,搭建java版的运行环境,安装Eclipse。和C++版调试运行完全不同,作为java小白完全没有遇到障碍,直接以SfntTool.java为入口开始调试。java版本为新字体新建了四个tables (RenumberingSubsetter.java), C++版本需要一一新建出来。
GlyphTable(GlyphTableSubsetter.java):
1) 首先找出源字体中字符的glyph id。参考font_info.cc中的FontSourcedInfoBuilder::GetCharacterMap()函数写出自己的GetGlyphIds()。
2) chrome_subsetter中的SetupGlyfBuilders与java版的逻辑很相似,可以借用。但是loca table的部分要参考java版本的逻辑,生成正确的轻量级loca table。另外, 函数ResolveCompositeGlyphs() 会漏掉space 字符,需修改补全。
glyph_table_builder->GenerateLocaList(&loca_list);
loca_table_builder->SetLocaList(&loca_list);
C++版本的loca_table.cc有一点问题,
int32_t LocaTable::Builder::NumGlyphs() {
//return LastGlyphIndex() - 1;
//Take references as java loca_table, it should be "+ 1";
return LastGlyphIndex() + 1;
}
在生成glyph table的过程中还要注意composite glyph的处理。Chrome_subsetter没有考虑这个部分,要根据java版本的逻辑进行完善。
3) loca table完成后还需要调整MaximumProfileTable,同样参考java版的逻辑。要记得在max_profile_builder->SetNumGlyphs() 之前必须在源字库的基础上new一个max_profile_builder,否则InternalWriteData中的w_data_没有初始值会crash。
font_builder->NewTableBuilder(Tag::maxp, font_->GetTable(Tag::maxp)->ReadFontData());
CMapTable(RenumberingCMapTableSubsetter.java, CMapTableBuilder.java):
1) 在之前查找源字体的glyph id时保存一份新旧glyph id的mapping,然后建立新字体中的unicode和新glyph id的mapping。利用sfntly::CMapTable::CMap::CharacterIterator查找。
2) CMap中的segments的建立可以参考 font_assembler.cc中的FontAssembler::AssembleCMapTable()代码,在边界字符(unicode = 0xffff)的处理方式上和java版本的略有不同,稍加修改即可。
HorizontalMetricsTable(HorizontalMetricsTableSubsetter.java):
1) 找出源字体中各个字符的metrics信息。
2) 算出新字体中metrics总和的size,并进行填充。
WritableFontDataPtr data;
data.Attach(WritableFontData::CreateWritableFontData(size));
int32_t index = 0;
int32_t advanceWidthMax = 0;
for (int32_t i = 0; i < numberOfHMetrics; i++)
{
int32_t advanceWidth = hmetrics[i].advanceWidth;
advanceWidthMax = max(advanceWidth, advanceWidthMax);
index += data->WriteUShort(index, advanceWidth);
index += data->WriteShort(index, hmetrics[i].lsb);
}
for (int32_t i = numberOfHMetrics; i < nMetrics; i++)
{
index += data->WriteShort(index, hmetrics[i].lsb);
}
font_builder->NewTableBuilder(Tag::hmtx, data);
3) 设置HorizontalHeaderTable中的SetNumberOfHMetrics和SetAdvanceWidthMax。同样要记得设置创建新的 table builder.
font_builder->NewTableBuilder(Tag::hhea, font_->GetTable(Tag::hhea)->ReadFontData());
PostScriptTable: C++版本去掉了PostScript table,不用进行处理。
建议base在chrome_subsetter的基础上完成以上的tables。生成出的新字体效果就和java的sfnt tool一样了。
————————————————
版权声明:本文为CSDN博主「Cplusplus_engineer」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Cplusplus_engineer/article/details/72841054