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

news2024/12/25 9:14:58

上一节,我们了解了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*(奇偶规则) 来将路径作为一个裁剪区域

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2112197.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

移远通信高端5G智能模组SG560D-NA率先通过PTCRB认证

近日&#xff0c;移远通信宣布&#xff0c;其基于高通QCM6490平台打造的高端5G智能模组SG560D-NA顺利通过PTCRB认证。 在此之前&#xff0c;该模组还获得了美国FCC和加拿大IC认证&#xff0c;这意味着&#xff0c;其已完全满足北美地区的相关标准和规定&#xff0c;能够支持相关…

pdf压缩到指定大小需要怎么压缩?2024快速进行文件压缩的软件合集

pdf压缩到指定大小需要怎么压缩&#xff1f;2024快速进行文件压缩的软件合集 当你需要将PDF文件压缩到指定的大小时&#xff0c;选择适当的软件和方法可以帮助你在保持文件质量的同时&#xff0c;尽可能地减小文件体积。以下是五款可以帮助你快速压缩PDF文件并控制其大小的软件…

芯片散热设计

目录 摘要 散热方式分类 1.传导 2.对流 对流换热系数 对流方式 3.辐射 热阻 散热器 作用 材质 底部厚度 鳍片 表面处理 压力设计 界面材料 相关标准 摘要 散热设计是硬件设计中的进阶内容&#xff0c;掌握散热原理和设计要点是很有必要的。 散热方式分类 散…

【C++二分查找】1818. 绝对差值和

本文涉及的基础知识点 C二分查找 LeetCode1818. 绝对差值和 给你两个正整数数组 nums1 和 nums2 &#xff0c;数组的长度都是 n 。 数组 nums1 和 nums2 的 绝对差值和 定义为所有 |nums1[i] - nums2[i]|&#xff08;0 < i < n&#xff09;的 总和&#xff08;下标从 …

Java获取小程序码示例(三种小程序码)

首先我们可以看到官方文档上是有三种码的 获取小程序码 这里特别要注意的是第一种和第三种是有数量限制的&#xff0c;所以大家生成的时候记得保存&#xff0c;也不要一直瞎生成 还有一点要注意的是第一种和第二种是太阳码 第三种是方形码 好了直接上代码 这里要注意&#xff…

南京网站设计手机用的网站

近年来&#xff0c;随着移动互联网的快速发展&#xff0c;越来越多的用户通过手机浏览网页&#xff0c;这使得网站设计逐渐向移动端倾斜。在南京&#xff0c;网站设计特别注重适配手机端&#xff0c;这不仅是用户体验的提升&#xff0c;也是市场竞争的需要。一个响应式的网站能…

深度评测热门翻译工具,携手你的翻译得力助手

随着互联网技术的飞速发展&#xff0c;全球化交流日益频繁&#xff0c;跨语言沟通的需求也随之激增。对于外语水平有限的朋友来说&#xff0c;翻译器是一个必不可少的工具。今天我就分享几款我用的翻译器吧。 1.福晰在线翻译 链接直达>>https://fanyi.pdf365.cn/doc …

Java语言的Netty框架+云快充协议1.5+充电桩系统+新能源汽车充电桩系统源码

介绍 云快充协议云快充1.5协议云快充1.6云快充协议开源代码云快充底层协议云快充桩直连桩直连协议充电桩协议云快充源码 软件架构 1、提供云快充底层桩直连协议&#xff0c;版本为云快充1.5&#xff0c;对于没有对接过充电桩系统的开发者尤为合适&#xff1b; 2、包含&…

WebAPI (一)DOM树、DOM对象,操作元素样式(style className,classList)。表单元素属性。自定义属性。间歇函数定时器

文章目录 Web API基本认知一、 变量声明二、 DOM1. DOM 树2. DOM对象3. 获取DOM对象(1)、选择匹配的第一个元素(2)、选择匹配多个元素 三、 操作元素1. 操作元素内容2. 操作元素属性(1)、常用属性&#xff08;href之类的&#xff09;(2)、通过style属性操作CSS(3)、通过类名(cl…

Vivado 约束

