使用 iText 在横向模式下绘制线条

2024-01-04

这是我用来画线的代码。

double[] lineArray = annotation.getAsArray(PdfName.L).asDoubleArray();
double x1 = lineArray[0] - rect.getAsNumber(0).doubleValue();
double y1 = lineArray[1] - rect.getAsNumber(1).doubleValue();
double x2 = lineArray[2] - rect.getAsNumber(0).doubleValue();
double y2 = lineArray[3] - rect.getAsNumber(1).doubleValue();

cs.moveTo(x1, y1);
cs.lineTo(x2, y2);

其中 cs 是 PdfAppearance,注释是 PdfAnnotation,而 rect 是 PdfArray rect = comment.getAsArray(PdfName.RECT);

这在肖像中效果很好。但是来吧,横向模式,例如270度旋转,坐标错位。我还通过 cs.transform() 进行了旋转,因此我的 0,0 会被旋转,但它什么也不做。

知道可能缺少什么吗?


来源

这个答案涵盖了OP通过评论中的谷歌驱动器链接提供的更新的源代码:

public static void main(String[] args) throws Exception {
    PdfReader reader = new PdfReader("src");
    PdfStamper stamper = new PdfStamper(reader, new FileOutputStream("dest"));

    Rectangle location = new Rectangle(544.8f, 517.65f, 663f, 373.35f);

    PdfArray lineEndings = new PdfArray();
    lineEndings.add(new PdfName("None"));
    lineEndings.add(new PdfName("None"));

    PdfAnnotation stamp = PdfAnnotation.createLine(stamper.getWriter(), location, 
        "comment",  550.05f, 510.9f, 656.25f, 378.6f);
    stamp.put(new PdfName("LE"), lineEndings);
    stamp.put(new PdfName("IT"), new PdfName("Line"));
    stamp.setBorderStyle(new PdfBorderDictionary(1, PdfBorderDictionary.STYLE_SOLID));
    stamp.setColor(PdfGraphics2D.prepareColor(Color.RED));
    stamp.put(PdfName.ROTATE, new PdfNumber(270));
    stamper.addAnnotation(stamp, 1);

    addAppearance(stamper, stamp, location);

    stamper.close();
    reader.close();
}

private static void addAppearance(PdfStamper stamper, PdfAnnotation stamp, Rectangle location) {
    PdfContentByte cb = stamper.getOverContent(1);
    PdfAppearance app = cb.createAppearance(location.getWidth(),  location.getHeight());        

    PdfArray rect = stamp.getAsArray(PdfName.RECT);
    Rectangle bbox = app.getBoundingBox();

    double[] lineArray = stamp.getAsArray(PdfName.L).asDoubleArray();
    double x1 = lineArray[0] - rect.getAsNumber(0).doubleValue();
    double y1 = lineArray[1] - rect.getAsNumber(1).doubleValue();
    double x2 = lineArray[2] - rect.getAsNumber(0).doubleValue();
    double y2 = lineArray[3] - rect.getAsNumber(1).doubleValue();

    app.moveTo(x1, y1);
    app.lineTo(x2, y2);

    app.stroke();
    stamp.setAppearance(PdfName.N, app);
}

没有出现

在 Chrome 中查看生成的 PDF 时的第一个观察结果是,正如 OP 在评论中所说的那样:

什么也没有出现

检查 PDF,原因很清楚:注释没有外观流。因此,有限的 PDF 查看器只能通过外观流显示注释,而不能通过描述性值显示注释,例如 Chrome 中的集成查看器不会显示注释。

这是由于 OP 在其代码中调用 iText 功能的顺序造成的:

    [... create annotation object stamp ...]
    stamper.addAnnotation(stamp, 1);

    addAppearance(stamper, stamp, location);

所以他首先通过以下方式将注释添加到PDF中:stamper.addAnnotation然后创建一个外观并将其附加到stamp object.

这个顺序是错误的。在使用 iText 的情况下,我们必须意识到该库会尝试尽早将添加内容写入输出流以减少其内存占用。 (顺便说一句,这是 iText 在服务器应用程序环境中的重要功能之一,在服务器应用程序中可能必须并行处理多个 PDF。)

