| 1 | /* |
|---|
| 2 | * TransFig: Facility for Translating Fig code |
|---|
| 3 | * Copyright (c) 1985 Supoj Sutantavibul |
|---|
| 4 | * Copyright (c) 1991 Micah Beck |
|---|
| 5 | * |
|---|
| 6 | * Permission to use, copy, modify, distribute, and sell this software and its |
|---|
| 7 | * documentation for any purpose is hereby granted without fee, provided that |
|---|
| 8 | * the above copyright notice appear in all copies and that both that |
|---|
| 9 | * copyright notice and this permission notice appear in supporting |
|---|
| 10 | * documentation. The authors make no representations about the suitability |
|---|
| 11 | * of this software for any purpose. It is provided "as is" without express |
|---|
| 12 | * or implied warranty. |
|---|
| 13 | * |
|---|
| 14 | * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, |
|---|
| 15 | * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO |
|---|
| 16 | * EVENT SHALL THE AUTHORS BE LIABLE FOR ANY SPECIAL, INDIRECT OR |
|---|
| 17 | * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, |
|---|
| 18 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER |
|---|
| 19 | * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR |
|---|
| 20 | * PERFORMANCE OF THIS SOFTWARE. |
|---|
| 21 | * |
|---|
| 22 | */ |
|---|
| 23 | |
|---|
| 24 | /* |
|---|
| 25 | * genlatex.c : LaTeX driver for fig2dev |
|---|
| 26 | * |
|---|
| 27 | * Author: Frank Schmuck, Cornell University 6/88 |
|---|
| 28 | * Converted from fig2latex 5/89 by Micah Beck |
|---|
| 29 | * Color, rotated text and ISO-chars added by Herbert Bauer 11/91 |
|---|
| 30 | * |
|---|
| 31 | */ |
|---|
| 32 | #if defined(hpux) || defined(SYSV) |
|---|
| 33 | #include <sys/types.h> |
|---|
| 34 | #endif |
|---|
| 35 | #include <sys/file.h> |
|---|
| 36 | #include <stdio.h> |
|---|
| 37 | #include <math.h> |
|---|
| 38 | #include "object.h" |
|---|
| 39 | #include "fig2dev.h" |
|---|
| 40 | #include "texfonts.h" |
|---|
| 41 | #include "pi.h" |
|---|
| 42 | |
|---|
| 43 | #ifndef fabs |
|---|
| 44 | extern double fabs(); |
|---|
| 45 | #endif |
|---|
| 46 | #ifndef sin |
|---|
| 47 | extern double sin(); |
|---|
| 48 | #endif |
|---|
| 49 | #ifndef cos |
|---|
| 50 | extern double cos(); |
|---|
| 51 | #endif |
|---|
| 52 | #ifndef acos |
|---|
| 53 | extern double acos(); |
|---|
| 54 | #endif |
|---|
| 55 | #ifndef atan |
|---|
| 56 | extern double atan(); |
|---|
| 57 | #endif |
|---|
| 58 | extern double rad2deg; |
|---|
| 59 | extern void unpsfont(); |
|---|
| 60 | |
|---|
| 61 | #define rint(a) floor((a)+0.5) /* close enough? */ |
|---|
| 62 | |
|---|
| 63 | /* |
|---|
| 64 | * Installation dependent constants: |
|---|
| 65 | * |
|---|
| 66 | * THINDOT latex command for generating a dot if line width = \thinlines |
|---|
| 67 | * THICKDOT latex command for generating a dot if line width = \thicklines |
|---|
| 68 | * MIN_LEN shortest slanted line that latex can produce; shorter lines will |
|---|
| 69 | * we translated into a sequence of dots generated by \multiput. |
|---|
| 70 | * THICK_LDOT latex command for generating the dot for making short slanted |
|---|
| 71 | * lines if line width = \thinlines |
|---|
| 72 | * THIN_LDOT ... if line width = \thicklines |
|---|
| 73 | */ |
|---|
| 74 | #define THICKDOT "\\SetFigFont{10}{12}{rm}." |
|---|
| 75 | #define THINDOT "\\SetFigFont{7}{8.4}{rm}." |
|---|
| 76 | double THIN_XOFF = (0.1/72.0); |
|---|
| 77 | double THIN_YOFF = (0.7/72.0); |
|---|
| 78 | double THICK_XOFF = (0.4/72.0); |
|---|
| 79 | double THICK_YOFF = (0.6/72.0); |
|---|
| 80 | #define THICK_LDOT "\\SetFigFont{7}{8.4}{rm}." |
|---|
| 81 | #define THIN_LDOT "\\SetFigFont{5}{6}{rm}." |
|---|
| 82 | double THIN_LXOFF = (0.1/72.0); |
|---|
| 83 | double THIN_LYOFF = (0.7/72.0); |
|---|
| 84 | double THICK_LXOFF = (0.4/72.0); |
|---|
| 85 | double THICK_LYOFF = (0.6/72.0); |
|---|
| 86 | #define MIN_LEN (13.0/72.0) /* 13 points */ |
|---|
| 87 | |
|---|
| 88 | /* |
|---|
| 89 | * other constants and macros |
|---|
| 90 | */ |
|---|
| 91 | #define TOP 840 |
|---|
| 92 | #define THINLINES 1 |
|---|
| 93 | #define THICKLINES 2 |
|---|
| 94 | |
|---|
| 95 | #define MAXCIRCLEDIA 80 |
|---|
| 96 | #define MAXCIRCLERAD ((MAXCIRCLEDIA-0.5)/(2*72.27)) |
|---|
| 97 | |
|---|
| 98 | #define SWAP(x,y) {tmp=x; x=y; y=tmp;} |
|---|
| 99 | #define TRANS(x,y) (*translate_coordinates)(&x,&y) |
|---|
| 100 | #define TRANS2(x1,y1,x2,y2) (*translate_coordinates)(&x1,&y1); \ |
|---|
| 101 | (*translate_coordinates)(&x2,&y2) |
|---|
| 102 | #define TRANSD(x,y) (*translate_coordinates_d)(&x,&y) |
|---|
| 103 | #ifndef MIN |
|---|
| 104 | #define MIN(x,y) (((x) <= (y))? (x): (y)) |
|---|
| 105 | #endif |
|---|
| 106 | #ifndef MAX |
|---|
| 107 | #define MAX(x,y) (((x) >= (y))? (x): (y)) |
|---|
| 108 | #endif |
|---|
| 109 | #define ABS(x) (((x) >= 0)? (x): -(x)) |
|---|
| 110 | #define round4(x) ((round(10000.0*(x))/10000.0)) |
|---|
| 111 | #define round6(x) ((round(1000000.0*(x))/1000000.0)) |
|---|
| 112 | |
|---|
| 113 | char thindot [] = THINDOT; |
|---|
| 114 | char thickdot[] = THICKDOT; |
|---|
| 115 | char thin_ldot [] = THIN_LDOT; |
|---|
| 116 | char thick_ldot[] = THICK_LDOT; |
|---|
| 117 | |
|---|
| 118 | static int coord_system; |
|---|
| 119 | int verbose = 0; |
|---|
| 120 | double dash_mag = 1.0; |
|---|
| 121 | int thick_width = 2; |
|---|
| 122 | double tolerance = 2.0; |
|---|
| 123 | double arc_tolerance = 1.0; |
|---|
| 124 | int (*translate_coordinates)() = NULL; |
|---|
| 125 | int (*translate_coordinates_d)() = NULL; |
|---|
| 126 | double unitlength; |
|---|
| 127 | static int cur_thickness = -1; |
|---|
| 128 | double ldot_diameter = 1.0/72.0; |
|---|
| 129 | char *dot_cmd = thindot; |
|---|
| 130 | char *ldot_cmd = thin_ldot; |
|---|
| 131 | double dot_xoffset; |
|---|
| 132 | double dot_yoffset; |
|---|
| 133 | double ldot_xoffset; |
|---|
| 134 | double ldot_yoffset; |
|---|
| 135 | |
|---|
| 136 | extern char *ISOtoTeX[]; |
|---|
| 137 | |
|---|
| 138 | static translate1(xp, yp) |
|---|
| 139 | int *xp, *yp; |
|---|
| 140 | { |
|---|
| 141 | *xp = *xp + 1; |
|---|
| 142 | *yp = *yp + 1; |
|---|
| 143 | } |
|---|
| 144 | |
|---|
| 145 | static translate2(xp, yp) |
|---|
| 146 | int *xp, *yp; |
|---|
| 147 | { |
|---|
| 148 | *xp = *xp + 1; |
|---|
| 149 | *yp = TOP - *yp -1; |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | static translate1_d(xp, yp) |
|---|
| 153 | double *xp, *yp; |
|---|
| 154 | { |
|---|
| 155 | *xp = *xp + 1.0; |
|---|
| 156 | *yp = *yp + 1.0; |
|---|
| 157 | } |
|---|
| 158 | |
|---|
| 159 | static translate2_d(xp, yp) |
|---|
| 160 | double *xp, *yp; |
|---|
| 161 | { |
|---|
| 162 | *xp = *xp + 1.0; |
|---|
| 163 | *yp = (double)TOP - *yp -1.0; |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | void genlatex_option(opt, optarg) |
|---|
| 167 | char opt, *optarg; |
|---|
| 168 | { |
|---|
| 169 | int i; |
|---|
| 170 | |
|---|
| 171 | switch (opt) { |
|---|
| 172 | case 'a': |
|---|
| 173 | fprintf(stderr, "warning: latex option -a obsolete"); |
|---|
| 174 | break; |
|---|
| 175 | |
|---|
| 176 | case 'd': |
|---|
| 177 | dash_mag = atof(optarg); /* set dash magnification */ |
|---|
| 178 | break; |
|---|
| 179 | |
|---|
| 180 | |
|---|
| 181 | case 'f': /* set default text font */ |
|---|
| 182 | for ( i = 1; i <= MAX_FONT; i++ ) |
|---|
| 183 | if ( !strcmp(optarg, texfontnames[i]) ) break; |
|---|
| 184 | |
|---|
| 185 | if ( i > MAX_FONT) |
|---|
| 186 | fprintf(stderr, |
|---|
| 187 | "warning: non-standard font name %s\n", optarg); |
|---|
| 188 | |
|---|
| 189 | texfontnames[0] = texfontnames[1] = optarg; |
|---|
| 190 | break; |
|---|
| 191 | |
|---|
| 192 | case 'l': /* set thin/thick line threshold */ |
|---|
| 193 | thick_width = atoi(optarg); |
|---|
| 194 | break; |
|---|
| 195 | |
|---|
| 196 | case 's': |
|---|
| 197 | if (font_size <= 0 || font_size > MAXFONTSIZE) { |
|---|
| 198 | fprintf(stderr, |
|---|
| 199 | "warning: font size %d out of bounds\n", font_size); |
|---|
| 200 | } |
|---|
| 201 | break; |
|---|
| 202 | |
|---|
| 203 | case 'v': |
|---|
| 204 | verbose = 1; /* verbose mode */ |
|---|
| 205 | break; |
|---|
| 206 | |
|---|
| 207 | case 'm': |
|---|
| 208 | case 'L': |
|---|
| 209 | break; |
|---|
| 210 | |
|---|
| 211 | default: |
|---|
| 212 | put_msg(Err_badarg, opt, "latex"); |
|---|
| 213 | exit(1); |
|---|
| 214 | break; |
|---|
| 215 | } |
|---|
| 216 | } |
|---|
| 217 | |
|---|
| 218 | void genlatex_start(objects) |
|---|
| 219 | F_compound *objects; |
|---|
| 220 | { |
|---|
| 221 | int tmp; |
|---|
| 222 | |
|---|
| 223 | texfontsizes[0] = texfontsizes[1] = TEXFONTSIZE(font_size); |
|---|
| 224 | |
|---|
| 225 | coord_system = objects->nwcorner.y; |
|---|
| 226 | unitlength = mag/objects->nwcorner.x; |
|---|
| 227 | |
|---|
| 228 | switch (coord_system) { |
|---|
| 229 | case 1: |
|---|
| 230 | translate_coordinates = translate1; |
|---|
| 231 | translate_coordinates_d = translate1_d; |
|---|
| 232 | break; |
|---|
| 233 | case 2: |
|---|
| 234 | translate_coordinates = translate2; |
|---|
| 235 | translate_coordinates_d = translate2_d; |
|---|
| 236 | break; |
|---|
| 237 | default: |
|---|
| 238 | fprintf(stderr, "Wrong coordinate system; cannot continue\n"); |
|---|
| 239 | return; |
|---|
| 240 | } |
|---|
| 241 | |
|---|
| 242 | TRANS2(llx, lly, urx, ury); |
|---|
| 243 | if (llx > urx) SWAP(llx, urx) |
|---|
| 244 | if (lly > ury) SWAP(lly, ury) |
|---|
| 245 | |
|---|
| 246 | /* LaTeX start */ |
|---|
| 247 | fprintf(tfp, "\\setlength{\\unitlength}{%.6fin}%%\n", |
|---|
| 248 | round6(unitlength)); |
|---|
| 249 | /* define the SetFigFont macro */ |
|---|
| 250 | define_setfigfont(tfp); |
|---|
| 251 | fprintf(tfp, "\\begin{picture}(%d,%d)(%d,%d)\n", |
|---|
| 252 | urx-llx, ury-lly, llx, lly); |
|---|
| 253 | } |
|---|
| 254 | |
|---|
| 255 | void genlatex_end() |
|---|
| 256 | { |
|---|
| 257 | /* LaTeX ending */ |
|---|
| 258 | fprintf(tfp, "\\end{picture}\n"); |
|---|
| 259 | } |
|---|
| 260 | |
|---|
| 261 | static set_linewidth(w) |
|---|
| 262 | int w; |
|---|
| 263 | { |
|---|
| 264 | int latex_w; |
|---|
| 265 | |
|---|
| 266 | if (w == 0) return; |
|---|
| 267 | /* latex only knows thin lines or thick lines */ |
|---|
| 268 | latex_w = (w >= thick_width)? THICKLINES: THINLINES; |
|---|
| 269 | if (latex_w != cur_thickness) { |
|---|
| 270 | cur_thickness = latex_w; |
|---|
| 271 | if (cur_thickness == THICKLINES) { |
|---|
| 272 | fprintf(tfp, "\\thicklines\n"); |
|---|
| 273 | dot_cmd = thickdot; |
|---|
| 274 | dot_xoffset = round4(THICK_XOFF/unitlength); |
|---|
| 275 | dot_yoffset = round4(THICK_YOFF/unitlength); |
|---|
| 276 | ldot_cmd = thick_ldot; |
|---|
| 277 | ldot_xoffset = round4(THICK_LXOFF/unitlength); |
|---|
| 278 | ldot_yoffset = round4(THICK_LYOFF/unitlength); |
|---|
| 279 | } |
|---|
| 280 | else { |
|---|
| 281 | fprintf(tfp, "\\thinlines\n"); |
|---|
| 282 | dot_cmd = thin_ldot; |
|---|
| 283 | dot_xoffset = round4(THIN_XOFF/unitlength); |
|---|
| 284 | dot_yoffset = round4(THIN_YOFF/unitlength); |
|---|
| 285 | ldot_cmd = thin_ldot; |
|---|
| 286 | ldot_xoffset = round4(THIN_LXOFF/unitlength); |
|---|
| 287 | ldot_yoffset = round4(THIN_LYOFF/unitlength); |
|---|
| 288 | } |
|---|
| 289 | } |
|---|
| 290 | } |
|---|
| 291 | |
|---|
| 292 | void genlatex_line(l) |
|---|
| 293 | F_line *l; |
|---|
| 294 | { |
|---|
| 295 | F_point *p, *q; |
|---|
| 296 | int x, y, llx, lly, urx, ury, arrow; |
|---|
| 297 | |
|---|
| 298 | if (verbose) fprintf(tfp, "%%\n%% Fig POLYLINE object\n%%\n"); |
|---|
| 299 | |
|---|
| 300 | set_linewidth(l->thickness); |
|---|
| 301 | set_color(l->color); |
|---|
| 302 | |
|---|
| 303 | p = l->points; |
|---|
| 304 | q = p->next; |
|---|
| 305 | |
|---|
| 306 | if (q == NULL) { /* A single point line */ |
|---|
| 307 | x = p->x; y = p->y; |
|---|
| 308 | TRANS(x, y); |
|---|
| 309 | fprintf(tfp, "\\put(%3d,%3d){\\makebox(%.4f,%.4f){%s}}\n", |
|---|
| 310 | x, y, dot_xoffset, dot_yoffset, dot_cmd); |
|---|
| 311 | return; |
|---|
| 312 | } |
|---|
| 313 | |
|---|
| 314 | if (l->type == T_ARC_BOX) { /* A box with rounded corners */ |
|---|
| 315 | fprintf(stderr, "Arc box not implemented; substituting box.\n"); |
|---|
| 316 | l->type = T_BOX; |
|---|
| 317 | } |
|---|
| 318 | |
|---|
| 319 | if (l->type == T_BOX) { /* A box */ |
|---|
| 320 | x = p->x; y = p->y; |
|---|
| 321 | TRANS(x, y); |
|---|
| 322 | llx = urx = x; |
|---|
| 323 | lly = ury = y; |
|---|
| 324 | while (q != NULL) { |
|---|
| 325 | x = q->x; y = q->y; |
|---|
| 326 | TRANS(x, y); |
|---|
| 327 | if (x < llx) llx = x; |
|---|
| 328 | if (y < lly) lly = y; |
|---|
| 329 | if (x > urx) urx = x; |
|---|
| 330 | if (y > ury) ury = y; |
|---|
| 331 | q = q->next; |
|---|
| 332 | } |
|---|
| 333 | put_box (llx, lly, urx, ury, l->style, l->style_val); |
|---|
| 334 | return; |
|---|
| 335 | } |
|---|
| 336 | |
|---|
| 337 | while (q != NULL) { |
|---|
| 338 | arrow = 0; |
|---|
| 339 | if (l->for_arrow && q->next == NULL) |
|---|
| 340 | arrow = 1; |
|---|
| 341 | if (l->back_arrow && p == l->points) |
|---|
| 342 | arrow = (arrow)? 2: -1; |
|---|
| 343 | single_line(p->x, p->y, q->x, q->y, arrow, l->style, l->style_val); |
|---|
| 344 | p = q; |
|---|
| 345 | q = q->next; |
|---|
| 346 | } |
|---|
| 347 | |
|---|
| 348 | if (l->area_fill && (int)l->area_fill != DEFAULT) |
|---|
| 349 | fprintf(stderr, "Line area fill not implemented\n"); |
|---|
| 350 | reset_color(l->color); |
|---|
| 351 | } |
|---|
| 352 | |
|---|
| 353 | static single_line (x1, y1, x2, y2, arrow, style, val) |
|---|
| 354 | int x1, y1, x2, y2, arrow, style; |
|---|
| 355 | double val; |
|---|
| 356 | { |
|---|
| 357 | int dx, dy, sx, sy; |
|---|
| 358 | double l, m, deviation; |
|---|
| 359 | |
|---|
| 360 | TRANS2(x1, y1, x2, y2); |
|---|
| 361 | dx = x2-x1; |
|---|
| 362 | dy = y2-y1; |
|---|
| 363 | /*** compute direction vector ***/ |
|---|
| 364 | get_slope(dx, dy, &sx, &sy, arrow); |
|---|
| 365 | /*** compute line length in x-direction ***/ |
|---|
| 366 | if (sx == 0) { |
|---|
| 367 | l = (double)abs(dy); |
|---|
| 368 | } else { |
|---|
| 369 | m = (double)abs(sy) / (double)abs(sx); |
|---|
| 370 | l = ((double)abs(dx) + m*(double)abs(dy)) / (1.0 + m*m); |
|---|
| 371 | deviation = fabs(l-abs(dx)) + fabs(m*l-abs(dy)); |
|---|
| 372 | if (deviation > tolerance) |
|---|
| 373 | fprintf(stderr, |
|---|
| 374 | "Not a LaTeX slope (%d, %d), deviation %.1f pixels\n", |
|---|
| 375 | dx, dy, deviation); |
|---|
| 376 | } |
|---|
| 377 | l = round4(l); |
|---|
| 378 | /*** output letex command ***/ |
|---|
| 379 | switch (style) { |
|---|
| 380 | case SOLID_LINE: |
|---|
| 381 | put_solidline(x1, y1, sx, sy, l, arrow); |
|---|
| 382 | break; |
|---|
| 383 | case DASH_LINE: |
|---|
| 384 | put_dashline(x1, y1, sx, sy, l, arrow, val); |
|---|
| 385 | break; |
|---|
| 386 | case DOTTED_LINE: |
|---|
| 387 | put_dotline(x1, y1, sx, sy, l, arrow, val); |
|---|
| 388 | break; |
|---|
| 389 | } |
|---|
| 390 | } |
|---|
| 391 | |
|---|
| 392 | |
|---|
| 393 | /* |
|---|
| 394 | * draw box |
|---|
| 395 | */ |
|---|
| 396 | static put_box (llx, lly, urx, ury, style, val) |
|---|
| 397 | int llx, lly, urx, ury, style; |
|---|
| 398 | double val; |
|---|
| 399 | { |
|---|
| 400 | int dlen; |
|---|
| 401 | |
|---|
| 402 | switch (style) { |
|---|
| 403 | case SOLID_LINE: |
|---|
| 404 | fprintf(tfp, "\\put(%3d,%3d){\\framebox(%d,%d){}}\n", |
|---|
| 405 | llx, lly, urx-llx, ury-lly); |
|---|
| 406 | break; |
|---|
| 407 | case DASH_LINE: |
|---|
| 408 | dlen = round(val*dash_mag); |
|---|
| 409 | fprintf(tfp, "\\put(%3d,%3d){\\dashbox{%d}(%d,%d){}}\n", |
|---|
| 410 | llx, lly, dlen, urx-llx, ury-lly); |
|---|
| 411 | break; |
|---|
| 412 | case DOTTED_LINE: |
|---|
| 413 | put_dotline (llx, lly, 1, 0, (double)(urx-llx), 0, val); |
|---|
| 414 | put_dotline (llx, ury, 1, 0, (double)(urx-llx), 0, val); |
|---|
| 415 | put_dotline (llx, lly, 0, 1, (double)(ury-lly), 0, val); |
|---|
| 416 | put_dotline (urx, lly, 0, 1, (double)(ury-lly), 0, val); |
|---|
| 417 | break; |
|---|
| 418 | } |
|---|
| 419 | return; |
|---|
| 420 | } |
|---|
| 421 | |
|---|
| 422 | /* |
|---|
| 423 | * draw a solid line given latex slope |
|---|
| 424 | */ |
|---|
| 425 | static put_solidline (x, y, sx, sy, l, arrow) |
|---|
| 426 | int x, y, sx, sy, arrow; |
|---|
| 427 | double l; |
|---|
| 428 | { |
|---|
| 429 | double cosine; /* cosine of line angle */ |
|---|
| 430 | double dx, dy; |
|---|
| 431 | int x2, y2, n; |
|---|
| 432 | |
|---|
| 433 | if (sx) { |
|---|
| 434 | cosine = (double)abs(sx) / sqrt((double)(sx*sx)+(double)(sy*sy)); |
|---|
| 435 | x2 = (sx >= 0)? x + round(l): x - round(l); |
|---|
| 436 | y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx); |
|---|
| 437 | } |
|---|
| 438 | else { |
|---|
| 439 | cosine = 1.0; |
|---|
| 440 | x2 = x; |
|---|
| 441 | y2 = (sy >= 0)? y + round(l): y - round(l); |
|---|
| 442 | } |
|---|
| 443 | if (sx == 0 || sy == 0 || (l/cosine)*unitlength >= MIN_LEN) { |
|---|
| 444 | switch (arrow) { |
|---|
| 445 | case 0: /* simple line */ |
|---|
| 446 | fprintf(tfp, "\\put(%3d,%3d){\\line(%2d,%2d)", x, y, sx,sy); |
|---|
| 447 | break; |
|---|
| 448 | case 1: /* forward arrow */ |
|---|
| 449 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx,sy); |
|---|
| 450 | break; |
|---|
| 451 | case -1: /* backward arrow */ |
|---|
| 452 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x2, y2, -sx,-sy); |
|---|
| 453 | break; |
|---|
| 454 | case 2: /* double arrow */ |
|---|
| 455 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){ 0}}\n", x,y,-sx,-sy); |
|---|
| 456 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d)", x, y, sx, sy); |
|---|
| 457 | break; |
|---|
| 458 | } |
|---|
| 459 | if (l == floor(l)) |
|---|
| 460 | fprintf(tfp, "{%3.0f}}\n", l); |
|---|
| 461 | else |
|---|
| 462 | fprintf(tfp, "{%7.3f}}\n", l); |
|---|
| 463 | } |
|---|
| 464 | else { |
|---|
| 465 | n = 2 * (l/cosine) / (ldot_diameter/unitlength); |
|---|
| 466 | fprintf(stderr, "Line too short; will do %d dots\n", n); |
|---|
| 467 | dx = l / (double)n; |
|---|
| 468 | if (sx < 0) dx = -dx; |
|---|
| 469 | dy = dx * (double)sy / (double)sx; |
|---|
| 470 | fprintf(tfp, |
|---|
| 471 | "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\makebox(%.4f,%.4f){%s}}\n", |
|---|
| 472 | x, y, dx, dy, n+1, ldot_xoffset, ldot_yoffset, ldot_cmd); |
|---|
| 473 | if (arrow == 1 || arrow == 2) /* forward arrow */ |
|---|
| 474 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2,y2, sx,sy); |
|---|
| 475 | if (arrow == -1 || arrow == 2) /* backward arrow */ |
|---|
| 476 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x,y, -sx,-sy); |
|---|
| 477 | } |
|---|
| 478 | } |
|---|
| 479 | |
|---|
| 480 | /* |
|---|
| 481 | * draw a dashed line given latex slope |
|---|
| 482 | */ |
|---|
| 483 | static put_dashline (x, y, sx, sy, l, arrow, val) |
|---|
| 484 | int x, y, sx, sy, arrow; |
|---|
| 485 | double l; |
|---|
| 486 | double val; |
|---|
| 487 | { |
|---|
| 488 | double cosine; /* cosine of line angle */ |
|---|
| 489 | double nd; /* number of dashes and gaps fitting on line */ |
|---|
| 490 | int n; /* nd rounded to the nearest odd integer */ |
|---|
| 491 | double dl; /* actual x-length of each dash */ |
|---|
| 492 | double dg; /* actual x-length of each gap */ |
|---|
| 493 | double dx, dy; /* step between dashes */ |
|---|
| 494 | int x2, y2; |
|---|
| 495 | |
|---|
| 496 | if (sx) { |
|---|
| 497 | cosine = (double)abs(sx) / sqrt((double)(sx*sx)+(double)(sy*sy)); |
|---|
| 498 | x2 = (sx >= 0)? x + round(l): x - round(l); |
|---|
| 499 | y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx ); |
|---|
| 500 | } |
|---|
| 501 | else { |
|---|
| 502 | cosine = 1.0; |
|---|
| 503 | x2 = x; |
|---|
| 504 | y2 = (sy >= 0)? y + round(l): y - round(l); |
|---|
| 505 | } |
|---|
| 506 | /*** compute number of dashes, length of dashes and gaps ***/ |
|---|
| 507 | nd = l / (val*dash_mag*cosine); |
|---|
| 508 | n = (int) (rint((nd + 1.0)/2.0)*2 - 1); |
|---|
| 509 | dl = l / (double)n; |
|---|
| 510 | if (sx && sy && (dl/cosine)*unitlength < MIN_LEN) { |
|---|
| 511 | fprintf(stderr, "Dash too small; using larger dash\n"); |
|---|
| 512 | dl = MIN_LEN/unitlength * cosine; |
|---|
| 513 | nd = l / dl; |
|---|
| 514 | n = (int) (rint((nd + 1.0)/2.0)*2 - 1); |
|---|
| 515 | } |
|---|
| 516 | if (2*dl >= l || (sx && sy && (l/cosine)*unitlength < MIN_LEN)) { |
|---|
| 517 | fprintf(stderr, "Dashed line too short; drawing solid line\n"); |
|---|
| 518 | put_solidline (x, y, sx, sy, l, arrow); |
|---|
| 519 | return; |
|---|
| 520 | } |
|---|
| 521 | dg = (l - (n/2+1)*dl) / (double)(n/2); |
|---|
| 522 | if (sx) { |
|---|
| 523 | dx = dl+dg; |
|---|
| 524 | if (sx < 0) dx = -dx; |
|---|
| 525 | dy = dx * (double)sy / (double)sx; |
|---|
| 526 | } |
|---|
| 527 | else { |
|---|
| 528 | dx = 0.0; |
|---|
| 529 | dy = dl+dg; |
|---|
| 530 | if (sy < 0) dy = -dy; |
|---|
| 531 | } |
|---|
| 532 | /*** draw dashed line ***/ |
|---|
| 533 | fprintf(tfp, "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\line(%2d,%2d){%7.3f}}\n", |
|---|
| 534 | x, y, dx, dy, n/2+1, sx, sy, dl); |
|---|
| 535 | /*** draw arrow heads ***/ |
|---|
| 536 | if (arrow == 1 || arrow == 2) |
|---|
| 537 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy); |
|---|
| 538 | if (arrow == -1 || arrow == 2) |
|---|
| 539 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy); |
|---|
| 540 | } |
|---|
| 541 | |
|---|
| 542 | /* |
|---|
| 543 | * draw a dotted line given latex slope |
|---|
| 544 | */ |
|---|
| 545 | static put_dotline (x, y, sx, sy, l, arrow, val) |
|---|
| 546 | int x, y, sx, sy, arrow; |
|---|
| 547 | double l; |
|---|
| 548 | double val; |
|---|
| 549 | { |
|---|
| 550 | double cosine; /* cosine of line angle */ |
|---|
| 551 | double nd; /* number of dots fitting on line */ |
|---|
| 552 | int n; /* nd rounded to the nearest integer */ |
|---|
| 553 | double dx, dy; /* step between dashes */ |
|---|
| 554 | int x2, y2; |
|---|
| 555 | |
|---|
| 556 | |
|---|
| 557 | cosine = (sx)? (double)abs(sx) / sqrt((double)(sx*sx)+(double)(sy*sy)): 1.0; |
|---|
| 558 | /*** compute step width ***/ |
|---|
| 559 | nd = l / (3*val*cosine); |
|---|
| 560 | n = rint(nd); |
|---|
| 561 | dx = l / (double)n; |
|---|
| 562 | if (sx) { |
|---|
| 563 | dx = l / (double)n; |
|---|
| 564 | if (sx < 0) dx = -dx; |
|---|
| 565 | dy = dx * (double)sy / (double)sx; |
|---|
| 566 | } |
|---|
| 567 | else { |
|---|
| 568 | dx = 0.0; |
|---|
| 569 | dy = l / (double)n; |
|---|
| 570 | if (sy < 0) dy = -dy; |
|---|
| 571 | } |
|---|
| 572 | /*** draw arrow heads ***/ |
|---|
| 573 | if (arrow == 1 || arrow == 2) { |
|---|
| 574 | /* forward arrow */ |
|---|
| 575 | if (sx) { |
|---|
| 576 | x2 = (sx >= 0)? x + round(l): x - round(l); |
|---|
| 577 | y2 = y + round( ((sx>=0)? l: -l) * (double)sy / (double)sx ); |
|---|
| 578 | } |
|---|
| 579 | else { |
|---|
| 580 | x2 = x; |
|---|
| 581 | y2 = (sy >= 0)? y + round(l): y - round(l); |
|---|
| 582 | } |
|---|
| 583 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x2, y2, sx, sy); |
|---|
| 584 | n--; |
|---|
| 585 | } |
|---|
| 586 | if (arrow == -1 || arrow == 2) { |
|---|
| 587 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%2d,%2d){0}}\n", x, y, -sx, -sy); |
|---|
| 588 | x = round(x + dx); |
|---|
| 589 | y = round(y + dy); |
|---|
| 590 | n--; |
|---|
| 591 | } |
|---|
| 592 | /*** draw dotted line ***/ |
|---|
| 593 | fprintf(tfp, "\\multiput(%3d,%3d)(%.5f,%.5f){%d}{\\makebox(%.4f,%.4f){%s}}\n", |
|---|
| 594 | x, y, dx, dy, n+1, dot_xoffset, dot_yoffset, dot_cmd); |
|---|
| 595 | } |
|---|
| 596 | |
|---|
| 597 | void genlatex_spline(s) |
|---|
| 598 | F_spline *s; |
|---|
| 599 | { |
|---|
| 600 | fprintf(stderr, "Can't generate spline; omitting object\n"); |
|---|
| 601 | } |
|---|
| 602 | |
|---|
| 603 | void genlatex_ellipse(e) |
|---|
| 604 | F_ellipse *e; |
|---|
| 605 | { |
|---|
| 606 | int x, y, d, dx, dy; |
|---|
| 607 | |
|---|
| 608 | if (verbose) fprintf(tfp, "%%\n%% Fig ELLIPSE\n%%\n"); |
|---|
| 609 | |
|---|
| 610 | set_linewidth(e->thickness); |
|---|
| 611 | switch (e->style) { |
|---|
| 612 | case SOLID_LINE: |
|---|
| 613 | break; |
|---|
| 614 | case DASH_LINE: |
|---|
| 615 | fprintf(stderr, "Dashed circles and elipses not supported\n"); |
|---|
| 616 | break; |
|---|
| 617 | case DOTTED_LINE: |
|---|
| 618 | fprintf(stderr, "Dotted circles and elipses not supported\n"); |
|---|
| 619 | break; |
|---|
| 620 | } |
|---|
| 621 | |
|---|
| 622 | x = e->center.x; |
|---|
| 623 | y = e->center.y; |
|---|
| 624 | TRANS(x, y); |
|---|
| 625 | if ((e->type == T_CIRCLE_BY_RAD || e->type == T_CIRCLE_BY_DIA) |
|---|
| 626 | && e->radiuses.x*unitlength <= MAXCIRCLERAD) { |
|---|
| 627 | |
|---|
| 628 | d = 2 * e->radiuses.x; |
|---|
| 629 | if (e->area_fill == BLACK_FILL) |
|---|
| 630 | fprintf(tfp, "\\put(%3d,%3d){\\circle*{%d}}\n", x, y, d); |
|---|
| 631 | else { |
|---|
| 632 | fprintf(tfp, "\\put(%3d,%3d){\\circle{%d}}\n", x, y, d); |
|---|
| 633 | if (e->area_fill && (int)e->area_fill != DEFAULT) |
|---|
| 634 | fprintf(stderr, "Circle area fill not implemented\n"); |
|---|
| 635 | } |
|---|
| 636 | |
|---|
| 637 | } else { |
|---|
| 638 | dx = 2 * e->radiuses.x; |
|---|
| 639 | dy = 2 * e->radiuses.y; |
|---|
| 640 | fprintf(tfp, "\\put(%3d,%3d){\\oval(%d,%d)}\n", x, y, dx, dy); |
|---|
| 641 | if (e->area_fill && (int)e->area_fill != DEFAULT) |
|---|
| 642 | fprintf(stderr, "Ellipse area fill not implemented\n"); |
|---|
| 643 | } |
|---|
| 644 | } |
|---|
| 645 | |
|---|
| 646 | void genlatex_text(t) |
|---|
| 647 | F_text *t; |
|---|
| 648 | { |
|---|
| 649 | int x, y; |
|---|
| 650 | char *tpos; |
|---|
| 651 | unsigned char *cp; |
|---|
| 652 | |
|---|
| 653 | if (verbose) fprintf(tfp, "%%\n%% Fig TEXT object\n%%\n"); |
|---|
| 654 | |
|---|
| 655 | x = t->base_x; |
|---|
| 656 | y = t->base_y; |
|---|
| 657 | TRANS(x, y); |
|---|
| 658 | |
|---|
| 659 | switch (t->type) { |
|---|
| 660 | |
|---|
| 661 | case T_LEFT_JUSTIFIED: |
|---|
| 662 | case DEFAULT: |
|---|
| 663 | tpos = "[lb]"; |
|---|
| 664 | break; |
|---|
| 665 | |
|---|
| 666 | case T_CENTER_JUSTIFIED: |
|---|
| 667 | tpos = "[b]"; |
|---|
| 668 | break; |
|---|
| 669 | |
|---|
| 670 | case T_RIGHT_JUSTIFIED: |
|---|
| 671 | tpos = "[rb]"; |
|---|
| 672 | break; |
|---|
| 673 | |
|---|
| 674 | default: |
|---|
| 675 | fprintf(stderr, "Text incorrectly positioned\n"); |
|---|
| 676 | } |
|---|
| 677 | |
|---|
| 678 | /* smash is used to position text at baseline */ |
|---|
| 679 | unpsfont(t); |
|---|
| 680 | fprintf(tfp, |
|---|
| 681 | "\\put(%3d,%3d){\\makebox(0,0)%s{\\smash{", |
|---|
| 682 | x, y, tpos); |
|---|
| 683 | |
|---|
| 684 | #ifdef DVIPS |
|---|
| 685 | if(t->angle && t->type == T_LEFT_JUSTIFIED) |
|---|
| 686 | fprintf(tfp, "\\special{ps:gsave currentpoint currentpoint translate\n%.1f rotate neg exch neg exch translate}", -t->angle*180/M_PI); |
|---|
| 687 | #endif |
|---|
| 688 | |
|---|
| 689 | { int texsize; |
|---|
| 690 | double baselineskip; |
|---|
| 691 | |
|---|
| 692 | texsize = TEXFONTMAG(t); |
|---|
| 693 | baselineskip = (texsize * 1.2); |
|---|
| 694 | |
|---|
| 695 | fprintf(tfp, "\\SetFigFont{%d}{%.1f}{%s}", |
|---|
| 696 | texsize, baselineskip, TEXFONT(t->font)); |
|---|
| 697 | } |
|---|
| 698 | |
|---|
| 699 | set_color(t->color); |
|---|
| 700 | |
|---|
| 701 | if (!special_text(t)) |
|---|
| 702 | |
|---|
| 703 | /* this loop escapes characters "$&%#_{}" */ |
|---|
| 704 | /* and deleted characters "~^\" */ |
|---|
| 705 | for(cp = (unsigned char*)t->cstring; *cp; cp++) { |
|---|
| 706 | if (strchr("$&%#_{}", *cp)) (void)fputc('\\', tfp); |
|---|
| 707 | if (strchr("~^\\", *cp)) |
|---|
| 708 | fprintf(stderr, |
|---|
| 709 | "Bad character in text object '%c'\n" ,*cp); |
|---|
| 710 | else |
|---|
| 711 | (void)fputc(*cp, tfp); |
|---|
| 712 | } |
|---|
| 713 | else |
|---|
| 714 | for(cp = (unsigned char*)t->cstring; *cp; cp++) { |
|---|
| 715 | if (*cp >= 0xa0) |
|---|
| 716 | fprintf(tfp, "%s", ISOtoTeX[(int)*cp-0xa0]); |
|---|
| 717 | else |
|---|
| 718 | fputc(*cp, tfp); |
|---|
| 719 | } |
|---|
| 720 | |
|---|
| 721 | reset_color(t->color); |
|---|
| 722 | |
|---|
| 723 | #ifdef DVIPS |
|---|
| 724 | if(t->angle) |
|---|
| 725 | { |
|---|
| 726 | if (t->type == T_LEFT_JUSTIFIED) |
|---|
| 727 | fprintf(tfp, "\\special{ps:currentpoint grestore moveto}"); |
|---|
| 728 | else |
|---|
| 729 | fprintf(stderr, "Rotated Text only for left justified text\n"); |
|---|
| 730 | } |
|---|
| 731 | #endif |
|---|
| 732 | fprintf(tfp, "}}}\n"); |
|---|
| 733 | } |
|---|
| 734 | |
|---|
| 735 | void genlatex_arc(a) |
|---|
| 736 | F_arc *a; |
|---|
| 737 | /* |
|---|
| 738 | * Approximates an arc by a sequence of quarter ovals. |
|---|
| 739 | * |
|---|
| 740 | * Example: |
|---|
| 741 | * |
|---|
| 742 | * Arc with center at (0,0) and radius 10 from +45 degree to +225 degree |
|---|
| 743 | * (arc from p1 = (7.07, 7.07) to p2 = (-7.07, -7.07) counterclockwise). |
|---|
| 744 | * This arc is approximated by three quarter ovals, one for each quadrant |
|---|
| 745 | * through which the arc goes: |
|---|
| 746 | * |
|---|
| 747 | * 1. quarter oval from p1 to the intersection of arc and y-axis, |
|---|
| 748 | * i.e., from (7.07, 7.07) to (0, 10) in quadrant 0 |
|---|
| 749 | * |
|---|
| 750 | * \put(0, 7.07){\oval(14.14, 5.86)[tr]} |
|---|
| 751 | * |
|---|
| 752 | * 2. quarter oval from intersection arc/y-axis to intersection arc/x-axis |
|---|
| 753 | * i.e., from (0, 10) to (-10, 0) in quadrant 1 |
|---|
| 754 | * |
|---|
| 755 | * \put(0, 0){\oval(20,20)[tl]} |
|---|
| 756 | * |
|---|
| 757 | * 3. quarter oval from p1 to the intersection of arc and y-axis, |
|---|
| 758 | * i.e., from (-10, 0) to (-7.07, -7.07) in quadrant 2 |
|---|
| 759 | * |
|---|
| 760 | * \put(-7.07, 0){\oval(5.86, 14.14)[bl]} |
|---|
| 761 | */ |
|---|
| 762 | { |
|---|
| 763 | F_pos p1, p2, pq[4]; |
|---|
| 764 | double cx, cy; |
|---|
| 765 | double v1x, v1y, v2x, v2y; |
|---|
| 766 | double r, angle1, angle2; |
|---|
| 767 | int q1, q2; |
|---|
| 768 | int p1_arrow, p2_arrow; |
|---|
| 769 | static char *ad1[4] = { " 0,-1", " 1, 0", " 0, 1", "-1, 0" }; |
|---|
| 770 | static char *ad2[4] = { "-1, 0", " 0,-1", " 1, 0", " 0, 1" }; |
|---|
| 771 | |
|---|
| 772 | set_linewidth(a->thickness); |
|---|
| 773 | set_color(a->color); |
|---|
| 774 | switch (a->style) { |
|---|
| 775 | case SOLID_LINE: |
|---|
| 776 | break; |
|---|
| 777 | case DASH_LINE: |
|---|
| 778 | fprintf(stderr, "Dashed arcs not supported\n"); |
|---|
| 779 | break; |
|---|
| 780 | case DOTTED_LINE: |
|---|
| 781 | fprintf(stderr, "Dotted arcs not supported\n"); |
|---|
| 782 | break; |
|---|
| 783 | } |
|---|
| 784 | if (a->direction == 1) { |
|---|
| 785 | p1 = a->point[0]; |
|---|
| 786 | p2 = a->point[2]; |
|---|
| 787 | p1_arrow = (a->back_arrow != NULL); |
|---|
| 788 | p2_arrow = (a->for_arrow != NULL); |
|---|
| 789 | } |
|---|
| 790 | else { |
|---|
| 791 | p1 = a->point[2]; |
|---|
| 792 | p2 = a->point[0]; |
|---|
| 793 | p1_arrow = (a->for_arrow != NULL); |
|---|
| 794 | p2_arrow = (a->back_arrow != NULL); |
|---|
| 795 | } |
|---|
| 796 | cx = a->center.x; |
|---|
| 797 | cy = a->center.y; |
|---|
| 798 | TRANS2(p1.x, p1.y, p2.x, p2.y); |
|---|
| 799 | TRANSD(cx, cy); |
|---|
| 800 | /*** compute vectors and angles from arc center to p1, p2 ***/ |
|---|
| 801 | v1x = (double)p1.x - cx; |
|---|
| 802 | v1y = (double)p1.y - cy; |
|---|
| 803 | v2x = (double)p2.x - cx; |
|---|
| 804 | v2y = (double)p2.y - cy; |
|---|
| 805 | angle1 = atan2(v1y, v1x) * rad2deg; |
|---|
| 806 | angle2 = atan2(v2y, v2x) * rad2deg; |
|---|
| 807 | if (angle1 < 0.0) |
|---|
| 808 | angle1 += 360.0; |
|---|
| 809 | if (angle2 < 0.0) |
|---|
| 810 | angle2 += 360.0; |
|---|
| 811 | /* compute arc radius */ |
|---|
| 812 | r = sqrt(v1x*v1x+v1y*v1y); |
|---|
| 813 | /*** compute intersection of arc with x and y axis (origin at cx, cy) */ |
|---|
| 814 | pq[0].x = round(cx); |
|---|
| 815 | pq[0].y = round(cy + r); |
|---|
| 816 | pq[1].x = round(cx - r); |
|---|
| 817 | pq[1].y = round(cy); |
|---|
| 818 | pq[2].x = round(cx); |
|---|
| 819 | pq[2].y = round(cy - r); |
|---|
| 820 | pq[3].x = round(cx + r); |
|---|
| 821 | pq[3].y = round(cy); |
|---|
| 822 | /*** compute in which quadrants p1 and p2 are located ***/ |
|---|
| 823 | q1 = (int)(angle1/90.0); |
|---|
| 824 | q2 = (int)(angle2/90.0); |
|---|
| 825 | if (fabs(angle1 - 90.0*q1) > arc_tolerance |
|---|
| 826 | || fabs(angle2 - 90.0*q2) > arc_tolerance) |
|---|
| 827 | fprintf(stderr, "Approximating arc by ovals\n"); |
|---|
| 828 | /*** Draw arc ***/ |
|---|
| 829 | if (p1_arrow) |
|---|
| 830 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%s){0}}\n", p1.x, p1.y, ad1[q1]); |
|---|
| 831 | while (q1 != q2) { |
|---|
| 832 | put_quarter(p1, pq[q1], q1); |
|---|
| 833 | p1 = pq[q1]; |
|---|
| 834 | q1 = (q1 + 1) % 4; |
|---|
| 835 | } |
|---|
| 836 | put_quarter(p1, p2, q1); |
|---|
| 837 | if (p2_arrow) |
|---|
| 838 | fprintf(tfp, "\\put(%3d,%3d){\\vector(%s){0}}\n", p2.x, p2.y, ad2[q2]); |
|---|
| 839 | |
|---|
| 840 | if (a->area_fill && (int)a->area_fill != DEFAULT) |
|---|
| 841 | fprintf(stderr, "Arc area fill not implemented\n"); |
|---|
| 842 | reset_color(a->color); |
|---|
| 843 | } |
|---|
| 844 | |
|---|
| 845 | static put_quarter(p1, p2, q) |
|---|
| 846 | F_pos p1, p2; |
|---|
| 847 | int q; |
|---|
| 848 | /* |
|---|
| 849 | * Draw quarter oval from p1 to p2 in quadrant q |
|---|
| 850 | */ |
|---|
| 851 | { |
|---|
| 852 | char *opt; |
|---|
| 853 | int px, py, dx, dy; |
|---|
| 854 | |
|---|
| 855 | dx = 2*ABS(p1.x - p2.x); |
|---|
| 856 | dy = 2*ABS(p1.y - p2.y); |
|---|
| 857 | if (dx == 0 && dy == 0) |
|---|
| 858 | return; |
|---|
| 859 | switch (q) { |
|---|
| 860 | case 0: |
|---|
| 861 | px = MIN(p1.x, p2.x); |
|---|
| 862 | py = MIN(p1.y, p2.y); |
|---|
| 863 | opt = "tr"; |
|---|
| 864 | break; |
|---|
| 865 | case 1: |
|---|
| 866 | px = MAX(p1.x, p2.x); |
|---|
| 867 | py = MIN(p1.y, p2.y); |
|---|
| 868 | opt = "tl"; |
|---|
| 869 | break; |
|---|
| 870 | case 2: |
|---|
| 871 | px = MAX(p1.x, p2.x); |
|---|
| 872 | py = MAX(p1.y, p2.y); |
|---|
| 873 | opt = "bl"; |
|---|
| 874 | break; |
|---|
| 875 | case 3: |
|---|
| 876 | px = MIN(p1.x, p2.x); |
|---|
| 877 | py = MAX(p1.y, p2.y); |
|---|
| 878 | opt = "br"; |
|---|
| 879 | break; |
|---|
| 880 | } |
|---|
| 881 | fprintf(tfp, "\\put(%3d,%3d){\\oval(%3d,%3d)[%s]}\n", px, py, dx, dy, opt); |
|---|
| 882 | } |
|---|
| 883 | |
|---|
| 884 | #define MAXCOLORS 8 |
|---|
| 885 | |
|---|
| 886 | set_color(col) |
|---|
| 887 | int col; |
|---|
| 888 | { |
|---|
| 889 | static char *colors[] = { |
|---|
| 890 | "0 0 0", /* black */ |
|---|
| 891 | "0 0 1", /* blue */ |
|---|
| 892 | "0 1 0", /* green */ |
|---|
| 893 | "0 1 1", /* cyan */ |
|---|
| 894 | "1 0 0", /* red */ |
|---|
| 895 | "1 0 1", /* magenta */ |
|---|
| 896 | "1 1 0", /* yellow */ |
|---|
| 897 | "1 1 1", /* white */ |
|---|
| 898 | }; |
|---|
| 899 | |
|---|
| 900 | #ifdef DVIPS |
|---|
| 901 | if (col != -1 && col < MAXCOLORS) |
|---|
| 902 | fprintf(tfp, "\\special{ps: gsave %s setrgbcolor}", colors[col]); |
|---|
| 903 | #endif |
|---|
| 904 | return; |
|---|
| 905 | } |
|---|
| 906 | |
|---|
| 907 | reset_color(col) |
|---|
| 908 | int col; |
|---|
| 909 | { |
|---|
| 910 | #ifdef DVIPS |
|---|
| 911 | if (col != -1 && col < MAXCOLORS) |
|---|
| 912 | fprintf(tfp, "\\special{ps: grestore}"); |
|---|
| 913 | #endif |
|---|
| 914 | return; |
|---|
| 915 | } |
|---|
| 916 | |
|---|
| 917 | |
|---|
| 918 | struct driver dev_latex = { |
|---|
| 919 | genlatex_option, |
|---|
| 920 | genlatex_start, |
|---|
| 921 | genlatex_arc, |
|---|
| 922 | genlatex_ellipse, |
|---|
| 923 | genlatex_line, |
|---|
| 924 | genlatex_spline, |
|---|
| 925 | genlatex_text, |
|---|
| 926 | genlatex_end, |
|---|
| 927 | EXCLUDE_TEXT |
|---|
| 928 | }; |
|---|