首页/新闻资讯/正文详情

C++字体库开发之特性解析十三

发布时间:2026/11/11 13:13:47 来源:云帆数科 栏目:资讯中心
C++字体库开发之特性解析十三
Freetype#include freetype/freetype.h #include freetype/tttables.h #include memory #include set namespace { struct _Script_Lang { FT_Tag script; FT_Tag language; }; #define SCRIPT_kana FT_MAKE_TAG(k, a, n, a) #define SCRIPT_hani FT_MAKE_TAG(h, a, n, i) #define SCRIPT_hang FT_MAKE_TAG(h, a, n, g) #define LANGUAGE_JAN FT_MAKE_TAG(J, A, N, ) #define LANGUAGE_CHN FT_MAKE_TAG(C, H, N, ) #define LANGUAGE_KOR FT_MAKE_TAG(K, O, R, ) const struct _Script_Lang Script_Lang[] {{SCRIPT_kana, LANGUAGE_JAN}, {SCRIPT_hani, LANGUAGE_CHN}, {SCRIPT_hang, LANGUAGE_KOR}}; #define num_Script_Lang (sizeof(Script_Lang) / sizeof(Script_Lang[0])) } // namespace class TagsParse { public: typedef struct { FT_UShort req; FT_UShort count; FT_UShort *list; } LangSys_Item; typedef struct { FT_Tag tag; FT_ULong ptr; LangSys_Item *entry; } LangSys_Record; typedef struct { FT_ULong ptr; LangSys_Item *entry; FT_UShort count; LangSys_Record *list; } Script_Item; typedef struct { FT_Tag tag, ltag; FT_ULong ptr; Script_Item *entry; } Script_Record; typedef struct { FT_UShort count; FT_UShort *list; } Feature_Item; typedef struct { FT_Tag tag; FT_ULong ptr; Feature_Item *entry; } Feature_Record; tagsParse(FT_Face f) : face(f) {} ~tagsParse() { reset(); } void reset() { if (Table || TABLE_length || TABLE_ptr) { free(Table); Table nullptr; TABLE_length 0; TABLE_ptr 0; } if (Script_List || Script_Count) { free(Script_List); Script_List nullptr; Script_Count 0; } if (Feature_List || Feature_Count) { free(Feature_List); Feature_List nullptr; Feature_Count 0; } } inline void need(FT_ULong needed) { if (TABLE_ptr needed TABLE_length) printf(GSUB: Unexpected end of table.); } inline FT_Byte get_Byte(void) { return Table[TABLE_ptr]; } inline signed char get_SByte(void) { return (signed char)Table[TABLE_ptr]; } FT_UShort get_UShort(void) { unsigned int cc; cc get_Byte() 8; cc | get_Byte(); return (FT_UShort)cc; } FT_Short get_Short(void) { int cc; cc get_SByte() 8; cc | get_Byte(); return (FT_Short)cc; } FT_ULong get_ULong(void) { unsigned int cc; cc get_Byte() 24; cc | get_Byte() 16; cc | get_Byte() 8; cc | get_Byte(); return (FT_ULong)cc; } void *mymalloc(size_t len) { void *p; #ifdef SMALLMALLOC if (len 65500L) printf(Cannot allocate more than 64kByte.); #endif if (len) p malloc(len); else p malloc(1); if (p NULL) printf(Out of memory.); return p; } void *mycalloc(size_t nmemb, size_t len) { void *p; p calloc(nmemb ? nmemb : 1, len ? len : 1); if (p NULL) printf(Out of memory.); return p; } void gsub(void) { reset(); FT_Error error; /* * Fetch GSUB table */ if ((error FT_Load_Sfnt_Table(face, FT_MAKE_TAG(G, S, U, B), 0, NULL, TABLE_length))) { #ifdef DEBUG warning(No GSUB data available for vertical glyph presentation forms.); #endif return; } Table (FT_Byte *)mymalloc(TABLE_length); // std::shared_ptrvoid finally(nullptr, [Table](void *p) { free(Table); }); // 退出时自动销毁缓存 if ((error FT_Load_Sfnt_Table(face, FT_MAKE_TAG(G, S, U, B), 0, Table, TABLE_length))) { printf(Cannot load GSUB table (error code 0x%x)., error); return; } fetch_table(Table, TABLE_length); } void gpos(void) { reset(); FT_Error error; /* * Fetch GSUB table */ if ((error FT_Load_Sfnt_Table(face, FT_MAKE_TAG(G, P, O, S), 0, NULL, TABLE_length))) { #ifdef DEBUG warning(No GSUB data available for vertical glyph presentation forms.); #endif return; } Table (FT_Byte *)mymalloc(TABLE_length); // std::shared_ptrvoid finally(nullptr, [Table](void *p) { free(Table); }); // 退出时自动销毁缓存 if ((error FT_Load_Sfnt_Table(face, FT_MAKE_TAG(G, P, O, S), 0, Table, TABLE_length))) { printf(Cannot load GSUB table (error code 0x%x)., error); return; } fetch_table(Table, TABLE_length); } void fetch_table(FT_Byte *Table, FT_ULong TABLE_length) { FT_Error error; int i, j; FT_ULong Script_List_ptr, Feature_List_ptr, Lookup_List_ptr; /* * Read GSUB header */ need(10); if (get_ULong() ! 0x00010000) printf(GSUB: Bad version.); Script_List_ptr get_UShort(); Feature_List_ptr get_UShort(); Lookup_List_ptr get_UShort(); /* * Read Script_List */ TABLE_ptr Script_List_ptr; need(2); Script_Count get_UShort(); #ifdef DEBUG warning(GSUB: Script List with %d entries at 0x%04x., Script_Count, Script_List_ptr); #endif Script_List (Script_Record *)mycalloc(Script_Count, sizeof(Script_Record)); need(6 * Script_Count); for (i 0; i Script_Count; i) { FT_Tag tag get_ULong(); FT_ULong ptr Script_List_ptr get_UShort(); for (j 0; j num_Script_Lang; j) if (tag Script_Lang[j].script) { Script_List[i].tag tag; Script_List[i].ltag Script_Lang[j].language; Script_List[i].ptr ptr; } } /* * Read Feature_List */ TABLE_ptr Feature_List_ptr; need(2); Feature_Count get_UShort(); #ifdef DEBUG warning(GSUB: Feature List with %d entries at 0x%04x., Feature_Count, Feature_List_ptr); #endif Feature_List (Feature_Record *)mycalloc(Feature_Count, sizeof(Feature_Record)); need(6 * Feature_Count); for (i 0; i Feature_Count; i) { FT_Tag tag get_ULong(); FT_ULong ptr Feature_List_ptr get_UShort(); // char a (tag 24) 0xFF; // char b (tag 16) 0xFF; // char c (tag 8) 0xFF; // char d tag 0xFF; tags.insert(tag); } } public: FT_Face face nullptr; FT_ULong Script_List_ptr 0; FT_ULong Feature_List_ptr 0; FT_ULong Lookup_List_ptr 0; FT_ULong TABLE_ptr 0; Script_Record *Script_List nullptr; FT_UShort Script_Count 0; Feature_Record *Feature_List nullptr; FT_UShort Feature_Count 0; FT_ULong TABLE_length 0; FT_Byte *Table nullptr; std::setFT_Tag tags; }; TagsParse parse(face); parse.gsub(); parse.gpos(); parse.tags;Harfbuzz#include hb-ft.h hb_font_t *hb_font hb_ft_font_create(face, NULL); hb_face_t *hb_face hb_ft_face_create_referenced(face); std::setstd::string curFeatSet; for (hb_tag_t table_tag : {HB_OT_TAG_GSUB, HB_OT_TAG_GPOS}) { unsigned int feature_count hb_ot_layout_table_get_feature_tags(hb_face, table_tag, 0, nullptr, nullptr); std::vectorhb_tag_t feature_tags(feature_count); hb_ot_layout_table_get_feature_tags(hb_face, table_tag, 0, feature_count, feature_tags.data()); for (hb_tag_t feature_tag : feature_tags) { char tag_str[5] {0}; hb_tag_to_string(feature_tag, tag_str); curFeatSet.insert(tag_str); } curFeatSet.insert(curFeatSet.begin(), curFeatSet.end()); } hb_face_destroy(face); hb_font_destroy(hb_font);输出fontFeatures: [ aalt, calt, case, ccmp, cpsp, cv01, cv02, cv03, cv04, cv05, cv06, cv07, cv08, cv09, cv10, cv11, dlig, dnom, frac, kern, locl, mark, numr, ordn, pnum, salt, sinf, ss01, ss02, ss03, ss04, subs, sups, tnum, zero ]参考Registered features (OpenType 1.9.1) - Typography | Microsoft LearnC字体库开发之字体包解析十二-CSDN博客texlive/texk/ttf2pk2/ftlib.c at f1f3f83ecefcf1e03bc7c3616aa95e3a8f63396b · Distrotech/texlive · GitHubtexlive-source/texk/ttf2pk2/ftlib.c at 9e55052ce4db6d978ae8190b9e9ec021e5bd50ad · TeX-Live/texlive-source · GitHub创作不易小小的支持一下吧

