summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorMichael Drake <tlsa@netsurf-browser.org>2013-01-02 18:02:15 +0000
committerMichael Drake <tlsa@netsurf-browser.org>2013-01-02 18:02:15 +0000
commit96841ae2ff8d6a08a1ea453a7fcc14e9a8729401 (patch)
tree443573fdeaf426a62f52e105ebfc5f194d6a6fa9 /render
parent3f33f5327e783b3f4d7474007672c2c60a2969ea (diff)
downloadnetsurf-96841ae2ff8d6a08a1ea453a7fcc14e9a8729401.tar.gz
netsurf-96841ae2ff8d6a08a1ea453a7fcc14e9a8729401.tar.bz2
Remove forward declaration.
Diffstat (limited to 'render')
-rw-r--r--render/html_redraw.c2437
1 files changed, 1200 insertions, 1237 deletions
diff --git a/render/html_redraw.c b/render/html_redraw.c
index e7474f8c4..26bc46c98 100644
--- a/render/html_redraw.c
+++ b/render/html_redraw.c
@@ -53,125 +53,9 @@
#include "utils/utils.h"
-static bool html_redraw_box(const html_content *html, struct box *box,
- int x, int y, const struct rect *clip, float scale,
- colour current_background_color,
- const struct redraw_context *ctx);
-static bool html_redraw_box_children(const html_content *html, struct box *box,
- int x_parent, int y_parent, const struct rect *clip,
- float scale, colour current_background_color,
- const struct redraw_context *ctx);
-static bool html_redraw_text_box(const html_content *html, struct box *box,
- int x, int y, const struct rect *clip, float scale,
- colour current_background_color,
- const struct redraw_context *ctx);
-static bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
- int p_width, int p_height, const struct rect *clip,
- float scale, const struct redraw_context *ctx);
-static bool html_redraw_inline_borders(struct box *box, struct rect b,
- const struct rect *clip, float scale, bool first, bool last,
- const struct redraw_context *ctx);
-static bool html_redraw_border_plot(const int side, const int *p, colour c,
- enum css_border_style_e style, int thickness, bool rectangular,
- const struct rect *clip, const struct redraw_context *ctx);
-static bool html_redraw_checkbox(int x, int y, int width, int height,
- bool selected, const struct redraw_context *ctx);
-static bool html_redraw_radio(int x, int y, int width, int height,
- bool selected, const struct redraw_context *ctx);
-static bool html_redraw_file(int x, int y, int width, int height,
- struct box *box, float scale, colour background_colour,
- const struct redraw_context *ctx);
-static bool html_redraw_background(int x, int y, struct box *box, float scale,
- const struct rect *clip, colour *background_colour,
- struct box *background, const struct redraw_context *ctx);
-static bool html_redraw_inline_background(int x, int y, struct box *box,
- float scale, const struct rect *clip, struct rect b,
- bool first, bool last, colour *background_colour,
- const struct redraw_context *ctx);
-static bool html_redraw_text_decoration(struct box *box,
- int x_parent, int y_parent, float scale,
- colour background_colour, const struct redraw_context *ctx);
-static bool html_redraw_text_decoration_inline(struct box *box, int x, int y,
- float scale, colour colour, float ratio,
- const struct redraw_context *ctx);
-static bool html_redraw_text_decoration_block(struct box *box, int x, int y,
- float scale, colour colour, float ratio,
- const struct redraw_context *ctx);
-
-bool html_redraw_debug = false;
-
-/**
- * Draw a CONTENT_HTML using the current set of plotters (plot).
- *
- * \param c content of type CONTENT_HTML
- * \param data redraw data for this content redraw
- * \param clip current clip region
- * \param ctx current redraw context
- * \return true if successful, false otherwise
- *
- * x, y, clip_[xy][01] are in target coordinates.
- */
-
-bool html_redraw(struct content *c, struct content_redraw_data *data,
- const struct rect *clip, const struct redraw_context *ctx)
-{
- html_content *html = (html_content *) c;
- struct box *box;
- bool result = true;
- bool select, select_only;
- plot_style_t pstyle_fill_bg = {
- .fill_type = PLOT_OP_TYPE_SOLID,
- .fill_colour = data->background_colour,
- };
- box = html->layout;
- assert(box);
- /* The select menu needs special treating because, when opened, it
- * reaches beyond its layout box.
- */
- select = false;
- select_only = false;
- if (ctx->interactive && html->visible_select_menu != NULL) {
- struct form_control *control = html->visible_select_menu;
- select = true;
- /* check if the redraw rectangle is completely inside of the
- select menu */
- select_only = form_clip_inside_select_menu(control,
- data->scale, clip);
- }
-
- if (!select_only) {
- /* clear to background colour */
- result = ctx->plot->clip(clip);
-
- if (html->background_colour != NS_TRANSPARENT)
- pstyle_fill_bg.fill_colour = html->background_colour;
-
- result &= ctx->plot->rectangle(clip->x0, clip->y0,
- clip->x1, clip->y1,
- &pstyle_fill_bg);
-
- result &= html_redraw_box(html, box, data->x, data->y, clip,
- data->scale, pstyle_fill_bg.fill_colour, ctx);
- }
-
- if (select) {
- int menu_x, menu_y;
- box = html->visible_select_menu->box;
- box_coords(box, &menu_x, &menu_y);
-
- menu_x -= box->border[LEFT].width;
- menu_y += box->height + box->border[BOTTOM].width +
- box->padding[BOTTOM] + box->padding[TOP];
- result &= form_redraw_select_menu(html->visible_select_menu,
- data->x + menu_x, data->y + menu_y,
- data->scale, clip, ctx);
- }
-
- return result;
-
-}
+bool html_redraw_debug = false;
/**
* Determine if a box has a background that needs drawing
@@ -239,678 +123,6 @@ static struct box *html_redraw_find_bg_box(struct box *box)
}
/**
- * Recursively draw a box.
- *
- * \param html html content
- * \param box box to draw
- * \param x_parent coordinate of parent box
- * \param y_parent coordinate of parent box
- * \param clip clip rectangle
- * \param scale scale for redraw
- * \param current_background_color background colour under this box
- * \param ctx current redraw context
- * \return true if successful, false otherwise
- *
- * x, y, clip_[xy][01] are in target coordinates.
- */
-
-bool html_redraw_box(const html_content *html, struct box *box,
- int x_parent, int y_parent,
- const struct rect *clip, float scale,
- colour current_background_color,
- const struct redraw_context *ctx)
-{
- const struct plotter_table *plot = ctx->plot;
- int x, y;
- int width, height;
- int padding_left, padding_top, padding_width, padding_height;
- int border_left, border_top, border_right, border_bottom;
- struct rect r;
- int x_scrolled, y_scrolled;
- struct box *bg_box = NULL;
- bool has_x_scroll, has_y_scroll;
- css_computed_clip_rect css_rect;
-
- if (html_redraw_printing && (box->flags & PRINTED))
- return true;
-
- /* avoid trivial FP maths */
- if (scale == 1.0) {
- x = x_parent + box->x;
- y = y_parent + box->y;
- width = box->width;
- height = box->height;
- padding_left = box->padding[LEFT];
- padding_top = box->padding[TOP];
- padding_width = padding_left + box->width + box->padding[RIGHT];
- padding_height = padding_top + box->height +
- box->padding[BOTTOM];
- border_left = box->border[LEFT].width;
- border_top = box->border[TOP].width;
- border_right = box->border[RIGHT].width;
- border_bottom = box->border[BOTTOM].width;
- } else {
- x = (x_parent + box->x) * scale;
- y = (y_parent + box->y) * scale;
- width = box->width * scale;
- height = box->height * scale;
- /* left and top padding values are normally zero,
- * so avoid trivial FP maths */
- padding_left = box->padding[LEFT] ? box->padding[LEFT] * scale
- : 0;
- padding_top = box->padding[TOP] ? box->padding[TOP] * scale
- : 0;
- padding_width = (box->padding[LEFT] + box->width +
- box->padding[RIGHT]) * scale;
- padding_height = (box->padding[TOP] + box->height +
- box->padding[BOTTOM]) * scale;
- border_left = box->border[LEFT].width * scale;
- border_top = box->border[TOP].width * scale;
- border_right = box->border[RIGHT].width * scale;
- border_bottom = box->border[BOTTOM].width * scale;
- }
-
- /* calculate rectangle covering this box and descendants */
- if (box->style && css_computed_overflow(box->style) !=
- CSS_OVERFLOW_VISIBLE) {
- /* box contents clipped to box size */
- r.x0 = x - border_left;
- r.y0 = y - border_top;
- r.x1 = x + padding_width + border_right;
- r.y1 = y + padding_height + border_bottom;
- } else {
- /* box contents can hang out of the box; use descendant box */
- if (scale == 1.0) {
- r.x0 = x + box->descendant_x0;
- r.y0 = y + box->descendant_y0;
- r.x1 = x + box->descendant_x1 + 1;
- r.y1 = y + box->descendant_y1 + 1;
- } else {
- r.x0 = x + box->descendant_x0 * scale;
- r.y0 = y + box->descendant_y0 * scale;
- r.x1 = x + box->descendant_x1 * scale + 1;
- r.y1 = y + box->descendant_y1 * scale + 1;
- }
- if (!box->parent) {
- /* root element */
- int margin_left, margin_right;
- int margin_top, margin_bottom;
- if (scale == 1.0) {
- margin_left = box->margin[LEFT];
- margin_top = box->margin[TOP];
- margin_right = box->margin[RIGHT];
- margin_bottom = box->margin[BOTTOM];
- } else {
- margin_left = box->margin[LEFT] * scale;
- margin_top = box->margin[TOP] * scale;
- margin_right = box->margin[RIGHT] * scale;
- margin_bottom = box->margin[BOTTOM] * scale;
- }
- r.x0 = x - border_left - margin_left < r.x0 ?
- x - border_left - margin_left : r.x0;
- r.y0 = y - border_top - margin_top < r.y0 ?
- y - border_top - margin_top : r.y0;
- r.x1 = x + padding_width + border_right +
- margin_right > r.x1 ?
- x + padding_width + border_right +
- margin_right : r.x1;
- r.y1 = y + padding_height + border_bottom +
- margin_bottom > r.y1 ?
- y + padding_height + border_bottom +
- margin_bottom : r.y1;
- }
- }
-
- /* return if the rectangle is completely outside the clip rectangle */
- if (clip->y1 < r.y0 || r.y1 < clip->y0 ||
- clip->x1 < r.x0 || r.x1 < clip->x0)
- return true;
-
- /*if the rectangle is under the page bottom but it can fit in a page,
- don't print it now*/
- if (html_redraw_printing) {
- if (r.y1 > html_redraw_printing_border) {
- if (r.y1 - r.y0 <= html_redraw_printing_border &&
- (box->type == BOX_TEXT ||
- box->type == BOX_TABLE_CELL
- || box->object || box->gadget)) {
- /*remember the highest of all points from the
- not printed elements*/
- if (r.y0 < html_redraw_printing_top_cropped)
- html_redraw_printing_top_cropped = r.y0;
- return true;
- }
- }
- else box->flags |= PRINTED; /*it won't be printed anymore*/
- }
-
- /* if visibility is hidden render children only */
- if (box->style && css_computed_visibility(box->style) ==
- CSS_VISIBILITY_HIDDEN) {
- if ((plot->group_start) && (!plot->group_start("hidden box")))
- return false;
- if (!html_redraw_box_children(html, box, x_parent, y_parent,
- &r, scale, current_background_color, ctx))
- return false;
- return ((!plot->group_end) || (plot->group_end()));
- }
-
- if ((plot->group_start) && (!plot->group_start("vis box")))
- return false;
-
-
- if (box->style != NULL &&
- css_computed_position(box->style) ==
- CSS_POSITION_ABSOLUTE &&
- css_computed_clip(box->style, &css_rect) ==
- CSS_CLIP_RECT) {
- /* We have an absolutly positioned box with a clip rect */
- if (css_rect.left_auto == false)
- r.x0 = x - border_left + FIXTOINT(nscss_len2px(
- css_rect.left, css_rect.lunit,
- box->style));
-
- if (css_rect.top_auto == false)
- r.y0 = y - border_top + FIXTOINT(nscss_len2px(
- css_rect.top, css_rect.tunit,
- box->style));
-
- if (css_rect.right_auto == false)
- r.x1 = x - border_left + FIXTOINT(nscss_len2px(
- css_rect.right, css_rect.runit,
- box->style));
-
- if (css_rect.bottom_auto == false)
- r.y1 = y - border_top + FIXTOINT(nscss_len2px(
- css_rect.bottom, css_rect.bunit,
- box->style));
-
- /* find intersection of clip rectangle and box */
- if (r.x0 < clip->x0) r.x0 = clip->x0;
- if (r.y0 < clip->y0) r.y0 = clip->y0;
- if (clip->x1 < r.x1) r.x1 = clip->x1;
- if (clip->y1 < r.y1) r.y1 = clip->y1;
- /* no point trying to draw 0-width/height boxes */
- if (r.x0 == r.x1 || r.y0 == r.y1)
- /* not an error */
- return ((!plot->group_end) || (plot->group_end()));
- /* clip to it */
- if (!plot->clip(&r))
- return false;
-
- } else if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
- box->type == BOX_TABLE_CELL || box->object) {
- /* find intersection of clip rectangle and box */
- if (r.x0 < clip->x0) r.x0 = clip->x0;
- if (r.y0 < clip->y0) r.y0 = clip->y0;
- if (clip->x1 < r.x1) r.x1 = clip->x1;
- if (clip->y1 < r.y1) r.y1 = clip->y1;
- /* no point trying to draw 0-width/height boxes */
- if (r.x0 == r.x1 || r.y0 == r.y1)
- /* not an error */
- return ((!plot->group_end) || (plot->group_end()));
- /* clip to it */
- if (!plot->clip(&r))
- return false;
- } else {
- /* clip box is fine, clip to it */
- r = *clip;
- if (!plot->clip(&r))
- return false;
- }
-
- /* background colour and image for block level content and replaced
- * inlines */
-
- bg_box = html_redraw_find_bg_box(box);
-
- /* bg_box == NULL implies that this box should not have
- * its background rendered. Otherwise filter out linebreaks,
- * optimize away non-differing inlines, only plot background
- * for BOX_TEXT it's in an inline */
- if (bg_box && bg_box->type != BOX_BR &&
- bg_box->type != BOX_TEXT &&
- bg_box->type != BOX_INLINE_END &&
- (bg_box->type != BOX_INLINE || bg_box->object ||
- bg_box->flags & IFRAME || box->flags & REPLACE_DIM)) {
- /* find intersection of clip box and border edge */
- struct rect p;
- p.x0 = x - border_left < r.x0 ? r.x0 : x - border_left;
- p.y0 = y - border_top < r.y0 ? r.y0 : y - border_top;
- p.x1 = x + padding_width + border_right < r.x1 ?
- x + padding_width + border_right : r.x1;
- p.y1 = y + padding_height + border_bottom < r.y1 ?
- y + padding_height + border_bottom : r.y1;
- if (!box->parent) {
- /* Root element, special case:
- * background covers margins too */
- int m_left, m_top, m_right, m_bottom;
- if (scale == 1.0) {
- m_left = box->margin[LEFT];
- m_top = box->margin[TOP];
- m_right = box->margin[RIGHT];
- m_bottom = box->margin[BOTTOM];
- } else {
- m_left = box->margin[LEFT] * scale;
- m_top = box->margin[TOP] * scale;
- m_right = box->margin[RIGHT] * scale;
- m_bottom = box->margin[BOTTOM] * scale;
- }
- p.x0 = p.x0 - m_left < r.x0 ? r.x0 : p.x0 - m_left;
- p.y0 = p.y0 - m_top < r.y0 ? r.y0 : p.y0 - m_top;
- p.x1 = p.x1 + m_right < r.x1 ? p.x1 + m_right : r.x1;
- p.y1 = p.y1 + m_bottom < r.y1 ? p.y1 + m_bottom : r.y1;
- }
- /* valid clipping rectangles only */
- if ((p.x0 < p.x1) && (p.y0 < p.y1)) {
- /* plot background */
- if (!html_redraw_background(x, y, box, scale, &p,
- &current_background_color, bg_box, ctx))
- return false;
- /* restore previous graphics window */
- if (!plot->clip(&r))
- return false;
- }
- }
-
- /* borders for block level content and replaced inlines */
- if (box->style && box->type != BOX_TEXT &&
- box->type != BOX_INLINE_END &&
- (box->type != BOX_INLINE || box->object ||
- box->flags & IFRAME || box->flags & REPLACE_DIM) &&
- (border_top || border_right ||
- border_bottom || border_left)) {
- if (!html_redraw_borders(box, x_parent, y_parent,
- padding_width, padding_height, &r,
- scale, ctx))
- return false;
- }
-
- /* backgrounds and borders for non-replaced inlines */
- if (box->style && box->type == BOX_INLINE && box->inline_end &&
- (html_redraw_box_has_background(box) ||
- border_top || border_right ||
- border_bottom || border_left)) {
- /* inline backgrounds and borders span other boxes and may
- * wrap onto separate lines */
- struct box *ib;
- struct rect b; /* border edge rectangle */
- struct rect p; /* clipped rect */
- bool first = true;
- int ib_x;
- int ib_y = y;
- int ib_p_width;
- int ib_b_left, ib_b_right;
-
- b.x0 = x - border_left;
- b.x1 = x + padding_width + border_right;
- b.y0 = y - border_top;
- b.y1 = y + padding_height + border_bottom;
-
- p.x0 = b.x0 < r.x0 ? r.x0 : b.x0;
- p.x1 = b.x1 < r.x1 ? b.x1 : r.x1;
- p.y0 = b.y0 < r.y0 ? r.y0 : b.y0;
- p.y1 = b.y1 < r.y1 ? b.y1 : r.y1;
- for (ib = box; ib; ib = ib->next) {
- /* to get extents of rectangle(s) associated with
- * inline, cycle though all boxes in inline, skipping
- * over floats */
- if (ib->type == BOX_FLOAT_LEFT ||
- ib->type == BOX_FLOAT_RIGHT)
- continue;
- if (scale == 1.0) {
- ib_x = x_parent + ib->x;
- ib_y = y_parent + ib->y;
- ib_p_width = ib->padding[LEFT] + ib->width +
- ib->padding[RIGHT];
- ib_b_left = ib->border[LEFT].width;
- ib_b_right = ib->border[RIGHT].width;
- } else {
- ib_x = (x_parent + ib->x) * scale;
- ib_y = (y_parent + ib->y) * scale;
- ib_p_width = (ib->padding[LEFT] + ib->width +
- ib->padding[RIGHT]) * scale;
- ib_b_left = ib->border[LEFT].width * scale;
- ib_b_right = ib->border[RIGHT].width * scale;
- }
-
- if ((ib->flags & NEW_LINE) && ib != box) {
- /* inline element has wrapped, plot background
- * and borders */
- if (!html_redraw_inline_background(
- x, y, box, scale, &p, b,
- first, false,
- &current_background_color, ctx))
- return false;
- /* restore previous graphics window */
- if (!plot->clip(&r))
- return false;
- if (!html_redraw_inline_borders(box, b, &r,
- scale, first, false, ctx))
- return false;
- /* reset coords */
- b.x0 = ib_x - ib_b_left;
- b.y0 = ib_y - border_top - padding_top;
- b.y1 = ib_y + padding_height - padding_top +
- border_bottom;
-
- p.x0 = b.x0 < r.x0 ? r.x0 : b.x0;
- p.y0 = b.y0 < r.y0 ? r.y0 : b.y0;
- p.y1 = b.y1 < r.y1 ? b.y1 : r.y1;
-
- first = false;
- }
-
- /* increase width for current box */
- b.x1 = ib_x + ib_p_width + ib_b_right;
- p.x1 = b.x1 < r.x1 ? b.x1 : r.x1;
-
- if (ib == box->inline_end)
- /* reached end of BOX_INLINE span */
- break;
- }
- /* plot background and borders for last rectangle of
- * the inline */
- if (!html_redraw_inline_background(x, ib_y, box, scale, &p, b,
- first, true, &current_background_color, ctx))
- return false;
- /* restore previous graphics window */
- if (!plot->clip(&r))
- return false;
- if (!html_redraw_inline_borders(box, b, &r, scale, first, true,
- ctx))
- return false;
-
- }
-
- /* Debug outlines */
- if (html_redraw_debug) {
- int margin_left, margin_right;
- int margin_top, margin_bottom;
- if (scale == 1.0) {
- /* avoid trivial fp maths */
- margin_left = box->margin[LEFT];
- margin_top = box->margin[TOP];
- margin_right = box->margin[RIGHT];
- margin_bottom = box->margin[BOTTOM];
- } else {
- margin_left = box->margin[LEFT] * scale;
- margin_top = box->margin[TOP] * scale;
- margin_right = box->margin[RIGHT] * scale;
- margin_bottom = box->margin[BOTTOM] * scale;
- }
- /* Content edge -- blue */
- if (!plot->rectangle(x + padding_left,
- y + padding_top,
- x + padding_left + width,
- y + padding_top + height,
- plot_style_content_edge))
- return false;
- /* Padding edge -- red */
- if (!plot->rectangle(x, y,
- x + padding_width, y + padding_height,
- plot_style_padding_edge))
- return false;
- /* Margin edge -- yellow */
- if (!plot->rectangle(
- x - border_left - margin_left,
- y - border_top - margin_top,
- x + padding_width + border_right +
- margin_right,
- y + padding_height + border_bottom +
- margin_bottom,
- plot_style_margin_edge))
- return false;
- }
-
- /* clip to the padding edge for objects, or boxes with overflow hidden
- * or scroll */
- if ((box->style && css_computed_overflow(box->style) !=
- CSS_OVERFLOW_VISIBLE) || box->object ||
- box->flags & IFRAME) {
- r.x0 = x;
- r.y0 = y;
- r.x1 = x + padding_width;
- r.y1 = y + padding_height;
- if (r.x0 < clip->x0) r.x0 = clip->x0;
- if (r.y0 < clip->y0) r.y0 = clip->y0;
- if (clip->x1 < r.x1) r.x1 = clip->x1;
- if (clip->y1 < r.y1) r.y1 = clip->y1;
- if (r.x1 <= r.x0 || r.y1 <= r.y0)
- return ((!plot->group_end) || (plot->group_end()));
- if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
- box->type == BOX_TABLE_CELL || box->object) {
- if (!plot->clip(&r))
- return false;
- }
- }
-
- /* text decoration */
- if (box->type != BOX_TEXT && box->style &&
- css_computed_text_decoration(box->style) !=
- CSS_TEXT_DECORATION_NONE)
- if (!html_redraw_text_decoration(box, x_parent, y_parent,
- scale, current_background_color, ctx))
- return false;
-
- if (box->object && width != 0 && height != 0) {
- struct content_redraw_data obj_data;
-
- x_scrolled = x - scrollbar_get_offset(box->scroll_x) * scale;
- y_scrolled = y - scrollbar_get_offset(box->scroll_y) * scale;
-
- obj_data.x = x_scrolled + padding_left;
- obj_data.y = y_scrolled + padding_top;
- obj_data.width = width;
- obj_data.height = height;
- obj_data.background_colour = current_background_color;
- obj_data.scale = scale;
- obj_data.repeat_x = false;
- obj_data.repeat_y = false;
-
- if (content_get_type(box->object) == CONTENT_HTML) {
- obj_data.x /= scale;
- obj_data.y /= scale;
- }
-
- if (!content_redraw(box->object, &obj_data, &r, ctx)) {
- /* Show image fail */
- /* Unicode (U+FFFC) 'OBJECT REPLACEMENT CHARACTER' */
- const char *obj = "\xef\xbf\xbc";
- int obj_width;
- int obj_x = x + padding_left;
- if (!plot->rectangle(x + padding_left,
- y + padding_top,
- x + padding_left + width - 1,
- y + padding_top + height - 1,
- plot_style_broken_object))
- return false;
- if (!nsfont.font_width(plot_fstyle_broken_object, obj,
- sizeof(obj) - 1, &obj_width))
- obj_x += 1;
- else
- obj_x += width / 2 - obj_width / 2;
-
- if (!plot->text(obj_x, y + padding_top + (int)
- (height * 0.75),
- obj, sizeof(obj) - 1,
- plot_fstyle_broken_object))
- return false;
- }
-
-
- } else if (box->iframe) {
- /* Offset is passed to browser window redraw unscaled */
- browser_window_redraw(box->iframe,
- (x + padding_left) / scale,
- (y + padding_top) / scale, &r, ctx);
-
- } else if (box->gadget && box->gadget->type == GADGET_CHECKBOX) {
- if (!html_redraw_checkbox(x + padding_left, y + padding_top,
- width, height, box->gadget->selected, ctx))
- return false;
-
- } else if (box->gadget && box->gadget->type == GADGET_RADIO) {
- if (!html_redraw_radio(x + padding_left, y + padding_top,
- width, height, box->gadget->selected, ctx))
- return false;
-
- } else if (box->gadget && box->gadget->type == GADGET_FILE) {
- if (!html_redraw_file(x + padding_left, y + padding_top,
- width, height, box, scale,
- current_background_color, ctx))
- return false;
-
- } else if (box->text) {
- if (!html_redraw_text_box(html, box, x, y, &r, scale,
- current_background_color, ctx))
- return false;
-
- } else {
- if (!html_redraw_box_children(html, box, x_parent, y_parent, &r,
- scale, current_background_color, ctx))
- return false;
- }
-
- if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
- box->type == BOX_TABLE_CELL || box->type == BOX_INLINE)
- if (!plot->clip(clip))
- return false;
-
- /* list marker */
- if (box->list_marker)
- if (!html_redraw_box(html, box->list_marker,
- x_parent + box->x -
- scrollbar_get_offset(box->scroll_x),
- y_parent + box->y -
- scrollbar_get_offset(box->scroll_y),
- clip, scale, current_background_color, ctx))
- return false;
-
- /* scrollbars */
- if (((box->style && box->type != BOX_BR &&
- box->type != BOX_TABLE && box->type != BOX_INLINE &&
- (css_computed_overflow(box->style) ==
- CSS_OVERFLOW_SCROLL ||
- css_computed_overflow(box->style) ==
- CSS_OVERFLOW_AUTO)) || (box->object &&
- content_get_type(box->object) == CONTENT_HTML)) &&
- box->parent != NULL) {
-
- has_x_scroll = box_hscrollbar_present(box);
- has_y_scroll = box_vscrollbar_present(box);
-
- if (!box_handle_scrollbars((struct content *)html,
- box, has_x_scroll, has_y_scroll))
- return false;
-
- if (box->scroll_x != NULL)
- scrollbar_redraw(box->scroll_x,
- x_parent + box->x,
- y_parent + box->y + box->padding[TOP] +
- box->height + box->padding[BOTTOM] -
- SCROLLBAR_WIDTH, clip, scale, ctx);
- if (box->scroll_y != NULL)
- scrollbar_redraw(box->scroll_y,
- x_parent + box->x + box->padding[LEFT] +
- box->width + box->padding[RIGHT] -
- SCROLLBAR_WIDTH,
- y_parent + box->y, clip, scale, ctx);
- }
-
- if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
- box->type == BOX_TABLE_CELL || box->type == BOX_INLINE)
- if (!plot->clip(clip))
- return false;
-
- return ((!plot->group_end) || (plot->group_end()));
-}
-
-
-/**
- * Draw the various children of a box.
- *
- * \param html html content
- * \param box box to draw children of
- * \param x_parent coordinate of parent box
- * \param y_parent coordinate of parent box
- * \param clip clip rectangle
- * \param scale scale for redraw
- * \param current_background_color background colour under this box
- * \param ctx current redraw context
- * \return true if successful, false otherwise
- */
-
-bool html_redraw_box_children(const html_content *html, struct box *box,
- int x_parent, int y_parent,
- const struct rect *clip, float scale,
- colour current_background_color,
- const struct redraw_context *ctx)
-{
- struct box *c;
-
- for (c = box->children; c; c = c->next) {
-
- if (c->type != BOX_FLOAT_LEFT && c->type != BOX_FLOAT_RIGHT)
- if (!html_redraw_box(html, c,
- x_parent + box->x -
- scrollbar_get_offset(box->scroll_x),
- y_parent + box->y -
- scrollbar_get_offset(box->scroll_y),
- clip, scale, current_background_color,
- ctx))
- return false;
- }
- for (c = box->float_children; c; c = c->next_float)
- if (!html_redraw_box(html, c,
- x_parent + box->x -
- scrollbar_get_offset(box->scroll_x),
- y_parent + box->y -
- scrollbar_get_offset(box->scroll_y),
- clip, scale, current_background_color,
- ctx))
- return false;
-
- return true;
-}
-
-
-/**
- * Redraw the text content of a box, possibly partially highlighted
- * because the text has been selected, or matches a search operation.
- *
- * \param box box with text content
- * \param x x co-ord of box
- * \param y y co-ord of box
- * \param clip current clip rectangle
- * \param scale current scale setting (1.0 = 100%)
- * \param current_background_color
- * \param ctx current redraw context
- * \return true iff successful and redraw should proceed
- */
-
-bool html_redraw_text_box(const html_content *html, struct box *box,
- int x, int y, const struct rect *clip, float scale,
- colour current_background_color,
- const struct redraw_context *ctx)
-{
- bool excluded = (box->object != NULL);
- plot_font_style_t fstyle;
-
- font_plot_style_from_css(box->style, &fstyle);
- fstyle.background = current_background_color;
-
- if (!text_redraw(box->text, box->length, box->byte_offset,
- box->space, &fstyle, x, y,
- clip, box->height, scale, excluded,
- (struct content *)html, &html->sel,
- html->search, ctx))
- return false;
-
- return true;
-}
-
-/**
* Redraw a short text string, complete with highlighting
* (for selection/search)
*
@@ -1084,6 +296,386 @@ bool text_redraw(const char *utf8_text, size_t utf8_len,
return true;
}
+static plot_style_t plot_style_bdr = {
+ .stroke_type = PLOT_OP_TYPE_DASH,
+};
+static plot_style_t plot_style_fillbdr = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_dark = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_light = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_ddark = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+static plot_style_t plot_style_fillbdr_dlight = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+};
+
+/**
+ * Draw one border.
+ *
+ * \param side index of border side (TOP, RIGHT, BOTTOM, LEFT)
+ * \param p array of precomputed border vertices
+ * \param c colour for border
+ * \param style border line style
+ * \param thickness border thickness
+ * \param rectangular whether border is rectangular
+ * \param ctx current redraw context
+ * \return true if successful, false otherwise
+ */
+
+static bool html_redraw_border_plot(const int side, const int *p, colour c,
+ enum css_border_style_e style, int thickness, bool rectangular,
+ const struct rect *clip, const struct redraw_context *ctx)
+{
+ const struct plotter_table *plot = ctx->plot;
+ int z[8]; /* Vertices of border part */
+ unsigned int light = side;
+ plot_style_t *plot_style_bdr_in;
+ plot_style_t *plot_style_bdr_out;
+
+ if (c == NS_TRANSPARENT)
+ return true;
+
+ plot_style_bdr.stroke_type = PLOT_OP_TYPE_DASH;
+ plot_style_bdr.stroke_colour = c;
+ plot_style_bdr.stroke_width = thickness;
+ plot_style_fillbdr.fill_colour = c;
+ plot_style_fillbdr_dark.fill_colour = darken_colour(c);
+ plot_style_fillbdr_light.fill_colour = lighten_colour(c);
+ plot_style_fillbdr_ddark.fill_colour = double_darken_colour(c);
+ plot_style_fillbdr_dlight.fill_colour = double_lighten_colour(c);
+
+ switch (style) {
+ case CSS_BORDER_STYLE_DOTTED:
+ plot_style_bdr.stroke_type = PLOT_OP_TYPE_DOT;
+ /* fall through */
+ case CSS_BORDER_STYLE_DASHED:
+ if (!plot->line((p[0] + p[2]) / 2,
+ (p[1] + p[3]) / 2,
+ (p[4] + p[6]) / 2,
+ (p[5] + p[7]) / 2,
+ &plot_style_bdr))
+ return false;
+ break;
+
+ case CSS_BORDER_STYLE_SOLID:
+ /* fall through to default */
+ default:
+ if (rectangular || thickness == 1) {
+ int x0, y0, x1, y1;
+ if (side == TOP || side == RIGHT) {
+ x0 = p[2]; y0 = p[3];
+ x1 = p[6]; y1 = p[7];
+ x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
+ x1 + p[4] - p[6] : x1;
+ } else {
+ x0 = p[6]; y0 = p[7];
+ x1 = p[2]; y1 = p[3];
+ y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
+ y1 + p[1] - p[3] : y1;
+ }
+ /* find intersection of clip rectangle and border */
+ x0 = (clip->x0 > x0) ? clip->x0 : x0;
+ y0 = (clip->y0 > y0) ? clip->y0 : y0;
+ x1 = (clip->x1 < x1) ? clip->x1 : x1;
+ y1 = (clip->y1 < y1) ? clip->y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot->rectangle(x0, y0, x1, y1,
+ &plot_style_fillbdr))
+ return false;
+ }
+ } else {
+ if (!plot->polygon(p, 4, &plot_style_fillbdr))
+ return false;
+ }
+ break;
+
+ case CSS_BORDER_STYLE_DOUBLE:
+ z[0] = p[0];
+ z[1] = p[1];
+ z[2] = (p[0] * 2 + p[2]) / 3;
+ z[3] = (p[1] * 2 + p[3]) / 3;
+ z[4] = (p[6] * 2 + p[4]) / 3;
+ z[5] = (p[7] * 2 + p[5]) / 3;
+ z[6] = p[6];
+ z[7] = p[7];
+ if (!plot->polygon(z, 4, &plot_style_fillbdr))
+ return false;
+ z[0] = p[2];
+ z[1] = p[3];
+ z[2] = (p[2] * 2 + p[0]) / 3;
+ z[3] = (p[3] * 2 + p[1]) / 3;
+ z[4] = (p[4] * 2 + p[6]) / 3;
+ z[5] = (p[5] * 2 + p[7]) / 3;
+ z[6] = p[4];
+ z[7] = p[5];
+ if (!plot->polygon(z, 4, &plot_style_fillbdr))
+ return false;
+ break;
+
+ case CSS_BORDER_STYLE_GROOVE:
+ light = 3 - light;
+ /* fall through */
+ case CSS_BORDER_STYLE_RIDGE:
+ /* choose correct colours for each part of the border line */
+ if (light <= 1) {
+ plot_style_bdr_in = &plot_style_fillbdr_dark;
+ plot_style_bdr_out = &plot_style_fillbdr_light;
+ } else {
+ plot_style_bdr_in = &plot_style_fillbdr_light;
+ plot_style_bdr_out = &plot_style_fillbdr_dark;
+ }
+
+ /* Render border */
+ if ((rectangular || thickness == 2) && thickness != 1) {
+ /* Border made up from two parts and can be plotted
+ * with rectangles */
+ int x0, y0, x1, y1;
+
+ /* First part */
+ if (side == TOP || side == RIGHT) {
+ x0 = (p[0] + p[2]) / 2; y0 = (p[1] + p[3]) / 2;
+ x1 = p[6]; y1 = p[7];
+ } else {
+ x0 = p[6]; y0 = p[7];
+ x1 = (p[0] + p[2]) / 2; y1 = (p[1] + p[3]) / 2;
+ }
+ /* find intersection of clip rectangle and border */
+ x0 = (clip->x0 > x0) ? clip->x0 : x0;
+ y0 = (clip->y0 > y0) ? clip->y0 : y0;
+ x1 = (clip->x1 < x1) ? clip->x1 : x1;
+ y1 = (clip->y1 < y1) ? clip->y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot->rectangle(x0, y0, x1, y1,
+ plot_style_bdr_in))
+ return false;
+ }
+
+ /* Second part */
+ if (side == TOP || side == RIGHT) {
+ x0 = p[2]; y0 = p[3];
+ x1 = (p[6] + p[4]) / 2; y1 = (p[7] + p[5]) / 2;
+ } else {
+ x0 = (p[6] + p[4]) / 2; y0 = (p[7] + p[5]) / 2;
+ x1 = p[2]; y1 = p[3];
+ }
+ /* find intersection of clip rectangle and border */
+ x0 = (clip->x0 > x0) ? clip->x0 : x0;
+ y0 = (clip->y0 > y0) ? clip->y0 : y0;
+ x1 = (clip->x1 < x1) ? clip->x1 : x1;
+ y1 = (clip->y1 < y1) ? clip->y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot->rectangle(x0, y0, x1, y1,
+ plot_style_bdr_out))
+ return false;
+ }
+ } else if (thickness == 1) {
+ /* Border made up from one part which can be plotted
+ * as a rectangle */
+ int x0, y0, x1, y1;
+ if (side == TOP || side == RIGHT) {
+ x0 = p[2]; y0 = p[3];
+ x1 = p[6]; y1 = p[7];
+ x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
+ x1 + p[4] - p[6] : x1;
+ /* find intersection of clip rectangle and
+ * border */
+ x0 = (clip->x0 > x0) ? clip->x0 : x0;
+ y0 = (clip->y0 > y0) ? clip->y0 : y0;
+ x1 = (clip->x1 < x1) ? clip->x1 : x1;
+ y1 = (clip->y1 < y1) ? clip->y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot->rectangle(x0, y0, x1, y1,
+ plot_style_bdr_in))
+ return false;
+ }
+ } else {
+ x0 = p[6]; y0 = p[7];
+ x1 = p[2]; y1 = p[3];
+ y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
+ y1 + p[1] - p[3] : y1;
+ /* find intersection of clip rectangle and
+ * border */
+ x0 = (clip->x0 > x0) ? clip->x0 : x0;
+ y0 = (clip->y0 > y0) ? clip->y0 : y0;
+ x1 = (clip->x1 < x1) ? clip->x1 : x1;
+ y1 = (clip->y1 < y1) ? clip->y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot->rectangle(x0, y0, x1, y1,
+ plot_style_bdr_out))
+ return false;
+ }
+ }
+ } else {
+ /* Border made up from two parts and can't be plotted
+ * with rectangles */
+ z[0] = p[0];
+ z[1] = p[1];
+ z[2] = (p[0] + p[2]) / 2;
+ z[3] = (p[1] + p[3]) / 2;
+ z[4] = (p[6] + p[4]) / 2;
+ z[5] = (p[7] + p[5]) / 2;
+ z[6] = p[6];
+ z[7] = p[7];
+ if (!plot->polygon(z, 4, plot_style_bdr_in))
+ return false;
+ z[0] = p[2];
+ z[1] = p[3];
+ z[6] = p[4];
+ z[7] = p[5];
+ if (!plot->polygon(z, 4, plot_style_bdr_out))
+ return false;
+ }
+ break;
+
+ case CSS_BORDER_STYLE_INSET:
+ light = (light + 2) % 4;
+ /* fall through */
+ case CSS_BORDER_STYLE_OUTSET:
+ /* choose correct colours for each part of the border line */
+ switch (light) {
+ case 0:
+ plot_style_bdr_in = &plot_style_fillbdr_light;
+ plot_style_bdr_out = &plot_style_fillbdr_dlight;
+ break;
+ case 1:
+ plot_style_bdr_in = &plot_style_fillbdr_ddark;
+ plot_style_bdr_out = &plot_style_fillbdr_dark;
+ break;
+ case 2:
+ plot_style_bdr_in = &plot_style_fillbdr_dark;
+ plot_style_bdr_out = &plot_style_fillbdr_ddark;
+ break;
+ case 3:
+ plot_style_bdr_in = &plot_style_fillbdr_dlight;
+ plot_style_bdr_out = &plot_style_fillbdr_light;
+ break;
+ default:
+ plot_style_bdr_in = &plot_style_fillbdr;
+ plot_style_bdr_out = &plot_style_fillbdr;
+ break;
+ }
+
+ /* Render border */
+ if ((rectangular || thickness == 2) && thickness != 1) {
+ /* Border made up from two parts and can be plotted
+ * with rectangles */
+ int x0, y0, x1, y1;
+
+ /* First part */
+ if (side == TOP || side == RIGHT) {
+ x0 = (p[0] + p[2]) / 2; y0 = (p[1] + p[3]) / 2;
+ x1 = p[6]; y1 = p[7];
+ } else {
+ x0 = p[6]; y0 = p[7];
+ x1 = (p[0] + p[2]) / 2; y1 = (p[1] + p[3]) / 2;
+ }
+ /* find intersection of clip rectangle and border */
+ x0 = (clip->x0 > x0) ? clip->x0 : x0;
+ y0 = (clip->y0 > y0) ? clip->y0 : y0;
+ x1 = (clip->x1 < x1) ? clip->x1 : x1;
+ y1 = (clip->y1 < y1) ? clip->y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot->rectangle(x0, y0, x1, y1,
+ plot_style_bdr_in))
+ return false;
+ }
+
+ /* Second part */
+ if (side == TOP || side == RIGHT) {
+ x0 = p[2]; y0 = p[3];
+ x1 = (p[6] + p[4]) / 2; y1 = (p[7] + p[5]) / 2;
+ } else {
+ x0 = (p[6] + p[4]) / 2; y0 = (p[7] + p[5]) / 2;
+ x1 = p[2]; y1 = p[3];
+ }
+ /* find intersection of clip rectangle and border */
+ x0 = (clip->x0 > x0) ? clip->x0 : x0;
+ y0 = (clip->y0 > y0) ? clip->y0 : y0;
+ x1 = (clip->x1 < x1) ? clip->x1 : x1;
+ y1 = (clip->y1 < y1) ? clip->y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot->rectangle(x0, y0, x1, y1,
+ plot_style_bdr_out))
+ return false;
+ }
+ } else if (thickness == 1) {
+ /* Border made up from one part which can be plotted
+ * as a rectangle */
+ int x0, y0, x1, y1;
+ if (side == TOP || side == RIGHT) {
+ x0 = p[2]; y0 = p[3];
+ x1 = p[6]; y1 = p[7];
+ x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
+ x1 + p[4] - p[6] : x1;
+ /* find intersection of clip rectangle and
+ * border */
+ x0 = (clip->x0 > x0) ? clip->x0 : x0;
+ y0 = (clip->y0 > y0) ? clip->y0 : y0;
+ x1 = (clip->x1 < x1) ? clip->x1 : x1;
+ y1 = (clip->y1 < y1) ? clip->y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot->rectangle(x0, y0, x1, y1,
+ plot_style_bdr_in))
+ return false;
+ }
+ } else {
+ x0 = p[6]; y0 = p[7];
+ x1 = p[2]; y1 = p[3];
+ y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
+ y1 + p[1] - p[3] : y1;
+ /* find intersection of clip rectangle and
+ * border */
+ x0 = (clip->x0 > x0) ? clip->x0 : x0;
+ y0 = (clip->y0 > y0) ? clip->y0 : y0;
+ x1 = (clip->x1 < x1) ? clip->x1 : x1;
+ y1 = (clip->y1 < y1) ? clip->y1 : y1;
+ if ((x0 < x1) && (y0 < y1)) {
+ /* valid clip rectangles only */
+ if (!plot->rectangle(x0, y0, x1, y1,
+ plot_style_bdr_out))
+ return false;
+ }
+ }
+ } else {
+ /* Border made up from two parts and can't be plotted
+ * with rectangles */
+ z[0] = p[0];
+ z[1] = p[1];
+ z[2] = (p[0] + p[2]) / 2;
+ z[3] = (p[1] + p[3]) / 2;
+ z[4] = (p[6] + p[4]) / 2;
+ z[5] = (p[7] + p[5]) / 2;
+ z[6] = p[6];
+ z[7] = p[7];
+ if (!plot->polygon(z, 4, plot_style_bdr_in))
+ return false;
+ z[0] = p[2];
+ z[1] = p[3];
+ z[6] = p[4];
+ z[7] = p[5];
+ if (!plot->polygon(z, 4, plot_style_bdr_out))
+ return false;
+ }
+ break;
+ }
+
+ return true;
+}
+
/**
* Draw borders for a box.
@@ -1098,7 +690,7 @@ bool text_redraw(const char *utf8_text, size_t utf8_len,
* \return true if successful, false otherwise
*/
-bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
+static bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
int p_width, int p_height, const struct rect *clip, float scale,
const struct redraw_context *ctx)
{
@@ -1333,7 +925,7 @@ bool html_redraw_borders(struct box *box, int x_parent, int y_parent,
* \return true if successful, false otherwise
*/
-bool html_redraw_inline_borders(struct box *box, struct rect b,
+static bool html_redraw_inline_borders(struct box *box, struct rect b,
const struct rect *clip, float scale, bool first, bool last,
const struct redraw_context *ctx)
{
@@ -1528,386 +1120,6 @@ bool html_redraw_inline_borders(struct box *box, struct rect b,
return true;
}
-static plot_style_t plot_style_bdr = {
- .stroke_type = PLOT_OP_TYPE_DASH,
-};
-static plot_style_t plot_style_fillbdr = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_dark = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_light = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_ddark = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-static plot_style_t plot_style_fillbdr_dlight = {
- .fill_type = PLOT_OP_TYPE_SOLID,
-};
-
-/**
- * Draw one border.
- *
- * \param side index of border side (TOP, RIGHT, BOTTOM, LEFT)
- * \param p array of precomputed border vertices
- * \param c colour for border
- * \param style border line style
- * \param thickness border thickness
- * \param rectangular whether border is rectangular
- * \param ctx current redraw context
- * \return true if successful, false otherwise
- */
-
-bool html_redraw_border_plot(const int side, const int *p, colour c,
- enum css_border_style_e style, int thickness, bool rectangular,
- const struct rect *clip, const struct redraw_context *ctx)
-{
- const struct plotter_table *plot = ctx->plot;
- int z[8]; /* Vertices of border part */
- unsigned int light = side;
- plot_style_t *plot_style_bdr_in;
- plot_style_t *plot_style_bdr_out;
-
- if (c == NS_TRANSPARENT)
- return true;
-
- plot_style_bdr.stroke_type = PLOT_OP_TYPE_DASH;
- plot_style_bdr.stroke_colour = c;
- plot_style_bdr.stroke_width = thickness;
- plot_style_fillbdr.fill_colour = c;
- plot_style_fillbdr_dark.fill_colour = darken_colour(c);
- plot_style_fillbdr_light.fill_colour = lighten_colour(c);
- plot_style_fillbdr_ddark.fill_colour = double_darken_colour(c);
- plot_style_fillbdr_dlight.fill_colour = double_lighten_colour(c);
-
- switch (style) {
- case CSS_BORDER_STYLE_DOTTED:
- plot_style_bdr.stroke_type = PLOT_OP_TYPE_DOT;
- /* fall through */
- case CSS_BORDER_STYLE_DASHED:
- if (!plot->line((p[0] + p[2]) / 2,
- (p[1] + p[3]) / 2,
- (p[4] + p[6]) / 2,
- (p[5] + p[7]) / 2,
- &plot_style_bdr))
- return false;
- break;
-
- case CSS_BORDER_STYLE_SOLID:
- /* fall through to default */
- default:
- if (rectangular || thickness == 1) {
- int x0, y0, x1, y1;
- if (side == TOP || side == RIGHT) {
- x0 = p[2]; y0 = p[3];
- x1 = p[6]; y1 = p[7];
- x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
- x1 + p[4] - p[6] : x1;
- } else {
- x0 = p[6]; y0 = p[7];
- x1 = p[2]; y1 = p[3];
- y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
- y1 + p[1] - p[3] : y1;
- }
- /* find intersection of clip rectangle and border */
- x0 = (clip->x0 > x0) ? clip->x0 : x0;
- y0 = (clip->y0 > y0) ? clip->y0 : y0;
- x1 = (clip->x1 < x1) ? clip->x1 : x1;
- y1 = (clip->y1 < y1) ? clip->y1 : y1;
- if ((x0 < x1) && (y0 < y1)) {
- /* valid clip rectangles only */
- if (!plot->rectangle(x0, y0, x1, y1,
- &plot_style_fillbdr))
- return false;
- }
- } else {
- if (!plot->polygon(p, 4, &plot_style_fillbdr))
- return false;
- }
- break;
-
- case CSS_BORDER_STYLE_DOUBLE:
- z[0] = p[0];
- z[1] = p[1];
- z[2] = (p[0] * 2 + p[2]) / 3;
- z[3] = (p[1] * 2 + p[3]) / 3;
- z[4] = (p[6] * 2 + p[4]) / 3;
- z[5] = (p[7] * 2 + p[5]) / 3;
- z[6] = p[6];
- z[7] = p[7];
- if (!plot->polygon(z, 4, &plot_style_fillbdr))
- return false;
- z[0] = p[2];
- z[1] = p[3];
- z[2] = (p[2] * 2 + p[0]) / 3;
- z[3] = (p[3] * 2 + p[1]) / 3;
- z[4] = (p[4] * 2 + p[6]) / 3;
- z[5] = (p[5] * 2 + p[7]) / 3;
- z[6] = p[4];
- z[7] = p[5];
- if (!plot->polygon(z, 4, &plot_style_fillbdr))
- return false;
- break;
-
- case CSS_BORDER_STYLE_GROOVE:
- light = 3 - light;
- /* fall through */
- case CSS_BORDER_STYLE_RIDGE:
- /* choose correct colours for each part of the border line */
- if (light <= 1) {
- plot_style_bdr_in = &plot_style_fillbdr_dark;
- plot_style_bdr_out = &plot_style_fillbdr_light;
- } else {
- plot_style_bdr_in = &plot_style_fillbdr_light;
- plot_style_bdr_out = &plot_style_fillbdr_dark;
- }
-
- /* Render border */
- if ((rectangular || thickness == 2) && thickness != 1) {
- /* Border made up from two parts and can be plotted
- * with rectangles */
- int x0, y0, x1, y1;
-
- /* First part */
- if (side == TOP || side == RIGHT) {
- x0 = (p[0] + p[2]) / 2; y0 = (p[1] + p[3]) / 2;
- x1 = p[6]; y1 = p[7];
- } else {
- x0 = p[6]; y0 = p[7];
- x1 = (p[0] + p[2]) / 2; y1 = (p[1] + p[3]) / 2;
- }
- /* find intersection of clip rectangle and border */
- x0 = (clip->x0 > x0) ? clip->x0 : x0;
- y0 = (clip->y0 > y0) ? clip->y0 : y0;
- x1 = (clip->x1 < x1) ? clip->x1 : x1;
- y1 = (clip->y1 < y1) ? clip->y1 : y1;
- if ((x0 < x1) && (y0 < y1)) {
- /* valid clip rectangles only */
- if (!plot->rectangle(x0, y0, x1, y1,
- plot_style_bdr_in))
- return false;
- }
-
- /* Second part */
- if (side == TOP || side == RIGHT) {
- x0 = p[2]; y0 = p[3];
- x1 = (p[6] + p[4]) / 2; y1 = (p[7] + p[5]) / 2;
- } else {
- x0 = (p[6] + p[4]) / 2; y0 = (p[7] + p[5]) / 2;
- x1 = p[2]; y1 = p[3];
- }
- /* find intersection of clip rectangle and border */
- x0 = (clip->x0 > x0) ? clip->x0 : x0;
- y0 = (clip->y0 > y0) ? clip->y0 : y0;
- x1 = (clip->x1 < x1) ? clip->x1 : x1;
- y1 = (clip->y1 < y1) ? clip->y1 : y1;
- if ((x0 < x1) && (y0 < y1)) {
- /* valid clip rectangles only */
- if (!plot->rectangle(x0, y0, x1, y1,
- plot_style_bdr_out))
- return false;
- }
- } else if (thickness == 1) {
- /* Border made up from one part which can be plotted
- * as a rectangle */
- int x0, y0, x1, y1;
- if (side == TOP || side == RIGHT) {
- x0 = p[2]; y0 = p[3];
- x1 = p[6]; y1 = p[7];
- x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
- x1 + p[4] - p[6] : x1;
- /* find intersection of clip rectangle and
- * border */
- x0 = (clip->x0 > x0) ? clip->x0 : x0;
- y0 = (clip->y0 > y0) ? clip->y0 : y0;
- x1 = (clip->x1 < x1) ? clip->x1 : x1;
- y1 = (clip->y1 < y1) ? clip->y1 : y1;
- if ((x0 < x1) && (y0 < y1)) {
- /* valid clip rectangles only */
- if (!plot->rectangle(x0, y0, x1, y1,
- plot_style_bdr_in))
- return false;
- }
- } else {
- x0 = p[6]; y0 = p[7];
- x1 = p[2]; y1 = p[3];
- y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
- y1 + p[1] - p[3] : y1;
- /* find intersection of clip rectangle and
- * border */
- x0 = (clip->x0 > x0) ? clip->x0 : x0;
- y0 = (clip->y0 > y0) ? clip->y0 : y0;
- x1 = (clip->x1 < x1) ? clip->x1 : x1;
- y1 = (clip->y1 < y1) ? clip->y1 : y1;
- if ((x0 < x1) && (y0 < y1)) {
- /* valid clip rectangles only */
- if (!plot->rectangle(x0, y0, x1, y1,
- plot_style_bdr_out))
- return false;
- }
- }
- } else {
- /* Border made up from two parts and can't be plotted
- * with rectangles */
- z[0] = p[0];
- z[1] = p[1];
- z[2] = (p[0] + p[2]) / 2;
- z[3] = (p[1] + p[3]) / 2;
- z[4] = (p[6] + p[4]) / 2;
- z[5] = (p[7] + p[5]) / 2;
- z[6] = p[6];
- z[7] = p[7];
- if (!plot->polygon(z, 4, plot_style_bdr_in))
- return false;
- z[0] = p[2];
- z[1] = p[3];
- z[6] = p[4];
- z[7] = p[5];
- if (!plot->polygon(z, 4, plot_style_bdr_out))
- return false;
- }
- break;
-
- case CSS_BORDER_STYLE_INSET:
- light = (light + 2) % 4;
- /* fall through */
- case CSS_BORDER_STYLE_OUTSET:
- /* choose correct colours for each part of the border line */
- switch (light) {
- case 0:
- plot_style_bdr_in = &plot_style_fillbdr_light;
- plot_style_bdr_out = &plot_style_fillbdr_dlight;
- break;
- case 1:
- plot_style_bdr_in = &plot_style_fillbdr_ddark;
- plot_style_bdr_out = &plot_style_fillbdr_dark;
- break;
- case 2:
- plot_style_bdr_in = &plot_style_fillbdr_dark;
- plot_style_bdr_out = &plot_style_fillbdr_ddark;
- break;
- case 3:
- plot_style_bdr_in = &plot_style_fillbdr_dlight;
- plot_style_bdr_out = &plot_style_fillbdr_light;
- break;
- default:
- plot_style_bdr_in = &plot_style_fillbdr;
- plot_style_bdr_out = &plot_style_fillbdr;
- break;
- }
-
- /* Render border */
- if ((rectangular || thickness == 2) && thickness != 1) {
- /* Border made up from two parts and can be plotted
- * with rectangles */
- int x0, y0, x1, y1;
-
- /* First part */
- if (side == TOP || side == RIGHT) {
- x0 = (p[0] + p[2]) / 2; y0 = (p[1] + p[3]) / 2;
- x1 = p[6]; y1 = p[7];
- } else {
- x0 = p[6]; y0 = p[7];
- x1 = (p[0] + p[2]) / 2; y1 = (p[1] + p[3]) / 2;
- }
- /* find intersection of clip rectangle and border */
- x0 = (clip->x0 > x0) ? clip->x0 : x0;
- y0 = (clip->y0 > y0) ? clip->y0 : y0;
- x1 = (clip->x1 < x1) ? clip->x1 : x1;
- y1 = (clip->y1 < y1) ? clip->y1 : y1;
- if ((x0 < x1) && (y0 < y1)) {
- /* valid clip rectangles only */
- if (!plot->rectangle(x0, y0, x1, y1,
- plot_style_bdr_in))
- return false;
- }
-
- /* Second part */
- if (side == TOP || side == RIGHT) {
- x0 = p[2]; y0 = p[3];
- x1 = (p[6] + p[4]) / 2; y1 = (p[7] + p[5]) / 2;
- } else {
- x0 = (p[6] + p[4]) / 2; y0 = (p[7] + p[5]) / 2;
- x1 = p[2]; y1 = p[3];
- }
- /* find intersection of clip rectangle and border */
- x0 = (clip->x0 > x0) ? clip->x0 : x0;
- y0 = (clip->y0 > y0) ? clip->y0 : y0;
- x1 = (clip->x1 < x1) ? clip->x1 : x1;
- y1 = (clip->y1 < y1) ? clip->y1 : y1;
- if ((x0 < x1) && (y0 < y1)) {
- /* valid clip rectangles only */
- if (!plot->rectangle(x0, y0, x1, y1,
- plot_style_bdr_out))
- return false;
- }
- } else if (thickness == 1) {
- /* Border made up from one part which can be plotted
- * as a rectangle */
- int x0, y0, x1, y1;
- if (side == TOP || side == RIGHT) {
- x0 = p[2]; y0 = p[3];
- x1 = p[6]; y1 = p[7];
- x1 = ((side == TOP) && (p[4] - p[6] != 0)) ?
- x1 + p[4] - p[6] : x1;
- /* find intersection of clip rectangle and
- * border */
- x0 = (clip->x0 > x0) ? clip->x0 : x0;
- y0 = (clip->y0 > y0) ? clip->y0 : y0;
- x1 = (clip->x1 < x1) ? clip->x1 : x1;
- y1 = (clip->y1 < y1) ? clip->y1 : y1;
- if ((x0 < x1) && (y0 < y1)) {
- /* valid clip rectangles only */
- if (!plot->rectangle(x0, y0, x1, y1,
- plot_style_bdr_in))
- return false;
- }
- } else {
- x0 = p[6]; y0 = p[7];
- x1 = p[2]; y1 = p[3];
- y1 = ((side == LEFT) && (p[1] - p[3] != 0)) ?
- y1 + p[1] - p[3] : y1;
- /* find intersection of clip rectangle and
- * border */
- x0 = (clip->x0 > x0) ? clip->x0 : x0;
- y0 = (clip->y0 > y0) ? clip->y0 : y0;
- x1 = (clip->x1 < x1) ? clip->x1 : x1;
- y1 = (clip->y1 < y1) ? clip->y1 : y1;
- if ((x0 < x1) && (y0 < y1)) {
- /* valid clip rectangles only */
- if (!plot->rectangle(x0, y0, x1, y1,
- plot_style_bdr_out))
- return false;
- }
- }
- } else {
- /* Border made up from two parts and can't be plotted
- * with rectangles */
- z[0] = p[0];
- z[1] = p[1];
- z[2] = (p[0] + p[2]) / 2;
- z[3] = (p[1] + p[3]) / 2;
- z[4] = (p[6] + p[4]) / 2;
- z[5] = (p[7] + p[5]) / 2;
- z[6] = p[6];
- z[7] = p[7];
- if (!plot->polygon(z, 4, plot_style_bdr_in))
- return false;
- z[0] = p[2];
- z[1] = p[3];
- z[6] = p[4];
- z[7] = p[5];
- if (!plot->polygon(z, 4, plot_style_bdr_out))
- return false;
- }
- break;
- }
-
- return true;
-}
-
/**
* Plot a checkbox.
@@ -1921,8 +1133,8 @@ bool html_redraw_border_plot(const int side, const int *p, colour c,
* \return true if successful, false otherwise
*/
-bool html_redraw_checkbox(int x, int y, int width, int height, bool selected,
- const struct redraw_context *ctx)
+static bool html_redraw_checkbox(int x, int y, int width, int height,
+ bool selected, const struct redraw_context *ctx)
{
const struct plotter_table *plot = ctx->plot;
double z = width * 0.15;
@@ -1977,8 +1189,8 @@ bool html_redraw_checkbox(int x, int y, int width, int height, bool selected,
* \param ctx current redraw context
* \return true if successful, false otherwise
*/
-bool html_redraw_radio(int x, int y, int width, int height, bool selected,
- const struct redraw_context *ctx)
+static bool html_redraw_radio(int x, int y, int width, int height,
+ bool selected, const struct redraw_context *ctx)
{
const struct plotter_table *plot = ctx->plot;
@@ -2034,7 +1246,7 @@ bool html_redraw_radio(int x, int y, int width, int height, bool selected,
* \return true if successful, false otherwise
*/
-bool html_redraw_file(int x, int y, int width, int height,
+static bool html_redraw_file(int x, int y, int width, int height,
struct box *box, float scale, colour background_colour,
const struct redraw_context *ctx)
{
@@ -2082,7 +1294,7 @@ bool html_redraw_file(int x, int y, int width, int height,
* to ::box, using the background information contained within ::background.
*/
-bool html_redraw_background(int x, int y, struct box *box, float scale,
+static bool html_redraw_background(int x, int y, struct box *box, float scale,
const struct rect *clip, colour *background_colour,
struct box *background, const struct redraw_context *ctx)
{
@@ -2302,9 +1514,10 @@ bool html_redraw_background(int x, int y, struct box *box, float scale,
* \return true if successful, false otherwise
*/
-bool html_redraw_inline_background(int x, int y, struct box *box, float scale,
- const struct rect *clip, struct rect b, bool first, bool last,
- colour *background_colour, const struct redraw_context *ctx)
+static bool html_redraw_inline_background(int x, int y, struct box *box,
+ float scale, const struct rect *clip, struct rect b,
+ bool first, bool last, colour *background_colour,
+ const struct redraw_context *ctx)
{
const struct plotter_table *plot = ctx->plot;
struct rect r = *clip;
@@ -2433,6 +1646,91 @@ bool html_redraw_inline_background(int x, int y, struct box *box, float scale,
/**
+ * 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
+ * \param ctx current redraw context
+ * \return true if successful, false otherwise
+ */
+
+static bool html_redraw_text_decoration_inline(struct box *box, int x, int y,
+ float scale, colour colour, float ratio,
+ const struct redraw_context *ctx)
+{
+ const struct plotter_table *plot = ctx->plot;
+ struct box *c;
+ plot_style_t plot_style_box = {
+ .stroke_type = PLOT_OP_TYPE_SOLID,
+ .stroke_colour = colour,
+ };
+
+ for (c = box->next;
+ c && c != box->inline_end;
+ c = c->next) {
+ if (c->type != BOX_TEXT)
+ continue;
+ 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,
+ &plot_style_box))
+ 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
+ * \param ctx current redraw context
+ * \return true if successful, false otherwise
+ */
+
+static bool html_redraw_text_decoration_block(struct box *box, int x, int y,
+ float scale, colour colour, float ratio,
+ const struct redraw_context *ctx)
+{
+ const struct plotter_table *plot = ctx->plot;
+ struct box *c;
+ plot_style_t plot_style_box = {
+ .stroke_type = PLOT_OP_TYPE_SOLID,
+ .stroke_colour = colour,
+ };
+
+ /* draw through text descendants */
+ for (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,
+ &plot_style_box))
+ 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, ctx))
+ return false;
+ }
+ }
+ return true;
+}
+
+
+/**
* Plot text decoration for a box.
*
* \param box box to plot decorations for
@@ -2444,7 +1742,7 @@ bool html_redraw_inline_background(int x, int y, struct box *box, float scale,
* \return true if successful, false otherwise
*/
-bool html_redraw_text_decoration(struct box *box,
+static bool html_redraw_text_decoration(struct box *box,
int x_parent, int y_parent, float scale,
colour background_colour, const struct redraw_context *ctx)
{
@@ -2490,85 +1788,750 @@ bool html_redraw_text_decoration(struct box *box,
/**
- * Plot text decoration for an inline box.
+ * Redraw the text content of a box, possibly partially highlighted
+ * because the text has been selected, or matches a search operation.
*
- * \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
- * \param ctx current redraw context
+ * \param box box with text content
+ * \param x x co-ord of box
+ * \param y y co-ord of box
+ * \param clip current clip rectangle
+ * \param scale current scale setting (1.0 = 100%)
+ * \param current_background_color
+ * \param ctx current redraw context
+ * \return true iff successful and redraw should proceed
+ */
+
+static bool html_redraw_text_box(const html_content *html, struct box *box,
+ int x, int y, const struct rect *clip, float scale,
+ colour current_background_color,
+ const struct redraw_context *ctx)
+{
+ bool excluded = (box->object != NULL);
+ plot_font_style_t fstyle;
+
+ font_plot_style_from_css(box->style, &fstyle);
+ fstyle.background = current_background_color;
+
+ if (!text_redraw(box->text, box->length, box->byte_offset,
+ box->space, &fstyle, x, y,
+ clip, box->height, scale, excluded,
+ (struct content *)html, &html->sel,
+ html->search, ctx))
+ return false;
+
+ return true;
+}
+
+bool html_redraw_box(const html_content *html, struct box *box,
+ int x_parent, int y_parent,
+ const struct rect *clip, float scale,
+ colour current_background_color,
+ const struct redraw_context *ctx);
+
+/**
+ * Draw the various children of a box.
+ *
+ * \param html html content
+ * \param box box to draw children of
+ * \param x_parent coordinate of parent box
+ * \param y_parent coordinate of parent box
+ * \param clip clip rectangle
+ * \param scale scale for redraw
+ * \param current_background_color background colour under this box
+ * \param ctx current redraw context
* \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,
+static bool html_redraw_box_children(const html_content *html, struct box *box,
+ int x_parent, int y_parent,
+ const struct rect *clip, float scale,
+ colour current_background_color,
const struct redraw_context *ctx)
{
- const struct plotter_table *plot = ctx->plot;
struct box *c;
- plot_style_t plot_style_box = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_colour = colour,
- };
- for (c = box->next;
- c && c != box->inline_end;
- c = c->next) {
- if (c->type != BOX_TEXT)
- continue;
- 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,
- &plot_style_box))
- return false;
+ for (c = box->children; c; c = c->next) {
+
+ if (c->type != BOX_FLOAT_LEFT && c->type != BOX_FLOAT_RIGHT)
+ if (!html_redraw_box(html, c,
+ x_parent + box->x -
+ scrollbar_get_offset(box->scroll_x),
+ y_parent + box->y -
+ scrollbar_get_offset(box->scroll_y),
+ clip, scale, current_background_color,
+ ctx))
+ return false;
}
+ for (c = box->float_children; c; c = c->next_float)
+ if (!html_redraw_box(html, c,
+ x_parent + box->x -
+ scrollbar_get_offset(box->scroll_x),
+ y_parent + box->y -
+ scrollbar_get_offset(box->scroll_y),
+ clip, scale, current_background_color,
+ ctx))
+ return false;
+
return true;
}
-
/**
- * Plot text decoration for an non-inline box.
+ * Recursively draw a 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
- * \param ctx current redraw context
+ * \param html html content
+ * \param box box to draw
+ * \param x_parent coordinate of parent box
+ * \param y_parent coordinate of parent box
+ * \param clip clip rectangle
+ * \param scale scale for redraw
+ * \param current_background_color background colour under this box
+ * \param ctx current redraw context
* \return true if successful, false otherwise
+ *
+ * x, y, clip_[xy][01] are in target coordinates.
*/
-bool html_redraw_text_decoration_block(struct box *box, int x, int y,
- float scale, colour colour, float ratio,
+bool html_redraw_box(const html_content *html, struct box *box,
+ int x_parent, int y_parent,
+ const struct rect *clip, float scale,
+ colour current_background_color,
const struct redraw_context *ctx)
{
const struct plotter_table *plot = ctx->plot;
- struct box *c;
- plot_style_t plot_style_box = {
- .stroke_type = PLOT_OP_TYPE_SOLID,
- .stroke_colour = colour,
- };
+ int x, y;
+ int width, height;
+ int padding_left, padding_top, padding_width, padding_height;
+ int border_left, border_top, border_right, border_bottom;
+ struct rect r;
+ int x_scrolled, y_scrolled;
+ struct box *bg_box = NULL;
+ bool has_x_scroll, has_y_scroll;
+ css_computed_clip_rect css_rect;
- /* draw through text descendants */
- for (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,
- &plot_style_box))
+ if (html_redraw_printing && (box->flags & PRINTED))
+ return true;
+
+ /* avoid trivial FP maths */
+ if (scale == 1.0) {
+ x = x_parent + box->x;
+ y = y_parent + box->y;
+ width = box->width;
+ height = box->height;
+ padding_left = box->padding[LEFT];
+ padding_top = box->padding[TOP];
+ padding_width = padding_left + box->width + box->padding[RIGHT];
+ padding_height = padding_top + box->height +
+ box->padding[BOTTOM];
+ border_left = box->border[LEFT].width;
+ border_top = box->border[TOP].width;
+ border_right = box->border[RIGHT].width;
+ border_bottom = box->border[BOTTOM].width;
+ } else {
+ x = (x_parent + box->x) * scale;
+ y = (y_parent + box->y) * scale;
+ width = box->width * scale;
+ height = box->height * scale;
+ /* left and top padding values are normally zero,
+ * so avoid trivial FP maths */
+ padding_left = box->padding[LEFT] ? box->padding[LEFT] * scale
+ : 0;
+ padding_top = box->padding[TOP] ? box->padding[TOP] * scale
+ : 0;
+ padding_width = (box->padding[LEFT] + box->width +
+ box->padding[RIGHT]) * scale;
+ padding_height = (box->padding[TOP] + box->height +
+ box->padding[BOTTOM]) * scale;
+ border_left = box->border[LEFT].width * scale;
+ border_top = box->border[TOP].width * scale;
+ border_right = box->border[RIGHT].width * scale;
+ border_bottom = box->border[BOTTOM].width * scale;
+ }
+
+ /* calculate rectangle covering this box and descendants */
+ if (box->style && css_computed_overflow(box->style) !=
+ CSS_OVERFLOW_VISIBLE) {
+ /* box contents clipped to box size */
+ r.x0 = x - border_left;
+ r.y0 = y - border_top;
+ r.x1 = x + padding_width + border_right;
+ r.y1 = y + padding_height + border_bottom;
+ } else {
+ /* box contents can hang out of the box; use descendant box */
+ if (scale == 1.0) {
+ r.x0 = x + box->descendant_x0;
+ r.y0 = y + box->descendant_y0;
+ r.x1 = x + box->descendant_x1 + 1;
+ r.y1 = y + box->descendant_y1 + 1;
+ } else {
+ r.x0 = x + box->descendant_x0 * scale;
+ r.y0 = y + box->descendant_y0 * scale;
+ r.x1 = x + box->descendant_x1 * scale + 1;
+ r.y1 = y + box->descendant_y1 * scale + 1;
+ }
+ if (!box->parent) {
+ /* root element */
+ int margin_left, margin_right;
+ int margin_top, margin_bottom;
+ if (scale == 1.0) {
+ margin_left = box->margin[LEFT];
+ margin_top = box->margin[TOP];
+ margin_right = box->margin[RIGHT];
+ margin_bottom = box->margin[BOTTOM];
+ } else {
+ margin_left = box->margin[LEFT] * scale;
+ margin_top = box->margin[TOP] * scale;
+ margin_right = box->margin[RIGHT] * scale;
+ margin_bottom = box->margin[BOTTOM] * scale;
+ }
+ r.x0 = x - border_left - margin_left < r.x0 ?
+ x - border_left - margin_left : r.x0;
+ r.y0 = y - border_top - margin_top < r.y0 ?
+ y - border_top - margin_top : r.y0;
+ r.x1 = x + padding_width + border_right +
+ margin_right > r.x1 ?
+ x + padding_width + border_right +
+ margin_right : r.x1;
+ r.y1 = y + padding_height + border_bottom +
+ margin_bottom > r.y1 ?
+ y + padding_height + border_bottom +
+ margin_bottom : r.y1;
+ }
+ }
+
+ /* return if the rectangle is completely outside the clip rectangle */
+ if (clip->y1 < r.y0 || r.y1 < clip->y0 ||
+ clip->x1 < r.x0 || r.x1 < clip->x0)
+ return true;
+
+ /*if the rectangle is under the page bottom but it can fit in a page,
+ don't print it now*/
+ if (html_redraw_printing) {
+ if (r.y1 > html_redraw_printing_border) {
+ if (r.y1 - r.y0 <= html_redraw_printing_border &&
+ (box->type == BOX_TEXT ||
+ box->type == BOX_TABLE_CELL
+ || box->object || box->gadget)) {
+ /*remember the highest of all points from the
+ not printed elements*/
+ if (r.y0 < html_redraw_printing_top_cropped)
+ html_redraw_printing_top_cropped = r.y0;
+ return true;
+ }
+ }
+ else box->flags |= PRINTED; /*it won't be printed anymore*/
+ }
+
+ /* if visibility is hidden render children only */
+ if (box->style && css_computed_visibility(box->style) ==
+ CSS_VISIBILITY_HIDDEN) {
+ if ((plot->group_start) && (!plot->group_start("hidden box")))
+ return false;
+ if (!html_redraw_box_children(html, box, x_parent, y_parent,
+ &r, scale, current_background_color, ctx))
+ return false;
+ return ((!plot->group_end) || (plot->group_end()));
+ }
+
+ if ((plot->group_start) && (!plot->group_start("vis box")))
+ return false;
+
+
+ if (box->style != NULL &&
+ css_computed_position(box->style) ==
+ CSS_POSITION_ABSOLUTE &&
+ css_computed_clip(box->style, &css_rect) ==
+ CSS_CLIP_RECT) {
+ /* We have an absolutly positioned box with a clip rect */
+ if (css_rect.left_auto == false)
+ r.x0 = x - border_left + FIXTOINT(nscss_len2px(
+ css_rect.left, css_rect.lunit,
+ box->style));
+
+ if (css_rect.top_auto == false)
+ r.y0 = y - border_top + FIXTOINT(nscss_len2px(
+ css_rect.top, css_rect.tunit,
+ box->style));
+
+ if (css_rect.right_auto == false)
+ r.x1 = x - border_left + FIXTOINT(nscss_len2px(
+ css_rect.right, css_rect.runit,
+ box->style));
+
+ if (css_rect.bottom_auto == false)
+ r.y1 = y - border_top + FIXTOINT(nscss_len2px(
+ css_rect.bottom, css_rect.bunit,
+ box->style));
+
+ /* find intersection of clip rectangle and box */
+ if (r.x0 < clip->x0) r.x0 = clip->x0;
+ if (r.y0 < clip->y0) r.y0 = clip->y0;
+ if (clip->x1 < r.x1) r.x1 = clip->x1;
+ if (clip->y1 < r.y1) r.y1 = clip->y1;
+ /* no point trying to draw 0-width/height boxes */
+ if (r.x0 == r.x1 || r.y0 == r.y1)
+ /* not an error */
+ return ((!plot->group_end) || (plot->group_end()));
+ /* clip to it */
+ if (!plot->clip(&r))
+ return false;
+
+ } else if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
+ box->type == BOX_TABLE_CELL || box->object) {
+ /* find intersection of clip rectangle and box */
+ if (r.x0 < clip->x0) r.x0 = clip->x0;
+ if (r.y0 < clip->y0) r.y0 = clip->y0;
+ if (clip->x1 < r.x1) r.x1 = clip->x1;
+ if (clip->y1 < r.y1) r.y1 = clip->y1;
+ /* no point trying to draw 0-width/height boxes */
+ if (r.x0 == r.x1 || r.y0 == r.y1)
+ /* not an error */
+ return ((!plot->group_end) || (plot->group_end()));
+ /* clip to it */
+ if (!plot->clip(&r))
+ return false;
+ } else {
+ /* clip box is fine, clip to it */
+ r = *clip;
+ if (!plot->clip(&r))
+ return false;
+ }
+
+ /* background colour and image for block level content and replaced
+ * inlines */
+
+ bg_box = html_redraw_find_bg_box(box);
+
+ /* bg_box == NULL implies that this box should not have
+ * its background rendered. Otherwise filter out linebreaks,
+ * optimize away non-differing inlines, only plot background
+ * for BOX_TEXT it's in an inline */
+ if (bg_box && bg_box->type != BOX_BR &&
+ bg_box->type != BOX_TEXT &&
+ bg_box->type != BOX_INLINE_END &&
+ (bg_box->type != BOX_INLINE || bg_box->object ||
+ bg_box->flags & IFRAME || box->flags & REPLACE_DIM)) {
+ /* find intersection of clip box and border edge */
+ struct rect p;
+ p.x0 = x - border_left < r.x0 ? r.x0 : x - border_left;
+ p.y0 = y - border_top < r.y0 ? r.y0 : y - border_top;
+ p.x1 = x + padding_width + border_right < r.x1 ?
+ x + padding_width + border_right : r.x1;
+ p.y1 = y + padding_height + border_bottom < r.y1 ?
+ y + padding_height + border_bottom : r.y1;
+ if (!box->parent) {
+ /* Root element, special case:
+ * background covers margins too */
+ int m_left, m_top, m_right, m_bottom;
+ if (scale == 1.0) {
+ m_left = box->margin[LEFT];
+ m_top = box->margin[TOP];
+ m_right = box->margin[RIGHT];
+ m_bottom = box->margin[BOTTOM];
+ } else {
+ m_left = box->margin[LEFT] * scale;
+ m_top = box->margin[TOP] * scale;
+ m_right = box->margin[RIGHT] * scale;
+ m_bottom = box->margin[BOTTOM] * scale;
+ }
+ p.x0 = p.x0 - m_left < r.x0 ? r.x0 : p.x0 - m_left;
+ p.y0 = p.y0 - m_top < r.y0 ? r.y0 : p.y0 - m_top;
+ p.x1 = p.x1 + m_right < r.x1 ? p.x1 + m_right : r.x1;
+ p.y1 = p.y1 + m_bottom < r.y1 ? p.y1 + m_bottom : r.y1;
+ }
+ /* valid clipping rectangles only */
+ if ((p.x0 < p.x1) && (p.y0 < p.y1)) {
+ /* plot background */
+ if (!html_redraw_background(x, y, box, scale, &p,
+ &current_background_color, bg_box, ctx))
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, ctx))
+ /* restore previous graphics window */
+ if (!plot->clip(&r))
return false;
}
}
- return true;
+
+ /* borders for block level content and replaced inlines */
+ if (box->style && box->type != BOX_TEXT &&
+ box->type != BOX_INLINE_END &&
+ (box->type != BOX_INLINE || box->object ||
+ box->flags & IFRAME || box->flags & REPLACE_DIM) &&
+ (border_top || border_right ||
+ border_bottom || border_left)) {
+ if (!html_redraw_borders(box, x_parent, y_parent,
+ padding_width, padding_height, &r,
+ scale, ctx))
+ return false;
+ }
+
+ /* backgrounds and borders for non-replaced inlines */
+ if (box->style && box->type == BOX_INLINE && box->inline_end &&
+ (html_redraw_box_has_background(box) ||
+ border_top || border_right ||
+ border_bottom || border_left)) {
+ /* inline backgrounds and borders span other boxes and may
+ * wrap onto separate lines */
+ struct box *ib;
+ struct rect b; /* border edge rectangle */
+ struct rect p; /* clipped rect */
+ bool first = true;
+ int ib_x;
+ int ib_y = y;
+ int ib_p_width;
+ int ib_b_left, ib_b_right;
+
+ b.x0 = x - border_left;
+ b.x1 = x + padding_width + border_right;
+ b.y0 = y - border_top;
+ b.y1 = y + padding_height + border_bottom;
+
+ p.x0 = b.x0 < r.x0 ? r.x0 : b.x0;
+ p.x1 = b.x1 < r.x1 ? b.x1 : r.x1;
+ p.y0 = b.y0 < r.y0 ? r.y0 : b.y0;
+ p.y1 = b.y1 < r.y1 ? b.y1 : r.y1;
+ for (ib = box; ib; ib = ib->next) {
+ /* to get extents of rectangle(s) associated with
+ * inline, cycle though all boxes in inline, skipping
+ * over floats */
+ if (ib->type == BOX_FLOAT_LEFT ||
+ ib->type == BOX_FLOAT_RIGHT)
+ continue;
+ if (scale == 1.0) {
+ ib_x = x_parent + ib->x;
+ ib_y = y_parent + ib->y;
+ ib_p_width = ib->padding[LEFT] + ib->width +
+ ib->padding[RIGHT];
+ ib_b_left = ib->border[LEFT].width;
+ ib_b_right = ib->border[RIGHT].width;
+ } else {
+ ib_x = (x_parent + ib->x) * scale;
+ ib_y = (y_parent + ib->y) * scale;
+ ib_p_width = (ib->padding[LEFT] + ib->width +
+ ib->padding[RIGHT]) * scale;
+ ib_b_left = ib->border[LEFT].width * scale;
+ ib_b_right = ib->border[RIGHT].width * scale;
+ }
+
+ if ((ib->flags & NEW_LINE) && ib != box) {
+ /* inline element has wrapped, plot background
+ * and borders */
+ if (!html_redraw_inline_background(
+ x, y, box, scale, &p, b,
+ first, false,
+ &current_background_color, ctx))
+ return false;
+ /* restore previous graphics window */
+ if (!plot->clip(&r))
+ return false;
+ if (!html_redraw_inline_borders(box, b, &r,
+ scale, first, false, ctx))
+ return false;
+ /* reset coords */
+ b.x0 = ib_x - ib_b_left;
+ b.y0 = ib_y - border_top - padding_top;
+ b.y1 = ib_y + padding_height - padding_top +
+ border_bottom;
+
+ p.x0 = b.x0 < r.x0 ? r.x0 : b.x0;
+ p.y0 = b.y0 < r.y0 ? r.y0 : b.y0;
+ p.y1 = b.y1 < r.y1 ? b.y1 : r.y1;
+
+ first = false;
+ }
+
+ /* increase width for current box */
+ b.x1 = ib_x + ib_p_width + ib_b_right;
+ p.x1 = b.x1 < r.x1 ? b.x1 : r.x1;
+
+ if (ib == box->inline_end)
+ /* reached end of BOX_INLINE span */
+ break;
+ }
+ /* plot background and borders for last rectangle of
+ * the inline */
+ if (!html_redraw_inline_background(x, ib_y, box, scale, &p, b,
+ first, true, &current_background_color, ctx))
+ return false;
+ /* restore previous graphics window */
+ if (!plot->clip(&r))
+ return false;
+ if (!html_redraw_inline_borders(box, b, &r, scale, first, true,
+ ctx))
+ return false;
+
+ }
+
+ /* Debug outlines */
+ if (html_redraw_debug) {
+ int margin_left, margin_right;
+ int margin_top, margin_bottom;
+ if (scale == 1.0) {
+ /* avoid trivial fp maths */
+ margin_left = box->margin[LEFT];
+ margin_top = box->margin[TOP];
+ margin_right = box->margin[RIGHT];
+ margin_bottom = box->margin[BOTTOM];
+ } else {
+ margin_left = box->margin[LEFT] * scale;
+ margin_top = box->margin[TOP] * scale;
+ margin_right = box->margin[RIGHT] * scale;
+ margin_bottom = box->margin[BOTTOM] * scale;
+ }
+ /* Content edge -- blue */
+ if (!plot->rectangle(x + padding_left,
+ y + padding_top,
+ x + padding_left + width,
+ y + padding_top + height,
+ plot_style_content_edge))
+ return false;
+ /* Padding edge -- red */
+ if (!plot->rectangle(x, y,
+ x + padding_width, y + padding_height,
+ plot_style_padding_edge))
+ return false;
+ /* Margin edge -- yellow */
+ if (!plot->rectangle(
+ x - border_left - margin_left,
+ y - border_top - margin_top,
+ x + padding_width + border_right +
+ margin_right,
+ y + padding_height + border_bottom +
+ margin_bottom,
+ plot_style_margin_edge))
+ return false;
+ }
+
+ /* clip to the padding edge for objects, or boxes with overflow hidden
+ * or scroll */
+ if ((box->style && css_computed_overflow(box->style) !=
+ CSS_OVERFLOW_VISIBLE) || box->object ||
+ box->flags & IFRAME) {
+ r.x0 = x;
+ r.y0 = y;
+ r.x1 = x + padding_width;
+ r.y1 = y + padding_height;
+ if (r.x0 < clip->x0) r.x0 = clip->x0;
+ if (r.y0 < clip->y0) r.y0 = clip->y0;
+ if (clip->x1 < r.x1) r.x1 = clip->x1;
+ if (clip->y1 < r.y1) r.y1 = clip->y1;
+ if (r.x1 <= r.x0 || r.y1 <= r.y0)
+ return ((!plot->group_end) || (plot->group_end()));
+ if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
+ box->type == BOX_TABLE_CELL || box->object) {
+ if (!plot->clip(&r))
+ return false;
+ }
+ }
+
+ /* text decoration */
+ if (box->type != BOX_TEXT && box->style &&
+ css_computed_text_decoration(box->style) !=
+ CSS_TEXT_DECORATION_NONE)
+ if (!html_redraw_text_decoration(box, x_parent, y_parent,
+ scale, current_background_color, ctx))
+ return false;
+
+ if (box->object && width != 0 && height != 0) {
+ struct content_redraw_data obj_data;
+
+ x_scrolled = x - scrollbar_get_offset(box->scroll_x) * scale;
+ y_scrolled = y - scrollbar_get_offset(box->scroll_y) * scale;
+
+ obj_data.x = x_scrolled + padding_left;
+ obj_data.y = y_scrolled + padding_top;
+ obj_data.width = width;
+ obj_data.height = height;
+ obj_data.background_colour = current_background_color;
+ obj_data.scale = scale;
+ obj_data.repeat_x = false;
+ obj_data.repeat_y = false;
+
+ if (content_get_type(box->object) == CONTENT_HTML) {
+ obj_data.x /= scale;
+ obj_data.y /= scale;
+ }
+
+ if (!content_redraw(box->object, &obj_data, &r, ctx)) {
+ /* Show image fail */
+ /* Unicode (U+FFFC) 'OBJECT REPLACEMENT CHARACTER' */
+ const char *obj = "\xef\xbf\xbc";
+ int obj_width;
+ int obj_x = x + padding_left;
+ if (!plot->rectangle(x + padding_left,
+ y + padding_top,
+ x + padding_left + width - 1,
+ y + padding_top + height - 1,
+ plot_style_broken_object))
+ return false;
+ if (!nsfont.font_width(plot_fstyle_broken_object, obj,
+ sizeof(obj) - 1, &obj_width))
+ obj_x += 1;
+ else
+ obj_x += width / 2 - obj_width / 2;
+
+ if (!plot->text(obj_x, y + padding_top + (int)
+ (height * 0.75),
+ obj, sizeof(obj) - 1,
+ plot_fstyle_broken_object))
+ return false;
+ }
+
+
+ } else if (box->iframe) {
+ /* Offset is passed to browser window redraw unscaled */
+ browser_window_redraw(box->iframe,
+ (x + padding_left) / scale,
+ (y + padding_top) / scale, &r, ctx);
+
+ } else if (box->gadget && box->gadget->type == GADGET_CHECKBOX) {
+ if (!html_redraw_checkbox(x + padding_left, y + padding_top,
+ width, height, box->gadget->selected, ctx))
+ return false;
+
+ } else if (box->gadget && box->gadget->type == GADGET_RADIO) {
+ if (!html_redraw_radio(x + padding_left, y + padding_top,
+ width, height, box->gadget->selected, ctx))
+ return false;
+
+ } else if (box->gadget && box->gadget->type == GADGET_FILE) {
+ if (!html_redraw_file(x + padding_left, y + padding_top,
+ width, height, box, scale,
+ current_background_color, ctx))
+ return false;
+
+ } else if (box->text) {
+ if (!html_redraw_text_box(html, box, x, y, &r, scale,
+ current_background_color, ctx))
+ return false;
+
+ } else {
+ if (!html_redraw_box_children(html, box, x_parent, y_parent, &r,
+ scale, current_background_color, ctx))
+ return false;
+ }
+
+ if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
+ box->type == BOX_TABLE_CELL || box->type == BOX_INLINE)
+ if (!plot->clip(clip))
+ return false;
+
+ /* list marker */
+ if (box->list_marker)
+ if (!html_redraw_box(html, box->list_marker,
+ x_parent + box->x -
+ scrollbar_get_offset(box->scroll_x),
+ y_parent + box->y -
+ scrollbar_get_offset(box->scroll_y),
+ clip, scale, current_background_color, ctx))
+ return false;
+
+ /* scrollbars */
+ if (((box->style && box->type != BOX_BR &&
+ box->type != BOX_TABLE && box->type != BOX_INLINE &&
+ (css_computed_overflow(box->style) ==
+ CSS_OVERFLOW_SCROLL ||
+ css_computed_overflow(box->style) ==
+ CSS_OVERFLOW_AUTO)) || (box->object &&
+ content_get_type(box->object) == CONTENT_HTML)) &&
+ box->parent != NULL) {
+
+ has_x_scroll = box_hscrollbar_present(box);
+ has_y_scroll = box_vscrollbar_present(box);
+
+ if (!box_handle_scrollbars((struct content *)html,
+ box, has_x_scroll, has_y_scroll))
+ return false;
+
+ if (box->scroll_x != NULL)
+ scrollbar_redraw(box->scroll_x,
+ x_parent + box->x,
+ y_parent + box->y + box->padding[TOP] +
+ box->height + box->padding[BOTTOM] -
+ SCROLLBAR_WIDTH, clip, scale, ctx);
+ if (box->scroll_y != NULL)
+ scrollbar_redraw(box->scroll_y,
+ x_parent + box->x + box->padding[LEFT] +
+ box->width + box->padding[RIGHT] -
+ SCROLLBAR_WIDTH,
+ y_parent + box->y, clip, scale, ctx);
+ }
+
+ if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
+ box->type == BOX_TABLE_CELL || box->type == BOX_INLINE)
+ if (!plot->clip(clip))
+ return false;
+
+ return ((!plot->group_end) || (plot->group_end()));
+}
+
+/**
+ * Draw a CONTENT_HTML using the current set of plotters (plot).
+ *
+ * \param c content of type CONTENT_HTML
+ * \param data redraw data for this content redraw
+ * \param clip current clip region
+ * \param ctx current redraw context
+ * \return true if successful, false otherwise
+ *
+ * x, y, clip_[xy][01] are in target coordinates.
+ */
+
+bool html_redraw(struct content *c, struct content_redraw_data *data,
+ const struct rect *clip, const struct redraw_context *ctx)
+{
+ html_content *html = (html_content *) c;
+ struct box *box;
+ bool result = true;
+ bool select, select_only;
+ plot_style_t pstyle_fill_bg = {
+ .fill_type = PLOT_OP_TYPE_SOLID,
+ .fill_colour = data->background_colour,
+ };
+
+ box = html->layout;
+ assert(box);
+
+ /* The select menu needs special treating because, when opened, it
+ * reaches beyond its layout box.
+ */
+ select = false;
+ select_only = false;
+ if (ctx->interactive && html->visible_select_menu != NULL) {
+ struct form_control *control = html->visible_select_menu;
+ select = true;
+ /* check if the redraw rectangle is completely inside of the
+ select menu */
+ select_only = form_clip_inside_select_menu(control,
+ data->scale, clip);
+ }
+
+ if (!select_only) {
+ /* clear to background colour */
+ result = ctx->plot->clip(clip);
+
+ if (html->background_colour != NS_TRANSPARENT)
+ pstyle_fill_bg.fill_colour = html->background_colour;
+
+ result &= ctx->plot->rectangle(clip->x0, clip->y0,
+ clip->x1, clip->y1,
+ &pstyle_fill_bg);
+
+ result &= html_redraw_box(html, box, data->x, data->y, clip,
+ data->scale, pstyle_fill_bg.fill_colour, ctx);
+ }
+
+ if (select) {
+ int menu_x, menu_y;
+ box = html->visible_select_menu->box;
+ box_coords(box, &menu_x, &menu_y);
+
+ menu_x -= box->border[LEFT].width;
+ menu_y += box->height + box->border[BOTTOM].width +
+ box->padding[BOTTOM] + box->padding[TOP];
+ result &= form_redraw_select_menu(html->visible_select_menu,
+ data->x + menu_x, data->y + menu_y,
+ data->scale, clip, ctx);
+ }
+
+ return result;
+
}