当前位置: 首页 > news >正文

PDF 转 HTML5 —— HTML5 填充图形不支持 Even-Odd 奇偶规则?(第二部分)

这是关于该主题的第二部分。如果你还没有阅读第一部分,请先阅读,以便理解“绕组规则”的问题。

快速回顾一下:HTML5 只支持 Non-Zero(非零)绕组规则,而 PDF 同时支持 Non-Zero 和 Even-Odd(奇偶)两种规则。
这意味着我们必须对使用了 Even-Odd 填充规则的图形做些处理,否则它们在 HTML5 中可能无法正确显示。

为了演示这个问题,我会用以下这个例子:

看上去只是个红色的圆?
我第一次看到的时候也是这么想的。直到我把填充改为描边模式,才意识到它实际上是什么。

为了帮助理解发生了什么,我们再来看一张图,加上箭头,显示路径的绘制方向。

我们首先想到的是,可能需要改变图形的绘制方式。最直接的想法就是改变路径的方向,也就是“转换”成 Non-Zero 绕组规则的等价图形。

交替使用顺时针和逆时针方向可行吗?
值得一试,看看会发生什么。反正只需要一分钟时间试一下。

结果证明,这其实挺头疼的。如果只是用 lineTo 画个方框还好说,但涉及贝塞尔曲线的话,情况就复杂得多。

如果你只是简单地反转绘制指令的顺序,就会得到像这样的问题:

控制点的顺序会影响曲线的绘制方式。那么,我们能否也反转控制点的顺序呢?

哦——这样也不太对。我们使用的是 bezierCurveTo,它的意思是:从当前位置(由上一个绘图命令决定)开始,通过两个控制点绘制一段曲线,终点是我们指定的位置。这就意味着我们还必须反向地重新组织控制点和终点的顺序,这样曲线才能按正确的方式被绘制出来。

做对了之后,我们就能反转路径方向,让图形按预期绘制出来:

那么问题解决了吗?没有。

对于我们的“禁止通行”标志来说,或许可以这样处理——我们可以手动控制路径的顺序和方向。但在现实世界中,这种做法不能适用于通用场景。我们不可能为每个具体的 PDF 文件都手动处理,我们需要的是一套普适的代码逻辑,让它能应对任何 PDF 文件。

这也就意味着交替改变路径方向并不能真正解决问题。比如看一下我们禁止通行标志在这种方式下的效果:

我的下一个想法是:用背景色填充被遮挡的区域。但这也行不通,因为路径的绘制顺序还是关键。即使我们把两个 “D” 字母填充为白色,当外面的圆形被填充时,它还是会把我们之前的工作覆盖掉。

而且如果两个形状只是部分重叠,那么只有重叠部分才需要“未填充”。更关键的是,这些“未填充”的部分是真正的透明区域,如果你用背景色填充,就会失去透明性,导致我们无法在后面放其他图层,比如显示“你不可以做这件事”的提示。

那怎么办?
如果不能改变绘制顺序,也不能改变路径方向,也不能通过填色伪装,我们还能怎么改造图形,让它在使用 Non-Zero 绕组规则时正常显示?

或许我们可以非常巧妙地将图形切割成许多小块,然后分析每一块该如何绘制,再分别填充这些小块。

像这样:

_____
|   __|__
|__|__|  |
   |_____|

 _____
|   __|
|__|
    __
   |__|
       __
    __|  |
   |_____|
 

但这就太复杂了。对于我们的需求来说,有点大材小用了。而且,这种做法计算量大,会降低我们转换器的性能。更现实的是,我也没那么聪明,写不出来这样的算法。

其实从我开始研究这些形状开始,脑海里就一直有一个小声音在说:
“要不,我们干脆把这些图形输出成图片得了?”

确实,这样做是可行的,但并不理想。实际上,使用 Non-Zero 和 Even-Odd 绕组规则绘制图形,最终渲染结果真正不同的情况并不多。

所以,如果我们每次遇到 Even-Odd 绘制规则就输出成图片,那会产生大量没必要的图像文件。

这也不理想,因为矢量图形本身非常好用:缩放不会失真,从 PDF 转到 HTML5 非常快速,占用空间也远远小于图片。

那我们还能怎么办?

我们只能妥协。
最合理的做法就是:设定一套规则,只有当图形符合某些特定条件时,才把它输出为图片。
其余情况我们仍然尽可能用原始的路径绘制方式进行呈现。这样,在保持性能和显示效果之间取得一个平衡。

我们的主页:PDF 转 HTML5、Java 图像库、Java PDF SDK - IDRsolutions

 

http://www.xdnf.cn/news/880993.html

相关文章:

  • 智慧赋能:新能源汽车充电桩应用现状与管理升级方案
  • 矩阵分解相关知识点总结(二)
  • Playwright 测试框架 - Java
  • 【缺陷】温度对半导体缺陷电荷态跃迁能级的影响
  • React 样式方案与状态方案初探
  • AiPy实战:10分钟用AI造了个音乐游戏!
  • c++ 通过XOR自己实现一个对称分组加密算法
  • 谷歌披露威胁组织攻击方式:伪造Salesforce数据加载器实施钓鱼攻击
  • 使用 uv 工具快速部署并管理 vLLM 推理环境
  • [10-1]I2C通信协议 江协科技学习笔记(17个知识点)
  • 网站首页菜单两种布局vue+elementui顶部和左侧栏导航
  • 为什么需要自动下载浏览器驱动?
  • Linux(13)——Ext系列⽂件系统
  • Amazing晶焱科技:电子系统产品在多次静电放电测试后的退化案例
  • RKNN3588上部署 RTDETRV2
  • Day45
  • [Git] 分布式版本控制 远程仓库协作
  • C语言输入函数
  • 1、Go语言基础中的基础
  • Django之表格上传
  • Linux服务器如何安装wps?
  • Java中List的forEach用法详解
  • ObjectMapper 在 Spring 统一响应处理中的作用详解
  • 稳定币的深度剖析与展望
  • 探秘实验室铁地板:科技与安全的完美结合
  • Bug问题
  • Axure零基础跟我学:展开与收回
  • 【Axure高保真原型】图片列表添加和删除图片
  • 企业配电系统安全升级,从局放监测开始
  • vue-18(使用 Vuex 插件实现高级功能)