CSS utils: Handle new units in length conversion routines.

This causes a ripple effect of all the callsites needing
information they didn't have.
This commit is contained in:
Michael Drake 2018-01-03 23:58:18 +00:00
parent a67973f312
commit 6be6fa1b21
24 changed files with 956 additions and 456 deletions

View File

@ -27,11 +27,75 @@
/** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */ /** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
css_fixed nscss_screen_dpi = F_90; css_fixed nscss_screen_dpi = F_90;
/**
* Map viewport-relative length units to either vh or vw.
*
* Non-viewport-relative units are unchanged.
*
* \param[in] ctx Length conversion context.
* \param[in] unit Unit to map.
* \return the mapped unit.
*/
static inline css_unit css_utils__fudge_viewport_units(
const nscss_len_ctx *ctx,
css_unit unit)
{
switch (unit) {
case CSS_UNIT_VI:
assert(ctx->root_style != NULL);
if (css_computed_writing_mode(ctx->root_style) ==
CSS_WRITING_MODE_HORIZONTAL_TB) {
unit = CSS_UNIT_VW;
} else {
unit = CSS_UNIT_VH;
}
break;
case CSS_UNIT_VB:
assert(ctx->root_style != NULL);
if (css_computed_writing_mode(ctx->root_style) ==
CSS_WRITING_MODE_HORIZONTAL_TB) {
unit = CSS_UNIT_VH;
} else {
unit = CSS_UNIT_VW;
}
break;
case CSS_UNIT_VMIN:
if (ctx->vh < ctx->vw) {
unit = CSS_UNIT_VH;
} else {
unit = CSS_UNIT_VW;
}
break;
case CSS_UNIT_VMAX:
if (ctx->vh > ctx->vw) {
unit = CSS_UNIT_VH;
} else {
unit = CSS_UNIT_VW;
}
break;
default: break;
}
return unit;
}
/* exported interface documented in content/handlers/css/utils.h */ /* exported interface documented in content/handlers/css/utils.h */
css_fixed nscss_len2pt(css_fixed length, css_unit unit) css_fixed nscss_len2pt(
const nscss_len_ctx *ctx,
css_fixed length,
css_unit unit)
{ {
/* Length must not be relative */ /* Length must not be relative */
assert(unit != CSS_UNIT_EM && unit != CSS_UNIT_EX); assert(unit != CSS_UNIT_EM &&
unit != CSS_UNIT_EX &&
unit != CSS_UNIT_CAP &&
unit != CSS_UNIT_CH &&
unit != CSS_UNIT_IC &&
unit != CSS_UNIT_REM &&
unit != CSS_UNIT_RLH);
unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) { switch (unit) {
/* We assume the screen and any other output has the same dpi */ /* We assume the screen and any other output has the same dpi */
@ -45,36 +109,50 @@ css_fixed nscss_len2pt(css_fixed length, css_unit unit)
/* 1in = 25.4mm => 1mm = (72/25.4)pt */ /* 1in = 25.4mm => 1mm = (72/25.4)pt */
case CSS_UNIT_MM: return FMUL(length, case CSS_UNIT_MM: return FMUL(length,
FDIV(F_72, FLTTOFIX(25.4))); FDIV(F_72, FLTTOFIX(25.4)));
/* 1in = 101.6q => 1mm = (72/101.6)pt */
case CSS_UNIT_Q: return FMUL(length,
FDIV(F_72, FLTTOFIX(101.6)));
case CSS_UNIT_PT: return length; case CSS_UNIT_PT: return length;
/* 1pc = 12pt */ /* 1pc = 12pt */
case CSS_UNIT_PC: return FMUL(length, INTTOFIX(12)); case CSS_UNIT_PC: return FMUL(length, INTTOFIX(12));
case CSS_UNIT_VH: return FDIV(FMUL(FDIV((length * ctx->vh), F_100),
F_72), nscss_screen_dpi);
case CSS_UNIT_VW: return FDIV(FMUL(FDIV((length * ctx->vw), F_100),
F_72), nscss_screen_dpi);
default: break; default: break;
} }
return 0; return 0;
} }
/* exported interface documented in content/handlers/css/utils.h */ /* exported interface documented in content/handlers/css/utils.h */
css_fixed nscss_len2px(css_fixed length, css_unit unit, css_fixed nscss_len2px(
const nscss_len_ctx *ctx,
css_fixed length,
css_unit unit,
const css_computed_style *style) const css_computed_style *style)
{ {
/* We assume the screen and any other output has the same dpi */ /* We assume the screen and any other output has the same dpi */
css_fixed px_per_unit; css_fixed px_per_unit;
assert(style != NULL || (unit != CSS_UNIT_EM && unit != CSS_UNIT_EX)); unit = css_utils__fudge_viewport_units(ctx, unit);
switch (unit) { switch (unit) {
case CSS_UNIT_EM: case CSS_UNIT_EM:
case CSS_UNIT_EX: case CSS_UNIT_EX:
case CSS_UNIT_CAP:
case CSS_UNIT_CH:
case CSS_UNIT_IC:
{ {
css_fixed font_size = 0; css_fixed font_size = 0;
css_unit font_unit = CSS_UNIT_PT; css_unit font_unit = CSS_UNIT_PT;
assert(style != NULL);
css_computed_font_size(style, &font_size, &font_unit); css_computed_font_size(style, &font_size, &font_unit);
/* Convert to points */ /* Convert to points */
font_size = nscss_len2pt(font_size, font_unit); font_size = nscss_len2pt(ctx, font_size, font_unit);
/* Clamp to configured minimum */ /* Clamp to configured minimum */
if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) { if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
@ -85,9 +163,22 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
* 1in = 72pt => 1pt = (DPI/72)px */ * 1in = 72pt => 1pt = (DPI/72)px */
px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72); px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
/* Scale ex units: we use a fixed ratio of 1ex = 0.6em */ /* Scale non-em units to em. We have fixed ratios. */
if (unit == CSS_UNIT_EX) switch (unit) {
case CSS_UNIT_EX:
px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.6)); px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.6));
break;
case CSS_UNIT_CAP:
px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.9));
break;
case CSS_UNIT_CH:
px_per_unit = FMUL(px_per_unit, FLTTOFIX(0.4));
break;
case CSS_UNIT_IC:
px_per_unit = FMUL(px_per_unit, FLTTOFIX(1.1));
break;
default: break;
}
} }
break; break;
case CSS_UNIT_PX: case CSS_UNIT_PX:
@ -105,6 +196,10 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_MM: case CSS_UNIT_MM:
px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(25.4)); px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(25.4));
break; break;
/* 1in = 101.6q => 1q = (DPI/101.6)px */
case CSS_UNIT_Q:
px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(101.6));
break;
/* 1in = 72pt => 1pt = (DPI/72)px */ /* 1in = 72pt => 1pt = (DPI/72)px */
case CSS_UNIT_PT: case CSS_UNIT_PT:
px_per_unit = FDIV(nscss_screen_dpi, F_72); px_per_unit = FDIV(nscss_screen_dpi, F_72);
@ -113,6 +208,39 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
case CSS_UNIT_PC: case CSS_UNIT_PC:
px_per_unit = FDIV(nscss_screen_dpi, INTTOFIX(6)); px_per_unit = FDIV(nscss_screen_dpi, INTTOFIX(6));
break; break;
case CSS_UNIT_REM:
{
css_fixed font_size = 0;
css_unit font_unit = CSS_UNIT_PT;
assert(ctx->root_style != NULL);
css_computed_font_size(ctx->root_style,
&font_size, &font_unit);
/* Convert to points */
font_size = nscss_len2pt(ctx, font_size, font_unit);
/* Clamp to configured minimum */
if (font_size < FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10)) {
font_size = FDIV(INTTOFIX(nsoption_int(font_min_size)), F_10);
}
/* Convert to pixels (manually, to maximise precision)
* 1in = 72pt => 1pt = (DPI/72)px */
px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
break;
}
/* 1rlh = <user_font_size>pt => 1rlh = (DPI/user_font_size)px */
case CSS_UNIT_RLH:
px_per_unit = FDIV(nscss_screen_dpi, FDIV(
INTTOFIX(nsoption_int(font_size)),
INTTOFIX(10)));
break;
case CSS_UNIT_VH:
return TRUNCATEFIX((FDIV((length * ctx->vh), F_100) + F_0_5));
case CSS_UNIT_VW:
return TRUNCATEFIX((FDIV((length * ctx->vw), F_100) + F_0_5));
default: default:
px_per_unit = 0; px_per_unit = 0;
break; break;

View File