所以已经在stamper.addAnnotation(stamp, 1)注解被写入输出流,由于还没有出现,所以输出流中的注解是没有出现的。后来的addAppearance调用仅向注释的内存中表示添加外观,该外观将不再被序列化。

将顺序更改为

    [... create annotation object stamp ...]
    addAppearance(stamper, stamp, location);

    stamper.addAnnotation(stamp, 1);

生成带有画线的 PDF。不幸的是,没有达到所需的位置,但这是另一个问题。

位置错误

这条线的位置和方向都错误的原因是基于 iText 的一个特性,该特性已经成为一个话题这个答案 https://stackoverflow.com/a/43466487/1729265 and in 这个答案 https://stackoverflow.com/a/40930180/1729265:

对于旋转页面,iText 试图减轻在绘制直立文本所需的页面内容中添加旋转和平移的负担,并将坐标系原点设置在用户肩膀的页面左下角,这样用户就不会完全处理页面旋转。因此,它对于注释也是如此。

由于您已经有了要使用的实际坐标,iText 的这种“帮助”会损坏您的注释。正如其他答案中所讨论的,不幸的是没有明确的开关来关闭该机制;不过,有一个简单的解决方法:在进行操作之前,只需删除页面旋转条目,然后再次将其添加回来:

PdfReader reader = ...;
PdfStamper stamper = ...;

// hide the page rotation
PdfDictionary pageDict = reader.getPageN(1);
PdfNumber rotation = pageDict.getAsNumber(PdfName.ROTATE);
pageDict.remove(PdfName.ROTATE);

Rectangle location = new Rectangle(544.8f, 517.65f, 663f, 373.35f);

PdfArray lineEndings = new PdfArray();
lineEndings.add(new PdfName("None"));
lineEndings.add(new PdfName("None"));

PdfAnnotation stamp = PdfAnnotation.createLine(stamper.getWriter(), location, 
    "comment",  550.05f, 510.9f, 656.25f, 378.6f);
stamp.put(new PdfName("LE"), lineEndings);
stamp.put(new PdfName("IT"), new PdfName("Line"));
stamp.setBorderStyle(new PdfBorderDictionary(1, PdfBorderDictionary.STYLE_SOLID));
stamp.setColor(PdfGraphics2D.prepareColor(Color.RED));
stamp.put(PdfName.ROTATE, new PdfNumber(270));

addAppearance(stamper, stamp, location);

stamper.addAnnotation(stamp, 1);

// add page rotation again if required
if (rotation != null)
    pageDict.put(PdfName.ROTATE, rotation);

stamper.close();
reader.close();

这似乎是根据需要创建注释外观。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 iText 在横向模式下绘制线条 的相关文章

