diff options
Diffstat (limited to 'src/preproc/pic')
-rw-r--r-- | src/preproc/pic/common.cc | 1 | ||||
-rw-r--r-- | src/preproc/pic/common.h | 4 | ||||
-rw-r--r-- | src/preproc/pic/lex.cc | 7 | ||||
-rw-r--r-- | src/preproc/pic/object.cc | 80 | ||||
-rw-r--r-- | src/preproc/pic/object.h | 4 | ||||
-rw-r--r-- | src/preproc/pic/output.h | 8 | ||||
-rw-r--r-- | src/preproc/pic/pic.man | 37 | ||||
-rw-r--r-- | src/preproc/pic/pic.y | 36 | ||||
-rw-r--r-- | src/preproc/pic/tex.cc | 26 | ||||
-rw-r--r-- | src/preproc/pic/troff.cc | 78 |
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 ¢, const distance &dim, double rad, const line_type <) 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 ¢, 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 <) } } +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 <, 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 ¢, double rad, const line_type <, 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 ¢, double rad, void simple_output::ellipse(const position ¢, const distance &dim, const line_type <, 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; |