首页 > 其他分享 >PDF标准详解(四)——图形操作符

PDF标准详解(四)——图形操作符

时间:2024-09-06 22:03:58浏览次数:7  
标签:200 300 路径 详解 操作符 400 PDF 100

上一节,我们了解了PDF中cm操作符,它是定义变换矩阵的。同时也了解到re是创建一个矩阵的。上一节也说过,它用来构建一个路径,具体什么是路径,路径有什么作用呢?这些将在本节给出解释

图形操作符是用来在pdf中构建内容并输出到相关设备上进行显示的。pdf中我们能看到的内容几乎都是由图形操作构成的。PDF中主要有6中图形操作符:

  1. 图形状态操作符(Graphics state operator):CTM当前变换矩阵、 current color、 current clipping path。
  2. 路径构造操作符(Path construction operators):线的轨迹,,各种图形。
  3. 绘制路径操作符(Path-painting operators):填充, 描边, 或定义一个剪切区域。
  4. 其他绘图操作符(自我描述图形对象): 图像(image),shading。
  5. 文本操作符(Text operator):从字体(代表文本字符的字面/版式(TYPE-FACES)的描述)中选择,显示字符字形字符操作,例如前面显示hello,world 用到的Tj 操作符
  6. 标记内容操作符(Marked-content Operator): Layers

这一次我们主要介绍前两个,后面的等后续慢慢介绍

路径

路径构建操作符

路径对象主要由直线、矩形框(re)、3次贝塞尔曲线构成。

对于直线来说,我们需要先使用m(moveto) 来将画笔移动到指定位置,然后使用l(lineto) 来表示将画笔移动到某一个点。例如有下面的例子

3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
400 400 m 100 100 l s
endstream   % 流结束
endobj

这里我们定义了一个从 (400, 400) 到(100, 100) 的直线。在画直线的时候,m只能有一个,作为起点,而l可以有多个,每有一个l都表示从画笔的上一个点画一条直线到新的位置。例如我们可以模拟一个画一个矩形

3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
400 400 m 100 100 l s
100 100 m 300 100 l 300 300 l 100 300 l  100 100 l S
endstream   % 流结束
endobj

矩形的例子比较简单,这里就不给出了。我们只需要指定起点坐标并且加上长宽最后用re 操作符作为结束符即可构建

对于贝塞尔曲线来说,我们需要4个点来画出一条曲线,它们的位置如下图所示
在这里插入图片描述
我们需要一个起始和结束位置的点,并且加上两个控制点共同组成一条贝塞尔曲线。
贝塞尔曲线我们使用c来作为操作符,在构建的时候需要使用m来规定起始位置的坐标,然后再跟上上图p1, p2, p3 的坐标来控制曲线。例如下面的例子

3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
100 100 m 200 300 300 400 400 200 c S
endstream   % 流结束
endobj

这样我们构建了一条如下图所示的曲线
在这里插入图片描述
我们对上面出现的操作符做一个总结

操作符 含义
m 设置点的起始位置(moveto)
l 从当前位置构建一条直线到对应位置 (lineto)
rg 构建矩形路径
c 构建贝塞尔曲线

路径显示操作符

上述操作符只能构建一个路径,而这个路径究竟该如何显示,用作何种用途,需要另外给出操作,如果仅仅构建路径,那么页面上是不会有任何显示的,例如上述的内容流,我们稍微做一下更改,去掉最后的S 操作符,我们可以发现之前显示的内容现在不显示了

3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
100 100 m 200 300 300 400 400 200 c % 只构建路径,而不对路径做任何操作,页面不会有路径的内容
endstream   % 流结束
endobj

想要显示路径,我们需要使用 S 操作符。上面的路径,我们在最后加上S 就能显示出图形了。

另外我们可以使用h操作符来构建一个闭合的路径,它是在原来图形的基础之上,使用一条直线将起始点到终点的两个点连接起来构成要给封闭的区间。例如上面使用直线画矩形的例子,我们可以删掉最后一个l 操作符,并使用h 闭合,照样能形成矩形

3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
400 400 m 100 100 l s
100 100 m 300 100 l 300 300 l 100 300 l h S 
endstream   % 流结束
endobj

去掉h 我们将得到一个开口的矩形。这个读者可以自行尝试,这里就不给出结果了。

对于上面的贝塞尔曲线的例子

3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
100 100 m 200 300 300 400 400 200 c h S
endstream   % 流结束
endobj

加上h 之后将得到下面的结果
在这里插入图片描述

描边与填充操作

这里我们采用S对路径勾画出了边框,也就是描边路径,它对应的英文单词是stroke,我们也可以使用f 或者F(fill)来对路径构成的封闭区间进行填充。默认采用黑色进行填充。