随机推荐

  • Visual Studio 2008 中的 .NET 2.0 安装项目

    我开发了一个针对 net 2 0 的 win forms 应用程序 所有这些都在 Visual Studio 2008 sp1 中 我这样做是因为我并不真正需要应用程序中的 3 0 功能 我不希望客户在可以安装半大型框架的情况下必须安装一个
  • Kotlin:Kotlin 脚本 (.kts) 无法使用常规代码?

    在我的库的代码库中 我有这个包函数 fun sayHello println Hello there 该函数在包中定义org jire pomade 我想在一个 kts像这样的文件 sayHello 不幸的是 我似乎无法让除了 Kotlin
  • 在从 VSTS 进行新部署之前删除 Azure 上的文件和文件夹

    作为 VSTS 中构建过程的一部分 我想在新部署之前从我的 Azure 站点中删除所有文件和文件夹 除了少数几个 我的猜测是 使用 Azure Powershell 脚本将是一个好主意 我更喜欢制作内联脚本 我使用 Azure 资源管理器作
  • 如何使用 useEffect() 更改 React-Hook-Form defaultValue?

    我正在创建一个页面 供用户使用 React Hook Form 更新个人数据 加载分页后 我使用useEffect获取用户当前的个人数据并将其设置为表单的默认值 我将获取的值放入defaultValue of
  • libvlc_new 始终返回 NULL

    我尝试做教程示例 https wiki videolan org LibVLC Tutorial libvlc 的工作 我通过安装了vlc SDKsudo apt install libvlc dev并链接到它 lvlc 编译和链接完成时没
  • 在移动 Safari 中忽略 Overflow-x 值

    我们将body和可滚动元素上的overflow x值设置为隐藏 但移动Safari会忽略这些值 在桌面上 溢出值工作正常 相关代码 body overflow x hidden width 320px height 100 min heig
  • 如何修复状态为“已拒绝”的 dig 命令?

    我需要帮助修复被拒绝的状态 我看了一下named conf一切看起来都很好 我什至改变了allow query to any 它曾经是localhost dig xxx com ns1 xxx com lt lt gt gt DiG 9 8
  • C++中的时差

    有谁知道如何计算 C 中的时间差 以毫秒为单位 我用了difftime http linux die net man 3 difftime但它对于我想要测量的东西来说没有足够的精度 我知道这是一个老问题 但 C 0x 有一个更新的答案 有一
  • 如何避免在 GEKKO 中创建许多二进制切换变量

    我通过最小化数千个方程来求解 14 个变量IMODE 3 in GEKKO 每个方程都是真实响应与 P 样条模型预测之间的平方误差 i e 惩罚 B 样条 eq i m Minimize y true i spline coeffs kno
  • Python:如何创建函数?例如f(x) = ax^2

    我想要对函数进行某种引用 但我不知道是否需要使用def f x or a lambda某种 例如我想print f 3 并让它输出9a 或者这不是 python 的工作原理 第二个问题 假设我有一个工作函数 我如何返回degree of i
  • Excel VBA 在 Windows 10 中回答 Internet Explorer 11 下载提示?

    我正在尝试自动下载 csv 文件http www nasdaqomxnordic com http www nasdaqomxnordic com使用 Excel 2010 VBA 和 Internet Explorer 如何使用 保存 自
  • 如何消除 iPad 应用程序主窗口上的圆角?

    我见过一些 iPad 应用程序填满屏幕 例如 Stanza 或在状态栏下方形成方形角 例如 iPod 播放器顶部有方形角 底部看不出来 有人知道这是怎么做到的吗 默认情况下 顶层 UIWindow 似乎应用了一个剪切区域 因为我放置在该窗口
  • 显示网络浏览器设置

    使用不同的网络浏览器及其版本号字符串以及无数的配置列表确实很痛苦 我想知道是否有人想出了一个网页 可以将浏览器设置转储到浏览器 以便可以保存并转发给开发人员 Thanks 像这样的东西吗 http mybrowserinfo com det
  • 预期是二维数组,却得到一维数组,而是错误

    我得到的错误为 ValueError 需要 2D 数组 却得到 1D 数组 array 45000 50000 60000 80000 110000 150000 200000 300000 500000 1000000 如果数据具有单个特
  • 委托、Lambda 和 LINQ,天哪!

    作为一名相当初级的开发人员 我遇到了一个突出我经验不足和知识漏洞的问题 如果这里的序言太长 请原谅 我发现自己参与的一个项目需要学习许多 对我而言 新技术 其中包括 LINQ 用于该项目的 OBJECTS 和 XML 等 到目前为止我读到的
  • 如何获取使用“文本数字”的字体的升序或降序高度

    我对文本数字有疑问 参见维基百科 http en wikipedia org wiki Text figures 在使用以下命令创建的 PDF 文档中itextsharp 基线和数字最低点之间的距离 例如9 与字体的正常下降高度不同 使用下
  • 验证多态关联模型中的范围唯一性

    是的 所以我有一个多态关联 允许收藏不同的对象类型 所以一个人可以喜欢一个产品 一个人 或者其他什么 我想要做的是防止有人使用验证收藏夹模型中的唯一性来复制收藏夹 class Favorite lt ActiveRecord Base be
  • XMLHttpRequest 与 HttpRequest

    有谁知道 什么是XMLHttpRequest使网页能够执行普通网页无法完成的操作HttpRequest XMLHttpRequest http en wikipedia org wiki XMLHttpRequest是一个标准的 javas
  • 如何使用 Pandas 的时间戳按小时对数据帧进行分组

    我有以下使用时间戳索引的数据帧结构 neg neu norm pol pos date time 1520353341 0 000 1 000 0 0000 0 000000 0 000 1520353342 0 121 0 879 0 2
  • 使用 iText 在横向模式下绘制线条

    这是我用来画线的代码 double lineArray annotation getAsArray PdfName L asDoubleArray double x1 lineArray 0 rect getAsNumber 0 doubl