diff options
| author | Mattias Andrée <maandree@kth.se> | 2021-08-13 18:06:45 +0200 | 
|---|---|---|
| committer | Mattias Andrée <maandree@kth.se> | 2021-08-13 18:06:45 +0200 | 
| commit | fcffe4810f59de6a4f39596a37242022b68e7bc5 (patch) | |
| tree | d91ef754fe3b24ecfea8270ef4ef0c070de8c359 | |
| download | libparsesfnt-fcffe4810f59de6a4f39596a37242022b68e7bc5.tar.gz libparsesfnt-fcffe4810f59de6a4f39596a37242022b68e7bc5.tar.bz2 libparsesfnt-fcffe4810f59de6a4f39596a37242022b68e7bc5.tar.xz | |
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
| -rw-r--r-- | .gitignore | 13 | ||||
| -rw-r--r-- | LICENSE | 15 | ||||
| -rw-r--r-- | Makefile | 79 | ||||
| -rw-r--r-- | avar.c | 73 | ||||
| -rw-r--r-- | bhed.c | 12 | ||||
| -rw-r--r-- | common.h | 15 | ||||
| -rw-r--r-- | config.mk | 8 | ||||
| -rw-r--r-- | fdsc.c | 27 | ||||
| -rw-r--r-- | fmtx.c | 12 | ||||
| -rw-r--r-- | fpgm.c | 22 | ||||
| -rw-r--r-- | gasp.c | 27 | ||||
| -rw-r--r-- | gcid.c | 35 | ||||
| -rw-r--r-- | head.c | 12 | ||||
| -rw-r--r-- | hhea.c | 12 | ||||
| -rw-r--r-- | hmtx.c | 44 | ||||
| -rw-r--r-- | libparsesfnt.h | 771 | ||||
| -rw-r--r-- | libparsesfnt_parse___.c | 188 | ||||
| -rw-r--r-- | libparsesfnt_parse_fontdir.c | 11 | ||||
| -rw-r--r-- | libparsesfnt_parse_tabdir.c | 12 | ||||
| -rw-r--r-- | loca.c | 24 | ||||
| -rw-r--r-- | ltag.c | 44 | ||||
| -rw-r--r-- | maxp.c | 34 | ||||
| -rw-r--r-- | meta.c | 32 | ||||
| -rw-r--r-- | name.c | 33 | ||||
| -rw-r--r-- | trak.c | 76 | ||||
| -rw-r--r-- | vhea.c | 12 | ||||
| -rw-r--r-- | vmtx.c | 44 | ||||
| -rw-r--r-- | xref.c | 48 | 
28 files changed, 1735 insertions, 0 deletions
| diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..048b700 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +*\#* +*~ +*.o +*.a +*.lo +*.su +*.so +*.so.* +*.gch +*.gcov +*.gcno +*.gcda +/libparsesfnt-all.c @@ -0,0 +1,15 @@ +ISC License + +© 2020, 2021 Mattias Andrée <maandree@kth.se> + +Permission to use, copy, modify, and/or distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..11982d0 --- /dev/null +++ b/Makefile @@ -0,0 +1,79 @@ +.POSIX: + +CONFIGFILE = config.mk +include $(CONFIGFILE) + +MODULES =\ +	head\ +	bhed\ +	hhea\ +	hmtx\ +	vhea\ +	vmtx\ +	maxp\ +	loca\ +	name\ +	fmtx\ +	ltag\ +	xref\ +	trak\ +	gcid\ +	fpgm\ +	fdsc\ +	gasp\ +	avar\ +	meta + +OBJ =\ +	libparsesfnt_parse___.o\ +	libparsesfnt_parse_fontdir.o\ +	libparsesfnt_parse_tabdir.o\ +	$(MODULES:=.o) + +HDR =\ +	libparsesfnt.h\ +	common.h + +AR_OBJ = $(OBJ) +# Using "AR_OBJ=libparsesfnt-all.o" can reduce the size of the +# library, however this may affect the size of applications that +# don't use most of the functions. If you are compiling for your +# application specification you can combine this with setting +# MODULES to the parts your application will use; note however +# that 'fpgm' covers both 'fpgm' and 'prep'. + +all: libparsesfnt.a +$(OBJ): $(@:.o=.c) $(HDR) +libparsesfnt-all.o: libparsesfnt-all.c $(HDR) + +libparsesfnt-all.c: $(OBJ:.o=.c) +	cat $(OBJ:.o=.c) > $@ + +.c.o: +	$(CC) -c -o $@ $< $(CFLAGS) $(CPPFLAGS) + +.c.lo: +	$(CC) -fPIC -c -o $@ $< $(CFLAGS) $(CPPFLAGS) + +libparsesfnt.a: $(AR_OBJ) +	@rm -f -- $@ +	$(AR) rc $@ $(AR_OBJ) + +install: libparsesfnt.a +	mkdir -p -- "$(DESTDIR)$(PREFIX)/lib" +	mkdir -p -- "$(DESTDIR)$(PREFIX)/include" +	cp -- libparsesfnt.a "$(DESTDIR)$(PREFIX)/lib/" +	cp -- libparsesfnt.h "$(DESTDIR)$(PREFIX)/include/" + +uninstall: +	-rm -f -- "$(DESTDIR)$(PREFIX)/lib/libparsesfnt.a" +	-rm -f -- "$(DESTDIR)$(PREFIX)/include/libparsesfnt.h" + +clean: +	-rm -f -- *.o *.a *.lo *.su *.so *.so.* *.gch *.gcov *.gcno *.gcda +	-rm -f -- libparsesfnt-all.c + +.SUFFIXES: +.SUFFIXES: .lo .o .c + +.PHONY: all install uninstall clean @@ -0,0 +1,73 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_avar( +			const char *data, size_t size, +			struct libparsesfnt_avar *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	return PARSE(LIBPARSESFNT_AVAR__, tag->offset, 0, 0, 0, 1, tag); +} + + +static uint16_t +avar_parse16(const char *data) +{ +	uint16_t b1 = (uint16_t)((const uint8_t *)data)[0]; +	uint16_t b2 = (uint16_t)((const uint8_t *)data)[1]; +	b1 = (uint16_t)(b1 << 8); +	b2 = (uint16_t)(b2 << 0); +	return (uint16_t)(b1 | b2); +} + +int +libparsesfnt_parse_avar_entries( +			const char *data, size_t size, +			struct libparsesfnt_avar_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t *offsetp, size_t count) +{ +	size_t offset = offsetp ? *offsetp : 0; +	if (offset < 8) { +		if (tag->length < 8) { +			errno = EBFONT; +			return -1; +		} +		offset = 8; +	} +	if ((size_t)tag->length < offset || size < (size_t)tag->length - offset) { +		errno = EBFONT; +		return -1; +	} +	while (count--) { +		if (tag->length - offset < 2) { +			errno = EBFONT; +			return -1; +		} +		infop->pair_count = avar_parse16(&data[offset]); +		offset += 2; +		infop->libparsesfnt_subentry_location = offset; +		memset(infop->__padding1, 0, sizeof(infop->__padding1)); +		if ((size_t)infop->pair_count > ((size_t)tag->length - offset) / 4) { +			errno = EBFONT; +			return -1; +		} +		infop++; +	} +	if (offsetp) +		*offsetp = offset; +	return 0; +} + + +int +libparsesfnt_parse_avar_subentries( +			const char *data, size_t size, +			struct libparsesfnt_avar_subentry *infop, +			const struct libparsesfnt_avar_entry *entry, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_AVAR_SUBENTRY__, entry->libparsesfnt_subentry_location, 0, 0, first, count, NULL); +} @@ -0,0 +1,12 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_bhed( +			const char *data, size_t size, +			struct libparsesfnt_bhed *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	return PARSE(LIBPARSESFNT_BHED__, tag->offset, 0, 0, 0, 1, tag); +} diff --git a/common.h b/common.h new file mode 100644 index 0000000..a1b0f87 --- /dev/null +++ b/common.h @@ -0,0 +1,15 @@ +/* See LICENSE file for copyright and license details. */ +#include "libparsesfnt.h" + +#include <errno.h> +#include <limits.h> +#include <stdlib.h> +#include <string.h> + + + +int libparsesfnt_parse___(const char *data, size_t size, void *infop, size_t esize, +                          const char *fmt, size_t offset, size_t offset2, size_t offset3, +                          size_t first, size_t count, const struct libparsesfnt_tabdir_entry *tag); + +#define PARSE(...) libparsesfnt_parse___(data, size, infop, sizeof(*infop), __VA_ARGS__) diff --git a/config.mk b/config.mk new file mode 100644 index 0000000..af85cea --- /dev/null +++ b/config.mk @@ -0,0 +1,8 @@ +PREFIX    = /usr +MANPREFIX = $(PREFIX)/share/man + +CC = cc + +CPPFLAGS = -D_DEFAULT_SOURCE -D_BSD_SOURCE -D_XOPEN_SOURCE=700 -D_GNU_SOURCE +CFLAGS   = -std=c99 -Wall +LDFLAGS  = @@ -0,0 +1,27 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_fdsc( +			const char *data, size_t size, +			struct libparsesfnt_fdsc *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	if ((tag->length - 8) % 8) { +		errno = EBFONT; +		return -1; +	} +	return PARSE(LIBPARSESFNT_FDSC__, tag->offset, 0, 0, 0, 1, tag); +} + + +int +libparsesfnt_parse_fdsc_entries( +			const char *data, size_t size, +			struct libparsesfnt_fdsc_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_FDSC_ENTRY__, tag->offset, 8, 0, first, count, tag); +} @@ -0,0 +1,12 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_fmtx( +			const char *data, size_t size, +			struct libparsesfnt_fmtx *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	return PARSE(LIBPARSESFNT_NAME__, tag->offset, 0, 0, 0, 1, tag); +} @@ -0,0 +1,22 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_fpgm( +			const char *data, size_t size, +			uint8_t *programp, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	if (count > SIZE_MAX - first) { +		errno = EFBIG; +		return -1; +	} +	if (tag->offset < size || first + count > size - tag->offset) { +		errno = EBFONT; +		return -1; +	} +	memcpy(programp, &data[tag->offset + first], count - first); +	return 0; +} @@ -0,0 +1,27 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_gasp( +			const char *data, size_t size, +			struct libparsesfnt_gasp *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	if ((tag->length - 4) % 4) { +		errno = EBFONT; +		return -1; +	} +	return PARSE(LIBPARSESFNT_GASP__, tag->offset, 0, 0, 0, 1, tag); +} + + +int +libparsesfnt_parse_gasp_entries( +			const char *data, size_t size, +			struct libparsesfnt_gasp_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_GASP_ENTRY__, tag->offset, 4, 0, first, count, tag); +} @@ -0,0 +1,35 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_gcid( +			const char *data, size_t size, +			struct libparsesfnt_gcid *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	if ((tag->length - 144) % 2) +		goto ebfont; +	if (PARSE(LIBPARSESFNT_GCID__, tag->offset, 0, 0, 0, 1, tag)) +		return -1; +	if (((size_t)(tag->length - 144) / 2 != (size_t)infop->count && +	     (size_t)(tag->length - 144) / 2 != (size_t)infop->count + 1) || +	    tag->length != infop->size) +		goto ebfont; +	return 0; + +ebfont: +	errno = EBFONT; +	return -1; +} + + +int +libparsesfnt_parse_gcid_entries( +			const char *data, size_t size, +			struct libparsesfnt_gcid_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_GCID_ENTRY__, tag->offset, 144, 0, first, count, tag); +} @@ -0,0 +1,12 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_head( +			const char *data, size_t size, +			struct libparsesfnt_head *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	return PARSE(LIBPARSESFNT_HEAD__, tag->offset, 0, 0, 0, 1, tag); +} @@ -0,0 +1,12 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_hhea( +			const char *data, size_t size, +			struct libparsesfnt_hhea *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	return PARSE(LIBPARSESFNT_HHEA__, tag->offset, 0, 0, 0, 1, tag); +} @@ -0,0 +1,44 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_hmtx( +			const char *data, size_t size, +			struct libparsesfnt_hmtx_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_HMTX_ENTRY__, tag->offset, 0, 0, first, count, tag); +} + + +int +libparsesfnt_get_hmtx_lsb_subtable_length( +			size_t *lengthp, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_hhea *hhea) +{ +	size_t off; +	/* hhea->num_advances_in_hmtx_table is uint16_t, so overflow is impossible */ +	off = (size_t)hhea->num_advances_in_hmtx_table * 4; +	if (off > tag->length || (tag->length - off) % 2) { +		errno = EBFONT; +		return -1; +	} +	*lengthp = (tag->length - off) / 2; +	return 0; +} + + +int +libparsesfnt_parse_hmtx_lsb_subtable( +			const char *data, size_t size, +			struct libparsesfnt_hmtx_lsb_subtable_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_hhea *hhea, +			size_t first, size_t count) +{ +	size_t off; +	/* hhea->num_advances_in_hmtx_table is uint16_t, so overflow is impossible */ +	off = (size_t)hhea->num_advances_in_hmtx_table * 4; +	return PARSE(LIBPARSESFNT_HMTX_LSB_SUBTABLE_ENTRY__, tag->offset, off, 0, first, count, NULL); +} diff --git a/libparsesfnt.h b/libparsesfnt.h new file mode 100644 index 0000000..809fad7 --- /dev/null +++ b/libparsesfnt.h @@ -0,0 +1,771 @@ +/* See LICENSE file for copyright and license details. */ +#ifndef LIBPARSESFNT_H +#define LIBPARSESFNT_H + +#include <stddef.h> +#include <stdint.h> + + +#define LIBPARSESFNT_8C__ "1111""1111" +#define LIBPARSESFNT_16C__ LIBPARSESFNT_8C__""LIBPARSESFNT_8C__ +#define LIBPARSESFNT_32C__ LIBPARSESFNT_16C__""LIBPARSESFNT_16C__ +#define LIBPARSESFNT_64C__ LIBPARSESFNT_32C__""LIBPARSESFNT_32C__ +#define LIBPARSESFNT_128C__ LIBPARSESFNT_64C__""LIBPARSESFNT_64C__ +#define LIBPARSESFNT_255C__ LIBPARSESFNT_128C__""LIBPARSESFNT_64C__""LIBPARSESFNT_32C__""\ +                            LIBPARSESFNT_32C__""LIBPARSESFNT_16C__""LIBPARSESFNT_16C__""\ +                            LIBPARSESFNT_8C__"1111""11""1" + + +#define LIBPARSESFNT_UNIX_EPOCH          ((time_t)-2082844800L) /* 1904-01-01 00:00:00 */ +#define LIBPARSESFNT_TO_UNIX_EPOCH(TIME) ((time_t)(TIME) + LIBPARSESFNT_UNIX_EPOCH) + + + +/* === font directory === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6.html */ + +struct libparsesfnt_fontdir { +	char scaler_type[4]; +	uint16_t num_tables; +	uint16_t search_range;   /* use to determine how to bsearch(3) the table directory */ +	uint16_t entry_selector; /* use to determine whether to bsearch(3) the table directory */ +	uint16_t range_shift;    /* use to determine how to bsearch(3) the table directory */ +}; +#define LIBPARSESFNT_FONTDIR__ "11112222" + +int libparsesfnt_parse_fontdir( +	const char *data, size_t size, +	struct libparsesfnt_fontdir *infop); + + + +/* === table directory === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6.html */ + +struct libparsesfnt_tabdir_entry { +	char tab[4]; +	uint32_t checksum; +	uint32_t offset; +	uint32_t length; +}; +#define LIBPARSESFNT_TABDIR_ENTRY__ "1111444" + +int libparsesfnt_parse_tabdir( +	const char *data, size_t size, +	struct libparsesfnt_tabdir_entry *infop, +	size_t first, size_t count); + + + +/* === 'head' (font header) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6head.html */ + +struct libparsesfnt_head { +	uint32_t version; +	uint32_t font_revision; +	uint32_t checksum_adjustment; +	uint32_t magic_number; +#define LIBPARSESFNT_HEAD_MAGIC_NUMBER_EXPECTED UINT32_C(0x5f0f3cf5) +	uint16_t flags; +	uint16_t units_per_em; +#define LIBPARSESFNT_HEAD_UNITS_PER_EM_MIN 64 +#define LIBPARSESFNT_HEAD_UNITS_PER_EM_MAX 16384 +	uint32_t __padding1; +	uint64_t created; +	uint64_t modified; +	int16_t x_min; +	int16_t y_min; +	int16_t x_max; +	int16_t y_max; +	uint16_t style_flags; +	uint16_t lowest_ppem; /* smallest readable size in pixels (per em) */ +	int16_t font_direction_hint; +	int16_t loca_table_format; /* 0 = "short" offsets, 1 = "long" offsets */ +	int16_t glyph_data_format; +	uint16_t __padding2[3]; +}; +#define LIBPARSESFNT_HEAD__ "444422pppp88-2222+22-222pppppp" + +int libparsesfnt_parse_head( +	const char *data, size_t size, +	struct libparsesfnt_head *infop, +	const struct libparsesfnt_tabdir_entry *tag); + + + +/* === 'bhed' (bitmap font header) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6bhed.html */ + +struct libparsesfnt_bhed { +	uint32_t version; +	uint32_t font_revision; +	uint32_t checksum_adjustment; +	uint32_t magic_number; +#define LIBPARSESFNT_BHED_MAGIC_NUMBER_EXPECTED HEAD_MAGIC_NUMBER_EXPECTED +	uint16_t flags; +	uint16_t units_per_em; +#define LIBPARSESFNT_BHED_UNITS_PER_EM_MIN LIBPARSESFNT_HEAD_UNITS_PER_EM_MIN +#define LIBPARSESFNT_BHED_UNITS_PER_EM_MAX LIBPARSESFNT_HEAD_UNITS_PER_EM_MAX +	uint32_t __padding1; +	uint64_t created; +	uint64_t modified; +	int16_t x_min; +	int16_t y_min; +	int16_t x_max; +	int16_t y_max; +	uint16_t style_flags; +	uint16_t lowest_ppem; /* smallest readable size in pixels (per em) */ +	int16_t font_direction_hint; +	int16_t bloc_table_format; /* 0 = "short" offsets, 1 = "long" offsets */ +	int16_t glyph_data_format; +	uint16_t __padding2[3]; +}; +#define LIBPARSESFNT_BHED__ "444422pppp88-2222+22-222pppppp" + +int libparsesfnt_parse_bhed( +	const char *data, size_t size, +	struct libparsesfnt_bhed *infop, +	const struct libparsesfnt_tabdir_entry *tag); + + + +/* === 'hhea' (horizontal header) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6hhea.html */ + +struct libparsesfnt_hhea { +	uint32_t version; +	int16_t max_ascent; +	int16_t max_descent; +	int16_t line_gap; +	uint16_t max_advance; +	int16_t min_left_side_bearing; +	int16_t max_left_side_bearing; +	int16_t x_max_extent; +	int16_t caret_slope_rise; +	int16_t caret_slope_run; +	int16_t caret_offset; +	uint8_t ___reserved1[8]; +	int16_t metric_data_format; +	uint16_t num_advances_in_hmtx_table; +}; +#define LIBPARSESFNT_HHEA__ "4-222+2-222222........2+2" + +int libparsesfnt_parse_hhea( +	const char *data, size_t size, +	struct libparsesfnt_hhea *infop, +	const struct libparsesfnt_tabdir_entry *tag); + + + +/* === 'hmtx' (horizontal metrics) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6hmtx.html */ + +struct libparsesfnt_hmtx_entry { +	uint16_t advance; +	int16_t left_side_bearing; +}; +#define LIBPARSESFNT_HMTX_ENTRY__ "2-2" + +struct libparsesfnt_hmtx_lsb_subtable_entry { +	int16_t left_side_bearing2; +}; +#define LIBPARSESFNT_HMTX_LSB_SUBTABLE_ENTRY__ "-2" + +int libparsesfnt_parse_hmtx( +	const char *data, size_t size, +	struct libparsesfnt_hmtx_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + +int libparsesfnt_get_hmtx_lsb_subtable_length( +	size_t *lengthp, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_hhea *hhea); + +int libparsesfnt_parse_hmtx_lsb_subtable( +	const char *data, size_t size, +	struct libparsesfnt_hmtx_lsb_subtable_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_hhea *hhea, +	size_t first, size_t count); + + + +/* === 'vhea' (vertical header) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6vhea.html */ + +struct libparsesfnt_vhea { +	int32_t version; +	int16_t max_ascent; +	int16_t max_descent; +	int16_t line_gap; +	uint16_t max_advance; +	int16_t min_top_side_bearing; +	int16_t min_bottom_side_bearing; +	int16_t y_max_extent; +	int16_t caret_slope_rise; +	int16_t caret_slope_run; +	int16_t caret_offset; +	uint8_t ___reserved1[8]; +	int16_t metric_data_format; +	uint16_t num_advances_in_vmtx_table; +}; +#define LIBPARSESFNT_VHEA__ "4-222+2-222222........2+2" + +int libparsesfnt_parse_vhea( +	const char *data, size_t size, +	struct libparsesfnt_vhea *infop, +	const struct libparsesfnt_tabdir_entry *tag); + + + +/* === 'vmtx' (vertical metrics) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6vmtx.html */ + +struct libparsesfnt_vmtx_entry { +	uint16_t advance; +	int16_t top_side_bearing; +}; +#define LIBPARSESFNT_VMTX_ENTRY__ "2-2" + +struct libparsesfnt_vmtx_tsb_subtable_entry { +	int16_t top_side_bearing2; +}; +#define LIBPARSESFNT_VMTX_TSB_SUBTABLE_ENTRY__ "-2" + +int libparsesfnt_parse_vmtx( +	const char *data, size_t size, +	struct libparsesfnt_vmtx_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + +int libparsesfnt_get_vmtx_tsb_subtable_length( +	size_t *lengthp, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_vhea *vhea); + +int libparsesfnt_parse_vmtx_tsb_subtable( +	const char *data, size_t size, +	struct libparsesfnt_vmtx_tsb_subtable_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_vhea *vhea, +	size_t first, size_t count); + + + +/* === 'maxp' (maximum profile) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6maxp.html */ + +struct libparsesfnt_maxp_0_5 { +	uint16_t num_glyphs; +}; +#define LIBPARSESFNT_MAXP_0_5__ "2" + +struct libparsesfnt_maxp_1_0 { +	uint16_t num_glyphs; +	uint16_t max_points_noncompound; +	uint16_t max_contours_noncompound; +	uint16_t max_points_compound; +	uint16_t max_contours_compound; +	uint16_t max_zones; /* should be 2 */ +	uint16_t max_twilight_points; +	uint16_t max_storage_areas; +	uint16_t max_fdefs; +	uint16_t max_odefs; +	uint16_t max_stack_depth; +	uint16_t max_size_of_instructions; +	uint16_t max_top_level_glyphs; +	uint16_t max_recursion; +}; +#define LIBPARSESFNT_MAXP_1_0__ "22222222222222" + +struct libparsesfnt_maxp { +	uint32_t version; +	union { +		struct libparsesfnt_maxp_0_5 v0_5; +		struct libparsesfnt_maxp_1_0 v1_0; /* extends .v0_5 */ +	} v; +}; +#define LIBPARSESFNT_MAXP__ "4" + +int libparsesfnt_parse_maxp( +	const char *data, size_t size, +	struct libparsesfnt_maxp *infop, +	const struct libparsesfnt_tabdir_entry *tag); + + + +/* === 'loca' (glyph locations) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6loca.html */ + +/* There is one extra entry at the end, so that (entry[i + 1].offset - entry[i].offset) + * calculates the size of entry i. */ + +struct libparsesfnt_loca_short_entry { +	uint16_t offset; +}; +#define LIBPARSESFNT_LOCA_SHORT_ENTRY__ "2" + +struct libparsesfnt_loca_long_entry { +	uint32_t offset; +}; +#define LIBPARSESFNT_LOCA_LONG_ENTRY__ "4" + +int libparsesfnt_parse_loca_short( +	const char *data, size_t size, +	struct libparsesfnt_loca_short_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + +int libparsesfnt_parse_loca_long( +	const char *data, size_t size, +	struct libparsesfnt_loca_long_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + + + +/* === 'name' (name) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6name.html */ +/* TODO platform ID, platform-specific ID, language ID */ + +struct libparsesfnt_name { +	uint16_t format; +	uint16_t count; +	uint16_t string_offset; +}; +#define LIBPARSESFNT_NAME__ "222" + +struct libparsesfnt_name_entry { +	uint16_t platform_id; +	uint16_t platform_specific_id; +	uint16_t language_id; +	uint16_t name_id; +	uint16_t name_length; +	uint16_t name_offset; +}; +#define LIBPARSESFNT_NAME_ENTRY__ "222222" + +enum libparsesfnt_name_id { +	LIBPARSESFNT_NAME_ID_COPYRIGHT_NOTICE = 0, +	LIBPARSESFNT_NAME_ID_FONT_FAMILY = 1, +	LIBPARSESFNT_NAME_ID_FONT_SUBFAMILY = 2, +	LIBPARSESFNT_NAME_ID_UNIQUE_SUBFAMILY_IDENTIFICATION = 3, +	LIBPARSESFNT_NAME_ID_FULL_NAME_OF_THE_FONT = 4, +	LIBPARSESFNT_NAME_ID_VERSION_OF_THE_NAME_TABLE = 5, +	LIBPARSESFNT_NAME_ID_POSTSCRIPT_NAME_OF_THE_FONT = 6, +	LIBPARSESFNT_NAME_ID_TRADEMARK_NOTICE = 7, +	LIBPARSESFNT_NAME_ID_MANUFACTURER = 8, +	LIBPARSESFNT_NAME_ID_DESIGNER = 9, +	LIBPARSESFNT_NAME_ID_DESCRIPTION = 10, +	LIBPARSESFNT_NAME_ID_VENDOR_URL = 11, +	LIBPARSESFNT_NAME_ID_DESIGNER_URL = 12, +	LIBPARSESFNT_NAME_ID_LICENSE_DESCRIPTION = 13, +	LIBPARSESFNT_NAME_ID_LICENSE_INFORMATION_URL = 14, +	/* 15 is reserved */ +	LIBPARSESFNT_NAME_ID_PREFERRED_FAMILY = 16, +	LIBPARSESFNT_NAME_ID_PREFERRED_SUBFAMILY = 17, +	LIBPARSESFNT_NAME_ID_COMPATIBLE_FULL = 18, +	LIBPARSESFNT_NAME_ID_SAMPLE_TEXT = 19 +	/* 20–22 are defined by OpenType */ +	/* 23–255 are reserved for future expansions*/ +	/* 256–32767 are for font-specific names */ +}; + +int libparsesfnt_parse_name( +	const char *data, size_t size, +	struct libparsesfnt_name *infop, +	const struct libparsesfnt_tabdir_entry *tag); + +int libparsesfnt_parse_name_entries( +	const char *data, size_t size, +	struct libparsesfnt_name_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + + + +/* === 'fmtx' (font metrics) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fmtx.html */ + +struct libparsesfnt_fmtx { +	uint32_t version; +	uint32_t glyph_index; +	uint8_t horizontal_before; +	uint8_t horizontal_after; +	uint8_t horizontal_caret_head; +	uint8_t horizontal_caret_base; +	uint8_t vertical_before; +	uint8_t vertical_after; +	uint8_t vertical_caret_head; +	uint8_t vertical_caret_base; +}; +#define LIBPARSESFNT_FMTX__ "4411111111" + +int libparsesfnt_parse_fmtx( +	const char *data, size_t size, +	struct libparsesfnt_fmtx *infop, +	const struct libparsesfnt_tabdir_entry *tag); + + + +/* === 'ltag' (language tag) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6ltag.html */ + +struct libparsesfnt_ltag { +	uint32_t version; +	uint32_t flags; /* unused, should be 0 */ +	uint32_t num_tags; +}; +#define LIBPARSESFNT_LTAG__ "444" + +struct libparsesfnt_ltag_entry { +	uint16_t offset; /* relative to the beginning of the 'ltag' table */ +	uint16_t length; +}; +#define LIBPARSESFNT_LTAG_ENTRY__ "22" + +int libparsesfnt_parse_ltag( +	const char *data, size_t size, +	struct libparsesfnt_ltag *infop, +	const struct libparsesfnt_tabdir_entry *tag); + +int libparsesfnt_parse_ltag_entries( +	const char *data, size_t size, +	struct libparsesfnt_ltag_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + +int libparsesfnt_get_ltag_offset( +	size_t size, +	size_t *offsetp, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_ltag_entry *entry); + + + +/* === 'xref' (cross-reference) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6xref.html */ + +struct libparsesfnt_xref { +	uint32_t version; +	uint32_t flags; /* unused, should be 0 */ +	uint32_t num_entries; +	uint32_t string_offset; /* position of the string table: relative to the beginning of this table */ +}; +#define LIBPARSESFNT_XREF__ "4444" + +struct libparsesfnt_xref_entry { +	char table_tab[4]; +	int16_t chain_index; +	int16_t subtable_index; +	int16_t table_type; +	uint16_t string_offset; /* relative to the beginning of the string table */ +	uint16_t string_length; +}; +#define LIBPARSESFNT_XREF_ENTRY__ "1111-2222+22" + +enum libparsesfnt_xref_table_type { +	LIBPARSESFNT_XREF_CLASS_NAME_TABLE = 0, +	LIBPARSESFNT_XREF_STATE_NAME_TABLE = 1, +	LIBPARSESFNT_XREF_ENTRY_TRANSITION_NAME_TABLE = 2, +	LIBPARSESFNT_XREF_ACTION_NAME_TABLE = 3, +	LIBPARSESFNT_XREF_COLUMN_CLASS_NAME_TABLE = 4, +	LIBPARSESFNT_XREF_ROW_CLASS_NAME_TABLE = 5 +}; + +int libparsesfnt_parse_xref( +	const char *data, size_t size, +	struct libparsesfnt_xref *infop, +	const struct libparsesfnt_tabdir_entry *tag); + +int libparsesfnt_parse_xref_entries( +	const char *data, size_t size, +	struct libparsesfnt_xref_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + +int libparsesfnt_get_xref_offset( +	size_t size, +	size_t *offsetp, +	const struct libparsesfnt_tabdir_entry *tag, +	  const struct libparsesfnt_xref *xref, +	  const struct libparsesfnt_xref_entry *entry); + + + +/* === 'trak' (tracking) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6trak.html */ + +struct libparsesfnt_trak { +	uint32_t version; +	uint16_t format; +	uint16_t horiz_offset; /* relative to the beginning of this table, 0 if missing */ +	uint16_t vert_offset; /* relative to the beginning of this table, 0 if missing */ +	uint8_t __reserved1[2]; +}; +#define LIBPARSESFNT_TRAK__ "4222.." + +struct libparsesfnt_trak_data { +	uint16_t n_tracks; +	uint16_t n_sizes; +	uint32_t size_table_offset; /* position of the size subtable: relative to the beginning of the 'trak' tabletable */ +}; +#define LIBPARSESFNT_TRAK_DATA__ "224" + +struct libparsesfnt_trak_track_entry { +	int32_t track; +	uint16_t name_index; /* should be > 255 */ +	uint16_t offset; /* position of this track's per-size tracking values: relative to the beginning of the 'trak' table */ +}; +#define LIBPARSESFNT_TRAK_TRACK_ENTRY__ "-4+22" + +struct libparsesfnt_trak_size_entry { +	int32_t size; +}; +#define LIBPARSESFNT_TRAK_SIZE_ENTRY__ "-4" + +int libparsesfnt_parse_trak( +	const char *data, size_t size, +	struct libparsesfnt_trak *infop, +	const struct libparsesfnt_tabdir_entry *tag); + +int libparsesfnt_parse_trak_horiz( +	const char *data, size_t size, +	struct libparsesfnt_trak_data *infop, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak *trak); + +int libparsesfnt_parse_trak_vert( +	const char *data, size_t size, +	struct libparsesfnt_trak_data *infop, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak *trak); + +int libparsesfnt_parse_trak_horiz_track_entries( +	const char *data, size_t size, +	struct libparsesfnt_trak_track_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak *trak, +	size_t first, size_t count); + +int libparsesfnt_parse_trak_vert_track_entries( +	const char *data, size_t size, +	struct libparsesfnt_trak_track_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak *trak, +	size_t first, size_t count); + +int libparsesfnt_parse_trak_size_entries( +	const char *data, size_t size, +	struct libparsesfnt_trak_size_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak_data *trak_data, +	size_t first, size_t count); + +int libparsesfnt_parse_trak_track_size_entries( +	const char *data, size_t size, +	struct libparsesfnt_trak_size_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak_track_entry *track, +	size_t first, size_t count); + + + +/* === 'cvt ' (control value) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6cvt.html */ + +struct libparsesfnt_cvt_entry { +	int16_t control_value; +}; + +/* TODO it is documented that entry count is table length divided by 4, + *      however the element type (FWord) is 2 bytes wide */ + + + +/* === 'gcid' (glyph to CID mapping) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6gcid.html */ + +struct libparsesfnt_gcid { +	uint16_t version; +	uint16_t format; +	uint32_t size; +	uint16_t registry; +	char registry_name[64]; +	uint16_t order; +	char order_name[64]; +	uint16_t supplement_version; +	uint16_t count; +}; +#define LIBPARSESFNT_GCID__ "2242"LIBPARSESFNT_64C__"2"LIBPARSESFNT_64C__"22" + +struct libparsesfnt_gcid_entry { +	uint16_t cid; +#define LIBPARSESFNT_GCID_NO_CID UINT16_C(0xFFFF) +}; +#define LIBPARSESFNT_GCID_ENTRY__ "2" + +int libparsesfnt_parse_gcid( +	const char *data, size_t size, +	struct libparsesfnt_gcid *infop, +	const struct libparsesfnt_tabdir_entry *tag); + +int libparsesfnt_parse_gcid_entries( +	const char *data, size_t size, +	struct libparsesfnt_gcid_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + + + +/* === 'fpgm' (font program) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fpgm.html */ + +int libparsesfnt_parse_fpgm( +	const char *data, size_t size, +	uint8_t *programp, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + + + +/* === 'prep' (control value program) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6prep.html */ + +#define libparsesfnt_parse_prep libparsesfnt_parse_fpgm + + + +/* === 'fdsc' (font descriptors) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6fdsc.html */ + +struct libparsesfnt_fdsc { +	uint32_t version; +	uint32_t descriptor_count; +}; +#define LIBPARSESFNT_FDSC__ "44" + +struct libparsesfnt_fdsc_entry { +	char tag[4]; +	int32_t value; +}; +#define LIBPARSESFNT_FDSC_ENTRY__ "1111-4" + +enum libparsesfnt_fdsc_nalf { +	LIBPARSESFNT_FDSC_NALF_ALPHABETIC = 0, +	LIBPARSESFNT_FDSC_NALF_DINGBATS = 1, +	LIBPARSESFNT_FDSC_NALF_PI_CHARACTERS = 2, +	LIBPARSESFNT_FDSC_NALF_FLEURONS = 3, +	LIBPARSESFNT_FDSC_NALF_DECORATIVE_BORDERS = 4, +	LIBPARSESFNT_FDSC_NALF_INTERNATIONAL_SYMBOLS = 5, +	LIBPARSESFNT_FDSC_NALF_MATH_SYMBOLS = 6 +}; + +int libparsesfnt_parse_fdsc( +	const char *data, size_t size, +	struct libparsesfnt_fdsc *infop, +	const struct libparsesfnt_tabdir_entry *tag); + +int libparsesfnt_parse_fdsc_entries( +	const char *data, size_t size, +	struct libparsesfnt_fdsc_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + + + +/* === 'gasp' (grid-fitting and scan-conversion procedure) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6gasp.html */ + +struct libparsesfnt_gasp { +	uint16_t version; +	uint16_t num_ranges; +}; +#define LIBPARSESFNT_GASP__ "22" + +struct libparsesfnt_gasp_entry { +	uint16_t range_max_ppem; +	uint16_t range_gasp_behaviour; +}; +#define LIBPARSESFNT_GASP_ENTRY__ "22" + +enum libparsesfnt_gasp_behaviour { +	LIBPARSESFNT_GASP_BEHAVIOUR_GRID_FIT = 0x0001, +	LIBPARSESFNT_GASP_BEHAVIOUR_DO_GREY = 0x0002 +}; + +int libparsesfnt_parse_gasp( +	const char *data, size_t size, +	struct libparsesfnt_gasp *infop, +	const struct libparsesfnt_tabdir_entry *tag); + +int libparsesfnt_parse_gasp_entries( +	const char *data, size_t size, +	struct libparsesfnt_gasp_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t first, size_t count); + + + +/* === 'avar' (axis variation) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6avar.html */ + +struct libparsesfnt_avar { +	uint32_t name; +	uint32_t axis_count; +}; +#define LIBPARSESFNT_AVAR__ "44" + +struct libparsesfnt_avar_entry { +	uint16_t pair_count; +	char __padding1[sizeof(size_t) - sizeof(uint16_t)]; /* using sizeof for simplicity (may have same alignment) */ +	size_t libparsesfnt_subentry_location; +}; +#define LIBPARSESFNT_AVAR_ENTRY__ "2" + +struct libparsesfnt_avar_subentry { +	int16_t from_coord; +	int16_t to_coord; +}; +#define LIBPARSESFNT_AVAR_SUBENTRY__ "22" + +int libparsesfnt_parse_avar( +	const char *data, size_t size, +	struct libparsesfnt_avar *infop, +	const struct libparsesfnt_tabdir_entry *tag); + +int libparsesfnt_parse_avar_entries( +	const char *data, size_t size, +	struct libparsesfnt_avar_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, +	size_t *offsetp /* start at 0 */, size_t count); + +int libparsesfnt_parse_avar_subentries( +	const char *data, size_t size, +	struct libparsesfnt_avar_subentry *infop, +	const struct libparsesfnt_avar_entry *entry, +	size_t first, size_t count); + + + +/* === 'meta' (metadata) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6meta.html */ + +struct libparsesfnt_meta { +	uint32_t version; +	uint32_t flags; +	uint32_t data_offset; /* relative to the beginning of this table */ +	uint32_t num_data_maps; +}; +#define LIBPARSESFNT_META__ "4444" + +struct libparsesfnt_meta_entry { +	char tag[4]; +	uint32_t data_offset; /* relative to the beginning of the 'meta' table */ +	uint32_t data_length; +}; +#define LIBPARSESFNT_META_ENTRY__ "111144" + +int libparsesfnt_parse_meta( +	const char *data, size_t size, +	struct libparsesfnt_meta *infop, +	const struct libparsesfnt_tabdir_entry *tag); + +int libparsesfnt_parse_meta_entries( +	const char *data, size_t size, +	struct libparsesfnt_meta_entry *infop, +	const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_meta *meta, +	size_t first, size_t count); + + +#endif diff --git a/libparsesfnt_parse___.c b/libparsesfnt_parse___.c new file mode 100644 index 0000000..17ee018 --- /dev/null +++ b/libparsesfnt_parse___.c @@ -0,0 +1,188 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +static uint16_t +parse16(const char *data) +{ +	uint16_t b1 = (uint16_t)((const uint8_t *)data)[0]; +	uint16_t b2 = (uint16_t)((const uint8_t *)data)[1]; +	b1 = (uint16_t)(b1 << 8); +	b2 = (uint16_t)(b2 << 0); +	return (uint16_t)(b1 | b2); +} + +static uint32_t +parse32(const char *data) +{ +	uint32_t b1 = (uint32_t)((const uint8_t *)data)[0]; +	uint32_t b2 = (uint32_t)((const uint8_t *)data)[1]; +	uint32_t b3 = (uint32_t)((const uint8_t *)data)[2]; +	uint32_t b4 = (uint32_t)((const uint8_t *)data)[3]; +	b1 = (uint32_t)(b1 << 24); +	b2 = (uint32_t)(b2 << 16); +	b3 = (uint32_t)(b3 << 8); +	b4 = (uint32_t)(b4 << 0); +	return (uint32_t)(b1 | b2 | b3 | b4); +} + +static uint64_t +parse64(const char *data) +{ +	uint64_t b1 = (uint64_t)((const uint8_t *)data)[0]; +	uint64_t b2 = (uint64_t)((const uint8_t *)data)[1]; +	uint64_t b3 = (uint64_t)((const uint8_t *)data)[2]; +	uint64_t b4 = (uint64_t)((const uint8_t *)data)[3]; +	uint64_t b5 = (uint64_t)((const uint8_t *)data)[4]; +	uint64_t b6 = (uint64_t)((const uint8_t *)data)[5]; +	uint64_t b7 = (uint64_t)((const uint8_t *)data)[6]; +	uint64_t b8 = (uint64_t)((const uint8_t *)data)[7]; +	b1 = (uint32_t)(b1 << 56); +	b2 = (uint32_t)(b2 << 48); +	b3 = (uint32_t)(b3 << 40); +	b4 = (uint32_t)(b4 << 32); +	b5 = (uint32_t)(b5 << 24); +	b6 = (uint32_t)(b6 << 16); +	b7 = (uint32_t)(b7 << 8); +	b8 = (uint32_t)(b8 << 0); +	return (uint32_t)(b1 | b2 | b3 | b4 | b5 | b6 | b7 | b8); +} + + +static void +sign8(union {uint8_t u; int8_t s;} *info) +{ +	info->s = ((info->u >> 7) ? -(int8_t)(~info->u + 1) : (int8_t)info->u); +} + +static void +sign16(union {uint16_t u; int16_t s;} *info) +{ +	info->s = ((info->u >> 15) ? -(int16_t)(~info->u + 1) : (int16_t)info->u); +} + +static void +sign32(union {uint32_t u; int32_t s;} *info) +{ +	info->s = ((info->u >> 31) ? -(int32_t)(~info->u + 1) : (int32_t)info->u); +} + +static void +sign64(union {uint64_t u; int64_t s;} *info) +{ +	info->s = ((info->u >> 63) ? -(int64_t)(~info->u + 1) : (int64_t)info->u); +} + + +int +libparsesfnt_parse___(const char *data, size_t size, void *infop, size_t esize, +                      const char *fmt, size_t offset, size_t offset2, size_t offset3, +                      size_t first, size_t count, const struct libparsesfnt_tabdir_entry *tag) +{ +	const char *s; +	size_t tag_offset = 0; +	size_t need = 0; +	size_t padding = 0; +	int is_signed = 0; +	char *info = infop; + +	if (offset > size || offset2 > size - offset) +		goto ebfont; +	offset += offset2; +	if (offset3 > size - offset) +		goto ebfont; +	offset += offset3; + +	if (tag) +		tag_offset = offset - tag->offset; + +	for (s = fmt; *s; s++) { +		if (*s == 'p') +			padding += 1; +		else if (*s == '1' || *s == '.') +			need += 1; +		else if (*s == '2') +			need += 2; +		else if (*s == '4') +			need += 4; +		else if (*s == '8') +			need += 8; +	} + +	if (count > SIZE_MAX - first || +	    first > (SIZE_MAX - offset) / need) +		goto efbig; +	offset += first * need; + +	if (offset > size || need > size - offset) +		goto ebfont; + +	if (count > (SIZE_MAX - offset) / need) +		goto efbig; +	if (offset + count * need > size || +	    (tag && (tag->length < count * need || +	             tag->length > size || +	             tag_offset > tag->length || +	             first + count > (tag->length - tag_offset) / need))) +		goto ebfont; + +	data = &data[offset]; + +	padding = esize - need - padding; +	for (; count--; info = &info[padding]) { +		for (s = fmt; *s; s++) { +			if (*s == 'p') { +				*info++ = 0; +			} else if (*s == '.') { +				*info++ = *data++; +			} else if (*s == '1') { +				*(uint8_t *)info = *(const uint8_t *)data; +				if (is_signed) +					sign8((void *)info); +				data = &data[1]; +				info = &info[1]; +#ifdef __GNUC__ +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wcast-align" /* in practice alignment will be correct */ +#endif +			} else if (*s == '2') { +				*(uint16_t *)info = parse16(data); +				if (is_signed) +					sign16((void *)info); +				data = &data[2]; +				info = &info[2]; +			} else if (*s == '4') { +				*(uint32_t *)info = parse32(data); +				if (is_signed) +					sign32((void *)info); +				data = &data[4]; +				info = &info[4]; +			} else if (*s == '8') { +				*(uint64_t *)info = parse64(data); +				if (is_signed) +					sign64((void *)info); +				data = &data[8]; +				info = &info[8]; +#ifdef __GNUC__ +# pragma GCC diagnostic pop +#endif +			} else if (*s == '-') { +				is_signed = 1; +			} else if (*s == '+') { +				is_signed = 0; +			} else { +				abort(); +			} +		} +	} + +	return 0; + +efbig: +	errno = EFBIG; +	return -1; + +ebfont: +	errno = EBFONT; +	return -1; +} diff --git a/libparsesfnt_parse_fontdir.c b/libparsesfnt_parse_fontdir.c new file mode 100644 index 0000000..ce3085a --- /dev/null +++ b/libparsesfnt_parse_fontdir.c @@ -0,0 +1,11 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_fontdir( +			const char *data, size_t size, +			struct libparsesfnt_fontdir *infop) +{ +	return PARSE(LIBPARSESFNT_FONTDIR__, 0, 0, 0, 0, 1, NULL); +} diff --git a/libparsesfnt_parse_tabdir.c b/libparsesfnt_parse_tabdir.c new file mode 100644 index 0000000..1302e3a --- /dev/null +++ b/libparsesfnt_parse_tabdir.c @@ -0,0 +1,12 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_tabdir( +			const char *data, size_t size, +			struct libparsesfnt_tabdir_entry *infop, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_TABDIR_ENTRY__, 12, 0, 0, first, count, NULL); +} @@ -0,0 +1,24 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_loca_short( +			const char *data, size_t size, +			struct libparsesfnt_loca_short_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_LOCA_SHORT_ENTRY__, tag->offset, 0, 0, first, count, tag); +} + + +int +libparsesfnt_parse_loca_long( +			const char *data, size_t size, +			struct libparsesfnt_loca_long_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_LOCA_LONG_ENTRY__, tag->offset, 0, 0, first, count, tag); +} @@ -0,0 +1,44 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_ltag( +			const char *data, size_t size, +			struct libparsesfnt_ltag *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	return PARSE(LIBPARSESFNT_LTAG__, tag->offset, 0, 0, 0, 1, tag); +} + + +int +libparsesfnt_parse_ltag_entries( +			const char *data, size_t size, +			struct libparsesfnt_ltag_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_LTAG_ENTRY__, tag->offset, 12, 0, first, count, tag); +} + + +int +libparsesfnt_get_ltag_offset( +			size_t size, +			size_t *offsetp, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_ltag_entry *entry) +{ +	size_t offset; +	if ((size_t)entry->offset > size - (size_t)tag->offset) { +		errno = EBFONT; +		return -1; +	} +	offset = (size_t)tag->offset + (size_t)entry->offset; +	if ((size_t)entry->length > size - offset) { +		errno = EBFONT; +		return -1; +	} +	*offsetp = offset; +	return 0; +} @@ -0,0 +1,34 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_maxp( +			const char *data, size_t size, +			struct libparsesfnt_maxp *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	uint8_t major_high, major_low; +	const char *fmt; + +	major_high = *(const uint8_t *)&data[tag->offset + 0]; +	major_low  = *(const uint8_t *)&data[tag->offset + 1]; + +	if (major_high == 0 && major_low == 0) { +		if (*(const uint8_t *)&data[tag->offset + 2] < 0x50U) +			goto bfont; +		fmt = LIBPARSESFNT_MAXP__""LIBPARSESFNT_MAXP_0_5__; + +	} else if (major_high && major_low == 1) { +		fmt = LIBPARSESFNT_MAXP__""LIBPARSESFNT_MAXP_1_0__; + +	} else { +		goto bfont; +	} + +	return PARSE(fmt, tag->offset, 0, 0, 0, 1, tag); + +bfont: +	errno = EBFONT; +	return -1; +} @@ -0,0 +1,32 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_meta( +			const char *data, size_t size, +			struct libparsesfnt_meta *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	int ret; +	ret = PARSE(LIBPARSESFNT_META__, tag->offset, 0, 0, 0, 1, tag); +	if (!ret) { +		if (infop->data_offset > size - tag->offset || +		    infop->num_data_maps > (size - tag->offset - infop->data_offset) / 12) { +			errno = EBFONT; +			return -1; +		} +	} +	return ret; +} + + +int +libparsesfnt_parse_meta_entries( +			const char *data, size_t size, +			struct libparsesfnt_meta_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_meta *meta, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_META_ENTRY__, tag->offset, meta->data_offset, 0, first, count, NULL); +} @@ -0,0 +1,33 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_name( +			const char *data, size_t size, +			struct libparsesfnt_name *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	if ((tag->length - 6) % 12) +		goto ebfont; +	if (PARSE(LIBPARSESFNT_NAME__, tag->offset, 0, 0, 0, 1, tag)) +		return -1; +	if ((tag->length - 6) / 12 != infop->count) +		goto ebfont; +	return 0; + +ebfont: +	errno = EBFONT; +	return -1; +} + + +int +libparsesfnt_parse_name_entries( +			const char *data, size_t size, +			struct libparsesfnt_name_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_NAME_ENTRY__, tag->offset, 6, 0, first, count, tag); +} @@ -0,0 +1,76 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_trak( +			const char *data, size_t size, +			struct libparsesfnt_trak *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	return PARSE(LIBPARSESFNT_TRAK__, tag->offset, 0, 0, 0, 1, tag); +} + + +int +libparsesfnt_parse_trak_horiz( +			const char *data, size_t size, +			struct libparsesfnt_trak_data *infop, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak *trak) +{ +	return PARSE(LIBPARSESFNT_TRAK_DATA__, tag->offset, trak->horiz_offset, 0, 0, 1, NULL); +} + + +int +libparsesfnt_parse_trak_vert( +			const char *data, size_t size, +			struct libparsesfnt_trak_data *infop, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak *trak) +{ +	return PARSE(LIBPARSESFNT_TRAK_DATA__, tag->offset, trak->vert_offset, 0, 0, 1, NULL); +} + + +int +libparsesfnt_parse_trak_horiz_track_entries( +			const char *data, size_t size, +			struct libparsesfnt_trak_track_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak *trak, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_TRAK_TRACK_ENTRY__, tag->offset, trak->horiz_offset, 8, first, count, NULL); +} + + +int +libparsesfnt_parse_trak_vert_track_entries( +			const char *data, size_t size, +			struct libparsesfnt_trak_track_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak *trak, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_TRAK_TRACK_ENTRY__, tag->offset, trak->vert_offset, 8, first, count, NULL); +} + + +int +libparsesfnt_parse_trak_size_entries( +			const char *data, size_t size, +			struct libparsesfnt_trak_size_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak_data *trak_data, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_TRAK_SIZE_ENTRY__, tag->offset, trak_data->size_table_offset, 0, first, count, NULL); +} + + +int +libparsesfnt_parse_trak_track_size_entries( +			const char *data, size_t size, +			struct libparsesfnt_trak_size_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_trak_track_entry *track, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_TRAK_SIZE_ENTRY__, tag->offset, track->offset, 0, first, count, NULL); +} @@ -0,0 +1,12 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_vhea( +			const char *data, size_t size, +			struct libparsesfnt_vhea *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	return PARSE(LIBPARSESFNT_VHEA__, tag->offset, 0, 0, 0, 1, tag); +} @@ -0,0 +1,44 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_vmtx( +			const char *data, size_t size, +			struct libparsesfnt_vmtx_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_VMTX_ENTRY__, tag->offset, 0, 0, first, count, tag); +} + + +int +libparsesfnt_get_vmtx_tsb_subtable_length( +			size_t *lengthp, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_vhea *vhea) +{ +	size_t off; +	/* vhea->num_advances_in_vmtx_table is uint16_t, so overflow is impossible */ +	off = (size_t)vhea->num_advances_in_vmtx_table * 4; +	if (off > tag->length || (tag->length - off) % 2) { +		errno = EBFONT; +		return -1; +	} +	*lengthp = (tag->length - off) / 2; +	return 0; +} + + +int +libparsesfnt_parse_vmtx_tsb_subtable( +			const char *data, size_t size, +			struct libparsesfnt_vmtx_tsb_subtable_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_vhea *vhea, +			size_t first, size_t count) +{ +	size_t off; +	/* vhea->num_advances_in_vmtx_table is uint16_t, so overflow is impossible */ +	off = (size_t)vhea->num_advances_in_vmtx_table * 4; +	return PARSE(LIBPARSESFNT_VMTX_TSB_SUBTABLE_ENTRY__, tag->offset, off, 0, first, count, NULL); +} @@ -0,0 +1,48 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_xref( +			const char *data, size_t size, +			struct libparsesfnt_xref *infop, +			const struct libparsesfnt_tabdir_entry *tag) +{ +	return PARSE(LIBPARSESFNT_XREF__, tag->offset, 0, 0, 0, 1, tag); +} + + +int +libparsesfnt_parse_xref_entries( +			const char *data, size_t size, +			struct libparsesfnt_xref_entry *infop, +			const struct libparsesfnt_tabdir_entry *tag, +			size_t first, size_t count) +{ +	return PARSE(LIBPARSESFNT_XREF_ENTRY__, tag->offset, 16, 0, first, count, tag); +} + + +int +libparsesfnt_get_xref_offset( +			size_t size, +			size_t *offsetp, +			const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_xref *xref, +			const struct libparsesfnt_xref_entry *entry) +{ +	size_t offset = (size_t)tag->offset; +	if ((size_t)xref->string_offset > size - offset) +		goto ebfont; +	offset += (size_t)xref->string_offset; +	if ((size_t)entry->string_offset > size - offset) +		goto ebfont; +	offset += (size_t)entry->string_offset; +	if ((size_t)entry->string_length > size - offset) +		goto ebfont; +	*offsetp = offset; +	return 0; + +ebfont: +	errno = EBFONT; +	return -1; +} | 
