File indexing completed on 2024-12-22 04:04:09
0001 /* Copyright (C) 2001-2019 Peter Selinger. 0002 This file is part of Potrace. It is free software and it is covered 0003 by the GNU General Public License. See the file COPYING for details. */ 0004 0005 0006 /* The xfig backend of Potrace. */ 0007 0008 #ifdef HAVE_CONFIG_H 0009 #include <config.h> 0010 #endif 0011 0012 #include <stdio.h> 0013 #include <stdarg.h> 0014 #include <string.h> 0015 #include <math.h> 0016 0017 #include "main.h" 0018 #include "backend_xfig.h" 0019 #include "potracelib.h" 0020 #include "lists.h" 0021 #include "auxiliary.h" 0022 #include "trans.h" 0023 0024 #ifndef M_PI 0025 #define M_PI 3.14159265358979323846 0026 #endif 0027 0028 struct pageformat_s { 0029 const char *name; 0030 int w, h; 0031 }; 0032 typedef struct pageformat_s pageformat_t; 0033 0034 /* page formats known by xfig, and their dimensions in postscript points */ 0035 static pageformat_t pageformat[] = { 0036 { "A9", 105, 149 }, 0037 { "A8", 149, 211 }, 0038 { "A7", 211, 298 }, 0039 { "A6", 298, 421 }, 0040 { "A5", 421, 595 }, 0041 { "A4", 595, 842 }, 0042 { "A3", 842, 1191 }, 0043 { "A2", 1191, 1685 }, 0044 { "A1", 1685, 2383 }, 0045 { "A0", 2383, 3370 }, 0046 0047 { "B10", 91, 129 }, 0048 { "B9", 129, 182 }, 0049 { "B8", 182, 258 }, 0050 { "B7", 258, 365 }, 0051 { "B6", 365, 516 }, 0052 { "B5", 516, 730 }, 0053 { "B4", 730, 1032 }, 0054 { "B3", 1032, 1460 }, 0055 { "B2", 1460, 2064 }, 0056 { "B1", 2064, 2920 }, 0057 { "B0", 2920, 4127 }, 0058 0059 { "Letter", 612, 792 }, 0060 { "Legal", 612, 1008 }, 0061 { "Tabloid", 792, 1224 }, 0062 { "A", 612, 792 }, 0063 { "B", 792, 1224 }, 0064 { "C", 1224, 1584 }, 0065 { "D", 1584, 2448 }, 0066 { "E", 2448, 3168 }, 0067 0068 { NULL, 0, 0 }, 0069 }; 0070 0071 /* ---------------------------------------------------------------------- */ 0072 /* path-drawing auxiliary functions */ 0073 0074 /* coordinate quantization */ 0075 static inline point_t unit(dpoint_t p) { 0076 point_t q; 0077 0078 q.x = (long)(floor(p.x+.5)); 0079 q.y = (long)(floor(p.y+.5)); 0080 return q; 0081 } 0082 0083 static void xfig_point(FILE *fout, dpoint_t p, trans_t t) { 0084 point_t q; 0085 0086 q = unit(trans(p, t)); 0087 0088 fprintf(fout, "%ld %ld\n", q.x, q.y); 0089 } 0090 0091 /* ---------------------------------------------------------------------- */ 0092 /* functions for converting a path to a xfig */ 0093 0094 /* calculate number of xfig control points in this path */ 0095 static int npoints(potrace_curve_t *curve, int m) { 0096 int i; 0097 int n=0; 0098 0099 for (i=0; i<m; i++) { 0100 switch (curve->tag[i]) { 0101 case POTRACE_CORNER: 0102 n += 1; 0103 break; 0104 case POTRACE_CURVETO: 0105 n += 2; 0106 break; 0107 } 0108 } 0109 return n; 0110 } 0111 0112 /* do one path. */ 0113 static void xfig_path(FILE *fout, potrace_curve_t *curve, trans_t t, int sign, int depth) { 0114 int i; 0115 dpoint_t *c; 0116 int m = curve->n; 0117 0118 fprintf(fout, "3 1 0 0 0 %d %d 0 20 0.000 0 0 0 %d\n", sign=='+' ? 32 : 33, depth, npoints(curve, m)); 0119 0120 for (i=0; i<m; i++) { 0121 c = curve->c[i]; 0122 switch (curve->tag[i]) { 0123 case POTRACE_CORNER: 0124 xfig_point(fout, c[1], t); 0125 break; 0126 case POTRACE_CURVETO: 0127 xfig_point(fout, c[0], t); 0128 xfig_point(fout, c[1], t); 0129 break; 0130 } 0131 } 0132 for (i=0; i<m; i++) { 0133 switch (curve->tag[i]) { 0134 case POTRACE_CORNER: 0135 fprintf(fout, "0\n"); 0136 break; 0137 case POTRACE_CURVETO: 0138 fprintf(fout, "1 1\n"); 0139 break; 0140 } 0141 } 0142 } 0143 0144 /* render a whole tree */ 0145 static void xfig_write_paths(FILE *fout, potrace_path_t *plist, trans_t t, int depth) { 0146 potrace_path_t *p, *q; 0147 0148 for (p=plist; p; p=p->sibling) { 0149 xfig_path(fout, &p->curve, t, p->sign, depth); 0150 for (q=p->childlist; q; q=q->sibling) { 0151 xfig_path(fout, &q->curve, t, q->sign, depth >= 1 ? depth-1 : 0); 0152 } 0153 for (q=p->childlist; q; q=q->sibling) { 0154 xfig_write_paths(fout, q->childlist, t, depth >= 2 ? depth-2 : 0); 0155 } 0156 } 0157 } 0158 0159 /* calculate the depth of a tree. Call with d=0. */ 0160 static int xfig_get_depth(potrace_path_t *plist) { 0161 potrace_path_t *p; 0162 int max =0; 0163 int d; 0164 0165 for (p=plist; p; p=p->sibling) { 0166 d = xfig_get_depth(p->childlist); 0167 if (d > max) { 0168 max = d; 0169 } 0170 } 0171 return max + 1; 0172 } 0173 0174 /* ---------------------------------------------------------------------- */ 0175 /* Backend. */ 0176 0177 /* public interface for XFIG */ 0178 int page_xfig(FILE *fout, potrace_path_t *plist, imginfo_t *imginfo) { 0179 trans_t t; 0180 double origx = imginfo->trans.orig[0] + imginfo->lmar; 0181 double origy = - imginfo->trans.orig[1] - imginfo->bmar + info.paperheight; 0182 const char *formatname; 0183 int best, penalty; 0184 pageformat_t *f; 0185 int i; 0186 int x0, y0, x1, y1; /* in xfig's coordinates */ 0187 int depth; 0188 0189 t.orig[0] = 1200/72.0 * origx; 0190 t.orig[1] = 1200/72.0 * origy; 0191 t.x[0] = 1200/72.0 * imginfo->trans.x[0]; 0192 t.x[1] = -1200/72.0 * imginfo->trans.x[1]; 0193 t.y[0] = 1200/72.0 * imginfo->trans.y[0]; 0194 t.y[1] = -1200/72.0 * imginfo->trans.y[1]; 0195 0196 x0 = (int)(1200/72.0 * (origx - imginfo->trans.orig[0])); 0197 y0 = (int)(1200/72.0 * (origy + imginfo->trans.orig[1])); 0198 x1 = x0 + (int)(1200/72.0 * imginfo->trans.bb[0]); 0199 y1 = y0 - (int)(1200/72.0 * imginfo->trans.bb[1]); 0200 0201 best = -1; 0202 formatname = "Letter"; 0203 0204 /* find closest page format */ 0205 for (i=0; pageformat[i].name; i++) { 0206 f = &pageformat[i]; 0207 if (f->w >= info.paperwidth-1 && f->h >= info.paperheight-1) { 0208 penalty = f->w + f->h; 0209 if (best == -1 || penalty < best) { 0210 best = penalty; 0211 formatname = f->name; 0212 } 0213 } 0214 } 0215 0216 /* header */ 0217 fprintf(fout, "#FIG 3.2\n"); 0218 fprintf(fout, "#created by " POTRACE " " VERSION ", written by Peter Selinger 2001-2019\n"); 0219 fprintf(fout, "Portrait\n"); 0220 fprintf(fout, "Center\n"); 0221 fprintf(fout, "Inches\n"); 0222 fprintf(fout, "%s\n", formatname); 0223 fprintf(fout, "100.0\n"); 0224 fprintf(fout, "Single\n"); 0225 fprintf(fout, "-2\n"); 0226 fprintf(fout, "1200 2\n"); /* 1200 pixels per inch */ 0227 fprintf(fout, "0 32 #%06x\n", info.color); 0228 fprintf(fout, "0 33 #%06x\n", info.fillcolor); 0229 fprintf(fout, "6 %d %d %d %d\n", x0-75, y1-35, x1+75, y0+35); /* bounding box */ 0230 0231 /* determine depth of the tree */ 0232 depth = xfig_get_depth(plist); 0233 0234 /* figure out appropriate xfig starting depth. Note: xfig only has 1000 depths available */ 0235 if (depth <= 40) { 0236 depth = 50; 0237 } else if (depth < 990) { 0238 depth += 10; 0239 } else { 0240 depth = 999; 0241 } 0242 0243 /* write paths. Note: can never use "opticurve" with this backend - 0244 it just does not approximate Bezier curves closely enough. */ 0245 xfig_write_paths(fout, plist, t, depth); 0246 0247 fprintf(fout, "-6\n"); /* end bounding box */ 0248 0249 fflush(fout); 0250 0251 return 0; 0252 }