From 52ed5832db9ea4bcc9dcfd2f0391af89f5aadd95 Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Wed, 27 Jan 2016 15:19:58 +0100 Subject: Add fallback font cache to font context. --- source/fitz/font.c | 125 +++++++++++++++++++++++++++++++++++++++------- source/html/html-font.c | 39 --------------- source/html/html-layout.c | 19 +++---- 3 files changed, 118 insertions(+), 65 deletions(-) (limited to 'source') diff --git a/source/fitz/font.c b/source/fitz/font.c index 792e8d95..a7db05d4 100644 --- a/source/fitz/font.c +++ b/source/fitz/font.c @@ -178,12 +178,18 @@ fz_set_font_bbox(fz_context *ctx, fz_font *font, float xmin, float ymin, float x * Freetype hooks */ -struct fz_font_context_s { +struct fz_font_context_s +{ int ctx_refs; FT_Library ftlib; int ftlib_refs; fz_load_system_font_func load_font; fz_load_system_cjk_font_func load_cjk_font; + + /* Cached fallback fonts */ + struct { fz_font *serif, *sans; } fallback[256]; + fz_font *symbol; + fz_font *emoji; }; #undef __FTERRORS_H__ @@ -216,8 +222,19 @@ fz_keep_font_context(fz_context *ctx) void fz_drop_font_context(fz_context *ctx) { + int i; + if (!ctx) return; + + for (i = 0; i < nelem(ctx->font->fallback); ++i) + { + fz_drop_font(ctx, ctx->font->fallback[i].serif); + fz_drop_font(ctx, ctx->font->fallback[i].sans); + } + fz_drop_font(ctx, ctx->font->symbol); + fz_drop_font(ctx, ctx->font->emoji); + if (fz_drop_imp(ctx, ctx->font, &ctx->font->ctx_refs)) fz_free(ctx, ctx->font); } @@ -266,6 +283,66 @@ fz_font *fz_load_system_cjk_font(fz_context *ctx, const char *name, int ros, int return font; } +fz_font *fz_load_fallback_font(fz_context *ctx, int script, int serif, int bold, int italic) +{ + unsigned char *data; + unsigned int size; + + if (script < 0 || script > nelem(ctx->font->fallback)) + return NULL; + + /* TODO: bold and italic */ + + if (serif) + { + if (ctx->font->fallback[script].serif) + return ctx->font->fallback[script].serif; + data = fz_lookup_noto_font(ctx, script, 1, &size); + if (data) + { + ctx->font->fallback[script].serif = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0); + return ctx->font->fallback[script].serif; + } + } + + if (ctx->font->fallback[script].sans) + return ctx->font->fallback[script].sans; + data = fz_lookup_noto_font(ctx, script, 0, &size); + if (data) + { + ctx->font->fallback[script].sans = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0); + return ctx->font->fallback[script].sans; + } + + return NULL; +} + +fz_font *fz_load_fallback_symbol_font(fz_context *ctx) +{ + unsigned char *data; + unsigned int size; + if (!ctx->font->symbol) + { + data = fz_lookup_noto_symbol_font(ctx, &size); + if (data) + ctx->font->symbol = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0); + } + return ctx->font->symbol; +} + +fz_font *fz_load_fallback_emoji_font(fz_context *ctx) +{ + unsigned char *data; + unsigned int size; + if (!ctx->font->emoji) + { + data = fz_lookup_noto_emoji_font(ctx, &size); + if (data) + ctx->font->emoji = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0); + } + return ctx->font->emoji; +} + static const struct ft_error ft_errors[] = { #include FT_ERRORS_H @@ -1366,31 +1443,45 @@ fz_encode_character(fz_context *ctx, fz_font *font, int ucs) } int -fz_encode_character_with_fallback(fz_context *ctx, fz_font *first_font, int ucs, fz_font **out_font) +fz_encode_character_with_fallback(fz_context *ctx, fz_font *user_font, int unicode, int script, fz_font **out_font) { fz_font *font; + int gid; + + gid = fz_encode_character(ctx, user_font, unicode); + if (gid > 0) + return *out_font = user_font, gid; - for (font = first_font; font; font = font->fallback) + if (script == 0) + script = ucdn_get_script(unicode); + + font = fz_load_fallback_font(ctx, script, 0, 0, 0); + if (font) { - int gid = fz_encode_character(ctx, font, ucs); + gid = fz_encode_character(ctx, font, unicode); if (gid > 0) - { - *out_font = font; - return gid; - } + return *out_font = font, gid; } - ucs = 0x25CF; /* bullet */ - for (font = first_font; font; font = font->fallback) + font = fz_load_fallback_symbol_font(ctx); + if (font) { - int gid = fz_encode_character(ctx, font, ucs); + gid = fz_encode_character(ctx, font, unicode); if (gid > 0) - { - *out_font = font; - return gid; - } + return *out_font = font, gid; } - *out_font = first_font; - return 0; + font = fz_load_fallback_emoji_font(ctx); + if (font) + { + gid = fz_encode_character(ctx, font, unicode); + if (gid > 0) + return *out_font = font, gid; + } + + /* bullet */ + if (unicode != 0x25CF) + return fz_encode_character_with_fallback(ctx, user_font, 0x25CF, UCDN_SCRIPT_LATIN, out_font); + + return *out_font = user_font, 0; } diff --git a/source/html/html-font.c b/source/html/html-font.c index bca1625e..bb356d6c 100644 --- a/source/html/html-font.c +++ b/source/html/html-font.c @@ -8,41 +8,6 @@ static const char *font_names[16] = "Courier", "Courier-Oblique", "Courier-Bold", "Courier-BoldOblique", }; -static fz_font * -fz_load_html_fallback_font(fz_context *ctx, fz_html_font_set *set) -{ - fz_font *font; - - /* TODO: Use set->fallback[script] instead of font->fallback chain */ - if (!set->fallback) - { - unsigned char *data; - unsigned int size; - int script; - - data = fz_lookup_noto_symbol_font(ctx, &size); - if (data) - { - font = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0); - font->fallback = set->fallback; - set->fallback = font; - } - - for (script = UCDN_SCRIPT_LATIN; script < UCDN_SCRIPT_SIGNWRITING; ++script) - { - data = fz_lookup_noto_font(ctx, script, 1, &size); - if (data) - { - font = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0); - font->fallback = set->fallback; - set->fallback = font; - } - } - } - - return set->fallback; -} - fz_font * fz_load_html_builtin_font(fz_context *ctx, fz_html_font_set *set, const char *family, int is_bold, int is_italic) { @@ -58,7 +23,6 @@ fz_load_html_builtin_font(fz_context *ctx, fz_html_font_set *set, const char *fa if (!data) fz_throw(ctx, FZ_ERROR_GENERIC, "cannot load html font: %s", font_names[idx]); set->fonts[idx] = fz_new_font_from_memory(ctx, font_names[idx], data, size, 0, 1); - set->fonts[idx]->fallback = fz_load_html_fallback_font(ctx, set); } return set->fonts[idx]; } @@ -101,8 +65,6 @@ fz_add_html_font_face(fz_context *ctx, fz_html_font_set *set, custom->is_italic = is_italic; custom->next = set->custom; set->custom = custom; - - font->fallback = fz_load_html_builtin_font(ctx, set, family, is_bold, is_italic); } fz_html_font_set *fz_new_html_font_set(fz_context *ctx) @@ -128,7 +90,6 @@ void fz_drop_html_font_set(fz_context *ctx, fz_html_font_set *set) for (i = 0; i < nelem(set->fonts); ++i) fz_drop_font(ctx, set->fonts[i]); - fz_drop_font(ctx, set->fallback); fz_free(ctx, set); } diff --git a/source/html/html-layout.c b/source/html/html-layout.c index 24edc567..3f6fe919 100644 --- a/source/html/html-layout.c +++ b/source/html/html-layout.c @@ -553,7 +553,7 @@ static void measure_word(fz_context *ctx, fz_html_flow *node, float em) while (*s) { s += fz_chartorune(&c, s); - g = fz_encode_character_with_fallback(ctx, node->style->font, c, &font); + g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font); w += fz_advance_glyph(ctx, font, g) * em; } node->w = w; @@ -931,6 +931,7 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p /* TODO: reuse text object if color is unchanged */ text = fz_new_text(ctx); + trm.e = node->x; trm.f = node->y; s = node->content.text; @@ -944,7 +945,7 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p t += fz_chartorune(&c, t); if (node->mirror) c = ucdn_mirror(c); - g = fz_encode_character_with_fallback(ctx, node->style->font, c, &font); + g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font); w += fz_advance_glyph(ctx, font, g) * node->em; } @@ -954,7 +955,7 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p s += fz_chartorune(&c, s); if (node->mirror) c = ucdn_mirror(c); - g = fz_encode_character_with_fallback(ctx, node->style->font, c, &font); + g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font); trm.e -= fz_advance_glyph(ctx, font, g) * node->em; if (node->style->visibility == V_VISIBLE) fz_add_text(ctx, text, font, 0, &trm, g, c); @@ -966,7 +967,7 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p while (*s) { s += fz_chartorune(&c, s); - g = fz_encode_character_with_fallback(ctx, node->style->font, c, &font); + g = fz_encode_character_with_fallback(ctx, node->style->font, c, 0, &font); if (node->style->visibility == V_VISIBLE) fz_add_text(ctx, text, font, 0, &trm, g, c); trm.e += fz_advance_glyph(ctx, font, g) * node->em; @@ -1154,8 +1155,8 @@ static void draw_list_mark(fz_context *ctx, fz_html *box, float page_top, float while (*s) { s += fz_chartorune(&c, s); - g = fz_encode_character_with_fallback(ctx, box->style.font, c, &font); - w += fz_advance_glyph(ctx, box->style.font, g) * box->em; + g = fz_encode_character_with_fallback(ctx, box->style.font, c, UCDN_SCRIPT_LATIN, &font); + w += fz_advance_glyph(ctx, font, g) * box->em; } s = buf; @@ -1164,9 +1165,9 @@ static void draw_list_mark(fz_context *ctx, fz_html *box, float page_top, float while (*s) { s += fz_chartorune(&c, s); - g = fz_encode_character(ctx, box->style.font, c); - fz_add_text(ctx, text, box->style.font, 0, &trm, g, c); - trm.e += fz_advance_glyph(ctx, box->style.font, g) * box->em; + g = fz_encode_character_with_fallback(ctx, box->style.font, c, UCDN_SCRIPT_LATIN, &font); + fz_add_text(ctx, text, font, 0, &trm, g, c); + trm.e += fz_advance_glyph(ctx, font, g) * box->em; } color[0] = box->style.color.r / 255.0f; -- cgit v1.2.3