2 /* Copyright (C) 1989, 1990, 1991, 1992 Free Software Foundation, Inc.
3 Written by James Clark (jjc@jclark.com)
5 This file is part of groff.
7 groff is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 2, or (at your option) any later
12 groff is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License along
18 with groff; see the file COPYING. If not, write to the Free Software
19 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
27 class tex_output : public common_output {
31 void start_picture(double, const position &ll, const position &ur);
32 void finish_picture();
33 void text(const position &, text_piece *, int, double);
34 void line(const position &, const position *, int n,
36 void polygon(const position *, int n,
37 const line_type &, double);
38 void spline(const position &, const position *, int n,
40 void arc(const position &, const position &, const position &,
42 void circle(const position &, double rad, const line_type &, double);
43 void ellipse(const position &, const distance &, const line_type &, double);
44 void command(const char *, const char *, int);
45 void set_color(char *, char *);
47 char *get_last_filled();
48 char *get_outline_color();
49 int supports_filled_polygons();
57 void point(const position &);
58 void dot(const position &, const line_type &);
59 void solid_arc(const position ¢, double rad, double start_angle,
60 double end_angle, const line_type <);
61 position transform(const position &);
63 virtual void set_pen_size(double ps);
66 // convert inches to milliinches
68 inline int milliinches(double x)
70 return int(x*1000.0 + .5);
73 inline position tex_output::transform(const position &pos)
75 return position((pos.x - upper_left.x)/scale,
76 (upper_left.y - pos.y)/scale);
79 output *make_tex_output()
81 return new tex_output;
84 tex_output::tex_output()
88 tex_output::~tex_output()
92 const int DEFAULT_PEN_SIZE = 8;
94 void tex_output::set_pen_size(double ps)
100 printf(" \\special{pn %d}%%\n",
101 ps < 0.0 ? DEFAULT_PEN_SIZE : int(ps*(1000.0/72.0) + .5));
105 void tex_output::start_picture(double sc, const position &ll,
110 scale = compute_scale(sc, ll, ur);
111 height = (ur.y - ll.y)/scale;
112 width = (ur.x - ll.x)/scale;
113 /* the point of \vskip 0pt is to ensure that the vtop gets
114 a height of 0 rather than the height of the hbox; this
115 might be non-zero if text from text attributes lies outside pic's
116 idea of the bounding box of the picture. */
117 fputs("\\expandafter\\ifx\\csname graph\\endcsname\\relax \\csname newbox\\endcsname\\graph\\fi\n"
118 "\\expandafter\\ifx\\csname graphtemp\\endcsname\\relax \\csname newdimen\\endcsname\\graphtemp\\fi\n"
119 "\\setbox\\graph=\\vtop{\\vskip 0pt\\hbox{%\n",
124 void tex_output::finish_picture()
126 printf(" \\hbox{\\vrule depth%.3fin width0pt height 0pt}%%\n"
133 void tex_output::text(const position ¢er, text_piece *v, int n, double)
135 position c = transform(center);
136 for (int i = 0; i < n; i++)
137 if (v[i].text != 0 && *v[i].text != '\0') {
139 if (v[i].adj.v == ABOVE_ADJUST)
141 else if (v[i].adj.v == BELOW_ADJUST)
144 printf(" \\graphtemp=.5ex\\advance\\graphtemp by %.3fin\n", c.y);
147 printf(" \\graphtemp=\\baselineskip"
148 "\\multiply\\graphtemp by %d"
149 "\\divide\\graphtemp by 2\n"
150 " \\advance\\graphtemp by .5ex"
151 "\\advance\\graphtemp by %.3fin\n",
154 printf(" \\rlap{\\kern %.3fin\\lower\\graphtemp", c.x);
155 fputs("\\hbox to 0pt{", stdout);
156 if (v[i].adj.h != LEFT_ADJUST)
157 fputs("\\hss ", stdout);
158 fputs(v[i].text, stdout);
159 if (v[i].adj.h != RIGHT_ADJUST)
160 fputs("\\hss", stdout);
161 fputs("}}%\n", stdout);
165 void tex_output::point(const position &pos)
167 position p = transform(pos);
168 printf(" \\special{pa %d %d}%%\n", milliinches(p.x), milliinches(p.y));
171 void tex_output::line(const position &start, const position *v, int n,
174 set_pen_size(lt.thickness);
176 for (int i = 0; i < n; i++)
178 fputs(" \\special{", stdout);
180 case line_type::invisible:
183 case line_type::solid:
186 case line_type::dotted:
187 printf("dt %.3f", lt.dash_width/scale);
189 case line_type::dashed:
190 printf("da %.3f", lt.dash_width/scale);
193 fputs("}%\n", stdout);
196 void tex_output::polygon(const position *v, int n,
197 const line_type <, double fill)
202 printf(" \\special{sh %.3f}%%\n", fill);
204 line(v[n-1], v, n, lt);
207 void tex_output::spline(const position &start, const position *v, int n,
210 if (lt.type == line_type::invisible)
212 set_pen_size(lt.thickness);
214 for (int i = 0; i < n; i++)
216 fputs(" \\special{sp", stdout);
218 case line_type::solid:
220 case line_type::dotted:
221 printf(" %.3f", -lt.dash_width/scale);
223 case line_type::dashed:
224 printf(" %.3f", lt.dash_width/scale);
226 case line_type::invisible:
229 fputs("}%\n", stdout);
232 void tex_output::solid_arc(const position ¢, double rad,
233 double start_angle, double end_angle,
236 set_pen_size(lt.thickness);
237 position c = transform(cent);
238 printf(" \\special{ar %d %d %d %d %f %f}%%\n",
241 milliinches(rad/scale),
242 milliinches(rad/scale),
244 (-end_angle > -start_angle) ? (double)M_PI * 2 - start_angle
248 void tex_output::arc(const position &start, const position ¢,
249 const position &end, const line_type <)
252 case line_type::invisible:
254 case line_type::dashed:
255 dashed_arc(start, cent, end, lt);
257 case line_type::dotted:
258 dotted_arc(start, cent, end, lt);
260 case line_type::solid:
263 if (!compute_arc_center(start, cent, end, &c)) {
264 line(start, &end, 1, lt);
269 atan2(start.y - c.y, start.x - c.x),
270 atan2(end.y - c.y, end.x - c.x),
277 void tex_output::circle(const position ¢, double rad,
278 const line_type <, double fill)
280 if (fill >= 0.0 && lt.type != line_type::solid) {
284 ilt.type = line_type::invisible;
285 ellipse(cent, position(rad*2.0, rad*2.0), ilt, fill);
288 case line_type::dashed:
289 dashed_circle(cent, rad, lt);
291 case line_type::invisible:
293 case line_type::solid:
294 ellipse(cent, position(rad*2.0,rad*2.0), lt, fill);
296 case line_type::dotted:
297 dotted_circle(cent, rad, lt);
304 void tex_output::ellipse(const position ¢, const distance &dim,
305 const line_type <, double fill)
307 if (lt.type == line_type::invisible) {
312 set_pen_size(lt.thickness);
316 printf(" \\special{sh %.3f}%%\n", fill);
318 position c = transform(cent);
319 printf(" \\special{%s %d %d %d %d 0 6.28319}%%\n",
320 (lt.type == line_type::invisible ? "ia" : "ar"),
323 milliinches(dim.x/(2.0*scale)),
324 milliinches(dim.y/(2.0*scale)));
327 void tex_output::command(const char *s, const char *, int)
330 putchar('%'); // avoid unwanted spaces
334 int tex_output::supports_filled_polygons()
339 void tex_output::dot(const position &pos, const line_type <)
341 if (zero_length_line_flag) {
343 slt.type = line_type::solid;
344 line(pos, &pos, 1, slt);
347 int dot_rad = int(lt.thickness*(1000.0/(72.0*2)) + .5);
350 position p = transform(pos);
351 printf(" \\special{sh 1}%%\n"
352 " \\special{ia %d %d %d %d 0 6.28319}%%\n",
353 milliinches(p.x), milliinches(p.y), dot_rad, dot_rad);
357 void tex_output::set_color(char *, char *)
359 /* not implemented yet */
362 void tex_output::reset_color()
364 /* not implemented yet */
367 char *tex_output::get_last_filled()
369 /* not implemented yet */
373 char *tex_output::get_outline_color()
375 /* not implemented yet */
379 class tpic_output : public tex_output {
382 void command(const char *, const char *, int);
384 void set_pen_size(double ps);
385 int default_pen_size;
386 int prev_default_pen_size;
389 tpic_output::tpic_output()
390 : default_pen_size(DEFAULT_PEN_SIZE), prev_default_pen_size(DEFAULT_PEN_SIZE)
394 void tpic_output::command(const char *s, const char *filename, int lineno)
397 if (s[1] == 'p' && s[2] == 's' && (s[3] == '\0' || !csalpha(s[3]))) {
398 const char *p = s + 3;
402 int temp = default_pen_size;
403 default_pen_size = prev_default_pen_size;
404 prev_default_pen_size = temp;
408 int temp = (int)strtol(p, &ptr, 10);
409 if (temp == 0 && ptr == p)
410 error_with_file_and_line(filename, lineno,
411 "argument to `.ps' not an integer");
413 error_with_file_and_line(filename, lineno,
414 "negative pen size");
416 prev_default_pen_size = default_pen_size;
417 default_pen_size = temp;
422 printf("\\%s%%\n", s + 1);
425 void tpic_output::set_pen_size(double ps)
428 printf(" \\special{pn %d}%%\n", default_pen_size);
430 tex_output::set_pen_size(ps);
433 output *make_tpic_output()
435 return new tpic_output;