summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2005-05-22 21:50:14 +0000
committerJames Bursa <james@netsurf-browser.org>2005-05-22 21:50:14 +0000
commit22640f85e0d245df817df96afa18d382e3a1b49a (patch)
tree57420cd508f6bd05fe7ad4fff3d8438a91ebf770
parent48d1759374e95bbc0c59fa2c87e9e8122f0e1273 (diff)
downloadnetsurf-22640f85e0d245df817df96afa18d382e3a1b49a.tar.gz
netsurf-22640f85e0d245df817df96afa18d382e3a1b49a.tar.bz2
[project @ 2005-05-22 21:50:14 by bursa]
Add BOX_TEXT type to distinguish boxes which came from an inline element to boxes which came from a text node. Add inline_parent pointer to box structure. Rewrite text-decoration support to take advantage of the new data (line colours are now correct). Note: there is a clipping issue in redraw. svn path=/import/netsurf/; revision=1732
-rw-r--r--css/css.c2
-rw-r--r--render/box.c4
-rw-r--r--render/box.h6
-rw-r--r--render/box_construct.c29
-rw-r--r--render/box_normalise.c9
-rw-r--r--render/html_redraw.c171
-rw-r--r--render/layout.c14
7 files changed, 177 insertions, 58 deletions
diff --git a/css/css.c b/css/css.c
index 5477ca856..706e27561 100644
--- a/css/css.c
+++ b/css/css.c
@@ -363,7 +363,7 @@ const struct css_style css_blank_style = {
CSS_POSITION_STATIC,
CSS_TABLE_LAYOUT_AUTO,
CSS_TEXT_ALIGN_INHERIT,
- CSS_TEXT_DECORATION_INHERIT,
+ CSS_TEXT_DECORATION_NONE,
{ CSS_TEXT_INDENT_INHERIT, { { 0, CSS_UNIT_EM } } },
CSS_TEXT_TRANSFORM_INHERIT,
CSS_UNICODE_BIDI_NORMAL,
diff --git a/render/box.c b/render/box.c
index f00b8aa1d..51db3c0cf 100644
--- a/render/box.c
+++ b/render/box.c
@@ -76,6 +76,7 @@ struct box * box_create(struct css_style *style,
box->last = NULL;
box->parent = NULL;
box->fallback = NULL;
+ box->inline_parent = NULL;
box->float_children = NULL;
box->next_float = NULL;
box->col = NULL;
@@ -457,6 +458,7 @@ void box_dump(struct box *box, unsigned int depth)
case BOX_FLOAT_LEFT: fprintf(stderr, "FLOAT_LEFT "); break;
case BOX_FLOAT_RIGHT: fprintf(stderr, "FLOAT_RIGHT "); break;
case BOX_BR: fprintf(stderr, "BR "); break;
+ case BOX_TEXT: fprintf(stderr, "TEXT "); break;
default: fprintf(stderr, "Unknown box type ");
}
@@ -474,6 +476,8 @@ void box_dump(struct box *box, unsigned int depth)
fprintf(stderr, " [%s]", box->title);
if (box->id != 0)
fprintf(stderr, " <%s>", box->id);
+ if (box->inline_parent)
+ fprintf(stderr, " inline_parent %p", box->inline_parent);
if (box->float_children)
fprintf(stderr, " float_children %p", box->float_children);
if (box->next_float)
diff --git a/render/box.h b/render/box.h
index 60aba1ba5..9bef5edd3 100644
--- a/render/box.h
+++ b/render/box.h
@@ -141,7 +141,8 @@ struct box {
int min_width;
int max_width; /**< Width that would be taken with no line breaks. */
- unsigned byte_offset; /**< byte offset within a textual representation of this content */
+ /**< Byte offset within a textual representation of this content. */
+ size_t byte_offset;
char *text; /**< Text, or 0 if none. Unterminated. */
size_t length; /**< Length of text. */
@@ -165,6 +166,9 @@ struct box {
struct box *last; /**< Last child box, or 0. */
struct box *parent; /**< Parent box, or 0. */
struct box *fallback; /**< Fallback children for object, or 0. */
+ /** Box of type INLINE which contains this box in the document tree
+ * (only valid for TEXT boxes). */
+ struct box *inline_parent;
/** First float child box, or 0. Float boxes are in the tree twice, in
* this list for the block box which defines the area for floats, and
diff --git a/render/box_construct.c b/render/box_construct.c
index 57046120f..d6841bf7b 100644
--- a/render/box_construct.c
+++ b/render/box_construct.c
@@ -72,14 +72,17 @@ static const content_type image_types[] = {
static bool convert_xml_to_box(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
+ struct box *inline_parent,
char *href, char *title);
bool box_construct_element(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
+ struct box *inline_parent,
char *href, char *title);
bool box_construct_text(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
+ struct box *inline_parent,
char *href, char *title);
static struct css_style * box_get_style(struct content *c,
struct css_style *parent_style,
@@ -174,7 +177,7 @@ bool xml_to_box(xmlNode *n, struct content *c)
c->data.html.object = 0;
if (!convert_xml_to_box(n, c, c->data.html.style, &root,
- &inline_container, 0, 0))
+ &inline_container, 0, 0, 0))
return false;
if (!box_normalise_block(&root, c))
return false;
@@ -224,15 +227,16 @@ static const box_type box_map[] = {
bool convert_xml_to_box(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
+ struct box *inline_parent,
char *href, char *title)
{
switch (n->type) {
case XML_ELEMENT_NODE:
return box_construct_element(n, content, parent_style, parent,
- inline_container, href, title);
+ inline_container, inline_parent, href, title);
case XML_TEXT_NODE:
return box_construct_text(n, content, parent_style, parent,
- inline_container, href, title);
+ inline_container, inline_parent, href, title);
default:
/* not an element or text node: ignore it (eg. comment) */
return true;
@@ -256,6 +260,7 @@ bool convert_xml_to_box(xmlNode *n, struct content *content,
bool box_construct_element(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
+ struct box *inline_parent,
char *href, char *title)
{
bool convert_children = true;
@@ -335,10 +340,11 @@ bool box_construct_element(xmlNode *n, struct content *content,
if (box->type == BOX_INLINE || box->type == BOX_BR) {
/* inline box: add to tree and recurse */
+ box->inline_parent = inline_parent;
box_add_child(*inline_container, box);
for (c = n->children; convert_children && c; c = c->next)
if (!convert_xml_to_box(c, content, style, parent,
- inline_container, href, title))
+ inline_container, box, href, title))
return false;
} else if (box->type == BOX_INLINE_BLOCK) {
/* inline block box: add to tree and recurse */
@@ -346,7 +352,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
inline_container_c = 0;
for (c = n->children; convert_children && c; c = c->next)
if (!convert_xml_to_box(c, content, style, box,
- &inline_container_c, href, title))
+ &inline_container_c, 0, href, title))
return false;
} else {
if (style->float_ == CSS_FLOAT_LEFT ||
@@ -373,7 +379,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
inline_container_c = 0;
for (c = n->children; convert_children && c; c = c->next)
if (!convert_xml_to_box(c, content, style, box,
- &inline_container_c, href, title))
+ &inline_container_c, 0, href, title))
return false;
if (style->float_ == CSS_FLOAT_NONE)
/* new inline container unless this is a float */
@@ -486,6 +492,7 @@ bool box_construct_element(xmlNode *n, struct content *content,
bool box_construct_text(xmlNode *n, struct content *content,
struct css_style *parent_style,
struct box *parent, struct box **inline_container,
+ struct box *inline_parent,
char *href, char *title)
{
struct box *box = 0;
@@ -529,6 +536,8 @@ bool box_construct_text(xmlNode *n, struct content *content,
free(text);
return false;
}
+ box->type = BOX_TEXT;
+ box->inline_parent = inline_parent;
box->text = talloc_strdup(content, text);
free(text);
if (!box->text)
@@ -604,7 +613,8 @@ bool box_construct_text(xmlNode *n, struct content *content,
free(text);
return false;
}
- box->type = BOX_INLINE;
+ box->type = BOX_TEXT;
+ box->inline_parent = inline_parent;
box->text = talloc_strdup(content, current);
if (!box->text) {
free(text);
@@ -648,9 +658,6 @@ struct css_style * box_get_style(struct content *c,
xmlNode *n)
{
char *s;
- unsigned int i;
- unsigned int stylesheet_count = c->data.html.stylesheet_count;
- struct content **stylesheet = c->data.html.stylesheet_content;
struct css_style *style;
struct css_style *style_new;
char *url;
@@ -1284,7 +1291,7 @@ bool box_object(BOX_SPECIAL_PARAMS)
/* convert children and place into fallback */
for (c = n->children; c; c = c->next) {
if (!convert_xml_to_box(c, content, box->style, box,
- &inline_container, 0, 0))
+ &inline_container, 0, 0, 0))
return false;
}
box->fallback = box->children;
diff --git a/render/box_normalise.c b/render/box_normalise.c
index e05aa077a..05e2f2d76 100644
--- a/render/box_normalise.c
+++ b/render/box_normalise.c
@@ -69,8 +69,8 @@ static bool box_normalise_inline_container(struct box *cont, struct content *c);
* \code
* parent permitted child nodes
* BLOCK, INLINE_BLOCK BLOCK, INLINE_CONTAINER, TABLE
- * INLINE_CONTAINER INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR
- * INLINE none
+ * INLINE_CONTAINER INLINE, INLINE_BLOCK, FLOAT_LEFT, FLOAT_RIGHT, BR, TEXT
+ * INLINE, TEXT none
* TABLE at least 1 TABLE_ROW_GROUP
* TABLE_ROW_GROUP at least 1 TABLE_ROW
* TABLE_ROW at least 1 TABLE_CELL
@@ -114,6 +114,7 @@ bool box_normalise_block(struct box *block, struct content *c)
case BOX_FLOAT_LEFT:
case BOX_FLOAT_RIGHT:
case BOX_BR:
+ case BOX_TEXT:
/* should have been wrapped in inline
container by convert_xml_to_box() */
assert(0);
@@ -249,6 +250,7 @@ bool box_normalise_table(struct box *table, struct content * c)
case BOX_FLOAT_LEFT:
case BOX_FLOAT_RIGHT:
case BOX_BR:
+ case BOX_TEXT:
/* should have been wrapped in inline
container by convert_xml_to_box() */
assert(0);
@@ -411,6 +413,7 @@ bool box_normalise_table_row_group(struct box *row_group,
case BOX_FLOAT_LEFT:
case BOX_FLOAT_RIGHT:
case BOX_BR:
+ case BOX_TEXT:
/* should have been wrapped in inline
container by convert_xml_to_box() */
assert(0);
@@ -507,6 +510,7 @@ bool box_normalise_table_row(struct box *row,
case BOX_FLOAT_LEFT:
case BOX_FLOAT_RIGHT:
case BOX_BR:
+ case BOX_TEXT:
/* should have been wrapped in inline
container by convert_xml_to_box() */
assert(0);
@@ -640,6 +644,7 @@ bool box_normalise_inline_container(struct box *cont, struct content * c)
switch (child->type) {
case BOX_INLINE:
case BOX_BR:
+ case BOX_TEXT:
/* ok */
break;
case BOX_INLINE_BLOCK:
diff --git a/render/html_redraw.c b/render/html_redraw.c
index eb7a974a3..13f1315d3 100644
--- a/render/html_redraw.c
+++ b/render/html_redraw.c
@@ -45,6 +45,13 @@ static bool html_redraw_file(int x, int y, int width, int height,
static bool html_redraw_background(int x, int y, struct box *box, float scale,
int clip_x0, int clip_y0, int clip_x1, int clip_y1,
colour *background_colour);
+static bool html_redraw_text_decoration(struct box *box,
+ int x_parent, int y_parent, float scale,
+ colour background_colour);
+static bool html_redraw_text_decoration_inline(struct box *box, int x, int y,
+ float scale, colour colour, float ratio);
+static bool html_redraw_text_decoration_block(struct box *box, int x, int y,
+ float scale, colour colour, float ratio);
static bool html_redraw_scrollbars(struct box *box, float scale,
int x, int y, int padding_width, int padding_height,
colour background_colour);
@@ -119,7 +126,6 @@ bool html_redraw_box(struct box *box,
int width, height;
int padding_left, padding_top, padding_width, padding_height;
int x0, y0, x1, y1;
- int colour;
int x_scrolled, y_scrolled;
/* avoid trivial FP maths */
@@ -259,6 +265,14 @@ bool html_redraw_box(struct box *box,
}
}
+ /* text decoration */
+ if (box->type != BOX_TEXT && box->style &&
+ box->style->text_decoration !=
+ CSS_TEXT_DECORATION_NONE)
+ if (!html_redraw_text_decoration(box, x_parent, y_parent,
+ scale, current_background_color))
+ return false;
+
if (box->object) {
x_scrolled = x - box->scroll_x * scale;
y_scrolled = y - box->scroll_y * scale;
@@ -290,40 +304,6 @@ bool html_redraw_box(struct box *box,
} else if (box->text) {
bool highlighted = false;
- /* antialias colour for under/overline */
- colour = html_redraw_aa(current_background_color,
- /*print_text_black ? 0 :*/ box->style->color);
-
- if (box->style->text_decoration &
- CSS_TEXT_DECORATION_UNDERLINE) {
- if (!plot.line(x,
- y + (int) (box->height * 0.9 * scale),
- x + box->width * scale,
- y + (int) (box->height * 0.9 * scale),
- 0, colour, false, false))
- return false;
- }
-
- if (box->style->text_decoration &
- CSS_TEXT_DECORATION_OVERLINE) {
- if (!plot.line(x,
- y + (int) (box->height * 0.1 * scale),
- x + box->width * scale,
- y + (int) (box->height * 0.1 * scale),
- 0, colour, false, false))
- return false;
- }
-
- if (box->style->text_decoration &
- CSS_TEXT_DECORATION_LINE_THROUGH) {
- if (!plot.line(x,
- y + (int) (box->height * 0.5 * scale),
- x + box->width * scale,
- y + (int) (box->height * 0.5 * scale),
- 0, colour, false, false))
- return false;
- }
-
/* is this box part of a selection? */
if (box->text && !box->object && current_redraw_browser) {
unsigned start_idx;
@@ -863,7 +843,7 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
do {
if (clip_to_children) {
assert(clip_box->type == BOX_TABLE_CELL);
-
+
/* update clip_* to the child cell */
clip_x0 = ox + (clip_box->x * scale);
clip_y0 = oy + (clip_box->y * scale);
@@ -875,7 +855,7 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
if (clip_y0 < py0) clip_y0 = py0;
if (clip_x1 > px1) clip_x1 = px1;
if (clip_y1 > py1) clip_y1 = py1;
-
+
if ((clip_x0 >= clip_x1) || (clip_y0 >= clip_y1) ||
(clip_box->style->background_color != TRANSPARENT) ||
(clip_box->background &&
@@ -907,7 +887,7 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
repeat_x, repeat_y))
return false;
}
-
+
/* advance and loop for child clipping */
clip_box = clip_box->next;
} while (clip_box && clip_to_children);
@@ -916,6 +896,121 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
/**
+ * Plot text decoration for a box.
+ *
+ * \param box box to plot decorations for
+ * \param x_parent x coordinate of parent of box
+ * \param y_parent y coordinate of parent of box
+ * \param scale scale for redraw
+ * \param background_colour current background colour
+ * \return true if successful, false otherwise
+ */
+
+bool html_redraw_text_decoration(struct box *box,
+ int x_parent, int y_parent, float scale,
+ colour background_colour)
+{
+ static const css_text_decoration decoration[] = {
+ CSS_TEXT_DECORATION_UNDERLINE, CSS_TEXT_DECORATION_OVERLINE,
+ CSS_TEXT_DECORATION_LINE_THROUGH };
+ static const float line_ratio[] = { 0.9, 0.5, 0.1 };
+ int colour;
+ unsigned int i;
+
+ /* antialias colour for under/overline */
+ colour = html_redraw_aa(background_colour, box->style->color);
+
+ if (box->type == BOX_INLINE) {
+ for (i = 0; i != NOF_ELEMENTS(decoration); i++)
+ if (box->style->text_decoration & decoration[i])
+ if (!html_redraw_text_decoration_inline(box,
+ x_parent, y_parent, scale,
+ colour, line_ratio[i]))
+ return false;
+ } else {
+ for (i = 0; i != NOF_ELEMENTS(decoration); i++)
+ if (box->style->text_decoration & decoration[i])
+ if (!html_redraw_text_decoration_block(box,
+ x_parent + box->x,
+ y_parent + box->y,
+ scale,
+ colour, line_ratio[i]))
+ return false;
+ }
+
+ return true;
+}
+
+
+/**
+ * Plot text decoration for an inline box.
+ *
+ * \param box box to plot decorations for, of type BOX_INLINE
+ * \param x x coordinate of parent of box
+ * \param y y coordinate of parent of box
+ * \param scale scale for redraw
+ * \param colour colour for decorations
+ * \param ratio position of line as a ratio of line height
+ * \return true if successful, false otherwise
+ */
+
+bool html_redraw_text_decoration_inline(struct box *box, int x, int y,
+ float scale, colour colour, float ratio)
+{
+ /* draw from next sibling to the sibling which has the same inline
+ * parent as this box (which must mean it was the next sibling of this
+ * inline in the HTML tree) */
+ for (struct box *c = box->next;
+ c && c->inline_parent != box->inline_parent;
+ c = c->next) {
+ if (!plot.line((x + c->x) * scale,
+ (y + c->y + c->height * ratio) * scale,
+ (x + c->x + c->width) * scale,
+ (y + c->y + c->height * ratio) * scale,
+ 0, colour, false, false))
+ return false;
+ }
+ return true;
+}
+
+
+/**
+ * Plot text decoration for an non-inline box.
+ *
+ * \param box box to plot decorations for, of type other than BOX_INLINE
+ * \param x x coordinate of box
+ * \param y y coordinate of box
+ * \param scale scale for redraw
+ * \param colour colour for decorations
+ * \param ratio position of line as a ratio of line height
+ * \return true if successful, false otherwise
+ */
+
+bool html_redraw_text_decoration_block(struct box *box, int x, int y,
+ float scale, colour colour, float ratio)
+{
+ /* draw through text descendants */
+ for (struct box *c = box->children; c; c = c->next) {
+ if (c->type == BOX_TEXT) {
+ if (!plot.line((x + c->x) * scale,
+ (y + c->y + c->height * ratio) * scale,
+ (x + c->x + c->width) * scale,
+ (y + c->y + c->height * ratio) * scale,
+ 0, colour, false, false))
+ return false;
+ } else if (c->type == BOX_INLINE_CONTAINER ||
+ c->type == BOX_BLOCK) {
+ if (!html_redraw_text_decoration_block(c,
+ x + c->x, y + c->y,
+ scale, colour, ratio))
+ return false;
+ }
+ }
+ return true;
+}
+
+
+/**
* Plot scrollbars for a scrolling box.
*
* \param box scrolling box
diff --git a/render/layout.c b/render/layout.c
index 3e6c2a367..8cf417c4e 100644
--- a/render/layout.c
+++ b/render/layout.c
@@ -761,7 +761,7 @@ bool layout_line(struct box *first, int width, int *y,
assert(b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK ||
b->type == BOX_FLOAT_LEFT ||
b->type == BOX_FLOAT_RIGHT ||
- b->type == BOX_BR);
+ b->type == BOX_BR || b->type == BOX_TEXT);
x += space_after;
@@ -784,7 +784,7 @@ bool layout_line(struct box *first, int width, int *y,
if (b->type == BOX_BR)
break;
- if (b->type != BOX_INLINE)
+ if (b->type != BOX_INLINE && b->type != BOX_TEXT)
continue;
if (!b->object && !b->gadget) {
@@ -908,7 +908,8 @@ bool layout_line(struct box *first, int width, int *y,
/* pass 2: place boxes in line: loop body executed at least once */
for (x = x_previous = 0, b = first; x <= x1 - x0 && b; b = b->next) {
- if (b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK) {
+ if (b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK ||
+ b->type == BOX_TEXT) {
assert(b->width != UNKNOWN_WIDTH);
x_previous = x;
@@ -1000,7 +1001,9 @@ bool layout_line(struct box *first, int width, int *y,
x = x_previous;
- if (split_box->type == BOX_INLINE && !split_box->object &&
+ if ((split_box->type == BOX_INLINE ||
+ split_box->type == BOX_TEXT) &&
+ !split_box->object &&
!split_box->gadget && split_box->text) {
for (i = 0; i != split_box->length &&
split_box->text[i] != ' '; i++)
@@ -1116,7 +1119,7 @@ bool layout_line(struct box *first, int width, int *y,
for (d = first; d != b; d = d->next) {
if (d->type == BOX_INLINE || d->type == BOX_INLINE_BLOCK ||
- d->type == BOX_BR) {
+ d->type == BOX_BR || d->type == BOX_TEXT) {
d->x += x0;
d->y = *y + d->border[TOP];
h = d->border[TOP] + d->padding[TOP] + d->height +
@@ -1800,6 +1803,7 @@ bool calculate_inline_container_widths(struct box *box)
for (child = box->children; child != 0; child = child->next) {
switch (child->type) {
case BOX_INLINE:
+ case BOX_TEXT:
if (child->object)
calculate_inline_replaced_widths(child,
&min, &max, &line_max);