summaryrefslogtreecommitdiff
path: root/src/preproc/pic
diff options
context:
space:
mode:
Diffstat (limited to 'src/preproc/pic')
-rw-r--r--src/preproc/pic/common.cc1
-rw-r--r--src/preproc/pic/common.h4
-rw-r--r--src/preproc/pic/lex.cc7
-rw-r--r--src/preproc/pic/object.cc80
-rw-r--r--src/preproc/pic/object.h4
-rw-r--r--src/preproc/pic/output.h8
-rw-r--r--src/preproc/pic/pic.man37
-rw-r--r--src/preproc/pic/pic.y36
-rw-r--r--src/preproc/pic/tex.cc26
-rw-r--r--src/preproc/pic/troff.cc78
10 files changed, 234 insertions, 47 deletions
diff --git a/src/preproc/pic/common.cc b/src/preproc/pic/common.cc
index e83ef312..5075e936 100644
--- a/src/preproc/pic/common.cc
+++ b/src/preproc/pic/common.cc
@@ -437,7 +437,6 @@ void common_output::dot_line(const position &start, const position &end,
}
}
-
void common_output::solid_rounded_box(const position &cent,
const distance &dim, double rad,
const line_type &lt)
diff --git a/src/preproc/pic/common.h b/src/preproc/pic/common.h
index 25a6e10c..90b65fa9 100644
--- a/src/preproc/pic/common.h
+++ b/src/preproc/pic/common.h
@@ -63,6 +63,10 @@ public:
const line_type &, double) = 0;
void rounded_box(const position &, const distance &, double,
const line_type &, double);
+ void set_color(char *, char *) = 0;
+ void reset_color() = 0;
+ char *get_last_filled() = 0;
+ char *get_outline_color() = 0;
};
int compute_arc_center(const position &start, const position &cent,
diff --git a/src/preproc/pic/lex.cc b/src/preproc/pic/lex.cc
index 5b6d439a..0e0161c2 100644
--- a/src/preproc/pic/lex.cc
+++ b/src/preproc/pic/lex.cc
@@ -446,6 +446,10 @@ int lookup_keyword(const char *str, int len)
{ "center", CENTER },
{ "chop", CHOP },
{ "circle", CIRCLE },
+ { "color", COLORED },
+ { "colored", COLORED },
+ { "colour", COLORED },
+ { "coloured", COLORED },
{ "command", COMMAND },
{ "copy", COPY },
{ "cos", COS },
@@ -481,6 +485,8 @@ int lookup_keyword(const char *str, int len)
{ "min", K_MIN },
{ "move", MOVE },
{ "of", OF },
+ { "outline", OUTLINED },
+ { "outlined", OUTLINED },
{ "plot", PLOT },
{ "print", PRINT },
{ "rad", RADIUS },
@@ -491,6 +497,7 @@ int lookup_keyword(const char *str, int len)
{ "rjust", RJUST },
{ "same", SAME },
{ "sh", SH },
+ { "shaded", SHADED },
{ "sin", SIN },
{ "solid", SOLID },
{ "spline", SPLINE },
diff --git a/src/preproc/pic/object.cc b/src/preproc/pic/object.cc
index 6b346330..38b0963b 100644
--- a/src/preproc/pic/object.cc
+++ b/src/preproc/pic/object.cc
@@ -53,14 +53,6 @@ void output::set_args(const char *s)
args = strsave(s);
}
-void output::command(const char *, const char *, int)
-{
-}
-
-void output::set_location(const char *, int)
-{
-}
-
int output::supports_filled_polygons()
{
return 0;
@@ -549,6 +541,8 @@ class graphic_object : public object {
int aligned;
protected:
line_type lt;
+ char *outline_color;
+ char *color_fill;
public:
graphic_object();
~graphic_object();
@@ -559,10 +553,14 @@ public:
void set_dashed(double);
void set_thickness(double);
void set_invisible();
+ void set_outline_color(char *);
+ char *get_outline_color();
virtual void set_fill(double);
+ virtual void set_fill_color(char *);
};
-graphic_object::graphic_object() : ntext(0), text(0), aligned(0)
+graphic_object::graphic_object()
+: ntext(0), text(0), aligned(0), outline_color(0), color_fill(0)
{
}
@@ -587,6 +585,21 @@ void graphic_object::set_fill(double)
{
}
+void graphic_object::set_fill_color(char *c)
+{
+ color_fill = c;
+}
+
+void graphic_object::set_outline_color(char *c)
+{
+ outline_color = c;
+}
+
+char *graphic_object::get_outline_color()
+{
+ return outline_color;
+}
+
void graphic_object::set_invisible()
{
lt.type = line_type::invisible;
@@ -622,8 +635,11 @@ void graphic_object::print_text()
if (d.x != 0.0 || d.y != 0.0)
angle = atan2(d.y, d.x);
}
- if (text != 0)
+ if (text != 0) {
+ out->set_color(color_fill, get_outline_color());
out->text(center(), text, ntext, angle);
+ out->reset_color();
+ }
}
graphic_object::~graphic_object()
@@ -676,12 +692,14 @@ public:
closed_object(const position &);
object_type type() = 0;
void set_fill(double);
+ void set_fill_color(char *fill);
protected:
double fill; // < 0 if not filled
+ char *color_fill; // = 0 if not colored
};
closed_object::closed_object(const position &pos)
-: rectangle_object(pos), fill(-1.0)
+: rectangle_object(pos), fill(-1.0), color_fill(0)
{
}
@@ -691,6 +709,10 @@ void closed_object::set_fill(double f)
fill = f;
}
+void closed_object::set_fill_color(char *fill)
+{
+ color_fill = fill;
+}
class box_object : public closed_object {
double xrad;
@@ -738,8 +760,9 @@ position box_object::south_west()
void box_object::print()
{
- if (lt.type == line_type::invisible && fill < 0.0)
+ if (lt.type == line_type::invisible && fill < 0.0 && color_fill == 0)
return;
+ out->set_color(color_fill, graphic_object::get_outline_color());
if (xrad == 0.0) {
distance dim2 = dim/2.0;
position vec[4];
@@ -753,6 +776,7 @@ void box_object::print()
distance abs_dim(fabs(dim.x), fabs(dim.y));
out->rounded_box(cent, abs_dim, fabs(xrad), lt, fill);
}
+ out->reset_color();
}
graphic_object *object_spec::make_box(position *curpos, direction *dirp)
@@ -990,9 +1014,11 @@ ellipse_object::ellipse_object(const position &d)
void ellipse_object::print()
{
- if (lt.type == line_type::invisible && fill < 0.0)
+ if (lt.type == line_type::invisible && fill < 0.0 && color_fill == 0)
return;
+ out->set_color(color_fill, graphic_object::get_outline_color());
out->ellipse(cent, dim, lt, fill);
+ out->reset_color();
}
graphic_object *object_spec::make_ellipse(position *curpos, direction *dirp)
@@ -1037,9 +1063,11 @@ circle_object::circle_object(double diam)
void circle_object::print()
{
- if (lt.type == line_type::invisible && fill < 0.0)
+ if (lt.type == line_type::invisible && fill < 0.0 && color_fill == 0)
return;
+ out->set_color(color_fill, graphic_object::get_outline_color());
out->circle(cent, dim.x/2.0, lt, fill);
+ out->reset_color();
}
graphic_object *object_spec::make_circle(position *curpos, direction *dirp)
@@ -1222,11 +1250,13 @@ void line_object::print()
{
if (lt.type == line_type::invisible)
return;
+ out->set_color(0, graphic_object::get_outline_color());
out->line(strt, v, n, lt);
if (arrow_at_start)
draw_arrow(strt, strt-v[0], aht, lt);
if (arrow_at_end)
draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt);
+ out->reset_color();
}
void line_object::update_bounding_box(bounding_box *p)
@@ -1289,11 +1319,13 @@ void spline_object::print()
{
if (lt.type == line_type::invisible)
return;
+ out->set_color(0, graphic_object::get_outline_color());
out->spline(strt, v, n, lt);
if (arrow_at_start)
draw_arrow(strt, strt-v[0], aht, lt);
if (arrow_at_end)
draw_arrow(en, v[n-1] - (n > 1 ? v[n - 2] : strt), aht, lt);
+ out->reset_color();
}
line_object::~line_object()
@@ -1500,6 +1532,7 @@ void arc_object::print()
{
if (lt.type == line_type::invisible)
return;
+ out->set_color(0, graphic_object::get_outline_color());
if (clockwise)
out->arc(en, cent, strt, lt);
else
@@ -1516,6 +1549,7 @@ void arc_object::print()
(clockwise ? position(e.y, -e.x) : position(-e.y, e.x)),
aht, lt);
}
+ out->reset_color();
}
inline double max(double a, double b)
@@ -1708,13 +1742,19 @@ object *object_spec::make_object(position *curpos, direction *dirp)
else
lookup_variable("linethick", &th);
obj->set_thickness(th);
+ if (flags & IS_OUTLINED)
+ obj->set_outline_color(outlined);
if (flags & (IS_DEFAULT_FILLED|IS_FILLED)) {
- if (flags & IS_DEFAULT_FILLED)
- lookup_variable("fillval", &fill);
- if (fill < 0.0)
- error("bad fill value %1", fill);
- else
- obj->set_fill(fill);
+ if (flags & IS_SHADED)
+ obj->set_fill_color(shaded);
+ else {
+ if (flags & IS_DEFAULT_FILLED)
+ lookup_variable("fillval", &fill);
+ if (fill < 0.0)
+ error("bad fill value %1", fill);
+ else
+ obj->set_fill(fill);
+ }
}
}
return obj;
diff --git a/src/preproc/pic/object.h b/src/preproc/pic/object.h
index 2748e81e..dc6cf57f 100644
--- a/src/preproc/pic/object.h
+++ b/src/preproc/pic/object.h
@@ -150,6 +150,8 @@ const unsigned long HAS_THICKNESS = 01000000;
const unsigned long IS_FILLED = 02000000;
const unsigned long IS_DEFAULT_FILLED = 04000000;
const unsigned long IS_ALIGNED = 010000000;
+const unsigned long IS_SHADED = 020000000;
+const unsigned long IS_OUTLINED = 040000000;
struct segment {
int is_absolute;
@@ -183,6 +185,8 @@ struct object_spec {
double end_chop;
double thickness;
double fill;
+ char *shaded;
+ char *outlined;
direction dir;
segment *segment_list;
position segment_pos;
diff --git a/src/preproc/pic/output.h b/src/preproc/pic/output.h
index ac490db4..a0a8331f 100644
--- a/src/preproc/pic/output.h
+++ b/src/preproc/pic/output.h
@@ -55,8 +55,12 @@ public:
const line_type &, double) = 0;
virtual void rounded_box(const position &, const distance &, double,
const line_type &, double) = 0;
- virtual void command(const char *, const char *, int);
- virtual void set_location(const char *, int);
+ virtual void command(const char *, const char *, int) = 0;
+ virtual void set_location(const char *, int) {}
+ virtual void set_color(char *, char *) = 0;
+ virtual void reset_color() = 0;
+ virtual char *get_last_filled() = 0;
+ virtual char *get_outline_color() = 0;
virtual int supports_filled_polygons();
virtual void begin_block(const position &ll, const position &ur);
virtual void end_block();
diff --git a/src/preproc/pic/pic.man b/src/preproc/pic/pic.man
index ea53074e..e7ca94dd 100644
--- a/src/preproc/pic/pic.man
+++ b/src/preproc/pic/pic.man
@@ -622,14 +622,7 @@ this will produce the arguments formatted according to
.IR format ,
which should be a string as described in
.BR printf (3)
-appropriate for the number of arguments supplied,
-using only the
-.BR e ,
-.BR f ,
-.B g
-or
-.B %
-format characters.
+appropriate for the number of arguments supplied.
.LP
The thickness of the lines used to draw objects is controlled by the
.B linethick
@@ -684,6 +677,30 @@ Any text associated with a filled object will be added after the
object has been filled, so that the text will not be obscured
by the filling.
.LP
+Three additional modifiers are available to specify colored objects:
+.B outline
+sets the color of the outline,
+.B shaded
+the fill color, and
+.B color
+sets both.
+All three keywords expect a suffix specifying the color, for example
+.RS
+.LP
+.B circle shaded """green""" outline """black"""
+.RE
+.LP
+Currently, color support isn't available in \*(tx mode.
+Predefined color names for
+.B groff
+are in the file
+.BR color.tmac ;
+additional colors can be defined with the
+.B .defcolor
+request (see the manual page of
+.BR @g@troff (@MAN1EXT@)
+for more details).
+.LP
Arrow heads will be drawn as solid triangles if the variable
.B arrowhead
is non-zero and either \*(tx mode is enabled or
@@ -872,8 +889,8 @@ Input characters that are illegal for
.B groff
(ie those with
.SM ASCII
-code 0 or between 013 and 037 octal or between 0200 and 0237 octal)
-are rejected even in \*(tx mode.
+code 0, or 013 octal, or between 015 and 037 octal, or between 0200 and 0237
+octal) are rejected even in \*(tx mode.
.LP
The interpretation of
.B fillval
diff --git a/src/preproc/pic/pic.y b/src/preproc/pic/pic.y
index a02e7269..d3eccae7 100644
--- a/src/preproc/pic/pic.y
+++ b/src/preproc/pic/pic.y
@@ -210,6 +210,9 @@ char *do_sprintf(const char *form, const double *v, int nv);
%token PLOT
%token THICKNESS
%token FILL
+%token COLORED
+%token OUTLINED
+%token SHADED
%token ALIGNED
%token SPRINTF
%token COMMAND
@@ -231,7 +234,7 @@ box "foo" above ljust == box ("foo" above ljust)
/* Give attributes that take an optional expression a higher
precedence than left and right, so that eg `line chop left'
parses properly. */
-%left CHOP SOLID DASHED DOTTED UP DOWN FILL
+%left CHOP SOLID DASHED DOTTED UP DOWN FILL COLORED OUTLINED
%left LABEL
%left VARIABLE NUMBER '(' SIN COS ATAN2 LOG EXP SQRT K_MAX K_MIN INT RAND SRAND LAST
@@ -350,7 +353,7 @@ placeless_element:
{
fprintf(stderr, "%s\n", $2.str);
a_delete $2.str;
- fflush(stderr);
+ fflush(stderr);
}
| SH
{ delim_flag = 1; }
@@ -888,6 +891,29 @@ object_spec:
$$->flags |= IS_FILLED;
$$->fill = $3;
}
+ | object_spec SHADED text
+ {
+ $$ = $1;
+ $$->flags |= (IS_SHADED | IS_FILLED);
+ $$->shaded = new char[strlen($3.str)+1];
+ strcpy($$->shaded, $3.str);
+ }
+ | object_spec COLORED text
+ {
+ $$ = $1;
+ $$->flags |= (IS_SHADED | IS_OUTLINED | IS_FILLED);
+ $$->shaded = new char[strlen($3.str)+1];
+ strcpy($$->shaded, $3.str);
+ $$->outlined = new char[strlen($3.str)+1];
+ strcpy($$->outlined, $3.str);
+ }
+ | object_spec OUTLINED text
+ {
+ $$ = $1;
+ $$->flags |= IS_OUTLINED;
+ $$->outlined = new char[strlen($3.str)+1];
+ strcpy($$->outlined, $3.str);
+ }
| object_spec CHOP
{
$$ = $1;
@@ -1176,7 +1202,7 @@ ordinal:
;
optional_ordinal_last:
- LAST
+ LAST
{ $$ = 1; }
| ordinal LAST
{ $$ = $1; }
@@ -1777,7 +1803,7 @@ char *do_sprintf(const char *form, const double *v, int nv)
one_format += *form++;
one_format += '\0';
snprintf(sprintf_buf, sizeof(sprintf_buf),
- "%s", one_format.contents());
+ "%s", one_format.contents());
}
else {
if (i >= nv) {
@@ -1789,7 +1815,7 @@ char *do_sprintf(const char *form, const double *v, int nv)
one_format += *form++;
one_format += '\0';
snprintf(sprintf_buf, sizeof(sprintf_buf),
- one_format.contents(), v[i++]);
+ one_format.contents(), v[i++]);
}
one_format.clear();
result += sprintf_buf;
diff --git a/src/preproc/pic/tex.cc b/src/preproc/pic/tex.cc
index 2a91b621..a9192acd 100644
--- a/src/preproc/pic/tex.cc
+++ b/src/preproc/pic/tex.cc
@@ -42,6 +42,10 @@ public:
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);
+ void set_color(char *, char *);
+ void reset_color();
+ char *get_last_filled();
+ char *get_outline_color();
int supports_filled_polygons();
private:
position upper_left;
@@ -350,6 +354,28 @@ void tex_output::dot(const position &pos, const line_type &lt)
}
}
+void tex_output::set_color(char *, char *)
+{
+ /* not implemented yet */
+}
+
+void tex_output::reset_color()
+{
+ /* not implemented yet */
+}
+
+char *tex_output::get_last_filled()
+{
+ /* not implemented yet */
+ return NULL;
+}
+
+char *tex_output::get_outline_color()
+{
+ /* not implemented yet */
+ return NULL;
+}
+
class tpic_output : public tex_output {
public:
tpic_output();
diff --git a/src/preproc/pic/troff.cc b/src/preproc/pic/troff.cc
index 62fe540a..7bd878c2 100644
--- a/src/preproc/pic/troff.cc
+++ b/src/preproc/pic/troff.cc
@@ -37,6 +37,9 @@ class simple_output : public common_output {
virtual void simple_polygon(int, const position *, int) = 0;
virtual void line_thickness(double) = 0;
virtual void set_fill(double) = 0;
+ virtual void set_color(char *, char *) = 0;
+ virtual void reset_color() = 0;
+ virtual char *get_last_filled() = 0;
void dot(const position &, const line_type &) = 0;
public:
void start_picture(double sc, const position &ll, const position &ur) = 0;
@@ -140,11 +143,10 @@ void simple_output::spline(const position &start, const position *v, int n,
void simple_output::polygon(const position *v, int n,
const line_type &lt, double fill)
{
- if (driver_extension_flag) {
- if (fill >= 0.0) {
+ if (driver_extension_flag && ((fill >= 0.0) || (get_last_filled() != 0))) {
+ if (get_last_filled() == 0)
set_fill(fill);
- simple_polygon(1, v, n);
- }
+ simple_polygon(1, v, n);
}
if (lt.type == line_type::solid && driver_extension_flag) {
line_thickness(lt.thickness);
@@ -159,8 +161,9 @@ void simple_output::polygon(const position *v, int n,
void simple_output::circle(const position &cent, double rad,
const line_type &lt, double fill)
{
- if (driver_extension_flag && fill >= 0.0) {
- set_fill(fill);
+ if (driver_extension_flag && ((fill >= 0.0) || (get_last_filled() != 0))) {
+ if (get_last_filled() == 0)
+ set_fill(fill);
simple_circle(1, cent, rad);
}
line_thickness(lt.thickness);
@@ -184,8 +187,9 @@ void simple_output::circle(const position &cent, double rad,
void simple_output::ellipse(const position &cent, const distance &dim,
const line_type &lt, double fill)
{
- if (driver_extension_flag && fill >= 0.0) {
- set_fill(fill);
+ if (driver_extension_flag && ((fill >= 0.0) || (get_last_filled() != 0))) {
+ if (get_last_filled() == 0)
+ set_fill(fill);
simple_ellipse(1, cent, dim);
}
if (lt.type != line_type::invisible)
@@ -212,6 +216,8 @@ class troff_output : public simple_output {
double scale;
double last_line_thickness;
double last_fill;
+ char *last_filled; // color
+ char *last_outlined; // color
public:
troff_output();
~troff_output();
@@ -229,6 +235,10 @@ public:
void simple_polygon(int, const position *, int);
void line_thickness(double p);
void set_fill(double);
+ void set_color(char *, char *);
+ void reset_color();
+ char *get_last_filled();
+ char *get_outline_color();
position transform(const position &);
};
@@ -238,7 +248,8 @@ output *make_troff_output()
}
troff_output::troff_output()
-: last_filename(0), last_line_thickness(BAD_THICKNESS), last_fill(-1.0)
+: last_filename(0), last_line_thickness(BAD_THICKNESS),
+ last_fill(-1.0), last_filled(0), last_outlined(0)
{
}
@@ -288,6 +299,7 @@ void troff_output::finish_picture()
{
line_thickness(BAD_THICKNESS);
last_fill = -1.0; // force it to be reset for each picture
+ reset_color();
if (!flyback_flag)
printf(".sp %.3fi+1\n", height);
printf(".if \\n(" FILL_REG " .fi\n");
@@ -472,6 +484,54 @@ void troff_output::set_fill(double f)
printf("\\D'f %du'\\h'%du'\n.sp -1\n", int(f*FILL_MAX), -int(f*FILL_MAX));
last_fill = f;
}
+ if (last_filled) {
+ free(last_filled);
+ last_filled = 0;
+ printf("\\MP\n.sp -1\n");
+ }
+}
+
+void troff_output::set_color(char *color_fill, char *color_outlined)
+{
+ if (driver_extension_flag) {
+ if (last_filled || last_outlined) {
+ reset_color();
+ }
+ if (color_fill) {
+ printf("\\M[%s]\n.sp -1\n", color_fill);
+ last_filled = strdup(color_fill);
+ }
+ if (color_outlined) {
+ printf("\\m[%s]\n.sp -1\n", color_outlined);
+ last_outlined = strdup(color_outlined);
+ }
+ }
+}
+
+void troff_output::reset_color()
+{
+ if (driver_extension_flag) {
+ if (last_filled) {
+ printf("\\MP\n.sp -1\n");
+ free(last_filled);
+ last_filled = 0;
+ }
+ if (last_outlined) {
+ printf("\\mP\n.sp -1\n");
+ free(last_outlined);
+ last_outlined = 0;
+ }
+ }
+}
+
+char *troff_output::get_last_filled()
+{
+ return last_filled;
+}
+
+char *troff_output::get_outline_color()
+{
+ return last_outlined;
}
const double DOT_AXIS = .044;