Statistics
| Revision:

gvsig-raster / libjni-potrace / trunk / libjni-potrace / src / main / native / jpotrace / backend_pdf.c @ 1780

History | View | Annotate | Download (8.95 KB)

1
/* Copyright (C) 2001-2007 Peter Selinger.
2
   This file is part of Potrace. It is free software and it is covered
3
   by the GNU General Public License. See the file COPYING for details. */
4

    
5
/* $Id: backend_pdf.c 147 2007-04-09 00:44:09Z selinger $ */
6

    
7
/* The PDF backend of Potrace. Stream compression is optionally
8
        supplied via the functions in flate.c. */
9

    
10
#include <stdio.h>
11
#include <stdarg.h>
12
#include <string.h>
13
#include <math.h>
14
#include <stdlib.h>
15

    
16
#include "main.h"
17
#include "backend_pdf.h"
18
#include "flate.h"
19
#include "lists.h"
20
#include "potracelib.h"
21
#include "auxiliary.h"
22

    
23
#ifdef HAVE_CONFIG_H
24
#include "config.h"
25
#endif
26

    
27
#ifndef M_PI
28
        #define M_PI 3.14159265358979323846
29
#endif
30

    
31

    
32
typedef int color_t;
33

    
34
#define black  0x000000
35
#define red    0xff0000
36
#define green  0x008000
37
#define blue   0x0000ff
38

    
39
/* ---------------------------------------------------------------------- */
40
/* auxiliary: growing arrays */
41

    
42
struct intarray_s {
43
  int size;
44
  int *data;
45
};
46
typedef struct intarray_s intarray_t;
47

    
48
static inline void intarray_init(intarray_t *ar) {
49
  ar->size = 0;
50
  ar->data = NULL;
51
}
52

    
53
static inline void intarray_term(intarray_t *ar) {
54
  free(ar->data);
55
  ar->size = 0;
56
  ar->data = NULL;
57
}
58

    
59
/* Set ar[n]=val. Expects n>=0. Grows array if necessary. Return 0 on
60
   success and -1 on error with errno set. */
61
static inline int intarray_set(intarray_t *ar, int n, int val) {
62
  int *p;
63
  int s;
64

    
65
  if (n >= ar->size) {
66
    s = n+1024;
67
    p = (int *)realloc(ar->data, s * sizeof(int));
68
    if (!p) {
69
      return -1;
70
    }
71
    ar->data = p;
72
    ar->size = s;
73
  }
74
  ar->data[n] = val;
75
  return 0;
76
}
77

    
78
/* ---------------------------------------------------------------------- */
79
/* some global variables */
80

    
81
static intarray_t xref;
82
static int nxref = 0;
83
static intarray_t pages;
84
static int npages;
85
static int streamofs;
86
static size_t outcount;  /* output file position */
87

    
88
/* ---------------------------------------------------------------------- */
89
/* functions for interfacing with compression backend */
90

    
91
/* xship: callback function that must be initialized before calling
92
   any other functions of the "ship" family. xship_file must be
93
   initialized too. */
94

    
95
/* print the token to f, but filtered through a compression
96
   filter in case filter!=0 */
