diff options
-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; +} |