当前位置: 首页 > 工具软件 > sfntly > 使用案例 >

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

栾和玉
2023-12-01

      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

 类似资料: