1 #include "mupdf/fitz.h"
2 #include "html-imp.h"
3 
4 #include <string.h>
5 
6 static fz_font *
fz_load_html_default_font(fz_context * ctx,fz_html_font_set * set,const char * family,int is_bold,int is_italic)7 fz_load_html_default_font(fz_context *ctx, fz_html_font_set *set, const char *family, int is_bold, int is_italic)
8 {
9 	int is_mono = !strcmp(family, "monospace");
10 	int is_sans = !strcmp(family, "sans-serif");
11 	const char *real_family = is_mono ? "Courier" : is_sans ? "Helvetica" : "Charis SIL";
12 	const char *backup_family = is_mono ? "Courier" : is_sans ? "Helvetica" : "Times";
13 	int idx = (is_mono ? 8 : is_sans ? 4 : 0) + is_bold * 2 + is_italic;
14 	if (!set->fonts[idx])
15 	{
16 		const unsigned char *data;
17 		int size;
18 
19 		data = fz_lookup_builtin_font(ctx, real_family, is_bold, is_italic, &size);
20 		if (!data)
21 			data = fz_lookup_builtin_font(ctx, backup_family, is_bold, is_italic, &size);
22 		if (!data)
23 			fz_throw(ctx, FZ_ERROR_GENERIC, "cannot load html font: %s", real_family);
24 		set->fonts[idx] = fz_new_font_from_memory(ctx, NULL, data, size, 0, 1);
25 		fz_font_flags(set->fonts[idx])->is_serif = !is_sans;
26 	}
27 	return set->fonts[idx];
28 }
29 
30 void
fz_add_html_font_face(fz_context * ctx,fz_html_font_set * set,const char * family,int is_bold,int is_italic,int is_small_caps,const char * src,fz_font * font)31 fz_add_html_font_face(fz_context *ctx, fz_html_font_set *set,
32 	const char *family, int is_bold, int is_italic, int is_small_caps,
33 	const char *src, fz_font *font)
34 {
35 	fz_html_font_face *custom = fz_malloc_struct(ctx, fz_html_font_face);
36 	custom->font = fz_keep_font(ctx, font);
37 	custom->src = fz_strdup(ctx, src);
38 	custom->family = fz_strdup(ctx, family);
39 	custom->is_bold = is_bold;
40 	custom->is_italic = is_italic;
41 	custom->is_small_caps = is_small_caps;
42 	custom->next = set->custom;
43 	set->custom = custom;
44 }
45 
46 fz_font *
fz_load_html_font(fz_context * ctx,fz_html_font_set * set,const char * family,int is_bold,int is_italic,int is_small_caps)47 fz_load_html_font(fz_context *ctx, fz_html_font_set *set,
48 	const char *family, int is_bold, int is_italic, int is_small_caps)
49 {
50 	fz_html_font_face *custom;
51 	const unsigned char *data;
52 	int best_score = 0;
53 	fz_font *best_font = NULL;
54 	int size;
55 
56 	for (custom = set->custom; custom; custom = custom->next)
57 	{
58 		if (!strcmp(family, custom->family))
59 		{
60 			int score =
61 				1 * (is_bold == custom->is_bold) +
62 				2 * (is_italic == custom->is_italic) +
63 				4 * (is_small_caps == custom->is_small_caps);
64 			if (score > best_score)
65 			{
66 				best_score = score;
67 				best_font = custom->font;
68 			}
69 		}
70 	}
71 	if (best_font)
72 		return best_font;
73 
74 	data = fz_lookup_builtin_font(ctx, family, is_bold, is_italic, &size);
75 	if (data)
76 	{
77 		fz_font *font = fz_new_font_from_memory(ctx, NULL, data, size, 0, 0);
78 		fz_font_flags_t *flags = fz_font_flags(font);
79 		if (is_bold && !flags->is_bold)
80 			flags->fake_bold = 1;
81 		if (is_italic && !flags->is_italic)
82 			flags->fake_italic = 1;
83 		fz_add_html_font_face(ctx, set, family, is_bold, is_italic, 0, "<builtin>", font);
84 		fz_drop_font(ctx, font);
85 		return font;
86 	}
87 
88 	if (!strcmp(family, "monospace") || !strcmp(family, "sans-serif") || !strcmp(family, "serif"))
89 		return fz_load_html_default_font(ctx, set, family, is_bold, is_italic);
90 
91 	return NULL;
92 }
93 
fz_new_html_font_set(fz_context * ctx)94 fz_html_font_set *fz_new_html_font_set(fz_context *ctx)
95 {
96 	return fz_malloc_struct(ctx, fz_html_font_set);
97 }
98 
fz_drop_html_font_set(fz_context * ctx,fz_html_font_set * set)99 void fz_drop_html_font_set(fz_context *ctx, fz_html_font_set *set)
100 {
101 	fz_html_font_face *font, *next;
102 	int i;
103 
104 	if (!set)
105 		return;
106 
107 	font = set->custom;
108 	while (font)
109 	{
110 		next = font->next;
111 		fz_drop_font(ctx, font->font);
112 		fz_free(ctx, font->src);
113 		fz_free(ctx, font->family);
114 		fz_free(ctx, font);
115 		font = next;
116 	}
117 
118 	for (i = 0; i < (int)nelem(set->fonts); ++i)
119 		fz_drop_font(ctx, set->fonts[i]);
120 
121 	fz_free(ctx, set);
122 }
123