aboutsummaryrefslogtreecommitdiffstats
path: root/libparsepcf_preparse_font.c
blob: 63c245e20ff34fc8f26ad3d42091d0baf9a9c754 (plain) (blame)
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
/* See LICENSE file for copyright and license details. */
#include "common.h"


int
libparsepcf_preparse_font(const void *file, size_t size, struct libparsepcf_font *font)
{
	size_t min = SIZE_MAX, max = 0, table_i, table_n;
	struct libparsepcf_table *tables = NULL;

	*font = (struct libparsepcf_font){0};

	if (libparsepcf_get_table_count(file, size, &table_n))
		goto fail;
	tables = calloc(table_n, sizeof(*tables));
	if (!tables)
		goto fail;
	if (libparsepcf_get_tables(file, size, tables, 0, table_n))
		goto fail;

	for (table_i = 0; table_i < table_n; table_i++) {
		if (tables[table_i].type == LIBPARSEPCF_PROPERTIES) {
			font->prob_table = &tables[table_i];
			if (libparsepcf_get_properties(file, size, &tables[table_i], &font->props))
				goto fail;
		} else if (tables[table_i].type == LIBPARSEPCF_ACCELERATORS && !font->accel_table) {
			font->accel_table = &tables[table_i];
			if (libparsepcf_get_accelerators(file, size, &tables[table_i], &font->accels))
				goto fail;
		} else if (tables[table_i].type == LIBPARSEPCF_BDF_ACCELERATORS) {
			font->accel_table = &tables[table_i];
			if (libparsepcf_get_accelerators(file, size, &tables[table_i], &font->accels))
				goto fail;
		} else if (tables[table_i].type == LIBPARSEPCF_METRICS) {
			font->mtx_table = &tables[table_i];
			if (libparsepcf_get_metrics_count(file, size, &tables[table_i], &font->metrics))
				goto fail;
		} else if (tables[table_i].type == LIBPARSEPCF_INK_METRICS) {
			font->inkmtx_table = &tables[table_i];
			if (libparsepcf_get_metrics_count(file, size, &tables[table_i], &font->ink_metrics))
				goto fail;
		} else if (tables[table_i].type == LIBPARSEPCF_BDF_ENCODINGS) {
			font->enc_table = &tables[table_i];
			if (libparsepcf_get_encoding(file, size, &tables[table_i], &font->encoding))
				goto fail;
		} else if (tables[table_i].type == LIBPARSEPCF_BITMAPS) {
			font->bitmap_table = &tables[table_i];
			if (libparsepcf_get_bitmaps(file, size, &tables[table_i], &font->bitmaps))
				goto fail;
		} else if (tables[table_i].type == LIBPARSEPCF_GLYPH_NAMES) {
			font->name_table = &tables[table_i];
			if (libparsepcf_get_glyph_names(file, size, &tables[table_i], &font->names))
				goto fail;
		} else if (tables[table_i].type == LIBPARSEPCF_SWIDTHS) {
			font->swidth_table = &tables[table_i];
			if (libparsepcf_get_swidth_count(file, size, &tables[table_i], &font->swidths))
				goto fail;
		}
	}

	if (font->mtx_table) {
		if (font->metrics < min)
			min = font->metrics;
		if (font->metrics > max)
			max = font->metrics;
	}
	if (font->inkmtx_table) {
		if (font->ink_metrics < min)
			min = font->ink_metrics;
		if (font->ink_metrics > max)
			max = font->ink_metrics;
	}
	if (font->bitmap_table) {
		if (font->bitmaps.glyph_count < min)
			min = font->bitmaps.glyph_count;
		if (font->bitmaps.glyph_count > max)
			max = font->bitmaps.glyph_count;
	}
	if (font->name_table) {
		if (font->names.glyph_count < min)
			min = font->names.glyph_count;
		if (font->names.glyph_count > max)
			max = font->names.glyph_count;
	}
	if (font->swidth_table) {
		if (font->swidths < min)
			min = font->swidths;
		if (font->swidths > max)
			max = font->swidths;
	}

	if (min != max || !font->mtx_table || !font->enc_table)
		goto ebfont;
	if (!font->inkmtx_table && font->accel_table && font->accels.ink_metrics)
		goto ebfont;
	font->glyph_count = min;
	font->_tables = tables;

	return 0;

ebfont:
	errno = EBFONT;
fail:
	free(tables);
	return -1;
}