@ -26,25 +26,55 @@
/** DPI of the screen, in fixed point units */ /** DPI of the screen, in fixed point units */
extern css_fixed nscss_screen_dpi; extern css_fixed nscss_screen_dpi;
/**
* Length conversion context data.
*/
typedef struct nscss_len_ctx {
/**
* Viewport width in px.
* Only used if unit is vh, vw, vi, vb, vmin, or vmax.
*/
int vw;
/**
* Viewport height in px.
* Only used if unit is vh, vw, vi, vb, vmin, or vmax.
*/
int vh;
/**
* Computed style for the document root element.
* May be NULL if unit is not rem, or rlh.
*/
const css_computed_style *root_style;
} nscss_len_ctx;
/** /**
* Convert an absolute CSS length to points. * Convert an absolute CSS length to points.
* *
* \param[in] length Absolute CSS length. * \param[in] ctx Length conversion context.
* \param[in] unit Unit of the length. * \param[in] length Absolute CSS length.
* \param[in] unit Unit of the length.
* \return length in points * \return length in points
*/ */
css_fixed nscss_len2pt(css_fixed length, css_unit unit); css_fixed nscss_len2pt(
const nscss_len_ctx *ctx,
css_fixed length,
css_unit unit);
/** /**
* Convert a CSS length to pixels. * Convert a CSS length to pixels.
* *
* \param length Length to convert * \param[in] ctx Length conversion context.
* \param unit Corresponding unit * \param[in] length Length to convert.
* \param style Computed style applying to length. May be NULL if unit is * \param[in] unit Corresponding unit.
* neither em nor ex * \param[in] style Computed style applying to length.
* May be NULL if unit is not em, ex, cap, ch, or ic.
* \return length in pixels * \return length in pixels
*/ */
css_fixed nscss_len2px(css_fixed length, css_unit unit, const css_computed_style *style); css_fixed nscss_len2px(
const nscss_len_ctx *ctx,
css_fixed length,
css_unit unit,
const css_computed_style *style);
/** /**

View File

@ -257,6 +257,11 @@ struct print_settings *print_make_settings(print_configuration configuration,
struct print_settings *settings; struct print_settings *settings;
css_fixed length = 0; css_fixed length = 0;
css_unit unit = CSS_UNIT_MM; css_unit unit = CSS_UNIT_MM;
nscss_len_ctx len_ctx = {
.vw = DEFAULT_PAGE_WIDTH,
.vh = DEFAULT_PAGE_HEIGHT,
.root_style = NULL,
};
switch (configuration){ switch (configuration){
case PRINT_DEFAULT: case PRINT_DEFAULT:
@ -272,17 +277,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = DEFAULT_EXPORT_SCALE; settings->scale = DEFAULT_EXPORT_SCALE;
length = INTTOFIX(DEFAULT_MARGIN_LEFT_MM); length = INTTOFIX(DEFAULT_MARGIN_LEFT_MM);
settings->margins[MARGINLEFT] = settings->margins[MARGINLEFT] = nscss_len2px(
nscss_len2px(length, unit, NULL); &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_RIGHT_MM); length = INTTOFIX(DEFAULT_MARGIN_RIGHT_MM);
settings->margins[MARGINRIGHT] = settings->margins[MARGINRIGHT] = nscss_len2px(
nscss_len2px(length, unit, NULL); &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_TOP_MM); length = INTTOFIX(DEFAULT_MARGIN_TOP_MM);
settings->margins[MARGINTOP] = settings->margins[MARGINTOP] = nscss_len2px(
nscss_len2px(length, unit, NULL); &len_ctx, length, unit, NULL);
length = INTTOFIX(DEFAULT_MARGIN_BOTTOM_MM); length = INTTOFIX(DEFAULT_MARGIN_BOTTOM_MM);
settings->margins[MARGINBOTTOM] = settings->margins[MARGINBOTTOM] = nscss_len2px(
nscss_len2px(length, unit, NULL); &len_ctx, length, unit, NULL);
break; break;
/* use settings from the Export options tab */ /* use settings from the Export options tab */
case PRINT_OPTIONS: case PRINT_OPTIONS:
@ -298,17 +303,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
settings->scale = (float)nsoption_int(export_scale) / 100; settings->scale = (float)nsoption_int(export_scale) / 100;
length = INTTOFIX(nsoption_int(margin_left)); length = INTTOFIX(nsoption_int(margin_left));
settings->margins[MARGINLEFT] = settings->margins[MARGINLEFT] = nscss_len2px(
nscss_len2px(length, unit, NULL); &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_right)); length = INTTOFIX(nsoption_int(margin_right));
settings->margins[MARGINRIGHT] = settings->margins[MARGINRIGHT] = nscss_len2px(
nscss_len2px(length, unit, NULL); &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_top)); length = INTTOFIX(nsoption_int(margin_top));
settings->margins[MARGINTOP] = settings->margins[MARGINTOP] = nscss_len2px(
nscss_len2px(length, unit, NULL); &len_ctx, length, unit, NULL);
length = INTTOFIX(nsoption_int(margin_bottom)); length = INTTOFIX(nsoption_int(margin_bottom));
settings->margins[MARGINBOTTOM] = settings->margins[MARGINBOTTOM] = nscss_len2px(
nscss_len2px(length, unit, NULL); &len_ctx, length, unit, NULL);
break; break;
default: default:
return NULL; return NULL;

View File