3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
100 100 m 200 300 300 400 400 200 c h f
endstream   % 流结束
endobj

在这里插入图片描述
当然也可以提前指定画刷颜色,这个我们在后面介绍颜色空间的时候再介绍如何定义画刷和画笔。

另外也可以使用b或者B(both) 来同时进行描边和填充操作。

非0缠绕规则和奇偶绕组规则

上述图形,我们很明确的仅定义了一个简单的区域,当出现重叠的复杂区域时,该如何进行填充呢?这里有两套不同的填充规则,即非0缠绕规则和奇偶绕组规则。

3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
100 350 200 200 re %生成矩形左上角坐标 (100, 350) 宽高都是200
120 370 160 160 re f %按照非0缠绕规则
400 350 200 200 re %生成矩形左上角坐标 (400, 350) 宽高都是200
420 370 160 160 re f* %按照奇偶缠绕规则
endstream   % 流结束
endobj

这里显示的效果如下
在这里插入图片描述
我们在这里定义了两组矩形,每组有两个矩形路径进行了重叠。第一组采用非0缠绕规则,第二组采用奇偶规则来填充。
我们先以这两个图形为例,来说明这两个规则
在这里插入图片描述
非0规则:

  1. 初始化环绕数到 0 。
  2. 从图形中的任意一点 P 向外任意引一条射线。
  3. 每遇到一条与该线的交叉线,如果射线与路劲的顺时针相交则计数加一,否则计数减一
  4. 假如环绕数不等于 0 ,则点 P 在多边形内。
  5. 但是这个方法有局限性 , 不适合相交 , 或者选一条正切的射线 . 因为射线的方向是任意的 , 这个规则简单的选用射线并不碰到这些情况

例如上面我们定义了两个矩形,这两个矩形划分出了两个区域,也就是图中A和B所在区域。我们从A区域随意一点往外引一条射线。从图上看,射线与两条路劲相交,并且都是顺时针相交,所以这里的技术是2。同理,B点与一条顺时针路径路径计数是1。这两个区域的计数都不是0,所以他们都需要进行填充,因此它显示的是上图左侧的效果

奇偶规则:

  1. 从区域内某一点向外引一条射线。
  2. 简单计算与该射线相交线的数量。
  3. 如果这个数是奇数,则认为点在图形内。
    根据这个规则,我们看到A点的计数是2,是偶数,Bdian的计数是1,是奇数。按照奇偶规则,B点需要填充,而A点不需要进行填充。所以它显示的是上图右侧的效果

我们再看一个例子

3 0 obj     % 页面内容流
<< >>
stream      % 流的开始

150 50 m 150 250 l 250 50 l 50 150 l 350 150 l h f 
550 50 m 550 250 l 650 50 l 450 150 l 750 150 l h f*
endstream   % 流结束
endobj

这里我们画了两个五角星,线条的顺序按照m给出的为起点,每一个l代表笔画移动的一个端点,根据上述给出的值我们可以得到对应路径的环绕方向,具体的分析过程这里就不展开了,有兴趣的小伙伴可以自己尝试着画图分析一下,然后使用pdf阅读软件打开看看效果与预估的是否一样

定义裁剪区域

我们利用一些操作符来定义一个路径,这些路径可以作为图形显示出来,也可以作为一个裁剪区域,在该区域中的内容显示出来,不在该区域的内容则丢弃。

对于给出的路径,我们使用W (非0缠绕)或者 W*(奇偶规则)来定义一个裁剪区域。例如下面有一个例子

3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
100 100 200 200 re h
W %将上述路径设置为裁剪路径
150 150 m 200 200 l S %在裁剪路径中,所以会显示
0 0 m 500 800 l S %只显示裁剪路径中的内容
endstream   % 流结束
endobj

这里我们定义了一个长宽都为200的矩形,并且使用h 将矩形区域封闭,然后使用W来将矩形内部作为裁剪区域,然后在(150, 150) 的位置画一条直线到 (200, 200) 的位置。这两个点都在矩形内部,所以会显示出来,另外再画一条从 (0, 0) 到 (500, 800) 的线条,因为这条线有一部分在裁剪区域外,一部分在裁剪区域内,所以只会显示一部分线条。最终图形呈现的效果如下
在这里插入图片描述

总结

本文主要介绍PDF中基本的图形操作符。一般构建图形的操作符有3中

  1. 使用m 定义画笔的起始位置,然后使用 l 来画一条直线
  2. 或者直接使用 re 操作符来绘制一个矩形
  3. 还可以使用c 来构建贝塞尔曲线

