From ff225194f338519a4856f24b1196ded583ff51af Mon Sep 17 00:00:00 2001 From: Vincent Sanders Date: Sun, 7 Feb 2021 00:07:24 +0000 Subject: [PATCH] use list style formatting from libcss --- content/handlers/html/Makefile | 1 - content/handlers/html/box_construct.c | 47 +- content/handlers/html/list_counter_style.c | 555 --------------------- content/handlers/html/list_counter_style.h | 45 -- 4 files changed, 29 insertions(+), 619 deletions(-) delete mode 100644 content/handlers/html/list_counter_style.c delete mode 100644 content/handlers/html/list_counter_style.h diff --git a/content/handlers/html/Makefile b/content/handlers/html/Makefile index 968c96feb..8bb329b76 100644 --- a/content/handlers/html/Makefile +++ b/content/handlers/html/Makefile @@ -16,7 +16,6 @@ S_HTML := box_construct.c \ imagemap.c \ interaction.c \ layout.c \ - list_counter_style.c \ object.c \ redraw.c \ redraw_border.c \ diff --git a/content/handlers/html/box_construct.c b/content/handlers/html/box_construct.c index 6c6fc2400..a13357809 100644 --- a/content/handlers/html/box_construct.c +++ b/content/handlers/html/box_construct.c @@ -47,7 +47,6 @@ #include "html/box_special.h" #include "html/box_normalise.h" #include "html/form_internal.h" -#include "html/list_counter_style.h" /** * Context for box tree construction @@ -424,6 +423,7 @@ box_construct_marker(struct box *box, 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); @@ -467,25 +467,36 @@ box_construct_marker(struct box *box, return false; } - counter_len = list_counter_style_value(marker->text, - LIST_MARKER_SIZE, - list_style_type, - marker->rows); - if (counter_len > LIST_MARKER_SIZE) { - /* use computed size as marker did not fit allocation */ - marker->text = talloc_realloc(ctx->bctx, - marker->text, - char, - counter_len); - if (marker->text == NULL) { - return false; - } - counter_len = list_counter_style_value(marker->text, + 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, - list_style_type, - marker->rows); + &counter_len); + } + marker->length = counter_len; + } else { + /* failed to format marker so use none type */ + marker->text = NULL; + marker->length = 0; } - marker->length = counter_len; break; } diff --git a/content/handlers/html/list_counter_style.c b/content/handlers/html/list_counter_style.c deleted file mode 100644 index 81d9aa3d3..000000000 --- a/content/handlers/html/list_counter_style.c +++ /dev/null @@ -1,555 +0,0 @@ -/* - * Copyright 2021 Vincent Sanders - * - * This file is part of NetSurf, http://www.netsurf-browser.org/ - * - * NetSurf is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * NetSurf is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * \file - * Implementation of css list counter styling - */ - -#include - -#include "css/select.h" - -#include "html/list_counter_style.h" - - -#define SYMBOL_SIZE 4 -typedef char symbol_t[SYMBOL_SIZE]; - -struct list_counter_style { - const char *name; /**< style name for debug purposes */ - struct { - const int start; /**< first acceptable value for this style */ - const int end; /**< last acceptable value for this style */ - } range; - struct { - const unsigned int length; - const symbol_t value; - } pad; - const char *prefix; - const char *postfix; - const symbol_t *symbols; /**< array of symbols which represent this style */ - const int *weights; /**< symbol weights for additive schemes */ - const size_t items; /**< items in symbol and weight table */ - size_t (*calc)(uint8_t *ares, const size_t alen, int value, const struct list_counter_style *cstyle); /**< function to calculate the system */ -}; - -/** - * Copy a null-terminated UTF-8 string to buffer at offset, if there is space - * - * \param[in] buf The output buffer - * \param[in] buflen The length of \a buf - * \param[in] pos Current position in \a buf - * \param[in] str The string to copy into \a buf - * \return The number of bytes needed in the output buffer which may be - * larger than \a buflen but the buffer will not be overrun - */ -static inline size_t -copy_string(char *buf, const size_t buflen, size_t pos, const char *str) -{ - size_t sidx = 0; /* current string index */ - - while (str[sidx] != '\0') { - if (pos < buflen) { - buf[pos] = str[sidx]; - } - pos++; - sidx++; - } - - return sidx; -} - -/** - * Copy a UTF-8 symbol to buffer at offset, if there is space - * - * \param[in] buf The output buffer - * \param[in] buflen The length of \a buf - * \param[in] pos Current position in \a buf - * \param[in] symbol The symbol to copy into \a buf - * \return The number of bytes needed in the output buffer which may be - * larger than \a buflen but the buffer will not be overrun - */ -static inline size_t -copy_symbol(char *buf, const size_t buflen, size_t pos, const symbol_t symbol) -{ - size_t sidx = 0; /* current symbol index */ - - while ((sidx < sizeof(symbol_t)) && (symbol[sidx] != '\0')) { - if (pos < buflen) { - buf[pos] = symbol[sidx]; - } - pos++; - sidx++; - } - - return sidx; -} - -/** - * maps alphabet values to output values with a symbol table - * - * Takes a list of alphabet values and for each one outputs the - * compete symbol (in utf8) to an output buffer. - * - * \param buf The oputput buffer - * \param buflen the length of \a buf - * \param aval array of alphabet values - * \param alen The number of values in \a alen - * \param symtab The symbol table - * \param symtablen The number of symbols in \a symtab - * \return The number of bytes needed in the output buffer whichmay be - * larger than \a buflen but the buffer will not be overrun - */ -static size_t -map_aval_to_symbols(char *buf, const size_t buflen, - const uint8_t *aval, const size_t alen, - const struct list_counter_style *cstyle) -{ - size_t oidx = 0; - size_t aidx; /* numeral index */ - const symbol_t postfix = "."; /* default postfix string */ - - /* add padding if required */ - if (alen < cstyle->pad.length) { - size_t pidx; /* padding index */ - for (pidx=cstyle->pad.length - alen; pidx > 0; pidx--) { - oidx += copy_symbol(buf, buflen, oidx, - cstyle->pad.value); - } - } - - /* map symbols */ - for (aidx=0; aidx < alen; aidx++) { - oidx += copy_symbol(buf, buflen, oidx, - cstyle->symbols[aval[aidx]]); - } - - /* postfix */ - oidx += copy_string(buf, buflen, oidx, - (cstyle->postfix != NULL) ? - cstyle->postfix : postfix); - - return oidx; -} - - -/** - * generate numeric symbol values - * - * fills array with numeric values that represent the input value - * - * \param ares Buffer to recive the converted values - * \param alen the length of \a ares buffer - * \param value The value to convert - * \param slen The number of symbols in the alphabet - * \return The length a complete conversion which may be larger than \a alen - */ -static size_t -calc_numeric_system(uint8_t *ares, - const size_t alen, - int value, - const struct list_counter_style *cstyle) -{ - size_t idx = 0; - uint8_t *first; - uint8_t *last; - - /* generate alphabet values in ascending order */ - while (value > 0) { - if (idx < alen) { - ares[idx] = value % cstyle->items; - } - idx++; - value = value / cstyle->items; - } - - /* put the values in decending order */ - first = ares; - if (idx < alen) { - last = first + (idx - 1); - } else { - last = first + (alen - 1); - } - while (first < last) { - *first ^= *last; - *last ^= *first; - *first ^= *last; - first++; - last--; - } - - return idx; -} - - -/** - * generate addative symbol values - * - * fills array with numeric values that represent the input value - * - * \param ares Buffer to recive the converted values - * \param alen the length of \a ares buffer - * \param value The value to convert - * \param wlen The number of weights - * \return The length a complete conversion which may be larger than \a alen - */ -static size_t -calc_additive_system(uint8_t *ares, - const size_t alen, - int value, - const struct list_counter_style *cstyle) -{ - size_t widx; /* weight index */ - size_t aidx = 0; - size_t idx; - size_t times; /* number of times a weight occours */ - - /* iterate over the available weights */ - for (widx = 0; widx < cstyle->items;widx++) { - times = value / cstyle->weights[widx]; - if (times > 0) { - for (idx=0;idx < times;idx++) { - if (aidx < alen) { - ares[aidx] = widx; - } - aidx++; - } - - value -= times * cstyle->weights[widx]; - } - } - - return aidx; -} - - -/** - * generate alphabet symbol values for latin and greek labelling - * - * fills array with alphabet values suitable for the input value - * - * \param ares Buffer to recive the converted values - * \param alen the length of \a ares buffer - * \param value The value to convert - * \param slen The number of symbols in the alphabet - * \return The length a complete conversion which may be larger than \a alen - */ -static size_t -calc_alphabet_system(uint8_t *ares, - const size_t alen, - int value, - const struct list_counter_style *cstyle) -{ - size_t idx = 0; - uint8_t *first; - uint8_t *last; - - /* generate alphabet values in ascending order */ - while (value > 0) { - --value; - if (idx < alen) { - ares[idx] = value % cstyle->items; - } - idx++; - value = value / cstyle->items; - } - - /* put the values in decending order */ - first = ares; - if (idx < alen) { - last = first + (idx - 1); - } else { - last = first + (alen - 1); - } - while (first < last) { - *first ^= *last; - *last ^= *first; - *first ^= *last; - first++; - last--; - } - - return idx; -} - - -/** - * Roman numeral conversion - * - * \return The number of numerals that are nesesary for full output - */ -static size_t -calc_roman_system(uint8_t *buf, - const size_t maxlen, - int value, - const struct list_counter_style *cstyle) -{ - const int S[] = { 0, 2, 4, 2, 4, 2, 4 }; - const int D[] = { 1000, 500, 100, 50, 10, 5, 1 }; - const size_t L = sizeof(D) / sizeof(int) - 1; - size_t k = 0; /* index into output buffer */ - unsigned int i = 0; /* index into maps */ - int r, r2; - - assert(cstyle->items == 7); - - while (value > 0) { - if (D[i] <= value) { - r = value / D[i]; - value = value - (r * D[i]); - if (i < L) { - /* lookahead */ - r2 = value / D[i+1]; - } - if (i < L && r2 >= S[i+1]) { - /* will violate repeat boundary on next pass */ - value = value - (r2 * D[i+1]); - if (k < maxlen) buf[k++] = i+1; - if (k < maxlen) buf[k++] = i-1; - } else if (S[i] && r >= S[i]) { - /* violated repeat boundary on this pass */ - if (k < maxlen) buf[k++] = i; - if (k < maxlen) buf[k++] = i-1; - } else { - while (r-- > 0 && k < maxlen) { - buf[k++] = i; - } - } - } - i++; - } - if (k < maxlen) { - buf[k] = '\0'; - } - return k; -} - - -/* tables for all the counter styles */ - - -static const symbol_t georgian_symbols[] = { - "ჵ", - "ჰ", "ჯ", "ჴ", "ხ", "ჭ", "წ", "ძ", "ც", "ჩ", - "შ", "ყ", "ღ", "ქ", "ფ", "ჳ", "ტ", "ს", "რ", - "ჟ", "პ", "ო", "ჲ", "ნ", "მ", "ლ", "კ", "ი", - "თ", "ჱ", "ზ", "ვ", "ე", "დ", "გ", "ბ", "ა", -}; -static const int georgian_weights[] = { - 10000, - 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000, - 900, 800, 700, 600, 500, 400, 300, 200, 100, - 90, 80, 70, 60, 50, 40, 30, 20, 10, - 9, 8, 7, 6, 5, 4, 3, 2, 1 -}; -static struct list_counter_style lcs_georgian = { - .name="georgian", - .range.start = 1, - .range.end = 19999, - .symbols = georgian_symbols, - .weights = georgian_weights, - .items = (sizeof(georgian_symbols) / SYMBOL_SIZE), - .calc = calc_additive_system, -}; - - -static const symbol_t armenian_symbols[] = { - "Ք", "Փ", "Ւ", "Ց", "Ր", "Տ", "Վ", "Ս", "Ռ", - "Ջ", "Պ", "Չ", "Ո", "Շ", "Ն", "Յ", "Մ", "Ճ", - "Ղ", "Ձ", "Հ", "Կ", "Ծ", "Խ", "Լ", "Ի", "Ժ", - "Թ", "Ը", "Է", "Զ", "Ե", "Դ", "Գ", "Բ", "Ա" -}; -static const int armenian_weights[] = { - 9000, 8000, 7000, 6000, 5000, 4000, 3000, 2000, 1000, - 900, 800, 700, 600, 500, 400, 300, 200, 100, - 90, 80, 70, 60, 50, 40, 30, 20, 10, - 9, 8, 7, 6, 5, 4, 3, 2, 1 -}; -static struct list_counter_style lcs_armenian = { - .name = "armenian", - .range.start = 1, - .range.end = 9999, - .symbols = armenian_symbols, - .weights = armenian_weights, - .items = (sizeof(armenian_symbols) / SYMBOL_SIZE), - .calc = calc_additive_system, -}; - - -static const symbol_t decimal_symbols[] = { - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" -}; -static struct list_counter_style lcs_decimal = { - .name = "decimal", - .symbols = decimal_symbols, - .items = (sizeof(decimal_symbols) / SYMBOL_SIZE), - .calc = calc_numeric_system, -}; - - -static struct list_counter_style lcs_decimal_leading_zero = { - .name = "decimal-leading-zero", - .pad.length = 2, - .pad.value = "0", - .symbols = decimal_symbols, - .items = (sizeof(decimal_symbols) / SYMBOL_SIZE), - .calc = calc_numeric_system, -}; - - -static const symbol_t lower_greek_symbols[] = { - "α", "β", "γ", "δ", "ε", "ζ", "η", "θ", "ι", "κ", - "λ", "μ", "ν", "ξ", "ο", "π", "ρ", "σ", "τ", "υ", - "φ", "χ", "ψ", "ω" -}; -static struct list_counter_style lcs_lower_greek = { - .name="lower-greek", - .symbols = lower_greek_symbols, - .items = (sizeof(lower_greek_symbols) / SYMBOL_SIZE), - .calc = calc_alphabet_system, -}; - - -static const symbol_t upper_alpha_symbols[] = { - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", - "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", - "U", "V", "W", "X", "Y", "Z" -}; -static struct list_counter_style lcs_upper_alpha = { - .name="upper-alpha", - .symbols = upper_alpha_symbols, - .items = (sizeof(upper_alpha_symbols) / SYMBOL_SIZE), - .calc = calc_alphabet_system, -}; - - -static const symbol_t lower_alpha_symbols[] = { - "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", - "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", - "u", "v", "w", "x", "y", "z" -}; -static struct list_counter_style lcs_lower_alpha = { - .name="lower-alpha", - .symbols = lower_alpha_symbols, - .items = (sizeof(lower_alpha_symbols) / SYMBOL_SIZE), - .calc = calc_alphabet_system, -}; - - -static const symbol_t upper_roman_symbols[] = { - "M", "D", "C", "L", "X", "V", "I" -}; -static struct list_counter_style lcs_upper_roman = { - .name="upper-roman", - .symbols = upper_roman_symbols, - .items = (sizeof(upper_roman_symbols) / SYMBOL_SIZE), - .calc = calc_roman_system, -}; - - -static const symbol_t lower_roman_symbols[] = { - "m", "d", "c", "l", "x", "v", "i" -}; -static struct list_counter_style lcs_lower_roman = { - .name="lower-roman", - .symbols = lower_roman_symbols, - .items = (sizeof(lower_roman_symbols) / SYMBOL_SIZE), - .calc = calc_roman_system, -}; - -#if 0 -static const symbol_t lower_hexidecimal_symbols[] = { - "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", - "a", "b", "c", "d", "e", "f" -}; -static struct list_counter_style lcs_lower_hexidecimal = { - .name="lower_hexidecimal", - .symbols = lower_hexidecimal_symbols, - .items = (sizeof(lower_hexidecimal_symbols) / SYMBOL_SIZE), - .calc = calc_numeric_system, -}; -#endif - - -/* exported interface defined in html/list_counter_style.h */ -size_t -list_counter_style_value(char *text, - size_t text_len, - enum css_list_style_type_e list_style_type, - int value) -{ - size_t alen; - uint8_t aval[20]; - struct list_counter_style *cstyle; - - switch (list_style_type) { - case CSS_LIST_STYLE_TYPE_DECIMAL_LEADING_ZERO: - cstyle = &lcs_decimal_leading_zero; - break; - - case CSS_LIST_STYLE_TYPE_LOWER_ROMAN: - cstyle = &lcs_lower_roman; - break; - - case CSS_LIST_STYLE_TYPE_UPPER_ROMAN: - cstyle = &lcs_upper_roman; - break; - - case CSS_LIST_STYLE_TYPE_LOWER_ALPHA: - case CSS_LIST_STYLE_TYPE_LOWER_LATIN: - cstyle = &lcs_lower_alpha; - break; - - case CSS_LIST_STYLE_TYPE_UPPER_ALPHA: - case CSS_LIST_STYLE_TYPE_UPPER_LATIN: - cstyle = &lcs_upper_alpha; - break; - - case CSS_LIST_STYLE_TYPE_LOWER_GREEK: - cstyle = &lcs_lower_greek; - break; - - case CSS_LIST_STYLE_TYPE_ARMENIAN: - cstyle = &lcs_armenian; - break; - - case CSS_LIST_STYLE_TYPE_GEORGIAN: - cstyle = &lcs_georgian; - break; - - case CSS_LIST_STYLE_TYPE_DECIMAL: - default: - cstyle = &lcs_decimal; - break; - } - - alen = cstyle->calc(aval, sizeof(aval), value, cstyle); - - /* ensure it is possible to calculate with the selected system */ - if ((alen == 0) || (alen >= sizeof(aval))) { - /* retry in decimal */ - alen = lcs_decimal.calc(aval, sizeof(aval), value, &lcs_decimal); - if ((alen == 0) || (alen >= sizeof(aval))) { - /* failed in decimal, give up */ - return 0; - } - } - - return map_aval_to_symbols(text, text_len, aval, alen, cstyle); -} diff --git a/content/handlers/html/list_counter_style.h b/content/handlers/html/list_counter_style.h deleted file mode 100644 index 2b1e79ab9..000000000 --- a/content/handlers/html/list_counter_style.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2021 Vincent Sanders - * - * This file is part of NetSurf, http://www.netsurf-browser.org/ - * - * NetSurf is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * NetSurf is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -/** - * \file - * List counter style handling - * - * These functions provide font related services. They all work on - * UTF-8 strings with lengths given. - */ - -#ifndef NETSURF_HTML_LIST_COUNTER_STYLE_H -#define NETSURF_HTML_LIST_COUNTER_STYLE_H - -/** - * format value into a list marker with a style - * - * \param text buffer to recive the result - * \param text_len The length of the \a text buffer - * \param list_style_type the css list style. - * \param value The value to format. - * \return The length of the complete output which may exceed \a text_len - */ -size_t -list_counter_style_value(char *text, - size_t text_len, - enum css_list_style_type_e list_style_type, - int value); - -#endif