相关推荐

C++ std::any升级为SafeAny
C++ std::any升级为SafeAny

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/5 0:16:27

初阶数据结构【顺序表及其接口的实现】
初阶数据结构【顺序表及其接口的实现】

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/7 17:06:10

C++文档数据保存与解析
C++文档数据保存与解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/11 4:19:25

工地太忙根本没时间复习考试?万全县低压电工证全国通用怎么考?
工地太忙根本没时间复习考试?万全县低压电工证全国通用怎么考?

工地太忙根本没时间复习考试?万全县低压电工证全国通用怎么考? 工地太忙根本没时间复习考试,但低压电工证又必须拿到手,否则连进场资格都没有。万全县低压电工证虽然在本地办理,但全国通用,这点对很多在外施工的劳务班组来说,是必须了解的。今天就从平… · 2026/11/11 13:13:33

办理咋在网上查电工证需要什么材料
办理咋在网上查电工证需要什么材料

怎么查电工证电子证书网上查证流程全攻略 怕考不过白交培训费?别急,今天就把【咋在网上查电工证】的流程、细节、避坑指南一次性说清楚。现在电工证都是电子证书,查证流程简单,但很多人第一步就卡在不会查,最后耽误了工作。… · 2026/11/11 13:13:33

电工证从哪里发出来?外省证能转过来吗?上岗必备全攻略
电工证从哪里发出来?外省证能转过来吗?上岗必备全攻略

