summaryrefslogtreecommitdiff
path: root/source/html/html-font.c
blob: bca1625e921c3b52e7151cbf6158e30a8a796575 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include "mupdf/html.h"

static const char *font_names[16] =
{
	"Times-Roman", "Times-Italic", "Times-Bold", "Times-BoldItalic",
	"Helvetica", "Helvetica-Oblique", "Helvetica-Bold", "Helvetica-BoldOblique",
	"Courier", "Courier-Oblique", "Courier-Bold", "Courier-BoldOblique",
	"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)
{
	int is_mono = !strcmp(family, "monospace");
	int is_sans = !strcmp(family, "sans-serif");
	int idx = is_mono * 8 + is_sans * 4 + is_bold * 2 + is_italic;
	if (!set->fonts[idx])
	{
		unsigned char *data;
		unsigned int size;

		data = fz_lookup_base14_font(ctx, font_names[idx], &size);
		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];
}

fz_font *
fz_load_html_font(fz_context *ctx, fz_html_font_set *set, const char *family, int is_bold, int is_italic)
{
	fz_html_font_face *custom;

	for (custom = set->custom; custom; custom = custom->next)
	{
		if (!strcmp(family, custom->family) &&
				is_bold == custom->is_bold &&
				is_italic == custom->is_italic)
		{
			return custom->font;
		}
	}

	if (!strcmp(family, "monospace") ||
			!strcmp(family, "sans-serif") ||
			!strcmp(family, "serif"))
		return fz_load_html_builtin_font(ctx, set, family, is_bold, is_italic);

	return NULL;
}

void
fz_add_html_font_face(fz_context *ctx, fz_html_font_set *set,
	const char *family, int is_bold, int is_italic, const char *src,
	fz_font *font)
{
	fz_html_font_face *custom;

	custom = fz_malloc_struct(ctx, fz_html_font_face);
	custom->font = fz_keep_font(ctx, font);
	custom->src = fz_strdup(ctx, src);
	custom->family = fz_strdup(ctx, family);
	custom->is_bold = is_bold;
	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)
{
	return fz_malloc_struct(ctx, fz_html_font_set);
}

void fz_drop_html_font_set(fz_context *ctx, fz_html_font_set *set)
{
	fz_html_font_face *font, *next;
	int i;

	font = set->custom;
	while (font)
	{
		next = font->next;
		fz_drop_font(ctx, font->font);
		fz_free(ctx, font->src);
		fz_free(ctx, font->family);
		fz_free(ctx, font);
		font = next;
	}

	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);
}