backend_eps.c
Go to the documentation of this file.
00001 /* Copyright (C) 2001-2007 Peter Selinger.
00002    This file is part of Potrace. It is free software and it is covered
00003    by the GNU General Public License. See the file COPYING for details. */
00004 
00005 /* $Id: backend_eps.c 147 2007-04-09 00:44:09Z selinger $ */
00006 
00007 /* The Postscript backend of Potrace. This can produce "ps" or "eps"
00008    output, and different kinds of graphical debugging
00009    output. Postscript compression is optionally supplied via the
00010    functions in flate.c. */
00011 
00012 #include <stdio.h>
00013 #include <stdarg.h>
00014 #include <string.h>
00015 #include <math.h>
00016 #include <stdlib.h>
00017 
00018 #include "potracelib.h"
00019 #include "curve.h"
00020 #include "main.h"
00021 #include "backend_eps.h"
00022 #include "flate.h"
00023 #include "lists.h"
00024 #include "auxiliary.h"
00025 
00026 #ifdef HAVE_CONFIG_H
00027 #include "config.h"
00028 #endif
00029 
00030 #define SAFE_MALLOC(var, n, typ) \
00031   if ((var = (typ *)malloc((n)*sizeof(typ))) == NULL) goto malloc_error 
00032 
00033 typedef int color_t;
00034 
00035 #define black  0x000000
00036 #define red    0xff0000
00037 #define green  0x008000
00038 #define blue   0x0000ff
00039 
00040 /* ---------------------------------------------------------------------- */
00041 /* functions for interfacing with compression backend */
00042 
00043 /* xship: callback function that must be initialized before calling
00044    any other functions of the "ship" family. xship_file must be
00045    initialized too. */
00046 
00047 /* print the token to f, but filtered through a compression
00048    filter in case filter!=0 */
00049 static int (*xship)(FILE *f, int filter, char *s, int len);
00050 static FILE *xship_file;
00051 
00052 /* ship postscript code, filtered */
00053 static int ship(const char *fmt, ...) {
00054   va_list args;
00055   static char buf[4096]; /* static string limit is okay here because
00056                             we only use constant format strings - for
00057                             the same reason, it is okay to use
00058                             vsprintf instead of vsnprintf below. */
00059   va_start(args, fmt);
00060   vsprintf(buf, fmt, args);
00061   buf[4095] = 0;
00062   va_end(args);
00063 
00064   xship(xship_file, 1, buf, strlen(buf));
00065   return 0;
00066 }  
00067 
00068 /* ship a postscript comment, unfiltered */
00069 static int shipcom(char *fmt, ...) {
00070   static char buf[4096];
00071   va_list args;
00072 
00073   va_start(args, fmt);
00074   vsprintf(buf, fmt, args);
00075   buf[4095] = 0;
00076   va_end(args);
00077 
00078   xship(xship_file, 0, buf, strlen(buf));
00079   return 0;
00080 }
00081 
00082 /* set all callback functions */
00083 static void eps_callbacks(FILE *fout) {
00084   if (info.compress && info.pslevel==2) {
00085     xship = lzw_xship;
00086   } else if (info.compress && info.pslevel==3) {
00087     xship = flate_xship;
00088   } else {
00089     xship = dummy_xship;
00090   }
00091   xship_file = fout;
00092 }  
00093 
00094 /* ---------------------------------------------------------------------- */
00095 /* postscript path-drawing auxiliary functions */
00096 
00097 /* coordinate quantization */
00098 static inline point_t unit(dpoint_t p) {
00099   point_t q;
00100 
00101   q.x = (long)(floor(p.x*info.unit+.5));
00102   q.y = (long)(floor(p.y*info.unit+.5));
00103   return q;
00104 }
00105 
00106 /* current point */
00107 static point_t cur;
00108 
00109 static void eps_coords(dpoint_t p) {
00110   cur = unit(p);
00111   ship("%ld %ld ", cur.x, cur.y);
00112 }
00113 
00114 static void eps_rcoords(dpoint_t p) {
00115   point_t q;
00116 
00117   q = unit(p);
00118   ship("%ld %ld ", q.x-cur.x, q.y-cur.y);
00119   cur = q;
00120 }
00121 
00122 static void eps_moveto(dpoint_t p) {
00123   eps_coords(p);
00124   ship("moveto\n");
00125 }
00126 
00127 /* move to point + offset */
00128 static void eps_moveto_offs(dpoint_t p, double xoffs, double yoffs) {
00129   /* note: structs are passed by value, so the following assignment
00130      does not modify the original struct in the caller */
00131   p.x += xoffs;
00132   p.y += yoffs;
00133   eps_coords(p);
00134   ship("moveto\n");
00135 }
00136 
00137 static void eps_lineto(dpoint_t p) {
00138   eps_rcoords(p);
00139   ship("rlineto\n");
00140 }
00141 
00142 static void eps_curveto(dpoint_t p1, dpoint_t p2, dpoint_t p3) {
00143   point_t q1, q2, q3;
00144 
00145   q1 = unit(p1);
00146   q2 = unit(p2);
00147   q3 = unit(p3);
00148 
00149   ship("%ld %ld %ld %ld %ld %ld rcurveto\n", q1.x-cur.x, q1.y-cur.y, q2.x-cur.x, q2.y-cur.y, q3.x-cur.x, q3.y-cur.y);
00150   
00151   cur = q3;
00152 }
00153 
00154 /* this procedure returns a statically allocated string */
00155 static char *eps_colorstring(const color_t col) {
00156   double r, g, b;
00157   static char buf[100];
00158 
00159   r = (col & 0xff0000) >> 16;
00160   g = (col & 0x00ff00) >> 8;
00161   b = (col & 0x0000ff) >> 0;
00162 
00163   if (r==0 && g==0 && b==0) {
00164     return "0 setgray";
00165   } else if (r==255 && g==255 && b==255) {
00166     return "1 setgray";
00167   } else if (r == g && g == b) {
00168     sprintf(buf, "%.3f setgray", r/255.0);
00169     return buf;
00170   } else {
00171     sprintf(buf, "%.3f %.3f %.3f setrgbcolor", r/255.0, g/255.0, b/255.0);
00172     return buf;
00173   }
00174 }
00175 
00176 static color_t eps_color = -1;
00177 static double eps_width = -1;
00178 
00179 static void eps_setcolor(const color_t col) {
00180   if (col == eps_color) {
00181     return;
00182   }
00183   eps_color = col;
00184 
00185   ship("%s\n", eps_colorstring(col));
00186 }
00187 
00188 static void eps_linewidth(double w) {
00189   if (w == eps_width) {
00190     return;
00191   }
00192   eps_width = w;
00193   ship("%f setlinewidth\n", w * info.unit);
00194 }
00195 
00196 /* ---------------------------------------------------------------------- */
00197 /* functions for converting a path to postscript code */
00198 
00199 /* ---------------------------------------------------------------------- */
00200 /* ASCII encoding */
00201 
00202 /* explicit encoding, does not use special macros */
00203 static int eps_path_long(privcurve_t *curve) {
00204   int i;
00205   dpoint_t *c;
00206   int m = curve->n;
00207 
00208   c = curve->c[m-1];
00209   eps_moveto(c[2]);
00210 
00211   for (i=0; i<m; i++) {
00212     c = curve->c[i];
00213     switch (curve->tag[i]) {
00214     case POTRACE_CORNER:
00215       eps_lineto(c[1]);
00216       eps_lineto(c[2]);
00217       break;
00218     case POTRACE_CURVETO:
00219       eps_curveto(c[0], c[1], c[2]);
00220       break;
00221     }
00222   }
00223   return 0;
00224 }
00225 
00226 /* size-optimized encoding relies on special macros */
00227 static int eps_path_short(privcurve_t *curve) {
00228   int i, i1;
00229   long int *bq = NULL;  /* bq[m] */
00230   long int *aq = NULL;  /* aq[m] */
00231   point_t *v = NULL;    /* v[m] */
00232   dpoint_t *q = NULL;   /* q[m] */
00233   double M;
00234   int m = curve->n;
00235 
00236   SAFE_MALLOC(bq, m, long int);
00237   SAFE_MALLOC(aq, m, long int);
00238   SAFE_MALLOC(v, m, point_t);
00239   SAFE_MALLOC(q, m, dpoint_t);
00240 
00241   /* quantize vertices */
00242   for (i=0; i<m; i++) {
00243     v[i] = unit(curve->vertex[i]);
00244   }
00245 
00246   /* quantize beta */
00247   for (i=0; i<m; i++) {
00248     i1 = mod(i+1,m);
00249     M = max(10, max(abs(v[i1].x-v[i].x), abs(v[i1].y-v[i].y)));
00250     bq[i] = (int)(M * curve->beta[i] + 0.5);
00251     if (curve->beta[i] != 0.5) {
00252       q[i1] = interval(bq[i]/M, dpoint(v[i]), dpoint(v[i1]));
00253     } else {
00254       q[i1] = interval(0.5, dpoint(v[i]), dpoint(v[i1]));
00255     }
00256   }
00257 
00258   /* quantize alpha */
00259   for (i=0; i<m; i++) {
00260     i1 = mod(i+1,m);
00261     M = max(10, max(max(abs(q[i].x-v[i].x), abs(q[i].y-v[i].y)),
00262                     max(abs(v[i].x-q[i1].x), abs(v[i].y-q[i1].y))));
00263     if (curve->tag[i] == POTRACE_CURVETO) {
00264       aq[i] = (int)(M * curve->alpha[i] + 0.5);
00265       if (aq[i] > M) {
00266         aq[i]--;
00267       }
00268     }
00269   }
00270 
00271   /* generate output */
00272   ship("%ld %ld ", v[m-1].x, v[m-1].y);
00273   ship("%ld %ld ", v[0].x - v[m-1].x, v[0].y - v[m-1].y);
00274   if (curve->beta[m-1] == 0.5) {
00275     ship("i\n");
00276   } else {
00277     ship("%ld I\n", bq[m-1]);
00278   }
00279   for (i=0; i<m; i++) {
00280     if (i<m-1) {
00281       ship("%ld %ld ", v[i+1].x - v[i].x, v[i+1].y - v[i].y);
00282       if (curve->beta[i] != 0.5) {
00283         ship("%ld ", bq[i]);
00284       }
00285     }
00286     if (curve->tag[i] == POTRACE_CURVETO) {
00287       ship(curve->beta[i] == 0.5 ? "%ld c\n" : "%ld C\n", aq[i]);
00288     } else {
00289       ship(curve->beta[i] == 0.5 ? "v\n" : "V\n");
00290     }
00291   }  
00292 
00293   free(bq);
00294   free(aq);
00295   free(v);
00296   free(q);
00297   return 0;
00298 
00299  malloc_error:
00300   free(bq);
00301   free(aq);
00302   free(v);
00303   free(q);
00304   return 1;
00305 }
00306 
00307 static int eps_path(privcurve_t *curve) {
00308   if (info.longcoding==0 && curve->alphacurve) {
00309     return eps_path_short(curve);
00310   } else {
00311     return eps_path_long(curve);
00312   }
00313 }
00314 
00315 /* ---------------------------------------------------------------------- */
00316 /* functions for rendering various internal data structures, used to
00317    generate debugging output */
00318 
00319 /* output jaggie curve in grey */
00320 static void eps_jaggy(potrace_path_t *plist) {
00321   potrace_path_t *p;
00322   int i;
00323 
00324   ship(".9 setgray\n");
00325   list_forall (p, plist) {
00326     point_t *pt = p->priv->pt;
00327     point_t cur, prev;
00328 
00329     if (p->sign == '+') {
00330       cur = prev = pt[p->priv->len-1];
00331       eps_moveto(dpoint(cur));
00332       for (i=0; i<p->priv->len; i++) {
00333         if (pt[i].x != cur.x && pt[i].y != cur.y) {
00334           cur = prev;
00335           eps_lineto(dpoint(cur));
00336         }
00337         prev = pt[i];
00338       }
00339       eps_lineto(dpoint(pt[p->priv->len-1]));
00340     } else {
00341       cur = prev = pt[0];
00342       eps_moveto(dpoint(cur));
00343       for (i=p->priv->len-1; i>=0; i--) {
00344         if (pt[i].x != cur.x && pt[i].y != cur.y) {
00345           cur = prev;
00346           eps_lineto(dpoint(cur));
00347         }
00348         prev = pt[i];
00349       }
00350       eps_lineto(dpoint(pt[0]));
00351     }
00352     if (p->next == NULL || p->next->sign == '+') {
00353       ship("fill\n");
00354     }
00355   }
00356 }
00357 
00358 /* output polygon */
00359 static void eps_polygon(privcurve_t *curve, const color_t col) {
00360   int i;
00361   int m = curve->n;
00362 
00363   eps_linewidth(.02);
00364   eps_setcolor(col);
00365   eps_moveto(curve->vertex[m-1]);
00366   for (i=0; i<m; i++) {
00367     eps_lineto(curve->vertex[i]);
00368   }
00369   ship("stroke\n");
00370 }
00371 
00372 /* output lines L and parameter alpha */
00373 static void eps_L(privcurve_t *curve, const color_t col) {
00374   int i, i1;
00375   double gamma;
00376   dpoint_t p1, p4, p1l, p4l;
00377   int m = curve->n;
00378  
00379   for (i=0; i<m; i++) {
00380     i1 = mod(i+1, m);
00381     gamma = curve->alpha0[i1] * 0.75;
00382     
00383     p1 = curve->c[i][2];
00384     p4 = curve->c[i1][2];
00385     p1l = interval(gamma, p1, curve->vertex[i1]);
00386     p4l = interval(gamma, p4, curve->vertex[i1]);
00387     eps_linewidth(.02);
00388     eps_setcolor(col);
00389     eps_moveto(p1l);
00390     eps_lineto(p4l);
00391     ship("stroke\n");
00392     eps_moveto_offs(curve->vertex[i1], -.4, -.4);
00393     ship("times (%.2f) show\n", curve->alpha0[i1]);
00394   }
00395 }
00396 
00397 /* ---------------------------------------------------------------------- */
00398 /* postscript macros */
00399 
00400 /* special macros for size-optimized rendering of Bezier curves */
00401 static char *optimacros =
00402   "/D{bind def}def\n"
00403   "/R{roll}D\n"
00404   "/K{copy}D\n"
00405   "/P{pop}D\n"
00406   "/p{3 2 R add 3 1 R add exch}D\n"
00407   "/t{dup 4 3 R mul 3 1 R mul}D\n"
00408   "/a{dup 1 sub neg 4 1 R t 5 2 R t p}D\n"
00409   "/m{2 K le{exch}if P}D\n"
00410   "/n{abs exch abs m}D\n"
00411   "/d{-1 t p n}D\n"
00412   "/s{[4 2 R] cvx def}D\n"
00413   "/g{7 K P 4 K P P d 5 1 R d 10 m m div 5 K 12 8 R 5 4 R a 9 4 R 3 2 R a 6 4 R curveto}D\n"
00414   "/e{4 2 R lineto lineto P P}D\n"
00415   "/q{3 K P n 10 m div}D\n"
00416   "/f{x y 7 4 R 5 1 R 4 K p /y s 7 2 R 2 K 9 7 R 7 6 R t p 2 K /x s}D\n"
00417   "/C{4 1 R q f 7 6 R g}D\n"
00418   "/V{q f e}D\n"
00419   "/c{3 1 R .5 f 7 6 R g}D\n"
00420   "/v{.5 f e}D\n"
00421   "/j{5 K P p /y s 3 K t 7 5 R p /x s x moveto P}D\n"
00422   "/i{.5 j}D\n"
00423   "/I{dup 6 1 R q j 3 2 R}D\n"
00424   "/z{closepath}D\n"
00425   "/b{%s z fill}D\n"
00426   "/w{%s z fill}D\n";
00427 
00428 /* special macros for debug output */
00429 static char *debugmacros =
00430   "/unit { %f } def\n"
00431   "/box { newpath 0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath } def\n"
00432   "/circ { newpath 0 0 1 0 360 arc closepath } def\n"
00433   "/dot { gsave .15 mul dup scale circ fill grestore } def\n"
00434   "/sq { gsave unit unit scale -.5 -.5 translate box .02 setlinewidth stroke grestore } def\n"
00435   "/sq1 { gsave translate sq unit .6 mul dot grestore } def\n"
00436   "/dot2 { gsave translate unit dot grestore } def\n"
00437   "/usq { gsave unit unit scale -.5 -.5 rmoveto 0 1 rlineto 1 0 rlineto 0 -1 rlineto closepath .02 setlinewidth stroke grestore } def\n"
00438   "/dot1 { gsave translate unit .3 mul dup scale circ fill grestore } def\n"
00439   "/times { /Times-Roman findfont unit .3 mul scalefont setfont } def\n"
00440   "/times1 { /Times-Roman findfont unit 10 mul scalefont setfont 0 0 0 setrgbcolor } def\n"
00441   "/times2 { /Times-Roman findfont unit 2 mul scalefont setfont 0 0 0 setrgbcolor } def\n";
00442 
00443 /* ---------------------------------------------------------------------- */
00444 /* Backends for various types of output. */
00445 
00446 /* Normal output: black on transparent */
00447 static int render0(potrace_path_t *plist) {
00448   potrace_path_t *p;
00449 
00450   if (info.longcoding) {
00451     eps_setcolor(info.color);
00452     list_forall (p, plist) {
00453       eps_path(p->priv->fcurve);
00454       ship("closepath\n");
00455       if (p->next == NULL || p->next->sign == '+') {
00456         ship("fill\n");
00457       }
00458     }
00459   } else {
00460     list_forall (p, plist) {
00461       eps_path(p->priv->fcurve);
00462       if (p->next == NULL || p->next->sign == '+') {
00463         ship("b\n");
00464       } else {
00465         ship("z\n");
00466       }
00467     }
00468   }
00469   return 0;
00470 }
00471 
00472 /* Opaque output: alternating black and white */
00473 static int render0_opaque(potrace_path_t *plist) {
00474   potrace_path_t *p;
00475   
00476   if (info.longcoding) {
00477     list_forall (p, plist) {
00478       eps_path(p->priv->fcurve);
00479       ship("closepath\n");
00480       eps_setcolor(p->sign=='+' ? info.color : info.fillcolor);
00481       ship("fill\n");
00482     }
00483   } else {
00484     list_forall (p, plist) {
00485       eps_path(p->priv->fcurve);
00486       ship(p->sign=='+' ? "b\n" : "w\n");
00487     }
00488   }
00489   return 0;
00490 }
00491 
00492 /* Debug output type 1 (show optimal polygon) */
00493 static int render1(potrace_path_t *plist) {
00494   potrace_path_t *p;
00495   int i;
00496 
00497   eps_jaggy(plist);
00498 
00499   list_forall (p, plist) {
00500 
00501     point_t *pt = p->priv->pt;
00502     int n = p->priv->len;
00503     int m = p->priv->m;
00504     int *po = p->priv->po;
00505 
00506     eps_linewidth(.02);
00507     eps_setcolor(black);
00508     /* output jaggie curve in boxed style */
00509     for (i=1; i<n; i++) {
00510       eps_moveto(dpoint(pt[i-1]));
00511       eps_lineto(dpoint(pt[i]));
00512       ship("stroke\n");
00513       eps_coords(dpoint(pt[i]));
00514       ship("sq1\n");
00515     }
00516     eps_moveto(dpoint(pt[n-1]));
00517     eps_lineto(dpoint(pt[0]));
00518     ship("stroke\n");
00519     eps_coords(dpoint(pt[0]));
00520     ship("sq1\n");
00521 
00522     /* output the uncorrected polygon */
00523     eps_linewidth(.1);
00524     eps_setcolor(blue);
00525     eps_moveto(dpoint(pt[po[0]]));
00526     for (i=1; i<m; i++) {
00527       eps_lineto(dpoint(pt[po[i]]));
00528     }
00529     eps_lineto(dpoint(pt[po[0]]));
00530     ship("stroke\n");
00531     for (i=0; i<m; i++) {
00532       eps_coords(dpoint(pt[po[i]]));
00533       ship("dot2\n");
00534     }
00535   }
00536   return 0;
00537 }
00538 
00539 /* Debug output type 2 (show corrected polygon and edge detection) */
00540 static int render2(potrace_path_t *plist) {
00541   potrace_path_t *p;
00542   int i;
00543 
00544   /* output original bitmap in grey */
00545   eps_jaggy(plist);
00546   
00547   list_forall (p, plist) {
00548     /* output polygon with corrected edges, lines L, and parameter alpha */
00549     eps_polygon(&p->priv->curve, black);
00550     eps_L(&p->priv->curve, black);
00551     
00552     /* output the vertex unit squares */
00553     for (i=0; i<p->priv->curve.n; i++) {
00554       eps_moveto(p->priv->curve.vertex[i]);
00555       ship("usq\n");
00556     }
00557 
00558     /* output the path */
00559     eps_linewidth(.1);
00560     eps_setcolor(blue);
00561     eps_path(&p->priv->curve);
00562     ship("closepath\n");
00563     ship("stroke\n");
00564 
00565     if (info.param->opticurve && info.debug == 3) {
00566 
00567       /* output opticurve */
00568       eps_linewidth(.05);
00569       eps_setcolor(red);
00570       eps_path(&p->priv->ocurve);
00571       ship("closepath\n");
00572       ship("stroke\n");
00573       
00574       /* output dots */
00575       for (i=0; i<p->priv->ocurve.n; i++) {
00576         eps_coords(p->priv->ocurve.c[i][2]);
00577         ship("dot1\n");
00578       }
00579     }
00580   }
00581   return 0;
00582 }
00583 
00584 /* Free-style debug output */
00585 static int render_debug(potrace_path_t *plist) {
00586   potrace_path_t *p;
00587   int count;
00588   int i;
00589 
00590   /* output original bitmap in grey */
00591   eps_jaggy(plist);
00592 
00593   count = -1;
00594   list_forall (p, plist) {
00595     count++;
00596 
00597     /* output path numbers */
00598     eps_moveto_offs(p->priv->curve.vertex[0], 0, 5);
00599     ship("times1 (%d) show\n", count);
00600 
00601     /* output polygon with corrected edges, lines L, and parameter alpha */
00602     eps_polygon(&p->priv->curve, black);
00603     eps_L(&p->priv->curve, black);
00604 
00605     /* output the vertex unit squares */
00606     for (i=0; i<p->priv->curve.n; i++) {
00607       eps_moveto(p->priv->curve.vertex[i]);
00608       ship("usq\n");
00609     }
00610 
00611     /* output the vertex numbers */
00612     for (i=0; i<p->priv->curve.n; i++) {
00613       eps_moveto_offs(p->priv->curve.vertex[i], +1, +1);
00614       ship("times2 (%d) show\n", i);
00615     }
00616     
00617     /* output the path */
00618     eps_linewidth(.1);
00619     eps_setcolor(blue);
00620     eps_path(&p->priv->curve);
00621     ship("closepath\n");
00622     ship("stroke\n");
00623     
00624     if (info.param->opticurve) {
00625 
00626       /* output the opti-verteces polygon */
00627       eps_polygon(&p->priv->ocurve, green);
00628       
00629       /* output opticurve */
00630       eps_linewidth(.05);
00631       eps_setcolor(red);
00632       eps_path(&p->priv->ocurve);
00633       ship("closepath\n");
00634       ship("stroke\n");
00635       
00636       /* output dots */
00637       for (i=0; i<p->priv->ocurve.n; i++) {
00638         eps_coords(p->priv->ocurve.c[i][2]);
00639         ship("dot1\n");
00640       }
00641 
00642       /* output beta parameters */
00643       for (i=0; i<p->priv->ocurve.n; i++) {
00644         eps_moveto_offs(p->priv->ocurve.c[i][2], +.4, -.4);
00645         ship("times (%.2f) show\n", p->priv->ocurve.beta[i]);
00646       }
00647     }
00648   }
00649   return 0;
00650 }
00651 
00652 /* select the appropriate rendering function from above */
00653 static int eps_render(potrace_path_t *plist) {
00654   int r;
00655   
00656   switch (info.debug) {
00657   case 0:
00658     if (info.opaque) {
00659       r = render0_opaque(plist);
00660     } else {
00661       r = render0(plist);
00662     }
00663     break;
00664   case 1:
00665     r = render1(plist);
00666     break;
00667   case 2: case 3:
00668     r = render2(plist);
00669     break;
00670   default:
00671     r = render_debug(plist);
00672     break;
00673   }
00674   return r;
00675 }  
00676 
00677 /* ---------------------------------------------------------------------- */
00678 /* EPS header and footer */
00679 
00680 static int eps_init(imginfo_t *imginfo) {
00681   double origx = imginfo->trans.orig[0] + imginfo->lmar;
00682   double origy = imginfo->trans.orig[1] + imginfo->bmar;
00683   double scalex = imginfo->width / imginfo->pixwidth / info.unit;
00684   double scaley = imginfo->height / imginfo->pixheight / info.unit;
00685   char *c0, *c1;
00686 
00687   shipcom("%%!PS-Adobe-3.0 EPSF-3.0\n");
00688   shipcom("%%%%Creator: "POTRACE" "VERSION", written by Peter Selinger 2001-2007\n");
00689   shipcom("%%%%LanguageLevel: %d\n", info.pslevel);
00690   shipcom("%%%%BoundingBox: 0 0 %d %d\n", 
00691           (int)ceil(imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar),
00692           (int)ceil(imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar));
00693   shipcom("%%%%Pages: 1\n");
00694   shipcom("%%%%EndComments\n");
00695   
00696   shipcom("%%%%Page: 1 1\n");
00697   if (!info.longcoding) {
00698     c0 = strdup(eps_colorstring(info.color));
00699     c1 = strdup(eps_colorstring(info.fillcolor));
00700     ship(optimacros, c0, c1);
00701     free(c0);
00702     free(c1);
00703   }
00704   if (info.debug) {
00705     ship(debugmacros, info.unit);
00706   }
00707   ship("gsave\n");
00708   if (origx != 0 || origy != 0) {
00709     ship("%.0f %.0f translate\n", origx, origy);
00710   }
00711   if (info.angle != 0) {
00712     ship("%.2f rotate\n", info.angle);
00713   }
00714   ship("%f %f scale\n", scalex, scaley);
00715 
00716   return 0;
00717 }
00718 
00719 static int eps_term(void) {
00720   ship("grestore\n");
00721   shipcom("%%%%EOF\n");
00722   return 0;
00723 }
00724 
00725 /* public interface for EPS */
00726 int page_eps(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
00727   int r;
00728 
00729   eps_callbacks(fout);
00730 
00731   eps_init(imginfo);
00732   
00733   r = eps_render(plist);
00734   if (r) {
00735     return r;
00736   }
00737 
00738   eps_term();
00739 
00740   return 0;
00741 }
00742 
00743 /* ---------------------------------------------------------------------- */
00744 /* PostScript header and footer */
00745 
00746 static int eps_pagenumber;
00747 
00748 int init_ps(FILE *fout) {
00749   char *c0, *c1;
00750 
00751   /* set callback functions for shipping routines */
00752   eps_callbacks(fout);
00753 
00754   shipcom("%%!PS-Adobe-3.0\n");
00755   shipcom("%%%%Creator: "POTRACE" "VERSION", written by Peter Selinger 2001-2007\n");
00756   shipcom("%%%%LanguageLevel: %d\n", info.pslevel);
00757   shipcom("%%%%BoundingBox: 0 0 %d %d\n", info.paperwidth, info.paperheight);
00758   shipcom("%%%%Pages: (atend)\n");
00759   shipcom("%%%%EndComments\n");
00760   if (!info.longcoding || info.debug) {
00761     shipcom("%%%%BeginSetup\n");
00762     if (!info.longcoding) {
00763       c0 = strdup(eps_colorstring(info.color));
00764       c1 = strdup(eps_colorstring(info.fillcolor));
00765       ship(optimacros, c0, c1);
00766       free(c0);
00767       free(c1);
00768     }
00769     if (info.debug) {
00770       ship(debugmacros, info.unit);
00771     }
00772     shipcom("%%%%EndSetup\n");
00773   }
00774   eps_pagenumber = 0;
00775   fflush(fout);
00776   return 0;
00777 }
00778 
00779 int term_ps(FILE *fout) {
00780   eps_callbacks(fout);
00781 
00782   shipcom("%%%%Trailer\n");
00783   shipcom("%%%%Pages: %d\n", eps_pagenumber);
00784   shipcom("%%%%EOF\n");
00785   fflush(fout);
00786 
00787   return 0;
00788 }
00789 
00790 static void eps_pageinit_ps(imginfo_t *imginfo) {
00791   double origx = imginfo->trans.orig[0] + imginfo->lmar;
00792   double origy = imginfo->trans.orig[1] + imginfo->bmar;
00793   double scalex = imginfo->width / imginfo->pixwidth / info.unit;
00794   double scaley = imginfo->height / imginfo->pixheight / info.unit;
00795 
00796   eps_pagenumber++;
00797   eps_color = -1;
00798   eps_width = -1;
00799 
00800   shipcom("%%%%Page: %d %d\n", eps_pagenumber, eps_pagenumber);
00801   ship("gsave\n");
00802   if (origx != 0 || origy != 0) {
00803     ship("%.0f %.0f translate\n", origx, origy);
00804   }
00805   if (info.angle != 0) {
00806     ship("%.2f rotate\n", info.angle);
00807   }
00808   ship("%f %f scale\n", scalex, scaley);
00809 }
00810 
00811 static void eps_pageterm_ps(void) {
00812   ship("grestore\n");
00813   ship("showpage\n");
00814 }
00815 
00816 int page_ps(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
00817   int r;
00818 
00819   eps_callbacks(fout);
00820 
00821   eps_pageinit_ps(imginfo);
00822 
00823   r = eps_render(plist);
00824   if (r) {
00825     return r;
00826   }
00827 
00828   eps_pageterm_ps();
00829 
00830   shipcom("");
00831 
00832   fflush(fout);
00833 
00834   return 0;
00835 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Defines


portrait_painter
Author(s): Niklas Meinzer, Ina Baumgarten
autogenerated on Wed Dec 26 2012 16:00:42