html: Do list item counting at layout time.

This commit is contained in:
Michael Drake 2021-02-09 20:30:53 +00:00
parent 9434fe1ff0
commit 41a0c21812
2 changed files with 82 additions and 98 deletions

View File

@ -349,61 +349,6 @@ box_construct_generate(dom_node *n,
}
/**
* compute the index for a list marker
*
* calculates a one based index of a list item
*/
static unsigned int compute_list_marker_index(struct box *last)
{
/* Drill down into last child of parent
* to find the list marker (if any)
*
* Floated list boxes end up as:
*
* parent
* BOX_INLINE_CONTAINER
* BOX_FLOAT_{LEFT,RIGHT}
* BOX_BLOCK <-- list box
* ...
*/
while ((last != NULL) && (last->list_marker == NULL)) {
struct box *last_inner = last;
while (last_inner != NULL) {
if (last_inner->list_marker != NULL) {
break;
}
if (last_inner->type == BOX_INLINE_CONTAINER ||
last_inner->type == BOX_FLOAT_LEFT ||
last_inner->type == BOX_FLOAT_RIGHT) {
last_inner = last_inner->last;
} else {
last_inner = NULL;
}
}
if (last_inner != NULL) {
last = last_inner;
} else {
last = last->prev;
}
}
if ((last == NULL) || (last->list_marker == NULL)) {
return 1;
}
return last->list_marker->rows + 1;
}
/**
* initial length of a list marker buffer
*
* enough for 9,999,999,999,999,999,999 in decimal
* or five characters for 4byte utf8
*/
#define LIST_MARKER_SIZE 20
/**
* Construct a list marker box
*
@ -422,8 +367,6 @@ box_construct_marker(struct box *box,
lwc_string *image_uri;
struct box *marker;
enum css_list_style_type_e list_style_type;
size_t counter_len;
css_error css_res;
marker = box_create(NULL, box->style, false, NULL, NULL, title,
NULL, ctx->bctx);
@ -454,51 +397,13 @@ box_construct_marker(struct box *box,
marker->length = 3;
break;
default:
/* Numerical list counters get handled in layout. */
/* Fall through. */
case CSS_LIST_STYLE_TYPE_NONE:
marker->text = NULL;
marker->length = 0;
break;
default:
marker->rows = compute_list_marker_index(parent->last);
marker->text = talloc_array(ctx->bctx, char, LIST_MARKER_SIZE);
if (marker->text == NULL) {
return false;
}
css_res = css_computed_format_list_style(box->style,
marker->rows,
marker->text,
LIST_MARKER_SIZE,
&counter_len);
if (css_res == CSS_OK) {
if (counter_len > LIST_MARKER_SIZE) {
/*
* use computed size as marker did not fit
* in default allocation
*/
marker->text = talloc_realloc(ctx->bctx,
marker->text,
char,
counter_len);
if (marker->text == NULL) {
return false;
}
css_computed_format_list_style(box->style,
marker->rows,
marker->text,
counter_len,
&counter_len);
}
marker->length = counter_len;
} else {
/* failed to format marker so use none type */
marker->text = NULL;
marker->length = 0;
}
break;
}
if (css_computed_list_style_image(box->style, &image_uri) == CSS_LIST_STYLE_IMAGE_URI &&

View File

@ -4505,6 +4505,79 @@ layout__ordered_list_count(
box->rows = count;
}
/**
* Set up the marker text for a numerical list item.
*
* \param[in] content The HTML content.
* \param[in] box The list item's main box.
*/
static void
layout__set_numerical_marker_text(
const html_content *content,
struct box *box)
{
struct box *marker = box->list_marker;
size_t counter_len;
css_error css_res;
enum {
/**
* initial length of a list marker buffer
*
* enough for 9,999,999,999,999,999,999 in decimal
* or five characters for 4-byte UTF-8.
*/
LIST_MARKER_SIZE = 20,
};
marker->text = talloc_array(content->bctx, char, LIST_MARKER_SIZE);
if (marker->text == NULL) {
return;
}
css_res = css_computed_format_list_style(box->style, marker->rows,
marker->text, LIST_MARKER_SIZE, &counter_len);
if (css_res == CSS_OK) {
if (counter_len > LIST_MARKER_SIZE) {
/* Use computed size as marker did not fit in
* default allocation. */
marker->text = talloc_realloc(content->bctx,
marker->text,
char,
counter_len);
if (marker->text == NULL) {
return;
}
css_computed_format_list_style(box->style,
marker->rows, marker->text,
counter_len, &counter_len);
}
marker->length = counter_len;
}
}
/**
* Find out if box's style represents a numerical list style type.
*
* \param[in] b Box with style to test.
* \return true if box has numerical list style type, false otherwise.
*/
static bool
layout__list_item_is_numerical(
const struct box *b)
{
enum css_list_style_type_e t = css_computed_list_style_type(b->style);
switch (t) {
case CSS_LIST_STYLE_TYPE_DISC: /* Fall through. */
case CSS_LIST_STYLE_TYPE_CIRCLE: /* Fall through. */
case CSS_LIST_STYLE_TYPE_SQUARE: /* Fall through. */
case CSS_LIST_STYLE_TYPE_NONE:
return false;
default:
return true;
}
}
/**
* Layout list markers.
@ -4521,6 +4594,12 @@ layout_lists(const html_content *content, struct box *box)
for (child = box->children; child; child = child->next) {
if (child->list_marker) {
marker = child->list_marker;
if (layout__list_item_is_numerical(child)) {
if (marker->text == NULL) {
layout__set_numerical_marker_text(
content, child);
}
}
if (marker->object) {
marker->width =
content_get_width(marker->object);