C++ 阅读「;表格「;在C++;

C++ 阅读「;表格「;在C++;,c++,c,c++11,data-structures,C++,C,C++11,Data Structures,我目前正在查看,并注意到它谈论了很多关于“表”的内容。我的理解是,这些表是数据结构的表示,但是通过我的谷歌搜索,我没有发现关于如何从我的TTF文件中提取这些数据、如何计算每个表占用多少字符、如何从另一个表中确定一个表的解释,如何确定每个表中的每个数据段 目前我所知道的是,我得到了每一条信息(例如)的数据类型,这可能有助于我确定表中的每一条数据,但这又回到了不理解如何确定表本身在文件中的位置的问题 如果有人能解释这一原理,或者展示任何简短但注释良好的代码片段来帮助我更好地理解这一点,我将不胜感激。

我目前正在查看,并注意到它谈论了很多关于“表”的内容。我的理解是,这些表是数据结构的表示,但是通过我的谷歌搜索,我没有发现关于如何从我的TTF文件中提取这些数据、如何计算每个表占用多少字符、如何从另一个表中确定一个表的解释,如何确定每个表中的每个数据段

目前我所知道的是,我得到了每一条信息(例如)的数据类型,这可能有助于我确定表中的每一条数据,但这又回到了不理解如何确定表本身在文件中的位置的问题


如果有人能解释这一原理,或者展示任何简短但注释良好的代码片段来帮助我更好地理解这一点,我将不胜感激。

第一种方法是仔细研究提到的苹果文档,它确实包含数据结构的描述。您还可以查看并了解这些数据结构在实际代码中是如何处理的。

user3159253非常正确-您链接到的文档提供了您需要的所有信息。。。例如:

请注意,searchRange、entrySelector和rangeShift都乘以16,16表示目录项的大小

表4:偏移子表

鉴于:

表5:表目录

您可以继续编码:

struct Table_Directory_Entry
{
    uint32 tag_;
    uint32 checkSum_;
    uint32 offset_;
    uint32 length_;
};

const void* p_ttf = ...;
const Offset_Subtable* p_os = static_cast<const Offset_Subtable*>(p_ttf);
... use any data you're interested in...
for (int table_num = 1; table_num <= p_os->numTables_; ++table_num)
{
    const Table_Directory_Entry* p_tde =
        reinterpret_cast<const Table_Directory_Entry*>(&p_os[1]);
    ... use the table directory entry data ...
}
struct Table\u目录\u条目
{
uint32标签;
uint32校验和;
uint32偏移量;
uint32长度;
};
常数void*p_ttf=。。。;
const Offset_Subtable*p_os=静态转换(p_ttf);
... 使用您感兴趣的任何数据。。。
对于(int table_num=1;table_num numTables++table_num)
{
const Table_Directory_Entry*p_tde=
重新解释铸造(p_os[1]);
…使用表目录条目数据。。。
}
……等等

现在,一些原始数据非常混乱(“神奇的”哨兵值,您更喜欢将结果视为来自
枚举的值的整数,需要乘、除或偏移的数字,以产生人们可能直观地期望它们保持的值),因此添加像
这样的小辅助函数是_-truetype()
是一个很好的开始,您可以进一步防止使用原始字段,方法是在将
is_truetype()
等公开为
public
成员函数时,将原始字段设置为private


如果您需要您的结构具有不属于TTF内容的额外数据,那么这种将原始数据强制转换到您的结构以帮助您解析/解释它的方法将崩溃。相反,您可以使用这种仅原始数据结构中的一种来方便地解释原始内存,支持在堆栈或堆上或全局/静态范围内创建的更高级别的类,该类在给定原始数据结构的指针或引用的情况下对自身进行初始化。这可以在构造函数、赋值操作符、流式
操作符>
或任何常规成员函数中完成-无论您发现什么适合您的代码。然后,您可以在标准容器等中提取并持久化解析的数据。

我应该提到,将所描述的数据结构直接转换为C struct并不十分安全:您不可避免地会遇到数据对齐/填充和endiannes问题
#pragma pack
uu属性(packed))
帮助,但并不总是如此。因此,只有当您对目标平台架构和其他性能有绝对把握时,才应该使用这些结构
struct Offset_Subtable;
{
    uint32 scaler_type_;
    uint16 numTables_;
    uint16 searchRange_;
    uint16 entrySelector_;
    uint16 rangeShift_;

    bool is_for_macOS() { return scaler_type_ == 0x74727565; }
    bool is_for_windoes() { return scaler_type_ == 0x00010000; }
    bool is_truetype() { return scaler_type_ == 0x74727565 ||
                         scaler_type_ == 0x00010000; }
    bool is_postscript() { return scaler_type_ == 0x74797031; }
};
Type    Name    Description
uint32  tag     4-byte identifier
uint32  checkSum    checksum for this table
uint32  offset  offset from beginning of sfnt
uint32  length  length of this table in byte (actual length not padded length)
struct Table_Directory_Entry
{
    uint32 tag_;
    uint32 checkSum_;
    uint32 offset_;
    uint32 length_;
};

const void* p_ttf = ...;
const Offset_Subtable* p_os = static_cast<const Offset_Subtable*>(p_ttf);
... use any data you're interested in...
for (int table_num = 1; table_num <= p_os->numTables_; ++table_num)
{
    const Table_Directory_Entry* p_tde =
        reinterpret_cast<const Table_Directory_Entry*>(&p_os[1]);
    ... use the table directory entry data ...
}