之前我们了解了PDF文档的基本结构,并且展示了一个简单的hello world。这个hello world 虽然只在页面中显示一个hello world 文字,但是包含的内容却是不少。这次我们仍然以它为切入点,来了解PDF的坐标系统以及坐标变换的相关知识
图形学中二维图形变换
中学我们学习了平面直角坐标系,x轴沿着水平方向从左往右递增,Y轴沿着竖直方向,从下往上坐标递增。而PDF的坐标系与数学中的坐标系相同。但是PDF的坐标是有单位的,PDF的坐标单位为磅,一般来说他们与英寸等的转化关系为
 1 磅 = 1/72 英寸
 因为PDF需要做到设备无关,也是就是在不同的显示像素和打印机上,显示的长度都一致,所以这里不能采用像素做单位。但是我们可以通过相关的接口来将这个单位转化为像素。例如在Windows平台可以通过下列的代码来获取一英寸有多少像素
HDC hdc = GetDC(NULL);
short cxInch = GetDeviceCaps(hdc, LOGPIXELSX);
short cyInch = GetDeviceCaps(hdc, LOGPIXELSY);
ReleaseDC(NULL, hdc);
 
对于我的显示器来说,水平和竖直方向都是 1英寸=96像素
有了这些概念之后,我们来看一个例子,下面是在页面的(200, 200) 位置画一个 长宽都为100的正方形
3 0 obj % 页面内容流
 << >>
 stream % 流的开始
 200 200 100 100 re S
 endstream % 流结束
 endobj
之前说过,页面显示内容在页面流中,因此这里我们将内容放置到页面流对象中。前面的200 200 是矩形的起始位置。后面的100 100 分别是长和宽。re 代表我们要构建一个矩形,最后的S表示要显示这个图形。严格意义上来说,re 和S都是路径构造所使用的操作符。这里的矩形也不单单是一个图形,它是一个路径。关于他们的概念将在后面继续介绍。下面我们来介绍基本的2D图形变换
平移

