00001
00002
00003
00004
00005
00006
00007
00008
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
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
00055
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
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;
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092 static int (*xship)(FILE *f, int filter, char *s, int len);
00093 static FILE *xship_file;
00094
00095
00096 static int ship(const char *fmt, ...) {
00097 va_list args;
00098 static char buf[4096];
00099
00100
00101
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
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
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
00138
00139
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
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
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
00233
00234
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
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
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
00273
00274 int init_pdf(FILE *fout)
00275 {
00276 intarray_init(&xref);
00277 intarray_init(&pages);
00278 nxref = 0;
00279 npages = 0;
00280
00281
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
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