对于构建的路径,可以使用 h 来进行画笔起始位置和终点位置的连线,这个连线一般是一条直线。对于这个路径我们可以使用 S (stroke) 来对路劲进行描边显示或者使用 f(非0缠绕) f*(奇偶规则)进行内容的填充,又或者使用 b(B) 来描边和填充。

我们可以使用 W (非0缠绕)或者 W*(奇偶规则) 来将路径作为一个裁剪区域

标签:200,300,路径,详解,操作符,400,PDF,100
From: https://www.cnblogs.com/lanuage/p/18401134

相关文章

  • MySQL 字符串操作详解和案例示范
    MySQL字符串操作详解MySQL提供了丰富的字符串操作函数,能够对这些字符串进行截取、定位、替换等操作。本文将详细讲解MySQL中的字符串操作函数,包括SUBSTRING()、SUBSTR()、LEFT()、RIGHT()、LOCATE()、POSITION()、FIND_IN_SET()、ELT()、INSERT()和REPLACE(),并分析......
  • jQuery中的大于等于(>=)操作符使用技巧
    jQuery中的大于等于(>=)操作符使用技巧在jQuery中,常常需要对元素的某个属性或数值进行比较,判断是否大于等于某个特定的值。在这种情况下,使用大于等于(>=)操作符是非常常见的。本文将介绍如何在jQuery中使用大于等于操作符的技巧,帮助您更好地进行数据处理和交互操作。基本语法大于等于(>=......
  • Prometheus Alertmanager设置与告警规则配置详解
    PrometheusAlertmanager设置与告警规则配置详解Prometheus是一个开源的监控和告警系统,其设计理念是通过时间序列数据库存储指标数据,并通过多维数据模型和查询语言进行数据分析。Prometheus的告警系统由两部分组成:Prometheus服务器本身和Alertmanager。Alertmanager......
  • 72. 编辑距离算法实现详解
    LeetCode72.编辑距离详解一、题目描述给你两个单词word1和word2,请返回将word1转换成word2所使用的最少操作数。你可以对一个单词进行如下三种操作:插入一个字符。删除一个字符。替换一个字符。示例1:输入:word1="horse",word2="ros"输出:3解释:horse......
  • PyCharm的使用教程详解;PyCharm编程利器安装包下载!
    PyCharm是一款由JetBrains开发的跨平台Python集成开发环境,旨在帮助Python开发者提高效率。它拥有强大的代码编辑、调试和测试工具,能够支持各种Python框架和库的开发。PyCharm还具备自动代码补全、语法高亮、代码导航、版本控制、数据库工具等一系列高级功能,以及可扩展的插件系......
  • Java线程池详解
    线程池解释线程池采用了池化思想,能够有效的管理线程的生命周期,减少了每次获取资源的消耗,提高了资源的利用率。类似池化实现还有数据库连接池、HTTP连接池等好处减少了线程创建和销毁的开销提高了响应速度使得线程更加方便管理常见使用场景量大处理时间较短......
  • Leetcode算法挑战:详解如何实现交替合并字符串的解题思路
    Leetcode算法挑战中的“交替合并字符串”问题,要求我们将两个字符串以交替的方式合并,终形成一个新的字符串。乍一看,这道题目似乎不复杂,但要写出高效且简洁的解法,还需要一定的思路和技巧。一、问题描述题目要求给定两个字符串word1和word2,将它们按照索引依次交替合并。如果某个......
  • 若依框架登录鉴权详解(动态路由)
     编辑若依框架登录鉴权:1.获取token(过期在响应拦截器中实现),2.基于RBAC模型获取用户、角色和权限信息(在路由前置守卫),3.根据用户权限动态生成(从字符串->组件,根据permission添加动态路由信息)和添加路由addRoutes(在路由前置守卫)若依框架(Ruoyi)后端的登录权限身份认证流程是一个复杂但高......
  • 【K8s】专题十三:Kubernetes 容器运行时之 Docker 与 Containerd 详解
    本文内容均来自个人笔记并重新梳理,如有错误欢迎指正!如果对您有帮助,烦请点赞、关注、转发、订阅专栏!专栏订阅入口Linux专栏 | Docker专栏 | Kubernetes专栏往期精彩文章【Docker】(全网首发)KylinV10下MySQL容器内存占用异常的解决方法【Docker】(全网首发)Kyli......
  • TLV62080DSGR高效降压转换器中文资料PDF数据手册引脚图功能框图
    TLV62080的说明TLV6208x系列器件是小型降压转换器,所用外部组件较少,可实现具有成本效益的解决方案。此类器件属于同步降压转换器,其输入电压范围为2.5V/2.7V(TLV62080为2.5V,TLV62084x为2.7V)至6V。TLV6208x器件专注于在宽输出电流范围内实现高效降压转换。该转换器在中等......