PDFium 处理通用 `W` 数组的方式

文章目录

    • [PDFium 处理通用 `W` 数组的方式](#PDFium 处理通用 W 数组的方式)
      • [1. `W` 数组的结构与取值](#1. W 数组的结构与取值)
      • [2. PDFium 的通用处理逻辑](#2. PDFium 的通用处理逻辑)
      • 总结

PDFium 处理通用 W 数组的方式

W 数组结构不一定是 [1, 4, 1],PDFium 使用一套通用逻辑来处理各种情况。该逻辑的核心思想是:W 数组的三个值分别指定每个 XRef 条目中类型(Type)字段2(Field2)生成号(Generation Number) 的字节宽度,字段宽度为 0 时表示该字段在流中省略,使用默认值。解析器通过 WidthArray 存储这三个宽度值,并计算每个条目的总字节数,然后通过一个通用的 GetVarInt 函数来读取指定宽度的整数值。

1. W 数组的结构与取值

W 数组是一个包含三个整数的数组,如 [1 4 1],表示类型占 1 字节、字段2占 4 字节、生成号占 1 字节,每个条目共 6 字节。实际中,W 数组可能有各种组合,例如:

  • [0 4 1]: 类型字段宽度为 0,意味着流中不存储类型,应使用默认类型 1。
  • [1 2 1]: 字段2宽度为 2 字节,常用于对象数量较少的小文件。
  • [1 8 2]: 字段2宽度为 8 字节,用于支持超大文件中的偏移量。
  • [1 4 0]: 生成号字段宽度为 0,意味着生成号默认使用 0。
  • [0 8 0]: 类型字段默认 1,生成号默认 0,流中只存储一个 8 字节的字段2。

2. PDFium 的通用处理逻辑

PDFium 通过 LoadCrossRefV5 函数中的三段核心代码实现了对 W 数组的通用处理:

cpp 复制代码
// 从字典中读取 W 数组并存入 WidthArray
std::vector<uint32_t> WidthArray;
for (size_t i = 0; i < pArray->GetCount(); ++i)
    WidthArray.push_back(pArray->GetIntegerAt(i));
uint32_t totalWidth = WidthArray[0] + WidthArray[1] + WidthArray[2];

WidthArray 的每个值可以不同,totalWidth 是动态计算的。随后,GetVarInt 函数被用于解析条目中的整数值:

cpp 复制代码
uint32_t GetVarInt(const uint8_t* p, int32_t n) {
    uint32_t result = 0;
    for (int32_t i = 0; i < n; ++i)
        result = result * 256 + p[i];
    return result;
}

GetVarIntn 参数正是 WidthArray 中的某个值,如 WidthArray[0]WidthArray[1]WidthArray[2]。如果 n 为 0,函数不会执行循环,直接返回 result 的初始值 0。

在解析每个 XRef 条目时,PDFium 使用 WidthArray 来控制解析流程:

cpp 复制代码
const uint8_t* entrystart = segstart + j * totalWidth;
int32_t type = 1;
if (WidthArray[0])
    type = GetVarInt(entrystart, WidthArray[0]);

FX_FILESIZE field2 = GetVarInt(entrystart + WidthArray[0], WidthArray[1]);
int32_t gen = GetVarInt(entrystart + WidthArray[0] + WidthArray[1], WidthArray[2]);

这段代码的逻辑是:

  • 如果 WidthArray[0] 大于 0,则从流中读取 type;否则 type 保持默认值 1。
  • field2 的起始位置是 entrystart + WidthArray[0],读取的字节数是 WidthArray[1],值可以为 0。
  • gen 的起始位置是 entrystart + WidthArray[0] + WidthArray[1],读取的字节数是 WidthArray[2]

这意味着,只要按照 WidthArray 中指定的宽度去读取并解释每个字段,无论 W 数组是 [1,4,1][0,4,1] 还是其他组合,PDFium 都能正确解析。

总结

总结来说,PDFium 通过 动态解析 W 数组按字节流式读取使用通用整数转换 ,以及 对零宽度的字段使用默认值 的方式,实现了对任意 W 数组结构的通用处理,从而保证了其作为 PDF 解析库的兼容性。

如果对具体的字段默认值来源或者解析后的条目如何使用还有疑问,我们可以继续探讨。

相关推荐
王老师青少年编程2 分钟前
csp信奥赛C++高频考点专项训练之贪心算法 --【跳跃与过河问题】:过河问题
c++·算法·贪心·csp·信奥赛·跳跃与过河问题·过河问题
沉默-_-43 分钟前
备战蓝桥杯-哈希
c++·学习·算法·蓝桥杯·哈希算法
拼好饭和她皆失1 小时前
基础算法--写给算法小白的模板指南:快速掌握核心代码,蓝桥杯必备模板
算法
吞下星星的少年·-·1 小时前
rotate函数应用模板
算法
保持清醒5401 小时前
二叉链表实现
数据结构
AI科技星1 小时前
人类首张【全域数学公理体系】黑洞内部结构图—基于「0-1-∞」三元本源的全维深度解析
人工智能·算法·机器学习·数学建模·数据挖掘·量子计算
paeamecium1 小时前
【PAT甲级真题】- Recover the Smallest Number (30)
数据结构·算法·pat考试·pat
Dillon Dong1 小时前
【风电控制】变流器转矩控制回路深度解析:从指令生成到闭环控制
算法·变流器·风电控制
玛丽莲茼蒿1 小时前
Leetcode hot100 在排序数组中查找元素的第一个和最后一个位置【中等】
数据结构·算法
墨染天姬1 小时前
[AI]OPENAI的PPO算法
人工智能·算法