summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorwl <wl>2010-12-20 22:57:04 +0000
committerwl <wl>2010-12-20 22:57:04 +0000
commit5aee29f535290297d490fad3b2ef5c055715dcb3 (patch)
treedeb81db53753ee5454ee3ee0626fc990e0d51092 /src
parent887dda6d764c36155b0ea4e30d9509b40d39442e (diff)
downloadgroff-5aee29f535290297d490fad3b2ef5c055715dcb3.tar.gz
Replace patch from 2010-12-18 with a much faster implementation.
* src/roff/troff/node.h (node): Add virtual function `get_break_code'. * src/roff/troff/node.cpp (inter_char_space_node): Remove class completely. (glyph_node::merge_glyph_node): Restore previous version. (break_char_node): Add `prev_break_code' field and update constructors. (node::get_break_code, break_char_node::get_break_code): Implement. (node::add_char): Pass remaining cflags values. (break_char_node::add_self): Use the logic of the now deleted `inter_char_space_node::add_self' function to insert a space node if necessary.
Diffstat (limited to 'src')
-rw-r--r--src/roff/troff/node.cpp315
-rw-r--r--src/roff/troff/node.h1
2 files changed, 54 insertions, 262 deletions
diff --git a/src/roff/troff/node.cpp b/src/roff/troff/node.cpp
index ec082ff2..311a5cde 100644
--- a/src/roff/troff/node.cpp
+++ b/src/roff/troff/node.cpp
@@ -2111,47 +2111,6 @@ node *node::merge_glyph_node(glyph_node *)
return 0;
}
-class inter_char_space_node : public node {
- hunits amount;
- char left_break_code;
- char right_break_code;
- color *col;
- node *n1;
- node *n2;
-public:
- inter_char_space_node(hunits, char, char, color *, node *, node *,
- statem *, int, node * = 0);
- ~inter_char_space_node();
- node *copy();
- node *merge_glyph_node(glyph_node *);
- node *add_self(node *, hyphen_list **);
- hyphen_list *get_hyphen_list(hyphen_list *, int *);
- node *add_discretionary_hyphen();
- hunits width();
- node *last_char_node();
- hunits italic_correction();
- hunits subscript_correction();
- void tprint(troff_output_file *);
- hyphenation_type get_hyphenation_type();
- int ends_sentence();
- void ascii_print(ascii_output_file *);
- void asciify(macro *);
- int same(node *);
- const char *type();
- int force_tprint();
- int is_tag();
- void vertical_extent(vunits *, vunits *);
-};
-
-enum break_char_type {
- CAN_BREAK_BEFORE = 0x01,
- CAN_BREAK_AFTER = 0x02,
- IGNORE_HCODES = 0x04,
- PROHIBIT_BREAK_BEFORE = 0x08,
- PROHIBIT_BREAK_AFTER = 0x10,
- INTER_CHAR_SPACE = 0x20
-};
-
node *glyph_node::merge_glyph_node(glyph_node *gn)
{
if (tf == gn->tf && gcol == gn->gcol && fcol == gn->fcol) {
@@ -2170,28 +2129,6 @@ node *glyph_node::merge_glyph_node(glyph_node *gn)
gn->div_nest_level, next1);
}
}
- int left_bc = 0, right_bc = 0;
- if (ci->prohibit_break_before())
- left_bc = PROHIBIT_BREAK_BEFORE;
- if (gn->ci->prohibit_break_before())
- right_bc = PROHIBIT_BREAK_BEFORE;
- if (ci->prohibit_break_after())
- left_bc |= PROHIBIT_BREAK_AFTER;
- if (gn->ci->prohibit_break_after())
- right_bc |= PROHIBIT_BREAK_AFTER;
- if (ci->inter_char_space())
- left_bc |= INTER_CHAR_SPACE;
- if (gn->ci->inter_char_space())
- right_bc |= INTER_CHAR_SPACE;
- if (left_bc && right_bc) {
- node *next1 = next;
- next = 0;
- // ic_space not supported yet
- int ic_space = 0;
- return new inter_char_space_node(ic_space, left_bc, right_bc,
- gcol, this, gn, state,
- gn->div_nest_level, next1);
- }
return 0;
}
@@ -2605,6 +2542,11 @@ int node::is_tag()
return 0;
}
+int node::get_break_code()
+{
+ return 0;
+}
+
hunits hmotion_node::width()
{
return n;
@@ -2823,10 +2765,11 @@ int italic_corrected_node::character_type()
class break_char_node : public node {
node *ch;
char break_code;
+ char prev_break_code;
color *col;
public:
- break_char_node(node *, int, color *, node * = 0);
- break_char_node(node *, int, color *, statem *, int, node * = 0);
+ break_char_node(node *, int, int, color *, node * = 0);
+ break_char_node(node *, int, int, color *, statem *, int, node * = 0);
~break_char_node();
node *copy();
hunits width();
@@ -2849,16 +2792,17 @@ public:
const char *type();
int force_tprint();
int is_tag();
+ int get_break_code();
};
-break_char_node::break_char_node(node *n, int bc, color *c, node *x)
-: node(x), ch(n), break_code(bc), col(c)
+break_char_node::break_char_node(node *n, int bc, int pbc, color *c, node *x)
+: node(x), ch(n), break_code(bc), prev_break_code(pbc), col(c)
{
}
-break_char_node::break_char_node(node *n, int bc, color *c, statem *s,
- int pop, node *x)
-: node(x, s, pop), ch(n), break_code(bc), col(c)
+break_char_node::break_char_node(node *n, int bc, int pbc, color *c,
+ statem *s, int pop, node *x)
+: node(x, s, pop), ch(n), break_code(bc), prev_break_code(pbc), col(c)
{
}
@@ -2869,8 +2813,8 @@ break_char_node::~break_char_node()
node *break_char_node::copy()
{
- return new break_char_node(ch->copy(), break_code, col, state,
- div_nest_level);
+ return new break_char_node(ch->copy(), break_code, prev_break_code,
+ col, state, div_nest_level);
}
hunits break_char_node::width()
@@ -2898,13 +2842,37 @@ int break_char_node::ends_sentence()
return ch->ends_sentence();
}
+enum break_char_type {
+ CAN_BREAK_BEFORE = 0x01,
+ CAN_BREAK_AFTER = 0x02,
+ IGNORE_HCODES = 0x04,
+ PROHIBIT_BREAK_BEFORE = 0x08,
+ PROHIBIT_BREAK_AFTER = 0x10,
+ INTER_CHAR_SPACE = 0x20
+};
+
node *break_char_node::add_self(node *n, hyphen_list **p)
{
+ int have_space_node = 0;
assert((*p)->hyphenation_code == 0);
if (break_code & CAN_BREAK_BEFORE) {
if ((*p)->breakable || break_code & IGNORE_HCODES) {
n = new space_node(H0, col, n);
n->freeze_space();
+ have_space_node = 1;
+ }
+ }
+ if (!have_space_node) {
+ if (prev_break_code & INTER_CHAR_SPACE
+ || prev_break_code & PROHIBIT_BREAK_AFTER) {
+ if (break_code & PROHIBIT_BREAK_BEFORE)
+ // stretchable zero-width space not implemented yet
+ ;
+ else {
+ // breakable, stretchable zero-width space not implemented yet
+ n = new space_node(H0, col, n);
+ n->freeze_space();
+ }
}
}
next = n;
@@ -5137,10 +5105,17 @@ node *node::add_char(charinfo *ci, environment *env,
break_code |= CAN_BREAK_AFTER;
if (ci->ignore_hcodes())
break_code |= IGNORE_HCODES;
+ if (ci->prohibit_break_before())
+ break_code = PROHIBIT_BREAK_BEFORE;
+ if (ci->prohibit_break_after())
+ break_code |= PROHIBIT_BREAK_AFTER;
+ if (ci->inter_char_space())
+ break_code |= INTER_CHAR_SPACE;
if (break_code) {
node *next1 = res->next;
res->next = 0;
- res = new break_char_node(res, break_code, env->get_fill_color(), next1);
+ res = new break_char_node(res, break_code, get_break_code(),
+ env->get_fill_color(), next1);
}
return res;
}
@@ -5775,195 +5750,6 @@ int dbreak_node::is_tag()
return 0;
}
-inter_char_space_node::inter_char_space_node(hunits n,
- char left, char right,
- color *c, node *first, node *second,
- statem* s, int pop, node *x)
-: node(x, s, pop), amount(n), left_break_code(left), right_break_code(right),
- col(c), n1(first), n2(second)
-{
-}
-
-inter_char_space_node::~inter_char_space_node()
-{
- if (n1 != 0)
- delete n1;
- if (n2 != 0)
- delete n2;
-}
-
-node *inter_char_space_node::merge_glyph_node(glyph_node *gn)
-{
- node *nd = n2->merge_glyph_node(gn);
- if (nd == 0)
- return 0;
- n2 = nd;
- nd = n2->merge_self(n1);
- if (nd) {
- nd->next = next;
- n1 = 0;
- n2 = 0;
- delete this;
- return nd;
- }
- return this;
-}
-
-hunits inter_char_space_node::italic_correction()
-{
- return n2->italic_correction();
-}
-
-hunits inter_char_space_node::subscript_correction()
-{
- return n2->subscript_correction();
-}
-
-void inter_char_space_node::vertical_extent(vunits *min, vunits *max)
-{
- n1->vertical_extent(min, max);
- vunits min2, max2;
- n2->vertical_extent(&min2, &max2);
- if (min2 < *min)
- *min = min2;
- if (max2 > *max)
- *max = max2;
-}
-
-node *inter_char_space_node::add_discretionary_hyphen()
-{
- tfont *tf = n1->get_tfont();
- if (tf) {
- if (tf->contains(soft_hyphen_char)) {
- color *gcol = n2->get_glyph_color();
- color *fcol = n2->get_fill_color();
- node *next1 = next;
- next = 0;
- node *n = copy();
- glyph_node *gn = new glyph_node(soft_hyphen_char, tf, gcol, fcol,
- state, div_nest_level);
- node *nn = n->merge_glyph_node(gn);
- if (nn == 0) {
- gn->next = n;
- nn = gn;
- }
- return new dbreak_node(this, nn, state, div_nest_level, next1);
- }
- }
- return this;
-}
-
-node *inter_char_space_node::copy()
-{
- return new inter_char_space_node(amount, left_break_code, right_break_code,
- col, n1->copy(), n2->copy(),
- state, div_nest_level);
-}
-
-hyphen_list *inter_char_space_node::get_hyphen_list(hyphen_list *tail,
- int *count)
-{
- hyphen_list *hl = n2->get_hyphen_list(tail, count);
- return n1->get_hyphen_list(hl, count);
-}
-
-node *inter_char_space_node::add_self(node *n, hyphen_list **p)
-{
- n = n1->add_self(n, p);
- if (left_break_code & INTER_CHAR_SPACE
- || left_break_code & PROHIBIT_BREAK_AFTER) {
- if (right_break_code & PROHIBIT_BREAK_BEFORE)
- // stretchable zero-width space not implemented yet
- ;
- else {
- // breakable, stretchable zero-width space not implemented yet
- n = new space_node(H0, col, n);
- n->freeze_space();
- }
- }
- n = n2->add_self(n, p);
- n1 = n2 = 0;
- delete this;
- return n;
-}
-
-hunits inter_char_space_node::width()
-{
- return n1->width() + n2->width();
-}
-
-node *inter_char_space_node::last_char_node()
-{
- node *nd = n2->last_char_node();
- if (nd)
- return nd;
- return n1->last_char_node();
-}
-
-int inter_char_space_node::ends_sentence()
-{
- switch (n2->ends_sentence()) {
- case 0:
- return 0;
- case 1:
- return 1;
- case 2:
- break;
- default:
- assert(0);
- }
- return n1->ends_sentence();
-}
-
-void inter_char_space_node::ascii_print(ascii_output_file *ascii)
-{
- n1->ascii_print(ascii);
- n2->ascii_print(ascii);
-}
-
-void inter_char_space_node::asciify(macro *m)
-{
- n1->asciify(m);
- n2->asciify(m);
- n1 = n2 = 0;
- delete this;
-}
-
-hyphenation_type inter_char_space_node::get_hyphenation_type()
-{
- return HYPHEN_MIDDLE;
-}
-
-void inter_char_space_node::tprint(troff_output_file *out)
-{
- n1->tprint(out);
- n2->tprint(out);
-}
-
-int inter_char_space_node::same(node *nd)
-{
- return (amount == ((inter_char_space_node *)nd)->amount
- && left_break_code == ((inter_char_space_node *)nd)->left_break_code
- && right_break_code == ((inter_char_space_node *)nd)->right_break_code
- && same_node(n1, ((inter_char_space_node *)nd)->n1)
- && same_node(n2, ((inter_char_space_node *)nd)->n2));
-}
-
-const char *inter_char_space_node::type()
-{
- return "inter_char_space_node";
-}
-
-int inter_char_space_node::force_tprint()
-{
- return 0;
-}
-
-int inter_char_space_node::is_tag()
-{
- return 0;
-}
-
int break_char_node::same(node *nd)
{
return break_code == ((break_char_node *)nd)->break_code
@@ -5986,6 +5772,11 @@ int break_char_node::is_tag()
return 0;
}
+int break_char_node::get_break_code()
+{
+ return break_code;
+}
+
int line_start_node::same(node * /*nd*/)
{
return 1;
diff --git a/src/roff/troff/node.h b/src/roff/troff/node.h
index 615cc930..393e18d1 100644
--- a/src/roff/troff/node.h
+++ b/src/roff/troff/node.h
@@ -64,6 +64,7 @@ struct node {
virtual int set_unformat_flag();
virtual int force_tprint() = 0;
virtual int is_tag() = 0;
+ virtual int get_break_code();
virtual hunits width();
virtual hunits subscript_correction();
virtual hunits italic_correction();