2 * Copyright (c) 2014 - 2017 Steffen (Daode) Nurpmeso <steffen@sdaoden.eu>.
4 * Copyright (C) 1989 - 1992, 2003 Free Software Foundation, Inc.
5 * Written by James Clark (jjc@jclark.com)
7 * This 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 * This 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, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA.
23 #include "pic-config.h"
30 : public common_output
38 void point(const position
&);
39 void dot(const position
&, const line_type
&);
40 void solid_arc(const position
¢
, double rad
, double start_angle
,
41 double end_angle
, const line_type
<
);
42 position
transform(const position
&);
45 virtual void set_pen_size(double ps
);
50 void start_picture(double, const position
&ll
, const position
&ur
);
51 void finish_picture();
52 void text(const position
&, text_piece
*, int, double);
53 void line(const position
&, const position
*, int n
,
55 void polygon(const position
*, int n
,
56 const line_type
&, double);
57 void spline(const position
&, const position
*, int n
,
59 void arc(const position
&, const position
&, const position
&,
61 void circle(const position
&, double rad
, const line_type
&, double);
62 void ellipse(const position
&, const distance
&, const line_type
&, double);
63 void command(const char *, const char *, int);
64 void set_color(char *, char *);
66 char *get_last_filled();
67 char *get_outline_color();
68 int supports_filled_polygons();
71 // convert inches to milliinches
73 inline int milliinches(double x
)
75 return int(x
*1000.0 + .5);
78 inline position
tex_output::transform(const position
&pos
)
80 return position((pos
.x
- upper_left
.x
)/scale
,
81 (upper_left
.y
- pos
.y
)/scale
);
84 output
*make_tex_output()
86 return new tex_output
;
89 tex_output::tex_output()
93 tex_output::~tex_output()
97 const int DEFAULT_PEN_SIZE
= 8;
99 void tex_output::set_pen_size(double ps
)
103 if (ps
!= pen_size
) {
105 printf(" \\special{pn %d}%%\n",
106 ps
< 0.0 ? DEFAULT_PEN_SIZE
: int(ps
*(1000.0/72.0) + .5));
110 void tex_output::start_picture(double sc
, const position
&ll
,
115 scale
= compute_scale(sc
, ll
, ur
);
116 height
= (ur
.y
- ll
.y
)/scale
;
117 width
= (ur
.x
- ll
.x
)/scale
;
118 /* The point of \vskip 0pt is to ensure that the vtop gets
119 a height of 0 rather than the height of the hbox; this
120 might be non-zero if text from text attributes lies outside pic's
121 idea of the bounding box of the picture. */
122 /* \newbox and \newdimen are defined with \outer in plain.tex and can't
123 be used directly in an \if clause. */
124 printf("\\expandafter\\ifx\\csname %s\\endcsname\\relax\n"
125 " \\csname newbox\\expandafter\\endcsname\\csname %s\\endcsname\n"
127 "\\ifx\\graphtemp\\undefined\n"
128 " \\csname newdimen\\endcsname\\graphtemp\n"
130 "\\expandafter\\setbox\\csname %s\\endcsname\n"
131 " =\\vtop{\\vskip 0pt\\hbox{%%\n",
132 graphname
, graphname
, graphname
);
136 void tex_output::finish_picture()
138 printf(" \\hbox{\\vrule depth%.3fin width0pt height 0pt}%%\n"
145 void tex_output::text(const position
¢er
, text_piece
*v
, int n
, double)
147 position c
= transform(center
);
148 for (int i
= 0; i
< n
; i
++)
149 if (v
[i
].text
!= 0 && *v
[i
].text
!= '\0') {
151 if (v
[i
].adj
.v
== ABOVE_ADJUST
)
153 else if (v
[i
].adj
.v
== BELOW_ADJUST
)
156 printf(" \\graphtemp=.5ex\n"
157 " \\advance\\graphtemp by %.3fin\n", c
.y
);
160 printf(" \\graphtemp=\\baselineskip\n"
161 " \\multiply\\graphtemp by %d\n"
162 " \\divide\\graphtemp by 2\n"
163 " \\advance\\graphtemp by .5ex\n"
164 " \\advance\\graphtemp by %.3fin\n",
167 printf(" \\rlap{\\kern %.3fin\\lower\\graphtemp", c
.x
);
168 fputs("\\hbox to 0pt{", stdout
);
169 if (v
[i
].adj
.h
!= LEFT_ADJUST
)
170 fputs("\\hss ", stdout
);
171 fputs(v
[i
].text
, stdout
);
172 if (v
[i
].adj
.h
!= RIGHT_ADJUST
)
173 fputs("\\hss", stdout
);
174 fputs("}}%\n", stdout
);
178 void tex_output::point(const position
&pos
)
180 position p
= transform(pos
);
181 printf(" \\special{pa %d %d}%%\n", milliinches(p
.x
), milliinches(p
.y
));
184 void tex_output::line(const position
&start
, const position
*v
, int n
,
187 set_pen_size(lt
.thickness
);
189 for (int i
= 0; i
< n
; i
++)
191 fputs(" \\special{", stdout
);
193 case line_type::invisible
:
196 case line_type::solid
:
199 case line_type::dotted
:
200 printf("dt %.3f", lt
.dash_width
/scale
);
202 case line_type::dashed
:
203 printf("da %.3f", lt
.dash_width
/scale
);
206 fputs("}%\n", stdout
);
209 void tex_output::polygon(const position
*v
, int n
,
210 const line_type
<
, double fill
)
215 printf(" \\special{sh %.3f}%%\n", fill
);
217 line(v
[n
-1], v
, n
, lt
);
220 void tex_output::spline(const position
&start
, const position
*v
, int n
,
223 if (lt
.type
== line_type::invisible
)
225 set_pen_size(lt
.thickness
);
227 for (int i
= 0; i
< n
; i
++)
229 fputs(" \\special{sp", stdout
);
231 case line_type::solid
:
233 case line_type::dotted
:
234 printf(" %.3f", -lt
.dash_width
/scale
);
236 case line_type::dashed
:
237 printf(" %.3f", lt
.dash_width
/scale
);
239 case line_type::invisible
:
242 fputs("}%\n", stdout
);
245 void tex_output::solid_arc(const position
¢
, double rad
,
246 double start_angle
, double end_angle
,
249 set_pen_size(lt
.thickness
);
250 position c
= transform(cent
);
251 printf(" \\special{ar %d %d %d %d %f %f}%%\n",
254 milliinches(rad
/scale
),
255 milliinches(rad
/scale
),
257 (-end_angle
> -start_angle
) ? (double)M_PI
* 2 - start_angle
261 void tex_output::arc(const position
&start
, const position
¢
,
262 const position
&end
, const line_type
<
)
265 case line_type::invisible
:
267 case line_type::dashed
:
268 dashed_arc(start
, cent
, end
, lt
);
270 case line_type::dotted
:
271 dotted_arc(start
, cent
, end
, lt
);
273 case line_type::solid
:
276 if (!compute_arc_center(start
, cent
, end
, &c
)) {
277 line(start
, &end
, 1, lt
);
282 atan2(start
.y
- c
.y
, start
.x
- c
.x
),
283 atan2(end
.y
- c
.y
, end
.x
- c
.x
),
290 void tex_output::circle(const position
¢
, double rad
,
291 const line_type
<
, double fill
)
293 if (fill
>= 0.0 && lt
.type
!= line_type::solid
) {
297 ilt
.type
= line_type::invisible
;
298 ellipse(cent
, position(rad
*2.0, rad
*2.0), ilt
, fill
);
301 case line_type::dashed
:
302 dashed_circle(cent
, rad
, lt
);
304 case line_type::invisible
:
306 case line_type::solid
:
307 ellipse(cent
, position(rad
*2.0,rad
*2.0), lt
, fill
);
309 case line_type::dotted
:
310 dotted_circle(cent
, rad
, lt
);
317 void tex_output::ellipse(const position
¢
, const distance
&dim
,
318 const line_type
<
, double fill
)
320 if (lt
.type
== line_type::invisible
) {
325 set_pen_size(lt
.thickness
);
329 printf(" \\special{sh %.3f}%%\n", fill
);
331 position c
= transform(cent
);
333 case line_type::solid
:
334 case line_type::invisible
:
335 printf(" \\special{%s %d %d %d %d 0 6.28319}%%\n",
336 (lt
.type
== line_type::invisible
? "ia" : "ar"),
339 milliinches(dim
.x
/(2.0*scale
)),
340 milliinches(dim
.y
/(2.0*scale
)));
342 case line_type::dashed
:
343 dashed_ellipse(cent
, dim
/ scale
, lt
);
345 case line_type::dotted
:
346 dotted_ellipse(cent
, dim
/ scale
, lt
);
353 void tex_output::command(const char *s
, const char *, int)
356 putchar('%'); // avoid unwanted spaces
360 int tex_output::supports_filled_polygons()
365 void tex_output::dot(const position
&pos
, const line_type
<
)
367 if (zero_length_line_flag
) {
369 slt
.type
= line_type::solid
;
370 line(pos
, &pos
, 1, slt
);
373 int dot_rad
= int(lt
.thickness
*(1000.0/(72.0*2)) + .5);
376 position p
= transform(pos
);
377 printf(" \\special{sh 1}%%\n"
378 " \\special{ia %d %d %d %d 0 6.28319}%%\n",
379 milliinches(p
.x
), milliinches(p
.y
), dot_rad
, dot_rad
);
383 void tex_output::set_color(char *, char *)
385 /* not implemented yet */
388 void tex_output::reset_color()
390 /* not implemented yet */
393 char *tex_output::get_last_filled()
395 /* not implemented yet */
399 char *tex_output::get_outline_color()
401 /* not implemented yet */
408 int default_pen_size
;
409 int prev_default_pen_size
;
411 void set_pen_size(double ps
);
415 void command(const char *, const char *, int);
418 tpic_output::tpic_output()
419 : default_pen_size(DEFAULT_PEN_SIZE
), prev_default_pen_size(DEFAULT_PEN_SIZE
)
423 void tpic_output::command(const char *s
, const char *filename
, int lineno
)
426 if (s
[1] == 'p' && s
[2] == 's' && (s
[3] == '\0' || !csalpha(s
[3]))) {
427 const char *p
= s
+ 3;
431 int temp
= default_pen_size
;
432 default_pen_size
= prev_default_pen_size
;
433 prev_default_pen_size
= temp
;
437 int temp
= (int)strtol(p
, &ptr
, 10);
438 if (temp
== 0 && ptr
== p
)
439 error_with_file_and_line(filename
, lineno
,
440 "argument to `.ps' not an integer");
442 error_with_file_and_line(filename
, lineno
,
443 "negative pen size");
445 prev_default_pen_size
= default_pen_size
;
446 default_pen_size
= temp
;
451 printf("\\%s%%\n", s
+ 1);
454 void tpic_output::set_pen_size(double ps
)
457 printf(" \\special{pn %d}%%\n", default_pen_size
);
459 tex_output::set_pen_size(ps
);
462 output
*make_tpic_output()
464 return new tpic_output
;
467 #endif // TEX_SUPPORT