backend_pdf.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_pdf.c 147 2007-04-09 00:44:09Z selinger $ */
00006 
00007 /* The PDF backend of Potrace. Stream compression is optionally
00008         supplied via the functions in flate.c. */
00009 
00010 #include <stdio.h>
00011 #include <stdarg.h>
00012 #include <string.h>
00013 #include <math.h>
00014 #include <stdlib.h>
00015 
00016 #include "main.h"
00017 #include "backend_pdf.h"
00018 #include "flate.h"
00019 #include "lists.h"
00020 #include "potracelib.h"
00021 #include "auxiliary.h"
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include "config.h"
00025 #endif
00026 
00027 typedef int color_t;
00028 
00029 #define black  0x000000
00030 #define red    0xff0000
00031 #define green  0x008000
00032 #define blue   0x0000ff
00033 
00034 /* ---------------------------------------------------------------------- */
00035 /* auxiliary: growing arrays */
00036 
00037 struct intarray_s {
00038   int size;
00039   int *data;
00040 };
00041 typedef struct intarray_s intarray_t;
00042 
00043 static inline void intarray_init(intarray_t *ar) {
00044   ar->size = 0;
00045   ar->data = NULL;
00046 }
00047 
00048 static inline void intarray_term(intarray_t *ar) {
00049   free(ar->data);
00050   ar->size = 0;
00051   ar->data = NULL;
00052 }
00053 
00054 /* Set ar[n]=val. Expects n>=0. Grows array if necessary. Return 0 on
00055    success and -1 on error with errno set. */
00056 static inline int intarray_set(intarray_t *ar, int n, int val) {
00057   int *p;
00058   int s;
00059 
00060   if (n >= ar->size) {
00061     s = n+1024;
00062     p = (int *)realloc(ar->data, s * sizeof(int));
00063     if (!p) {
00064       return -1;
00065     }
00066     ar->data = p;
00067     ar->size = s;
00068   }
00069   ar->data[n] = val;
00070   return 0;
00071 }
00072 
00073 /* ---------------------------------------------------------------------- */
00074 /* some global variables */
00075 
00076 static intarray_t xref;
00077 static int nxref = 0;
00078 static intarray_t pages;
00079 static int npages;
00080 static int streamofs;
00081 static size_t outcount;  /* output file position */
00082 
00083 /* ---------------------------------------------------------------------- */
00084 /* functions for interfacing with compression backend */
00085 
00086 /* xship: callback function that must be initialized before calling
00087    any other functions of the "ship" family. xship_file must be
00088    initialized too. */
00089 
00090 /* print the token to f, but filtered through a compression
00091    filter in case filter!=0 */
00092 static int (*xship)(FILE *f, int filter, char *s, int len);
00093 static FILE *xship_file;
00094 
00095 /* ship PDF code, filtered */
00096 static int ship(const char *fmt, ...) {
00097   va_list args;
00098   static char buf[4096]; /* static string limit is okay here because
00099                             we only use constant format strings - for
00100                             the same reason, it is okay to use
00101                             vsprintf instead of vsnprintf below. */
00102   va_start(args, fmt);
00103   vsprintf(buf, fmt, args);
00104   buf[4095] = 0;
00105   va_end(args);
00106 
00107   outcount += xship(xship_file, 1, buf, strlen(buf));
00108   return 0;
00109 }  
00110 
00111 /* ship PDF code, unfiltered */
00112 static int shipclear(char *fmt, ...) {
00113   static char buf[4096];
00114   va_list args;
00115 
00116   va_start(args, fmt);
00117   vsprintf(buf, fmt, args);
00118   buf[4095] = 0;
00119   va_end(args);
00120 
00121   outcount += xship(xship_file, 0, buf, strlen(buf));
00122   return 0;
00123 }
00124 
00125 /* set all callback functions */
00126 static void pdf_callbacks(FILE *fout) {
00127 
00128   if (info.compress) {
00129     xship = pdf_xship;
00130   } else {
00131     xship = dummy_xship;
00132   }
00133   xship_file = fout;
00134 }  
00135 
00136 /* ---------------------------------------------------------------------- */
00137 /* PDF path-drawing auxiliary functions */
00138 
00139 /* coordinate quantization */
00140 static inline point_t unit(dpoint_t p) {
00141   point_t q;
00142 
00143   q.x = (long)(floor(p.x*info.unit+.5));
00144   q.y = (long)(floor(p.y*info.unit+.5));
00145   return q;
00146 }
00147 
00148 static void pdf_coords(dpoint_t p) {
00149   point_t cur = unit(p);
00150   ship("%ld %ld ", cur.x, cur.y);
00151 }
00152 
00153 static void pdf_moveto(dpoint_t p) {
00154   pdf_coords(p);
00155   ship("m\n");
00156 }
00157 
00158 static void pdf_lineto(dpoint_t p) {
00159   pdf_coords(p);
00160   ship("l\n");
00161 }
00162 
00163 static void pdf_curveto(dpoint_t p1, dpoint_t p2, dpoint_t p3) {
00164   point_t q1, q2, q3;
00165 
00166   q1 = unit(p1);
00167   q2 = unit(p2);
00168   q3 = unit(p3);
00169 
00170   ship("%ld %ld %ld %ld %ld %ld c\n", q1.x, q1.y, q2.x, q2.y, q3.x, q3.y);
00171 }
00172 
00173 /* this procedure returns a statically allocated string */
00174 static char *pdf_colorstring(const color_t col) {
00175   double r, g, b;
00176   static char buf[100];
00177 
00178   r = (col & 0xff0000) >> 16;
00179   g = (col & 0x00ff00) >> 8;
00180   b = (col & 0x0000ff) >> 0;
00181 
00182   if (r==0 && g==0 && b==0) {
00183     return "0 g";
00184   } else if (r==255 && g==255 && b==255) {
00185     return "1 g";
00186   } else if (r == g && g == b) {
00187     sprintf(buf, "%.3f g", r/255.0);
00188     return buf;
00189   } else {
00190     sprintf(buf, "%.3f %.3f %.3f rg", r/255.0, g/255.0, b/255.0);
00191     return buf;
00192   }
00193 }
00194 
00195 static color_t pdf_color = -1;
00196 static double pdf_width = -1;
00197 
00198 static void pdf_setcolor(const color_t col) {
00199   if (col == pdf_color) {
00200     return;
00201   }
00202   pdf_color = col;
00203 
00204   ship("%s\n", pdf_colorstring(col));
00205 }
00206 
00207 /* explicit encoding, does not use special macros */
00208 static int pdf_path(potrace_curve_t *curve) {
00209   int i;
00210   dpoint_t *c;
00211   int m = curve->n;
00212 
00213   c = curve->c[m-1];
00214   pdf_moveto(c[2]);
00215 
00216   for (i=0; i<m; i++) {
00217     c = curve->c[i];
00218     switch (curve->tag[i]) {
00219     case POTRACE_CORNER:
00220       pdf_lineto(c[1]);
00221       pdf_lineto(c[2]);
00222       break;
00223     case POTRACE_CURVETO:
00224       pdf_curveto(c[0], c[1], c[2]);
00225       break;
00226     }
00227   }
00228   return 0;
00229 }
00230 
00231 /* ---------------------------------------------------------------------- */
00232 /* Backends for various types of output. */
00233 
00234 /* Normal output: black on transparent */
00235 static int render0(potrace_path_t *plist) {
00236   potrace_path_t *p;
00237 
00238   pdf_setcolor(info.color);
00239   list_forall (p, plist) {
00240     pdf_path(&p->curve);
00241     ship("h\n");
00242     if (p->next == NULL || p->next->sign == '+') {
00243       ship("f\n");
00244     }
00245   }
00246   return 0;
00247 }
00248 
00249 /* Opaque output: alternating black and white */
00250 static int render0_opaque(potrace_path_t *plist) {
00251   potrace_path_t *p;
00252   
00253   list_forall (p, plist) {
00254     pdf_path(&p->curve);
00255     ship("h\n");
00256     pdf_setcolor(p->sign=='+' ? info.color : info.fillcolor);
00257     ship("f\n");
00258   }
00259   return 0;
00260 }
00261 
00262 /* select the appropriate rendering function from above */
00263 static int pdf_render(potrace_path_t *plist)
00264 {
00265   if (info.opaque) {
00266     return render0_opaque(plist);
00267   }
00268   return render0(plist);
00269 }  
00270 
00271 /* ---------------------------------------------------------------------- */
00272 /* PDF header and footer */
00273 
00274 int init_pdf(FILE *fout)
00275 {
00276         intarray_init(&xref);
00277         intarray_init(&pages);
00278         nxref = 0;
00279         npages = 0;
00280 
00281         /* set callback functions for shipping routines */
00282         pdf_callbacks(fout);
00283         outcount = 0;
00284 
00285         shipclear("%%PDF-1.3\n");
00286 
00287         intarray_set(&xref, nxref++, outcount);
00288         shipclear("1 0 obj\n<</Type/Catalog/Pages 3 0 R>>\nendobj\n");
00289 
00290         intarray_set(&xref, nxref++, outcount);
00291         shipclear("2 0 obj\n"
00292                 "<</Creator"
00293                 "("POTRACE" "VERSION", written by Peter Selinger 2001-2007)>>\n"
00294                 "endobj\n");
00295 
00296         /* delay obj #3 (pages) until end */
00297         nxref++;
00298 
00299         fflush(fout);
00300         return 0;
00301 }
00302 
00303 int term_pdf(FILE *fout)
00304 {
00305         int startxref;
00306         int i;
00307 
00308         pdf_callbacks(fout);
00309 
00310         intarray_set(&xref, 2, outcount);
00311         shipclear("3 0 obj\n"
00312                 "<</Type/Pages/Count %d/Kids[\n", npages);
00313         for (i = 0; i < npages; i++)
00314                 shipclear("%d 0 R\n", pages.data[i]);
00315         shipclear("]>>\nendobj\n");
00316 
00317         startxref = outcount;
00318 
00319         shipclear("xref\n0 %d\n", nxref + 1);
00320         shipclear("0000000000 65535 f \n");
00321         for (i = 0; i < nxref; i++)
00322                 shipclear("%0.10d 00000 n \n", xref.data[i]);
00323 
00324         shipclear("trailer\n<</Size %d/Root 1 0 R/Info 2 0 R>>\n", nxref + 1);
00325         shipclear("startxref\n%d\n%%%%EOF\n", startxref);
00326 
00327         fflush(fout);
00328         intarray_term(&xref);
00329         intarray_term(&pages);
00330         return 0;
00331 }
00332 
00333 static void pdf_pageinit(imginfo_t *imginfo)
00334 {
00335         double s, c;
00336 
00337         double origx = imginfo->trans.orig[0] + imginfo->lmar;
00338         double origy = imginfo->trans.orig[1] + imginfo->bmar;
00339         double scalex = imginfo->width / imginfo->pixwidth / info.unit;
00340         double scaley = imginfo->height / imginfo->pixheight / info.unit;
00341         int pagew = (int)ceil(imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar);
00342         int pageh = (int)ceil(imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar);
00343 
00344         pdf_color = -1;
00345         pdf_width = -1;
00346 
00347         intarray_set(&xref, nxref++, outcount);
00348         shipclear("%d 0 obj\n", nxref);
00349         shipclear("<</Type/Page/Parent 3 0 R/Resources<</ProcSet[/PDF]>>");
00350         shipclear("/MediaBox[0 0 %d %d]", pagew, pageh);
00351         shipclear("/Contents %d 0 R>>\n", nxref + 1);
00352         shipclear("endobj\n");
00353 
00354         intarray_set(&pages, npages++, nxref);
00355 
00356         intarray_set(&xref, nxref++, outcount);
00357         shipclear("%d 0 obj\n", nxref);
00358         if (info.compress)
00359                 shipclear("<</Filter/FlateDecode/Length %d 0 R>>\n", nxref + 1);
00360         else
00361                 shipclear("<</Length %d 0 R>>\n", nxref + 1);
00362         shipclear("stream\n");
00363 
00364         streamofs = outcount;
00365 
00366         s = sin(info.angle * M_PI / 180.0);
00367         c = cos(info.angle * M_PI / 180.0);
00368 
00369         ship("%f %f %f %f %.0f %.0f cm\n", scalex*c, scalex*s, -scaley*s, scaley*c, origx, origy);
00370 }
00371 
00372 static void pdf_pageterm(void)
00373 {
00374         int streamlen;
00375 
00376         shipclear("");
00377 
00378         streamlen = outcount - streamofs;
00379         shipclear("endstream\nendobj\n");
00380         
00381         intarray_set(&xref, nxref++, outcount);
00382         shipclear("%d 0 obj\n%d\nendobj\n", nxref, streamlen);
00383 }
00384 
00385 int page_pdf(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo)
00386 {
00387   int r;
00388 
00389   pdf_callbacks(fout);
00390 
00391   pdf_pageinit(imginfo);
00392 
00393   r = pdf_render(plist);
00394   if (r) {
00395     return r;
00396   }
00397 
00398   pdf_pageterm();
00399 
00400   fflush(fout);
00401 
00402   return 0;
00403 }
00404 
 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