diff options
Diffstat (limited to 'source/html')
-rw-r--r-- | source/html/css-apply.c | 12 | ||||
-rw-r--r-- | source/html/html-layout.c | 97 |
2 files changed, 97 insertions, 12 deletions
diff --git a/source/html/css-apply.c b/source/html/css-apply.c index 98818239..40cae696 100644 --- a/source/html/css-apply.c +++ b/source/html/css-apply.c @@ -78,6 +78,7 @@ static const char *list_style_type_kw[] = { "none", "square", "upper-alpha", + "upper-greek", "upper-latin", "upper-roman", }; @@ -884,6 +885,17 @@ fz_apply_css_style(fz_context *ctx, fz_html_font_set *set, fz_css_style *style, else if (!strcmp(value->data, "circle")) style->list_style_type = LST_CIRCLE; else if (!strcmp(value->data, "square")) style->list_style_type = LST_SQUARE; else if (!strcmp(value->data, "decimal")) style->list_style_type = LST_DECIMAL; + else if (!strcmp(value->data, "decimal-leading-zero")) style->list_style_type = LST_DECIMAL_ZERO; + else if (!strcmp(value->data, "lower-roman")) style->list_style_type = LST_LC_ROMAN; + else if (!strcmp(value->data, "upper-roman")) style->list_style_type = LST_UC_ROMAN; + else if (!strcmp(value->data, "lower-greek")) style->list_style_type = LST_LC_GREEK; + else if (!strcmp(value->data, "upper-greek")) style->list_style_type = LST_UC_GREEK; + else if (!strcmp(value->data, "lower-latin")) style->list_style_type = LST_LC_LATIN; + else if (!strcmp(value->data, "upper-latin")) style->list_style_type = LST_UC_LATIN; + else if (!strcmp(value->data, "lower-alpha")) style->list_style_type = LST_LC_ALPHA; + else if (!strcmp(value->data, "upper-alpha")) style->list_style_type = LST_UC_ALPHA; + else if (!strcmp(value->data, "armenian")) style->list_style_type = LST_ARMENIAN; + else if (!strcmp(value->data, "georgian")) style->list_style_type = LST_GEORGIAN; } style->line_height = number_from_property(match, "line-height", 1.2f, N_SCALE); diff --git a/source/html/html-layout.c b/source/html/html-layout.c index 7231205f..d8c30506 100644 --- a/source/html/html-layout.c +++ b/source/html/html-layout.c @@ -760,13 +760,91 @@ static void draw_rect(fz_context *ctx, fz_device *dev, const fz_matrix *ctm, flo fz_drop_path(ctx, path); } +static const char *roman_uc[3][10] = { + { "", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX" }, + { "", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC" }, + { "", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM" }, +}; + +static const char *roman_lc[3][10] = { + { "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" }, + { "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" }, + { "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" }, +}; + +static void format_roman_number(fz_context *ctx, char *buf, int size, int n, const char *sym[3][10], const char *sym_m) +{ + int I = n % 10; + int X = (n / 10) % 10; + int C = (n / 100) % 100; + int M = (n / 1000); + + fz_strlcpy(buf, "", size); + while (M--) + fz_strlcat(buf, sym_m, size); + fz_strlcat(buf, sym[2][C], size); + fz_strlcat(buf, sym[1][X], size); + fz_strlcat(buf, sym[0][I], size); + fz_strlcat(buf, ". ", size); +} + +static void format_alpha_number(fz_context *ctx, char *buf, int size, int n, int alpha, int omega) +{ + int base = omega - alpha + 1; + int tmp[40]; + int i, c; + + if (alpha > 256) /* to skip final-s for greek */ + --base; + + /* Bijective base-26 (base-24 for greek) numeration */ + i = 0; + while (n > 0) + { + --n; + c = n % base + alpha; + if (alpha > 256 && c > alpha + 16) /* skip final-s for greek */ + ++c; + tmp[i++] = c; + n /= base; + } + + while (i > 0) + buf += fz_runetochar(buf, tmp[--i]); + *buf++ = '.'; + *buf++ = ' '; + *buf = 0; +} + +static void format_list_number(fz_context *ctx, int type, int x, char *buf, int size) +{ + switch (type) + { + case LST_NONE: fz_strlcpy(buf, "", size); break; + case LST_DISC: fz_strlcpy(buf, "\342\227\217 ", size); break; /* U+25CF BLACK CIRCLE */ + case LST_CIRCLE: fz_strlcpy(buf, "\342\227\213 ", size); break; /* U+25CB WHITE CIRCLE */ + case LST_SQUARE: fz_strlcpy(buf, "\342\226\240 ", size); break; /* U+25A0 BLACK SQUARE */ + default: + case LST_DECIMAL: fz_snprintf(buf, size, "%d. ", x); break; + case LST_DECIMAL_ZERO: fz_snprintf(buf, size, "%02d. ", x); break; + case LST_LC_ROMAN: format_roman_number(ctx, buf, size, x, roman_lc, "m"); break; + case LST_UC_ROMAN: format_roman_number(ctx, buf, size, x, roman_uc, "M"); break; + case LST_LC_ALPHA: format_alpha_number(ctx, buf, size, x, 'a', 'z'); break; + case LST_UC_ALPHA: format_alpha_number(ctx, buf, size, x, 'A', 'Z'); break; + case LST_LC_LATIN: format_alpha_number(ctx, buf, size, x, 'a', 'z'); break; + case LST_UC_LATIN: format_alpha_number(ctx, buf, size, x, 'A', 'Z'); break; + case LST_LC_GREEK: format_alpha_number(ctx, buf, size, x, 0x03B1, 0x03C9); break; + case LST_UC_GREEK: format_alpha_number(ctx, buf, size, x, 0x0391, 0x03A9); break; + } +} + static void draw_list_mark(fz_context *ctx, fz_html *box, float page_top, float page_bot, fz_device *dev, const fz_matrix *ctm, int n) { fz_text *text; fz_matrix trm; float x, y, w, baseline; float color[3]; - const char *s, *p; + const char *s; char buf[40]; int c, g; @@ -774,17 +852,12 @@ static void draw_list_mark(fz_context *ctx, fz_html *box, float page_top, float text = fz_new_text(ctx, box->style.font, &trm, 0); baseline = box->em * 0.8 + (box->h - box->em) / 2; - switch (box->style.list_style_type) - { - default: - case LST_DISC: p = "\342\227\217 "; break; /* U+25CF BLACK CIRCLE */ - case LST_CIRCLE: p = "\342\227\213 "; break; /* U+25CB WHITE CIRCLE */ - case LST_SQUARE: p = "\342\226\240 "; break; /* U+25A0 BLACK SQUARE */ - case LST_DECIMAL: p = buf; fz_snprintf(buf, sizeof buf, "%d. ", n); break; - case LST_NONE: p = ""; break; - } + if (box->y + baseline > page_bot || box->y + baseline < page_top) + return; + + format_list_number(ctx, box->style.list_style_type, n, buf, sizeof buf); - s = p; + s = buf; w = 0; while (*s) { @@ -793,7 +866,7 @@ static void draw_list_mark(fz_context *ctx, fz_html *box, float page_top, float w += fz_advance_glyph(ctx, box->style.font, g) * box->em; } - s = p; + s = buf; x = box->x - box->padding[L] - box->border[L] - box->margin[L] - w; y = box->y + baseline; while (*s) |