PostScript——学习postscrip

本文转载自:https://www.cnblogs.com/wurui1994/p/6290969.html

 

1.前言

  PostScript是一种编程语言,直译为"后处理脚本"[相对印刷过程而言],学名为页面描述语言。更为详细的解释见维基百科,以及其翻译版百度百科

  值得一提的是,PostScript于1985年由Adobe推出,而Adobe的软件Photoshop 1.0版本于1990发布,两者的缩写均为PS。虽然就知名度而言,PhotoShop更为人所熟知,但是在Adobe的发家史中,PostScript扮演着非常重要的作用,时至今日PostScript的衍生技术PDF已经是一项ISO标准。

  老实说,关于PostScript的基础知识,大家看维基百科的介绍以及附录的四本书就够了,四本书分别是:PostScript语言参考PostScript语言教程与手册PostScript程序设计数学图表:几何与PostScript手册 。本文只是介绍PostScript的简单绘图知识。

  大多数人开始接触PostScript大概是因为LaTeX,参考如何在论文中画出漂亮的插图?中 地铁风 的回答。LaTeX中常用的矢量图格式是EPS[Encapsulated PostScript],不过对PDF格式的支持应该是最好的。大多数与LaTeX相关的绘图与渲染都是基于PostScript技术的,如PSTricksTikZ /PGFMetaPost以及AsymptoteTexample.net上有大量关于Tikz的例子Asymptote官网也有大量 asy的例子

2.简单例子

  在学习之前,你需要两个软件:GhostScriptSumatraPDF。GhostScript是PostScript的一个开源解释器;SumatraPDF是一个文档阅读器,默认支持PDF,结合GhostScript可以支持PostScript。

  HelloWorld的例子,保存到文本文件HelloWorld.ps, 用SumatraPDF打开:

%!PS
 /Courier                     % name the desired font
 20 selectfont              % choose the size in points and establish 
                                  % the font as the current one
 72 500 moveto           % position the current point at 
                                  % coordinates 72, 500 (the origin is at the 
                                  % lower-left corner of the page)
 (Hello world!) show     % stroke the text in parentheses
 showpage                  % print all on the page

  下面给出C语言生成PostScript图案的一个简单例子:

#include <math.h>
#include <stdio.h>
void init(FILE* fp)
{
    int w=640,h=480;
    fputs("%!PS-Adobe-3.0 EPSF-3.0\n",fp);
    fprintf(fp,"%%%%BoundingBox: 0 0 %d %d\n",w,h);
    fputs("/rgb {setrgbcolor} def\n",fp);
    fputs("/np {newpath} def\n",fp);
    fputs("/cp {closepath} def\n",fp);
    fputs("/mt {moveto} def\n",fp);
    fputs("/ll {lineto} def\n",fp);
    fputs("/st {stroke} def\n",fp);
    fputs("/lw {setlinewidth} def\n",fp);
    fputs("/line {np mt ll st} def\n",fp);
}
void close(FILE* fp)
{
    fputs("showpage\n%%EOF",fp);
    fclose(fp);
}
void line(FILE* fp,float x[],float y[],int n)
{
    fprintf(fp,"0 0 1 rgb\nnp\n%.3f %.3f mt\n",x[0],y[0]);
    for(int i=1;i<n;i++){
        fprintf(fp,"%.3f %.3f ll\n",x[i],y[i]);
    }
    fprintf(fp,"st\n");
}
#define N 628
int main()
{

    FILE* fp=fopen("main.ps","wb");
    init(fp);
    //
    float x[N],y[N],t;
    for(int i=0;i<N;i++){
        t=-3.14+i/100.0;
        x[i]=200*sin(3*t)*cos(t)+320;
        y[i]=200*sin(3*t)*sin(t)+240;
    }
    line(fp,x,y,N);
    //
    close(fp);
    return 0;
}

  如图所示,更多的例子可以看之前提到的四本书,三维绘图请看第四本数学图表:几何与PostScript手册

  

   另一个简单例子,可以作为一个练习,更多例子见星云的彼岸的GitHub:LearnPostScript

  

3.复杂一点的例子

  这个例子需要一点三维旋转矩阵的知识,代码仅作演示:

#include <math.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#define Random rand()%255
#define Length(x) (sizeof(x)/sizeof(x[0])/3)
const float PI=3.1415926536;
typedef float vector3[3];
//三维点数组结构
typedef struct {
    int length;
    float *x, *y, *z;
}PointArray ;
//
//三维点初始化
PointArray Array3d(int n)
{
    PointArray r;
    r.length = n;
    r.x = (float*)malloc(n*sizeof(float));
    r.y = (float*)malloc(n*sizeof(float));
    r.z = (float*)malloc(n*sizeof(float));
    for (int i = 0; i < n; i++) {
        r.x[i] = r.y[i] = r.z[i] = 0.0;
    }
    return r;
}
//三维点通过数组赋值
PointArray eval(float *a, int n)
{
    PointArray r;
    r.length = n;
    r.x = (float*)malloc(n*sizeof(float));
    r.y = (float*)malloc(n*sizeof(float));
    r.z = (float*)malloc(n*sizeof(float));
    for (int i = 0; i < n; i++) {
        r.x[i] = a[3*i];
        r.y[i] = a[3*i + 1];
        r.z[i] = a[3*i + 2];
    }
    return r;
}
//输出三维点数组的数据
void print(PointArray r)
{
    for (int i = 0; i < r.length; i++) {
        printf("%f %f %f\n", r.x[i], r.y[i], r.z[i]);
    }
}
//
void fileprint(FILE* fp,PointArray r)
{
    for (int i = 0; i < r.length; i++) {
        fprintf(fp,"%f %f ", r.x[i], r.y[i], r.z[i]);
    }
    fprintf(fp," quad\n");
}
//
//对三维点进行旋转
void Rotate(PointArray pa, vector3 vec,float t)
{
    float x,y,z,a,b,c;
    float base=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
    a=vec[0]/base,b=vec[1]/base,c=vec[2]/base;
    for (int i = 0; i < pa.length; i++) {
        x=pa.x[i],y=pa.y[i],z=pa.z[i];
        //
        pa.x[i]=(cos(t)+(1-cos(t))*a*a)*x+
                ((1-cos(t))*a*b-sin(t)*c)*y+
                ((1-cos(t))*a*c+sin(t)*b)*z;
        //
        pa.y[i]=((1-cos(t))*b*a+sin(t)*c)*x+
                (cos(t)+(1-cos(t))*b*b)*y+
                ((1-cos(t))*b*c-sin(t)*a)*z;
        //
        pa.z[i]=((1-cos(t))*c*a-sin(t)*b)*x+
                ((1-cos(t))*c*b+sin(t)*a)*y+
                (cos(t)+(1-cos(t))*c*c)*z;
    }
}
//
void RotateX(PointArray pa,float t)
{
    float x,y,z;

    for (int i = 0; i < pa.length; i++) {
        x=pa.x[i],y=pa.y[i],z=pa.z[i];

        pa.x[i]=x;
        //
        pa.y[i]=y*cos(t)-z*sin(t);
        //
        pa.z[i]=y*sin(t)+z*cos(t);
    }
}
//
void RotateY(PointArray pa,float t)
{
    float x,y,z;
    for (int i = 0; i < pa.length; i++) {
        x=pa.x[i],y=pa.y[i],z=pa.z[i];
        //
        pa.x[i]=z*sin(t)+x*cos(t);
        pa.y[i]=y;
        pa.z[i]=z*cos(t)-x*sin(t);
    }
}
//
void RotateZ(PointArray pa,float t)
{
    float x,y,z;
    for (int i = 0; i < pa.length; i++) {
        x=pa.x[i],y=pa.y[i],z=pa.z[i];
        pa.x[i]=x*cos(t)-y*sin(t);
        pa.y[i]=x*sin(t)+y*cos(t);
        pa.z[i]=z;
    }
}
//透视投影
void Perspective(PointArray pa,float ez,float n,float f)
{
    float x,y,z;
    for (int i = 0; i < pa.length; i++) {
        x=pa.x[i],y=pa.y[i],z=pa.z[i];
        pa.x[i]=(ez-z)/(n-f)*x;
        pa.y[i]=(ez-z)/(n-f)*y;
        pa.z[i]=z;
    }
}
//
static float yrot=45;
//
inline float fun(float x,float y)
{
    //Matlab Peaks Function
    float z=3*(1-x)*(1-x)*exp(-x*x - (y+1)*(y+1))
            - 10*(x/5 - x*x*x - y*y*y*y*y)*exp(-x*x-y*y)
            - 1.0/3*exp(-(x+1)*(x+1) - y*y);
    return z*10;
}
//
void display()
{
    float a[12];
    PointArray ptsa,ptsb;
    float d=0.1,factor=50;
    float x,y,z1,z2,z3,z4;
    FILE* fp=fopen("main.ps","wb");
    fprintf(fp,"%%!PS-Adobe-3.0 EPSF-3.0\n%%%%BoundingBox: -250 -250 250 250\n/rgb {setrgbcolor} def\n/np {newpath} def\n/cp {closepath} def\n/mt {moveto} def\n/rmt {rmoveto} def\n/ll {lineto} def\n/rl {rlineto} def\n/st {stroke} def\n/lw {setlinewidth} def\n/line {np mt ll st} def\n/quad {np mt ll ll ll cp st} def\n0 0 1 rgb\n0.2 lw\n");
    for(x=-3; x<3; x+=d) {
        for(y=-3; y<3; y+=d) {
            z1=fun(x,y);
            a[0]=x*factor,a[1]=z1,a[2]=y*factor;
            z2=fun(x+d,y);
            a[3]=(x+d)*factor,a[4]=z2,a[5]=y*factor;
            z3=fun(x+d,y+d);
            a[6]=(x+d)*factor,a[7]=z3,a[8]=(y+d)*factor;
            z4=fun(x,y+d);
            a[9]=x*factor,a[10]=z4,a[11]=(y+d)*factor;
            //
            ptsa=eval(a,Length(a));
            RotateY(ptsa,yrot);
            RotateX(ptsa,15*2*PI/360);
            //ptsb=RotateZ(ptsb,6);
            fileprint(fp,ptsa);
        }
    }
    fprintf(fp,"\nshowpage\n%%%%EOF\n");
    fclose(fp);
    yrot+=0.1;
}
int main()
{
    display();
}

4.结束语

  虽然越来越多的新技术涌现出来,但是它们都不是凭空产生的。PostScript作为一项古老的技术,对于文档的排版和印刷而言,依然是值得学习的。

posted @ 2018-09-12 11:05  怪猫佐良  阅读(4995)  评论(0编辑  收藏  举报