步骤5&#xff1a;保存约束 约束管理是设计流程的重要一步&#xff0c;Vivado设计套件 为您提供了在现有约束文件中添加新约束、覆盖的灵活性 现有约束&#xff0c;或创建新的约束文件以跟踪设计更改或完成 缺少约束。 您为设计创建了一些定时异常&#xff0c;但这些异常仅存在…

​​NIFI汉化_替换logo_二次开发_Idea编译NIFI最新源码_详细过程记录_全解析_Maven编译NIFI避坑指南002

继续,执行pom.xml引入依赖以后,发现以下几种报错: 可以看到在下载aws-java-sdk-bundle 1.12.710版本的时候报错了 可以看到日志信息,就是在阿里云上下载的,因为阿里云上缺少这个jar包 aws-java-sdk-bundle-1.12.710.jar 这个jar包,我还特意去阿里云上查询了一下 https://deve…

从零到一:Java三层架构下的图书馆管理系统开发指南

引言 使用JavaSE相关知识完成一个以三层架构为设计规范的图书管理系统&#xff0c;不包括前端页面&#xff08;使用main方法Scanner()模拟用户输入&#xff09;&#xff0c;目的是为了基于一个项目快速了解三层架构的项目设计规范的实践。 开发流程 确认需求导入相关的jar包和…

jmeter 梯度测试 如何查看TPS、RT指标

TPS 服务器处理请求总数/花费的总时间 149371 &#xff08;请求量&#xff09; 113&#xff08;1分53秒&#xff09;1321/秒 跟汇总报告的吞吐量差不多&#xff0c;可以认为吞吐量TPS 平均值&#xff0c;中位数&#xff0c;最大值&#xff0c;最小值的单位都是毫秒ms 下载插…

用Git把本地仓库上传到远程仓库

用Git把本地仓库上传到远程仓库 GitHub创建远程仓库 在创建新仓库界面里输入你的仓库名后点击Create repository就好了。 创建本地项目 当你已经有一个项目后在命令行输入如下指令即可 git init git commit -m "first commit" git branch -M main git remote a…

寄存器映射及地址计算(STM32F407)

上篇文章介绍了存储器映射&#xff08;存储器映射&#xff08;STM32F407&#xff09;-CSDN博客&#xff09;&#xff0c;本文介绍寄存器映射的基本概念。 1、寄存器映射简介 寄存器是一类特殊的存储器&#xff0c;它的每个位都有特定的功能&#xff0c;可以实现对外设/功能的…

ubuntu16.04下qt5.7.1添加对openssl的支持

文章目录 前言一、编译安装openssl二、编译qt5.7.1三、配置qtcreator开发环境四、demo 前言 最近工作中要求客户端和服务端通过ssl加密通信,其中客户端是qt编程,服务端是linux编程.我的开发环境是ubuntu16.04;运行环境是debian9.13,是基于gnu的linux操作系统,64位arm架构. 一…

【数据库】|子查询

子查询 什么叫子查询&#xff1f;如何实现子查询&#xff1f; 定义&#xff1a;什么叫子查询&#xff0c;也就是先执行子查询&#xff0c;后执行父查询 ❓✅面试题&#xff1a;如何实现替换&#xff0c;执行顺序&#xff1f; 1、使用子查询&#xff0c;因为子查询会先执行子…

大语言模型LLM权重4bit向量量化(Vector Quantization)/查找表量化基本原理

参考 https://apple.github.io/coremltools/docs-guides/source/opt-palettization-overview.html https://apple.github.io/coremltools/docs-guides/source/opt-palettization-algos.html Apple Intelligence Foundation Language Models 苹果向量量化&#xff1a; DKM:…

深度学习基础--卷积的变种

随着卷积同经网络在各种问题中的广泛应用&#xff0c;卷积层也逐渐衍生出了许多变种&#xff0c;比较有代表性的有&#xff1a; 分组卷积( Group Convolution )、转置卷积 (Transposed Convolution) 、空洞卷积( Dilated/Atrous Convolution )、可变形卷积( Deformable Convolu…

协程的原理与实现:GMP源码走读

在计算机科学领域&#xff0c;尤其是在现代软件开发中&#xff0c;高并发处理能力是衡量技术架构性能的关键指标之一。Go语言&#xff0c;以其简洁的语法和内置的协程支持&#xff0c;为开发者提供了一套高效且易于使用的并发编程模型。本文深入剖析了Go语言协程的原理与其实现…