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:
parent
a67973f312
commit
6be6fa1b21
|
@ -27,11 +27,75 @@
|
|||
/** Screen DPI in fixed point units: defaults to 90, which RISC OS uses */
|
||||
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 */
|
||||
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 */
|
||||
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) {
|
||||
/* 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 */
|
||||
case CSS_UNIT_MM: return FMUL(length,
|
||||
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;
|
||||
/* 1pc = 12pt */
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* 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)
|
||||
{
|
||||
/* We assume the screen and any other output has the same dpi */
|
||||
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) {
|
||||
case CSS_UNIT_EM:
|
||||
case CSS_UNIT_EX:
|
||||
case CSS_UNIT_CAP:
|
||||
case CSS_UNIT_CH:
|
||||
case CSS_UNIT_IC:
|
||||
{
|
||||
css_fixed font_size = 0;
|
||||
css_unit font_unit = CSS_UNIT_PT;
|
||||
|
||||
assert(style != NULL);
|
||||
|
||||
css_computed_font_size(style, &font_size, &font_unit);
|
||||
|
||||
/* Convert to points */
|
||||
font_size = nscss_len2pt(font_size, font_unit);
|
||||
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)) {
|
||||
|
@ -85,9 +163,22 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
|
|||
* 1in = 72pt => 1pt = (DPI/72)px */
|
||||
px_per_unit = FDIV(FMUL(font_size, nscss_screen_dpi), F_72);
|
||||
|
||||
/* Scale ex units: we use a fixed ratio of 1ex = 0.6em */
|
||||
if (unit == CSS_UNIT_EX)
|
||||
/* Scale non-em units to em. We have fixed ratios. */
|
||||
switch (unit) {
|
||||
case CSS_UNIT_EX:
|
||||
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;
|
||||
case CSS_UNIT_PX:
|
||||
|
@ -105,6 +196,10 @@ css_fixed nscss_len2px(css_fixed length, css_unit unit,
|
|||
case CSS_UNIT_MM:
|
||||
px_per_unit = FDIV(nscss_screen_dpi, FLTTOFIX(25.4));
|
||||
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 */
|
||||
case CSS_UNIT_PT:
|
||||
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:
|
||||
px_per_unit = FDIV(nscss_screen_dpi, INTTOFIX(6));
|
||||
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:
|
||||
px_per_unit = 0;
|
||||
break;
|
||||
|
|
|
@ -26,25 +26,55 @@
|
|||
/** DPI of the screen, in fixed point units */
|
||||
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.
|
||||
*
|
||||
* \param[in] length Absolute CSS length.
|
||||
* \param[in] unit Unit of the length.
|
||||
* \param[in] ctx Length conversion context.
|
||||
* \param[in] length Absolute CSS length.
|
||||
* \param[in] unit Unit of the length.
|
||||
* \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.
|
||||
*
|
||||
* \param length Length to convert
|
||||
* \param unit Corresponding unit
|
||||
* \param style Computed style applying to length. May be NULL if unit is
|
||||
* neither em nor ex
|
||||
* \param[in] ctx Length conversion context.
|
||||
* \param[in] length Length to convert.
|
||||
* \param[in] unit Corresponding unit.
|
||||
* \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
|
||||
*/
|
||||
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);
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -257,6 +257,11 @@ struct print_settings *print_make_settings(print_configuration configuration,
|
|||
struct print_settings *settings;
|
||||
css_fixed length = 0;
|
||||
css_unit unit = CSS_UNIT_MM;
|
||||
nscss_len_ctx len_ctx = {
|
||||
.vw = DEFAULT_PAGE_WIDTH,
|
||||
.vh = DEFAULT_PAGE_HEIGHT,
|
||||
.root_style = NULL,
|
||||
};
|
||||
|
||||
switch (configuration){
|
||||
case PRINT_DEFAULT:
|
||||
|
@ -272,17 +277,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
|
|||
settings->scale = DEFAULT_EXPORT_SCALE;
|
||||
|
||||
length = INTTOFIX(DEFAULT_MARGIN_LEFT_MM);
|
||||
settings->margins[MARGINLEFT] =
|
||||
nscss_len2px(length, unit, NULL);
|
||||
settings->margins[MARGINLEFT] = nscss_len2px(
|
||||
&len_ctx, length, unit, NULL);
|
||||
length = INTTOFIX(DEFAULT_MARGIN_RIGHT_MM);
|
||||
settings->margins[MARGINRIGHT] =
|
||||
nscss_len2px(length, unit, NULL);
|
||||
settings->margins[MARGINRIGHT] = nscss_len2px(
|
||||
&len_ctx, length, unit, NULL);
|
||||
length = INTTOFIX(DEFAULT_MARGIN_TOP_MM);
|
||||
settings->margins[MARGINTOP] =
|
||||
nscss_len2px(length, unit, NULL);
|
||||
settings->margins[MARGINTOP] = nscss_len2px(
|
||||
&len_ctx, length, unit, NULL);
|
||||
length = INTTOFIX(DEFAULT_MARGIN_BOTTOM_MM);
|
||||
settings->margins[MARGINBOTTOM] =
|
||||
nscss_len2px(length, unit, NULL);
|
||||
settings->margins[MARGINBOTTOM] = nscss_len2px(
|
||||
&len_ctx, length, unit, NULL);
|
||||
break;
|
||||
/* use settings from the Export options tab */
|
||||
case PRINT_OPTIONS:
|
||||
|
@ -298,17 +303,17 @@ struct print_settings *print_make_settings(print_configuration configuration,
|
|||
settings->scale = (float)nsoption_int(export_scale) / 100;
|
||||
|
||||
length = INTTOFIX(nsoption_int(margin_left));
|
||||
settings->margins[MARGINLEFT] =
|
||||
nscss_len2px(length, unit, NULL);
|
||||
settings->margins[MARGINLEFT] = nscss_len2px(
|
||||
&len_ctx, length, unit, NULL);
|
||||
length = INTTOFIX(nsoption_int(margin_right));
|
||||
settings->margins[MARGINRIGHT] =
|
||||
nscss_len2px(length, unit, NULL);
|
||||
settings->margins[MARGINRIGHT] = nscss_len2px(
|
||||
&len_ctx, length, unit, NULL);
|
||||
length = INTTOFIX(nsoption_int(margin_top));
|
||||
settings->margins[MARGINTOP] =
|
||||
nscss_len2px(length, unit, NULL);
|
||||
settings->margins[MARGINTOP] = nscss_len2px(
|
||||
&len_ctx, length, unit, NULL);
|
||||
length = INTTOFIX(nsoption_int(margin_bottom));
|
||||
settings->margins[MARGINBOTTOM] =
|
||||
nscss_len2px(length, unit, NULL);
|
||||
settings->margins[MARGINBOTTOM] = nscss_len2px(
|
||||
&len_ctx, length, unit, NULL);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
|
|
|
@ -70,18 +70,20 @@ struct selection_string {
|
|||
|
||||
|
||||
typedef bool (*seln_traverse_handler)(const char *text, size_t length,
|
||||
struct box *box, void *handle, const char *whitespace_text,
|
||||
size_t whitespace_length);
|
||||
struct box *box, const nscss_len_ctx *len_ctx, void *handle,
|
||||
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,
|
||||
size_t whitespace_length);
|
||||
static void selection_redraw(struct selection *s, 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);
|
||||
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,
|
||||
void *handle, save_text_whitespace *before, bool *first,
|
||||
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
|
||||
*/
|
||||
|
||||
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)
|
||||
selection_clear(s, true);
|
||||
|
@ -207,6 +212,13 @@ void selection_init(struct selection *s, struct box *root)
|
|||
s->start_idx = 0;
|
||||
s->end_idx = 0;
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
*
|
||||
* \param box box subtree
|
||||
* \param len_ctx Length conversion context.
|
||||
* \param start_idx start of range within textual representation (bytes)
|
||||
* \param end_idx end of range
|
||||
* \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
|
||||
*/
|
||||
|
||||
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,
|
||||
void *handle, save_text_whitespace *before, bool *first,
|
||||
bool do_marker)
|
||||
|
@ -473,9 +488,9 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
|
|||
if (box->list_marker) {
|
||||
/* do the marker box before continuing with the rest of the
|
||||
* list element */
|
||||
if (!traverse_tree(box->list_marker, start_idx, end_idx,
|
||||
handler, handle, before, first,
|
||||
true))
|
||||
if (!traverse_tree(box->list_marker, len_ctx,
|
||||
start_idx, end_idx, handler, handle,
|
||||
before, first, true))
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -506,7 +521,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
|
|||
&end_offset)) {
|
||||
if (!handler(box->text + start_offset, min(box->length,
|
||||
end_offset) - start_offset,
|
||||
box, handle, whitespace_text,
|
||||
box, len_ctx, handle, whitespace_text,
|
||||
whitespace_length))
|
||||
return false;
|
||||
if (before) {
|
||||
|
@ -533,7 +548,7 @@ bool traverse_tree(struct box *box, unsigned start_idx, unsigned end_idx,
|
|||
* the tree */
|
||||
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))
|
||||
return false;
|
||||
|
||||
|
@ -568,14 +583,16 @@ static bool selection_traverse(struct selection *s,
|
|||
|
||||
if (s->root) {
|
||||
/* HTML */
|
||||
return traverse_tree(s->root, s->start_idx, s->end_idx,
|
||||
handler, handle, &before, &first, false);
|
||||
return traverse_tree(s->root, &s->len_ctx,
|
||||
s->start_idx, s->end_idx,
|
||||
handler, handle,
|
||||
&before, &first, false);
|
||||
}
|
||||
|
||||
/* Text */
|
||||
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 true;
|
||||
|
@ -597,8 +614,8 @@ static bool selection_traverse(struct selection *s,
|
|||
*/
|
||||
|
||||
bool redraw_handler(const char *text, size_t length, struct box *box,
|
||||
void *handle, const char *whitespace_text,
|
||||
size_t whitespace_length)
|
||||
const nscss_len_ctx *len_ctx, void *handle,
|
||||
const char *whitespace_text, size_t whitespace_length)
|
||||
{
|
||||
if (box) {
|
||||
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;
|
||||
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
|
||||
* 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;
|
||||
|
||||
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,
|
||||
NULL, NULL, false))
|
||||
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
|
||||
*
|
||||
* \param text pointer to text being added, or NULL for newline
|
||||
* \param length length of text to be appended (bytes)
|
||||
* \param box pointer to text box, or NULL if from textplain
|
||||
* \param handle selection string to append to
|
||||
* \param text pointer to text being added, or NULL for newline
|
||||
* \param length length of text to be appended (bytes)
|
||||
* \param box pointer to text box, or NULL if from textplain
|
||||
* \param len_ctx Length conversion context
|
||||
* \param handle selection string to append to
|
||||
* \param whitespace_text whitespace to place before text for formatting
|
||||
* may be NULL
|
||||
* \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,
|
||||
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)
|
||||
{
|
||||
bool add_space = false;
|
||||
|
@ -771,7 +790,7 @@ static bool selection_copy_handler(const char *text, size_t length,
|
|||
|
||||
if (box->style != NULL) {
|
||||
/* Override default font style */
|
||||
font_plot_style_from_css(box->style, &style);
|
||||
font_plot_style_from_css(len_ctx, box->style, &style);
|
||||
pstyle = &style;
|
||||
} else {
|
||||
/* If there's no style, there must be no text */
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
#include "netsurf/mouse.h"
|
||||
#include "content/handlers/css/utils.h"
|
||||
|
||||
struct box;
|
||||
|
||||
|
@ -43,6 +44,7 @@ struct selection
|
|||
{
|
||||
struct content *c;
|
||||
struct box *root;
|
||||
nscss_len_ctx len_ctx;
|
||||
|
||||
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_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);
|
||||
|
||||
/* struct box *selection_root(struct selection *s); */
|
||||
|
|
|
@ -1803,6 +1803,10 @@ static void textarea_setup_text_offsets(struct textarea *ta)
|
|||
{
|
||||
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;
|
||||
if (ta->flags & TEXTAREA_MULTILINE) {
|
||||
/* 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 */
|
||||
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_col = setup->border_col;
|
||||
|
||||
ret->fstyle = setup->text;
|
||||
|
||||
ret->sel_fstyle = setup->text;
|
||||
ret->sel_fstyle.foreground = setup->selected_text;
|
||||
ret->sel_fstyle.background = setup->selected_bg;
|
||||
textarea_set_text_style(ret,
|
||||
&setup->text,
|
||||
setup->selected_text,
|
||||
setup->selected_bg);
|
||||
|
||||
ret->scroll_x = 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 */
|
||||
void textarea_set_layout(struct textarea *ta, int width, int height,
|
||||
int top, int right, int bottom, int left)
|
||||
void textarea_set_layout(
|
||||
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};
|
||||
|
||||
|
@ -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_left = left;
|
||||
|
||||
textarea_set_text_style(ta, fstyle,
|
||||
ta->sel_fstyle.foreground,
|
||||
ta->sel_fstyle.background);
|
||||
|
||||
textarea_setup_text_offsets(ta);
|
||||
|
||||
if (ta->flags & TEXTAREA_MULTILINE) {
|
||||
|
|
|
@ -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 left the new left padding of the textarea
|
||||
*/
|
||||
void textarea_set_layout(struct textarea *ta, int width, int height,
|
||||
int top, int right, int bottom, int left);
|
||||
void textarea_set_layout(
|
||||
struct textarea *ta,
|
||||
const plot_font_style_t *fstyle,
|
||||
int width, int height,
|
||||
int top, int right,
|
||||
int bottom, int left);
|
||||
|
||||
|
||||
/**
|
||||
|
|
41
render/box.c
41
render/box.c
|
@ -342,20 +342,27 @@ void box_bounds(struct box *box, struct rect *r)
|
|||
/**
|
||||
* Determine if a point lies within a box.
|
||||
*
|
||||
* \param box box to consider
|
||||
* \param x coordinate relative to box
|
||||
* \param y coordinate relative to box
|
||||
* \param physically if function returning true, physically is set true if
|
||||
* point is within the box's physical dimensions and false
|
||||
* if the point is not within the box's physical dimensions
|
||||
* but is in the area defined by the box's descendants.
|
||||
* if function returning false, physically is undefined.
|
||||
* \param[in] len_ctx CSS length conversion context to use.
|
||||
* \param[in] box Box to consider
|
||||
* \param[in] x Coordinate relative to box
|
||||
* \param[in] y Coordinate relative to box
|
||||
* \param[out] physically If function returning true, physically is set true
|
||||
* iff point is within the box's physical dimensions and
|
||||
* false if the point is not within the box's physical
|
||||
* 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
|
||||
*
|
||||
* 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;
|
||||
|
||||
|
@ -382,25 +389,25 @@ static bool box_contains_point(struct box *box, int x, int y, bool *physically)
|
|||
|
||||
/* Adjust rect to css clip region */
|
||||
if (css_rect.left_auto == false) {
|
||||
r.x0 += FIXTOINT(nscss_len2px(
|
||||
r.x0 += FIXTOINT(nscss_len2px(len_ctx,
|
||||
css_rect.left, css_rect.lunit,
|
||||
box->style));
|
||||
}
|
||||
if (css_rect.top_auto == false) {
|
||||
r.y0 += FIXTOINT(nscss_len2px(
|
||||
r.y0 += FIXTOINT(nscss_len2px(len_ctx,
|
||||
css_rect.top, css_rect.tunit,
|
||||
box->style));
|
||||
}
|
||||
if (css_rect.right_auto == false) {
|
||||
r.x1 = box->border[LEFT].width +
|
||||
FIXTOINT(nscss_len2px(
|
||||
FIXTOINT(nscss_len2px(len_ctx,
|
||||
css_rect.right,
|
||||
css_rect.runit,
|
||||
box->style));
|
||||
}
|
||||
if (css_rect.bottom_auto == false) {
|
||||
r.y1 = box->border[TOP].width +
|
||||
FIXTOINT(nscss_len2px(
|
||||
FIXTOINT(nscss_len2px(len_ctx,
|
||||
css_rect.bottom,
|
||||
css_rect.bunit,
|
||||
box->style));
|
||||
|
@ -659,6 +666,7 @@ skip_children:
|
|||
/**
|
||||
* Find the boxes at a point.
|
||||
*
|
||||
* \param len_ctx CSS length conversion context for document.
|
||||
* \param box box to search children of
|
||||
* \param x 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;
|
||||
* 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
|
||||
* }
|
||||
* \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)
|
||||
{
|
||||
bool skip_children;
|
||||
|
@ -690,7 +699,7 @@ struct box *box_at_point(struct box *box, const int x, const int y,
|
|||
|
||||
skip_children = false;
|
||||
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)) {
|
||||
*box_x -= scrollbar_get_offset(box->scroll_x);
|
||||
*box_y -= scrollbar_get_offset(box->scroll_y);
|
||||
|
|
|
@ -91,6 +91,8 @@
|
|||
#include <stdio.h>
|
||||
#include <libcss/libcss.h>
|
||||
|
||||
#include "content/handlers/css/utils.h"
|
||||
|
||||
struct content;
|
||||
struct box;
|
||||
struct browser_window;
|
||||
|
@ -328,7 +330,9 @@ void box_free(struct box *box);
|
|||
void box_free_box(struct box *box);
|
||||
void box_bounds(struct box *box, struct rect *r);
|
||||
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);
|
||||
struct box *box_pick_text_box(struct html_content *html,
|
||||
int x, int y, int dir, int *dx, int *dy);
|
||||
|
|
|
@ -422,9 +422,6 @@ bool box_normalise_table(
|
|||
|
||||
free(col_info.spans);
|
||||
|
||||
if (table_calculate_column_types(table) == false)
|
||||
return false;
|
||||
|
||||
#ifdef BOX_NORMALISE_DEBUG
|
||||
NSLOG(netsurf, INFO, "table %p done", table);
|
||||
#endif
|
||||
|
|
|
@ -239,7 +239,14 @@ bool box_textarea_create_textarea(html_content *html,
|
|||
dom_exception err;
|
||||
textarea_setup ta_setup;
|
||||
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 disabled = false;
|
||||
struct form_control *gadget = box->gadget;
|
||||
|
@ -307,8 +314,6 @@ bool box_textarea_create_textarea(html_content *html,
|
|||
|
||||
gadget->data.text.data.gadget = gadget;
|
||||
|
||||
font_plot_style_from_css(gadget->box->style, &fstyle);
|
||||
|
||||
/* Reset to correct values by layout */
|
||||
ta_setup.width = 200;
|
||||
ta_setup.height = 20;
|
||||
|
|
|
@ -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 */
|
||||
void font_plot_style_from_css(const css_computed_style *css,
|
||||
/* exported function documented in render/font.h */
|
||||
void font_plot_style_from_css(
|
||||
const nscss_len_ctx *len_ctx,
|
||||
const css_computed_style *css,
|
||||
plot_font_style_t *fstyle)
|
||||
{
|
||||
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_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)));
|
||||
|
||||
/* Clamp font size to configured minimum */
|
||||
|
|
|
@ -32,10 +32,13 @@ struct plot_font_style;
|
|||
/**
|
||||
* Populate a font style using data from a computed CSS style
|
||||
*
|
||||
* \param css Computed style to consider
|
||||
* \param fstyle Font style to populate
|
||||
* \param len_ctx Length conversion context
|
||||
* \param css Computed style to consider
|
||||
* \param fstyle Font style to populate
|
||||
*/
|
||||
void font_plot_style_from_css(const css_computed_style *css,
|
||||
struct plot_font_style *fstyle);
|
||||
void font_plot_style_from_css(
|
||||
const nscss_len_ctx *len_ctx,
|
||||
const css_computed_style *css,
|
||||
struct plot_font_style *fstyle);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1133,6 +1133,7 @@ bool form_open_select_menu(void *client_data,
|
|||
plot_font_style_t fstyle;
|
||||
int total_height;
|
||||
struct form_select_menu *menu;
|
||||
html_content *html = (html_content *)c;
|
||||
|
||||
|
||||
/* 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->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);
|
||||
menu->f_size = fstyle.size;
|
||||
|
||||
|
|
|
@ -1398,6 +1398,10 @@ static void html_reformat(struct content *c, int width, int height)
|
|||
|
||||
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 = htmlc->layout;
|
||||
|
||||
|
@ -1647,7 +1651,7 @@ html_open(struct content *c,
|
|||
html->drag_owner.no_owner = true;
|
||||
|
||||
/* 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_owner.none = true;
|
||||
|
||||
|
@ -1768,7 +1772,8 @@ html_get_contextual_content(struct content *c, int x, int y,
|
|||
struct box *next;
|
||||
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;
|
||||
|
||||
/* 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 */
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
if (box->style && css_computed_visibility(box->style) ==
|
||||
|
|
|
@ -208,7 +208,7 @@ static size_t html_selection_drag_end(struct html_content *html,
|
|||
if (box) {
|
||||
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,
|
||||
dx, &idx, &pixel_offset);
|
||||
|
@ -415,7 +415,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
|
|||
size_t idx;
|
||||
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,
|
||||
|
@ -649,7 +650,8 @@ void html_mouse_action(struct content *c, struct browser_window *bw,
|
|||
text_box = box;
|
||||
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
|
||||
* 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;
|
||||
size_t idx;
|
||||
|
||||
font_plot_style_from_css(text_box->style,
|
||||
&fstyle);
|
||||
font_plot_style_from_css(&html->len_ctx,
|
||||
text_box->style, &fstyle);
|
||||
|
||||
guit->layout->position(&fstyle,
|
||||
text_box->text,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <libcss/libcss.h>
|
||||
|
||||
#include "content/handlers/css/utils.h"
|
||||
#include "content/content_protected.h"
|
||||
#include "desktop/selection.h"
|
||||
#include "render/html.h"
|
||||
|
@ -94,6 +95,9 @@ typedef struct html_content {
|
|||
/** Base target */
|
||||
char *base_target;
|
||||
|
||||
/** CSS length conversion context for document. */
|
||||
nscss_len_ctx len_ctx;
|
||||
|
||||
/** Content has been aborted in the LOADING state */
|
||||
bool aborted;
|
||||
|
||||
|
|
|
@ -227,7 +227,8 @@ html_object_callback(hlcache_handle *object,
|
|||
if (hunit == CSS_UNIT_PCT) {
|
||||
l = (width - w) * hpos / INTTOFIX(100);
|
||||
} else {
|
||||
l = FIXTOINT(nscss_len2px(hpos, hunit,
|
||||
l = FIXTOINT(nscss_len2px(&c->len_ctx,
|
||||
hpos, hunit,
|
||||
box->style));
|
||||
}
|
||||
|
||||
|
@ -235,7 +236,8 @@ html_object_callback(hlcache_handle *object,
|
|||
if (vunit == CSS_UNIT_PCT) {
|
||||
t = (height - h) * vpos / INTTOFIX(100);
|
||||
} else {
|
||||
t = FIXTOINT(nscss_len2px(vpos, vunit,
|
||||
t = FIXTOINT(nscss_len2px(&c->len_ctx,
|
||||
vpos, vunit,
|
||||
box->style));
|
||||
}
|
||||
|
||||
|
|
|
@ -521,12 +521,14 @@ static bool html_redraw_radio(int x, int y, int width, int height,
|
|||
* \param box box of input
|
||||
* \param scale scale for redraw
|
||||
* \param background_colour current background colour
|
||||
* \param len_ctx Length conversion context
|
||||
* \param ctx current redraw context
|
||||
* \return true if successful, false otherwise
|
||||
*/
|
||||
|
||||
static bool html_redraw_file(int x, int y, int width, int height,
|
||||
struct box *box, float scale, colour background_colour,
|
||||
const nscss_len_ctx *len_ctx,
|
||||
const struct redraw_context *ctx)
|
||||
{
|
||||
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;
|
||||
nserror res;
|
||||
|
||||
font_plot_style_from_css(box->style, &fstyle);
|
||||
font_plot_style_from_css(len_ctx, box->style, &fstyle);
|
||||
fstyle.background = background_colour;
|
||||
|
||||
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 background_colour current background colour
|
||||
* \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
|
||||
*/
|
||||
|
||||
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)
|
||||
struct box *background,
|
||||
const nscss_len_ctx *len_ctx,
|
||||
const struct redraw_context *ctx)
|
||||
{
|
||||
bool repeat_x = 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)) *
|
||||
scale * FIXTOFLT(hpos) / 100.;
|
||||
} else {
|
||||
x += (int) (FIXTOFLT(nscss_len2px(hpos, hunit,
|
||||
x += (int) (FIXTOFLT(nscss_len2px(len_ctx, hpos, hunit,
|
||||
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)) *
|
||||
scale * FIXTOFLT(vpos) / 100.;
|
||||
} else {
|
||||
y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit,
|
||||
y += (int) (FIXTOFLT(nscss_len2px(len_ctx, vpos, vunit,
|
||||
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 last true if this is the last rectangle associated with the inline
|
||||
* \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
|
||||
*/
|
||||
|
||||
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 nscss_len_ctx *len_ctx,
|
||||
const struct redraw_context *ctx)
|
||||
{
|
||||
struct rect r = *clip;
|
||||
|
@ -869,7 +876,7 @@ static bool html_redraw_inline_background(int x, int y, struct box *box,
|
|||
plot_content = false;
|
||||
}
|
||||
} else {
|
||||
x += (int) (FIXTOFLT(nscss_len2px(hpos, hunit,
|
||||
x += (int) (FIXTOFLT(nscss_len2px(len_ctx, hpos, hunit,
|
||||
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) *
|
||||
scale) * FIXTOFLT(vpos) / 100.;
|
||||
} else {
|
||||
y += (int) (FIXTOFLT(nscss_len2px(vpos, vunit,
|
||||
y += (int) (FIXTOFLT(nscss_len2px(len_ctx, vpos, vunit,
|
||||
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);
|
||||
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;
|
||||
|
||||
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 */
|
||||
if (css_rect.left_auto == false)
|
||||
r.x0 = x - border_left + FIXTOINT(nscss_len2px(
|
||||
&html->len_ctx,
|
||||
css_rect.left, css_rect.lunit,
|
||||
box->style));
|
||||
|
||||
if (css_rect.top_auto == false)
|
||||
r.y0 = y - border_top + FIXTOINT(nscss_len2px(
|
||||
&html->len_ctx,
|
||||
css_rect.top, css_rect.tunit,
|
||||
box->style));
|
||||
|
||||
if (css_rect.right_auto == false)
|
||||
r.x1 = x - border_left + FIXTOINT(nscss_len2px(
|
||||
&html->len_ctx,
|
||||
css_rect.right, css_rect.runit,
|
||||
box->style));
|
||||
|
||||
if (css_rect.bottom_auto == false)
|
||||
r.y1 = y - border_top + FIXTOINT(nscss_len2px(
|
||||
&html->len_ctx,
|
||||
css_rect.bottom, css_rect.bunit,
|
||||
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)) {
|
||||
/* plot background */
|
||||
if (!html_redraw_background(x, y, box, scale, &p,
|
||||
¤t_background_color, bg_box, ctx))
|
||||
¤t_background_color, bg_box,
|
||||
&html->len_ctx, ctx))
|
||||
return false;
|
||||
/* restore previous graphics window */
|
||||
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(
|
||||
x, y, box, scale, &p, b,
|
||||
first, false,
|
||||
¤t_background_color, ctx))
|
||||
¤t_background_color,
|
||||
&html->len_ctx, ctx))
|
||||
return false;
|
||||
/* restore previous graphics window */
|
||||
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
|
||||
* the inline */
|
||||
if (!html_redraw_inline_background(x, ib_y, box, scale, &p, b,
|
||||
first, true, ¤t_background_color, ctx))
|
||||
first, true, ¤t_background_color,
|
||||
&html->len_ctx, ctx))
|
||||
return false;
|
||||
/* restore previous graphics window */
|
||||
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)
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
} else if (box->iframe) {
|
||||
/* 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) {
|
||||
if (!html_redraw_file(x + padding_left, y + padding_top,
|
||||
width, height, box, scale,
|
||||
current_background_color, ctx))
|
||||
current_background_color, &html->len_ctx, ctx))
|
||||
return false;
|
||||
|
||||
} else if (box->gadget &&
|
||||
|
|
562
render/layout.c
562
render/layout.c
File diff suppressed because it is too large
Load Diff
|
@ -621,13 +621,14 @@ void search_show_all(bool all, struct search_context *context)
|
|||
if (!a->sel)
|
||||
continue;
|
||||
|
||||
selection_init(a->sel, html->layout);
|
||||
selection_init(a->sel, html->layout,
|
||||
&html->len_ctx);
|
||||
} else {
|
||||
a->sel = selection_create(context->c, false);
|
||||
if (!a->sel)
|
||||
continue;
|
||||
|
||||
selection_init(a->sel, NULL);
|
||||
selection_init(a->sel, NULL, NULL);
|
||||
}
|
||||
|
||||
selection_set_start(a->sel, a->start_idx);
|
||||
|
|
319
render/table.c
319
render/table.c
|
@ -45,31 +45,57 @@ struct border {
|
|||
css_unit unit; /**< border-width units */
|
||||
};
|
||||
|
||||
static void table_used_left_border_for_cell(struct box *cell);
|
||||
static void table_used_top_border_for_cell(struct box *cell);
|
||||
static void table_used_right_border_for_cell(struct box *cell);
|
||||
static void table_used_bottom_border_for_cell(struct box *cell);
|
||||
static bool table_border_is_more_eyecatching(const struct border *a,
|
||||
box_type a_src, const struct border *b, box_type b_src);
|
||||
static void table_cell_top_process_table(struct box *table, struct border *a,
|
||||
static void table_used_left_border_for_cell(
|
||||
const nscss_len_ctx *len_ctx,
|
||||
struct box *cell);
|
||||
static void table_used_top_border_for_cell(
|
||||
const nscss_len_ctx *len_ctx,
|
||||
struct box *cell);
|
||||
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);
|
||||
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.
|
||||
*
|
||||
* \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
|
||||
*
|
||||
* The table->col array is allocated and type and width are filled in for each
|
||||
* 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;
|
||||
struct column *col;
|
||||
|
@ -109,7 +135,7 @@ bool table_calculate_column_types(struct box *table)
|
|||
css_computed_position(cell->style) !=
|
||||
CSS_POSITION_FIXED) {
|
||||
col[i].positioned = false;
|
||||
}
|
||||
}
|
||||
|
||||
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 &&
|
||||
type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT) {
|
||||
col[i].type = COLUMN_WIDTH_FIXED;
|
||||
col[i].width = FIXTOINT(nscss_len2px(value, unit,
|
||||
cell->style));
|
||||
col[i].width = FIXTOINT(nscss_len2px(len_ctx,
|
||||
value, unit, cell->style));
|
||||
if (col[i].width < 0)
|
||||
col[i].width = 0;
|
||||
continue;
|
||||
|
@ -181,7 +207,7 @@ bool table_calculate_column_types(struct box *table)
|
|||
if (type == CSS_WIDTH_SET && unit != CSS_UNIT_PCT &&
|
||||
fixed_columns + unknown_columns ==
|
||||
cell->columns) {
|
||||
int width = (FIXTOFLT(nscss_len2px(value, unit,
|
||||
int width = (FIXTOFLT(nscss_len2px(len_ctx, value, unit,
|
||||
cell->style)) - fixed_width) /
|
||||
unknown_columns;
|
||||
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.
|
||||
*
|
||||
* \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
|
||||
*/
|
||||
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;
|
||||
|
||||
|
@ -257,7 +286,8 @@ void table_used_border_for_cell(struct box *cell)
|
|||
&cell->border[LEFT].c);
|
||||
css_computed_border_left_width(cell->style, &width, &unit);
|
||||
cell->border[LEFT].width =
|
||||
FIXTOINT(nscss_len2px(width, unit, cell->style));
|
||||
FIXTOINT(nscss_len2px(len_ctx,
|
||||
width, unit, cell->style));
|
||||
|
||||
/* Top border */
|
||||
cell->border[TOP].style =
|
||||
|
@ -266,7 +296,8 @@ void table_used_border_for_cell(struct box *cell)
|
|||
&cell->border[TOP].c);
|
||||
css_computed_border_top_width(cell->style, &width, &unit);
|
||||
cell->border[TOP].width =
|
||||
FIXTOINT(nscss_len2px(width, unit, cell->style));
|
||||
FIXTOINT(nscss_len2px(len_ctx,
|
||||
width, unit, cell->style));
|
||||
|
||||
/* Right border */
|
||||
cell->border[RIGHT].style =
|
||||
|
@ -275,7 +306,8 @@ void table_used_border_for_cell(struct box *cell)
|
|||
&cell->border[RIGHT].c);
|
||||
css_computed_border_right_width(cell->style, &width, &unit);
|
||||
cell->border[RIGHT].width =
|
||||
FIXTOINT(nscss_len2px(width, unit, cell->style));
|
||||
FIXTOINT(nscss_len2px(len_ctx,
|
||||
width, unit, cell->style));
|
||||
|
||||
/* Bottom border */
|
||||
cell->border[BOTTOM].style =
|
||||
|
@ -284,19 +316,20 @@ void table_used_border_for_cell(struct box *cell)
|
|||
&cell->border[BOTTOM].c);
|
||||
css_computed_border_bottom_width(cell->style, &width, &unit);
|
||||
cell->border[BOTTOM].width =
|
||||
FIXTOINT(nscss_len2px(width, unit, cell->style));
|
||||
FIXTOINT(nscss_len2px(len_ctx,
|
||||
width, unit, cell->style));
|
||||
} else {
|
||||
/* Left border */
|
||||
table_used_left_border_for_cell(cell);
|
||||
table_used_left_border_for_cell(len_ctx, cell);
|
||||
|
||||
/* Top border */
|
||||
table_used_top_border_for_cell(cell);
|
||||
table_used_top_border_for_cell(len_ctx, cell);
|
||||
|
||||
/* Right border */
|
||||
table_used_right_border_for_cell(cell);
|
||||
table_used_right_border_for_cell(len_ctx, cell);
|
||||
|
||||
/* 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
|
||||
|
@ -316,9 +349,12 @@ void table_used_border_for_cell(struct box *cell)
|
|||
/**
|
||||
* 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;
|
||||
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.color = css_computed_border_left_color(cell->style, &a.c);
|
||||
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_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.color = css_computed_border_right_color(prev->style, &b.c);
|
||||
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_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_src = b_src;
|
||||
}
|
||||
|
@ -384,12 +421,13 @@ void table_used_left_border_for_cell(struct box *cell)
|
|||
row->style, &b.c);
|
||||
css_computed_border_left_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_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_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.color = css_computed_border_left_color(group->style, &b.c);
|
||||
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_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_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.color = css_computed_border_left_color(table->style, &b.c);
|
||||
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_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_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 */
|
||||
cell->border[LEFT].style = a.style;
|
||||
cell->border[LEFT].c = a.c;
|
||||
cell->border[LEFT].width =
|
||||
FIXTOINT(nscss_len2px(a.width, a.unit, cell->style));
|
||||
cell->border[LEFT].width = FIXTOINT(nscss_len2px(len_ctx,
|
||||
a.width, a.unit, cell->style));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
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);
|
||||
css_computed_border_top_color(cell->style, &a.c);
|
||||
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_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);
|
||||
css_computed_border_top_color(row->style, &b.c);
|
||||
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_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_src = b_src;
|
||||
}
|
||||
|
||||
if (row->prev != NULL) {
|
||||
/* 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) {
|
||||
if (row->prev->prev == NULL) {
|
||||
/* 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.color = css_computed_border_top_color(group->style, &b.c);
|
||||
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_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_src = b_src;
|
||||
}
|
||||
|
||||
if (group->prev == NULL) {
|
||||
/* 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 {
|
||||
/* 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) {
|
||||
if (group->prev->prev == NULL) {
|
||||
/* Top border of table */
|
||||
table_cell_top_process_table(
|
||||
group->parent,
|
||||
table_cell_top_process_table(len_ctx,
|
||||
group->parent,
|
||||
&a, &a_src);
|
||||
break;
|
||||
} 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 */
|
||||
cell->border[TOP].style = a.style;
|
||||
cell->border[TOP].c = a.c;
|
||||
cell->border[TOP].width =
|
||||
FIXTOINT(nscss_len2px(a.width, a.unit, cell->style));
|
||||
cell->border[TOP].width = FIXTOINT(nscss_len2px(len_ctx,
|
||||
a.width, a.unit, cell->style));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
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);
|
||||
css_computed_border_right_color(cell->style, &a.c);
|
||||
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_src = BOX_TABLE_CELL;
|
||||
|
||||
|
@ -565,12 +614,13 @@ void table_used_right_border_for_cell(struct box *cell)
|
|||
row->style, &b.c);
|
||||
css_computed_border_right_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_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_src = b_src;
|
||||
}
|
||||
|
@ -583,13 +633,14 @@ void table_used_right_border_for_cell(struct box *cell)
|
|||
/* Row group -- consider its right border */
|
||||
b.style = css_computed_border_right_style(group->style);
|
||||
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 = 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_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_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);
|
||||
css_computed_border_right_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_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_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 */
|
||||
cell->border[RIGHT].style = a.style;
|
||||
cell->border[RIGHT].c = a.c;
|
||||
cell->border[RIGHT].width =
|
||||
FIXTOINT(nscss_len2px(a.width, a.unit, cell->style));
|
||||
cell->border[RIGHT].width = FIXTOINT(nscss_len2px(len_ctx,
|
||||
a.width, a.unit, cell->style));
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
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);
|
||||
css_computed_border_bottom_color(cell->style, &a.c);
|
||||
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_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.color = css_computed_border_bottom_color(row->style, &b.c);
|
||||
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_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_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);
|
||||
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_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_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);
|
||||
css_computed_border_bottom_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_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;
|
||||
}
|
||||
}
|
||||
|
@ -696,21 +754,26 @@ void table_used_bottom_border_for_cell(struct box *cell)
|
|||
/* a now contains the used bottom border for the cell */
|
||||
cell->border[BOTTOM].style = a.style;
|
||||
cell->border[BOTTOM].c = a.c;
|
||||
cell->border[BOTTOM].width =
|
||||
FIXTOINT(nscss_len2px(a.width, a.unit, cell->style));
|
||||
cell->border[BOTTOM].width = FIXTOINT(nscss_len2px(len_ctx,
|
||||
a.width, a.unit, cell->style));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if a border style is more eyecatching than another
|
||||
*
|
||||
* \param a Reference border style
|
||||
* \param a_src Source of \a a
|
||||
* \param b Candidate border style
|
||||
* \param b_src Source of \a b
|
||||
* \param len_ctx Length conversion context
|
||||
* \param a Reference border style
|
||||
* \param a_src Source of \a a
|
||||
* \param b Candidate border style
|
||||
* \param b_src Source of \a b
|
||||
* \return True if \a b is more eyecatching than \a a
|
||||
*/
|
||||
bool table_border_is_more_eyecatching(const struct border *a,
|
||||
box_type a_src, const struct border *b, box_type b_src)
|
||||
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)
|
||||
{
|
||||
css_fixed awidth, bwidth;
|
||||
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. */
|
||||
assert(a->unit != CSS_UNIT_EM && a->unit != CSS_UNIT_EX);
|
||||
assert(b->unit != CSS_UNIT_EM && b->unit != CSS_UNIT_EX);
|
||||
awidth = nscss_len2px(a->width, a->unit, NULL);
|
||||
bwidth = nscss_len2px(b->width, b->unit, NULL);
|
||||
awidth = nscss_len2px(len_ctx, a->width, a->unit, NULL);
|
||||
bwidth = nscss_len2px(len_ctx, b->width, b->unit, NULL);
|
||||
|
||||
if (awidth < bwidth)
|
||||
return true;
|
||||
|
@ -811,14 +874,18 @@ bool table_border_is_more_eyecatching(const struct border *a,
|
|||
/**
|
||||
* Process a table
|
||||
*
|
||||
* \param table Table to process
|
||||
* \param a Current border style for cell
|
||||
* \param a_src Source of \a a
|
||||
* \param len_ctx Length conversion context
|
||||
* \param table Table to process
|
||||
* \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_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)
|
||||
{
|
||||
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.color = css_computed_border_top_color(table->style, &b.c);
|
||||
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_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_src = b_src;
|
||||
}
|
||||
|
@ -841,17 +908,22 @@ void table_cell_top_process_table(struct box *table, struct border *a,
|
|||
/**
|
||||
* Process a group
|
||||
*
|
||||
* \param cell Cell being considered
|
||||
* \param group Group to process
|
||||
* \param a Current border style for cell
|
||||
* \param a_src Source of \a a
|
||||
* \param len_ctx Length conversion context
|
||||
* \param cell Cell being considered
|
||||
* \param group Group to process
|
||||
* \param a Current border style for cell
|
||||
* \param a_src Source of \a a
|
||||
* \return true if group has non-empty rows, false otherwise
|
||||
*
|
||||
* \post \a a will be updated with most eyecatching style
|
||||
* \post \a a_src will be updated also
|
||||
*/
|
||||
bool table_cell_top_process_group(struct box *cell, struct box *group,
|
||||
struct border *a, box_type *a_src)
|
||||
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)
|
||||
{
|
||||
struct border b;
|
||||
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.color = css_computed_border_bottom_color(group->style, &b.c);
|
||||
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_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_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 */
|
||||
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) {
|
||||
if (row->prev == NULL) {
|
||||
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.color = css_computed_border_top_color(group->style, &b.c);
|
||||
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_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_src = b_src;
|
||||
}
|
||||
|
@ -904,17 +977,22 @@ bool table_cell_top_process_group(struct box *cell, struct box *group,
|
|||
/**
|
||||
* Process a row
|
||||
*
|
||||
* \param cell Cell being considered
|
||||
* \param row Row to process
|
||||
* \param a Current border style for cell
|
||||
* \param a_src Source of \a a
|
||||
* \param len_ctx Length conversion context
|
||||
* \param cell Cell being considered
|
||||
* \param row Row to process
|
||||
* \param a Current border style for cell
|
||||
* \param a_src Source of \a a
|
||||
* \return true if row has cells, false otherwise
|
||||
*
|
||||
* \post \a a will be updated with most eyecatching style
|
||||
* \post \a a_src will be updated also
|
||||
*/
|
||||
bool table_cell_top_process_row(struct box *cell, struct box *row,
|
||||
struct border *a, box_type *a_src)
|
||||
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)
|
||||
{
|
||||
struct border b;
|
||||
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.color = css_computed_border_bottom_color(row->style, &b.c);
|
||||
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_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_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.color = css_computed_border_top_color(row->style, &b.c);
|
||||
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_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_src = b_src;
|
||||
}
|
||||
|
@ -975,13 +1054,13 @@ bool table_cell_top_process_row(struct box *cell, struct box *row,
|
|||
c->style, &b.c);
|
||||
css_computed_border_bottom_width(c->style,
|
||||
&b.width, &b.unit);
|
||||
b.width = nscss_len2px(b.width, b.unit,
|
||||
c->style);
|
||||
b.width = nscss_len2px(len_ctx,
|
||||
b.width, b.unit, c->style);
|
||||
b.unit = CSS_UNIT_PX;
|
||||
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_src = b_src;
|
||||
}
|
||||
|
|
|
@ -28,7 +28,11 @@
|
|||
|
||||
struct box;
|
||||
|
||||
bool table_calculate_column_types(struct box *table);
|
||||
void table_used_border_for_cell(struct box *cell);
|
||||
bool table_calculate_column_types(
|
||||
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
|
||||
|
|
|
@ -988,7 +988,7 @@ textplain_open(struct content *c,
|
|||
text->bw = bw;
|
||||
|
||||
/* text selection */
|
||||
selection_init(&text->sel, NULL);
|
||||
selection_init(&text->sel, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue