summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-01-27 15:19:58 +0100
committerRobin Watts <robin.watts@artifex.com>2016-01-28 20:09:55 +0000
commit52ed5832db9ea4bcc9dcfd2f0391af89f5aadd95 (patch)
tree11f8c2460b8880f10b3baa048ad7e22a549b6f5c /source
parentafbb36f359273f272e23fc1e22fcdc6a0cc587de (diff)
downloadmupdf-52ed5832db9ea4bcc9dcfd2f0391af89f5aadd95.tar.xz
Add fallback font cache to font context.
Diffstat (limited to 'source')
-rw-r--r--source/fitz/font.c125
-rw-r--r--source/html/html-font.c39
-rw-r--r--source/html/html-layout.c19
3 files changed, 118 insertions, 65 deletions
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;