/* File: psprint.c * * This file is part of XSCHEM, * a schematic capture and Spice/Vhdl/Verilog netlisting tool for circuit * simulation. * Copyright (C) 1998-2020 Stefan Frederik Schippers * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "xschem.h" #define X_TO_PS(x) ( (x+xorigin)* mooz ) #define Y_TO_PS(y) ( (y+yorigin)* mooz ) static FILE *fd; typedef struct { int red; int green; int blue; } Ps_color; static Ps_color *ps_colors; static void restore_lw(void) { if(lw_double==0.0) fprintf(fd, "%.16g setlinewidth\n",0.5); else if(a3page) fprintf(fd, "%.16g setlinewidth\n",lw_double/1.2/sqrt(2)); else fprintf(fd, "%.16g setlinewidth\n",lw_double/1.2); } static void set_ps_colors(unsigned int pixel) { if(color_ps) fprintf(fd, "%.16g %.16g %.16g setrgbcolor\n", (double)ps_colors[pixel].red/256.0, (double)ps_colors[pixel].green/256.0, (double)ps_colors[pixel].blue/256.0); } static void ps_xdrawarc(int layer, int fillarc, double x, double y, double r, double a, double b) { if(fill && fillarc) fprintf(fd, "%.16g %.16g %.16g %.16g %.16g AF\n", x, y, r, -a, -a-b); else fprintf(fd, "%.16g %.16g %.16g %.16g %.16g A\n", x, y, r, -a, -a-b); } static void ps_xdrawline(int layer, double x1, double y1, double x2, double y2) { fprintf(fd, "%.16g %.16g %.16g %.16g L\n", x2, y2, x1, y1); } static void ps_xdrawpoint(int layer, double x1, double y1) { fprintf(fd, "%.16g %.16g %.16g %.16g L\n", x1, y1,x1,y1); } static void ps_xfillrectange(int layer, double x1, double y1, double x2, double y2) { /*fprintf(fd, "%.16g %.16g moveto %.16g %.16g lineto %.16g %.16g lineto %.16g %.16g lineto closepath\n", */ /* x1,y1,x2,y1,x2,y2,x1,y2); */ fprintf(fd, "%.16g %.16g %.16g %.16g R\n", x1,y1,x2-x1,y2-y1); if( (layer==4 || layer==PINLAYER || layer==WIRELAYER) && fill) { fprintf(fd, "%.16g %.16g %.16g %.16g RF\n", x1,y1,x2-x1,y2-y1); /* fprintf(fd,"fill\n"); */ } /*fprintf(fd,"stroke\n"); */ } /* Convex Nonconvex Complex */ #define Polygontype Nonconvex static void ps_drawpolygon(int c, int what, double *x, double *y, int points, int poly_fill) { double x1,y1,x2,y2; double xx, yy; int i; polygon_bbox(x, y, points, &x1,&y1,&x2,&y2); x1=X_TO_PS(x1); y1=Y_TO_PS(y1); x2=X_TO_PS(x2); y2=Y_TO_PS(y2); if( !rectclip(areax1,areay1,areax2,areay2,&x1,&y1,&x2,&y2) ) { return; } for(i=0;iareay1 && yareax1 && xlines[layer];j++) { line = ((inst_ptr[n].ptr+instdef)->lineptr[layer])[j]; ROTATION(0.0,0.0,line.x1,line.y1,x1,y1); ROTATION(0.0,0.0,line.x2,line.y2,x2,y2); ORDER(x1,y1,x2,y2); ps_drawline(layer, x0+x1, y0+y1, x0+x2, y0+y2); } for(j=0;j< (inst_ptr[n].ptr+instdef)->polygons[layer];j++) /* 20171115 */ { polygon = ((inst_ptr[n].ptr+instdef)->polygonptr[layer])[j]; { /* scope block so we declare some auxiliary arrays for coord transforms. 20171115 */ int k; double *x = my_malloc(309, sizeof(double) * polygon.points); double *y = my_malloc(310, sizeof(double) * polygon.points); for(k=0;karcs[layer];j++) { double angle; arc = ((inst_ptr[n].ptr+instdef)->arcptr[layer])[j]; if(flip) { angle = 270.*rot+180.-arc.b-arc.a; } else { angle = arc.a+rot*270.; } angle = fmod(angle, 360.); if(angle<0.) angle+=360.; ROTATION(0.0,0.0,arc.x,arc.y,x1,y1); ps_drawarc(layer, arc.fill, x0+x1, y0+y1, arc.r, angle, arc.b); } if( (layer != PINLAYER || enable_layer[layer]) ) for(j=0;j< (inst_ptr[n].ptr+instdef)->rects[layer];j++) { box = ((inst_ptr[n].ptr+instdef)->boxptr[layer])[j]; ROTATION(0.0,0.0,box.x1,box.y1,x1,y1); ROTATION(0.0,0.0,box.x2,box.y2,x2,y2); RECTORDER(x1,y1,x2,y2); ps_filledrect(layer, x0+x1, y0+y1, x0+x2, y0+y2); } if( (layer==TEXTWIRELAYER && !(inst_ptr[n].flags&2) ) || (sym_txt && (layer==TEXTLAYER) && (inst_ptr[n].flags&2) ) ) { for(j=0;j< (inst_ptr[n].ptr+instdef)->texts;j++) { text = (inst_ptr[n].ptr+instdef)->txtptr[j]; /* if(text.xscale*FONTWIDTH* mooz<1) continue; */ text.txt_ptr= translate(n, text.txt_ptr); ROTATION(0.0,0.0,text.x0,text.y0,x1,y1); textlayer = layer; if( !(layer == PINLAYER && (inst_ptr[n].flags & 4))) { textlayer = (inst_ptr[n].ptr+instdef)->txtptr[j].layer; if(textlayer < 0 || textlayer >= cadlayers) textlayer = layer; } if((layer == PINLAYER && inst_ptr[n].flags & 4) || enable_layer[textlayer]) { ps_draw_string(textlayer, text.txt_ptr, (text.rot + ( (flip && (text.rot & 1) ) ? rot+2 : rot) ) & 0x3, flip^text.flip, text.hcenter, text.vcenter, x0+x1, y0+y1, text.xscale, text.yscale); } } restore_lw(); } Tcl_SetResult(interp,"",TCL_STATIC); /* 26102003 */ } static void fill_ps_colors() { char s[200]; /* overflow safe 20161122 */ unsigned int i,c; if(debug_var>=1) { tcleval( "puts $ps_colors"); } for(i=0;i> 16; ps_colors[i].green = (c & 0x00ff00) >> 8; ps_colors[i].blue = (c & 0x0000ff); } } void ps_draw(void) { double dx, dy, delta,scale; int c,i, textlayer; char *tmp=NULL; /* 20161121 */ int old_grid; int modified_save; const char *r; if(!plotfile[0]) { my_strdup(59, &tmp, "tk_getSaveFile -title {Select destination file} -initialdir $env(PWD)"); tcleval(tmp); my_free(878, &tmp); r = tclresult(); if(r[0]) my_strncpy(plotfile, r, S(plotfile)); else { return; } } modified_save=modified; push_undo(); /* 20161121 */ trim_wires(); /* 20161121 add connection boxes on wires but undo at end */ ps_colors=my_calloc(311, cadlayers, sizeof(Ps_color)); if(ps_colors==NULL){ fprintf(errfp, "ps_draw(): calloc error\n");tcleval( "exit"); } fill_ps_colors(); old_grid=draw_grid; draw_grid=0; dx=areax2-areax1; dy=areay2-areay1; dbg(1, "ps_draw(): dx=%.16g dy=%.16g\n", dx, dy); fd=fopen("plot.ps", "w"); fprintf(fd, "%%!\n"); fprintf(fd, "%%%%BoundingBox: (atend)\n"); fprintf(fd, "%%%%Title: xschem plot\n"); fprintf(fd, "%%%%Creator: xschem\n"); fprintf(fd, "%%%%Pages: 1\n"); fprintf(fd, "%%%%DocumentFonts: (atend)\n"); fprintf(fd, "%%%%EndComments\n"); fprintf(fd, "%%%%BeginProlog\n\n"); fprintf(fd, "%%%%EndProlog\n"); fprintf(fd, "%%%%BeginSetup\n"); if(a3page) { fprintf(fd, "%%%%BeginFeature: *PageSize A3\n"); fprintf(fd, "<< /PageSize [842 1191] /ImagingBBox null >> setpagedevice\n"); } fprintf(fd, "%%%%EndSetup\n"); fprintf(fd, "%%%%Page: 1 1\n\n"); fprintf(fd,"/cm {28.346457 mul} bind def\n"); fprintf(fd,"/LT {lineto} bind def\n"); fprintf(fd,"/MT {moveto} bind def\n"); fprintf(fd,"/L {moveto lineto stroke} bind def\n"); fprintf(fd,"/A {arcn stroke} bind def\n"); fprintf(fd,"/AF {arcn fill stroke} bind def\n"); fprintf(fd,"/R {rectstroke} bind def\n"); fprintf(fd,"/RF {rectfill} bind def\n"); if(dx/dy>27.7/19 || dy/dx>27.7/19) { delta=dx>dy? dx:dy; if(a3page) scale=28.7*28.346457/delta*sqrt(2); else scale=27.7*28.346457/delta; } else { delta=dx>dy? dy:dx; if(a3page) scale=20*28.346457/delta*sqrt(2); else scale=19*28.346457/delta; } if(dx>dy) { if(a3page) fprintf(fd,"28.99137803 cm 41.29503602 cm translate\n"); else fprintf(fd,"20 cm 28.7 cm translate\n"); fprintf(fd,"-90 rotate\n"); fprintf(fd,"%.16g %.16g scale\n",scale,-scale); } else { fprintf(fd,"1 cm 28.7 cm translate\n"); fprintf(fd,"%.16g %.16g scale\n",scale,-scale); } fprintf(fd, "1 setlinejoin 1 setlinecap\n"); restore_lw(); ps_drawgrid(); for(i=0;i= cadlayers) textlayer = TEXTLAYER; ps_draw_string(textlayer, textelement[i].txt_ptr, textelement[i].rot, textelement[i].flip, textelement[i].hcenter, textelement[i].vcenter, textelement[i].x0,textelement[i].y0, textelement[i].xscale, textelement[i].yscale); } restore_lw(); for(c=0;cn; if( wire[i].end1 >1 ) { /* 20150331 draw_dots */ ps_drawarc(WIRELAYER, 1, wire[i].x1, wire[i].y1, cadhalfdotsize, 0, 360); } if( wire[i].end2 >1 ) { /* 20150331 draw_dots */ ps_drawarc(WIRELAYER, 1, wire[i].x2, wire[i].y2, cadhalfdotsize, 0, 360); } } } dbg(1, "ps_draw(): lw=%d plotfile=%s\n",lw, plotfile); fprintf(fd, "showpage\n\n"); fprintf(fd, "%%%%EOF\n"); fclose(fd); draw_grid=old_grid; my_free(879, &ps_colors); if(plotfile[0]) { my_strdup(53, &tmp, "convert_to_pdf plot.ps "); /* 20161121 */ my_strcat(54, &tmp, plotfile); } else { my_strdup(312, &tmp, "convert_to_pdf plot.ps plot.pdf"); /* 20161121 */ } my_strncpy(plotfile,"", S(plotfile)); tcleval( tmp); my_free(880, &tmp); pop_undo(0); /* 20161121 */ modified=modified_save; /* 20161121 */ }