电工证从哪里发出来?外省证能转过来吗?上岗必备全攻略 之前考的证在外省能不能转过来?你不是一个人。很多转岗的、跨省打工的、甚至想换个城市发展的朋友都遇到过这个问题。电工证从哪里发出来,其实关系到你能不能顺利上岗,能不能拿到工资,能不能在新的… · 2026/11/11 13:13:33

你别怕高压操作证和电工证考不过白交培训费,内部消息教你稳过
你别怕高压操作证和电工证考不过白交培训费,内部消息教你稳过

你别怕高压操作证和电工证考不过白交培训费,内部消息教你稳过 你怕高压操作证和电工证考不过白交培训费?这不是怕,这是怕错。我跟你说,每年都有人交了钱,最后连报名都没上,更别说考试了。这不是因为你不行,而是你没搞清楚最新的政策和流程,特别是现在… · 2026/11/11 13:13:33

西安东郊电工证复审多少钱?别被中介坑了,全流程全解析
西安东郊电工证复审多少钱?别被中介坑了,全流程全解析

西安东郊电工证复审多少钱?别被中介坑了,全流程全解析 你是不是正在为西安东郊电工证复审发愁?不知道去哪报名怕被中介坑,还纠结着多少钱?别急,今天我就来带你从头到尾了解清楚,别再花冤枉钱。… · 2026/11/11 13:13:33

