diff options
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | hdmx.c | 89 | ||||
-rw-r--r-- | libparsesfnt.h | 35 |
3 files changed, 126 insertions, 1 deletions
@@ -22,7 +22,8 @@ MODULES =\ fdsc\ gasp\ avar\ - meta + meta\ + hdmx OBJ =\ libparsesfnt_parse___.o\ @@ -0,0 +1,89 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +int +libparsesfnt_parse_hdmx( + const char *data, size_t size, + struct libparsesfnt_hdmx *infop, + const struct libparsesfnt_tabdir_entry *tag) +{ + int ret; + ret = PARSE(LIBPARSESFNT_HDMX__, tag->offset, 0, 0, 0, 1, tag); + if (!ret) { + if (!infop->record_size || + (size_t)infop->num_records > (size_t)tag->length / (size_t)infop->record_size) { + errno = EBFONT; + return -1; + } + } + return ret; +} + + +int +libparsesfnt_parse_hdmx_entries( + const char *data, size_t size, + struct libparsesfnt_hdmx_v0_entry *infop, + const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_hdmx *hdmx, + size_t first, size_t count) +{ + size_t off; + + off = tag->offset; + if (off > size || 8 > size - off || hdmx->record_size < 2) + goto ebfont; + off += 8; + if (first > (size - off) / hdmx->record_size) + goto ebfont; + off += hdmx->record_size * first; + if (count > (size - off) / hdmx->record_size) + goto ebfont; + + data = &data[off]; + for (; count--; infop++) { + infop->pixel_size = ((const uint8_t *)data)[0]; + infop->maximum_width = ((const uint8_t *)data)[1]; + data = &data[2]; + } + + return 0; + +ebfont: + errno = EBFONT; + return -1; +} + + +int +libparsesfnt_parse_hdmx_v0_subentry( + const char *data, size_t size, + uint8_t *widthp, + const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_hdmx *hdmx, size_t record, + size_t first, size_t count) +{ + size_t off; + + off = tag->offset; + if (off > size || 10 > size - off) + goto ebfont; + off += 10; + if (record > (size - off) / hdmx->record_size) + goto ebfont; + off += hdmx->record_size * record; + if (first > size - off) + goto ebfont; + off += first; + if (count > size - off) + goto ebfont; + + if (2 > hdmx->record_size || first + count > hdmx->record_size - 2) + goto ebfont; + + memcpy(widthp, &data[off], count); + return 0; + +ebfont: + errno = EBFONT; + return -1; +} diff --git a/libparsesfnt.h b/libparsesfnt.h index 809fad7..f79ed03 100644 --- a/libparsesfnt.h +++ b/libparsesfnt.h @@ -768,4 +768,39 @@ int libparsesfnt_parse_meta_entries( size_t first, size_t count); + +/* === 'hdmx' (horizontal device metrics) === */ +/* https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6hdmx.html */ + +struct libparsesfnt_hdmx { + uint16_t version; + uint16_t num_records; + uint32_t record_size; /* includes alignment */ +}; +#define LIBPARSESFNT_HDMX__ "224" + +struct libparsesfnt_hdmx_v0_entry { + uint8_t pixel_size; + uint8_t maximum_width; +}; +#define LIBPARSESFNT_HDMX_V0_ENTRY__ "11" + +int libparsesfnt_parse_hdmx( + const char *data, size_t size, + struct libparsesfnt_hdmx *infop, + const struct libparsesfnt_tabdir_entry *tag); + +int libparsesfnt_parse_hdmx_v0_entries( + const char *data, size_t size, + struct libparsesfnt_hdmx_v0_entry *infop, + const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_hdmx *hdmx, + size_t first, size_t count); + +int libparsesfnt_parse_hdmx_v0_subentry( + const char *data, size_t size, + uint8_t *widthp, + const struct libparsesfnt_tabdir_entry *tag, const struct libparsesfnt_hdmx *hdmx, size_t record, + size_t first, size_t count); + + #endif |