PAYATHON 2026

如何使用 PoDoFo 设置 PDF 中整段文本或单个单词的颜色?

数据小许

在支持 GraphicsState.SetNonStrokingColor 的 PoDoFo 版本中,先设置非描边颜色,再调用 DrawText,就能改变普通填充文本的颜色。如果只想给某个单词着色,可以把文本拆成几段,切换颜色后分别绘制。

为什么要设置非描边颜色?

PDF 区分填充颜色和描边颜色。普通文本默认以填充方式显示,因此需要设置非描边颜色。PoDoFo 对应的接口是 painter.GraphicsState.SetNonStrokingColor(...),声明见官方 PdfPainter.h。

创建 PdfColor 对象本身不会改变绘制状态,还需要将它传给颜色设置接口。

如何将整段文本设为红色?

将原示例中注释掉的颜色设置部分替换为下面的调用,放在 DrawText 之前:

painter.TextState.SetFont(*font, 18.0);

painter.GraphicsState.SetNonStrokingColor(
    PdfColor(1.0, 0.0, 0.0));

painter.DrawText(
    "Hello World!", 56.69, page.GetRect().Height - 56.69);

这里使用 RGB 颜色,各分量的范围为 0.0 到 1.0,(1.0, 0.0, 0.0) 表示红色。PoDoFo 仓库也有一条针对示例颜色设置方式的修正记录。

颜色设置会影响后续使用该绘制状态的操作,不会修改已经绘制的文字。如果只想临时改变颜色,可以成对使用 Save() 和 Restore()。

如何只将一个单词设为红色?

以 Hello World! 为例,将 World 显示为红色,其余文字保持黑色。保留原示例的文档、页面和字体初始化代码,将原来的单次 DrawText 调用替换为:

painter.TextState.SetFont(*font, 18.0);

const double x = 56.69;
const double y = page.GetRect().Height - 56.69;

const double prefixWidth =
    font->GetStringLength("Hello ", painter.TextState);
const double wordWidth =
    font->GetStringLength("World", painter.TextState);

painter.GraphicsState.SetNonStrokingColor(
    PdfColor(0.0, 0.0, 0.0));
painter.DrawText("Hello ", x, y);

painter.Save();
painter.GraphicsState.SetNonStrokingColor(
    PdfColor(1.0, 0.0, 0.0));
painter.DrawText("World", x + prefixWidth, y);
painter.Restore();

painter.DrawText("!", x + prefixWidth + wordWidth, y);

GetStringLength 根据字体和当前 PdfTextState 计算文本宽度,返回值以 PDF 单位计,可用于确定下一段文字的起点,详见官方 PdfFont 文档。测量 Hello 时需要保留末尾空格,否则单词之间会缺少间隔。

使用时需要注意什么?

  • 原问题没有提供 PoDoFo 版本。以上写法以安装版本提供这些接口为前提;如果成员不存在,应核对对应版本的头文件和API 迁移说明,避免混用不同版本的示例。
  • 在解引用 font 前检查 SearchFont("Arial") 的返回值,并单独处理字体查找失败的情况。
  • 分段示例适用于这里的简单英文单行文本。涉及复杂文字塑形、连字或自动换行时,需要结合实际排版过程处理,不能假定在任意位置拆分后字形和间距都保持不变。
  • 绘制结束后,保留原示例中的 painter.FinishDrawing(),再调用 document.Save(...)。

备注:内容仅供参考。