沙井哪里可以考电工证,郑州报考避坑指南教你避开常见雷区
沙井哪里可以考电工证,郑州报考避坑指南教你避开常见雷区

沙井哪里可以考电工证,郑州报考避坑指南教你避开常见雷区 工地太忙根本没时间复习考试,这事儿我懂。作为漯河房建工程的一线施工员,我也曾为电工证的事儿头疼不已。报名流程复杂、材料准备繁杂、考试内容难懂,还时不时被“代办机构”骗钱,这些坑我几乎都… · 2026/11/11 13:12:32

电工证丢失还能补吗?千万别踩坑,丢了证等于失业
电工证丢失还能补吗?千万别踩坑,丢了证等于失业

电工证丢失还能补吗?千万别踩坑,丢了证等于失业 你正在找工作,但手里的电工证突然丢了,这下怎么办?别急,先别慌, 电工证丢失还能补吗 ?答案是肯定的,但 千万别踩坑 ,补办流程如果不了解,可能会耽误你上岗、甚至影响到你的收入。… · 2026/11/11 12:18:07

电力电缆作业证直播报名入口与办理流程良心建议
电力电缆作业证直播报名入口与办理流程良心建议

电力电缆作业证直播报名入口与办理流程良心建议 你是不是也担心学历不高报不了名?别急,今天就给你讲讲 电力电缆作业证直播 的报名流程和那些你必须知道的干货, 良心建议 在这里,别错过。 电力电缆作业证直播报名需要什么条件?… · 2026/11/10 17:46:39

英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑
英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑

英德电工证报考费多少钱,怕考不过白交培训费?看完这篇别再踩坑 怕考不过白交培训费?英德电工证报考费多少钱,你真的了解吗?现在市面上培训机构五花八门,价格参差不齐,很多人一不小心就花了冤枉钱,结果还考不过。别急,今天就来给你说清楚英德电工证的… · 2026/11/10 17:11:43

_中职电工证最新政策解读
_中职电工证最新政策解读

中职电工证在哪考?工地太忙根本没时间复习考试的救星来了 工地太忙根本没时间复习考试,这是很多正在备考 中职电工证 的建筑工友的真实写照。你不是不想考,而是真的没时间。但别担心,这期内容是 新乡初次报考人员… · 2026/11/11 0:00:52

昆明电工证培训价格值不值得考?老电工告诉你真相
昆明电工证培训价格值不值得考?老电工告诉你真相

昆明电工证培训价格值不值得考?老电工告诉你真相 之前考的证在外省能不能转过来?这个问题是很多在外地打工、换城市生活、或者是想在昆明发展的朋友最关心的。尤其是现在云南发展快,很多企业都在招持证上岗的电工,如果你手头有证但不在本地,那这个证是不… · 2026/11/11 0:00:52

特种电缆张工网上查询全攻略:外省证如何转过来
特种电缆张工网上查询全攻略:外省证如何转过来

特种电缆张工网上查询全攻略:外省证如何转过来 之前考的证在外省能不能转过来?这是很多特种作业从业者最关心的问题,尤其是像特种电缆张工这类证书,直接关系到日常工作是否合规、能否顺利晋升。很多小伙伴因为证书归属地的问题,陷入职业发展的瓶颈,甚至… · 2026/11/11 0:00:52

双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 20:19:29

STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 19:22:45

DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/10 17:00:47

了解更多?预约专属演示

我们的顾问将为您一对一讲解产品与方案

企业微信二维码