C++版本的sfntly库使用示例(二)

来源:互联网 发布:流量充值平台源码 编辑:程序博客网 时间:2024/06/05 03:22

      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一样了。

原创粉丝点击