假设一个点原始坐标是(x1, x2),那么沿着x轴平移a,y轴平移b,那么平移之后点的坐标为 (x1 + a, x2 + b) ,转换成矩阵就是
  
      
       
        
         
         
           [ 
          
          
           
            
             
             
               x 
              
             
            
            
             
             
               y 
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
         
         
           [ 
          
          
           
            
             
             
               1 
              
             
            
            
             
             
               0 
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
             
               0 
              
             
            
            
             
             
               1 
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
             
               a 
              
             
            
            
             
             
               b 
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
        
          = 
         
         
         
           [ 
          
          
           
            
             
              
              
                x 
               
              
                + 
               
              
                a 
               
              
             
            
            
             
              
              
                y 
               
              
                + 
               
              
                b 
               
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
        
       
         \begin{bmatrix} x & y & 1\end{bmatrix} \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ a & b & 1 \end{bmatrix} = \begin{bmatrix}x + a & y + b & 1\end{bmatrix} 
        
       
     [xy1] 
              10a01b001 
              =[x+ay+b1]
旋转

 利用中学的知识可以知道
  
      
       
        
         
         
           x 
          
         
           1 
          
         
        
          = 
         
        
          r 
         
        
          ∗ 
         
        
          c 
         
        
          o 
         
        
          s 
         
        
          ( 
         
        
          θ 
         
        
          + 
         
        
          ψ 
         
        
          ) 
         
        
            
         
        
          = 
         
        
          r 
         
        
          ∗ 
         
        
          ( 
         
        
          c 
         
        
          o 
         
        
          s 
         
        
          θ 
         
        
          ∗ 
         
        
          c 
         
        
          o 
         
        
          s 
         
        
          ψ 
         
        
          − 
         
        
          s 
         
        
          i 
         
        
          n 
         
        
          θ 
         
        
          ∗ 
         
        
          s 
         
        
          i 
         
        
          n 
         
        
          ψ 
         
        
          ) 
         
        
            
         
        
          = 
         
        
          x 
         
        
          ∗ 
         
        
          c 
         
        
          o 
         
        
          s 
         
        
          θ 
         
        
          − 
         
        
          y 
         
        
          s 
         
        
          i 
         
        
          n 
         
        
          θ 
         
        
       
         x_1 = r * cos(\theta+\psi) \ = r*(cos\theta*cos\psi-sin\theta*sin\psi) \ = x*cos\theta-ysin\theta 
        
       
     x1=r∗cos(θ+ψ) =r∗(cosθ∗cosψ−sinθ∗sinψ) =x∗cosθ−ysinθ
同理,我们可以得到
  
      
       
        
         
         
           y 
          
         
           1 
          
         
        
          = 
         
        
          r 
         
        
          ∗ 
         
        
          s 
         
        
          i 
         
        
          n 
         
        
          ( 
         
        
          θ 
         
        
          + 
         
        
          ψ 
         
        
          ) 
         
        
            
         
        
          = 
         
        
          r 
         
        
          ∗ 
         
        
          ( 
         
        
          s 
         
        
          i 
         
        
          n 
         
        
          θ 
         
        
          ∗ 
         
        
          c 
         
        
          o 
         
        
          s 
         
        
          ψ 
         
        
          + 
         
        
          c 
         
        
          o 
         
        
          s 
         
        
          θ 
         
        
          ∗ 
         
        
          s 
         
        
          i 
         
        
          n 
         
        
          ψ 
         
        
          ) 
         
        
            
         
        
          = 
         
        
          x 
         
        
          ∗ 
         
        
          s 
         
        
          i 
         
        
          n 
         
        
          θ 
         
        
          + 
         
        
          y 
         
        
          ∗ 
         
        
          c 
         
        
          o 
         
        
          s 
         
        
          θ 
         
        
       
         y_1 = r * sin(\theta+\psi) \ = r * (sin\theta*cos\psi+cos\theta*sin\psi)\ = x*sin\theta+y*cos\theta 
        
       
     y1=r∗sin(θ+ψ) =r∗(sinθ∗cosψ+cosθ∗sinψ) =x∗sinθ+y∗cosθ
转换成矩阵就是
  
      
       
        
         
         
           [ 
          
          
           
            
             
             
               x 
              
             
            
            
             
             
               y 
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
         
         
           [ 
          
          
           
            
             
              
              
                c 
               
              
                o 
               
              
                s 
               
              
                θ 
               
              
             
            
            
             
              
              
                s 
               
              
                i 
               
              
                n 
               
              
                θ 
               
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
              
              
                − 
               
              
                s 
               
              
                i 
               
              
                n 
               
              
                θ 
               
              
             
            
            
             
              
              
                c 
               
              
                o 
               
              
                s 
               
              
                θ 
               
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
             
               0 
              
             
            
            
             
             
               0 
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
        
          = 
         
         
         
           [ 
          
          
           
            
             
              
              
                x 
               
              
                ∗ 
               
              
                c 
               
              
                o 
               
              
                s 
               
              
                θ 
               
              
                − 
               
              
                y 
               
              
                ∗ 
               
              
                s 
               
              
                i 
               
              
                n 
               
              
                θ 
               
              
             
            
            
             
              
              
                x 
               
              
                ∗ 
               
              
                s 
               
              
                i 
               
              
                n 
               
              
                θ 
               
              
                + 
               
              
                y 
               
              
                ∗ 
               
              
                c 
               
              
                o 
               
              
                s 
               
              
                θ 
               
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
        
       
         \begin{bmatrix} x & y & 1\end{bmatrix} \begin{bmatrix} cos\theta & sin\theta & 0 \\ -sin\theta & cos\theta & 0 \\ 0 & 0 & 1 \end{bmatrix} = \begin{bmatrix}x*cos\theta - y*sin\theta & x*sin\theta+y*cos\theta & 1\end{bmatrix} 
        
       
     [xy1] 
              cosθ−sinθ0sinθcosθ0001 
              =[x∗cosθ−y∗sinθx∗sinθ+y∗cosθ1]
缩放
缩放就是将坐标扩大或者缩小为原来的多少倍,我们可以很清楚的知道
  
      
       
        
         
         
           x 
          
         
           1 
          
         
        
          = 
         
        
          x 
         
        
          ∗ 
         
        
          a 
         
         
         
           y 
          
         
           1 
          
         
        
          = 
         
        
          y 
         
        
          ∗ 
         
        
          b 
         
        
       
         x_1=x*a y_1=y*b 
        
       
     x1=x∗ay1=y∗b
这里的a和b都是缩放的系数
 利用矩阵表示就是
  
      
       
        
         
         
           [ 
          
          
           
            
             
             
               x 
              
             
            
            
             
             
               y 
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
         
         
           [ 
          
          
           
            
             
             
               a 
              
             
            
            
             
             
               0 
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
             
               0 
              
             
            
            
             
             
               b 
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
             
               0 
              
             
            
            
             
             
               0 
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
        
       
         \begin{bmatrix} x & y & 1\end{bmatrix} \begin{bmatrix} a & 0 & 0 \\ 0 & b & 0 \\ 0 & 0 & 1\end{bmatrix} 
        
       
     [xy1] 
              a000b0001 
              
pdf 矩阵变换
还有另外几种变换,这里就不一一列举了。现在我们知道二维图形的变换使用一个矩阵就能进行描述。所以PDF在变换图形的时候直接使用的是变换的矩阵。另外我们观察到对于二维变换来说,最后一列一直都是 0 0 1这三个数字。所以pdf中设置变换矩阵时忽略最后一列,仅仅保留前两列,采用6个数字
  
      
       
        
        
          [ 
         
         
          
           
            
            
              a 
             
            
           
           
            
            
              b 
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
            
              c 
             
            
           
           
            
            
              d 
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
            
              e 
             
            
           
           
            
            
              f 
             
            
           
           
            
            
              1 
             
            
           
          
         
        
          ] 
         
        
       
         \begin{bmatrix}a & b & 0 \\ c & d & 0 \\ e & f & 1\end{bmatrix} 
        
       
      
              acebdf001 
              
这个矩阵在PDF中表现为 a b c d e f。
回到我们之前hello的例子中,我们在 hello world 字符流开始的时候,给定了几个数字
 1. 0. 0. 1. 50. 700. cm
 各个数字之间采用空格隔开,这里数字后面跟的点表示它是一个浮点数。我们可以将这一列数字写成如下的矩阵
  
      
       
        
        
          [ 
         
         
          
           
            
            
              1.0 
             
            
           
           
            
            
              0.0 
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
            
              0.0 
             
            
           
           
            
            
              1.0 
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
            
              50.0 
             
            
           
           
            
            
              700.0 
             
            
           
           
            
            
              1 
             
            
           
          
         
        
          ] 
         
        
       
         \begin{bmatrix}1.0 & 0.0 & 0 \\ 0.0 & 1.0 & 0 \\ 50.0 & 700.0 & 1 \end{bmatrix} 
        
       
      
              1.00.050.00.01.0700.0001 
              
这个矩阵我们叫做当前变换矩阵 (Current Transformation Matrix CTM),最后的cm表示使用该矩阵进行图形变换。它是current matrix 的缩写
所以上述这一串数值的意思就是将 hello world 这个字符串平移到页面坐标 (50, 700) 的位置
PDF 中控制图形变换的操作符
现在我们利用这个上述知识来做一个小练习。我们将一个长宽都为100 的矩形在 (200, 200) 位置逆时针旋转45°
 绕任意点旋转,可以先将该点移动到坐标原点,然后按照坐标原点的进行旋转的公式进行计算,最后再将坐标点平移回原来的位置。这个过程产生3个变换矩阵
平移矩阵
  
      
       
        
        
          [ 
         
         
          
           
            
            
              1 
             
            
           
           
            
            
              0 
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
            
              0 
             
            
           
           
            
            
              1 
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
             
             
               − 
              
              
              
                C 
               
              
                x 
               
              
             
            
           
           
            
             
             
               − 
              
              
              
                C 
               
              
                y 
               
              
             
            
           
           
            
            
              1 
             
            
           
          
         
        
          ] 
         
        
       
         \begin{bmatrix}1 & 0 & 0 \\ 0 & 1 & 0 \\ -C_x & -C_y & 1\end{bmatrix} 
        
       
      
              10−Cx01−Cy001 
              
旋转矩阵
  
      
       
        
        
          [ 
         
         
          
           
            
             
             
               c 
              
             
               o 
              
             
               s 
              
             
               θ 
              
             
            
           
           
            
             
             
               s 
              
             
               i 
              
             
               n 
              
             
               θ 
              
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
             
             
               − 
              
             
               s 
              
             
               i 
              
             
               n 
              
             
               θ 
              
             
            
           
           
            
             
             
               c 
              
             
               o 
              
             
               s 
              
             
               θ 
              
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
            
              0 
             
            
           
           
            
            
              0 
             
            
           
           
            
            
              1 
             
            
           
          
         
        
          ] 
         
        
       
         \begin{bmatrix}cos\theta & sin\theta & 0 \\ -sin\theta & cos\theta & 0 \\ 0 & 0 & 1\end{bmatrix} 
        
       
      
              cosθ−sinθ0sinθcosθ0001 
              
平移矩阵
  
      
       
        
        
          [ 
         
         
          
           
            
            
              1 
             
            
           
           
            
            
              0 
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
            
              0 
             
            
           
           
            
            
              1 
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
             
             
               C 
              
             
               x 
              
             
            
           
           
            
             
             
               C 
              
             
               y 
              
             
            
           
           
            
            
              1 
             
            
           
          
         
        
          ] 
         
        
       
         \begin{bmatrix}1 & 0 & 0 \\ 0 & 1 & 0 \\ C_x & C_y & 1\end{bmatrix} 
        
       
      
              10Cx01Cy001 
              
我们将这三个矩阵相乘
  
      
       
        
         
         
           [ 
          
          
           
            
             
             
               1 
              
             
            
            
             
             
               0 
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
             
               0 
              
             
            
            
             
             
               1 
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
              
              
                − 
               
               
               
                 C 
                
               
                 x 
                
               
              
             
            
            
             
              
              
                − 
               
               
               
                 C 
                
               
                 y 
                
               
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
        
          ∗ 
         
         
         
           [ 
          
          
           
            
             
              
              
                c 
               
              
                o 
               
              
                s 
               
              
                θ 
               
              
             
            
            
             
              
              
                s 
               
              
                i 
               
              
                n 
               
              
                θ 
               
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
              
              
                − 
               
              
                s 
               
              
                i 
               
              
                n 
               
              
                θ 
               
              
             
            
            
             
              
              
                c 
               
              
                o 
               
              
                s 
               
              
                θ 
               
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
             
               0 
              
             
            
            
             
             
               0 
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
        
          ∗ 
         
         
         
           [ 
          
          
           
            
             
             
               1 
              
             
            
            
             
             
               0 
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
             
               0 
              
             
            
            
             
             
               1 
              
             
            
            
             
             
               0 
              
             
            
           
           
            
             
              
              
                C 
               
              
                x 
               
              
             
            
            
             
              
              
                C 
               
              
                y 
               
              
             
            
            
             
             
               1 
              
             
            
           
          
         
           ] 
          
         
        
       
         \begin{bmatrix}1 & 0 & 0 \\ 0 & 1 & 0 \\ -C_x & -C_y & 1\end{bmatrix} * \begin{bmatrix}cos\theta & sin\theta & 0 \\ -sin\theta & cos\theta & 0 \\ 0 & 0 & 1\end{bmatrix} * \begin{bmatrix}1 & 0 & 0 \\ 0 & 1 & 0 \\ C_x & C_y & 1\end{bmatrix} 
        
       
      
              10−Cx01−Cy001 
              ∗ 
              cosθ−sinθ0sinθcosθ0001 
              ∗ 
              10Cx01Cy001 
              
最终得到这样一个矩阵
  
      
       
        
        
          [ 
         
         
          
           
            
             
             
               c 
              
             
               o 
              
             
               s 
              
             
               θ 
              
             
            
           
           
            
             
             
               s 
              
             
               i 
              
             
               n 
              
             
               θ 
              
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
             
             
               − 
              
             
               s 
              
             
               i 
              
             
               n 
              
             
               θ 
              
             
            
           
           
            
             
             
               c 
              
             
               o 
              
             
               s 
              
             
               θ 
              
             
            
           
           
            
            
              0 
             
            
           
          
          
           
            
             
              
              
                C 
               
              
                x 
               
              
             
               − 
              
              
              
                C 
               
              
                x 
               
              
             
               c 
              
             
               o 
              
             
               s 
              
             
               θ 
              
             
               + 
              
              
              
                C 
               
              
                y 
               
              
             
               s 
              
             
               i 
              
             
               n 
              
             
               θ 
              
             
            
           
           
            
             
              
              
                C 
               
              
                y 
               
              
             
               − 
              
              
              
                C 
               
              
                x 
               
              
             
               s 
              
             
               i 
              
             
               n 
              
             
               θ 
              
             
               − 
              
              
              
                C 
               
              
                y 
               
              
             
               c 
              
             
               o 
              
             
               s 
              
             
               θ 
              
             
            
           
           
            
            
              1 
             
            
           
          
         
        
          ] 
         
        
       
         \begin{bmatrix}cos\theta & sin\theta & 0 \\ -sin\theta & cos\theta & 0 \\ C_x - C_xcos\theta+C_ysin\theta & C_y-C_xsin\theta-C_ycos\theta & 1\end{bmatrix} 
        
       
      
              cosθ−sinθCx−Cxcosθ+CysinθsinθcosθCy−Cxsinθ−Cycosθ001 
              
 因此这里可以这样写
3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
200 200 100 100 re S %原始矩形
0.7 0.7 -0.7 0.7 200 -80 cm%进行坐标变换
200 200 100 100 re S %变换后的矩形
endstream   % 流结束
endobj
 
这样我们可以得到如下所示的图形
 
 这个时候我们会发现,同样是(200, 200) 的位置,在变换前和变换后,得到不一样的图形,这就说明我们的坐标系统被改变了。不再是水平和竖直方向的x y轴了。如果我们想要它变回原来的位置该怎么办?
在GDI或者其他框架的图形编程中,在改变画笔、画刷等图形状态的时候,会首先保存原来的,然后更新,最后再还原。同样在PDF中,也存在有这样的保存和还原的操作符。我们使用q/Q这么一对操作符来完成保存和还原的操作。
我在原来的基础上,再加一个矩形,在(400, 400) 位置画一个长宽都是100的矩形
3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
200 200 100 100 re S %原始矩形
0.7 0.7 -0.7 0.7 200 -80 cm%进行坐标变换
200 200 100 100 re S %变换后的矩形
400 400 100 100 re S % 这个矩形是相对于 (200, 200) 这个点旋转了45°的矩形
endstream   % 流结束
endobj
 
我们再采用q/Q这一对操作符来保存和还原图形状态
3 0 obj     % 页面内容流
<< >>
stream      % 流的开始
200 200 100 100 re S %原始矩形
q
0.7 0.7 -0.7 0.7 200 -80 cm%进行坐标变换
200 200 100 100 re S %变换后的矩形
Q
400 400 100 100 re S % 这个矩形是相对于 (400, 400) 这个点旋转了45°的矩形
endstream   % 流结束
endobj
 
这个时候我们发现它已经在(400, 400) 这个位置画了一个矩形。没有任何的图形变换
PDF中将图形状态保存成一个栈结构,每次执行q就是将当前图形状态进行入栈,使用Q将之前保存在栈顶的图形状态进行出栈,并还原成当前图形状态。一般来说q/Q必须成对出现。
 好了,本节到这里就结束了。本节主要介绍了图形变换矩阵以及PDF中变换矩阵的操作符cm以及q/Q 这一对保存和还原图形状态的操作符



