97
static int (*xship)(FILE *f, int filter, char *s, int len);
98
static FILE *xship_file;
99

    
100
/* ship PDF code, filtered */
101
static int ship(const char *fmt, ...) {
102
  va_list args;
103
  static char buf[4096]; /* static string limit is okay here because
104
                            we only use constant format strings - for
105
                            the same reason, it is okay to use
106
                            vsprintf instead of vsnprintf below. */
107
  va_start(args, fmt);
108
  vsprintf(buf, fmt, args);
109
  buf[4095] = 0;
110
  va_end(args);
111

    
112
  outcount += xship(xship_file, 1, buf, strlen(buf));
113
  return 0;
114
}  
115

    
116
/* ship PDF code, unfiltered */
117
static int shipclear(char *fmt, ...) {
118
  static char buf[4096];
119
  va_list args;
120

    
121
  va_start(args, fmt);
122
  vsprintf(buf, fmt, args);
123
  buf[4095] = 0;
124
  va_end(args);
125

    
126
  outcount += xship(xship_file, 0, buf, strlen(buf));
127
  return 0;
128
}
129

    
130
/* set all callback functions */
131
static void pdf_callbacks(FILE *fout) {
132

    
133
  if (info.compress) {
134
    xship = pdf_xship;
135
  } else {
136
    xship = dummy_xship;
137
  }
138
  xship_file = fout;
139
}  
140

    
141
/* ---------------------------------------------------------------------- */
142
/* PDF path-drawing auxiliary functions */
143

    
144
/* coordinate quantization */
145
static inline point_t unit(dpoint_t p) {
146
  point_t q;
147

    
148
  q.x = (long)(floor(p.x*info.unit+.5));
149
  q.y = (long)(floor(p.y*info.unit+.5));
150
  return q;
151
}
152

    
153
static void pdf_coords(dpoint_t p) {
154
  point_t cur = unit(p);
155
  ship("%ld %ld ", cur.x, cur.y);
156
}
157

    
158
static void pdf_moveto(dpoint_t p) {
159
  pdf_coords(p);
160
  ship("m\n");
161
}
162

    
163
static void pdf_lineto(dpoint_t p) {
164
  pdf_coords(p);
165
  ship("l\n");
166
}
167

    
168
static void pdf_curveto(dpoint_t p1, dpoint_t p2, dpoint_t p3) {
169
  point_t q1, q2, q3;
170

    
171
  q1 = unit(p1);
172
  q2 = unit(p2);
173
  q3 = unit(p3);
174

    
175
  ship("%ld %ld %ld %ld %ld %ld c\n", q1.x, q1.y, q2.x, q2.y, q3.x, q3.y);
176
}
177

    
178
/* this procedure returns a statically allocated string */
179
static char *pdf_colorstring(const color_t col) {
180
  double r, g, b;
181
  static char buf[100];
182

    
183
  r = (col & 0xff0000) >> 16;
184
  g = (col & 0x00ff00) >> 8;
185
  b = (col & 0x0000ff) >> 0;
186

    
187
  if (r==0 && g==0 && b==0) {
188
    return "0 g";
189
  } else if (r==255 && g==255 && b==255) {
190
    return "1 g";
191
  } else if (r == g && g == b) {
192
    sprintf(buf, "%.3f g", r/255.0);
193
    return buf;
194
  } else {
195
    sprintf(buf, "%.3f %.3f %.3f rg", r/255.0, g/255.0, b/255.0);
196
    return buf;
197
  }
198
}
199

    
200
static color_t pdf_color = -1;
201
static double pdf_width = -1;
202

    
203
static void pdf_setcolor(const color_t col) {
204
  if (col == pdf_color) {
205
    return;
206
  }
207
  pdf_color = col;
208

    
209
  ship("%s\n", pdf_colorstring(col));
210
}
211

    
212
/* explicit encoding, does not use special macros */
213
static int pdf_path(potrace_curve_t *curve) {
214
  int i;
215
  dpoint_t *c;
216
  int m = curve->n;
217

    
218
  c = curve->c[m-1];
219
  pdf_moveto(c[2]);
220

    
221
  for (i=0; i<m; i++) {
222
    c = curve->c[i];
223
    switch (curve->tag[i]) {
224
    case POTRACE_CORNER:
225
      pdf_lineto(c[1]);
226
      pdf_lineto(c[2]);
227
      break;
228
    case POTRACE_CURVETO:
229
      pdf_curveto(c[0], c[1], c[2]);
230
      break;
231
    }
232
  }
233
  return 0;
234
}
235

    
236
/* ---------------------------------------------------------------------- */
237
/* Backends for various types of output. */
238

    
239
/* Normal output: black on transparent */
240
static int render0(potrace_path_t *plist) {
241
  potrace_path_t *p;
242

    
243
  pdf_setcolor(info.color);
244
  list_forall (p, plist) {
245
    pdf_path(&p->curve);
246
    ship("h\n");
247
    if (p->next == NULL || p->next->sign == '+') {
248
      ship("f\n");
249
    }
250
  }
251
  return 0;
252
}
253

    
254
/* Opaque output: alternating black and white */
255
static int render0_opaque(potrace_path_t *plist) {
256
  potrace_path_t *p;
257
  
258
  list_forall (p, plist) {
259
    pdf_path(&p->curve);
260
    ship("h\n");
261
    pdf_setcolor(p->sign=='+' ? info.color : info.fillcolor);
262
    ship("f\n");
263
  }
264
  return 0;
265
}
266

    
267
/* select the appropriate rendering function from above */
268
static int pdf_render(potrace_path_t *plist)
269
{
270
  if (info.opaque) {
271
    return render0_opaque(plist);
272
  }
273
  return render0(plist);
274
}  
275

    
276
/* ---------------------------------------------------------------------- */
277
/* PDF header and footer */
278

    
279
int init_pdf(FILE *fout)
280
{
281
        intarray_init(&xref);
282
        intarray_init(&pages);
283
        nxref = 0;
284
        npages = 0;
285

    
286
        /* set callback functions for shipping routines */
287
        pdf_callbacks(fout);
288
        outcount = 0;
289

    
290
        shipclear("%%PDF-1.3\n");
291

    
292
        intarray_set(&xref, nxref++, outcount);
293
        shipclear("1 0 obj\n<</Type/Catalog/Pages 3 0 R>>\nendobj\n");
294

    
295
        intarray_set(&xref, nxref++, outcount);
296
        shipclear("2 0 obj\n"
297
                "<</Creator"
298
                "(\"POTRACE\" \"VERSION\", written by Peter Selinger 2001-2007)>>\n"
299
                "endobj\n");
300

    
301
        /* delay obj #3 (pages) until end */
302
        nxref++;
303

    
304
        fflush(fout);
305
        return 0;
306
}
307

    
308
int term_pdf(FILE *fout)
309
{
310
        int startxref;
311
        int i;
312

    
313
        pdf_callbacks(fout);
314

    
315
        intarray_set(&xref, 2, outcount);
316
        shipclear("3 0 obj\n"
317
                "<</Type/Pages/Count %d/Kids[\n", npages);
318
        for (i = 0; i < npages; i++)
319
                shipclear("%d 0 R\n", pages.data[i]);
320
        shipclear("]>>\nendobj\n");
321

    
322
        startxref = outcount;
323

    
324
        shipclear("xref\n0 %d\n", nxref + 1);
325
        shipclear("0000000000 65535 f \n");
326
        for (i = 0; i < nxref; i++)
327
                shipclear("%0.10d 00000 n \n", xref.data[i]);
328

    
329
        shipclear("trailer\n<</Size %d/Root 1 0 R/Info 2 0 R>>\n", nxref + 1);
330
        shipclear("startxref\n%d\n%%%%EOF\n", startxref);
331

    
332
        fflush(fout);
333
        intarray_term(&xref);
334
        intarray_term(&pages);
335
        return 0;
336
}
337

    
338
static void pdf_pageinit(imginfo_t *imginfo)
339
{
340
        double s, c;
341

    
342
        double origx = imginfo->trans.orig[0] + imginfo->lmar;
343
        double origy = imginfo->trans.orig[1] + imginfo->bmar;
344
        double scalex = imginfo->width / imginfo->pixwidth / info.unit;
345
        double scaley = imginfo->height / imginfo->pixheight / info.unit;
346
        int pagew = (int)ceil(imginfo->trans.bb[0]+imginfo->lmar+imginfo->rmar);
347
        int pageh = (int)ceil(imginfo->trans.bb[1]+imginfo->tmar+imginfo->bmar);
348

    
349
        pdf_color = -1;
350
        pdf_width = -1;
351

    
352
        intarray_set(&xref, nxref++, outcount);
353
        shipclear("%d 0 obj\n", nxref);
354
        shipclear("<</Type/Page/Parent 3 0 R/Resources<</ProcSet[/PDF]>>");
355
        shipclear("/MediaBox[0 0 %d %d]", pagew, pageh);
356
        shipclear("/Contents %d 0 R>>\n", nxref + 1);
357
        shipclear("endobj\n");
358

    
359
        intarray_set(&pages, npages++, nxref);
360

    
361
        intarray_set(&xref, nxref++, outcount);
362
        shipclear("%d 0 obj\n", nxref);
363
        if (info.compress)
364
                shipclear("<</Filter/FlateDecode/Length %d 0 R>>\n", nxref + 1);
365
        else
366
                shipclear("<</Length %d 0 R>>\n", nxref + 1);
367
        shipclear("stream\n");
368

    
369
        streamofs = outcount;
370

    
371
        s = sin(info.angle * M_PI / 180.0);
372
        c = cos(info.angle * M_PI / 180.0);
373

    
374
        ship("%f %f %f %f %.0f %.0f cm\n", scalex*c, scalex*s, -scaley*s, scaley*c, origx, origy);
375
}
376

    
377
static void pdf_pageterm(void)
378
{
379
        int streamlen;
380

    
381
        shipclear("");
382

    
383
        streamlen = outcount - streamofs;
384
        shipclear("endstream\nendobj\n");
385
        
386
        intarray_set(&xref, nxref++, outcount);
387
        shipclear("%d 0 obj\n%d\nendobj\n", nxref, streamlen);
388
}
389

    
390
int page_pdf(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo)
391
{
392
  int r;
393

    
394
  pdf_callbacks(fout);
395

    
396
  pdf_pageinit(imginfo);
397

    
398
  r = pdf_render(plist);
399
  if (r) {
400
    return r;
401
  }
402

    
403
  pdf_pageterm();
404

    
405
  fflush(fout);
406

    
407
  return 0;
408
}
409