1 /*
2    Copyright (c) 2001  Martin Kroeker  All rights reserved.
3 
4    Distributed by Free Software Foundation, Inc.
5 
6 This file is part of HP2xx.
7 
8 HP2xx is distributed in the hope that it will be useful, but
9 WITHOUT ANY WARRANTY.  No author or distributor accepts responsibility
10 to anyone for the consequences of using it or for whether it serves any
11 particular purpose or works at all, unless he says so in writing.  Refer
12 to the GNU General Public License, Version 2 or later, for full details.
13 
14 Everyone is granted permission to copy, modify and redistribute
15 HP2xx, but only under the conditions described in the GNU General Public
16 License.  A copy of this license is supposed to have been
17 given to you along with HP2xx so you can know your rights and
18 responsibilities.  It should be in a file named COPYING.  Among other
19 things, the copyright notice and this notice must be preserved on all
20 copies.
21 
22 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
23 */
24 
25 /** to_pdf.c:   Converter to Adobe Portable Document (PDF) Format using pdflib
26  **
27  ** 01/06/19  V 1.00 MK   derived from to_eps.c
28  **/
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <time.h>
34 #include <math.h>
35 #include <pdflib.h>
36 #include "bresnham.h"
37 #include "hp2xx.h"
38 #include "pendef.h"
39 #include "lindef.h"
40 
41 
42 static	int	linecount = 0;
43 static	float	xcoord2mm, ycoord2mm;
44 static	float	xmin, ymin;
45 
46 
47 int 	to_pdf (const GEN_PAR *, const OUT_PAR *);
48 void	pdf_init (const GEN_PAR *, const OUT_PAR *, PDF *, PEN_W);
49 void	pdf_set_linewidth (double, HPGL_Pt *, PDF *);
50 void pdf_set_linecap( LineEnds type,double pensize, PDF *fd);
51 void pdf_set_linejoin( LineJoins type, LineLimit limit, double pensize, PDF *fd);
52 void	pdf_set_color (double, double, double, HPGL_Pt *, PDF *);
53 void 	pdf_end(PDF *);
54 
55 
56 
57 /**
58  ** Close graphics file
59  **/
pdf_end(PDF * fd)60 void	pdf_end (PDF *fd)
61 {
62   PDF_end_page(fd);
63   PDF_close(fd);
64   PDF_delete(fd);
65   PDF_shutdown();
66   linecount = 0;
67 }
68 
69 
70 /**
71  ** Set line width
72  **/
pdf_set_linewidth(double width,HPGL_Pt * ppt,PDF * fd)73 void	pdf_set_linewidth (double width, HPGL_Pt *ppt, PDF *fd)
74 {
75   PDF_setlinewidth(fd, width);
76 }
77 
78 
79 /**
80  ** Set line Ends
81  **/
pdf_set_linecap(LineEnds type,double pensize,PDF * fd)82 void pdf_set_linecap( LineEnds type,double pensize, PDF *fd) {
83 
84    static int lastcap = -1;
85    int newcap;
86 
87    if ( pensize > 0.35 ) {
88       switch (type) {
89          case LAE_butt:
90             newcap=0;
91             break;
92          case LAE_triangular:                                /* triangular not implemented in PS/PDF */
93             newcap=1;
94             break;
95          case LAE_round:
96             newcap=1;
97             break;
98          case LAE_square:
99             newcap=2;
100             break;
101          default:
102             newcap=0;
103             break;
104       }
105    } else {
106       newcap=1;
107    }
108 
109    if(newcap != lastcap) {
110       PDF_setlinecap(fd,newcap);
111       lastcap=newcap;
112    }
113 }
114 
115 
116 /**
117  ** Set line Joins
118  **/
pdf_set_linejoin(LineJoins type,LineLimit limit,double pensize,PDF * fd)119 void pdf_set_linejoin( LineJoins type, LineLimit limit, double pensize, PDF *fd) {
120 
121    static int lastcap = -1;
122    static int lastlimit = -1;
123    int newcap;
124    int newlimit = lastlimit;
125 
126 
127    if ( pensize > 0.35 ) {
128       switch (type) {
129          case LAJ_plain_miter:
130             newcap=0;
131 	    newlimit = 100; /* arbitrary value */
132             break;
133          case LAJ_bevel_miter: /* not available */
134             newcap=0;
135 	    newlimit = limit;
136             break;
137          case LAJ_triangular: /* not available */
138             newcap=1;
139             break;
140          case LAJ_round:
141             newcap=1;
142             break;
143 	 case LAJ_bevelled:
144             newcap=2;
145             break;
146 	 case LAJ_nojoin: /* not available */
147             newcap=1;
148             break;
149          default:
150             newcap=0;
151 	    newlimit = 100; /* arbitrary value */
152             break;
153       }
154    } else {
155       newcap=1;
156    }
157 
158    if(newcap != lastcap) {
159       PDF_setlinejoin(fd,newcap);
160       lastcap=newcap;
161    }
162    if(newlimit != lastlimit) {
163       PDF_setmiterlimit(fd,newlimit);
164       lastlimit=newlimit;
165    }
166 }
167 
168 
169 /**
170  ** Set RGB color
171  **/
pdf_set_color(double red,double green,double blue,HPGL_Pt * ppt,PDF * fd)172 void	pdf_set_color (double red, double green, double blue,
173 			HPGL_Pt *ppt, PDF *fd)
174 {
175 PDF_setrgbcolor(fd,red,green,blue);
176 }
177 
178 
179 /**
180  ** basic PDF definitions
181  **/
182 
pdf_init(const GEN_PAR * pg,const OUT_PAR * po,PDF * fd,PEN_W pensize)183 void	pdf_init (const GEN_PAR *pg, const OUT_PAR *po, PDF *fd,
184 		 PEN_W pensize)
185 {
186 long	left, right, low, high;
187 double	hmxpenw;
188 
189   hmxpenw = pg->maxpensize / 20.0;	/* Half max. pen width, in mm	*/
190 
191   left  = (long) floor(abs(po->xoff-hmxpenw)		    * 2.834646);
192   low   = (long) floor(abs(po->yoff-hmxpenw)* 2.834646);
193   right = (long) ceil ((po->xoff   + po->width+hmxpenw)	    * 2.834646);
194   high  = (long) ceil ((po->yoff+po->height+hmxpenw)	    * 2.834646);
195 
196   PDF_begin_page(fd, right,high);
197   PDF_setlinewidth(fd, pensize);
198   pdf_set_linecap(CurrentLineAttr.End,pensize,fd);
199   pdf_set_linejoin(CurrentLineAttr.Join,CurrentLineAttr.Limit,pensize,fd);
200 }
201 
202 
203 
204 /**
205  ** Higher-level interface: Output Portable Document Format
206  **/
207 
208 int
to_pdf(const GEN_PAR * pg,const OUT_PAR * po)209 to_pdf (const GEN_PAR *pg, const OUT_PAR *po)
210 {
211 PlotCmd	cmd;
212 PDF	*md;
213 HPGL_Pt	pt1 = {0};
214 int	pen_no=0, pencolor=0, err;
215 int openpath;
216 PEN_W pensize;
217 
218    PDF_boot();
219 
220   err = 0;
221   if (!pg->quiet)
222 	Eprintf ("\n\n- Writing PDF code to \"%s\"\n",
223 		*po->outfile == '-' ? "stdout" : po->outfile);
224 
225   /* Init. of PDF file: */
226 
227   md=PDF_new();
228   if (PDF_open_file(md, po->outfile) == -1) {
229      PError("hp2xx (pdf)");
230      return ERROR;
231   }
232 
233   /* header */
234 
235   pensize = pt.width[DEFAULT_PEN_NO]; /* Default pen	*/
236   pdf_init (pg, po, md, pensize);
237 
238 
239   /* Factor for transformation of HP coordinates to mm	*/
240 
241   xcoord2mm = po->width  / (po->xmax - po->xmin) * 2.834646;
242   ycoord2mm = po->height / (po->ymax - po->ymin) * 2.834646;
243   xmin	    = po->xmin;
244   ymin	    = po->ymin;
245 
246 /**
247  ** Command loop: While temporary file not empty: process command.
248  **/
249   openpath=0;
250   while ((cmd = PlotCmd_from_tmpfile()) != CMD_EOF)
251   {
252 	switch (cmd)
253 	{
254 	  case NOP:
255 		break;
256 	  case SET_PEN:
257 		if ((pen_no = fgetc(pg->td)) == EOF)
258 		{
259 			PError("Unexpected end of temp. file: ");
260 			err = ERROR;
261 			goto PDF_exit;
262 		}
263 		pensize = pt.width[pen_no];
264 		pencolor = pt.color[pen_no];
265 		 if(openpath==1){PDF_stroke(md);
266 		 	openpath=0;
267 		 	}
268                     if (pensize != 0)
269 		pdf_set_linewidth ((double) pensize, &pt1, md);
270                 pdf_set_linecap(CurrentLineAttr.End,(double) pensize,md);
271                 pdf_set_linejoin(CurrentLineAttr.Join,CurrentLineAttr.Limit,(double) pensize,md);
272 		pdf_set_color (  pt.clut[pencolor][0]/255.0,
273 				pt.clut[pencolor][1]/255.0,
274 				pt.clut[pencolor][2]/255.0,
275 				&pt1, md);
276 		break;
277           case DEF_PW:
278                 if(!load_pen_width_table(pg->td)) {
279                     PError("Unexpected end of temp. file");
280 		    err = ERROR;
281 		    goto PDF_exit;
282                 }
283                 break;
284           case DEF_PC:
285                 err=load_pen_color_table(pg->td);
286                 if (err<0) {
287                     PError("Unexpected end of temp. file");
288 		    err = ERROR;
289 		    goto PDF_exit;
290                 }
291                 if (err==pencolor) pencolor *=-1; /*current pen changed*/
292                 break;
293           case DEF_LA:
294                 if(load_line_attr(pg->td) <0) {
295                     PError("Unexpected end of temp. file");
296 		    err = ERROR;
297 		    goto PDF_exit;
298                 }
299                 break;
300 	  case MOVE_TO:
301 		if (openpath==1) {
302 			PDF_stroke(md);
303 			openpath=0;
304 			}
305                 if(fabs(pensize-pt.width[pen_no]) >= 0.01) {
306                     pensize=pt.width[pen_no];
307                     if (pensize != 0){
308                        pdf_set_linewidth ((double) pensize, &pt1, md);
309                        pdf_set_linecap(CurrentLineAttr.End,(double) pensize,md);
310                        pdf_set_linejoin(CurrentLineAttr.Join,CurrentLineAttr.Limit,(double) pensize,md);
311                     }
312                 }
313                 if(pencolor <0) {
314                    pencolor=pt.color[pen_no];
315                    pdf_set_color(pt.clut[pencolor][0]/255.0,
316                                  pt.clut[pencolor][1]/255.0,
317                                  pt.clut[pencolor][2]/255.0,
318                                  &pt1, md);
319                 }
320 
321                 HPGL_Pt_from_tmpfile (&pt1);
322                 if(pensize != 0){
323                    PDF_moveto(md,(pt1.x-xmin)*xcoord2mm,(pt1.y-ymin)*ycoord2mm);
324                 }
325 		break;
326 	  case DRAW_TO:
327                 if(fabs(pensize-pt.width[pen_no]) >= 0.01) {
328                    pensize=pt.width[pen_no];
329                    if(pensize != 0){
330                       pdf_set_linewidth ((double) pensize, &pt1, md);
331                       pdf_set_linecap(CurrentLineAttr.End,(double) pensize,md);
332                       pdf_set_linejoin(CurrentLineAttr.Join,CurrentLineAttr.Limit,(double) pensize,md);
333                    }
334                 }
335                 if(pencolor <0) {
336                    pencolor=pt.color[pen_no];
337                    pdf_set_color(pt.clut[pencolor][0]/255.0,
338                                  pt.clut[pencolor][1]/255.0,
339                                  pt.clut[pencolor][2]/255.0,
340                                  &pt1, md);
341                 }
342                 HPGL_Pt_from_tmpfile (&pt1);
343                 if(pensize != 0){
344                    PDF_lineto(md,(pt1.x-xmin)*xcoord2mm,(pt1.y-ymin)*ycoord2mm);
345                    openpath=1;
346                 }
347                 break;
348 	  case PLOT_AT:
349 /*		if (openpath==1){
350 			PDF_stroke(md);
351 			openpath=0;
352 			}*/
353                 if(fabs(pensize-pt.width[pen_no]) >= 0.01) {
354                    pensize=pt.width[pen_no];
355                    if(pensize != 0){
356                       pdf_set_linewidth ((double) pensize, &pt1, md);
357                       pdf_set_linecap(CurrentLineAttr.End,(double) pensize,md);
358                       pdf_set_linejoin(CurrentLineAttr.Join,CurrentLineAttr.Limit,(double) pensize,md);
359                    }
360                 }
361                 if(pencolor<0) {
362                    pencolor=pt.color[pen_no];
363 		   pdf_set_color(pt.clut[pencolor][0]/255.0,
364                                  pt.clut[pencolor][1]/255.0,
365                                  pt.clut[pencolor][2]/255.0,
366                                  &pt1, md);
367                 }
368 		HPGL_Pt_from_tmpfile (&pt1);
369                 if(pensize != 0) {
370                    PDF_moveto(md,(pt1.x-xmin)*xcoord2mm,(pt1.y-ymin)*ycoord2mm);
371                    PDF_lineto(md,(pt1.x-xmin)*xcoord2mm+1,(pt1.y-ymin)*ycoord2mm+1);
372 /*		   PDF_stroke(md);*/
373 		openpath=1;
374                 }
375                 break;
376 	  default:
377 		Eprintf ("Illegal cmd in temp. file!");
378 		err = ERROR;
379 		goto PDF_exit;
380 	}
381   }
382 
383   /* Finish up */
384 if (openpath==1) PDF_stroke(md);
385   pdf_end (md);
386 
387 PDF_exit:
388 /*  if (md != stdout)
389 	fclose (md);
390 */
391   if (!pg->quiet)
392 	Eprintf ("\n");
393   return err;
394 }
395 
396