Layout: Implement CSS3 box-sizing property.

Updates user agent CSS to set form element box-sizing properties,
and removes some legacy pre-CSS3 hacks for handling gadget dimensions.
This commit is contained in:
Michael Drake 2017-04-27 16:47:38 +01:00
parent 66602e6327
commit 6c726473ef
2 changed files with 96 additions and 62 deletions

View File

@ -114,13 +114,13 @@ form { display: block; }
input, button { background-color: #fff; color: #000; text-align: left;
font-family: sans-serif; width: auto; height: auto; overflow: hidden;
border: 1px solid #444; padding: 2px 3px; line-height: 1.33;
margin: 1px; }
margin: 1px; box-sizing: border-box; }
input[disabled] { background-color: #ddd; color: #333; }
input[type=button], input[type=reset], input[type=submit], button {
background-color: #d9d9d9; color: #000; text-align: center;
border: 2px outset #d9d9d9; padding: 1px 0.5em; }
input[type=image] { background-color: transparent; color: #000;
border: none; padding: 0 2px; }
border: none; padding: 0 2px; box-sizing: content-box; }
input[type=checkbox], input[type=radio] { background-color: transparent;
border: none; padding: 0 0.1em; }
input[type=file] { background-color: #d9d9d9; color: #000; font-style: italic;

View File

@ -332,6 +332,7 @@ layout_minmax_line(struct box *first,
for (b = first; b; b = b->next) {
enum css_width_e wtype;
enum css_height_e htype;
enum css_box_sizing_e bs;
css_fixed value = 0;
css_unit unit = CSS_UNIT_PX;
@ -506,6 +507,7 @@ layout_minmax_line(struct box *first,
/* calculate box width */
wtype = css_computed_width(b->style, &value, &unit);
bs = css_computed_box_sizing(block->style);
if (wtype == CSS_WIDTH_SET) {
if (unit == CSS_UNIT_PCT) {
/*
@ -516,6 +518,19 @@ layout_minmax_line(struct box *first,
} else {
width = FIXTOINT(nscss_len2px(value, unit,
b->style));
if (bs == CSS_BOX_SIZING_BORDER_BOX) {
fixed = frac = 0;
calculate_mbp_width(block->style, LEFT,
false, true, true,
&fixed, &frac);
calculate_mbp_width(block->style, RIGHT,
false, true, true,
&fixed, &frac);
if (width < fixed) {
width = fixed;
}
}
if (width < 0)
width = 0;
}
@ -541,11 +556,21 @@ layout_minmax_line(struct box *first,
}
fixed = frac = 0;
calculate_mbp_width(b->style, LEFT, true, true, true,
&fixed, &frac);
calculate_mbp_width(b->style, RIGHT, true, true, true,
&fixed, &frac);
if (bs == CSS_BOX_SIZING_BORDER_BOX) {
calculate_mbp_width(b->style, LEFT,
true, false, false,
&fixed, &frac);
calculate_mbp_width(b->style, RIGHT,
true, false, false,
&fixed, &frac);
} else {
calculate_mbp_width(b->style, LEFT,
true, true, true,
&fixed, &frac);
calculate_mbp_width(b->style, RIGHT,
true, true, true,
&fixed, &frac);
}
if (0 < width + fixed)
width += fixed;
} else if (b->flags & IFRAME) {
@ -554,13 +579,25 @@ layout_minmax_line(struct box *first,
width = 400;
fixed = frac = 0;
calculate_mbp_width(b->style, LEFT, true, true, true,
&fixed, &frac);
calculate_mbp_width(b->style, RIGHT, true, true, true,
&fixed, &frac);
if (bs == CSS_BOX_SIZING_BORDER_BOX) {
calculate_mbp_width(b->style, LEFT,
true, false, false,
&fixed, &frac);
calculate_mbp_width(b->style, RIGHT,
true, false, false,
&fixed, &frac);
} else {
calculate_mbp_width(b->style, LEFT,
true, true, true,
&fixed, &frac);
calculate_mbp_width(b->style, RIGHT,
true, true, true,
&fixed, &frac);
}
if (0 < width + fixed)
width += fixed;
} else {
/* form control with no object */
if (width == AUTO)
@ -667,6 +704,7 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func)
enum css_height_e htype = CSS_HEIGHT_AUTO;
css_fixed height = 0;
css_unit hunit = CSS_UNIT_PX;
enum css_box_sizing_e bs = CSS_BOX_SIZING_CONTENT_BOX;
bool child_has_height = false;
assert(block->type == BOX_BLOCK ||
@ -680,6 +718,7 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func)
if (block->style != NULL) {
wtype = css_computed_width(block->style, &width, &wunit);
htype = css_computed_height(block->style, &height, &hunit);
bs = css_computed_box_sizing(block->style);
}
/* set whether the minimum width is of any interest for this box */
@ -800,6 +839,19 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func)
if (block->type != BOX_TABLE_CELL && wtype == CSS_WIDTH_SET &&
wunit != CSS_UNIT_PCT) {
min = max = FIXTOINT(nscss_len2px(width, wunit, block->style));
if (bs == CSS_BOX_SIZING_BORDER_BOX) {
int border_box_fixed = 0;
float border_box_frac = 0;
calculate_mbp_width(block->style, LEFT,
false, true, true,
&border_box_fixed, &border_box_frac);
calculate_mbp_width(block->style, RIGHT,
false, true, true,
&border_box_fixed, &border_box_frac);
if (min < border_box_fixed) {
min = max = border_box_fixed;
}
}
}
if (htype == CSS_HEIGHT_SET && hunit != CSS_UNIT_PCT &&
@ -811,12 +863,8 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func)
/* add margins, border, padding to min, max widths */
/* Note: we don't know available width here so percentage margin
* and paddings are wrong. */
if (block->gadget && wtype == CSS_WIDTH_SET &&
(block->gadget->type == GADGET_SUBMIT ||
block->gadget->type == GADGET_RESET ||
block->gadget->type == GADGET_BUTTON)) {
/* some gadgets with specified width already include border and
* padding, so just get margin */
if (bs == CSS_BOX_SIZING_BORDER_BOX && wtype == CSS_WIDTH_SET) {
/* Border and padding included in width, so just get margin */
calculate_mbp_width(block->style, LEFT, true, false, false,
&extra_fixed, &extra_frac);
calculate_mbp_width(block->style, RIGHT, true, false, false,
@ -850,12 +898,11 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func)
/**
* Under some circumstances, specified dimensions for form elements include
* borders and padding.
* Adjust a specified width or height for the box-sizing property.
*
* This turns the specified dimension into a content-box dimension.
*
* \param box gadget to adjust dimensions of
* \param percentage whether the gadget has its dimension specified as a
* percentage
* \param available_width width of containing block
* \param setwidth set true if the dimension to be tweaked is a width,
* else set false for a height
@ -863,25 +910,29 @@ layout_minmax_block(struct box *block, const struct gui_layout_table *font_func)
* updated to new value after consideration of
* gadget properties.
*/
static void layout_tweak_form_dimensions(struct box *box, bool percentage,
int available_width, bool setwidth, int *dimension)
static void layout_handle_box_sizing(
struct box *box,
int available_width,
bool setwidth,
int *dimension)
{
int fixed = 0;
float frac = 0;
enum css_box_sizing_e bs;
assert(box && box->gadget);
assert(box && box->style);
bs = css_computed_box_sizing(box->style);
if (bs == CSS_BOX_SIZING_BORDER_BOX) {
int orig = *dimension;
int fixed = 0;
float frac = 0;
/* specified gadget widths include borders and padding in some
* cases */
if (percentage || box->gadget->type == GADGET_SUBMIT ||
box->gadget->type == GADGET_RESET ||
box->gadget->type == GADGET_BUTTON) {
calculate_mbp_width(box->style, setwidth ? LEFT : TOP,
false, true, true, &fixed, &frac);
calculate_mbp_width(box->style, setwidth ? RIGHT : BOTTOM,
false, true, true, &fixed, &frac);
*dimension -= frac * available_width + fixed;
*dimension = *dimension > 0 ? *dimension : 0;
orig -= frac * available_width + fixed;
*dimension = orig > 0 ? orig : 0;
}
}
@ -921,7 +972,6 @@ layout_find_dimensions(int available_width,
{
struct box *containing_block = NULL;
unsigned int i;
bool percentage;
if (width) {
enum css_width_e wtype;
@ -942,13 +992,9 @@ layout_find_dimensions(int available_width,
*width = AUTO;
}
/* specified gadget widths include borders and padding in some
* cases */
if (box->gadget && *width != AUTO) {
percentage = unit == CSS_UNIT_PCT;
layout_tweak_form_dimensions(box, percentage,
available_width, true, width);
if (*width != AUTO) {
layout_handle_box_sizing(box, available_width,
true, width);
}
}
@ -1034,13 +1080,9 @@ layout_find_dimensions(int available_width,
*height = AUTO;
}
/* specified gadget heights include borders and padding in
* some cases */
if (box->gadget && *height != AUTO) {
percentage = unit == CSS_UNIT_PCT;
layout_tweak_form_dimensions(box, percentage,
available_width, false, height);
if (*height != AUTO) {
layout_handle_box_sizing(box, available_width,
false, height);
}
}
@ -1064,13 +1106,9 @@ layout_find_dimensions(int available_width,
*max_width = -1;
}
/* specified gadget widths include borders and padding in some
* cases */
if (box->gadget && *max_width != -1) {
percentage = unit == CSS_UNIT_PCT;
layout_tweak_form_dimensions(box, percentage,
available_width, true, max_width);
if (*max_width != -1) {
layout_handle_box_sizing(box, available_width,
true, max_width);
}
}
@ -1094,13 +1132,9 @@ layout_find_dimensions(int available_width,
*min_width = 0;
}
/* specified gadget widths include borders and padding in some
* cases */
if (box->gadget && *min_width != 0) {
percentage = unit == CSS_UNIT_PCT;
layout_tweak_form_dimensions(box, percentage,
available_width, true, min_width);
if (*min_width != 0) {
layout_handle_box_sizing(box, available_width,
true, min_width);
}
}