From 4c1676f8f2e0b7baff0f5b4ca019ce38aefbfd51 Mon Sep 17 00:00:00 2001 From: "Emden R. Gansner" <erg@alum.mit.edu> Date: Sun, 9 Mar 2014 16:16:06 -0400 Subject: [PATCH] Support text overlining. --- doc/info/output.html | 4 +++- doc/infosrc/outputs | 4 +++- lib/common/htmllex.c | 11 +++++++++++ lib/common/htmlparse.y | 12 ++++++++++-- lib/common/textspan.h | 17 ++++++++++------- lib/xdot/xdot.c | 14 +++++++++++++- lib/xdot/xdot.h | 2 +- plugin/core/gvrender_core_dot.c | 8 +++++--- plugin/core/gvrender_core_svg.c | 8 ++++++-- plugin/pango/gvrender_pango.c | 10 ++++++++++ 10 files changed, 72 insertions(+), 18 deletions(-) diff --git a/doc/info/output.html b/doc/info/output.html index 00248da36..2f49b8c09 100644 --- a/doc/info/output.html +++ b/doc/info/output.html @@ -215,7 +215,8 @@ n bytes following '-'. The text should be left-aligned (centered, right-aligned) on the point if j is -1 (0, 1), respectively. The value w gives the width of the text as computed by the library. <TR><TD>t f -<TD>Set font characteristics. The integer f is the OR of BOLD=1, ITALIC=2, UNDERLINE=4, SUPERSCRIPT=8, SUBSCRIPT=16, and STRIKE-THROUGH=32. (1.5) +<TD>Set font characteristics. The integer f is the OR of BOLD=1, ITALIC=2, UNDERLINE=4, SUPERSCRIPT=8, SUBSCRIPT=16, (1.5) STRIKE-THROUGH=32 (1.6), +and OVERLINE=64 (1.7). <TR><TD>C n -<I>b<sub>1</sub>b<sub>2</sub>...b<sub>n</sub></I> <TD>Set fill color. The color value consists of the n bytes following '-'. (1.1) @@ -297,6 +298,7 @@ Version info: <TR><TD>1.4</TD><TD>2.32</TD><TD>Add gradient colors</TD</TR> <TR><TD>1.5</TD><TD>2.34</TD><TD>Fix text layout problem; fix inverted vector in gradient; support version-specific output; new <B>t</B> op for text characteristics</TD</TR> <TR><TD>1.6</TD><TD>2.35</TD><TD>Add STRIKE-THROUGH bit for <tt>t</tt></TD</TR> +<TR><TD>1.7</TD><TD>2.37</TD><TD>Add OVERLINE for <tt>t</tt></TD</TR> </TABLE> <DT><A NAME=d:cgimage HREF=#a:cgimage><STRONG>cgimage</STRONG></A> diff --git a/doc/infosrc/outputs b/doc/infosrc/outputs index 73fe19ce2..1917c89d1 100644 --- a/doc/infosrc/outputs +++ b/doc/infosrc/outputs @@ -259,7 +259,8 @@ n bytes following '-'. The text should be left-aligned (centered, right-aligned) on the point if j is -1 (0, 1), respectively. The value w gives the width of the text as computed by the library. <TR><TD>t f -<TD>Set font characteristics. The integer f is the OR of BOLD=1, ITALIC=2, UNDERLINE=4, SUPERSCRIPT=8, SUBSCRIPT=16, and STRIKE-THROUGH=32. (1.5) +<TD>Set font characteristics. The integer f is the OR of BOLD=1, ITALIC=2, UNDERLINE=4, SUPERSCRIPT=8, SUBSCRIPT=16, (1.5) STRIKE-THROUGH=32 (1.6), +and OVERLINE=64 (1.7). <TR><TD>C n -<I>b<sub>1</sub>b<sub>2</sub>...b<sub>n</sub></I> <TD>Set fill color. The color value consists of the n bytes following '-'. (1.1) @@ -341,6 +342,7 @@ Version info: <TR><TD>1.4</TD><TD>2.32</TD><TD>Add gradient colors</TD</TR> <TR><TD>1.5</TD><TD>2.34</TD><TD>Fix text layout problem; fix inverted vector in gradient; support version-specific output; new <B>t</B> op for text characteristics</TD</TR> <TR><TD>1.6</TD><TD>2.35</TD><TD>Add STRIKE-THROUGH bit for <tt>t</tt></TD</TR> +<TR><TD>1.7</TD><TD>2.37</TD><TD>Add OVERLINE for <tt>t</tt></TD</TR> </TABLE> :plain/plain-ext:Simple text format The plain and plain-ext formats produce output using diff --git a/lib/common/htmllex.c b/lib/common/htmllex.c index 067efa6c1..c4a1dd99b 100644 --- a/lib/common/htmllex.c +++ b/lib/common/htmllex.c @@ -657,6 +657,9 @@ static void startElement(void *user, const char *name, char **atts) } else if (strcasecmp(name, "U") == 0) { htmllval.font = mkFont(gvc, 0, HTML_UL, 1); state.tok = T_underline; + } else if (strcasecmp(name, "O") == 0) { + htmllval.font = mkFont(gvc, 0, HTML_OL, 1); + state.tok = T_overline; } else if (strcasecmp(name, "I") == 0) { htmllval.font = mkFont(gvc, 0, HTML_IF, 0); state.tok = T_italic; @@ -702,6 +705,8 @@ static void endElement(void *user, const char *name) state.tok = T_n_bold; } else if (strcasecmp(name, "U") == 0) { state.tok = T_n_underline; + } else if (strcasecmp(name, "O") == 0) { + state.tok = T_n_overline; } else if (strcasecmp(name, "I") == 0) { state.tok = T_n_italic; } else if (strcasecmp(name, "SUP") == 0) { @@ -956,6 +961,12 @@ static void printTok(int tok) case T_n_underline: s = "T_n_underline"; break; + case T_overline: + s = "T_overline"; + break; + case T_n_overline: + s = "T_n_overline"; + break; case T_italic: s = "T_italic"; break; diff --git a/lib/common/htmlparse.y b/lib/common/htmlparse.y index 7a7dfb0c5..4d1656533 100644 --- a/lib/common/htmlparse.y +++ b/lib/common/htmlparse.y @@ -424,14 +424,14 @@ popFont (void) %token T_end_br T_end_img T_row T_end_row T_html T_end_html %token T_end_table T_end_cell T_end_font T_string T_error -%token T_n_italic T_n_bold T_n_underline T_n_sup T_n_sub T_n_s +%token T_n_italic T_n_bold T_n_underline T_n_overline T_n_sup T_n_sub T_n_s %token T_HR T_hr T_end_hr %token T_VR T_vr T_end_vr %token <i> T_BR T_br %token <img> T_IMG T_img %token <tbl> T_table %token <cell> T_cell -%token <font> T_font T_italic T_bold T_underline T_sup T_sub T_s +%token <font> T_font T_italic T_bold T_underline T_overline T_sup T_sub T_s %type <txt> fonttext %type <cell> cell cells @@ -461,6 +461,7 @@ textitem : string { appendFItemList(HTMLstate.str);} | font text n_font | italic text n_italic | underline text n_underline + | overline text n_overline | bold text n_bold | sup text n_sup | sub text n_sub @@ -497,6 +498,12 @@ underline : T_underline {pushFont($1);} n_underline : T_n_underline {popFont();} ; +overline : T_overline {pushFont($1);} + ; + +n_overline : T_n_overline {popFont();} + ; + sup : T_sup {pushFont($1);} ; @@ -542,6 +549,7 @@ fonttable : table { $$ = $1; } | font table n_font { $$=$2; } | italic table n_italic { $$=$2; } | underline table n_underline { $$=$2; } + | overline table n_overline { $$=$2; } | bold table n_bold { $$=$2; } ; diff --git a/lib/common/textspan.h b/lib/common/textspan.h index 4682e20c4..64ba97fc5 100644 --- a/lib/common/textspan.h +++ b/lib/common/textspan.h @@ -19,12 +19,15 @@ extern "C" { #endif /* Bold, Italic, Underline, Sup, Sub, Strike */ -#define HTML_BF 1 -#define HTML_IF 2 -#define HTML_UL 4 -#define HTML_SUP 8 -#define HTML_SUB 16 -#define HTML_S 32 +/* Stored in textfont_t.flags, which is 7 bits, so full */ +/* Probably should be moved to textspan_t */ +#define HTML_BF (1 << 0) +#define HTML_IF (1 << 1) +#define HTML_UL (1 << 2) +#define HTML_SUP (1 << 3) +#define HTML_SUB (1 << 4) +#define HTML_S (1 << 5) +#define HTML_OL (1 << 6) typedef struct _PostscriptAlias { char* name; @@ -47,7 +50,7 @@ extern "C" { char* color; PostscriptAlias *postscript_alias; double size; - int flags:7; /* HTML_UL, HTML_IF, HTML_BF, etc. */ + unsigned int flags:7; /* HTML_UL, HTML_IF, HTML_BF, etc. */ unsigned int cnt:(sizeof(unsigned int) * 8 - 7); /* reference count */ } textfont_t; diff --git a/lib/xdot/xdot.c b/lib/xdot/xdot.c index 14227684f..562f3636c 100755 --- a/lib/xdot/xdot.c +++ b/lib/xdot/xdot.c @@ -101,6 +101,7 @@ static char *parseReal(char *s, double *fp) return (p); } + static char *parseInt(char *s, int *ip) { char* endp; @@ -118,6 +119,17 @@ static char *parseInt(char *s, int *ip) return endp; } +static char *parseUInt(char *s, unsigned int *ip) +{ + char* endp; + + *ip = (unsigned int)strtoul (s, &endp, 10); + if (s == endp) + return 0; + else + return endp; +} + #ifdef UNUSED static char *parsePoint(char *s, xdot_point * pp) { @@ -393,7 +405,7 @@ static char *parseOp(xdot_op * op, char *s, drawfunc_t ops[], int* error) case 't': op->kind = xd_fontchar; - s = parseInt(s, &op->u.fontchar); + s = parseUInt(s, &op->u.fontchar); CHK(s); if (ops) op->drawfunc = ops[xop_fontchar]; diff --git a/lib/xdot/xdot.h b/lib/xdot/xdot.h index 3323b6b41..94f34accf 100755 --- a/lib/xdot/xdot.h +++ b/lib/xdot/xdot.h @@ -128,7 +128,7 @@ struct _xdot_op { xdot_color grad_color; /* xd_grad_fill_color, xd_grad_pen_color */ xdot_font font; /* xd_font */ char* style; /* xd_style */ - int fontchar; /* xd_fontchar */ + unsigned int fontchar; /* xd_fontchar */ } u; drawfunc_t drawfunc; }; diff --git a/plugin/core/gvrender_core_dot.c b/plugin/core/gvrender_core_dot.c index bdc8d8e00..d3c3b8f8f 100644 --- a/plugin/core/gvrender_core_dot.c +++ b/plugin/core/gvrender_core_dot.c @@ -54,7 +54,7 @@ typedef enum { // #pragma comment( lib, "ingraphs.lib" ) #endif -#define XDOTVERSION "1.6" +#define XDOTVERSION "1.7" #define NUMXBUFS (EMIT_HLABEL+1) /* There are as many xbufs as there are values of emit_state_t. @@ -535,6 +535,8 @@ static void dot_end_graph(GVJ_t *job) g->clos->disc.io = io_save; } +static unsigned int flag_masks[] = { 0x1F, 0x3F, 0x7F }; + static void xdot_textspan(GVJ_t * job, pointf p, textspan_t * span) { emit_state_t emit_state = job->obj->emit_state; @@ -565,10 +567,10 @@ static void xdot_textspan(GVJ_t * job, pointf p, textspan_t * span) else flags = 0; if (xd->version >= 15) { - unsigned int mask = (xd->version >= 16?0x3F:0x1F); + unsigned int mask = flag_masks[xd->version-15]; unsigned int bits = flags & mask; if (textflags[emit_state] != bits) { - sprintf (buf, "t %d ", bits); + sprintf (buf, "t %u ", bits); agxbput(xbufs[emit_state], buf); textflags[emit_state] = bits; } diff --git a/plugin/core/gvrender_core_svg.c b/plugin/core/gvrender_core_svg.c index 03a3e850d..59327ca9f 100644 --- a/plugin/core/gvrender_core_svg.c +++ b/plugin/core/gvrender_core_svg.c @@ -348,7 +348,7 @@ static void svg_textspan(GVJ_t * job, pointf p, textspan_t * span) obj_state_t *obj = job->obj; PostscriptAlias *pA; char *family = NULL, *weight = NULL, *stretch = NULL, *style = NULL; - int flags; + unsigned int flags; gvputs(job, "<text"); switch (span->just) { @@ -404,13 +404,17 @@ static void svg_textspan(GVJ_t * job, pointf p, textspan_t * span) gvprintf(job, " font-weight=\"bold\""); if ((flags & HTML_IF) && !style) gvprintf(job, " font-style=\"italic\""); - if ((flags & (HTML_UL|HTML_S))) { + if ((flags & (HTML_UL|HTML_S|HTML_OL))) { int comma = 0; gvprintf(job, " text-decoration=\""); if ((flags & HTML_UL)) { gvprintf(job, "underline"); comma = 1; } + if ((flags & HTML_OL)) { + gvprintf(job, "%soverline", (comma?",":"")); + comma = 1; + } if ((flags & HTML_S)) gvprintf(job, "%sline-through", (comma?",":"")); gvprintf(job, "\""); diff --git a/plugin/pango/gvrender_pango.c b/plugin/pango/gvrender_pango.c index 6be3a25bd..394be35cc 100644 --- a/plugin/pango/gvrender_pango.c +++ b/plugin/pango/gvrender_pango.c @@ -62,6 +62,8 @@ static int dotted_len = ARRAY_SIZE(dotted); #include <cairo-svg.h> #endif +static void cairogen_polyline(GVJ_t * job, pointf * A, int n); + static void cairogen_set_color(cairo_t * cr, gvcolor_t * color) { cairo_set_source_rgba(cr, color->u.RGBA[0], color->u.RGBA[1], @@ -223,6 +225,7 @@ static void cairogen_textspan(GVJ_t * job, pointf p, textspan_t * span) { obj_state_t *obj = job->obj; cairo_t *cr = (cairo_t *) job->context; + pointf A[2]; cairo_set_dash (cr, dashed, 0, 0.0); /* clear any dashing */ cairogen_set_color(cr, &(obj->pencolor)); @@ -246,6 +249,13 @@ static void cairogen_textspan(GVJ_t * job, pointf p, textspan_t * span) cairo_scale(cr, POINTS_PER_INCH / FONT_DPI, POINTS_PER_INCH / FONT_DPI); pango_cairo_show_layout(cr, (PangoLayout*)(span->layout)); cairo_restore(cr); + + if ((span->font) && (span->font->flags & HTML_OL)) { + A[0].x = p.x; + A[1].x = p.x + span->size.x; + A[1].y = A[0].y = p.y; + cairogen_polyline(job, A, 2); + } } static void cairogen_set_penstyle(GVJ_t *job, cairo_t *cr) -- 2.40.0