@ -70,18 +70,20 @@ struct selection_string {
typedef bool (*seln_traverse_handler)(const char *text, size_t length, typedef bool (*seln_traverse_handler)(const char *text, size_t length,
struct box *box, void *handle, const char *whitespace_text, struct box *box, const nscss_len_ctx *len_ctx, void *handle,
size_t whitespace_length); const char *whitespace_text, size_t whitespace_length);
static bool redraw_handler(const char *text, size_t length, struct box *box, static bool redraw_handler(const char *text, size_t length,
struct box *box, const nscss_len_ctx *len_ctx,
void *handle, const char *whitespace_text, void *handle, const char *whitespace_text,
size_t whitespace_length); size_t whitespace_length);
static void selection_redraw(struct selection *s, unsigned start_idx, static void selection_redraw(struct selection *s, unsigned start_idx,
unsigned end_idx); unsigned end_idx);
static bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx, static bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
unsigned *start_offset, unsigned *end_offset); unsigned *start_offset, unsigned *end_offset);
static bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx, static bool traverse_tree(struct box *box, const nscss_len_ctx *len_ctx,
unsigned start_idx, unsigned end_idx,
seln_traverse_handler handler, seln_traverse_handler handler,
void *handle, save_text_whitespace *before, bool *first, void *handle, save_text_whitespace *before, bool *first,
bool do_marker); bool do_marker);
@ -198,7 +200,10 @@ void selection_reinit(struct selection *s, struct box *root)
* \param root the root box for html document or NULL for text/plain * \param root the root box for html document or NULL for text/plain
*/ */
void selection_init(struct selection *s, struct box *root) void selection_init(
struct selection *s,
struct box *root,
const nscss_len_ctx *len_ctx)
{ {
if (s->defined) if (s->defined)
selection_clear(s, true); selection_clear(s, true);
@ -207,6 +212,13 @@ void selection_init(struct selection *s, struct box *root)
s->start_idx = 0; s->start_idx = 0;
s->end_idx = 0; s->end_idx = 0;
s->drag_state = DRAG_NONE; s->drag_state = DRAG_NONE;
if (len_ctx != NULL) {
s->len_ctx = *len_ctx;
} else {
s->len_ctx.vw = 0;
s->len_ctx.vh = 0;
s->len_ctx.root_style = NULL;
}
selection_reinit(s, root); selection_reinit(s, root);
} }
@ -442,6 +454,7 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
* for all boxes that lie (partially) within the given range * for all boxes that lie (partially) within the given range
* *
* \param box box subtree * \param box box subtree
* \param len_ctx Length conversion context.
* \param start_idx start of range within textual representation (bytes) * \param start_idx start of range within textual representation (bytes)
* \param end_idx end of range * \param end_idx end of range
* \param handler handler function to call * \param handler handler function to call
@ -452,7 +465,9 @@ bool selected_part(struct box *box, unsigned start_idx, unsigned end_idx,
* \return false iff traversal abandoned part-way through * \return false iff traversal abandoned part-way through
*/ */
bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx, bool traverse_tree(
struct box *box, const nscss_len_ctx *len_ctx,
unsigned start_idx, unsigned end_idx,
seln_traverse_handler handler, seln_traverse_handler handler,
void *handle, save_text_whitespace *before, bool *first, void *handle, save_text_whitespace *before, bool *first,
bool do_marker) bool do_marker)
@ -473,9 +488,9 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
if (box->list_marker) { if (box->list_marker) {
/* do the marker box before continuing with the rest of the /* do the marker box before continuing with the rest of the
* list element */ * list element */
if (!traverse_tree(box->list_marker, start_idx, end_idx, if (!traverse_tree(box->list_marker, len_ctx,
handler, handle, before, first, start_idx, end_idx, handler, handle,
true)) before, first, true))
return false; return false;
} }
@ -506,7 +521,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
&end_offset)) { &end_offset)) {
if (!handler(box->text + start_offset, min(box->length, if (!handler(box->text + start_offset, min(box->length,
end_offset) - start_offset, end_offset) - start_offset,
box, handle, whitespace_text, box, len_ctx, handle, whitespace_text,
whitespace_length)) whitespace_length))
return false; return false;
if (before) { if (before) {
@ -533,7 +548,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
* the tree */ * the tree */
struct box *next = child->next; struct box *next = child->next;
if (!traverse_tree(child, start_idx, end_idx, if (!traverse_tree(child, len_ctx, start_idx, end_idx,
handler, handle, before, first, false)) handler, handle, before, first, false))
return false; return false;
@ -568,14 +583,16 @@ static bool selection_traverse(struct selection *s,
if (s->root) { if (s->root) {
/* HTML */ /* HTML */
return traverse_tree(s->root, s->start_idx, s->end_idx, return traverse_tree(s->root, &s->len_ctx,
handler, handle, &before, &first, false); s->start_idx, s->end_idx,
handler, handle,
&before, &first, false);
} }
/* Text */ /* Text */
text = textplain_get_raw_data(s->c, s->start_idx, s->end_idx, &length); text = textplain_get_raw_data(s->c, s->start_idx, s->end_idx, &length);
if (text && !handler(text, length, NULL, handle, NULL, 0)) if (text && !handler(text, length, NULL, NULL, handle, NULL, 0))
return false; return false;
return true; return true;
@ -597,8 +614,8 @@ static bool selection_traverse(struct selection *s,
*/ */
bool redraw_handler(const char *text, size_t length, struct box *box, bool redraw_handler(const char *text, size_t length, struct box *box,
void *handle, const char *whitespace_text, const nscss_len_ctx *len_ctx, void *handle,
size_t whitespace_length) const char *whitespace_text, size_t whitespace_length)
{ {
if (box) { if (box) {
struct rdw_info *r = (struct rdw_info*)handle; struct rdw_info *r = (struct rdw_info*)handle;
@ -606,7 +623,7 @@ bool redraw_handler(const char *text, size_t length, struct box *box,
int x, y; int x, y;
plot_font_style_t fstyle; plot_font_style_t fstyle;
font_plot_style_from_css(box->style, &fstyle); font_plot_style_from_css(len_ctx, box->style, &fstyle);
/* \todo - it should be possible to reduce the redrawn area by /* \todo - it should be possible to reduce the redrawn area by
* considering the 'text', 'length' and 'space' parameters */ * considering the 'text', 'length' and 'space' parameters */
@ -652,7 +669,7 @@ void selection_redraw(struct selection *s, unsigned start_idx, unsigned end_idx)
rdw.inited = false; rdw.inited = false;
if (s->root) { if (s->root) {
if (!traverse_tree(s->root, start_idx, end_idx, if (!traverse_tree(s->root, &s->len_ctx, start_idx, end_idx,
redraw_handler, &rdw, redraw_handler, &rdw,
NULL, NULL, false)) NULL, NULL, false))
return; return;
@ -739,10 +756,11 @@ static bool selection_string_append(const char *text, size_t length, bool space,
/** /**
* Selection traversal routine for appending text to a string * Selection traversal routine for appending text to a string
* *
* \param text pointer to text being added, or NULL for newline * \param text pointer to text being added, or NULL for newline
* \param length length of text to be appended (bytes) * \param length length of text to be appended (bytes)
* \param box pointer to text box, or NULL if from textplain * \param box pointer to text box, or NULL if from textplain
* \param handle selection string to append to * \param len_ctx Length conversion context
* \param handle selection string to append to
* \param whitespace_text whitespace to place before text for formatting * \param whitespace_text whitespace to place before text for formatting
* may be NULL * may be NULL
* \param whitespace_length length of whitespace_text * \param whitespace_length length of whitespace_text
@ -750,7 +768,8 @@ static bool selection_string_append(const char *text, size_t length, bool space,
*/ */
static bool selection_copy_handler(const char *text, size_t length, static bool selection_copy_handler(const char *text, size_t length,
struct box *box, void *handle, const char *whitespace_text, struct box *box, const nscss_len_ctx *len_ctx,
void *handle, const char *whitespace_text,
size_t whitespace_length) size_t whitespace_length)
{ {
bool add_space = false; bool add_space = false;
@ -771,7 +790,7 @@ static bool selection_copy_handler(const char *text, size_t length,
if (box->style != NULL) { if (box->style != NULL) {
/* Override default font style */ /* Override default font style */
font_plot_style_from_css(box->style, &style); font_plot_style_from_css(len_ctx, box->style, &style);
pstyle = &style; pstyle = &style;
} else { } else {
/* If there's no style, there must be no text */ /* If there's no style, there must be no text */

View File

@ -25,6 +25,7 @@
#include <stdbool.h> #include <stdbool.h>
#include "netsurf/mouse.h" #include "netsurf/mouse.h"
#include "content/handlers/css/utils.h"
struct box; struct box;
@ -43,6 +44,7 @@ struct selection
{ {
struct content *c; struct content *c;
struct box *root; struct box *root;
nscss_len_ctx len_ctx;
unsigned max_idx; /* total bytes in text representation */ unsigned max_idx; /* total bytes in text representation */
@ -60,7 +62,10 @@ struct selection *selection_create(struct content *c, bool is_html);
void selection_prepare(struct selection *s, struct content *c, bool is_html); void selection_prepare(struct selection *s, struct content *c, bool is_html);
void selection_destroy(struct selection *s); void selection_destroy(struct selection *s);
void selection_init(struct selection *s, struct box *root); void selection_init(
struct selection *s,
struct box *root,
const nscss_len_ctx *len_ctx);
void selection_reinit(struct selection *s, struct box *root); void selection_reinit(struct selection *s, struct box *root);
/* struct box *selection_root(struct selection *s); */ /* struct box *selection_root(struct selection *s); */

View File

@ -1803,6 +1803,10 @@ static void textarea_setup_text_offsets(struct textarea *ta)
{ {
int text_y_offset, text_y_offset_baseline; int text_y_offset, text_y_offset_baseline;
ta->line_height = FIXTOINT(FMUL(FLTTOFIX(1.3), FDIV(FMUL(
nscss_screen_dpi, FDIV(INTTOFIX(ta->fstyle.size),
INTTOFIX(FONT_SIZE_SCALE))), F_72)));
text_y_offset = text_y_offset_baseline = ta->border_width; text_y_offset = text_y_offset_baseline = ta->border_width;
if (ta->flags & TEXTAREA_MULTILINE) { if (ta->flags & TEXTAREA_MULTILINE) {
/* Multiline textarea */ /* Multiline textarea */
@ -1822,6 +1826,27 @@ static void textarea_setup_text_offsets(struct textarea *ta)
} }
/**
* Set font styles up for a textarea.
*
* \param[in] ta Textarea to update.
* \param[in] fstyle Font style to set in textarea.
* \param[in] selected_text Textarea selected text colour.
* \param[in] selected_bg Textarea selection background colour.
*/
static void textarea_set_text_style(
struct textarea *ta,
const plot_font_style_t *fstyle,
colour selected_text,
colour selected_bg)
{
ta->fstyle = *fstyle;
ta->sel_fstyle = *fstyle;
ta->sel_fstyle.foreground = selected_text;
ta->sel_fstyle.background = selected_bg;
}
/* exported interface, documented in textarea.h */ /* exported interface, documented in textarea.h */
struct textarea *textarea_create(const textarea_flags flags, struct textarea *textarea_create(const textarea_flags flags,
@ -1861,11 +1886,10 @@ struct textarea *textarea_create(const textarea_flags flags,
ret->border_width = setup->border_width; ret->border_width = setup->border_width;
ret->border_col = setup->border_col; ret->border_col = setup->border_col;
ret->fstyle = setup->text; textarea_set_text_style(ret,
&setup->text,
ret->sel_fstyle = setup->text; setup->selected_text,
ret->sel_fstyle.foreground = setup->selected_text; setup->selected_bg);
ret->sel_fstyle.background = setup->selected_bg;
ret->scroll_x = 0; ret->scroll_x = 0;
ret->scroll_y = 0; ret->scroll_y = 0;
@ -3220,8 +3244,12 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height)
/* exported interface, documented in textarea.h */ /* exported interface, documented in textarea.h */
void textarea_set_layout(struct textarea *ta, int width, int height, void textarea_set_layout(
int top, int right, int bottom, int left) struct textarea *ta,
const plot_font_style_t *fstyle,
int width, int height,
int top, int right,
int bottom, int left)
{ {
struct rect r = {0, 0, 0, 0}; struct rect r = {0, 0, 0, 0};
@ -3232,6 +3260,10 @@ void textarea_set_layout(struct textarea *ta, int width, int height,
ta->pad_bottom = bottom + ((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH); ta->pad_bottom = bottom + ((ta->bar_x == NULL) ? 0 : SCROLLBAR_WIDTH);
ta->pad_left = left; ta->pad_left = left;
textarea_set_text_style(ta, fstyle,
ta->sel_fstyle.foreground,
ta->sel_fstyle.background);
textarea_setup_text_offsets(ta); textarea_setup_text_offsets(ta);
if (ta->flags & TEXTAREA_MULTILINE) { if (ta->flags & TEXTAREA_MULTILINE) {

View File

@ -329,8 +329,12 @@ void textarea_set_dimensions(struct textarea *ta, int width, int height);
* \param bottom the new bottom padding of the textarea * \param bottom the new bottom padding of the textarea
* \param left the new left padding of the textarea * \param left the new left padding of the textarea
*/ */
void textarea_set_layout(struct textarea *ta, int width, int height, void textarea_set_layout(
int top, int right, int bottom, int left); struct textarea *ta,
const plot_font_style_t *fstyle,
int width, int height,
int top, int right,
int bottom, int left);
/** /**

View File

@ -342,20 +342,27 @@ void box_bounds(struct box *box, struct rect *r)
/** /**
* Determine if a point lies within a box. * Determine if a point lies within a box.
* *
* \param box box to consider * \param[in] len_ctx CSS length conversion context to use.
* \param x coordinate relative to box * \param[in] box Box to consider
* \param y coordinate relative to box * \param[in] x Coordinate relative to box
* \param physically if function returning true, physically is set true if * \param[in] y Coordinate relative to box
* point is within the box's physical dimensions and false * \param[out] physically If function returning true, physically is set true
* if the point is not within the box's physical dimensions * iff point is within the box's physical dimensions and
* but is in the area defined by the box's descendants. * false if the point is not within the box's physical
* if function returning false, physically is undefined. * dimensions but is in the area defined by the box's
* descendants. If function returns false, physically
* is undefined.
* \return true if the point is within the box or a descendant box * \return true if the point is within the box or a descendant box
* *
* This is a helper function for box_at_point(). * This is a helper function for box_at_point().
*/ */
static bool box_contains_point(struct box *box, int x, int y, bool *physically) static bool box_contains_point(
const nscss_len_ctx *len_ctx,
const struct box *box,
int x,
int y,
bool *physically)
{ {
css_computed_clip_rect css_rect; css_computed_clip_rect css_rect;
@ -382,25 +389,25 @@ static bool box_contains_point(struct box *box, int x, int y, bool *physically)
/* Adjust rect to css clip region */ /* Adjust rect to css clip region */
if (css_rect.left_auto == false) { if (css_rect.left_auto == false) {
r.x0 += FIXTOINT(nscss_len2px( r.x0 += FIXTOINT(nscss_len2px(len_ctx,
css_rect.left, css_rect.lunit, css_rect.left, css_rect.lunit,
box->style)); box->style));
} }
if (css_rect.top_auto == false) { if (css_rect.top_auto == false) {
r.y0 += FIXTOINT(nscss_len2px( r.y0 += FIXTOINT(nscss_len2px(len_ctx,
css_rect.top, css_rect.tunit, css_rect.top, css_rect.tunit,
box->style)); box->style));
} }
if (css_rect.right_auto == false) { if (css_rect.right_auto == false) {
r.x1 = box->border[LEFT].width + r.x1 = box->border[LEFT].width +
FIXTOINT(nscss_len2px( FIXTOINT(nscss_len2px(len_ctx,
css_rect.right, css_rect.right,
css_rect.runit, css_rect.runit,
box->style)); box->style));
} }
if (css_rect.bottom_auto == false) { if (css_rect.bottom_auto == false) {
r.y1 = box->border[TOP].width + r.y1 = box->border[TOP].width +
FIXTOINT(nscss_len2px( FIXTOINT(nscss_len2px(len_ctx,
css_rect.bottom, css_rect.bottom,
css_rect.bunit, css_rect.bunit,
box->style)); box->style));
@ -659,6 +666,7 @@ skip_children:
/** /**
* Find the boxes at a point. * Find the boxes at a point.
* *
* \param len_ctx CSS length conversion context for document.
* \param box box to search children of * \param box box to search children of
* \param x point to find, in global document coordinates * \param x point to find, in global document coordinates
* \param y point to find, in global document coordinates * \param y point to find, in global document coordinates
@ -674,13 +682,14 @@ skip_children:
* struct box *box = top_of_document_to_search; * struct box *box = top_of_document_to_search;
* int box_x = 0, box_y = 0; * int box_x = 0, box_y = 0;
* *
* while ((box = box_at_point(box, x, y, &box_x, &box_y))) { * while ((box = box_at_point(len_ctx, box, x, y, &box_x, &box_y))) {
* // process box * // process box
* } * }
* \endcode * \endcode
*/ */
struct box *box_at_point(struct box *box, const int x, const int y, struct box *box_at_point(const nscss_len_ctx *len_ctx,
struct box *box, const int x, const int y,
int *box_x, int *box_y) int *box_x, int *box_y)
{ {
bool skip_children; bool skip_children;
@ -690,7 +699,7 @@ struct box *box_at_point(struct box *box, const int x, const int y,
skip_children = false; skip_children = false;
while ((box = box_next_xy(box, box_x, box_y, skip_children))) { while ((box = box_next_xy(box, box_x, box_y, skip_children))) {
if (box_contains_point(box, x - *box_x, y - *box_y, if (box_contains_point(len_ctx, box, x - *box_x, y - *box_y,
&physically)) { &physically)) {
*box_x -= scrollbar_get_offset(box->scroll_x); *box_x -= scrollbar_get_offset(box->scroll_x);
*box_y -= scrollbar_get_offset(box->scroll_y); *box_y -= scrollbar_get_offset(box->scroll_y);

View File

@ -91,6 +91,8 @@
#include <stdio.h> #include <stdio.h>
#include <libcss/libcss.h> #include <libcss/libcss.h>
#include "content/handlers/css/utils.h"
struct content; struct content;
struct box; struct box;
struct browser_window; struct browser_window;
@ -328,7 +330,9 @@ void box_free(struct box *box);
void box_free_box(struct box *box); void box_free_box(struct box *box);
void box_bounds(struct box *box, struct rect *r); void box_bounds(struct box *box, struct rect *r);
void box_coords(struct box *box, int *x, int *y); void box_coords(struct box *box, int *x, int *y);
struct box *box_at_point(struct box *box, const int x, const int y, struct box *box_at_point(
const nscss_len_ctx *len_ctx,
struct box *box, const int x, const int y,
int *box_x, int *box_y); int *box_x, int *box_y);
struct box *box_pick_text_box(struct html_content *html, struct box *box_pick_text_box(struct html_content *html,
int x, int y, int dir, int *dx, int *dy); int x, int y, int dir, int *dx, int *dy);

View File

@ -422,9 +422,6 @@ bool box_normalise_table(
free(col_info.spans); free(col_info.spans);
if (table_calculate_column_types(table) == false)
return false;
#ifdef BOX_NORMALISE_DEBUG #ifdef BOX_NORMALISE_DEBUG
NSLOG(netsurf, INFO, "table %p done", table); NSLOG(netsurf, INFO, "table %p done", table);
#endif #endif

View File

@ -239,7 +239,14 @@ bool box_textarea_create_textarea(html_content *html,
dom_exception err; dom_exception err;
textarea_setup ta_setup; textarea_setup ta_setup;
textarea_flags ta_flags; textarea_flags ta_flags;
plot_font_style_t fstyle; plot_font_style_t fstyle = {
.family = PLOT_FONT_FAMILY_SANS_SERIF,
.size = 10 * FONT_SIZE_SCALE,
.weight = 400,
.flags = FONTF_NONE,
.background = 0,
.foreground = 0,
};
bool read_only = false; bool read_only = false;
bool disabled = false; bool disabled = false;
struct form_control *gadget = box->gadget; struct form_control *gadget = box->gadget;
@ -307,8 +314,6 @@ bool box_textarea_create_textarea(html_content *html,
gadget->data.text.data.gadget = gadget; gadget->data.text.data.gadget = gadget;
font_plot_style_from_css(gadget->box->style, &fstyle);
/* Reset to correct values by layout */ /* Reset to correct values by layout */
ta_setup.width = 200; ta_setup.width = 200;
ta_setup.height = 20; ta_setup.height = 20;

View File

@ -131,8 +131,10 @@ static plot_font_flags_t plot_font_flags(enum css_font_style_e style,
} }
/* exported function documented in render/font_internal.h */ /* exported function documented in render/font.h */
void font_plot_style_from_css(const css_computed_style *css, void font_plot_style_from_css(
const nscss_len_ctx *len_ctx,
const css_computed_style *css,
plot_font_style_t *fstyle) plot_font_style_t *fstyle)
{ {
lwc_string **families; lwc_string **families;
@ -144,7 +146,7 @@ void font_plot_style_from_css(const css_computed_style *css,
css_computed_font_family(css, &families)); css_computed_font_family(css, &families));
css_computed_font_size(css, &length, &unit); css_computed_font_size(css, &length, &unit);
fstyle->size = FIXTOINT(FMUL(nscss_len2pt(length, unit), fstyle->size = FIXTOINT(FMUL(nscss_len2pt(len_ctx, length, unit),
INTTOFIX(FONT_SIZE_SCALE))); INTTOFIX(FONT_SIZE_SCALE)));
/* Clamp font size to configured minimum */ /* Clamp font size to configured minimum */

View File

@ -32,10 +32,13 @@ struct plot_font_style;
/** /**
* Populate a font style using data from a computed CSS style * Populate a font style using data from a computed CSS style
* *
* \param css Computed style to consider * \param len_ctx Length conversion context
* \param fstyle Font style to populate * \param css Computed style to consider
* \param fstyle Font style to populate
*/ */
void font_plot_style_from_css(const css_computed_style *css, void font_plot_style_from_css(
struct plot_font_style *fstyle); const nscss_len_ctx *len_ctx,
const css_computed_style *css,
struct plot_font_style *fstyle);
#endif #endif

View File

@ -1133,6 +1133,7 @@ bool form_open_select_menu(void *client_data,
plot_font_style_t fstyle; plot_font_style_t fstyle;
int total_height; int total_height;
struct form_select_menu *menu; struct form_select_menu *menu;
html_content *html = (html_content *)c;
/* if the menu is opened for the first time */ /* if the menu is opened for the first time */
@ -1153,7 +1154,7 @@ bool form_open_select_menu(void *client_data,
box->border[LEFT].width + box->border[LEFT].width +
box->padding[RIGHT] + box->padding[LEFT]; box->padding[RIGHT] + box->padding[LEFT];
font_plot_style_from_css(control->box->style, font_plot_style_from_css(&html->len_ctx, control->box->style,
&fstyle); &fstyle);
menu->f_size = fstyle.size; menu->f_size = fstyle.size;

View File

@ -1398,6 +1398,10 @@ static void html_reformat(struct content *c, int width, int height)
htmlc->reflowing = true; htmlc->reflowing = true;
htmlc->len_ctx.vw = width;
htmlc->len_ctx.vh = height;
htmlc->len_ctx.root_style = htmlc->layout->style;
layout_document(htmlc, width, height); layout_document(htmlc, width, height);
layout = htmlc->layout; layout = htmlc->layout;
@ -1647,7 +1651,7 @@ html_open(struct content *c,
html->drag_owner.no_owner = true; html->drag_owner.no_owner = true;
/* text selection */ /* text selection */
selection_init(&html->sel, html->layout); selection_init(&html->sel, html->layout, &html->len_ctx);
html->selection_type = HTML_SELECTION_NONE; html->selection_type = HTML_SELECTION_NONE;
html->selection_owner.none = true; html->selection_owner.none = true;
@ -1768,7 +1772,8 @@ html_get_contextual_content(struct content *c, int x, int y,
struct box *next; struct box *next;
int box_x = 0, box_y = 0; int box_x = 0, box_y = 0;
while ((next = box_at_point(box, x, y, &box_x, &box_y)) != NULL) { while ((next = box_at_point(&html->len_ctx, box, x, y,
&box_x, &box_y)) != NULL) {
box = next; box = next;
/* hidden boxes are ignored */ /* hidden boxes are ignored */
@ -1845,7 +1850,8 @@ html_scroll_at_point(struct content *c, int x, int y, int scrx, int scry)
/* TODO: invert order; visit deepest box first */ /* TODO: invert order; visit deepest box first */
while ((next = box_at_point(box, x, y, &box_x, &box_y)) != NULL) { while ((next = box_at_point(&html->len_ctx, box, x, y,
&box_x, &box_y)) != NULL) {
box = next; box = next;
if (box->style && css_computed_visibility(box->style) == if (box->style && css_computed_visibility(box->style) ==
@ -1987,7 +1993,8 @@ static bool html_drop_file_at_point(struct content *c, int x, int y, char *file)
int box_x = 0, box_y = 0; int box_x = 0, box_y = 0;
/* Scan box tree for boxes that can handle drop */ /* Scan box tree for boxes that can handle drop */
while ((next = box_at_point(box, x, y, &box_x, &box_y)) != NULL) { while ((next = box_at_point(&html->len_ctx, box, x, y,
&box_x, &box_y)) != NULL) {
box = next; box = next;
if (box->style && css_computed_visibility(box->style) == if (box->style && css_computed_visibility(box->style) ==

View File

@ -208,7 +208,7 @@ static size_t html_selection_drag_end(struct html_content *html,
if (box) { if (box) {
plot_font_style_t fstyle; plot_font_style_t fstyle;
font_plot_style_from_css(box->style, &fstyle); font_plot_style_from_css(&html->len_ctx, box->style, &fstyle);
guit->layout->position(&fstyle, box->text, box->length, guit->layout->position(&fstyle, box->text, box->length,
dx, &idx, &pixel_offset); dx, &idx, &pixel_offset);
@ -415,7 +415,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
size_t idx; size_t idx;
plot_font_style_t fstyle; plot_font_style_t fstyle;
font_plot_style_from_css(box->style, &fstyle); font_plot_style_from_css(&html->len_ctx,
box->style, &fstyle);
guit->layout->position(&fstyle, guit->layout->position(&fstyle,
box->text, box->length, box->text, box->length,
@ -649,7 +650,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
text_box = box; text_box = box;
text_box_x = box_x; text_box_x = box_x;
} }
} while ((box = box_at_point(box, x, y, &box_x, &box_y)) != NULL); } while ((box = box_at_point(&html->len_ctx, box, x, y,
&box_x, &box_y)) != NULL);
/* use of box_x, box_y, or content below this point is probably a /* use of box_x, box_y, or content below this point is probably a
* mistake; they will refer to the last box returned by box_at_point */ * mistake; they will refer to the last box returned by box_at_point */
@ -910,8 +912,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
int pixel_offset; int pixel_offset;
size_t idx; size_t idx;
font_plot_style_from_css(text_box->style, font_plot_style_from_css(&html->len_ctx,
&fstyle); text_box->style, &fstyle);
guit->layout->position(&fstyle, guit->layout->position(&fstyle,
text_box->text, text_box->text,

View File

@ -26,6 +26,7 @@
#include <libcss/libcss.h> #include <libcss/libcss.h>
#include "content/handlers/css/utils.h"
#include "content/content_protected.h" #include "content/content_protected.h"
#include "desktop/selection.h" #include "desktop/selection.h"
#include "render/html.h" #include "render/html.h"
@ -94,6 +95,9 @@ typedef struct html_content {
/** Base target */ /** Base target */
char *base_target; char *base_target;
/** CSS length conversion context for document. */
nscss_len_ctx len_ctx;
/** Content has been aborted in the LOADING state */ /** Content has been aborted in the LOADING state */
bool aborted; bool aborted;

View File

@ -227,7 +227,8 @@ html_object_callback(hlcache_handle *object,
if (hunit == CSS_UNIT_PCT) { if (hunit == CSS_UNIT_PCT) {
l = (width - w) * hpos / INTTOFIX(100); l = (width - w) * hpos / INTTOFIX(100);
} else { } else {
l = FIXTOINT(nscss_len2px(hpos, hunit, l = FIXTOINT(nscss_len2px(&c->len_ctx,
hpos, hunit,
box->style)); box->style));
} }
@ -235,7 +236,8 @@ html_object_callback(hlcache_handle *object,
if (vunit == CSS_UNIT_PCT) { if (vunit == CSS_UNIT_PCT) {
t = (height - h) * vpos / INTTOFIX(100); t = (height - h) * vpos / INTTOFIX(100);
} else { } else {
t = FIXTOINT(nscss_len2px(vpos, vunit, t = FIXTOINT(nscss_len2px(&c->len_ctx,
vpos, vunit,
box->style)); box->style));
} }

View File

@ -521,12 +521,14 @@ static bool html_redraw_radio(int x, int y, int width, int height,
* \param box box of input * \param box box of input
* \param scale scale for redraw * \param scale scale for redraw
* \param background_colour current background colour * \param background_colour current background colour
* \param len_ctx Length conversion context
* \param ctx current redraw context * \param ctx current redraw context
* \return true if successful, false otherwise * \return true if successful, false otherwise
*/ */
static 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, struct box *box, float scale, colour background_colour,
const nscss_len_ctx *len_ctx,
const struct redraw_context *ctx) const struct redraw_context *ctx)
{ {
int text_width; int text_width;
@ -535,7 +537,7 @@ static bool html_redraw_file(int x, int y, int width, int height,
plot_font_style_t fstyle; plot_font_style_t fstyle;
nserror res; nserror res;
font_plot_style_from_css(box->style, &fstyle); font_plot_style_from_css(len_ctx, box->style, &fstyle);
fstyle.background = background_colour; fstyle.background = background_colour;
if (box->gadget->value) { if (box->gadget->value) {
@ -578,13 +580,16 @@ static bool html_redraw_file(int x, int y, int width, int height,
* \param clip current clip rectangle * \param clip current clip rectangle
* \param background_colour current background colour * \param background_colour current background colour
* \param background box containing background details (usually \a box) * \param background box containing background details (usually \a box)
* \param ctx current redraw context * \param len_ctx Length conversion context
* \param ctx current redraw context
* \return true if successful, false otherwise * \return true if successful, false otherwise
*/ */
static 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, const struct rect *clip, colour *background_colour,
struct box *background, const struct redraw_context *ctx) struct box *background,
const nscss_len_ctx *len_ctx,
const struct redraw_context *ctx)
{ {
bool repeat_x = false; bool repeat_x = false;
bool repeat_y = false; bool repeat_y = false;
@ -660,7 +665,7 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale,
content_get_width(background->background)) * content_get_width(background->background)) *
scale * FIXTOFLT(hpos) / 100.; scale * FIXTOFLT(hpos) / 100.;
} else { } else {
x += (int) (FIXTOFLT(nscss_len2px(hpos, hunit, x += (int) (FIXTOFLT(nscss_len2px(len_ctx, hpos, hunit,
background->style)) * scale); background->style)) * scale);
} }
@ -669,7 +674,7 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale,
content_get_height(background->background)) * content_get_height(background->background)) *
scale * FIXTOFLT(vpos) / 100.; scale * FIXTOFLT(vpos) / 100.;
} else { } else {
y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit, y += (int) (FIXTOFLT(nscss_len2px(len_ctx, vpos, vunit,
background->style)) * scale); background->style)) * scale);
} }
} }
@ -802,13 +807,15 @@ static bool html_redraw_background(int x, int y, struct box *box, float scale,
* \param first true if this is the first rectangle associated with the inline * \param first true if this is the first rectangle associated with the inline
* \param last true if this is the last rectangle associated with the inline * \param last true if this is the last rectangle associated with the inline
* \param background_colour updated to current background colour if plotted * \param background_colour updated to current background colour if plotted
* \param ctx current redraw context * \param len_ctx Length conversion context
* \param ctx current redraw context
* \return true if successful, false otherwise * \return true if successful, false otherwise
*/ */
static bool html_redraw_inline_background(int x, int y, struct box *box, static bool html_redraw_inline_background(int x, int y, struct box *box,
float scale, const struct rect *clip, struct rect b, float scale, const struct rect *clip, struct rect b,
bool first, bool last, colour *background_colour, bool first, bool last, colour *background_colour,
const nscss_len_ctx *len_ctx,
const struct redraw_context *ctx) const struct redraw_context *ctx)
{ {
struct rect r = *clip; struct rect r = *clip;
@ -869,7 +876,7 @@ static bool html_redraw_inline_background(int x, int y, struct box *box,
plot_content = false; plot_content = false;
} }
} else { } else {
x += (int) (FIXTOFLT(nscss_len2px(hpos, hunit, x += (int) (FIXTOFLT(nscss_len2px(len_ctx, hpos, hunit,
box->style)) * scale); box->style)) * scale);
} }
@ -878,7 +885,7 @@ static bool html_redraw_inline_background(int x, int y, struct box *box,
content_get_height(box->background) * content_get_height(box->background) *
scale) * FIXTOFLT(vpos) / 100.; scale) * FIXTOFLT(vpos) / 100.;
} else { } else {
y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit, y += (int) (FIXTOFLT(nscss_len2px(len_ctx, vpos, vunit,
box->style)) * scale); box->style)) * scale);
} }
} }
@ -1120,7 +1127,7 @@ static bool html_redraw_text_box(const html_content *html, struct box *box,
bool excluded = (box->object != NULL); bool excluded = (box->object != NULL);
plot_font_style_t fstyle; plot_font_style_t fstyle;
font_plot_style_from_css(box->style, &fstyle); font_plot_style_from_css(&html->len_ctx, box->style, &fstyle);
fstyle.background = current_background_color; fstyle.background = current_background_color;
if (!text_redraw(box->text, box->length, box->byte_offset, if (!text_redraw(box->text, box->length, box->byte_offset,
@ -1382,21 +1389,25 @@ bool html_redraw_box(const html_content *html, struct box *box,
/* We have an absolutly positioned box with a clip rect */ /* We have an absolutly positioned box with a clip rect */
if (css_rect.left_auto == false) if (css_rect.left_auto == false)
r.x0 = x - border_left + FIXTOINT(nscss_len2px( r.x0 = x - border_left + FIXTOINT(nscss_len2px(
&html->len_ctx,
css_rect.left, css_rect.lunit, css_rect.left, css_rect.lunit,
box->style)); box->style));
if (css_rect.top_auto == false) if (css_rect.top_auto == false)
r.y0 = y - border_top + FIXTOINT(nscss_len2px( r.y0 = y - border_top + FIXTOINT(nscss_len2px(
&html->len_ctx,
css_rect.top, css_rect.tunit, css_rect.top, css_rect.tunit,
box->style)); box->style));
if (css_rect.right_auto == false) if (css_rect.right_auto == false)
r.x1 = x - border_left + FIXTOINT(nscss_len2px( r.x1 = x - border_left + FIXTOINT(nscss_len2px(
&html->len_ctx,
css_rect.right, css_rect.runit, css_rect.right, css_rect.runit,
box->style)); box->style));
if (css_rect.bottom_auto == false) if (css_rect.bottom_auto == false)
r.y1 = y - border_top + FIXTOINT(nscss_len2px( r.y1 = y - border_top + FIXTOINT(nscss_len2px(
&html->len_ctx,
css_rect.bottom, css_rect.bunit, css_rect.bottom, css_rect.bunit,
box->style)); box->style));
@ -1486,7 +1497,8 @@ bool html_redraw_box(const html_content *html, struct box *box,
if ((p.x0 < p.x1) && (p.y0 < p.y1)) { if ((p.x0 < p.x1) && (p.y0 < p.y1)) {
/* plot background */ /* plot background */
if (!html_redraw_background(x, y, box, scale, &p, if (!html_redraw_background(x, y, box, scale, &p,
&current_background_color, bg_box, ctx)) &current_background_color, bg_box,
&html->len_ctx, ctx))
return false; return false;
/* restore previous graphics window */ /* restore previous graphics window */
if (ctx->plot->clip(ctx, &r) != NSERROR_OK) if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
@ -1565,7 +1577,8 @@ bool html_redraw_box(const html_content *html, struct box *box,
if (!html_redraw_inline_background( if (!html_redraw_inline_background(
x, y, box, scale, &p, b, x, y, box, scale, &p, b,
first, false, first, false,
&current_background_color, ctx)) &current_background_color,
&html->len_ctx, ctx))
return false; return false;
/* restore previous graphics window */ /* restore previous graphics window */
if (ctx->plot->clip(ctx, &r) != NSERROR_OK) if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
@ -1597,7 +1610,8 @@ bool html_redraw_box(const html_content *html, struct box *box,
/* plot background and borders for last rectangle of /* plot background and borders for last rectangle of
* the inline */ * the inline */
if (!html_redraw_inline_background(x, ib_y, box, scale, &p, b, if (!html_redraw_inline_background(x, ib_y, box, scale, &p, b,
first, true, &current_background_color, ctx)) first, true, &current_background_color,
&html->len_ctx, ctx))
return false; return false;
/* restore previous graphics window */ /* restore previous graphics window */
if (ctx->plot->clip(ctx, &r) != NSERROR_OK) if (ctx->plot->clip(ctx, &r) != NSERROR_OK)
@ -1768,7 +1782,6 @@ bool html_redraw_box(const html_content *html, struct box *box,
obj, sizeof(obj) - 1) != NSERROR_OK) obj, sizeof(obj) - 1) != NSERROR_OK)
return false; return false;
} }
} else if (box->iframe) { } else if (box->iframe) {
/* Offset is passed to browser window redraw unscaled */ /* Offset is passed to browser window redraw unscaled */
@ -1789,7 +1802,7 @@ bool html_redraw_box(const html_content *html, struct box *box,
} else if (box->gadget && box->gadget->type == GADGET_FILE) { } else if (box->gadget && box->gadget->type == GADGET_FILE) {
if (!html_redraw_file(x + padding_left, y + padding_top, if (!html_redraw_file(x + padding_left, y + padding_top,
width, height, box, scale, width, height, box, scale,
current_background_color, ctx)) current_background_color, &html->len_ctx, ctx))
return false; return false;
} else if (box->gadget && } else if (box->gadget &&

File diff suppressed because it is too large Load Diff

View File

@ -621,13 +621,14 @@ void search_show_all(bool all, struct search_context *context)
if (!a->sel) if (!a->sel)
continue; continue;
selection_init(a->sel, html->layout); selection_init(a->sel, html->layout,
&html->len_ctx);
} else { } else {
a->sel = selection_create(context->c, false); a->sel = selection_create(context->c, false);
if (!a->sel) if (!a->sel)
continue; continue;
selection_init(a->sel, NULL); selection_init(a->sel, NULL, NULL);
} }
selection_set_start(a->sel, a->start_idx); selection_set_start(a->sel, a->start_idx);

View File

@ -45,31 +45,57 @@ struct border {
css_unit unit; /**< border-width units */ css_unit unit; /**< border-width units */
}; };
static void table_used_left_border_for_cell(struct box *cell); static void table_used_left_border_for_cell(
static void table_used_top_border_for_cell(struct box *cell); const nscss_len_ctx *len_ctx,
static void table_used_right_border_for_cell(struct box *cell); struct box *cell);
static void table_used_bottom_border_for_cell(struct box *cell); static void table_used_top_border_for_cell(
static bool table_border_is_more_eyecatching(const struct border *a, const nscss_len_ctx *len_ctx,
box_type a_src, const struct border *b, box_type b_src); struct box *cell);
static void table_cell_top_process_table(struct box *table, struct border *a, static void table_used_right_border_for_cell(
const nscss_len_ctx *len_ctx,
struct box *cell);
static void table_used_bottom_border_for_cell(
const nscss_len_ctx *len_ctx,
struct box *cell);
static bool table_border_is_more_eyecatching(
const nscss_len_ctx *len_ctx,
const struct border *a,
box_type a_src,
const struct border *b,
box_type b_src);
static void table_cell_top_process_table(
const nscss_len_ctx *len_ctx,
struct box *table,
struct border *a,
box_type *a_src);
static bool table_cell_top_process_group(
const nscss_len_ctx *len_ctx,
struct box *cell,
struct box *group,
struct border *a,
box_type *a_src);
static bool table_cell_top_process_row(
const nscss_len_ctx *len_ctx,
struct box *cell,
struct box *row,
struct border *a,
box_type *a_src); box_type *a_src);
static bool table_cell_top_process_group(struct box *cell, struct box *group,
struct border *a, box_type *a_src);
static bool table_cell_top_process_row(struct box *cell, struct box *row,
struct border *a, box_type *a_src);
/** /**
* Determine the column width types for a table. * Determine the column width types for a table.
* *
* \param table box of type BOX_TABLE * \param len_ctx Length conversion context
* \param table box of type BOX_TABLE
* \return true on success, false on memory exhaustion * \return true on success, false on memory exhaustion
* *
* The table->col array is allocated and type and width are filled in for each * The table->col array is allocated and type and width are filled in for each
* column. * column.
*/ */
bool table_calculate_column_types(struct box *table) bool table_calculate_column_types(
const nscss_len_ctx *len_ctx,
struct box *table)
{ {
unsigned int i, j; unsigned int i, j;
struct column *col; struct column *col;
@ -109,7 +135,7 @@ bool table_calculate_column_types(struct box *table)
css_computed_position(cell->style) != css_computed_position(cell->style) !=
CSS_POSITION_FIXED) { CSS_POSITION_FIXED) {
col[i].positioned = false; col[i].positioned = false;
} }
type = css_computed_width(cell->style, &value, &unit); type = css_computed_width(cell->style, &value, &unit);
@ -117,8 +143,8 @@ bool table_calculate_column_types(struct box *table)
if (col[i].type != COLUMN_WIDTH_FIXED && if (col[i].type != COLUMN_WIDTH_FIXED &&
type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT) { type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT) {
col[i].type = COLUMN_WIDTH_FIXED; col[i].type = COLUMN_WIDTH_FIXED;
col[i].width = FIXTOINT(nscss_len2px(value, unit, col[i].width = FIXTOINT(nscss_len2px(len_ctx,
cell->style)); value, unit, cell->style));
if (col[i].width < 0) if (col[i].width < 0)
col[i].width = 0; col[i].width = 0;
continue; continue;
@ -181,7 +207,7 @@ bool table_calculate_column_types(struct box *table)
if (type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT && if (type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT &&
fixed_columns + unknown_columns == fixed_columns + unknown_columns ==
cell->columns) { cell->columns) {
int width = (FIXTOFLT(nscss_len2px(value, unit, int width = (FIXTOFLT(nscss_len2px(len_ctx, value, unit,
cell->style)) - fixed_width) / cell->style)) - fixed_width) /
unknown_columns; unknown_columns;
if (width < 0) if (width < 0)
@ -235,11 +261,14 @@ bool table_calculate_column_types(struct box *table)
/** /**
* Calculate used values of border-{trbl}-{style,color,width} for table cells. * Calculate used values of border-{trbl}-{style,color,width} for table cells.
* *
* \param cell Table cell to consider * \param len_ctx Length conversion context
* \param cell Table cell to consider
* *
* \post \a cell's border array is populated * \post \a cell's border array is populated
*/ */
void table_used_border_for_cell(struct box *cell) void table_used_border_for_cell(
const nscss_len_ctx *len_ctx,
struct box *cell)
{ {
int side; int side;
@ -257,7 +286,8 @@ void table_used_border_for_cell(struct box *cell)
&cell->border[LEFT].c); &cell->border[LEFT].c);
css_computed_border_left_width(cell->style, &width, &unit); css_computed_border_left_width(cell->style, &width, &unit);
cell->border[LEFT].width = cell->border[LEFT].width =
FIXTOINT(nscss_len2px(width, unit, cell->style)); FIXTOINT(nscss_len2px(len_ctx,
width, unit, cell->style));
/* Top border */ /* Top border */
cell->border[TOP].style = cell->border[TOP].style =
@ -266,7 +296,8 @@ void table_used_border_for_cell(struct box *cell)
&cell->border[TOP].c); &cell->border[TOP].c);
css_computed_border_top_width(cell->style, &width, &unit); css_computed_border_top_width(cell->style, &width, &unit);
cell->border[TOP].width = cell->border[TOP].width =
FIXTOINT(nscss_len2px(width, unit, cell->style)); FIXTOINT(nscss_len2px(len_ctx,
width, unit, cell->style));
/* Right border */ /* Right border */
cell->border[RIGHT].style = cell->border[RIGHT].style =
@ -275,7 +306,8 @@ void table_used_border_for_cell(struct box *cell)
&cell->border[RIGHT].c); &cell->border[RIGHT].c);
css_computed_border_right_width(cell->style, &width, &unit); css_computed_border_right_width(cell->style, &width, &unit);
cell->border[RIGHT].width = cell->border[RIGHT].width =
FIXTOINT(nscss_len2px(width, unit, cell->style)); FIXTOINT(nscss_len2px(len_ctx,
width, unit, cell->style));
/* Bottom border */ /* Bottom border */
cell->border[BOTTOM].style = cell->border[BOTTOM].style =
@ -284,19 +316,20 @@ void table_used_border_for_cell(struct box *cell)
&cell->border[BOTTOM].c); &cell->border[BOTTOM].c);
css_computed_border_bottom_width(cell->style, &width, &unit); css_computed_border_bottom_width(cell->style, &width, &unit);
cell->border[BOTTOM].width = cell->border[BOTTOM].width =
FIXTOINT(nscss_len2px(width, unit, cell->style)); FIXTOINT(nscss_len2px(len_ctx,
width, unit, cell->style));
} else { } else {
/* Left border */ /* Left border */
table_used_left_border_for_cell(cell); table_used_left_border_for_cell(len_ctx, cell);
/* Top border */ /* Top border */
table_used_top_border_for_cell(cell); table_used_top_border_for_cell(len_ctx, cell);
/* Right border */ /* Right border */
table_used_right_border_for_cell(cell); table_used_right_border_for_cell(len_ctx, cell);
/* Bottom border */ /* Bottom border */
table_used_bottom_border_for_cell(cell); table_used_bottom_border_for_cell(len_ctx, cell);
} }
/* Finally, ensure that any borders configured as /* Finally, ensure that any borders configured as
@ -316,9 +349,12 @@ void table_used_border_for_cell(struct box *cell)
/** /**
* Calculate used values of border-left-{style,color,width} * Calculate used values of border-left-{style,color,width}
* *
* \param cell Table cell to consider * \param len_ctx Length conversion context
* \param cell Table cell to consider
*/ */
void table_used_left_border_for_cell(struct box *cell) void table_used_left_border_for_cell(
const nscss_len_ctx *len_ctx,
struct box *cell)
{ {
struct border a, b; struct border a, b;
box_type a_src, b_src; box_type a_src, b_src;
@ -329,7 +365,7 @@ void table_used_left_border_for_cell(struct box *cell)
a.style = css_computed_border_left_style(cell->style); a.style = css_computed_border_left_style(cell->style);
a.color = css_computed_border_left_color(cell->style, &a.c); a.color = css_computed_border_left_color(cell->style, &a.c);
css_computed_border_left_width(cell->style, &a.width, &a.unit); css_computed_border_left_width(cell->style, &a.width, &a.unit);
a.width = nscss_len2px(a.width, a.unit, cell->style); a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style);
a.unit = CSS_UNIT_PX; a.unit = CSS_UNIT_PX;
a_src = BOX_TABLE_CELL; a_src = BOX_TABLE_CELL;
@ -362,11 +398,12 @@ void table_used_left_border_for_cell(struct box *cell)
b.style = css_computed_border_right_style(prev->style); b.style = css_computed_border_right_style(prev->style);
b.color = css_computed_border_right_color(prev->style, &b.c); b.color = css_computed_border_right_color(prev->style, &b.c);
css_computed_border_right_width(prev->style, &b.width, &b.unit); css_computed_border_right_width(prev->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, prev->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, prev->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_CELL; b_src = BOX_TABLE_CELL;
if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
&a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
@ -384,12 +421,13 @@ void table_used_left_border_for_cell(struct box *cell)
row->style, &b.c); row->style, &b.c);
css_computed_border_left_width( css_computed_border_left_width(
row->style, &b.width, &b.unit); row->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, row->style); b.width = nscss_len2px(len_ctx,
b.width, b.unit, row->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW; b_src = BOX_TABLE_ROW;
if (table_border_is_more_eyecatching(&a, a_src, if (table_border_is_more_eyecatching(len_ctx,
&b, b_src)) { &a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
@ -403,11 +441,12 @@ void table_used_left_border_for_cell(struct box *cell)
b.style = css_computed_border_left_style(group->style); b.style = css_computed_border_left_style(group->style);
b.color = css_computed_border_left_color(group->style, &b.c); b.color = css_computed_border_left_color(group->style, &b.c);
css_computed_border_left_width(group->style, &b.width, &b.unit); css_computed_border_left_width(group->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, group->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW_GROUP; b_src = BOX_TABLE_ROW_GROUP;
if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
&a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
@ -416,11 +455,12 @@ void table_used_left_border_for_cell(struct box *cell)
b.style = css_computed_border_left_style(table->style); b.style = css_computed_border_left_style(table->style);
b.color = css_computed_border_left_color(table->style, &b.c); b.color = css_computed_border_left_color(table->style, &b.c);
css_computed_border_left_width(table->style, &b.width, &b.unit); css_computed_border_left_width(table->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, table->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE; b_src = BOX_TABLE;
if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
&a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
@ -429,16 +469,19 @@ void table_used_left_border_for_cell(struct box *cell)
/* a now contains the used left border for the cell */ /* a now contains the used left border for the cell */
cell->border[LEFT].style = a.style; cell->border[LEFT].style = a.style;
cell->border[LEFT].c = a.c; cell->border[LEFT].c = a.c;
cell->border[LEFT].width = cell->border[LEFT].width = FIXTOINT(nscss_len2px(len_ctx,
FIXTOINT(nscss_len2px(a.width, a.unit, cell->style)); a.width, a.unit, cell->style));
} }
/** /**
* Calculate used values of border-top-{style,color,width} * Calculate used values of border-top-{style,color,width}
* *
* \param cell Table cell to consider * \param len_ctx Length conversion context
* \param cell Table cell to consider
*/ */
void table_used_top_border_for_cell(struct box *cell) void table_used_top_border_for_cell(
const nscss_len_ctx *len_ctx,
struct box *cell)
{ {
struct border a, b; struct border a, b;
box_type a_src, b_src; box_type a_src, b_src;
@ -449,7 +492,7 @@ void table_used_top_border_for_cell(struct box *cell)
a.style = css_computed_border_top_style(cell->style); a.style = css_computed_border_top_style(cell->style);
css_computed_border_top_color(cell->style, &a.c); css_computed_border_top_color(cell->style, &a.c);
css_computed_border_top_width(cell->style, &a.width, &a.unit); css_computed_border_top_width(cell->style, &a.width, &a.unit);
a.width = nscss_len2px(a.width, a.unit, cell->style); a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style);
a.unit = CSS_UNIT_PX; a.unit = CSS_UNIT_PX;
a_src = BOX_TABLE_CELL; a_src = BOX_TABLE_CELL;
@ -457,18 +500,18 @@ void table_used_top_border_for_cell(struct box *cell)
b.style = css_computed_border_top_style(row->style); b.style = css_computed_border_top_style(row->style);
css_computed_border_top_color(row->style, &b.c); css_computed_border_top_color(row->style, &b.c);
css_computed_border_top_width(row->style, &b.width, &b.unit); css_computed_border_top_width(row->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, row->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW; b_src = BOX_TABLE_ROW;
if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx, &a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
if (row->prev != NULL) { if (row->prev != NULL) {
/* Consider row(s) above */ /* Consider row(s) above */
while (table_cell_top_process_row(cell, row->prev, while (table_cell_top_process_row(len_ctx, cell, row->prev,
&a, &a_src) == false) { &a, &a_src) == false) {
if (row->prev->prev == NULL) { if (row->prev->prev == NULL) {
/* Consider row group */ /* Consider row group */
@ -489,26 +532,29 @@ void table_used_top_border_for_cell(struct box *cell)
b.style = css_computed_border_top_style(group->style); b.style = css_computed_border_top_style(group->style);
b.color = css_computed_border_top_color(group->style, &b.c); b.color = css_computed_border_top_color(group->style, &b.c);
css_computed_border_top_width(group->style, &b.width, &b.unit); css_computed_border_top_width(group->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, group->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW_GROUP; b_src = BOX_TABLE_ROW_GROUP;
if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
&a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
if (group->prev == NULL) { if (group->prev == NULL) {
/* Top border of table */ /* Top border of table */
table_cell_top_process_table(group->parent, &a, &a_src); table_cell_top_process_table(len_ctx,
group->parent, &a, &a_src);
} else { } else {
/* Process previous group(s) */ /* Process previous group(s) */
while (table_cell_top_process_group(cell, group->prev, while (table_cell_top_process_group(len_ctx,
cell, group->prev,
&a, &a_src) == false) { &a, &a_src) == false) {
if (group->prev->prev == NULL) { if (group->prev->prev == NULL) {
/* Top border of table */ /* Top border of table */
table_cell_top_process_table( table_cell_top_process_table(len_ctx,
group->parent, group->parent,
&a, &a_src); &a, &a_src);
break; break;
} else { } else {
@ -521,16 +567,19 @@ void table_used_top_border_for_cell(struct box *cell)
/* a now contains the used top border for the cell */ /* a now contains the used top border for the cell */
cell->border[TOP].style = a.style; cell->border[TOP].style = a.style;
cell->border[TOP].c = a.c; cell->border[TOP].c = a.c;
cell->border[TOP].width = cell->border[TOP].width = FIXTOINT(nscss_len2px(len_ctx,
FIXTOINT(nscss_len2px(a.width, a.unit, cell->style)); a.width, a.unit, cell->style));
} }
/** /**
* Calculate used values of border-right-{style,color,width} * Calculate used values of border-right-{style,color,width}
* *
* \param cell Table cell to consider * \param len_ctx Length conversion context
* \param cell Table cell to consider
*/ */
void table_used_right_border_for_cell(struct box *cell) void table_used_right_border_for_cell(
const nscss_len_ctx *len_ctx,
struct box *cell)
{ {
struct border a, b; struct border a, b;
box_type a_src, b_src; box_type a_src, b_src;
@ -541,7 +590,7 @@ void table_used_right_border_for_cell(struct box *cell)
a.style = css_computed_border_right_style(cell->style); a.style = css_computed_border_right_style(cell->style);
css_computed_border_right_color(cell->style, &a.c); css_computed_border_right_color(cell->style, &a.c);
css_computed_border_right_width(cell->style, &a.width, &a.unit); css_computed_border_right_width(cell->style, &a.width, &a.unit);
a.width = nscss_len2px(a.width, a.unit, cell->style); a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style);
a.unit = CSS_UNIT_PX; a.unit = CSS_UNIT_PX;
a_src = BOX_TABLE_CELL; a_src = BOX_TABLE_CELL;
@ -565,12 +614,13 @@ void table_used_right_border_for_cell(struct box *cell)
row->style, &b.c); row->style, &b.c);
css_computed_border_right_width( css_computed_border_right_width(
row->style, &b.width, &b.unit); row->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, row->style); b.width = nscss_len2px(len_ctx,
b.width, b.unit, row->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW; b_src = BOX_TABLE_ROW;
if (table_border_is_more_eyecatching(&a, a_src, if (table_border_is_more_eyecatching(len_ctx,
&b, b_src)) { &a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
@ -583,13 +633,14 @@ void table_used_right_border_for_cell(struct box *cell)
/* Row group -- consider its right border */ /* Row group -- consider its right border */
b.style = css_computed_border_right_style(group->style); b.style = css_computed_border_right_style(group->style);
b.color = css_computed_border_right_color(group->style, &b.c); b.color = css_computed_border_right_color(group->style, &b.c);
css_computed_border_right_width(group->style, css_computed_border_right_width(group->style,
&b.width, &b.unit); &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, group->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW_GROUP; b_src = BOX_TABLE_ROW_GROUP;
if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
&a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
@ -599,11 +650,12 @@ void table_used_right_border_for_cell(struct box *cell)
b.color = css_computed_border_right_color(table->style, &b.c); b.color = css_computed_border_right_color(table->style, &b.c);
css_computed_border_right_width(table->style, css_computed_border_right_width(table->style,
&b.width, &b.unit); &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, table->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE; b_src = BOX_TABLE;
if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
&a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
@ -612,16 +664,19 @@ void table_used_right_border_for_cell(struct box *cell)
/* a now contains the used right border for the cell */ /* a now contains the used right border for the cell */
cell->border[RIGHT].style = a.style; cell->border[RIGHT].style = a.style;
cell->border[RIGHT].c = a.c; cell->border[RIGHT].c = a.c;
cell->border[RIGHT].width = cell->border[RIGHT].width = FIXTOINT(nscss_len2px(len_ctx,
FIXTOINT(nscss_len2px(a.width, a.unit, cell->style)); a.width, a.unit, cell->style));
} }
/** /**
* Calculate used values of border-bottom-{style,color,width} * Calculate used values of border-bottom-{style,color,width}
* *
* \param cell Table cell to consider * \param len_ctx Length conversion context
* \param cell Table cell to consider
*/ */
void table_used_bottom_border_for_cell(struct box *cell) void table_used_bottom_border_for_cell(
const nscss_len_ctx *len_ctx,
struct box *cell)
{ {
struct border a, b; struct border a, b;
box_type a_src, b_src; box_type a_src, b_src;
@ -632,7 +687,7 @@ void table_used_bottom_border_for_cell(struct box *cell)
a.style = css_computed_border_bottom_style(cell->style); a.style = css_computed_border_bottom_style(cell->style);
css_computed_border_bottom_color(cell->style, &a.c); css_computed_border_bottom_color(cell->style, &a.c);
css_computed_border_bottom_width(cell->style, &a.width, &a.unit); css_computed_border_bottom_width(cell->style, &a.width, &a.unit);
a.width = nscss_len2px(a.width, a.unit, cell->style); a.width = nscss_len2px(len_ctx, a.width, a.unit, cell->style);
a.unit = CSS_UNIT_PX; a.unit = CSS_UNIT_PX;
a_src = BOX_TABLE_CELL; a_src = BOX_TABLE_CELL;
@ -656,11 +711,12 @@ void table_used_bottom_border_for_cell(struct box *cell)
b.style = css_computed_border_bottom_style(row->style); b.style = css_computed_border_bottom_style(row->style);
b.color = css_computed_border_bottom_color(row->style, &b.c); b.color = css_computed_border_bottom_color(row->style, &b.c);
css_computed_border_bottom_width(row->style, &b.width, &b.unit); css_computed_border_bottom_width(row->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, row->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW; b_src = BOX_TABLE_ROW;
if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
&a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
@ -670,11 +726,12 @@ void table_used_bottom_border_for_cell(struct box *cell)
b.color = css_computed_border_bottom_color(group->style, &b.c); b.color = css_computed_border_bottom_color(group->style, &b.c);
css_computed_border_bottom_width(group->style, css_computed_border_bottom_width(group->style,
&b.width, &b.unit); &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, group->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW_GROUP; b_src = BOX_TABLE_ROW_GROUP;
if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
&a, a_src, &b, b_src)) {
a = b; a = b;
a_src = b_src; a_src = b_src;
} }
@ -684,11 +741,12 @@ void table_used_bottom_border_for_cell(struct box *cell)
b.color = css_computed_border_bottom_color(table->style, &b.c); b.color = css_computed_border_bottom_color(table->style, &b.c);
css_computed_border_bottom_width(table->style, css_computed_border_bottom_width(table->style,
&b.width, &b.unit); &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, table->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE; b_src = BOX_TABLE;
if (table_border_is_more_eyecatching(&a, a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
&a, a_src, &b, b_src)) {
a = b; a = b;
} }
} }
@ -696,21 +754,26 @@ void table_used_bottom_border_for_cell(struct box *cell)
/* a now contains the used bottom border for the cell */ /* a now contains the used bottom border for the cell */
cell->border[BOTTOM].style = a.style; cell->border[BOTTOM].style = a.style;
cell->border[BOTTOM].c = a.c; cell->border[BOTTOM].c = a.c;
cell->border[BOTTOM].width = cell->border[BOTTOM].width = FIXTOINT(nscss_len2px(len_ctx,
FIXTOINT(nscss_len2px(a.width, a.unit, cell->style)); a.width, a.unit, cell->style));
} }
/** /**
* Determine if a border style is more eyecatching than another * Determine if a border style is more eyecatching than another
* *
* \param a Reference border style * \param len_ctx Length conversion context
* \param a_src Source of \a a * \param a Reference border style
* \param b Candidate border style * \param a_src Source of \a a
* \param b_src Source of \a b * \param b Candidate border style
* \param b_src Source of \a b
* \return True if \a b is more eyecatching than \a a * \return True if \a b is more eyecatching than \a a
*/ */
bool table_border_is_more_eyecatching(const struct border *a, bool table_border_is_more_eyecatching(
box_type a_src, const struct border *b, box_type b_src) const nscss_len_ctx *len_ctx,
const struct border *a,
box_type a_src,
const struct border *b,
box_type b_src)
{ {
css_fixed awidth, bwidth; css_fixed awidth, bwidth;
int impact = 0; int impact = 0;
@ -731,8 +794,8 @@ bool table_border_is_more_eyecatching(const struct border *a,
* if they've come from a computed style. */ * if they've come from a computed style. */
assert(a->unit != CSS_UNIT_EM && a->unit != CSS_UNIT_EX); assert(a->unit != CSS_UNIT_EM && a->unit != CSS_UNIT_EX);
assert(b->unit != CSS_UNIT_EM && b->unit != CSS_UNIT_EX); assert(b->unit != CSS_UNIT_EM && b->unit != CSS_UNIT_EX);
awidth = nscss_len2px(a->width, a->unit, NULL); awidth = nscss_len2px(len_ctx, a->width, a->unit, NULL);
bwidth = nscss_len2px(b->width, b->unit, NULL); bwidth = nscss_len2px(len_ctx, b->width, b->unit, NULL);
if (awidth < bwidth) if (awidth < bwidth)
return true; return true;
@ -811,14 +874,18 @@ bool table_border_is_more_eyecatching(const struct border *a,
/** /**
* Process a table * Process a table
* *
* \param table Table to process * \param len_ctx Length conversion context
* \param a Current border style for cell * \param table Table to process
* \param a_src Source of \a a * \param a Current border style for cell
* \param a_src Source of \a a
* *
* \post \a a will be updated with most eyecatching style * \post \a a will be updated with most eyecatching style
* \post \a a_src will be updated also * \post \a a_src will be updated also
*/ */
void table_cell_top_process_table(struct box *table, struct border *a, void table_cell_top_process_table(
const nscss_len_ctx *len_ctx,
struct box *table,
struct border *a,
box_type *a_src) box_type *a_src)
{ {
struct border b; struct border b;
@ -828,11 +895,11 @@ void table_cell_top_process_table(struct box *table, struct border *a,
b.style = css_computed_border_top_style(table->style); b.style = css_computed_border_top_style(table->style);
b.color = css_computed_border_top_color(table->style, &b.c); b.color = css_computed_border_top_color(table->style, &b.c);
css_computed_border_top_width(table->style, &b.width, &b.unit); css_computed_border_top_width(table->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, table->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, table->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE; b_src = BOX_TABLE;
if (table_border_is_more_eyecatching(a, *a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx, a, *a_src, &b, b_src)) {
*a = b; *a = b;
*a_src = b_src; *a_src = b_src;
} }
@ -841,17 +908,22 @@ void table_cell_top_process_table(struct box *table, struct border *a,
/** /**
* Process a group * Process a group
* *
* \param cell Cell being considered * \param len_ctx Length conversion context
* \param group Group to process * \param cell Cell being considered
* \param a Current border style for cell * \param group Group to process
* \param a_src Source of \a a * \param a Current border style for cell
* \param a_src Source of \a a
* \return true if group has non-empty rows, false otherwise * \return true if group has non-empty rows, false otherwise
* *
* \post \a a will be updated with most eyecatching style * \post \a a will be updated with most eyecatching style
* \post \a a_src will be updated also * \post \a a_src will be updated also
*/ */
bool table_cell_top_process_group(struct box *cell, struct box *group, bool table_cell_top_process_group(
struct border *a, box_type *a_src) const nscss_len_ctx *len_ctx,
struct box *cell,
struct box *group,
struct border *a,
box_type *a_src)
{ {
struct border b; struct border b;
box_type b_src; box_type b_src;
@ -860,11 +932,11 @@ bool table_cell_top_process_group(struct box *cell, struct box *group,
b.style = css_computed_border_bottom_style(group->style); b.style = css_computed_border_bottom_style(group->style);
b.color = css_computed_border_bottom_color(group->style, &b.c); b.color = css_computed_border_bottom_color(group->style, &b.c);
css_computed_border_bottom_width(group->style, &b.width, &b.unit); css_computed_border_bottom_width(group->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, group->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW_GROUP; b_src = BOX_TABLE_ROW_GROUP;
if (table_border_is_more_eyecatching(a, *a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx, a, *a_src, &b, b_src)) {
*a = b; *a = b;
*a_src = b_src; *a_src = b_src;
} }
@ -873,7 +945,7 @@ bool table_cell_top_process_group(struct box *cell, struct box *group,
/* Process rows in group, starting with last */ /* Process rows in group, starting with last */
struct box *row = group->last; struct box *row = group->last;
while (table_cell_top_process_row(cell, row, while (table_cell_top_process_row(len_ctx, cell, row,
a, a_src) == false) { a, a_src) == false) {
if (row->prev == NULL) { if (row->prev == NULL) {
return false; return false;
@ -886,11 +958,12 @@ bool table_cell_top_process_group(struct box *cell, struct box *group,
b.style = css_computed_border_top_style(group->style); b.style = css_computed_border_top_style(group->style);
b.color = css_computed_border_top_color(group->style, &b.c); b.color = css_computed_border_top_color(group->style, &b.c);
css_computed_border_top_width(group->style, &b.width, &b.unit); css_computed_border_top_width(group->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, group->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, group->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW_GROUP; b_src = BOX_TABLE_ROW_GROUP;
if (table_border_is_more_eyecatching(a, *a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
a, *a_src, &b, b_src)) {
*a = b; *a = b;
*a_src = b_src; *a_src = b_src;
} }
@ -904,17 +977,22 @@ bool table_cell_top_process_group(struct box *cell, struct box *group,
/** /**
* Process a row * Process a row
* *
* \param cell Cell being considered * \param len_ctx Length conversion context
* \param row Row to process * \param cell Cell being considered
* \param a Current border style for cell * \param row Row to process
* \param a_src Source of \a a * \param a Current border style for cell
* \param a_src Source of \a a
* \return true if row has cells, false otherwise * \return true if row has cells, false otherwise
* *
* \post \a a will be updated with most eyecatching style * \post \a a will be updated with most eyecatching style
* \post \a a_src will be updated also * \post \a a_src will be updated also
*/ */
bool table_cell_top_process_row(struct box *cell, struct box *row, bool table_cell_top_process_row(
struct border *a, box_type *a_src) const nscss_len_ctx *len_ctx,
struct box *cell,
struct box *row,
struct border *a,
box_type *a_src)
{ {
struct border b; struct border b;
box_type b_src; box_type b_src;
@ -923,11 +1001,11 @@ bool table_cell_top_process_row(struct box *cell, struct box *row,
b.style = css_computed_border_bottom_style(row->style); b.style = css_computed_border_bottom_style(row->style);
b.color = css_computed_border_bottom_color(row->style, &b.c); b.color = css_computed_border_bottom_color(row->style, &b.c);
css_computed_border_bottom_width(row->style, &b.width, &b.unit); css_computed_border_bottom_width(row->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, row->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW; b_src = BOX_TABLE_ROW;
if (table_border_is_more_eyecatching(a, *a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx, a, *a_src, &b, b_src)) {
*a = b; *a = b;
*a_src = b_src; *a_src = b_src;
} }
@ -937,11 +1015,12 @@ bool table_cell_top_process_row(struct box *cell, struct box *row,
b.style = css_computed_border_top_style(row->style); b.style = css_computed_border_top_style(row->style);
b.color = css_computed_border_top_color(row->style, &b.c); b.color = css_computed_border_top_color(row->style, &b.c);
css_computed_border_top_width(row->style, &b.width, &b.unit); css_computed_border_top_width(row->style, &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, row->style); b.width = nscss_len2px(len_ctx, b.width, b.unit, row->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_ROW; b_src = BOX_TABLE_ROW;
if (table_border_is_more_eyecatching(a, *a_src, &b, b_src)) { if (table_border_is_more_eyecatching(len_ctx,
a, *a_src, &b, b_src)) {
*a = b; *a = b;
*a_src = b_src; *a_src = b_src;
} }
@ -975,13 +1054,13 @@ bool table_cell_top_process_row(struct box *cell, struct box *row,
c->style, &b.c); c->style, &b.c);
css_computed_border_bottom_width(c->style, css_computed_border_bottom_width(c->style,
&b.width, &b.unit); &b.width, &b.unit);
b.width = nscss_len2px(b.width, b.unit, b.width = nscss_len2px(len_ctx,
c->style); b.width, b.unit, c->style);
b.unit = CSS_UNIT_PX; b.unit = CSS_UNIT_PX;
b_src = BOX_TABLE_CELL; b_src = BOX_TABLE_CELL;
if (table_border_is_more_eyecatching(a, *a_src, if (table_border_is_more_eyecatching(len_ctx,
&b, b_src)) { a, *a_src, &b, b_src)) {
*a = b; *a = b;
*a_src = b_src; *a_src = b_src;
} }

View File

@ -28,7 +28,11 @@
struct box; struct box;
bool table_calculate_column_types(struct box *table); bool table_calculate_column_types(
void table_used_border_for_cell(struct box *cell); const nscss_len_ctx *len_ctx,
struct box *table);
void table_used_border_for_cell(
const nscss_len_ctx *len_ctx,
struct box *cell);
#endif #endif

View File

@ -988,7 +988,7 @@ textplain_open(struct content *c,
text->bw = bw; text->bw = bw;
/* text selection */ /* text selection */
selection_init(&text->sel, NULL); selection_init(&text->sel, NULL, NULL);
} }