summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwlemb <wlemb>2001-10-05 14:12:09 +0000
committerwlemb <wlemb>2001-10-05 14:12:09 +0000
commitd2b33439cf213ab60d62d6fe68b9cc9dead41995 (patch)
treef5758f60a78e70aa77063686652b32ff66381a3c
parentaaef8f141239e392a0caa5f7937e377c97fe4a94 (diff)
downloadgroff-d2b33439cf213ab60d62d6fe68b9cc9dead41995.tar.gz
Implementing color support in troff, pic, grops, and grohtml. These
changes are based on a major patch provided by Gaius Mulley <gaius@glam.ac.uk>. New request: `defcolor', supporting rgb, cmy, cmyk, and gray definitions with both hex values and fractions. New escapes: \m and \M for drawing and background color, respectively. This corresponds to the troff output commands `m' and `DF'. groff and troff accept command line switch `-c' to disable color output (which is automatically disabled in compatibility mode). New scaling indicator `f' for fractions (1f = 65536u). New conditional operator `m' to test for defined colors with `if' and `ie'. New keywords `color' (or `colour', `colored', `coloured'), `outline' (or `outlined'), and `shaded' added to pic. * src/include/color.h: New file. * src/include/driver.h: Include it. * src/include/printer.h: Include color.h. (environment): New members `col' and `fill'. (printer): Remove `adjust_arc_center' member function. * src/include/Makefile.sub: Updated. * src/libs/libdriver/input.cc (do_file): Initialize `env.col' and `env.fill'. Handle `m' and `DF' troff commands. * src/libs/libgroff/color.cc: New file. * src/libs/libgroff/Makefile.sub: Updated. * src/preproc/html/pre-html.cc (IMAGE_BORDER_PIXELS): Set to 2. (stop): Removed. (createImage): Fix computation of `y2'. Use `pnmcrop' also. (buffer::write_file_html): Remove calls to `stop'. * src/preproc/pic/common.h (common_output): New abstract function members `set_color', `reset_color', `get_last_filled', and `get_outline_color'. * src/preproc/pic/object.h: Add `IS_SHADED' and `IS_OUTLINED'. (object_spec): Add members `shaded' and `outlined'. * src/preproc/pic/output.h (output): `command' is now abstract. New function members `set_color', `reset_color', `get_last_filled', and `get_outline_color'. * src/preproc/pic/lex.cc (lookup_keyword): Recognize `colo[u]r[ed]', `outline[d]', and `shaded'. * src/preproc/pic/object.cc (output::command): Removed. (output::set_location):Moved to output.h. (graphic_object): Add protected members `outline_color' and `color_fill'. Add member functions `set_outline_color', `get_outline_color', and `set_fill_color'. (closed_object): Add member function `set_fill_color'. Add member `color_fill'. (graphic_object::print_text): Use `out->set_color' and `out->reset_color'. (box_object::print, ellipse_object::print, circle_object::print, line_object::print, spline_object::print, arc_object::print): Ditto. (object_spec::make_object): Implement `IS_OUTLINED' and `IS_SHADED'. * src/preproc/pic/pic.y: Add tokens `COLORED', `OUTLINED', and `SHADED', making them `%left'. Add rules `object_spec [SHADED|COLORED|OUTLINED] text'. * src/preproc/pic/tex.cc (tex_output): New dummy function members `set_color', `reset_color', `get_last_filled', and `get_outline_color'. * src/preproc/pic/troff.cc (simple_output): New abstract function members `set_color', `reset_color', and `get_last_filled'. (simple_output::polygon, simple_output::circle, simple_output::ellipse): Use `get_last_filled'. (troff_output): New members `last_filled' and `last_outlined'. New function members `set_color', `reset_color', `get_last_filled', and `get_outline_color'. (troff_output::finish_picture): Use `reset_color'. (troff_output::set_fill): Test `last_filled'. * src/preproc/pic/pic.man: Updated. * src/roff/groff/groff.cc (main): Implement `-c' option. (synopsis, help): Updated. src/roff/groff/groff.man: Updated. * src/roff/troff/troff.h: Include color.h. (warning_type): Add WARN_COLOR. * src/roff/troff/env.h (environment): New members `{cur,prev}_{glyph,fill}_color'. New member functions `get_{prev_,}{glyph,fill}_color'. * src/roff/troff/env.cc: Initialize and implement them. * src/roff/troff/input.cc: New global variable `disable_color_flag'. Replace `NULL' with `0' everywhere for consistency. (lookup_color, default_black, do_glyph_color, do_fill_color, get_color_element, read_rgb, read_cmy, read_cmyk, read_gray, define_color): New functions. (token::next): Implement \M and \m escapes. (do_if_request): Implement `m' operator. (usage): Updated. (main): Implement `-c' option. (init_markup_requests): Add `defcolor' request. (warning_table): Add `color' warning. * src/roff/troff/node.h (glyph_color_node, fill_color_node): New classes. * src/roff/troff/node.cc (troff_output_file): New members `current_{page,glyph}color'. New member functions `put_hex', `glyph_color', and `fill_color'. (glyph_color_node::*, fill_color_node::*): Implement it. * src/roff/troff/number.cc (SCALE_INDICATOR_CHARS): Add `f'. (parse_term): Add support for `f'. * src/roff/troff/troff.man: Updated. * src/devices/grodvi/dvi.cc (draw_dvi_printer::draw): Add dummy entry for `F'. * src/devices/grolbp/lbp.cc (lbp_printer::draw): Ditto. * src/devices/grolj4/lj4.cc (lj4_printer::draw): Ditto. * src/devices/grohtml/html-text.h (HTML_TAG): Add COLOR_TAG. (tag_definition): Use `void *' for arg1. (html_text): New member functions `do_color' and `done_color'. Use `void *' for second parameter of `push_para' member function. New `push_para' member function with a single parameter. Use `char *' for parameter of `issue_table_begin' member funtion. New `issue_color_begin' member function. * src/devices/grohtml/html-text.cc (html_text::end_tag): Handle COLOR_TAG. (html_text::issue_color_begin): New function. (html_text::issue_table_begin): Use `char *' for parameter. (html_text::start_tag, html_text::shutdown, html_text::check_emit_text): Updated. (html_text::push_para): Use `void *' for second parameter. Add same function with only one parameter. (html_text::do_*): Updated. (html_text::do_color, html_text::done_color): New functions. * src/devices/grohtml/post-html.cc (style): New member `col'. Mew member `style' with 6 parameters. (style::style, style::operator==): Updated. (html_printer::do_font): Use it. (html_printer::draw): Add dummy entry for `F'. (html_printer::set_char): Updated. * src/devices/grohtml/grohtml.man: Updated. * src/devices/grops/ps.cc (ps_output::put_float): Use `%g' to have trailing zeroes removed. (ps_printer): New members `sbuf_color', `fill_color', and `output_color'. Removed member `fill'. New member function `set_color'. (ps_printer::ps_printer, ps_printer::set_char): Updated. (ps_printer::flush_sbuf, ps_printer::set_line_thickness, ps_printer::fill_path, ps_printer::draw): Use `set_color'. * tmac/color-html.tmac, tmac/color.tmac: New files. * tmac/troffrc: Include them. * tmac/www.tmac (URL, FTP, MAILTO): Use blue color. * tmac/Makefile.sub: Updated. * NEWS, doc/groff.texinfo, doc/pic.ms, man/groff_out.man, man/groff.man: Updated. * font/devps/prologue.ps: Define FC and CO functions. Fix incorrect cropping of images and incorrect handling of special characters. Fix handling of file names in \O. * src/include/geometry.h: New file. * src/libs/libgroff/geometry.cc: New file. * src/libs/libdriver/printer.cc (printer::adjust_arc_center): Moved to `geometry.cc'. * src/roff/troff/input.cc (get_delim_file_name): Fixed problem with initial spaces. (do_suppress): Updated. * src/roff/troff/node.cc: Include geometry.h. (troff_output_file::flush_tbuf): Fixed parameters to `check_output_limits'. (troff_output_file::check_charinfo): Ditto. (troff_output_file::determine_line_limits): Add support for `Da' and `Dl' commands. * src/devices/grohtml/post-html.cc (str_translate_to_html): Add new parameter `is_special' to decode special characters from escape sequences. (html_printer::do_title, html_printer::do_heading, html_printer::do_indentedparagraph, html_printer::translate_to_html, html_printer::special): Updated. * Makefile.sub (DISTCLEANFILES): Add stamp-h. Fix entry for config.h. * test-groff (GROFF_BIN_PATH): Add $builddir/roff/groff. * tmac/troffrc: Translate nonbreakable space character to `\~'. * src/preproc/eqn/eqn.man: Document -d command line option.
-rw-r--r--ChangeLog197
-rw-r--r--Makefile.sub10
-rw-r--r--NEWS53
-rw-r--r--doc/groff.texinfo111
-rw-r--r--doc/pic.ms49
-rw-r--r--font/devps/prologue.ps8
-rw-r--r--man/groff.man44
-rw-r--r--man/groff_out.man44
-rw-r--r--src/devices/grodvi/dvi.cc3
-rw-r--r--src/devices/grohtml/grohtml.man28
-rw-r--r--src/devices/grohtml/html-text.cc101
-rw-r--r--src/devices/grohtml/html-text.h13
-rw-r--r--src/devices/grohtml/post-html.cc131
-rw-r--r--src/devices/grolbp/lbp.cc3
-rw-r--r--src/devices/grolj4/lj4.cc3
-rw-r--r--src/devices/grops/ps.cc168
-rw-r--r--src/include/Makefile.sub2
-rw-r--r--src/include/driver.h1
-rw-r--r--src/include/printer.h5
-rw-r--r--src/libs/libdriver/input.cc49
-rw-r--r--src/libs/libdriver/printer.cc70
-rw-r--r--src/libs/libgroff/Makefile.sub4
-rw-r--r--src/libs/libgroff/font.cc2
-rw-r--r--src/preproc/eqn/eqn.man12
-rw-r--r--src/preproc/html/pre-html.cc10
-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
-rw-r--r--src/roff/groff/groff.cc8
-rw-r--r--src/roff/groff/groff.man4
-rw-r--r--src/roff/troff/dictionary.cc2
-rw-r--r--src/roff/troff/div.cc2
-rw-r--r--src/roff/troff/env.cc52
-rw-r--r--src/roff/troff/env.h10
-rw-r--r--src/roff/troff/input.cc420
-rw-r--r--src/roff/troff/node.cc170
-rw-r--r--src/roff/troff/node.h28
-rw-r--r--src/roff/troff/number.cc5
-rw-r--r--src/roff/troff/troff.h7
-rw-r--r--src/roff/troff/troff.man90
-rw-r--r--test-groff1
-rw-r--r--tmac/Makefile.sub3
-rw-r--r--tmac/troffrc14
-rw-r--r--tmac/troffrc-end10
-rw-r--r--tmac/www.tmac8
52 files changed, 1771 insertions, 465 deletions
diff --git a/ChangeLog b/ChangeLog
index 8ab7347e..1a115563 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,200 @@
+2001-10-04 Werner LEMBERG <wl@gnu.org>
+
+ Implementing color support in troff, pic, grops, and grohtml. These
+ changes are based on a major patch provided by Gaius Mulley
+ <gaius@glam.ac.uk>.
+
+ New request: `defcolor', supporting rgb, cmy, cmyk, and gray
+ definitions with both hex values and fractions.
+
+ New escapes: \m and \M for drawing and background color,
+ respectively. This corresponds to the troff output commands `m'
+ and `DF'.
+
+ groff and troff accept command line switch `-c' to disable color
+ output (which is automatically disabled in compatibility mode).
+
+ New scaling indicator `f' for fractions (1f = 65536u).
+
+ New conditional operator `m' to test for defined colors with `if'
+ and `ie'.
+
+ New keywords `color' (or `colour', `colored', `coloured'), `outline'
+ (or `outlined'), and `shaded' added to pic.
+
+ * src/include/color.h: New file.
+ * src/include/driver.h: Include it.
+ * src/include/printer.h: Include color.h.
+ (environment): New members `col' and `fill'.
+ (printer): Remove `adjust_arc_center' member function.
+ * src/include/Makefile.sub: Updated.
+
+ * src/libs/libdriver/input.cc (do_file): Initialize `env.col' and
+ `env.fill'.
+ Handle `m' and `DF' troff commands.
+ * src/libs/libgroff/color.cc: New file.
+ * src/libs/libgroff/Makefile.sub: Updated.
+
+ * src/preproc/html/pre-html.cc (IMAGE_BORDER_PIXELS): Set to 2.
+ (stop): Removed.
+ (createImage): Fix computation of `y2'.
+ Use `pnmcrop' also.
+ (buffer::write_file_html): Remove calls to `stop'.
+
+ * src/preproc/pic/common.h (common_output): New abstract function
+ members `set_color', `reset_color', `get_last_filled', and
+ `get_outline_color'.
+ * src/preproc/pic/object.h: Add `IS_SHADED' and `IS_OUTLINED'.
+ (object_spec): Add members `shaded' and `outlined'.
+ * src/preproc/pic/output.h (output): `command' is now abstract.
+ New function members `set_color', `reset_color', `get_last_filled',
+ and `get_outline_color'.
+ * src/preproc/pic/lex.cc (lookup_keyword): Recognize `colo[u]r[ed]',
+ `outline[d]', and `shaded'.
+ * src/preproc/pic/object.cc (output::command): Removed.
+ (output::set_location): Moved to output.h.
+ (graphic_object): Add protected members `outline_color' and
+ `color_fill'.
+ Add member functions `set_outline_color', `get_outline_color', and
+ `set_fill_color'.
+ (closed_object): Add member function `set_fill_color'.
+ Add member `color_fill'.
+ (graphic_object::print_text): Use `out->set_color' and
+ `out->reset_color'.
+ (box_object::print, ellipse_object::print, circle_object::print,
+ line_object::print, spline_object::print, arc_object::print): Ditto.
+ (object_spec::make_object): Implement `IS_OUTLINED' and `IS_SHADED'.
+ * src/preproc/pic/pic.y: Add tokens `COLORED', `OUTLINED', and
+ `SHADED', making them `%left'.
+ Add rules `object_spec [SHADED|COLORED|OUTLINED] text'.
+ * src/preproc/pic/tex.cc (tex_output): New dummy function members
+ `set_color', `reset_color', `get_last_filled', and
+ `get_outline_color'.
+ * src/preproc/pic/troff.cc (simple_output): New abstract function
+ members `set_color', `reset_color', and `get_last_filled'.
+ (simple_output::polygon, simple_output::circle,
+ simple_output::ellipse): Use `get_last_filled'.
+ (troff_output): New members `last_filled' and `last_outlined'.
+ New function members `set_color', `reset_color', `get_last_filled',
+ and `get_outline_color'.
+ (troff_output::finish_picture): Use `reset_color'.
+ (troff_output::set_fill): Test `last_filled'.
+ * src/preproc/pic/pic.man: Updated.
+
+ * src/roff/groff/groff.cc (main): Implement `-c' option.
+ (synopsis, help): Updated.
+ src/roff/groff/groff.man: Updated.
+
+ * src/roff/troff/troff.h: Include color.h.
+ (warning_type): Add WARN_COLOR.
+ * src/roff/troff/env.h (environment): New members
+ `{cur,prev}_{glyph,fill}_color'.
+ New member functions `get_{prev_,}{glyph,fill}_color'.
+ * src/roff/troff/env.cc: Initialize and implement them.
+ * src/roff/troff/input.cc: New global variable `disable_color_flag'.
+ Replace `NULL' with `0' everywhere for consistency.
+ (lookup_color, default_black, do_glyph_color, do_fill_color,
+ get_color_element, read_rgb, read_cmy, read_cmyk, read_gray,
+ define_color): New functions.
+ (token::next): Implement \M and \m escapes.
+ (do_if_request): Implement `m' operator.
+ (usage): Updated.
+ (main): Implement `-c' option.
+ (init_markup_requests): Add `defcolor' request.
+ (warning_table): Add `color' warning.
+ * src/roff/troff/node.h (glyph_color_node, fill_color_node): New
+ classes.
+ * src/roff/troff/node.cc (troff_output_file): New members
+ `current_{page,glyph}color'. New member functions `put_hex',
+ `glyph_color', and `fill_color'.
+ (glyph_color_node::*, fill_color_node::*): Implement it.
+ * src/roff/troff/number.cc (SCALE_INDICATOR_CHARS): Add `f'.
+ (parse_term): Add support for `f'.
+ * src/roff/troff/troff.man: Updated.
+
+ * src/devices/grodvi/dvi.cc (draw_dvi_printer::draw): Add dummy
+ entry for `F'.
+ * src/devices/grolbp/lbp.cc (lbp_printer::draw): Ditto.
+ * src/devices/grolj4/lj4.cc (lj4_printer::draw): Ditto.
+
+ * src/devices/grohtml/html-text.h (HTML_TAG): Add COLOR_TAG.
+ (tag_definition): Use `void *' for arg1.
+ (html_text): New member functions `do_color' and `done_color'.
+ Use `void *' for second parameter of `push_para' member function.
+ New `push_para' member function with a single parameter.
+ Use `char *' for parameter of `issue_table_begin' member funtion.
+ New `issue_color_begin' member function.
+ * src/devices/grohtml/html-text.cc (html_text::end_tag): Handle
+ COLOR_TAG.
+ (html_text::issue_color_begin): New function.
+ (html_text::issue_table_begin): Use `char *' for parameter.
+ (html_text::start_tag, html_text::shutdown,
+ html_text::check_emit_text): Updated.
+ (html_text::push_para): Use `void *' for second parameter.
+ Add same function with only one parameter.
+ (html_text::do_*): Updated.
+ (html_text::do_color, html_text::done_color): New functions.
+ * src/devices/grohtml/post-html.cc (style): New member `col'.
+ Mew member `style' with 6 parameters.
+ (style::style, style::operator==): Updated.
+ (html_printer::do_font): Use it.
+ (html_printer::draw): Add dummy entry for `F'.
+ (html_printer::set_char): Updated.
+ * src/devices/grohtml/grohtml.man: Updated.
+
+ * src/devices/grops/ps.cc (ps_output::put_float): Use `%g' to have
+ trailing zeroes removed.
+ (ps_printer): New members `sbuf_color', `fill_color', and
+ `output_color'.
+ Removed member `fill'.
+ New member function `set_color'.
+ (ps_printer::ps_printer, ps_printer::set_char): Updated.
+ (ps_printer::flush_sbuf, ps_printer::set_line_thickness,
+ ps_printer::fill_path, ps_printer::draw): Use `set_color'.
+
+ * tmac/color-html.tmac, tmac/color.tmac: New files.
+ * tmac/troffrc: Include them.
+ * tmac/www.tmac (URL, FTP, MAILTO): Use blue color.
+ * tmac/Makefile.sub: Updated.
+
+ * NEWS, doc/groff.texinfo, doc/pic.ms, man/groff_out.man,
+ man/groff.man: Updated.
+ * font/devps/prologue.ps: Define FC and CO functions.
+
+2001-10-04 Gaius Mulley <gaius@glam.ac.uk>
+
+ Fix incorrect cropping of images and incorrect handling of special
+ characters. Fix handling of file names in \O.
+
+ * src/include/geometry.h: New file.
+ * src/libs/libgroff/geometry.cc: New file.
+ * src/libs/libdriver/printer.cc (printer::adjust_arc_center): Moved
+ to `geometry.cc'.
+ * src/roff/troff/input.cc (get_delim_file_name): Fixed problem with
+ initial spaces.
+ (do_suppress): Updated.
+ * src/roff/troff/node.cc: Include geometry.h.
+ (troff_output_file::flush_tbuf): Fixed parameters to
+ `check_output_limits'.
+ (troff_output_file::check_charinfo): Ditto.
+ (troff_output_file::determine_line_limits): Add support for `Da'
+ and `Dl' commands.
+
+ * src/devices/grohtml/post-html.cc (str_translate_to_html):
+ Add new parameter `is_special' to decode special characters from
+ escape sequences.
+ (html_printer::do_title, html_printer::do_heading,
+ html_printer::do_indentedparagraph,
+ html_printer::translate_to_html, html_printer::special): Updated.
+
+2001-10-03 Werner LEMBERG <wl@gnu.org>
+
+ * Makefile.sub (DISTCLEANFILES): Add stamp-h.
+ Fix entry for config.h.
+ * test-groff (GROFF_BIN_PATH): Add $builddir/roff/groff.
+ * tmac/troffrc: Translate nonbreakable space character to `\~'.
+ * src/preproc/eqn/eqn.man: Document -d command line option.
+
2001-09-27 Werner LEMBERG <wl@gnu.org>
* man/groff.man: Use
diff --git a/Makefile.sub b/Makefile.sub
index 7ecd5fc9..8dc3c71a 100644
--- a/Makefile.sub
+++ b/Makefile.sub
@@ -1,5 +1,11 @@
-DISTCLEANFILES=config.h config.status config.log config.cache Makefile \
- src/xditview/Imakefile
+DISTCLEANFILES=\
+ config.status \
+ config.log \
+ config.cache \
+ stamp-h \
+ Makefile \
+ src/xditview/Imakefile \
+ src/include/config.h
CLEANADD=Makefile.cfg conftest*
distfiles: configure
diff --git a/NEWS b/NEWS
index d7db05e1..76ad1273 100644
--- a/NEWS
+++ b/NEWS
@@ -1,14 +1,30 @@
This file describes recent user-visible changes in groff. Bug fixes are not
described. There are more details in the man pages.
-VERSION 1.17.3
-==============
-
-This is mainly a bug-fixing release.
+VERSION 1.18
+============
Troff
-----
+o Color support has been added to troff and pic (and to two device drivers,
+ grops and grohtml -- other preprocessors and drivers will follow). A new
+ function `defcolor' defines colors; the escape sequence `\m' sets the
+ drawing color, the escape sequence `\M' specifies the background color for
+ clsed objects created with \D'...' commands. Similar to fonts, `\mP' and
+ `\MP' switch back to the previous color. `\m' and `\M' correspond to the
+ new troff output commands `m' and `DF'.
+
+ Outputting color can be disabled in troff and groff with the option -c
+ (it is always disabled in compatibility mode).
+
+ For defining color components as fractions between 0 and 1, a new scaling
+ indicator `f' has been defined: 1f = 65536u. For testing whether a color
+ is defined (with .if and .ie), a new conditional operator `m' is
+ available.
+
+ More details can be found in the troff manual page.
+
o Two macros `AT' (AT&T) and `UC' (Univ. of California) have been added to
the man macros for compatibility with older BSD releases.
@@ -19,6 +35,23 @@ o The `-xwidth' specifier in the mdoc macro package has been removed. Its
o A new macro `Ex' has been added to the mdoc macro package to document an
exit status.
+groff
+-----
+
+o The new command line `-c' disables color output (which is always disabled
+ in compatibility mode).
+
+pic
+---
+
+o New keywords `color' (or `colour', `colored', `coloured'), `outline' (or
+ `outlined'), and `shaded' are available. `outline' sets the color of the
+ outline, `shaded' the fill color, and `color' sets both. Example:
+
+ circle shaded "green" outline "black" ;
+
+ Color support for TeX output is not implemented yet.
+
Pic2graph
---------
@@ -26,6 +59,16 @@ o A new script contributed by Eric S. Raymond <esr@thyrsus.com>. It
converts a PIC diagram into a cropped image. Since it uses gs and the PNM
library, virtually all graphics formats are available for output.
+grops
+-----
+
+o Color support has been added.
+
+grohtml
+-------
+
+o Color support for glyphs has been added (no fill color support yet).
+
VERSION 1.17.2
==============
@@ -88,7 +131,7 @@ o `-mFOO' now searches first for `FOO.tmac' and then for `tmac.FOO'. The
o The new environment variable GROFF_BIN_PATH is checked for programs groff
is calling (preprocessors, troff, and output devices) before PATH. If not
- set, it defaults to the directory where the groff binary is located.
+ set, it defaults to the directory where the groff binary is located.
Previously, it was PATH only. The nroff script only uses GROFF_BIN_PATH
to find the groff binary but passes both the GROFF_BIN_PATH and PATH
environment variable to groff.
diff --git a/doc/groff.texinfo b/doc/groff.texinfo
index 1255fbcf..3510c216 100644
--- a/doc/groff.texinfo
+++ b/doc/groff.texinfo
@@ -2466,6 +2466,7 @@ Users of macro packages may skip it if not interested in details.
* Diversions::
* Environments::
* Suppressing output::
+* Colors::
* I/O::
* Postprocessor Access::
* Miscellaneous::
@@ -2765,6 +2766,12 @@ Pica. Another typesetting measurement. 6@w{ }Picas to an inch (and
@cindex @code{z} unit
@cindex unit, @code{z}
@xref{Fractional Type Sizes}, for a discussion of these units.
+
+@item f
+@cindex @code{f} unit
+@cindex unit, @code{f}
+Fractions. Value is 65536.
+@xref{Colors}, for usage.
@end table
The other measurements understood by @code{gtroff} depend on
@@ -7012,6 +7019,9 @@ True if there is a number register named @var{xxx}.
@item d @var{xxx}
True if there is a string, macro, diversion, or request named @var{xxx}.
+@item m @var{xxx}
+True if there is a color named @var{xxx}.
+
@item c @var{ch}
True if there is a character @var{ch} available; @var{ch} is either an
@acronym{ASCII} character or a special character (@code{\(@var{ch}} or
@@ -7396,7 +7406,7 @@ The @code{als} request can make a macro have more than one name.
This would be called as
@Example
-.vl $Id: groff.texinfo,v 1.80 2001/09/11 21:40:36 wlemb Exp $
+.vl $Id: groff.texinfo,v 1.81 2001/10/05 14:12:11 wlemb Exp $
@endExample
@endDefesc
@@ -8272,7 +8282,7 @@ Copies the environment @var{env} into the current environment.
@c =====================================================================
-@node Suppressing output, I/O, Environments, gtroff Reference
+@node Suppressing output, Colors, Environments, gtroff Reference
@section Suppressing output
@cindex suppressing output (@code{\O})
@@ -8282,10 +8292,13 @@ Disables or enables output depending on the value of @var{num}:
@table @samp
@item \O0
-Disable any ditroff glyphs from being emitted to the device driver.
+Disable any ditroff glyphs from being emitted to the device driver,
+provided that the escape occurs at the outer level (see @code{\O3} and
+@code{\O4}).
@item \O1
-Enable output of glyphs.
+Enable output of glyphs, provided that the escape occurs at the outer
+level.
@end table
@vindex opminx
@@ -8297,25 +8310,97 @@ Enable output of glyphs.
@xref{Register Index}. These four registers mark the top left and
bottom right hand corners of a box which encompasses all written glyphs.
-The following two forms of @code{\O} are specific to @code{grohtml}.
-
@table @samp
@item \O2
-Disable any ditroff glyphs from being emitted to the device driver. Also
-write out to @code{stderr} the page number and four registers encompassing
-the glyphs previously written since the last call to @code{\O}.
+Provided that the escape occurs at the outer level, enable output of
+glyphs and also write out to @code{stderr} the page number and four
+registers encompassing the glyphs previously written since the last call
+to @code{\O}.
@item \O3
-Enable output of glyphs (the default). Also write out to @code{stderr}
-the page number and four registers encompassing the glyphs previously
-written since the last call to @code{\O}.
+Begin a nesting level.
+
+@item \O4
+End a nesting level.
+
+@item \O[5 filename]
+This escape is @code{grohtml} specific. Provided that this escape
+occurs at the outer nesting level write the filename to @code{stderr}.
+This filename will be associated with the production of the next inline
+image.
@end table
@endDefesc
@c =====================================================================
-@node I/O, Postprocessor Access, Suppressing output, gtroff Reference
+@node Colors, I/O, Suppressing output, gtroff Reference
+@section Colors
+
+@Defreq {defcolor, ident scheme color_components}
+Define color with name @var{ident}. @var{scheme} can be one of the
+following values: @code{rgb} (three components), @code{cym} (three
+components), @code{cmyk} (four components), and @code{gray} or
+@code{grey} (one component).
+
+Color components can be given either as a hexadecimal string or as
+positive decimal integers in the range 0--65535. A hexadecimal string
+contains all color components concatenated. It must start with either
+@code{#} or @code{##}; the former specifies hex values in the range
+0--255 (which are internally multiplied by@w{ }257), the latter in the
+range 0--65535. Examples: @code{#FFC0CB} (pink), @code{##ffff0000ffff}
+(magenta).
+
+@cindex @code{f} unit, and colors
+@cindex unit, @code{f}, and colors
+
+A new scaling indicator @code{f} has been introduced which multiplies
+its value by 65536; this makes it convenient to specify color components
+as fractions in the range 0 to@w{ }1 (1f equals 65536u). Example:
+
+@Example
+.defcolor darkgreen rgb 0.1f 0.5f 0.2f
+@endExample
+
+Note that @code{f} is the default scaling indicator for the
+@code{defcolor} request, thus the above statement is equivalent to
+
+@Example
+.defcolor darkgreen rgb 0.1 0.5 0.2
+@endExample
+@endDefreq
+
+@Defesc {\\m, , c, }
+@Defescx {\\m, @lparen{}, co, }
+@Defescx {\\m, @lbrack{}, color, @rbrack}
+Set drawing color. The following example shows how to turn the next four
+words red.
+
+@Example
+\m[red]these are in red\mP and these words are in black.
+@endExample
+
+The escape @code{\mP} returns to the previous color.
+@endDefesc
+
+@Defesc {\\M, , c, }
+@Defescx {\\M, @lparen{}, co, }
+@Defescx {\\M, @lbrack{}, color, @rbrack}
+Set background color for filled objects drawn with the
+@code{\D'@dots{}'} commands.
+
+A red ellipse can be created with the following code:
+
+@Example
+\M[red]\h'0.5i'\D'E 2i 1i'\Mp
+@endExample
+
+The escape @code{\MP} returns to the previous fill color.
+@endDefesc
+
+@c =====================================================================
+
+@node I/O, Postprocessor Access, Colors, gtroff Reference
@section I/O
@cindex i/o
@cindex input and output requests
diff --git a/doc/pic.ms b/doc/pic.ms
index 8b7b582d..14bd5413 100644
--- a/doc/pic.ms
+++ b/doc/pic.ms
@@ -10,7 +10,7 @@
.\" This document was written for free use and redistribution by
.\" Eric S. Raymond <esr@thyrsus.com> in August 1995.
.\"
-.\" $Id: pic.ms,v 1.7 2001/08/26 04:41:56 wlemb Exp $
+.\" $Id: pic.ms,v 1.8 2001/10/05 14:12:11 wlemb Exp $
.\"
.\" Set a proper TeX
.ie t .ds tx T\h'-.1667m'\v'.224m'E\v'-.224m'\h'-.125m'X
@@ -355,8 +355,7 @@ box width 3 "this text is far too long for a default box"
.PP
This modifier takes a dimension in inches. There is also a "height"
modifier that will change a box's height. The \fBwidth\fP keyword may
-be abbreviated to \fBewid\fP; the \fBheight\fP keyword to
-\fBheight\fP.
+be abbreviated to \fBwid\fP; the \fBheight\fP keyword to \fBht\fP.
.NH 2
Resizing Other Object Types
.PP
@@ -377,7 +376,7 @@ Ellipses are sized to fit in the rectangular box defined by their
axes, and can be resized with \fBwidth\fP and \fBheight\fP like boxes.
.PP
You can also change the radius of curvature of an arc with \fBrad\fP
-(which specifies the radius of the circle of which the arc is a segnmment).
+(which specifies the radius of the circle of which the arc is a segment).
Larger values yield flatter arcs.
.KS
.PS
@@ -566,7 +565,7 @@ box rad 0.2 "rad=0.2";
move;
box rad 0.25 "rad=0.25";
.PE
-.CE "3: \fBbox rad\fP with increasing radius values;"
+.CE "3: \fBbox rad\fP with increasing radius values"
.PP
Radius values higher than half the minimum box dimension are silently
truncated to that value.
@@ -642,7 +641,7 @@ values are darker; GNU \fBfillval\fP uses 0 for white and 1 for black.
.PS
circle fill; move; circle fill 0.4; move; circle fill 0.2;
.PE
-.CE "5: \fBcircle fill; move; circle fill 0.4; move; circle fill 0.9;\fB"
+.CE "5: \fBcircle fill; move; circle fill 0.4; move; circle fill 0.9;\fR"
.PP
GNU \fBgpic\fP makes some additional guarantees. A fill value greater
than 1 can also be used: this means fill with the shade of gray that
@@ -652,16 +651,37 @@ The invisible attribute does not affect the filling of objects. 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.
.PP
-The closed-object modifier \fBsolid\fR is equivalent to \fBfill\fR
-with the darkest fill value (DWB \fBpic\fR had this capability but
+The closed-object modifier \fBsolid\fP is equivalent to \fBfill\fP
+with the darkest fill value (DWB \fBpic\fP had this capability but
mentioned it only in a reference section).
+.NH 2
+Colored Objects
+.PP
+As a GNU extension, three additional modifiers are available to specify
+colored objects. \fBoutline\fP sets the color of the outline, \fBshaded\fP
+the fill color, and \fBcolor\fP sets both. All three keywords expect a
+suffix specifying the color. Example:
+.KS
+.PS
+box color "yellow"; arrow color "cyan"; circle shaded "green" outline "black";
+.PE
+.CE "6: \fBbox color ""yellow""; arrow color ""cyan""; \
+circle shaded ""green"" outline ""black"";\fR"
+.PP
+Alternative spellings are \fBcolour\fP, \fBcolored\fP, \fBcoloured\fP,
+and \fBoutlined\fP.
+.PP
+Currently, color support is not available in \*(tx mode. Predefined color
+names for \fIgroff\fP(1) are in the file \f(CWcolor.tmac\fP; additional
+colors can be defined with the \f(CW.defcolor\fP request (see the manual
+page of GNU \fItroff\fP(1) for more details).
.NH 1
More About Text Placement
.PP
By default, text is centered at the geometric center of the object it is
-associated with. The modifier \fBljust\fR causes the left end to be
+associated with. The modifier \fBljust\fP causes the left end to be
at the specified point (which means that the text lies to the right of
-the specified place!), The modifier \fBrjust\fP puts the right end at
+the specified place!), the modifier \fBrjust\fP puts the right end at
the place. The modifiers \fBabove\fP and \fBbelow\fP center the text
one half line space in the given direction.
.PP
@@ -746,14 +766,14 @@ in the obvious way:
.PS
box; arrow; circle; down; arrow; ellipse
.PE
-.CE "3: \fBbox; arrow; circle; down; arrow; ellipse\fP
+.CE "3: \fBbox; arrow; circle; down; arrow; ellipse\fP"
.LP
You might have expected that program to yield this:
.KS
.PS
box; arrow; circle; move to last circle .s; down; arrow; ellipse
.PE
-.CE "4: More intuitive?
+.CE "4: More intuitive?"
.LP
But, in fact, to get Figure \*[SN]3 you have to do this:
.KS
@@ -956,7 +976,7 @@ the implied circle.
Locations Relative to Open Objects
.PP
Every open object (line, arrow, arc, or spline) has three named
-points; \fB.start\fP, \fB.center\fP, and \fB.end\fP. They can
+points: \fB.start\fP, \fB.center\fP, and \fB.end\fP. They can
also be used without leading dots in the \fBof\fP prefix form.
The center of an arc is the center of its circle, but the center of
a line, path, or spline is halfway between its endpoints.
@@ -2231,6 +2251,9 @@ on the block's bounding box.
invis \fR# Make primitive invisible\fP
solid \fR# Make closed figure solid\fP
fill <expr> \fR# Set fill density for figure\fP
+ colo[u]r[ed] <word> \fR# Set fill and outline color for figure\fP
+ outline[d] <word> \fR# Set outline color for figure\fP
+ shaded <word> \fR# Set fill color for figure\fP
same \fR# Copy size of previous object\fP
<text> <text> ... \fR# Text within object\fP
<expr> \fR# Motion in the current direction\fR
diff --git a/font/devps/prologue.ps b/font/devps/prologue.ps
index b7bad1c5..d95b8fd2 100644
--- a/font/devps/prologue.ps
+++ b/font/devps/prologue.ps
@@ -154,11 +154,19 @@
currentgray exch setgray fill setgray
} bind def
+% r g b FC -
+
+/FC {
+ setrgbcolor fill
+} bind def
+
% fill with the ``current color''
/BL /fill load def
/LW /setlinewidth load def
+/CO /setrgbcolor load def
+
% new_font_name encoding_vector old_font_name RE -
/RE {
diff --git a/man/groff.man b/man/groff.man
index 1c465e1e..d84a0a0c 100644
--- a/man/groff.man
+++ b/man/groff.man
@@ -636,12 +636,13 @@ Em\ \(eq\ \fRthe font size in points (width of letter `\f(CRm\fR')
T}
M@100th \fRof an \f(CREm
n@En\ \(eq\ Em/2
-u@\fRBasic unit for actual output device
-v@\fRVertical line space in basic units
+u@Basic unit for actual output device
+v@Vertical line space in basic units
z@T{
scaled point\ \(eq\ 1/\f(CIsizescale\fR of a point (defined in
font \fIDESC\fP file)
T}
+f@Scale by 65536.
.TE
.LP
.ev
@@ -731,6 +732,9 @@ called \f(CIname\fP.
T}
e@Current page number is even.
o@Current page number is odd.
+m\f(CIname@T{
+True if there is a color called \f(CIname\fP.
+T}
n@Formatter is \fBnroff\fP.
r\f(CIreg@T{
True if there is a register named \f(CIreg\fP.
@@ -1049,6 +1053,26 @@ Same as
.request .de
but with compatibility mode switched off during macro expansion.
.
+.REQ .defcolor color scheme component
+Define or redefine a color with name
+.argument color .
+.argument scheme
+can be
+.BR rgb ,
+.BR cym ,
+.BR cymk ,
+.BR gray ,
+or
+.BR grey .
+.argument component
+can be single components specified as fractions in the range 0 to 1
+(default scale indicator\ \c
+.scaleindicator f ),
+as a string of two-digit hexadecimal color components with a leading
+.BR # ,
+or as a string of four-digit hexadecimal components with two leading
+.BR # .
+.
.REQ .dei macro
Define or redefine a macro whose name is contained in the string register
.argument macro
@@ -2121,6 +2145,22 @@ Horizontal line drawing function (optionally using character
Vertical line drawing function (optionally using character
.argument c ).
.
+.ESC[] m color
+Change to color
+.argument color .
+Alternative forms
+.esc(arg m co
+and
+.escarg m c .
+.
+.ESC[] M color
+Change filling color for closed drawn objects to color
+.argument color .
+Alternative forms
+.esc(arg M co
+and
+.escarg M c .
+.
.ESC n r
The numerical value stored in the register variable with the 1-character
name
diff --git a/man/groff_out.man b/man/groff_out.man
index 80746cc0..c04967cb 100644
--- a/man/groff_out.man
+++ b/man/groff_out.man
@@ -21,6 +21,13 @@ the original English.
.\" This man page must be preprocessed with eqn.
.ie \n(.g .ds ic \/
.el .ds ic \^
+.
+.de TQ
+.br
+.ns
+.TP \\$1
+..
+.
.TH GROFF_OUT @MAN5EXT@ "@MDATE@" "Groff Version @VERSION@"
.SH NAME
groff_out \- groff intermediate output format
@@ -86,6 +93,32 @@ in the current font.
Unlike device-independent troff, it is not necessary
for drivers to search special fonts to find a character.
.LP
+For color support, a new command has been added:
+.TP
+\fBm \fIr g b\fR
+.TQ
+\fBm #\fIrrggbb\fR
+.TQ
+\fBm ##\fIrrrrggggbbbb\fR
+Set the red, green, and blue components of the current drawing color to
+.IR r ,
+.IR g ,
+and
+.I b
+(to be specified as fractions in the range 0 to 1), or
+.IR rr ,
+.IR gg ,
+and
+.I bb
+(to be specified as hexadecimal values in the range 0 to 0xff), or
+.IR rrrr ,
+.IR gggg ,
+and
+.I bbbb
+(to be specified as hexadecimal values in the range 0 to 0xffff).
+.B troff
+emits only the latest form.
+.LP
The
.B x
device control command has been extended.
@@ -217,6 +250,17 @@ command of the form
the current position should be increased by
$( sum from i=1 to n x sub i , sum from i=1 to n y sub i )$.
.LP
+Another extension is
+.TP
+\fBDF \fIr g b\fR\*(ic\en
+.TQ
+\fBDF #\fIrrggbb\fR\*(ic\en
+.TQ
+\fBDF ##\fIrrrrggggbbbb\fR\*(ic\en
+Set the RGB components of the filling color similar to the
+.B m
+command above.
+.LP
There is a continuation convention which permits the argument to the
.B x\ X
command to contain newlines:
diff --git a/src/devices/grodvi/dvi.cc b/src/devices/grodvi/dvi.cc
index b5b7c49d..9e80b266 100644
--- a/src/devices/grodvi/dvi.cc
+++ b/src/devices/grodvi/dvi.cc
@@ -801,6 +801,9 @@ void draw_dvi_printer::draw(int code, int *p, int np, const environment *env)
fill = FILL_MAX;
break;
}
+ case 'F':
+ // not implemented yet
+ break;
case 'R':
{
if (np != 2) {
diff --git a/src/devices/grohtml/grohtml.man b/src/devices/grohtml/grohtml.man
index 4903070f..7525ae6a 100644
--- a/src/devices/grohtml/grohtml.man
+++ b/src/devices/grohtml/grohtml.man
@@ -36,17 +36,22 @@ grohtml \- html driver for groff
.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
.el .RB "[\ " "\\$1" "\ ]"
..
-.OP \-v?lrn
+.OP \-vlrn
.OP \-D dir
.OP \-F dir
.OP \-i resolution
-.OP \-I image stem
-.OP \-o image vertical offset
+.OP \-I image-stem
+.OP \-o image-vertical-offset
.RI "[\ " files\|.\|.\|. "\ ]"
.br
.ad \na
.SH DESCRIPTION
+The
.B grohtml
+front end (which consists of a preprocessor,
+.BR pre-grohtml ,
+and a device driver,
+.BR post-grohtml )
translates the output of GNU
.B troff
to html.
@@ -76,12 +81,6 @@ using
option.
.SH OPTIONS
.TP
-.B \-v
-Displays the version.
-.TP
-.B \-?
-Emits a usage synopsis.
-.TP
.B -l
Turns off the production of automatic section links at the top of the document.
.TP
@@ -91,7 +90,7 @@ Turns off the automatic header and footer line (html rule).
.B -n
Generate simple heading anchors whenever a section/number heading is found.
Without the option the anchor value is the textual heading.
-This can cause problems when a heading contains a `?' on some brousers
+This can cause problems when a heading contains a `?' on some browsers
(netscape).
This flag is automatically turned on if a heading contains an image.
.TP
@@ -115,6 +114,9 @@ If omitted grohtml uses
.RI ( XXX
is the process ID).
.TP
+.BI \-o vertical-offset
+Specify the vertical offset of images in points.
+.TP
.BI \-D dir
Inform
.B grohtml
@@ -123,9 +125,7 @@ to place all image files into directory
.TP
.B \-v
Print the version number.
-.TP
-.B \-?
-Display usage.
+.
.SH USAGE
There are styles called
.BR R ,
@@ -137,7 +137,7 @@ mounted at font positions 1 to 4.
.SH DEPENDENCIES
.B grohtml
is dependent upon the png utilities
-.RB ( \&\%pnmcut ,\ \%pnmtopng )
+.RB ( \&\%pnmcut ,\ \%pnmcrop ,\ \%pnmtopng )
and GhostScript
.RB ( gs ).
.B \%pnmtopng
diff --git a/src/devices/grohtml/html-text.cc b/src/devices/grohtml/html-text.cc
index 56d6c78d..f0c6dcd2 100644
--- a/src/devices/grohtml/html-text.cc
+++ b/src/devices/grohtml/html-text.cc
@@ -75,6 +75,7 @@ void html_text::end_tag (tag_definition *t)
case SMALL_TAG: out->put_string("</small>"); break;
case BIG_TAG: out->put_string("</big>"); break;
case TABLE_TAG: issue_table_end(); break;
+ case COLOR_TAG: out->put_string("</font>"); break;
default:
error("unrecognised tag");
@@ -99,6 +100,25 @@ void html_text::issue_tag (char *tagname, char *arg)
}
/*
+ * issue_color_begin - writes out an html color tag.
+ */
+
+void html_text::issue_color_begin (color *c)
+{
+ double r, g, b;
+ char buf[6+1];
+
+ out->put_string("<font color=\"#");
+ c->get_rgb(&r, &g, &b);
+ sprintf(buf, "%.2X%.2X%.2X",
+ (unsigned int)(((double) 0xff)*r),
+ (unsigned int)(((double) 0xff)*g),
+ (unsigned int)(((double) 0xff)*b));
+ out->put_string(buf);
+ out->put_string("\">");
+}
+
+/*
* start_tag - starts a tag.
*/
@@ -106,19 +126,20 @@ void html_text::start_tag (tag_definition *t)
{
switch (t->type) {
- case I_TAG: issue_tag("<i", t->arg1); break;
- case B_TAG: issue_tag("<b", t->arg1); break;
- case P_TAG: issue_tag("\n<p", t->arg1);
+ case I_TAG: issue_tag("<i", (char *)t->arg1); break;
+ case B_TAG: issue_tag("<b", (char *)t->arg1); break;
+ case P_TAG: issue_tag("\n<p", (char *)t->arg1);
out->enable_newlines(TRUE); break;
- case SUB_TAG: issue_tag("<sub", t->arg1); break;
- case SUP_TAG: issue_tag("<sup", t->arg1); break;
- case TT_TAG: issue_tag("<tt", t->arg1); break;
- case PRE_TAG: out->nl(); issue_tag("<pre", t->arg1);
+ case SUB_TAG: issue_tag("<sub", (char *)t->arg1); break;
+ case SUP_TAG: issue_tag("<sup", (char *)t->arg1); break;
+ case TT_TAG: issue_tag("<tt", (char *)t->arg1); break;
+ case PRE_TAG: out->nl(); issue_tag("<pre", (char *)t->arg1);
out->enable_newlines(FALSE); break;
- case SMALL_TAG: issue_tag("<small", t->arg1); break;
- case BIG_TAG: issue_tag("<big", t->arg1); break;
- case TABLE_TAG: issue_table_begin(t); break;
+ case SMALL_TAG: issue_tag("<small", (char *)t->arg1); break;
+ case BIG_TAG: issue_tag("<big", (char *)t->arg1); break;
+ case TABLE_TAG: issue_table_begin((char *)t->arg1); break;
case BREAK_TAG: break;
+ case COLOR_TAG: issue_color_begin((color *)t->arg1); break;
default:
error("unrecognised tag");
@@ -134,7 +155,7 @@ int html_text::table_is_void (tag_definition *t)
}
}
-void html_text::issue_table_begin (tag_definition *t)
+void html_text::issue_table_begin (char *arg)
{
if (linelength > 0) {
int width=current_indentation*100/linelength;
@@ -142,12 +163,12 @@ void html_text::issue_table_begin (tag_definition *t)
if (width > 0) {
out->put_string("<table width=\"100%\" border=0 rules=\"none\" frame=\"void\"\n cols=\"2\" cellspacing=\"0\" cellpadding=\"0\">").nl();
out->put_string("<tr valign=\"top\" align=\"left\">").nl();
- if ((t->arg1 == 0) || (strcmp(t->arg1, "") == 0))
+ if ((arg == 0) || (strcmp(arg, "") == 0))
out->put_string("<td width=\"").put_number(width).put_string("%\"></td>");
else {
out->put_string("<td width=\"").put_number(width).put_string("%\">").nl();
- out->put_string(t->arg1).put_string("</td>");
- t->arg1[0] = (char)0;
+ out->put_string(arg).put_string("</td>");
+ arg[0] = (char)0;
}
out->put_string("<td width=\"").put_number(100-width).put_string("%\">").nl();
}
@@ -202,7 +223,7 @@ int html_text::is_present (HTML_TAG t)
* push_para - adds a new entry onto the html paragraph stack.
*/
-void html_text::push_para (HTML_TAG t, char *arg)
+void html_text::push_para (HTML_TAG t, void *arg)
{
tag_definition *p=(tag_definition *)malloc(sizeof(tag_definition));
@@ -257,6 +278,11 @@ void html_text::push_para (HTML_TAG t, char *arg)
}
}
+void html_text::push_para (HTML_TAG t)
+{
+ push_para(t, (void *)"");
+}
+
/*
* do_indent - remember the indent parameters and if
* indent is > pageoff and indent has changed
@@ -311,7 +337,7 @@ void html_text::do_italic (void)
done_bold();
done_tt();
if (! is_present(I_TAG)) {
- push_para(I_TAG, "");
+ push_para(I_TAG);
}
}
@@ -324,7 +350,7 @@ void html_text::do_bold (void)
done_italic();
done_tt();
if (! is_present(B_TAG)) {
- push_para(B_TAG, "");
+ push_para(B_TAG);
}
}
@@ -337,7 +363,7 @@ void html_text::do_tt (void)
done_bold();
done_italic();
if ((! is_present(TT_TAG)) && (! is_present(PRE_TAG))) {
- push_para(TT_TAG, "");
+ push_para(TT_TAG);
}
}
@@ -352,7 +378,7 @@ void html_text::do_pre (void)
done_tt();
(void)done_para();
if (! is_present(PRE_TAG)) {
- push_para(PRE_TAG, "");
+ push_para(PRE_TAG);
}
}
@@ -376,6 +402,27 @@ int html_text::is_in_table (void)
}
/*
+ * do_color - initiates a new color tag.
+ */
+
+void html_text::do_color (color *c)
+{
+ if (c != 0) {
+ shutdown(COLOR_TAG); // shutdown a previous color tag, if present
+ push_para(COLOR_TAG, (void *)c);
+ }
+}
+
+/*
+ * done_color - shutdown an outstanding color tag, if it exists.
+ */
+
+void html_text::done_color (void)
+{
+ shutdown(COLOR_TAG);
+}
+
+/*
* shutdown - shuts down an html tag.
*/
@@ -417,7 +464,7 @@ char *html_text::shutdown (HTML_TAG t)
end_tag(stackptr);
}
if (t == P_TAG) {
- arg = stackptr->arg1;
+ arg = (char *)stackptr->arg1;
}
p = stackptr;
stackptr = stackptr->next;
@@ -534,7 +581,7 @@ void html_text::check_emit_text (tag_definition *t)
*/
if ((t->next != NULL) &&
(t->next->type == P_TAG) &&
- ((t->next->arg1 == 0) || strcmp(t->next->arg1, "") == 0)) {
+ ((t->next->arg1 == 0) || strcmp((char *)t->next->arg1, "") == 0)) {
/*
* yes skip the <p>
*/
@@ -591,7 +638,7 @@ void html_text::do_para (char *arg)
if ((arg != 0) && (strcmp(arg, "") != 0)) {
remove_tag(TABLE_TAG);
}
- push_para(P_TAG, arg);
+ push_para(P_TAG, (void *)arg);
space_emitted = TRUE;
}
}
@@ -629,7 +676,7 @@ void html_text::do_break (void)
if (! is_present(PRE_TAG)) {
if (emitted_text()) {
if (! is_present(BREAK_TAG)) {
- push_para(BREAK_TAG, "");
+ push_para(BREAK_TAG);
}
}
}
@@ -792,7 +839,7 @@ void html_text::do_small (void)
if (is_present(BIG_TAG)) {
done_big();
} else {
- push_para(SMALL_TAG, "");
+ push_para(SMALL_TAG);
}
}
@@ -805,7 +852,7 @@ void html_text::do_big (void)
if (is_present(SMALL_TAG)) {
done_small();
} else {
- push_para(BIG_TAG, "");
+ push_para(BIG_TAG);
}
}
@@ -815,7 +862,7 @@ void html_text::do_big (void)
void html_text::do_sup (void)
{
- push_para(SUP_TAG, "");
+ push_para(SUP_TAG);
}
/*
@@ -824,6 +871,6 @@ void html_text::do_sup (void)
void html_text::do_sub (void)
{
- push_para(SUB_TAG, "");
+ push_para(SUB_TAG);
}
diff --git a/src/devices/grohtml/html-text.h b/src/devices/grohtml/html-text.h
index 5bbcd431..c59b4646 100644
--- a/src/devices/grohtml/html-text.h
+++ b/src/devices/grohtml/html-text.h
@@ -32,11 +32,12 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
*/
typedef enum {I_TAG, B_TAG, P_TAG, SUB_TAG, SUP_TAG, TT_TAG,
- PRE_TAG, SMALL_TAG, BIG_TAG, BREAK_TAG, TABLE_TAG} HTML_TAG;
+ PRE_TAG, SMALL_TAG, BIG_TAG, BREAK_TAG, TABLE_TAG,
+ COLOR_TAG} HTML_TAG;
typedef struct tag_definition {
HTML_TAG type;
- char *arg1;
+ void *arg1;
int text_emitted;
tag_definition *next;
} tag_definition ;
@@ -77,6 +78,8 @@ public:
void done_small (void);
void done_big (void);
void do_indent (char *arg, int indent, int pageoff, int linelen);
+ void do_color (color *c);
+ void done_color (void);
int emitted_text (void);
void emit_space (void);
int is_in_pre (void);
@@ -97,12 +100,14 @@ private:
int is_present (HTML_TAG t);
void end_tag (tag_definition *t);
void start_tag (tag_definition *t);
- void push_para (HTML_TAG t, char *arg);
+ void push_para (HTML_TAG t, void *arg);
+ void push_para (HTML_TAG t);
char *shutdown (HTML_TAG t);
void check_emit_text (tag_definition *t);
int remove_break (void);
void issue_tag (char *tagname, char *arg);
- void issue_table_begin (tag_definition *t);
+ void issue_color_begin (color *c);
+ void issue_table_begin (char *arg);
void issue_table_end (void);
int table_is_void (tag_definition *t);
void remove_def (tag_definition *t);
diff --git a/src/devices/grohtml/post-html.cc b/src/devices/grohtml/post-html.cc
index 961be23e..9bb08fcc 100644
--- a/src/devices/grohtml/post-html.cc
+++ b/src/devices/grohtml/post-html.cc
@@ -64,7 +64,7 @@ typedef enum {CENTERED, LEFT, RIGHT, INLINE} TAG_ALIGNMENT;
* prototypes
*/
-void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len, int and_single);
+void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len, int and_single, int is_special);
char *get_html_translation (font *f, const char *name);
@@ -230,8 +230,9 @@ struct style {
int font_no;
int height;
int slant;
+ color *col;
style ();
- style (font *, int, int, int, int);
+ style (font *, int, int, int, int, color *);
int operator == (const style &) const;
int operator != (const style &) const;
};
@@ -241,15 +242,15 @@ style::style()
{
}
-style::style(font *p, int sz, int h, int sl, int no)
- : f(p), point_size(sz), font_no(no), height(h), slant(sl)
+style::style(font *p, int sz, int h, int sl, int no, color *c)
+ : f(p), point_size(sz), font_no(no), height(h), slant(sl), col(c)
{
}
int style::operator==(const style &s) const
{
return (f == s.f && point_size == s.point_size
- && height == s.height && slant == s.slant);
+ && height == s.height && slant == s.slant && col == s.col);
}
int style::operator!=(const style &s) const
@@ -1074,15 +1075,15 @@ class html_printer : public printer {
// ADD HERE
public:
- html_printer ();
- ~html_printer ();
- void set_char (int i, font *f, const environment *env, int w, const char *name);
- void draw (int code, int *p, int np, const environment *env);
- void begin_page (int);
- void end_page (int);
- void special (char *arg, const environment *env, char type);
- font *make_font (const char *);
- void end_of_line ();
+ html_printer ();
+ ~html_printer ();
+ void set_char (int i, font *f, const environment *env, int w, const char *name);
+ void draw (int code, int *p, int np, const environment *env);
+ void begin_page (int);
+ void end_page (int);
+ void special (char *arg, const environment *env, char type);
+ font *make_font (const char *);
+ void end_of_line ();
};
printer *make_printer()
@@ -1325,13 +1326,13 @@ void html_printer::do_title (void)
return;
} else if (found_title_start) {
strcat(title.text, " ");
- str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
+ str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE, FALSE);
strcat(title.text, buf);
page_contents->glyphs.sub_move_right(); /* move onto next word */
removed_from_head = ((!page_contents->glyphs.is_empty()) &&
(page_contents->glyphs.is_equal_to_head()));
} else {
- str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
+ str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE, FALSE);
strcpy((char *)title.text, buf);
found_title_start = TRUE;
title.has_been_found = TRUE;
@@ -1450,7 +1451,7 @@ void html_printer::do_heading (char *arg)
strcat(header.header_buffer, " ");
}
l = g;
- str_translate_to_html(g->text_style.f, buf, MAX_STRING_LENGTH, g->text_string, g->text_length, TRUE);
+ str_translate_to_html(g->text_style.f, buf, MAX_STRING_LENGTH, g->text_string, g->text_length, TRUE, FALSE);
strcat(header.header_buffer, (char *)buf);
}
page_contents->glyphs.move_right();
@@ -1604,13 +1605,13 @@ void html_printer::do_indentedparagraph (void)
page_contents->glyphs.sub_move_right(); /* move onto next word */
} else if (found_indent_start) {
strcat(indent.text, " ");
- str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
+ str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE, FALSE);
strcat(indent.text, buf);
page_contents->glyphs.sub_move_right(); /* move onto next word */
removed_from_head = ((!page_contents->glyphs.is_empty()) &&
(page_contents->glyphs.is_equal_to_head()));
} else {
- str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE);
+ str_translate_to_html(t->text_style.f, buf, MAX_STRING_LENGTH, t->text_string, t->text_length, TRUE, FALSE);
strcpy((char *)indent.text, buf);
found_indent_start = TRUE;
indent.has_been_found = TRUE;
@@ -1988,6 +1989,13 @@ void html_printer::do_font (text_glob *g)
output_style.point_size = g->text_style.point_size;
}
}
+ if (output_style.col != g->text_style.col) {
+ current_paragraph->done_color();
+ output_style.col = g->text_style.col;
+ if (output_style.col != 0) {
+ current_paragraph->do_color(output_style.col);
+ }
+ }
}
/*
@@ -2082,7 +2090,7 @@ void html_printer::translate_to_html (text_glob *g)
do_font(g);
determine_space(g);
str_translate_to_html(g->text_style.f, buf, MAX_STRING_LENGTH,
- g->text_string, g->text_length, TRUE);
+ g->text_string, g->text_length, TRUE, FALSE);
current_paragraph->do_emittext(buf, strlen(buf));
output_vpos = g->minv;
output_hpos = g->maxh;
@@ -2264,6 +2272,9 @@ void html_printer::draw(int code, int *p, int np, const environment *env)
#endif
break;
}
+ case 'F':
+ // fill with color env->fill
+ break;
default:
error("unrecognised drawing command `%1'", char(code));
@@ -2582,9 +2593,10 @@ int char_translate_to_html (font *f, char *buf, int buflen, unsigned char ch, in
* there is not enough space in buf.
* It looks up the html character encoding of single characters
* if, and_single, is TRUE. Characters such as < > & etc.
+ * If is_special then we will decode special characters from an escape sequence.
*/
-void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len, int and_single)
+void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len, int and_single, int is_special)
{
char *translation;
int e;
@@ -2600,44 +2612,38 @@ void str_translate_to_html (font *f, char *buf, int buflen, char *str, int len,
}
#endif
while (str[i] != (char)0) {
- if ((str[i]=='\\') && (i+1<len)) {
- i++; // skip the leading backslash
- if (str[i] == '(') {
- // start of escape
- i++;
- e = 0;
- while ((str[i] != (char)0) &&
- (! ((str[i] == '\\') && (i+1<len) && (str[i+1] == ')')))) {
- if (str[i] == '\\') {
- i++;
- }
- escaped_char[e] = str[i];
- e++;
+ if ((str[i]=='\\') && (i+1<len) && (str[i+1] == '(') && is_special) {
+ // start of escape
+ i += 2; // move over \(
+ e = 0;
+ while ((str[i] != (char)0) &&
+ (! ((str[i] == '\\') && (i+1<len) && (str[i+1] == ')')))) {
+ if (str[i] == '\\') {
i++;
}
- if ((str[i] == '\\') && (i+1<len) && (str[i+1] == ')')) {
- i += 2;
- }
- escaped_char[e] = (char)0;
- if (e > 0) {
- translation = get_html_translation(f, escaped_char);
- if (translation) {
- l = strlen(translation);
- t = max(0, min(l, buflen-b));
- strncpy(&buf[b], translation, t);
- b += t;
- } else {
- int index=f->name_to_index(escaped_char);
+ escaped_char[e] = str[i];
+ e++;
+ i++;
+ }
+ if ((str[i] == '\\') && (i+1<len) && (str[i+1] == ')')) {
+ i += 2;
+ }
+ escaped_char[e] = (char)0;
+ if (e > 0) {
+ translation = get_html_translation(f, escaped_char);
+ if (translation) {
+ l = strlen(translation);
+ t = max(0, min(l, buflen-b));
+ strncpy(&buf[b], translation, t);
+ b += t;
+ } else {
+ int index=f->name_to_index(escaped_char);
- if (f->contains(index) && (index != 0)) {
- buf[b] = f->get_code(index);
- b++;
- }
+ if (f->contains(index) && (index != 0)) {
+ buf[b] = f->get_code(index);
+ b++;
}
}
- } else {
- b = char_translate_to_html(f, buf, buflen, str[i], b, and_single);
- i++;
}
} else {
b = char_translate_to_html(f, buf, buflen, str[i], b, and_single);
@@ -2661,7 +2667,7 @@ void html_printer::set_char(int i, font *f, const environment *env, int w, const
stop();
}
#endif
- style sty(f, env->size, env->height, env->slant, env->fontno);
+ style sty(f, env->size, env->height, env->slant, env->fontno, env->col);
if (sty.slant != 0) {
if (sty.slant > 80 || sty.slant < -80) {
error("silly slant `%1' degrees", sty.slant);
@@ -2827,7 +2833,8 @@ void html_printer::special(char *s, const environment *env, char type)
if (s != 0) {
flush_sbuf();
if (env->fontno >= 0) {
- style sty(get_font_from_index(env->fontno), env->size, env->height, env->slant, env->fontno);
+ style sty(get_font_from_index(env->fontno), env->size, env->height,
+ env->slant, env->fontno, env->col);
sbuf_style = sty;
}
@@ -2842,7 +2849,7 @@ void html_printer::special(char *s, const environment *env, char type)
f = font::load_font("TR", &found);
}
str_translate_to_html(f, buf, MAX_STRING_LENGTH,
- &s[5], strlen(s)-5, FALSE);
+ &s[5], strlen(s)-5, FALSE, TRUE);
/*
* need to pass rest of string through to html output during flush
@@ -2881,15 +2888,13 @@ int main(int argc, char **argv)
{ "version", no_argument, 0, 'v' },
{ NULL, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "o:i:I:D:F:vd?lrn", long_options, NULL))
+ while ((c = getopt_long(argc, argv, "o:i:I:D:F:vdlrn", long_options, NULL))
!= EOF)
switch(c) {
case 'v':
- {
- printf("GNU post-grohtml (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
+ printf("GNU post-grohtml (groff) version %s\n", Version_string);
+ exit(0);
+ break;
case 'F':
font::command_line_font_dir(optarg);
break;
diff --git a/src/devices/grolbp/lbp.cc b/src/devices/grolbp/lbp.cc
index 376324b6..58a3ac30 100644
--- a/src/devices/grolbp/lbp.cc
+++ b/src/devices/grolbp/lbp.cc
@@ -517,6 +517,9 @@ void lbp_printer::draw(int code, int *p, int np, const environment *env)
else fill_pattern = -21;
}; // if (p[0] >= 0 && p[0] <= 1000)
break;
+ case 'F':
+ // not implemented yet
+ break;
default:
error("unrecognised drawing command `%1'", char(code));
break;
diff --git a/src/devices/grolj4/lj4.cc b/src/devices/grolj4/lj4.cc
index 6829acb1..0ee11852 100644
--- a/src/devices/grolj4/lj4.cc
+++ b/src/devices/grolj4/lj4.cc
@@ -502,6 +502,9 @@ void lj4_printer::draw(int code, int *p, int np, const environment *env)
printf("FT10,%d", p[0]/10);
hpgl_end();
break;
+ case 'F':
+ // not implemented yet
+ break;
case 't':
{
if (np == 0) {
diff --git a/src/devices/grops/ps.cc b/src/devices/grops/ps.cc
index a467f047..5fb84054 100644
--- a/src/devices/grops/ps.cc
+++ b/src/devices/grops/ps.cc
@@ -319,7 +319,7 @@ ps_output &ps_output::put_fix_number(int i)
ps_output &ps_output::put_float(double d)
{
char buf[128];
- sprintf(buf, "%.4f", d);
+ sprintf(buf, "%.3g", d);
int len = strlen(buf);
if (col > 0 && col + len + need_space > max_line_length) {
putc('\n', fp);
@@ -476,13 +476,15 @@ class ps_printer : public printer {
int sbuf_space_code;
int sbuf_kern;
style sbuf_style;
+ color *sbuf_color;
style output_style;
int output_hpos;
int output_vpos;
int output_draw_point_size;
int line_thickness;
int output_line_thickness;
- int fill;
+ color *fill_color;
+ color *output_color;
unsigned char output_space_code;
enum { MAX_DEFINED_STYLES = 50 };
style defined_styles[MAX_DEFINED_STYLES];
@@ -509,6 +511,8 @@ class ps_printer : public printer {
void encode_fonts();
void define_encoding(const char *, int);
void reencode_font(ps_font *);
+ void set_color(color *c, int complete = 1);
+
public:
ps_printer();
~ps_printer();
@@ -528,7 +532,6 @@ ps_printer::ps_printer()
output_hpos(-1),
output_vpos(-1),
line_thickness(-1),
- fill(FILL_MAX + 1),
ndefined_styles(0),
next_encoding_index(0),
ndefs(0),
@@ -557,6 +560,11 @@ ps_printer::ps_printer()
if (paper_length == 0)
paper_length = 11*font::res;
equalise_spaces = font::res >= 72000;
+ fill_color = new color;
+ fill_color->set_gray(1.0); // black
+ output_color = new color;
+ output_color->set_gray(1.0);
+ sbuf_color = output_color;
}
int ps_printer::set_encoding_index(ps_font *f)
@@ -590,7 +598,8 @@ void ps_printer::set_char(int i, font *f, const environment *env, int w, const c
if (sbuf_len > 0) {
if (sbuf_len < SBUF_SIZE
&& sty == sbuf_style
- && sbuf_vpos == env->vpos) {
+ && sbuf_vpos == env->vpos
+ && sbuf_color->is_equal(env->col)) {
if (sbuf_end_hpos == env->hpos) {
sbuf[sbuf_len++] = code;
sbuf_end_hpos += w + sbuf_kern;
@@ -645,6 +654,7 @@ void ps_printer::set_char(int i, font *f, const environment *env, int w, const c
sbuf_space_width = 0;
sbuf_space_count = sbuf_space_diff_count = 0;
sbuf_kern = 0;
+ sbuf_color = env->col;
}
static char *make_encoding_name(int encoding_index)
@@ -693,7 +703,8 @@ void ps_printer::define_encoding(const char *encoding, int encoding_index)
a_delete vec[i];
}
}
- out.put_delimiter(']').put_symbol("def");
+ out.put_delimiter(']')
+ .put_symbol("def");
}
void ps_printer::reencode_font(ps_font *f)
@@ -759,18 +770,37 @@ void ps_printer::set_style(const style &sty)
int h = sty.height == 0 ? sty.point_size : sty.height;
h *= font::res/(72*font::sizescale);
int c = int(h*tan(radians(sty.slant)) + .5);
- out.put_fix_number(c).put_fix_number(h).put_literal_symbol(psname)
+ out.put_fix_number(c)
+ .put_fix_number(h)
+ .put_literal_symbol(psname)
.put_symbol("MF");
}
else {
- out.put_literal_symbol(psname).put_symbol("SF");
+ out.put_literal_symbol(psname)
+ .put_symbol("SF");
}
defined_styles[ndefined_styles++] = sty;
}
+void ps_printer::set_color(color *col, int complete)
+{
+ output_color = col;
+ if (col) {
+ double r, g, b;
+ col->get_rgb(&r, &g, &b);
+ out.put_float(r)
+ .put_float(g)
+ .put_float(b);
+ if (complete)
+ out.put_symbol("CO");
+ }
+}
+
void ps_printer::set_space_code(unsigned char c)
{
- out.put_literal_symbol("SC").put_number(c).put_symbol("def");
+ out.put_literal_symbol("SC")
+ .put_number(c)
+ .put_symbol("def");
}
void ps_printer::end_of_line()
@@ -796,6 +826,8 @@ void ps_printer::flush_sbuf()
set_style(sbuf_style);
output_style = sbuf_style;
}
+ if (!output_color->is_equal(sbuf_color))
+ set_color(sbuf_color);
int extra_space = 0;
if (output_hpos < 0 || output_vpos < 0)
motion = ABSOLUTE;
@@ -870,26 +902,43 @@ void ps_printer::set_line_thickness(const environment *env)
if (output_draw_point_size != env->size) {
// we ought to check for overflow here
int lw = ((font::res/(72*font::sizescale))*linewidth*env->size)/1000;
- out.put_fix_number(lw).put_symbol("LW");
+ out.put_fix_number(lw)
+ .put_symbol("LW");
output_draw_point_size = env->size;
output_line_thickness = -1;
}
}
else {
if (output_line_thickness != line_thickness) {
- out.put_fix_number(line_thickness).put_symbol("LW");
+ out.put_fix_number(line_thickness)
+ .put_symbol("LW");
output_line_thickness = line_thickness;
output_draw_point_size = -1;
}
}
+ if (!env->col->is_equal(output_color))
+ set_color(env->col);
}
void ps_printer::fill_path()
{
- if (fill > FILL_MAX)
- out.put_symbol("BL");
- else
- out.put_float(transform_fill(fill)).put_symbol("FL");
+ double c, m, y, k;
+ fill_color->get_cmyk(&c, &m, &y, &k);
+ if (fill_color->is_gray()) {
+ if (k == 1.0)
+ out.put_symbol("BL");
+ else
+ out.put_float(1.0-k)
+ .put_symbol("FL");
+ }
+ else {
+ if (output_color->is_equal(fill_color))
+ out.put_symbol("fill");
+ else {
+ set_color(fill_color, 0);
+ out.put_symbol("FC");
+ }
+ }
}
void ps_printer::draw(int code, int *p, int np, const environment *env)
@@ -1043,33 +1092,33 @@ void ps_printer::draw(int code, int *p, int np, const environment *env)
}
break;
case 't':
- {
- if (np == 0) {
- line_thickness = -1;
- }
- else {
- // troff gratuitously adds an extra 0
- if (np != 1 && np != 2) {
- error("0 or 1 argument required for thickness");
- break;
- }
- line_thickness = p[0];
- }
- break;
- }
- case 'f':
- {
+ if (np == 0)
+ line_thickness = -1;
+ else {
+ // troff gratuitously adds an extra 0
if (np != 1 && np != 2) {
- error("1 argument required for fill");
+ error("0 or 1 argument required for thickness");
break;
}
- fill = p[0];
- if (fill < 0 || fill > FILL_MAX) {
- // This means fill with the current color.
- fill = FILL_MAX + 1;
- }
+ line_thickness = p[0];
+ }
+ break;
+ case 'f':
+ if (np != 1 && np != 2) {
+ error("1 argument required for fill");
break;
- }
+ }
+ if (p[0] < 0 || p[0] > FILL_MAX) {
+ // This means fill with the current color.
+ fill_color->set_gray(1.0);
+ }
+ else
+ fill_color->set_gray(double(p[0]) / FILL_MAX);
+ break;
+ case 'F':
+ // fill with color env->fill
+ *fill_color = *env->fill;
+ break;
default:
error("unrecognised drawing command `%1'", char(code));
break;
@@ -1081,17 +1130,19 @@ void ps_printer::draw(int code, int *p, int np, const environment *env)
void ps_printer::begin_page(int n)
{
- out.begin_comment("Page:").comment_arg(i_to_a(n));
- out.comment_arg(i_to_a(++pages_output)).end_comment();
+ out.begin_comment("Page:")
+ .comment_arg(i_to_a(n));
+ out.comment_arg(i_to_a(++pages_output))
+ .end_comment();
output_style.f = 0;
output_space_code = 32;
output_draw_point_size = -1;
output_line_thickness = -1;
output_hpos = output_vpos = -1;
ndefined_styles = 0;
- out.simple_comment("BeginPageSetup");
- out.put_symbol("BP");
- out.simple_comment("EndPageSetup");
+ out.simple_comment("BeginPageSetup")
+ .put_symbol("BP")
+ .simple_comment("EndPageSetup");
}
void ps_printer::end_page(int)
@@ -1111,9 +1162,9 @@ font *ps_printer::make_font(const char *nm)
ps_printer::~ps_printer()
{
- out.simple_comment("Trailer");
- out.put_symbol("end");
- out.simple_comment("EOF");
+ out.simple_comment("Trailer")
+ .put_symbol("end")
+ .simple_comment("EOF");
if (fseek(tempfp, 0L, 0) < 0)
fatal("fseek on temporary file failed");
fputs("%!PS-Adobe-", stdout);
@@ -1142,8 +1193,12 @@ ps_printer::~ps_printer()
rm.need_font(psf->get_internal_name());
}
rm.print_header_comments(out);
- out.begin_comment("Pages:").comment_arg(i_to_a(pages_output)).end_comment();
- out.begin_comment("PageOrder:").comment_arg("Ascend").end_comment();
+ out.begin_comment("Pages:")
+ .comment_arg(i_to_a(pages_output))
+ .end_comment();
+ out.begin_comment("PageOrder:")
+ .comment_arg("Ascend")
+ .end_comment();
#if 0
fprintf(out.get_file(), "%%%%DocumentMedia: () %g %g 0 () ()\n",
font::paperwidth*72.0/font::res,
@@ -1164,7 +1219,8 @@ ps_printer::~ps_printer()
out.simple_comment("BeginSetup");
}
rm.document_setup(out);
- out.put_symbol(dict_name).put_symbol("begin");
+ out.put_symbol(dict_name)
+ .put_symbol("begin");
if (ndefs > 0)
ndefs += DEFS_DICT_SPARE;
out.put_literal_symbol(defs_dict_name)
@@ -1184,8 +1240,12 @@ ps_printer::~ps_printer()
out.special(defs.contents());
out.put_symbol("end");
if (ncopies != 1)
- out.put_literal_symbol("#copies").put_number(ncopies).put_symbol("def");
- out.put_literal_symbol("RES").put_number(res).put_symbol("def");
+ out.put_literal_symbol("#copies")
+ .put_number(ncopies)
+ .put_symbol("def");
+ out.put_literal_symbol("RES")
+ .put_number(res)
+ .put_symbol("def");
out.put_literal_symbol("PL");
if (guess_flag)
out.put_symbol("PLG");
@@ -1495,11 +1555,9 @@ int main(int argc, char **argv)
!= EOF)
switch(c) {
case 'v':
- {
- printf("GNU grops (groff) version %s\n", Version_string);
- exit(0);
- break;
- }
+ printf("GNU grops (groff) version %s\n", Version_string);
+ exit(0);
+ break;
case 'c':
if (sscanf(optarg, "%d", &ncopies) != 1 || ncopies <= 0) {
error("bad number of copies `%s'", optarg);
diff --git a/src/include/Makefile.sub b/src/include/Makefile.sub
index cee00d31..b68e631c 100644
--- a/src/include/Makefile.sub
+++ b/src/include/Makefile.sub
@@ -2,11 +2,13 @@ HDRS=\
assert.h \
cmap.h \
cset.h \
+ color.h \
device.h \
driver.h \
errarg.h \
error.h \
font.h \
+ geometry.h \
getopt.h \
groff-getopt.h \
htmlindicate.h \
diff --git a/src/include/driver.h b/src/include/driver.h
index 798b3504..8bf53e4b 100644
--- a/src/include/driver.h
+++ b/src/include/driver.h
@@ -30,6 +30,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "error.h"
#include "font.h"
#include "printer.h"
+#include "geometry.h"
void do_file(const char *);
extern printer *pr;
diff --git a/src/include/printer.h b/src/include/printer.h
index beae4d9a..8ad8e719 100644
--- a/src/include/printer.h
+++ b/src/include/printer.h
@@ -18,6 +18,8 @@ You should have received a copy of the GNU General Public License along
with groff; see the file COPYING. If not, write to the Free Software
Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+#include "color.h"
+
struct environment {
int fontno;
int size;
@@ -25,6 +27,8 @@ struct environment {
int vpos;
int height;
int slant;
+ color *col;
+ color *fill;
};
struct font;
@@ -55,7 +59,6 @@ public:
virtual font *make_font(const char *nm);
virtual void end_of_line();
virtual void special(char *arg, const environment *env, char type = 'p');
- static int adjust_arc_center(const int *, double *);
protected:
font_pointer_list *font_list;
diff --git a/src/libs/libdriver/input.cc b/src/libs/libdriver/input.cc
index e19841c1..efe63c38 100644
--- a/src/libs/libdriver/input.cc
+++ b/src/libs/libdriver/input.cc
@@ -91,6 +91,10 @@ void do_file(const char *filename)
env.fontno = -1;
env.height = 0;
env.slant = 0;
+ env.col = new color;
+ env.col->set_gray(1.0);
+ env.fill = new color;
+ env.fill->set_gray(1.0);
environment_list *env_list = 0;
current_lineno = 1;
int command;
@@ -207,6 +211,11 @@ void do_file(const char *filename)
pr->set_ascii_char(c, &env);
}
break;
+ case 'm':
+ // glyph color
+ env.col = new color;
+ env.col->read_rgb(get_string());
+ break;
case 'n':
if (npages == 0)
fatal("`n' command illegal before first `p' command");
@@ -289,32 +298,40 @@ void do_file(const char *filename)
int c;
while ((c = get_char()) == ' ')
;
- int n;
+ int n = 0;
int *p = 0;
int szp = 0;
- int np;
- for (np = 0; possibly_get_integer(&n); np++) {
- if (np >= szp) {
- if (szp == 0) {
- szp = 16;
- p = new int[szp];
- }
- else {
- int *oldp = p;
- p = new int[szp*2];
- memcpy(p, oldp, szp*sizeof(int));
- szp *= 2;
- a_delete oldp;
+ int np = 0;
+
+ if (c == 'F') {
+ // fill color
+ env.fill = new color;
+ env.fill->read_rgb(get_string());
+ }
+ else {
+ for (np = 0; possibly_get_integer(&n); np++) {
+ if (np >= szp) {
+ if (szp == 0) {
+ szp = 16;
+ p = new int[szp];
+ }
+ else {
+ int *oldp = p;
+ p = new int[szp*2];
+ memcpy(p, oldp, szp*sizeof(int));
+ szp *= 2;
+ a_delete oldp;
+ }
}
+ p[np] = n;
}
- p[np] = n;
}
pr->draw(c, p, np, &env);
if (c == 'e') {
if (np > 0)
env.hpos += p[0];
}
- else if (c == 'f' || c == 't')
+ else if (c == 'f' || c == 'F' || c == 't')
;
else {
int i;
diff --git a/src/libs/libdriver/printer.cc b/src/libs/libdriver/printer.cc
index 4d66f7ba..171ee9fd 100644
--- a/src/libs/libdriver/printer.cc
+++ b/src/libs/libdriver/printer.cc
@@ -199,73 +199,3 @@ font *printer::get_font_from_index(int fontno)
else
return(0);
}
-
-// This utility function adjusts the specified center of the
-// arc so that it is equidistant between the specified start
-// and end points. (p[0], p[1]) is a vector from the current
-// point to the center; (p[2], p[3]) is a vector from the
-// center to the end point. If the center can be adjusted,
-// a vector from the current point to the adjusted center is
-// stored in c[0], c[1] and 1 is returned. Otherwise 0 is
-// returned.
-
-#if 1
-int printer::adjust_arc_center(const int *p, double *c)
-{
- // We move the center along a line parallel to the line between
- // the specified start point and end point so that the center
- // is equidistant between the start and end point.
- // It can be proved (using Lagrange multipliers) that this will
- // give the point nearest to the specified center that is equidistant
- // between the start and end point.
-
- double x = p[0] + p[2]; // (x, y) is the end point
- double y = p[1] + p[3];
- double n = x*x + y*y;
- if (n != 0) {
- c[0]= double(p[0]);
- c[1] = double(p[1]);
- double k = .5 - (c[0]*x + c[1]*y)/n;
- c[0] += k*x;
- c[1] += k*y;
- return 1;
- }
- else
- return 0;
-}
-#else
-int printer::adjust_arc_center(const int *p, double *c)
-{
- int x = p[0] + p[2]; // (x, y) is the end point
- int y = p[1] + p[3];
- // Start at the current point; go in the direction of the specified
- // center point until we reach a point that is equidistant between
- // the specified starting point and the specified end point. Place
- // the center of the arc there.
- double n = p[0]*double(x) + p[1]*double(y);
- if (n > 0) {
- double k = (double(x)*x + double(y)*y)/(2.0*n);
- // (cx, cy) is our chosen center
- c[0] = k*p[0];
- c[1] = k*p[1];
- return 1;
- }
- else {
- // We would never reach such a point. So instead start at the
- // specified end point of the arc. Go towards the specified
- // center point until we reach a point that is equidistant between
- // the specified start point and specified end point. Place
- // the center of the arc there.
- n = p[2]*double(x) + p[3]*double(y);
- if (n > 0) {
- double k = 1 - (double(x)*x + double(y)*y)/(2.0*n);
- // (c[0], c[1]) is our chosen center
- c[0] = p[0] + k*p[2];
- c[1] = p[1] + k*p[3];
- return 1;
- }
- else
- return 0;
- }
-}
-#endif
diff --git a/src/libs/libgroff/Makefile.sub b/src/libs/libgroff/Makefile.sub
index b97a7784..2ebaf54b 100644
--- a/src/libs/libgroff/Makefile.sub
+++ b/src/libs/libgroff/Makefile.sub
@@ -3,6 +3,7 @@ OBJS=\
assert.o \
change_lf.o \
cmap.o \
+ color.o \
cset.o \
device.o \
errarg.o \
@@ -11,6 +12,7 @@ OBJS=\
filename.o \
font.o \
fontfile.o \
+ geometry.o \
getopt.o \
getopt1.o \
htmlindicate.o \
@@ -39,6 +41,7 @@ CCSRCS=\
$(srcdir)/assert.cc \
$(srcdir)/change_lf.cc \
$(srcdir)/cmap.cc \
+ $(srcdir)/color.cc \
$(srcdir)/cset.cc \
$(srcdir)/device.cc \
$(srcdir)/errarg.cc \
@@ -47,6 +50,7 @@ CCSRCS=\
$(srcdir)/filename.cc \
$(srcdir)/font.cc \
$(srcdir)/fontfile.cc \
+ $(srcdir)/geometry.cc \
$(srcdir)/htmlindicate.cc \
$(srcdir)/illegal.cc \
$(srcdir)/lf.cc \
diff --git a/src/libs/libgroff/font.cc b/src/libs/libgroff/font.cc
index fdf1afca..0e28d4b5 100644
--- a/src/libs/libgroff/font.cc
+++ b/src/libs/libgroff/font.cc
@@ -302,7 +302,7 @@ int font::get_space_width(int point_size)
}
font_kern_list::font_kern_list(int c1, int c2, int n, font_kern_list *p)
- : i1(c1), i2(c2), amount(n), next(p)
+: i1(c1), i2(c2), amount(n), next(p)
{
}
diff --git a/src/preproc/eqn/eqn.man b/src/preproc/eqn/eqn.man
index 46de7f14..6d0733c4 100644
--- a/src/preproc/eqn/eqn.man
+++ b/src/preproc/eqn/eqn.man
@@ -42,7 +42,7 @@ the original English.
.el .RB "[\ " "\\$1" "\ ]"
..
.OP \-rvCNR
-.OP \-d cc
+.OP \-d xy
.OP \-T name
.OP \-M dir
.OP \-f F
@@ -97,6 +97,16 @@ it does not support low-resolution, typewriter-like devices
(although it may work adequately for very simple input).
.SH OPTIONS
.TP
+.BI \-d xy
+Specify delimiters
+.I x
+and
+.I y
+for the left and right end, respectively, of in-line equations.
+Any
+.B delim
+statements in the source file overrides this.
+.TP
.B \-C
Recognize
.B .EQ
diff --git a/src/preproc/html/pre-html.cc b/src/preproc/html/pre-html.cc
index 92a0b2c4..a83fa811 100644
--- a/src/preproc/html/pre-html.cc
+++ b/src/preproc/html/pre-html.cc
@@ -63,7 +63,7 @@ extern "C" const char *Version_string;
#else
# define DEFAULT_VERTICAL_OFFSET 50 // DEFAULT_VERTICAL_OFFSET/72 of an inch
#endif
-#define IMAGE_BOARDER_PIXELS 0
+#define IMAGE_BOARDER_PIXELS 2
#define MAX_WIDTH 8 // inches
#define INLINE_LEADER_CHAR '\\'
@@ -89,8 +89,6 @@ extern "C" const char *Version_string;
# define FALSE (1==0)
#endif
-void stop() {}
-
typedef enum {CENTERED, LEFT, RIGHT, INLINE} IMAGE_ALIGNMENT;
static int stdoutfd = 1; // output file descriptor - normally 1 but might move
@@ -791,9 +789,9 @@ static void createImage (imageItem *i)
int x1 = max(min(i->X1, i->X2)*image_res/POSTSCRIPTRES-1*IMAGE_BOARDER_PIXELS, 0);
int y1 = max((image_res*vertical_offset/72)+min(i->Y1, i->Y2)*image_res/POSTSCRIPTRES-IMAGE_BOARDER_PIXELS, 0);
int x2 = max(i->X1, i->X2)*image_res/POSTSCRIPTRES+1*IMAGE_BOARDER_PIXELS;
- int y2 = (image_res*vertical_offset/72)+max(i->Y1, i->Y2)*image_res/POSTSCRIPTRES+1*IMAGE_BOARDER_PIXELS;
+ int y2 = (image_res*vertical_offset/72)+(max(i->Y1, i->Y2)*image_res/POSTSCRIPTRES)+1+IMAGE_BOARDER_PIXELS;
- s = make_message("pnmcut%s %d %d %d %d < %s/%d | pnmtopng%s %s > %s \n",
+ s = make_message("pnmcut%s %d %d %d %d < %s/%d | pnmcrop | pnmtopng%s %s > %s \n",
EXE_EXT,
x1, y1, x2-x1+1, y2-y1+1,
imagePageStem,
@@ -849,7 +847,6 @@ void char_buffer::write_file_html (void)
int i=0;
if (t != NULL) {
- stop();
do {
/*
* remember to check the shortest string last
@@ -864,7 +861,6 @@ void char_buffer::write_file_html (void)
write_start_image(RIGHT, TRUE);
skip_to_newline(&t, &i);
} else if (can_see(&t, &i, HTML_IMAGE_CENTERED)) {
- stop();
write_start_image(CENTERED, TRUE);
skip_to_newline(&t, &i);
} else {
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;
diff --git a/src/roff/groff/groff.cc b/src/roff/groff/groff.cc
index ec8d34af..71529a0d 100644
--- a/src/roff/groff/groff.cc
+++ b/src/roff/groff/groff.cc
@@ -125,7 +125,7 @@ int main(int argc, char **argv)
{ NULL, 0, 0, 0 }
};
while ((opt = getopt_long(argc, argv,
- "abCd:eEf:F:gGhiI:lL:m:M:n:No:pP:r:RsStT:UvVw:W:XzZ",
+ "abcCd:eEf:F:gGhiI:lL:m:M:n:No:pP:r:RsStT:UvVw:W:XzZ",
long_options, NULL))
!= EOF) {
char buf[3];
@@ -208,6 +208,9 @@ int main(int argc, char **argv)
case 'b':
commands[TROFF_INDEX].append_arg(buf);
break;
+ case 'c':
+ commands[TROFF_INDEX].append_arg(buf);
+ break;
case 'S':
safer_flag = 1;
break;
@@ -674,7 +677,7 @@ char **possible_command::get_argv()
void synopsis(FILE *stream)
{
fprintf(stream,
-"usage: %s [-abeghilpstvzCENRSUVXZ] [-Fdir] [-mname] [-Tdev] [-ffam]\n"
+"usage: %s [-abceghilpstvzCENRSUVXZ] [-Fdir] [-mname] [-Tdev] [-ffam]\n"
" [-wname] [-Wname] [-Mdir] [-dcs] [-rcn] [-nnum] [-olist] [-Parg]\n"
" [-Larg] [-Idir] [files...]\n",
program_name);
@@ -712,6 +715,7 @@ void help()
"-E\tinhibit all errors\n"
"-b\tprint backtraces with errors or warnings\n"
"-l\tspool the output\n"
+"-c\tdisable color output\n"
"-C\tenable compatibility mode\n"
"-V\tprint commands on stdout instead of running them\n"
"-Parg\tpass arg to the postprocessor\n"
diff --git a/src/roff/groff/groff.man b/src/roff/groff/groff.man
index ffb683e8..575e7a9a 100644
--- a/src/roff/groff/groff.man
+++ b/src/roff/groff/groff.man
@@ -41,7 +41,7 @@ groff \- front end for the groff document formatting system
.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
.el .RB "[\ " "\\$1" "\ ]"
..
-.OP \-abeghilpstvzCEGNRSUVXZ
+.OP \-abceghilpstvzCEGNRSUVXZ
.OP \-w name
.OP \-W name
.OP \-m name
@@ -293,6 +293,8 @@ Unsafe mode. Reverts to the old unsafe behaviour.
.TQ
.B \-b
.TQ
+.B \-c
+.TQ
.B \-i
.TQ
.B \-C
diff --git a/src/roff/troff/dictionary.cc b/src/roff/troff/dictionary.cc
index bca38451..a70ebb0e 100644
--- a/src/roff/troff/dictionary.cc
+++ b/src/roff/troff/dictionary.cc
@@ -138,7 +138,7 @@ int dictionary_iterator::get(symbol *sp, void **vp)
}
object_dictionary_iterator::object_dictionary_iterator(object_dictionary &od)
- : di(od.d)
+: di(od.d)
{
}
diff --git a/src/roff/troff/div.cc b/src/roff/troff/div.cc
index c885ca80..d3650662 100644
--- a/src/roff/troff/div.cc
+++ b/src/roff/troff/div.cc
@@ -467,7 +467,7 @@ void top_level_diversion::space(vunits n, int forced)
}
trap::trap(symbol s, vunits n, trap *p)
- : next(p), position(n), nm(s)
+: next(p), position(n), nm(s)
{
}
diff --git a/src/roff/troff/env.cc b/src/roff/troff/env.cc
index c0743441..477453c7 100644
--- a/src/roff/troff/env.cc
+++ b/src/roff/troff/env.cc
@@ -532,6 +532,42 @@ void environment::set_char_slant(int n)
char_slant = n;
}
+color *environment::get_prev_glyph_color()
+{
+ return prev_glyph_color;
+}
+
+color *environment::get_glyph_color()
+{
+ return cur_glyph_color;
+}
+
+color *environment::get_prev_fill_color()
+{
+ return prev_fill_color;
+}
+
+color *environment::get_fill_color()
+{
+ return cur_fill_color;
+}
+
+void environment::set_glyph_color(color *c)
+{
+ if (interrupted)
+ return;
+ curenv->prev_glyph_color = curenv->prev_glyph_color;
+ curenv->cur_glyph_color = c;
+}
+
+void environment::set_fill_color(color *c)
+{
+ if (interrupted)
+ return;
+ curenv->prev_fill_color = curenv->prev_fill_color;
+ curenv->cur_fill_color = c;
+}
+
environment::environment(symbol nm)
: dummy(0),
prev_line_length((units_per_inch*13)/2),
@@ -600,6 +636,10 @@ environment::environment(symbol nm)
need_eol(0),
ignore_next_eol(0),
emitted_node(0),
+ cur_glyph_color(0),
+ prev_glyph_color(0),
+ cur_fill_color(0),
+ prev_fill_color(0),
name(nm),
control_char('.'),
no_break_control_char('\''),
@@ -685,6 +725,10 @@ environment::environment(const environment *e)
#endif /* WIDOW_CONTROL */
need_eol(0),
ignore_next_eol(0),
+ cur_glyph_color(e->cur_glyph_color),
+ prev_glyph_color(e->prev_glyph_color),
+ cur_fill_color(e->cur_fill_color),
+ prev_fill_color(e->prev_fill_color),
name(e->name), // so that eg `.if "\n[.ev]"0"' works
control_char(e->control_char),
no_break_control_char(e->no_break_control_char),
@@ -765,6 +809,10 @@ void environment::copy(const environment *e)
hyphenation_space = e->hyphenation_space;
hyphenation_margin = e->hyphenation_margin;
composite = 0;
+ cur_glyph_color= e->cur_glyph_color;
+ prev_glyph_color = e->prev_glyph_color;
+ cur_fill_color = e->cur_fill_color;
+ prev_fill_color = e->prev_fill_color;
}
environment::~environment()
@@ -2371,7 +2419,7 @@ tab::tab(hunits x, tab_type t) : next(0), pos(x), type(t)
}
tab_stops::tab_stops(hunits distance, tab_type type)
- : initial_list(0)
+: initial_list(0)
{
repeated_list = new tab(distance, type);
}
@@ -2476,7 +2524,7 @@ tab_stops::tab_stops() : initial_list(0), repeated_list(0)
}
tab_stops::tab_stops(const tab_stops &ts)
- : initial_list(0), repeated_list(0)
+: initial_list(0), repeated_list(0)
{
tab **p = &initial_list;
tab *t = ts.initial_list;
diff --git a/src/roff/troff/env.h b/src/roff/troff/env.h
index 851a9a0a..166eafb5 100644
--- a/src/roff/troff/env.h
+++ b/src/roff/troff/env.h
@@ -184,6 +184,10 @@ class environment {
int need_eol;
int ignore_next_eol;
int emitted_node; // have we emitted a node since the last html eol tag?
+ color *cur_glyph_color;
+ color *prev_glyph_color;
+ color *cur_fill_color;
+ color *prev_fill_color;
tab_type distance_to_next_tab(hunits *);
void start_line();
@@ -261,6 +265,12 @@ public:
int get_center_lines();
int get_right_justify_lines();
int get_prev_line_interrupted() { return prev_line_interrupted; }
+ color *get_fill_color();
+ color *get_glyph_color();
+ color *get_prev_glyph_color();
+ color *get_prev_fill_color();
+ void set_glyph_color(color *c);
+ void set_fill_color(color *c);
node *make_char_node(charinfo *);
node *extract_output_line();
void width_registers();
diff --git a/src/roff/troff/input.cc b/src/roff/troff/input.cc
index 58f88565..ff7413b1 100644
--- a/src/roff/troff/input.cc
+++ b/src/roff/troff/input.cc
@@ -92,6 +92,7 @@ void transparent_file();
const char *program_name = 0;
token tok;
int break_flag = 0;
+int disable_color_flag = 0;
static int backtrace_flag = 0;
#ifndef POPEN_MISSING
char *pipe_command = 0;
@@ -185,7 +186,7 @@ void restore_escape_char()
class input_iterator {
public:
input_iterator();
- virtual ~input_iterator();
+ virtual ~input_iterator() {}
int get(node **);
friend class input_stack;
protected:
@@ -197,15 +198,13 @@ private:
virtual int peek();
virtual int has_args() { return 0; }
virtual int nargs() { return 0; }
- virtual input_iterator *get_arg(int) { return NULL; }
- virtual int get_location(int, const char **, int *)
- { return 0; }
+ virtual input_iterator *get_arg(int) { return 0; }
+ virtual int get_location(int, const char **, int *) { return 0; }
virtual void backtrace() {}
- virtual int set_location(const char *, int)
- { return 0; }
+ virtual int set_location(const char *, int) { return 0; }
virtual int next_file(FILE *, const char *) { return 0; }
virtual void shift(int) {}
- virtual int is_boundary() { return 0; }
+ virtual int is_boundary() {return 0; }
virtual int internal_level() { return 0; }
virtual int is_file() { return 0; }
virtual int is_macro() { return 0; }
@@ -218,10 +217,6 @@ input_iterator::input_iterator()
{
}
-input_iterator::~input_iterator()
-{
-}
-
int input_iterator::fill(node **)
{
return EOF;
@@ -517,7 +512,7 @@ void input_stack::push(input_iterator *in)
input_iterator *input_stack::get_arg(int i)
{
input_iterator *p;
- for (p = top; p != NULL; p = p->next)
+ for (p = top; p != 0; p = p->next)
if (p->has_args())
return p->get_arg(i);
return 0;
@@ -679,7 +674,7 @@ void shift()
static int get_char_for_escape_name()
{
- int c = get_copy(NULL);
+ int c = get_copy(0);
switch (c) {
case EOF:
copy_mode_error("end of input in escape name");
@@ -826,19 +821,19 @@ static int get_copy(node **nd, int defining)
case 0:
return escape_char;
case '"':
- (void)input_stack::get(NULL);
- while ((c = input_stack::get(NULL)) != '\n' && c != EOF)
+ (void)input_stack::get(0);
+ while ((c = input_stack::get(0)) != '\n' && c != EOF)
;
return c;
case '#': // Like \" but newline is ignored.
- (void)input_stack::get(NULL);
- while ((c = input_stack::get(NULL)) != '\n')
+ (void)input_stack::get(0);
+ while ((c = input_stack::get(0)) != '\n')
if (c == EOF)
return EOF;
break;
case '$':
{
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
symbol s = read_escape_name();
if (!s.is_null())
interpolate_arg(s);
@@ -846,24 +841,24 @@ static int get_copy(node **nd, int defining)
}
case '*':
{
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
symbol s = read_escape_name();
if (!s.is_null())
interpolate_string(s);
break;
}
case 'a':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return '\001';
case 'e':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_e;
case 'E':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_E;
case 'n':
{
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
int inc;
symbol s = read_increment_and_escape_name(&inc);
if (!s.is_null())
@@ -872,85 +867,85 @@ static int get_copy(node **nd, int defining)
}
case 'g':
{
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
symbol s = read_escape_name();
if (!s.is_null())
interpolate_number_format(s);
break;
}
case 't':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return '\t';
case 'V':
{
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
symbol s = read_escape_name();
if (!s.is_null())
interpolate_environment_variable(s);
break;
}
case '\n':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
if (defining)
return ESCAPE_NEWLINE;
break;
case ' ':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_SPACE;
case '~':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_TILDE;
case ':':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_COLON;
case '|':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_BAR;
case '^':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_CIRCUMFLEX;
case '{':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_LEFT_BRACE;
case '}':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_RIGHT_BRACE;
case '`':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_LEFT_QUOTE;
case '\'':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_RIGHT_QUOTE;
case '-':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_HYPHEN;
case '_':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_UNDERSCORE;
case 'c':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_c;
case '!':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_BANG;
case '?':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_QUESTION;
case '&':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_AMPERSAND;
case ')':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_RIGHT_PARENTHESIS;
case '.':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return c;
case '%':
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return ESCAPE_PERCENT;
default:
if (c == escape_char) {
- (void)input_stack::get(NULL);
+ (void)input_stack::get(0);
return c;
}
else
@@ -1007,6 +1002,226 @@ static node *do_special();
static node *do_suppress();
static void do_register();
+dictionary color_dictionary(501);
+
+static color *lookup_color(symbol nm)
+{
+ assert(!nm.is_null());
+ color *c = (color *)color_dictionary.lookup(nm);
+ if (c == 0)
+ warning(WARN_COLOR, "`%1' not defined", nm.contents());
+ return c;
+}
+
+static color *default_black(color *c)
+{
+ if (c == 0)
+ return lookup_color(symbol("black"));
+ else
+ return c;
+}
+
+static node *do_glyph_color(symbol nm)
+{
+ if (nm.is_null())
+ return 0;
+ if (nm == symbol("P"))
+ curenv->set_glyph_color(default_black(curenv->get_prev_glyph_color()));
+ else {
+ color *tem = lookup_color(nm);
+ if (tem)
+ curenv->set_glyph_color(tem);
+ else {
+ tem = new color;
+ tem->set_cmyk((unsigned int)0, (unsigned int)0,
+ (unsigned int)0, (unsigned int)0);
+ (void)color_dictionary.lookup(nm, tem);
+ }
+ }
+ return new glyph_color_node(default_black(curenv->get_glyph_color()));
+}
+
+static node *do_fill_color(symbol nm)
+{
+ if (nm.is_null())
+ return 0;
+ if (nm == symbol("P"))
+ curenv->set_fill_color(default_black(curenv->get_prev_fill_color()));
+ else {
+ color *tem = lookup_color(nm);
+ if (tem)
+ curenv->set_fill_color(tem);
+ else {
+ tem = new color;
+ tem->set_cmyk((unsigned int)0, (unsigned int)0,
+ (unsigned int)0, (unsigned int)0);
+ (void)color_dictionary.lookup(nm, tem);
+ }
+ }
+ return new fill_color_node(default_black(curenv->get_fill_color()));
+}
+
+static unsigned int get_color_element(const char *scheme, const char *color)
+{
+ units val;
+ if (!get_number(&val, 'f')) {
+ warning(WARN_COLOR, "%1 in %2 definition set to 0", color, scheme);
+ tok.next();
+ return 0;
+ }
+ if (val < 0) {
+ warning(WARN_RANGE, "%1 cannot be negative: set to 0", color);
+ return 0;
+ }
+ if (val > 65536) {
+ warning(WARN_RANGE, "%1 cannot be greater than 1", color);
+ return 65535; // this is 0xffff
+ }
+ return (unsigned int)val;
+}
+
+static color *read_rgb()
+{
+ symbol component = get_long_name(0);
+ if (component.is_null()) {
+ warning(WARN_COLOR, "missing rgb color values");
+ return 0;
+ }
+ const char *s = component.contents();
+ color *col = new color;
+ if (*s == '#') {
+ if (!col->read_rgb(s)) {
+ warning(WARN_COLOR, "expecting rgb color definition not `%1'", s);
+ delete col;
+ return 0;
+ }
+ }
+ else {
+ input_stack::push(make_temp_iterator(" "));
+ input_stack::push(make_temp_iterator(s));
+ unsigned int r = get_color_element("rgb color", "red component");
+ unsigned int g = get_color_element("rgb color", "green component");
+ unsigned int b = get_color_element("rgb color", "blue component");
+ col->set_rgb(r, g, b);
+ }
+ return col;
+}
+
+static color *read_cmy()
+{
+ symbol component = get_long_name(0);
+ if (component.is_null()) {
+ warning(WARN_COLOR, "missing cmy color values");
+ return 0;
+ }
+ const char *s = component.contents();
+ color *col = new color;
+ if (*s == '#') {
+ if (!col->read_cmy(s)) {
+ warning(WARN_COLOR, "expecting cmy color definition not `%1'", s);
+ delete col;
+ return 0;
+ }
+ }
+ else {
+ input_stack::push(make_temp_iterator(" "));
+ input_stack::push(make_temp_iterator(s));
+ unsigned int c = get_color_element("cmy color", "cyan component");
+ unsigned int m = get_color_element("cmy color", "magenta component");
+ unsigned int y = get_color_element("cmy color", "yellow component");
+ col->set_cmy(c, m, y);
+ }
+ return col;
+}
+
+static color *read_cmyk()
+{
+ symbol component = get_long_name(0);
+ if (component.is_null()) {
+ warning(WARN_COLOR, "missing cmyk color values");
+ return 0;
+ }
+ const char *s = component.contents();
+ color *col = new color;
+ if (*s == '#') {
+ if (!col->read_cmyk(s)) {
+ warning(WARN_COLOR, "`expecting a cmyk color definition not `%1'", s);
+ delete col;
+ return 0;
+ }
+ }
+ else {
+ input_stack::push(make_temp_iterator(" "));
+ input_stack::push(make_temp_iterator(s));
+ unsigned int c = get_color_element("cmyk color", "cyan component");
+ unsigned int m = get_color_element("cmyk color", "magenta component");
+ unsigned int y = get_color_element("cmyk color", "yellow component");
+ unsigned int k = get_color_element("cmyk color", "black component");
+ col->set_cmyk(c, m, y, k);
+ }
+ return col;
+}
+
+static color *read_gray()
+{
+ symbol component = get_long_name(0);
+ if (component.is_null()) {
+ warning(WARN_COLOR, "missing gray values");
+ return 0;
+ }
+ const char *s = component.contents();
+ color *col = new color;
+ if (*s == '#') {
+ if (!col->read_gray(s)) {
+ warning(WARN_COLOR, "`expecting a gray definition not `%1'", s);
+ delete col;
+ return 0;
+ }
+ }
+ else {
+ input_stack::push(make_temp_iterator(" "));
+ input_stack::push(make_temp_iterator(s));
+ unsigned int g = get_color_element("gray", "gray value");
+ col->set_gray(g);
+ }
+ return col;
+}
+
+static void define_color()
+{
+ symbol color_name = get_long_name(1);
+ if (color_name.is_null()) {
+ skip_line();
+ return;
+ }
+ symbol style = get_long_name(1);
+ if (style.is_null()) {
+ skip_line();
+ return;
+ }
+ color *col;
+ if (strcmp(style.contents(), "rgb") == 0)
+ col = read_rgb();
+ else if (strcmp(style.contents(), "cmyk") == 0)
+ col = read_cmyk();
+ else if (strcmp(style.contents(), "gray") == 0)
+ col = read_gray();
+ else if (strcmp(style.contents(), "grey") == 0)
+ col = read_gray();
+ else if (strcmp(style.contents(), "cmy") == 0)
+ col = read_cmy();
+ else {
+ warning(WARN_COLOR,
+ "unknown color space definition `%1', "
+ "use rgb, cmyk or gray", style.contents());
+ skip_line();
+ return;
+ }
+ if (col)
+ (void)color_dictionary.lookup(color_name, col);
+ skip_line();
+}
+
static node *do_overstrike()
{
token start;
@@ -1447,7 +1662,7 @@ void token::next()
}
else {
handle_escape_char:
- cc = input_stack::get(NULL);
+ cc = input_stack::get(0);
switch(cc) {
case '(':
nm = read_two_char_escape_name();
@@ -1497,7 +1712,7 @@ void token::next()
case ':':
goto ESCAPE_COLON;
case '"':
- while ((cc = input_stack::get(NULL)) != '\n' && cc != EOF)
+ while ((cc = input_stack::get(0)) != '\n' && cc != EOF)
;
if (cc == '\n')
type = TOKEN_NEWLINE;
@@ -1505,7 +1720,7 @@ void token::next()
type = TOKEN_EOF;
return;
case '#': // Like \" but newline is ignored.
- while ((cc = input_stack::get(NULL)) != '\n')
+ while ((cc = input_stack::get(0)) != '\n')
if (cc == EOF) {
type = TOKEN_EOF;
return;
@@ -1623,6 +1838,18 @@ void token::next()
nd = new vline_node(x, n);
return;
}
+ case 'm':
+ nd = do_glyph_color(read_escape_name());
+ if (!nd)
+ break;
+ type = TOKEN_NODE;
+ return;
+ case 'M':
+ nd = do_fill_color(read_escape_name());
+ if (!nd)
+ break;
+ type = TOKEN_NODE;
+ return;
case 'n':
{
int inc;
@@ -3229,16 +3456,16 @@ void read_request()
int reading_from_terminal = isatty(fileno(stdin));
int had_prompt = 0;
if (!tok.newline() && !tok.eof()) {
- int c = get_copy(NULL);
+ int c = get_copy(0);
while (c == ' ')
- c = get_copy(NULL);
+ c = get_copy(0);
while (c != EOF && c != '\n' && c != ' ') {
if (!illegal_input_char(c)) {
if (reading_from_terminal)
fputc(c, stderr);
had_prompt = 1;
}
- c = get_copy(NULL);
+ c = get_copy(0);
}
if (c == ' ') {
tok.make_space();
@@ -4122,6 +4349,11 @@ static symbol get_delim_file_name()
char *buf = abuf;
int buf_size = ABUF_SIZE;
int i = 0;
+ // move over initial spaces
+ while (tok.ch() == 0)
+ tok.next();
+ if ((buf[i] = start.ch()) != 0)
+ i++;
for (;;) {
if (i + 1 > buf_size) {
if (buf == abuf) {
@@ -4137,9 +4369,6 @@ static symbol get_delim_file_name()
a_delete old_buf;
}
}
- tok.next();
- if (tok.ch() == ']' && input_stack::get_level() == start_level)
- break;
if ((buf[i] = tok.ch()) == 0) {
error("missing delimiter (got %1)", tok.description());
if (buf != abuf)
@@ -4147,6 +4376,9 @@ static symbol get_delim_file_name()
return NULL_SYMBOL;
}
i++;
+ tok.next();
+ if (tok.ch() == ']' && input_stack::get_level() == start_level)
+ break;
}
buf[i] = '\0';
if (buf == abuf) {
@@ -4431,18 +4663,17 @@ node *do_suppress()
case '4':
begin_level--;
break;
- case '5': {
- symbol filename = get_delim_file_name();
- tok.next();
- if (filename.is_null()) {
- error("missing filename as second argument to \\O");
- return 0;
+ case '5':
+ {
+ symbol filename = get_delim_file_name();
+ if (filename.is_null()) {
+ error("missing filename as second argument to \\O");
+ return 0;
+ }
+ if (begin_level == 1)
+ return new suppress_node(filename, 'i');
}
- if (begin_level == 1)
- return new suppress_node(filename, 'i');
- return 0;
break;
- }
default:
error("`%1' is an invalid argument to \\O", char(c));
}
@@ -4454,7 +4685,7 @@ void special_node::tprint(troff_output_file *out)
tprint_start(out);
string_iterator iter(mac);
for (;;) {
- int c = iter.get(NULL);
+ int c = iter.get(0);
if (c == EOF)
break;
for (const char *s = ::asciify(c); *s; s++)
@@ -4504,7 +4735,7 @@ static void skip_alternative()
level++;
int c;
for (;;) {
- c = input_stack::get(NULL);
+ c = input_stack::get(0);
if (c == EOF)
break;
if (c == ESCAPE_LEFT_BRACE)
@@ -4512,7 +4743,7 @@ static void skip_alternative()
else if (c == ESCAPE_RIGHT_BRACE)
--level;
else if (c == escape_char && escape_char > 0)
- switch(input_stack::get(NULL)) {
+ switch(input_stack::get(0)) {
case '{':
++level;
break;
@@ -4520,7 +4751,7 @@ static void skip_alternative()
--level;
break;
case '"':
- while ((c = input_stack::get(NULL)) != '\n' && c != EOF)
+ while ((c = input_stack::get(0)) != '\n' && c != EOF)
;
}
/*
@@ -4594,6 +4825,15 @@ int do_if_request()
? request_dictionary.lookup(nm) != 0
: number_reg_dictionary.lookup(nm) != 0);
}
+ else if (c == 'm') {
+ tok.next();
+ symbol nm = get_long_name(1);
+ if (nm.is_null()) {
+ skip_alternative();
+ return 0;
+ }
+ result = (color_dictionary.lookup(nm) != 0);
+ }
else if (c == 'c') {
tok.next();
tok.skip();
@@ -4786,7 +5026,7 @@ void while_request()
input_stack::push(new string_iterator(mac, "while loop"));
tok.next();
if (!do_if_request()) {
- while (input_stack::get(NULL) != EOF)
+ while (input_stack::get(0) != EOF)
;
break;
}
@@ -4810,7 +5050,7 @@ void while_break_request()
}
else {
while_break_flag = 1;
- while (input_stack::get(NULL) != EOF)
+ while (input_stack::get(0) != EOF)
;
tok.next();
}
@@ -4823,7 +5063,7 @@ void while_continue_request()
skip_line();
}
else {
- while (input_stack::get(NULL) != EOF)
+ while (input_stack::get(0) != EOF)
;
tok.next();
}
@@ -4866,12 +5106,12 @@ void pipe_source()
error("missing command");
else {
int c;
- while ((c = get_copy(NULL)) == ' ' || c == '\t')
+ while ((c = get_copy(0)) == ' ' || c == '\t')
;
int buf_size = 24;
char *buf = new char[buf_size];
int buf_used = 0;
- for (; c != '\n' && c != EOF; c = get_copy(NULL)) {
+ for (; c != '\n' && c != EOF; c = get_copy(0)) {
const char *s = asciify(c);
int slen = strlen(s);
if (buf_used + slen + 1> buf_size) {
@@ -5011,7 +5251,8 @@ void do_ps_file(FILE *fp, const char* filename)
if (res == 1) {
assign_registers(bb.llx, bb.lly, bb.urx, bb.ury);
return;
- } else if (res == 2) {
+ }
+ else if (res == 2) {
bb_at_end = 1;
break;
}
@@ -5207,15 +5448,15 @@ void do_terminal(int newline, int string_like)
if (!tok.newline() && !tok.eof()) {
int c;
for (;;) {
- c = get_copy(NULL);
+ c = get_copy(0);
if (string_like && c == '"') {
- c = get_copy(NULL);
+ c = get_copy(0);
break;
}
if (c != ' ' && c != '\t')
break;
}
- for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ for (; c != '\n' && c != EOF; c = get_copy(0))
fputs(asciify(c), stderr);
}
if (newline)
@@ -5312,11 +5553,11 @@ void write_request()
return;
}
int c;
- while ((c = get_copy(NULL)) == ' ')
+ while ((c = get_copy(0)) == ' ')
;
if (c == '"')
- c = get_copy(NULL);
- for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ c = get_copy(0);
+ for (; c != '\n' && c != EOF; c = get_copy(0))
fputs(asciify(c), fp);
fputc('\n', fp);
fflush(fp);
@@ -5788,7 +6029,7 @@ void abort_request()
if (c == EOF || c == '\n')
fputs("User Abort.", stderr);
else {
- for (; c != '\n' && c != EOF; c = get_copy(NULL))
+ for (; c != '\n' && c != EOF; c = get_copy(0))
fputs(asciify(c), stderr);
}
fputc('\n', stderr);
@@ -6122,7 +6363,7 @@ static int evaluate_expression(const char *expr, units *res)
input_stack::push(make_temp_iterator(expr));
tok.next();
int success = get_number(res, 'u');
- while (input_stack::get(NULL) != EOF)
+ while (input_stack::get(0) != EOF)
;
return success;
}
@@ -6201,7 +6442,7 @@ static void add_string(const char *s, string_list **p)
void usage(FILE *stream, const char *prog)
{
fprintf(stream,
-"usage: %s -abivzCERU -wname -Wname -dcs -ffam -mname -nnum -olist\n"
+"usage: %s -abcivzCERU -wname -Wname -dcs -ffam -mname -nnum -olist\n"
" -rcn -Tname -Fdir -Mdir [files...]\n",
prog);
}
@@ -6237,10 +6478,10 @@ int main(int argc, char **argv)
static const struct option long_options[] = {
{ "help", no_argument, 0, CHAR_MAX + 1 },
{ "version", no_argument, 0, 'v' },
- { NULL, 0, 0, 0 }
+ { 0, 0, 0, 0 }
};
- while ((c = getopt_long(argc, argv, "abivw:W:zCEf:m:n:o:r:d:F:M:T:tqs:RU",
- long_options, NULL))
+ while ((c = getopt_long(argc, argv, "abcivw:W:zCEf:m:n:o:r:d:F:M:T:tqs:RU",
+ long_options, 0))
!= EOF)
switch(c) {
case 'v':
@@ -6256,6 +6497,9 @@ int main(int argc, char **argv)
break;
case 'C':
compatible_flag = 1;
+ // fall through
+ case 'c':
+ disable_color_flag = 1;
break;
case 'M':
macro_path.command_line_dir(optarg);
@@ -6565,6 +6809,7 @@ void init_input_requests()
init_request("pso", pipe_source);
#endif /* not POPEN_MISSING */
init_request("psbb", ps_bbox_request);
+ init_request("defcolor", define_color);
number_reg_dictionary.define("systat", new variable_reg(&system_status));
number_reg_dictionary.define("slimit",
new variable_reg(&input_stack::limit));
@@ -6782,6 +7027,7 @@ static struct {
{ "mac", WARN_MAC },
{ "reg", WARN_REG },
{ "ig", WARN_IG },
+ { "color", WARN_COLOR },
{ "all", WARN_TOTAL & ~(WARN_DI | WARN_MAC | WARN_REG) },
{ "w", WARN_TOTAL },
{ "default", DEFAULT_WARNING_MASK },
diff --git a/src/roff/troff/node.cc b/src/roff/troff/node.cc
index 255c4d28..9102869f 100644
--- a/src/roff/troff/node.cc
+++ b/src/roff/troff/node.cc
@@ -36,6 +36,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include "font.h"
#include "reg.h"
#include "input.h"
+#include "geometry.h"
#include "nonposix.h"
@@ -728,6 +729,8 @@ class troff_output_file : public real_output_file {
int current_slant;
int current_height;
tfont *current_tfont;
+ color *current_pagecolor;
+ color *current_glyphcolor;
int current_font_number;
symbol *font_position;
int nfont_positions;
@@ -741,6 +744,7 @@ class troff_output_file : public real_output_file {
void put(unsigned char c);
void put(int i);
void put(const char *s);
+ void put_hex(int i, int length);
void set_font(tfont *tf);
void flush_tbuf();
public:
@@ -767,6 +771,8 @@ public:
void draw(char, hvpair *, int, font_size);
void determine_line_limits (char code, hvpair *point, int npoints);
void check_charinfo(tfont *tf, charinfo *ci);
+ void glyph_color(color *c);
+ void fill_color(color *c);
int get_hpos() { return hpos; }
int get_vpos() { return vpos; }
};
@@ -797,6 +803,23 @@ inline void troff_output_file::put(int i)
put_string(i_to_a(i), fp);
}
+inline void troff_output_file::put_hex(int i, int length)
+{
+ char *a = new char[length+1];
+ a[length] = '\0';
+ while (length > 0) {
+ length--;
+ int j = i % 0x10;
+ if (j <= 9)
+ a[length] = '0' + j;
+ else
+ a[length] = 'a' + (j - 10);
+ i /= 0x10;
+ }
+ put_string(a, fp);
+ a_delete a;
+}
+
void troff_output_file::start_special(tfont *tf, int no_init_string)
{
flush_tbuf();
@@ -931,7 +954,7 @@ void troff_output_file::flush_tbuf()
put(' ');
}
check_output_limits(hpos, vpos);
- check_output_limits(hpos, vpos + current_size + current_height);
+ check_output_limits(hpos, vpos - current_size);
for (int i = 0; i < tbuf_len; i++)
put(tbuf[i]);
@@ -941,15 +964,11 @@ void troff_output_file::flush_tbuf()
void troff_output_file::check_charinfo(tfont *tf, charinfo *ci)
{
- int size = tf->get_size().to_scaled_points();
int height = tf->get_char_height(ci).to_units();
int width = tf->get_width(ci).to_units()
+ tf->get_italic_correction(ci).to_units();
- int depth = tf->get_char_depth(ci).to_units();
- check_output_limits(output_hpos,
- output_vpos - height);
- check_output_limits(output_hpos + width,
- output_vpos + size + depth);
+ check_output_limits(output_hpos, output_vpos - height);
+ check_output_limits(output_hpos + width, output_vpos);
}
void troff_output_file::put_char_width(charinfo *ci, tfont *tf, hunits w,
@@ -1116,6 +1135,36 @@ void troff_output_file::set_font(tfont *tf)
current_tfont = tf;
}
+void troff_output_file::fill_color(color *col)
+{
+ unsigned int r, g, b;
+ if ((current_pagecolor == col) || disable_color_flag)
+ return;
+ col->get_rgb(&r, &g, &b);
+ flush_tbuf();
+ put("DF ##");
+ put_hex(r, 4);
+ put_hex(g, 4);
+ put_hex(b, 4);
+ put('\n');
+ current_pagecolor = col;
+}
+
+void troff_output_file::glyph_color(color *col)
+{
+ unsigned int r, g, b;
+ if ((current_glyphcolor == col) || disable_color_flag)
+ return;
+ col->get_rgb(&r, &g, &b);
+ flush_tbuf();
+ put("m ##");
+ put_hex(r, 4);
+ put_hex(g, 4);
+ put_hex(b, 4);
+ put('\n');
+ current_glyphcolor = col;
+}
+
// determine_line_limits - works out the smallest box which will contain
// the entity, code, built from the point array.
void troff_output_file::determine_line_limits(char code, hvpair *point,
@@ -1158,8 +1207,37 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
check_output_limits(x, y);
}
break;
+ case 'a':
+ double c[2];
+ int p[4];
+ int minx, miny, maxx, maxy;
+ x = output_hpos;
+ y = output_vpos;
+ p[0] = point[0].h.to_units();
+ p[1] = point[0].v.to_units();
+ p[2] = point[1].h.to_units();
+ p[3] = point[1].v.to_units();
+ if (adjust_arc_center(p, c)) {
+ check_output_arc_limits(x, y,
+ p[0], p[1], p[2], p[3],
+ c[0], c[1],
+ &minx, &maxx, &miny, &maxy);
+ check_output_limits(minx, miny);
+ check_output_limits(maxx, maxy);
+ break;
+ }
+ // fall through
+ case 'l':
+ x = output_hpos;
+ y = output_vpos;
+ check_output_limits(x, y);
+ for (i = 0; i < npoints; i++) {
+ x += point[i].h.to_units();
+ y += point[i].v.to_units();
+ check_output_limits(x, y);
+ }
+ break;
default:
- // remember this doesn't work for arc.. yet
x = output_hpos;
y = output_vpos;
for (i = 0; i < npoints; i++) {
@@ -3590,6 +3668,80 @@ hunits suppress_node::width()
return H0;
}
+/* glyph color_node */
+
+glyph_color_node::glyph_color_node(color *col)
+: c(col)
+{
+}
+
+int glyph_color_node::same(node *n)
+{
+ return (c == ((glyph_color_node *)n)->c);
+}
+
+const char *glyph_color_node::type()
+{
+ return "glyph_color_node";
+}
+
+int glyph_color_node::force_tprint()
+{
+ return 0;
+}
+
+node *glyph_color_node::copy()
+{
+ return new glyph_color_node(c);
+}
+
+hunits glyph_color_node::width()
+{
+ return H0;
+}
+
+void glyph_color_node::tprint(troff_output_file *out)
+{
+ out->glyph_color(c);
+}
+
+/* page color_node */
+
+fill_color_node::fill_color_node(color *col)
+: c(col)
+{
+}
+
+int fill_color_node::same(node *n)
+{
+ return (c == ((fill_color_node *)n)->c);
+}
+
+const char *fill_color_node::type()
+{
+ return "fill_color_node";
+}
+
+int fill_color_node::force_tprint()
+{
+ return 0;
+}
+
+node *fill_color_node::copy()
+{
+ return new fill_color_node(c);
+}
+
+hunits fill_color_node::width()
+{
+ return H0;
+}
+
+void fill_color_node::tprint(troff_output_file *out)
+{
+ out->fill_color(c);
+}
+
/* composite_node */
class composite_node : public charinfo_node {
@@ -5346,7 +5498,7 @@ int symbol_fontno(symbol s)
int is_good_fontno(int n)
{
- return n >= 0 && n < font_table_size && font_table[n] != NULL;
+ return n >= 0 && n < font_table_size && font_table[n] != 0;
}
int get_bold_fontno(int n)
diff --git a/src/roff/troff/node.h b/src/roff/troff/node.h
index a58afed1..0d9793c9 100644
--- a/src/roff/troff/node.h
+++ b/src/roff/troff/node.h
@@ -281,9 +281,9 @@ protected:
unsigned char unformat;
public:
hmotion_node(hunits i, node *next = 0)
- : node(next), n(i), was_tab(0), unformat(0) {}
+ : node(next), n(i), was_tab(0), unformat(0) {}
hmotion_node(hunits i, int flag1, int flag2, node *next = 0)
- : node(next), n(i), was_tab(flag1), unformat(flag2) {}
+ : node(next), n(i), was_tab(flag1), unformat(flag2) {}
node *copy();
int reread(int *);
int set_unformat_flag();
@@ -493,6 +493,30 @@ private:
void put(troff_output_file *out, const char *s);
};
+class glyph_color_node : public node {
+ color *c;
+public:
+ glyph_color_node(color *col);
+ node *copy();
+ void tprint(troff_output_file *);
+ hunits width();
+ int same(node *);
+ const char *type();
+ int force_tprint();
+};
+
+class fill_color_node : public node {
+ color *c;
+public:
+ fill_color_node(color *col);
+ node *copy();
+ void tprint(troff_output_file *);
+ hunits width();
+ int same(node *);
+ const char *type();
+ int force_tprint();
+};
+
struct hvpair {
hunits h;
vunits v;
diff --git a/src/roff/troff/number.cc b/src/roff/troff/number.cc
index 53938428..d79298e6 100644
--- a/src/roff/troff/number.cc
+++ b/src/roff/troff/number.cc
@@ -234,7 +234,7 @@ static int start_number()
enum { OP_LEQ = 'L', OP_GEQ = 'G', OP_MAX = 'X', OP_MIN = 'N' };
-#define SCALE_INDICATOR_CHARS "icPmnpuvMsz"
+#define SCALE_INDICATOR_CHARS "icfPmnpuvMsz"
static int parse_term(units *v, int scale_indicator,
int parenthesised, int rigid);
@@ -590,6 +590,9 @@ static int parse_term(units *v, int scale_indicator,
if (divisor != 1)
*v /= divisor;
break;
+ case 'f':
+ *v = scale(*v, 65536, divisor);
+ break;
case 'p':
*v = scale(*v, units_per_inch, divisor*72);
break;
diff --git a/src/roff/troff/troff.h b/src/roff/troff/troff.h
index 17d45da2..48e72a6e 100644
--- a/src/roff/troff/troff.h
+++ b/src/roff/troff/troff.h
@@ -29,6 +29,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
#include <errno.h>
#include "assert.h"
+#include "color.h"
#include "device.h"
#include "searchpath.h"
@@ -42,6 +43,7 @@ extern units units_per_inch;
extern int ascii_output_flag;
extern int suppress_output_flag;
+extern int disable_color_flag;
extern int is_html;
extern int tcommand_flag;
@@ -75,11 +77,12 @@ enum warning_type {
WARN_ESCAPE = 0100000,
WARN_SPACE = 0200000,
WARN_FONT = 0400000,
- WARN_IG = 01000000
+ WARN_IG = 01000000,
+ WARN_COLOR = 02000000
// change WARN_TOTAL if you add more warning types
};
-const int WARN_TOTAL = 01777777;
+const int WARN_TOTAL = 02777777;
int warning(warning_type, const char *,
const errarg & = empty_errarg,
diff --git a/src/roff/troff/troff.man b/src/roff/troff/troff.man
index fc663153..7f81c228 100644
--- a/src/roff/troff/troff.man
+++ b/src/roff/troff/troff.man
@@ -65,7 +65,7 @@ the original English.
.ie \\n(.$-1 .RI "[\ \fB\\$1\fP" "\\$2" "\ ]"
.el .RB "[\ " "\\$1" "\ ]"
..
-.OP \-abivzCERU
+.OP \-abcivzCERU
.OP \-w name
.OP \-W name
.OP \-d cs
@@ -118,6 +118,9 @@ or
.B am
requests.
.TP
+.B \-c
+Disable color output (always disabled in compatibility mode).
+.TP
.B \-i
Read the standard input after all the named input files have been
processed.
@@ -278,9 +281,9 @@ Only the features not in UNIX troff are described here.
.
.SS Long names
.
-The names of number registers, fonts, strings/macros/diversions,
-special characters can be of any length. In escape sequences, where
-you can use
+The names of number registers, fonts, strings/\:macros/\:diversions,
+special characters, and colors can be of any length.
+In escape sequences, where you can use
.BI ( xx
for a two character name, you can use
.BI [ xxx ]
@@ -394,6 +397,12 @@ Spaces are permitted in a number expression within parentheses.
.LP
.B M
indicates a scale of 100ths of an em.
+.B f
+indicates a scale of 65536 units, providing fractions for color definitions
+with
+.B defcolor
+request.
+For example, 0.5f = 32768u.
.TP
.IB e1 >? e2
The maximum of
@@ -482,6 +491,26 @@ gets interpreted in copy-mode
(for example, by being used in a macro argument).
.RE
.TP
+.BI \em x
+.TQ
+.BI \em( xx
+.TQ
+.BI \em[ xxx ]
+Set drawing color.
+.B \emP
+switches back to the previous color.
+.TP
+.BI \eM x
+.TQ
+.BI \eM( xx
+.TQ
+.BI \eM[ xxx ]
+Set background color for filled objects drawn with the
+.BI \eD' ... '
+commands.
+.B \eMP
+switches back to the previous color.
+.TP
.BI \eN' n '
Typeset the character with code
.I n
@@ -965,6 +994,52 @@ disable it.
In compatibility mode, long names are not recognised, and the
incompatibilities caused by long names do not arise.
.TP
+.BI .defcolor\ xxx\ scheme\ color_components
+Define color.
+.I scheme
+can be one of the following values:
+.B rgb
+(three components),
+.B cym
+(three components),
+.B cmyk
+(four components), and
+.B gray
+or
+.B grey
+(one component).
+Color components can be given either as a hexadecimal string or as positive
+decimal integers in the range 0-65535.
+A hexadecimal string contains all color components concatenated.
+It must start with either
+.B #
+or
+.BR ## ;
+the former specifies hex values in the range 0-255 (which are internally
+multiplied by\~257), the latter in the range 0-65535.
+Examples: #FFC0CB (pink), ##ffff0000ffff (magenta).
+A new scaling indicator
+.B f
+has been introduced which multiplies its value by 65536; this makes it
+convenient to specify color components as fractions in the range 0 to\~1.
+Example:
+.RS
+.IP
+.B
+\&.defcolor darkgreen rgb 0.1f 0.5f 0.2f
+.RE
+.IP
+Note that
+.B f
+is the default scaling indicator for the
+.B defcolor
+request, thus the above statement is equivalent to
+.RS
+.IP
+.B
+\&.defcolor darkgreen rgb 0.1 0.5 0.2
+.RE
+.TP
.BI .dei\ xx\ yy
Define macro indirectly.
The following example
@@ -2125,6 +2200,10 @@ True if there is a number register named
True if there is a string, macro, diversion, or request named
.IR xxx .
.TP
+.BI .if\ m xxx
+True if there is a color named
+.IR xxx .
+.TP
.BI .if\ c ch
True if there is a character
.IR ch
@@ -2260,6 +2339,9 @@ Illegal escapes in text ignored with the
request.
These are conditions that are errors when they do not occur
in ignored text.
+.TP
+.BR color \t524288
+Color related warnings.
.LP
There are also names that can be used to refer to groups of warnings:
.TP
diff --git a/test-groff b/test-groff
index 4e06e962..15df490d 100644
--- a/test-groff
+++ b/test-groff
@@ -12,6 +12,7 @@ then
fi
GROFF_BIN_PATH=\
+$builddir/roff/groff:\
$builddir/roff/troff:\
$builddir/preproc/pic:\
$builddir/preproc/eqn:\
diff --git a/tmac/Makefile.sub b/tmac/Makefile.sub
index 954e177f..6d1b1352 100644
--- a/tmac/Makefile.sub
+++ b/tmac/Makefile.sub
@@ -20,7 +20,8 @@ NORMALFILES=\
tty.tmac tty-char.tmac latin1.tmac \
X.tmac Xps.tmac \
lj4.tmac \
- html.tmac mwww.tmac www.tmac \
+ html.tmac mwww.tmac www.tmac color-html.tmac \
+ color.tmac \
eqnrc \
troffrc troffrc-end \
hyphen.us
diff --git a/tmac/troffrc b/tmac/troffrc
index c4cfa20f..dd5597db 100644
--- a/tmac/troffrc
+++ b/tmac/troffrc
@@ -1,6 +1,8 @@
.\" Startup file for troff.
+.
.\" This is tested by pic.
.nr 0p 0
+.
.\" Use .do here, so that it works with -C.
.\" The groff command defines the .X string if the -X option was given.
.ie r.X .do ds troffrc!ps Xps.tmac
@@ -21,10 +23,18 @@
. do mso \*[troffrc!\*[.T]]
.do rm troffrc!ps troffrc!Xps troffrc!dvi troffrc!X75 troffrc!X75-12 \
troffrc!X100 troffrc!X100-12 troffrc!lj4 troff!lbp troffrc!html
-.ie '\*(.T'cp1047' .do tr \[char65]
-.el .do tr \[char160]
+.
+.\" now load up the color definitions
+.do if '\*[.T]'html' .do mso color-html.tmac
+.do if !'\*[.T]'html' .do mso color.tmac
+.
+.ie '\*(.T'cp1047' .do tr \[char65]\~
+.el .do tr \[char160]\~
+.
.\" Set the hyphenation language to `us'.
.do hla us
+.
.\" Load hyphenation patterns from `hyphen.us' (in the tmac directory).
.do hpf hyphen.us
+.
.\" Don't let blank lines creep in here.
diff --git a/tmac/troffrc-end b/tmac/troffrc-end
index f786059d..928c923d 100644
--- a/tmac/troffrc-end
+++ b/tmac/troffrc-end
@@ -1,14 +1,13 @@
-.\"
.\" final startup file for troff
+.
.\" this file is parsed after all macro sets have been read
-.\"
+.
.do if '\*[.T]'html' .do mso html.tmac
+.
.\" if we are running the postscript device for html images then load www.tmac
-.\"
.do if r ps4html .do mso www.tmac
-.\"
+.
.\" for all other devices blank out these macros
-.\"
.do if !d HTML-IMAGE-INLINE .do ds HTML-IMAGE-INLINE
.do if !d HTML-IMAGE .do ds HTML-IMAGE
.do if !d HTML-IMAGE-RIGHT .do ds HTML-IMAGE-RIGHT
@@ -16,4 +15,5 @@
.do if !d HTML-IMAGE-END .do ds HTML-IMAGE-END
.do if !d HTML-TAG .do ds HTML-TAG
.do if !d HTML-DO-IMAGE .do ds HTML-DO-IMAGE
+.
.\" Don't let blank lines creep in here.
diff --git a/tmac/www.tmac b/tmac/www.tmac
index 0bef6b60..004c351a 100644
--- a/tmac/www.tmac
+++ b/tmac/www.tmac
@@ -46,7 +46,7 @@
. HTML <a href="\\$2">\\$1</a>\\$3
. \}
. el \{\
-\\$1 \%\(la\fC\\$2\fP\(ra\\$3
+\m[blue]\\$1\mP \%\(la\fC\\$2\fP\(ra\\$3
. \}
..
.\"
@@ -58,7 +58,7 @@
. HTML <a href=\\$2>\\$1</a>\\$3
. \}
. el \{\
-\\$1 \%\(la\fC\\$2\fP\(ra\\$3
+\m[blue]\\$1\mP \%\(la\fC\\$2\fP\(ra\\$3
. \}
..
.\"
@@ -87,10 +87,10 @@
. \}
. el \{\
. ie '\\$2'' \{\
-\fC\\$1\fP\\$3
+\m[blue]\fC\\$1\fP\mP\\$3
. \}
. el \{\
-\\$2 \%\(la\fC\\$1\fP\(ra\\$3
+\m[blue]\\$2\mP \%\(la\fC\\$1\fP\(ra\\$3
. \}
. \}
..