gvsig-raster / libjni-potrace / trunk / libjni-potrace / resources / potrace-1.8 / src / backend_xfig.c @ 1780
History | View | Annotate | Download (5.88 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_xfig.c 147 2007-04-09 00:44:09Z selinger $ */
|
6 |
|
7 |
/* The xfig backend of Potrace. */
|
8 |
|
9 |
#include <stdio.h> |
10 |
#include <stdarg.h> |
11 |
#include <string.h> |
12 |
#include <math.h> |
13 |
|
14 |
#include "main.h" |
15 |
#include "backend_xfig.h" |
16 |
#include "potracelib.h" |
17 |
#include "lists.h" |
18 |
#include "auxiliary.h" |
19 |
|
20 |
#ifdef HAVE_CONFIG_H
|
21 |
#include "config.h" |
22 |
#endif
|
23 |
|
24 |
#ifndef M_PI
|
25 |
#define M_PI 3.14159265358979323846 |
26 |
#endif
|
27 |
|
28 |
struct pageformat_s {
|
29 |
char *name;
|
30 |
int w, h;
|
31 |
}; |
32 |
typedef struct pageformat_s pageformat_t; |
33 |
|
34 |
/* page formats known by xfig, and their dimensions in postscript points */
|
35 |
static pageformat_t pageformat[] = {
|
36 |
{ "A9", 105, 149 }, |
37 |
{ "A8", 149, 211 }, |
38 |
{ "A7", 211, 298 }, |
39 |
{ "A6", 298, 421 }, |
40 |
{ "A5", 421, 595 }, |
41 |
{ "A4", 595, 842 }, |
42 |
{ "A3", 842, 1191 }, |
43 |
{ "A2", 1191, 1685 }, |
44 |
{ "A1", 1685, 2383 }, |
45 |
{ "A0", 2383, 3370 }, |
46 |
|
47 |
{ "B10", 91, 129 }, |
48 |
{ "B9", 129, 182 }, |
49 |
{ "B8", 182, 258 }, |
50 |
{ "B7", 258, 365 }, |
51 |
{ "B6", 365, 516 }, |
52 |
{ "B5", 516, 730 }, |
53 |
{ "B4", 730, 1032 }, |
54 |
{ "B3", 1032, 1460 }, |
55 |
{ "B2", 1460, 2064 }, |
56 |
{ "B1", 2064, 2920 }, |
57 |
{ "B0", 2920, 4127 }, |
58 |
|
59 |
{ "Letter", 612, 792 }, |
60 |
{ "Legal", 612, 1008 }, |
61 |
{ "Tabloid", 792, 1224 }, |
62 |
{ "A", 612, 792 }, |
63 |
{ "B", 792, 1224 }, |
64 |
{ "C", 1224, 1584 }, |
65 |
{ "D", 1584, 2448 }, |
66 |
{ "E", 2448, 3168 }, |
67 |
|
68 |
{ NULL, 0, 0 }, |
69 |
}; |
70 |
|
71 |
/* ---------------------------------------------------------------------- */
|
72 |
/* path-drawing auxiliary functions */
|
73 |
|
74 |
/* structure to hold an affine coordinate transformation */
|
75 |
struct trans_s {
|
76 |
double ox, oy; /* origin */ |
77 |
double dxx, dxy, dyx, dyy; /* transformation matrix */ |
78 |
}; |
79 |
typedef struct trans_s trans_t; |
80 |
|
81 |
static inline dpoint_t trans(dpoint_t p, trans_t t) { |
82 |
dpoint_t res; |
83 |
|
84 |
res.x = t.ox + p.x * t.dxx + p.y * t.dyx; |
85 |
res.y = t.oy + p.x * t.dxy + p.y * t.dyy; |
86 |
return res;
|
87 |
} |
88 |
|
89 |
/* coordinate quantization */
|
90 |
static inline point_t unit(dpoint_t p) { |
91 |
point_t q; |
92 |
|
93 |
q.x = (long)(floor(p.x+.5)); |
94 |
q.y = (long)(floor(p.y+.5)); |
95 |
return q;
|
96 |
} |
97 |
|
98 |
static void xfig_point(FILE *fout, dpoint_t p, trans_t t) { |
99 |
point_t q; |
100 |
|
101 |
q = unit(trans(p, t)); |
102 |
|
103 |
fprintf(fout, "%ld %ld\n", q.x, q.y);
|
104 |
} |
105 |
|
106 |
/* ---------------------------------------------------------------------- */
|
107 |
/* functions for converting a path to a xfig */
|
108 |
|
109 |
/* calculate number of xfig control points in this path */
|
110 |
static int npoints(potrace_curve_t *curve, int m) { |
111 |
int i;
|
112 |
int n=0; |
113 |
|
114 |
for (i=0; i<m; i++) { |
115 |
switch (curve->tag[i]) {
|
116 |
case POTRACE_CORNER:
|
117 |
n += 1;
|
118 |
break;
|
119 |
case POTRACE_CURVETO:
|
120 |
n += 2;
|
121 |
break;
|
122 |
} |
123 |
} |
124 |
return n;
|
125 |
} |
126 |
|
127 |
/* do one path. First should be 1 on the very first path, else 0. */
|
128 |
static int xfig_path(FILE *fout, potrace_curve_t *curve, trans_t t, int sign) { |
129 |
int i;
|
130 |
dpoint_t *c; |
131 |
int m = curve->n;
|
132 |
|
133 |
fprintf(fout, "3 1 0 0 0 %d 50 0 20 0.000 0 0 0 %d\n", sign=='+' ? 32 : 33, npoints(curve, m)); |
134 |
|
135 |
for (i=0; i<m; i++) { |
136 |
c = curve->c[i]; |
137 |
switch (curve->tag[i]) {
|
138 |
case POTRACE_CORNER:
|
139 |
xfig_point(fout, c[1], t);
|
140 |
break;
|
141 |
case POTRACE_CURVETO:
|
142 |
xfig_point(fout, c[0], t);
|
143 |
xfig_point(fout, c[1], t);
|
144 |
break;
|
145 |
} |
146 |
} |
147 |
for (i=0; i<m; i++) { |
148 |
switch (curve->tag[i]) {
|
149 |
case POTRACE_CORNER:
|
150 |
fprintf(fout, "0\n");
|
151 |
break;
|
152 |
case POTRACE_CURVETO:
|
153 |
fprintf(fout, "1 1\n");
|
154 |
break;
|
155 |
} |
156 |
} |
157 |
return 0; |
158 |
} |
159 |
|
160 |
/* ---------------------------------------------------------------------- */
|
161 |
/* Backend. */
|
162 |
|
163 |
/* public interface for XFIG */
|
164 |
int page_xfig(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) {
|
165 |
potrace_path_t *p; |
166 |
trans_t t; |
167 |
double si, co;
|
168 |
double origx = imginfo->trans.orig[0] + imginfo->lmar; |
169 |
double origy = - imginfo->trans.orig[1] - imginfo->bmar + info.paperheight; |
170 |
double scalex = imginfo->width / imginfo->pixwidth;
|
171 |
double scaley = imginfo->height / imginfo->pixheight;
|
172 |
char *formatname;
|
173 |
int best, penalty;
|
174 |
pageformat_t *f; |
175 |
int i;
|
176 |
int x0, y0, x1, y1; /* in xfig's coordinates */ |
177 |
|
178 |
si = sin(info.angle/180*M_PI);
|
179 |
co = cos(info.angle/180*M_PI);
|
180 |
|
181 |
t.ox = 1200/72.0 * origx; |
182 |
t.oy = 1200/72.0 * origy; |
183 |
t.dxx = 1200/72.0 * scalex * co; |
184 |
t.dxy = 1200/72.0 * scalex * -si; |
185 |
t.dyx = 1200/72.0 * scaley * -si; |
186 |
t.dyy = 1200/72.0 * scaley * -co; |
187 |
|
188 |
x0 = (int)(1200/72.0 * (origx - imginfo->trans.orig[0])); |
189 |
y0 = (int)(1200/72.0 * (origy + imginfo->trans.orig[1])); |
190 |
x1 = x0 + (int)(1200/72.0 * imginfo->trans.bb[0]); |
191 |
y1 = y0 - (int)(1200/72.0 * imginfo->trans.bb[1]); |
192 |
|
193 |
best = -1;
|
194 |
formatname = "Letter";
|
195 |
|
196 |
/* find closest page format */
|
197 |
for (i=0; pageformat[i].name; i++) { |
198 |
f = &pageformat[i]; |
199 |
if (f->w >= info.paperwidth-1 && f->h >= info.paperheight-1) { |
200 |
penalty = f->w + f->h; |
201 |
if (best == -1 || penalty < best) { |
202 |
best = penalty; |
203 |
formatname = f->name; |
204 |
} |
205 |
} |
206 |
} |
207 |
|
208 |
/* header */
|
209 |
fprintf(fout, "#FIG 3.2\n");
|
210 |
fprintf(fout, "#created by "POTRACE" "VERSION", written by Peter Selinger 2001-2007\n"); |
211 |
fprintf(fout, "Portrait\n");
|
212 |
fprintf(fout, "Center\n");
|
213 |
fprintf(fout, "Inches\n");
|
214 |
fprintf(fout, "%s\n", formatname);
|
215 |
fprintf(fout, "100.0\n");
|
216 |
fprintf(fout, "Single\n");
|
217 |
fprintf(fout, "-2\n");
|
218 |
fprintf(fout, "1200 2\n"); /* 1200 pixels per inch */ |
219 |
fprintf(fout, "0 32 #%06x\n", info.color);
|
220 |
fprintf(fout, "0 33 #%06x\n", info.fillcolor);
|
221 |
fprintf(fout, "6 %d %d %d %d\n", x0-75, y1-35, x1+75, y0+35); /* bounding box */ |
222 |
|
223 |
/* write paths. Note: can never use "opticurve" with this backend -
|
224 |
it just does not approximate Bezier curves closely enough. */
|
225 |
list_forall (p, plist) { |
226 |
xfig_path(fout, &p->curve, t, p->sign); |
227 |
} |
228 |
|
229 |
fprintf(fout, "-6\n"); /* end bounding box */ |
230 |
|
231 |
fflush(fout); |
232 |
|
233 |
return 0; |
234 |
} |