/* Copyright (C) 1989, 1990 Free Software Foundation, Inc.
Written by James Clark (jjc@jclark.uucp)
This file is part of groff.
groff is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 1, or (at your option) any later
groff is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
You should have received a copy of the GNU General Public License along
with groff; see the file LICENSE. If not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
class tex_output
: public common_output
{
void start_picture(double, const position
&ll
, const position
&ur
);
void text(const position
&, text_piece
*, int, double);
void line(const position
&, const position
*, int n
,
void polygon(const position
*, int n
,
const line_type
&, double);
void spline(const position
&, const position
*, int n
,
void arc(const position
&, const position
&, const position
&,
void circle(const position
&, double rad
, const line_type
&, double);
void ellipse(const position
&, const distance
&, const line_type
&, double);
void command(const char *, const char *, int);
int supports_filled_polygons();
void point(const position
&);
void dot(const position
&, const line_type
&);
void solid_arc(const position
¢
, double rad
, double start_angle
,
double end_angle
, const line_type
<
);
position
transform(const position
&);
virtual void set_pen_size(double ps
);
// convert inches to milliinches
inline int milliinches(double x
)
return int(x
*1000.0 + .5);
inline position
tex_output::transform(const position
&pos
)
return position((pos
.x
- upper_left
.x
)/scale
,
(upper_left
.y
- pos
.y
)/scale
);
output
*make_tex_output()
tex_output::~tex_output()
const int DEFAULT_PEN_SIZE
= 8;
void tex_output::set_pen_size(double ps
)
printf(" \\special{pn %d}%%\n",
ps
< 0.0 ? DEFAULT_PEN_SIZE
: int(ps
*(1000.0/72.0) + .5));
void tex_output::start_picture(double sc
, const position
&ll
,
scale
= compute_scale(sc
, ll
, ur
);
height
= (ur
.y
- ll
.y
)/scale
;
width
= (ur
.x
- ll
.x
)/scale
;
/* the point of \vskip 0pt is to ensure that the vtop gets
a height of 0 rather than the height of the hbox; this
might be non-zero if text from text attributes lies outside pic's
idea of the bounding box of the picture. */
fputs("\\expandafter\\ifx\\csname graph\\endcsname\\relax \\csname newbox\\endcsname\\graph\\fi\n"
"\\expandafter\\ifx\\csname graphtemp\\endcsname\\relax \\csname newdimen\\endcsname\\graphtemp\\fi\n"
"\\setbox\\graph=\\vtop{\\vskip 0pt\\hbox{%\n",
void tex_output::finish_picture()
printf(" \\hbox{\\vrule depth%.3fin width0pt height 0pt}%%\n"
void tex_output::text(const position
¢er
, text_piece
*v
, int n
, double)
position c
= transform(center
);
for (int i
= 0; i
< n
; i
++)
if (v
[i
].text
!= 0 && *v
[i
].text
!= '\0') {
if (v
[i
].adj
.v
== ABOVE_ADJUST
)
else if (v
[i
].adj
.v
== BELOW_ADJUST
)
printf(" \\graphtemp=.5ex\\advance\\graphtemp by %.3fin\n", c
.y
);
printf(" \\graphtemp=\\baselineskip"
"\\multiply\\graphtemp by %d"
"\\divide\\graphtemp by 2\n"
" \\advance\\graphtemp by .5ex"
"\\advance\\graphtemp by %.3fin\n",
printf(" \\rlap{\\kern %.3fin\\lower\\graphtemp", c
.x
);
fputs("\\hbox to 0pt{", stdout
);
if (v
[i
].adj
.h
!= LEFT_ADJUST
)
fputs(v
[i
].text
, stdout
);
if (v
[i
].adj
.h
!= RIGHT_ADJUST
)
void tex_output::point(const position
&pos
)
position p
= transform(pos
);
printf(" \\special{pa %d %d}%%\n", milliinches(p
.x
), milliinches(p
.y
));
void tex_output::line(const position
&start
, const position
*v
, int n
,
set_pen_size(lt
.thickness
);
for (int i
= 0; i
< n
; i
++)
fputs(" \\special{", stdout
);
case line_type::invisible
:
printf("dt %.3f", lt
.dash_width
/scale
);
printf("da %.3f", lt
.dash_width
/scale
);
void tex_output::polygon(const position
*v
, int n
,
const line_type
<
, double fill
)
printf(" \\special{sh %.3f}%%\n", fill
);
void tex_output::spline(const position
&start
, const position
*v
, int n
,
if (lt
.type
== line_type::invisible
)
set_pen_size(lt
.thickness
);
for (int i
= 0; i
< n
; i
++)
fputs(" \\special{sp", stdout
);
printf(" %.3f", -lt
.dash_width
/scale
);
printf(" %.3f", lt
.dash_width
/scale
);
case line_type::invisible
:
void tex_output::solid_arc(const position
¢
, double rad
,
double start_angle
, double end_angle
,
set_pen_size(lt
.thickness
);
position c
= transform(cent
);
printf(" \\special{ar %d %d %d %d %f %f}%%\n",
(-end_angle
> -start_angle
) ? M_PI
* 2 - start_angle
: -start_angle
);
void tex_output::arc(const position
&start
, const position
¢
,
const position
&end
, const line_type
<
)
case line_type::invisible
:
dashed_arc(start
, cent
, end
, lt
);
dotted_arc(start
, cent
, end
, lt
);
if (!compute_arc_center(start
, cent
, end
, &c
)) {
line(start
, &end
, 1, lt
);
atan2(start
.y
- c
.y
, start
.x
- c
.x
),
atan2(end
.y
- c
.y
, end
.x
- c
.x
),
void tex_output::circle(const position
¢
, double rad
,
const line_type
<
, double fill
)
if (fill
>= 0.0 && lt
.type
!= line_type::solid
) {
ilt
.type
= line_type::invisible
;
ellipse(cent
, position(rad
*2.0, rad
*2.0), ilt
, fill
);
dashed_circle(cent
, rad
, lt
);
case line_type::invisible
:
ellipse(cent
, position(rad
*2.0,rad
*2.0), lt
, fill
);
dotted_circle(cent
, rad
, lt
);
void tex_output::ellipse(const position
¢
, const distance
&dim
,
const line_type
<
, double fill
)
if (lt
.type
== line_type::invisible
) {
set_pen_size(lt
.thickness
);
printf(" \\special{sh %.3f}%%\n", fill
);
position c
= transform(cent
);
printf(" \\special{%s %d %d %d %d 0 6.28319}%%\n",
(lt
.type
== line_type::invisible
? "ia" : "ar"),
milliinches(dim
.x
/(2.0*scale
)),
milliinches(dim
.y
/(2.0*scale
)));
void tex_output::command(const char *s
, const char *, int)
putchar('%'); // avoid unwanted spaces
int tex_output::supports_filled_polygons()
void tex_output::dot(const position
&pos
, const line_type
<
)
if (zero_length_line_flag
) {
slt
.type
= line_type::solid
;
int dot_rad
= int(lt
.thickness
*(1000.0/(72.0*2)) + .5);
position p
= transform(pos
);
printf(" \\special{sh 1}%%\n"
" \\special{ia %d %d %d %d 0 6.28319}%%\n",
milliinches(p
.x
), milliinches(p
.y
), dot_rad
, dot_rad
);
class tpic_output
: public tex_output
{
void command(const char *, const char *, int);
void set_pen_size(double ps
);
int prev_default_pen_size
;
tpic_output::tpic_output()
: default_pen_size(DEFAULT_PEN_SIZE
), prev_default_pen_size(DEFAULT_PEN_SIZE
)
void tpic_output::command(const char *s
, const char *filename
, int lineno
)
if (s
[1] == 'p' && s
[2] == 's' && (s
[3] == '\0' || !csalpha(s
[3]))) {
int temp
= default_pen_size
;
default_pen_size
= prev_default_pen_size
;
prev_default_pen_size
= temp
;
int temp
= (int)strtol(p
, &ptr
, 10);
if (temp
== 0 && ptr
== p
)
error_with_file_and_line(filename
, lineno
,
"argument to `.ps' not an integer");
error_with_file_and_line(filename
, lineno
,
prev_default_pen_size
= default_pen_size
;
printf("\\%s%%\n", s
+ 1);
void tpic_output::set_pen_size(double ps
)
printf(" \\special{pn %d}%%\n", default_pen_size
);
tex_output::set_pen_size(ps
);
output
*make_tpic_output()