From a81c96c0348af8caf6ae45e2d942a676792a2a31 Mon Sep 17 00:00:00 2001 From: Mattias Andrée Date: Sun, 13 Oct 2024 11:17:48 +0200 Subject: Documentation and minor improvements MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mattias Andrée --- demo.c | 28 +- libparsepcf.h | 681 ++++++++++++++++++++++++++++++++-- libparsepcf_destroy_preparsed_font.c | 6 +- libparsepcf_get_accelerators.c | 73 ++-- libparsepcf_get_bitmap_offsets.c | 9 +- libparsepcf_get_bitmaps.c | 29 +- libparsepcf_get_encoding.c | 26 +- libparsepcf_get_glyph_indices.c | 7 +- libparsepcf_get_glyph_name_subtable.c | 11 +- libparsepcf_get_glyph_names.c | 19 +- libparsepcf_get_metrics.c | 45 ++- libparsepcf_get_metrics_count.c | 15 +- libparsepcf_get_properties.c | 21 +- libparsepcf_get_property_subtable.c | 13 +- libparsepcf_get_swidth_count.c | 11 +- libparsepcf_get_swidths.c | 7 +- libparsepcf_get_table_count.c | 7 +- libparsepcf_get_tables.c | 17 +- libparsepcf_preparse_font.c | 4 +- 19 files changed, 833 insertions(+), 196 deletions(-) diff --git a/demo.c b/demo.c index 4a6cf10..80ac748 100644 --- a/demo.c +++ b/demo.c @@ -180,10 +180,12 @@ print_bitmaps(void) exit(1); } for (bitmap_i = 0; bitmap_i < bitmaps.glyph_count; bitmap_i++) { +#if 0 printf("\t #%zu: %zu -> %p (maxsize=%zu)\n", bitmap_i, bitmaptab[bitmap_i], (const void *)&bitmaps.bitmap_data[bitmaptab[bitmap_i]], bitmaps.bitmap_size - bitmaptab[bitmap_i]); +#endif } free(bitmaptab); } @@ -296,8 +298,8 @@ print_font(void) perror("libparsepcf_get_table_count"); exit(1); } - fprintf(stderr, "size: %zu\n", len); - fprintf(stderr, "ntables: %zu\n", table_n); + printf("size: %zu\n", len); + printf("ntables: %zu\n", table_n); tables = calloc(table_n, sizeof(*tables)); if (!tables) { @@ -336,7 +338,7 @@ print_font(void) print_glyph_names(); break; #endif -#if 0 +#if 1 case LIBPARSEPCF_BITMAPS: print_bitmaps(); break; @@ -518,7 +520,9 @@ print_glyph(size_t glyph) pixel = "[]"; } - printf("\033[%sm%s", ((bitmap[byte] >> bit) & 1) ? "1;37" : "2;37", pixel); + printf("\033[%sm%s\033[%sm", + ((bitmap[byte] >> bit) & 1) ? "1;37" : "2;37", pixel, + (int64_t)y + 1 == (int64_t)mtx.character_ascent ? "0;4" : "0"); } /* If horizontal advance is larger than character width, print extent in black */ @@ -663,9 +667,13 @@ print_line(const char *str) const uint8_t *s = (const void *)str; int32_t xpos = 0, left = 0, right = 0, ascent = 0, descent = 0; char **lines = NULL; - uint32_t codepoint = 0, hi, lo; + uint32_t codepoint = 0; + uint16_t hi, lo, k, m; size_t glyph, n = 0, y, x, width, height; + k = (uint16_t)(font.encoding.max_byte2 - font.encoding.min_byte2); + m = (uint16_t)(font.encoding.min_byte1 * k + font.encoding.min_byte2); + while (*s) { /* Very sloppy UTF-8 decoding */ if (n) { @@ -706,9 +714,9 @@ print_line(const char *str) } glyph = codepoint - (uint32_t)font.encoding.min_byte2; } else { - hi = (codepoint >> 8) & UINT32_C(0xFF); - lo = (codepoint >> 0) & UINT32_C(0xFF); - if (codepoint > UINT32_C(0xFF) || + hi = (uint16_t)((codepoint >> 8) & 0xFFU); + lo = (uint16_t)((codepoint >> 0) & 0xFFU); + if (codepoint > UINT16_C(0xFF) || hi < (uint32_t)font.encoding.min_byte1 || hi > (uint32_t)font.encoding.max_byte1 || lo < (uint32_t)font.encoding.min_byte2 || @@ -716,9 +724,7 @@ print_line(const char *str) glyph = (size_t)font.encoding.default_char; goto have_glyph; } - hi -= (size_t)font.encoding.min_byte1; - lo -= (size_t)font.encoding.min_byte2; - glyph = hi * (size_t)(font.encoding.max_byte2 - font.encoding.min_byte2 + 1) + lo; + glyph = (size_t)(uint16_t)(hi * k + lo - m); } /* For the purpose of the demo we are assuming ASCII/UCS-2 */ if (libparsepcf_get_glyph_indices(file, len, font.enc_table, &font.encoding, &glyph, glyph, 1)) { diff --git a/libparsepcf.h b/libparsepcf.h index 6931898..eef98c8 100644 --- a/libparsepcf.h +++ b/libparsepcf.h @@ -34,7 +34,7 @@ struct libparsepcf_table { /** * How the data in the table is formatted * - * This is only unsed internally, and supported + * This is only used internally, and supported * values are not exposed the the user */ uint32_t format; @@ -74,7 +74,7 @@ struct libparsepcf_table { * * @throws EBFONT The file is not a properly formatted PCF file */ -int libparsepcf_get_table_count(const char *, size_t, size_t *); +int libparsepcf_get_table_count(const void *, size_t, size_t *); /** * Get table metadata from the file @@ -85,73 +85,302 @@ int libparsepcf_get_table_count(const char *, size_t, size_t *); * @param first The index of the first table to store in `tables`, * the first table in the file has the index 0 * @param count The number of tables to store in `tables`; - * may not return the number of tables as retrieved - * by `libparsepcf_get_table_count` + * may not exceed the number of tables as retrieved + * by `libparsepcf_get_table_count` minus `first` * @return 0 on success, -1 on failure * * @throws EBFONT The file is not a properly formatted PCF file */ -int libparsepcf_get_tables(const char *, size_t, struct libparsepcf_table *, size_t, size_t); +int libparsepcf_get_tables(const void *, size_t, + struct libparsepcf_table *, + size_t, size_t); +/** + * Property list + */ struct libparsepcf_properties { + /** + * The number of properties available + */ size_t property_count; + + /** + * The size of `.strings` + * + * Used internally to detect corruption + */ size_t strings_size; + + /** + * Property names + * + * This is a buffer which requires an offset + * table, that is found in the file, to parse + * + * This is a pointer to data within the file + * + * Intended for internal use + */ const char *strings; }; +/** + * Property name and value + */ struct libparsepcf_property_subtable { + /** + * The name of the property + */ const char *name; + + /** + * 1 if the value is a string, + * 0 if the value is an integer + */ int is_string_property; + + /** + * The value of the property, + * use `.value.signed_value` if `.is_string_property` is 0, + * use `.value.string_value` if `.is_string_property` is 1 + */ union { + /** + * The value + * + * Used if `.is_string_property` is 0 + * (if the value is signed integer) + */ int32_t signed_value; + + /** + * The value + * + * Used if `.is_string_property` is 1 + * (if the value is string) + */ const char *string_value; } value; }; -int libparsepcf_get_properties(const char *, size_t, +/** + * Get the properties available in the file + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_PROPERTIES`, + * extracted using the `libparsepcf_get_tables` function + * @param meta Output parameter for the list of properties + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ +int libparsepcf_get_properties(const void *, size_t, const struct libparsepcf_table *, struct libparsepcf_properties *); -int libparsepcf_get_property_subtable(const char *, size_t, +/** + * Get the names and values of properties in the file + * + * The first four arguments shall be the same as + * passed into `libparsepcf_get_properties` + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_PROPERTIES`, + * extracted using the `libparsepcf_get_tables` function + * @param meta List of properties + * @param props Output parameter for the properties + * @param first The index of the first property to store in `props`, + * the first property in the file has the index 0 + * @param count The number of properties to store in `props`; + * may not exceed the number of properties (`.property_count`) + * as retrieved by `libparsepcf_get_properties` minus `first` + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ +int libparsepcf_get_property_subtable(const void *, size_t, const struct libparsepcf_table *, const struct libparsepcf_properties *, - struct libparsepcf_property_subtable *, size_t, size_t); + struct libparsepcf_property_subtable *, + size_t, size_t); +/** + * Glyph metrics + */ struct libparsepcf_metrics { + /** + * The number of pixels right of (negative if left of) + * the origin (caret position) of the leftmost ink-on + * pixel in the glyph + */ int16_t left_side_bearing; + + /** + * The number of pixels right of (negative if left of) + * the origin (caret position) of the rightmost ink-on + * pixel in the glyph + */ int16_t right_side_bearing; + + /** + * The number of pixels the next characters origin shall + * be right of the current character's origin (that is + * the number of pixels the caret shall advance) + */ int16_t character_width; + + /** + * The number of pixels the character ascend above + * the baseline (if non-positive, it's fully below + * the baseline) + */ int16_t character_ascent; + + /** + * The number of pixels the character descend below + * the baseline (if non-positive, it's fully above + * the baseline) + */ int16_t character_descent; + + /** + * Application-specific character attribute bits + */ uint16_t character_attributes; }; -int libparsepcf_get_metrics_count(const char *, size_t, const struct libparsepcf_table *, size_t *); +/** + * Get number of glyph metrics available in the file + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_METRICS` + * or `LIBPARSEPCF_INK_METRICS`, extracted using the + * `libparsepcf_get_tables` function + * @param count Output parameter for glyph metric count + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + * + * The `LIBPARSEPCF_METRICS` table is used for layout information, + * and the `LIBPARSEPCF_INK_METRICS` table is used for rendering + * information; that is `LIBPARSEPCF_METRICS` contains the size + * of the glyphs where as `LIBPARSEPCF_INK_METRICS` contains the + * size of the glyph bitmaps. + */ +int libparsepcf_get_metrics_count(const void *, size_t, + const struct libparsepcf_table *, + size_t *); -int libparsepcf_get_metrics(const char *, size_t, +/** + * Get the metrics for glyphs + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_METRICS` + * or `LIBPARSEPCF_INK_METRICS`, extracted using the + * `libparsepcf_get_tables` function + * @param metrics Output parameter for the glyph metrics + * @param first The index of the first glyph's metrics to store in + * `metrics`, the first glyph in the file has the index 0 + * @param count The number of glyph's metrics to store in `metrics`; + * may not exceed the number of glyph as retrieved by + * `libparsepcf_get_metrics_count` (stored in it's last + * argument) minus `first` + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + * + * The `LIBPARSEPCF_METRICS` table is used for layout information, + * and the `LIBPARSEPCF_INK_METRICS` table is used for rendering + * information; that is `LIBPARSEPCF_METRICS` contains the size + * of the glyphs where as `LIBPARSEPCF_INK_METRICS` contains the + * size of the glyph bitmaps. + */ +int libparsepcf_get_metrics(const void *, size_t, const struct libparsepcf_table *, - struct libparsepcf_metrics *, size_t, size_t); + struct libparsepcf_metrics *, + size_t, size_t); +/** + * Glyph name list + */ struct libparsepcf_glyph_names { + /** + * The number of glyphs available + */ size_t glyph_count; + + /** + * The size of `.strings` + * + * Used internally to detect corruption + */ size_t strings_size; + + /** + * Glyph names + * + * This is a buffer which requires an offset + * table, that is found in the file, to parse + * + * This is a pointer to data within the file + * + * Primarily for internal use + */ const char *strings; }; -int libparsepcf_get_glyph_names(const char *, size_t, +/** + * Get the PostScript glyph names available in the file + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_GLYPH_NAMES`, + * extracted using the `libparsepcf_get_tables` function + * @param meta Output parameter for the list of glyph names + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ +int libparsepcf_get_glyph_names(const void *, size_t, const struct libparsepcf_table *, struct libparsepcf_glyph_names *); -int libparsepcf_get_glyph_name_subtable(const char *, size_t, +/** + * Get the PostScript glyph names available in the file + * + * The first four arguments shall be the same as + * passed into `libparsepcf_get_glyph_names` + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_GLYPH_NAMES`, + * extracted using the `libparsepcf_get_tables` function + * @param meta List of glyph names + * @param names Output parameter for the glyph names; each stored name + * will be the pointer `file` with an offset + * @param first The index of the first glyph's whose name to store in + * `names`, the first glyph in the file has the index 0 + * @param count The number of glyph names to store in `names`; + * may not exceed the number of glyph (`.glyph_count`) + * as retrieved by `libparsepcf_get_glyph_names` minus `first` + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ +int libparsepcf_get_glyph_name_subtable(const void *, size_t, const struct libparsepcf_table *, const struct libparsepcf_glyph_names *, const char **, size_t, size_t); @@ -159,21 +388,40 @@ int libparsepcf_get_glyph_name_subtable(const char *, size_t, +/** + * Glyph bitmap metadata + */ struct libparsepcf_bitmaps { + /** + * The number of glyph available + */ size_t glyph_count; + + /** + * The size of `.bitmap_data` + */ size_t bitmap_size; + size_t bit_packing; + + /** + * The number of bytes each row is + * padded to align to + * + * This will always be a power of two + */ size_t row_padding; + int lsbyte; int lsbit; const uint8_t *bitmap_data; }; -int libparsepcf_get_bitmaps(const char *, size_t, +int libparsepcf_get_bitmaps(const void *, size_t, const struct libparsepcf_table *, struct libparsepcf_bitmaps *); -int libparsepcf_get_bitmap_offsets(const char *, size_t, +int libparsepcf_get_bitmap_offsets(const void *, size_t, const struct libparsepcf_table *, const struct libparsepcf_bitmaps *, size_t *, size_t, size_t); @@ -181,34 +429,146 @@ int libparsepcf_get_bitmap_offsets(const char *, size_t, +/** + * Glyph index lookup data + * + * This structure describes how to lookup a glyph's index + * based on the character's encoding. The properties + * "CHARSET_REGISTRY" and "CHARSET_ENCODING" are used to + * determine which character encoding scheme is used in + * the font file. + * + * This structure contains information for how to calculate + * the codepoint (provided to `libparsepcf_get_glyph_indices` + * to look up the index of a character's glyph) for a character. + * The PCF font format support single-byte encodings and + * dual-byte encodings (variable byte encodings are not + * supported), if the fields `.min_byte1` and `.max_byte1` + * are both set to 0, the file uses single-byte encoding, + * otherwise it uses dual-byte encoding. + * + * For single-byte encodings, the codepoint is calculated + * by subtracting `.min_byte2` from the byte. + * + * For dual-byte encodings, if the first byte is `byte1` and the + * second byte is `byte2` for a character, the character's codepoint is + * `(byte1-.min_byte1) * (.max_byte2-.min_byte2+1) + (byte2-.min_byte2)`, + * or, using less operations, `byte1 * k + byte2 - m` where `k` and `m` + * are precalculated as `k = .max_byte2 - .min_byte2 + 1` and + * `m = .min_byte1 * k + .min_byte2`. + */ struct libparsepcf_encoding { + /** + * If the second byte (or only byte for single-byte + * encodings) is lower this value, this character + * has no glyph in the font + */ uint16_t min_byte2; + + /** + * If the second byte (or only byte for single-byte + * encodings) is higher this value, this character + * has no glyph in the font + */ uint16_t max_byte2; + + /** + * For dual-byte encodings, if the first byte is + * lower than this value, the character has no + * glyph in the font + * + * Unused for single-byte encoding + */ uint16_t min_byte1; + + /** + * For dual-byte encodings, if the first byte is + * higher than this value, the character has no + * glyph in the font + * + * Unused for single-byte encoding + */ uint16_t max_byte1; + + /** + * The index of the glyph to use when no glyph is + * available for a character + * + * It value should _not_ be looked up with + * `libparsepcf_get_glyph_indices` but used as if + * `libparsepcf_get_glyph_indices` has already been + * called. In fact, the glyph reference by this + * field does not necessarily correspond to a + * character and thus may not be available in the + * encoding table + * + * This name of this field is choosen for consistence + * with the documentation the implementation is based + * on, and is confusing, it ought to be called + * "default_glyph" + */ uint16_t default_char; - size_t glyph_count; - /* If min_byte1 == 0 and max_byte1 == 0 (single byte encoding): - * glyph_index = glyph_indices[encoding - min_char_or_byte2] - * not included if encoding > max_byte2 or glyph_index == 0xFFFF + + /** + * The number of entries available in the index table, + * this is not number of glyphs in the file, but rather + * the product of `.max_byte2 - .min_byte2 + 1` and + * `.max_byte1 - .min_byte1 + 1`. * - * Otherwise (dual byte encoding): - * [min_byte1, max_byte1] = allowed range of the more signficant of the 2 bytes (the first byte) - * [min_byte2, max_byte2] = allowed range of the less signficant of the 2 bytes (the second byte) - * e1 = encoding[0] - min_byte1 - * e2 = encoding[1] - min_byte2 - * glyph_index = glyph_indices[e1 * (max_byte2 - min_byte2 + 1) + e2] - * not included if out of range or or glyph_index == 0xFFFF + * This name of this field is choosen for consistence + * with the documentation the implementation is based + * on, and is confusing, it ought to be called "char_count" */ + size_t glyph_count; }; +/** + * Glyph index returned when there is no glyph + * available for the character + */ #define LIBPARSEPCF_NOT_ENCODED ((size_t)0xFFFFUL) -int libparsepcf_get_encoding(const char *, size_t, +/** + * Get the glyph index lookup metadata for the file + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_BDF_ENCODINGS`, + * extracted using the `libparsepcf_get_tables` function + * @param meta Output parameter for the glyph index lookup metadata + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ +int libparsepcf_get_encoding(const void *, size_t, const struct libparsepcf_table *, struct libparsepcf_encoding *); -int libparsepcf_get_glyph_indices(const char *, size_t, +/** + * Get the glyph index in the file for characters + * + * The first four arguments shall be the same as + * passed into `libparsepcf_get_properties` + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_PROPERTIES`, + * extracted using the `libparsepcf_get_tables` function + * @param meta Glyph index lookup metadata + * @param indices Output parameter for the glyph indices; for any character + * the index `LIBPARSEPCF_NOT_ENCODED` is stored, the character + * is not included in the font + * @param first The codepoint of the first character whose index to store in + * `indices`; see the description of `struct libparsepcf_encoding` + * for information on how to calculate a character's codepoint + * @param count The number of glyph indices to store in `indices`; + * may not exceed the number of characters (`.glyph_count`) + * as retrieved by `libparsepcf_get_encoding` minus `first` + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ +int libparsepcf_get_glyph_indices(const void *, size_t, const struct libparsepcf_table *, const struct libparsepcf_encoding *, size_t *, size_t, size_t); @@ -216,87 +576,328 @@ int libparsepcf_get_glyph_indices(const char *, size_t, +/** + * Information, available for optimisation, about the font + */ struct libparsepcf_accelerators { /** - * Whether metrics[i].right_side_bearing - metrics[i].character_width - * less than or equal to .min_bounds.left_side_bearing for all i + * Whether `metrics[i].right_side_bearing - metrics[i].character_width` + * less than or equal to `.min_bounds.left_side_bearing` for all `i` */ uint8_t no_overlap : 1; + + /** + * Whether all glyph use the same layout metrics + */ uint8_t constant_metrics : 1; + /** - * .constant_metrics and, for all characters, left side bearing = 0, - * right side bearing = character width, ascent = .font_ascent, and - * descent = .font_descent + * `.constant_metrics` and, for all characters, left side bearing = 0, + * right side bearing = character width, ascent = `.font_ascent`, and + * descent = `.font_descent` */ uint8_t terminal_font : 1; + + /** + * Whether all glyph have the same layout width + */ uint8_t constant_width : 1; + /** * Whether all inked bits are inside the glyph's box */ uint8_t ink_inside : 1; + /** * Whether the ink metrics differ from the metrics for some glyph */ uint8_t ink_metrics : 1; + + /** + * Whether the font is a right-to-left font + */ uint8_t draw_rtl : 1; + /** - * If 0, .ink_min_bounds and .ink_max_bounds are just copies of - * .min_bounds and max_bounds + * If 0, `.ink_min_bounds` and `.ink_max_bounds` are just copies of + * `.min_bounds` and `.max_bounds` */ uint8_t have_ink_bounds : 1; + + /** + * The number of pixels the font ascend above the baseline + */ int32_t font_ascent; + + /** + * The number of pixels the font descend below the baseline + */ int32_t font_descent; + + /** + * The maximum horizontal overlap, in pixels, of two glyphs + */ int32_t max_overlap; + + /** + * The lower bounds, over each glyph, of the layout metrics + */ struct libparsepcf_metrics min_bounds; + + /** + * The upper bounds, over each glyph, of the layout metrics + */ struct libparsepcf_metrics max_bounds; + + /** + * The lower bounds, over each glyph, of the ink metrics + */ struct libparsepcf_metrics min_ink_bounds; + + /** + * The upper bounds, over each glyph, of the ink metrics + */ struct libparsepcf_metrics max_ink_bounds; }; -int libparsepcf_get_accelerators(const char *, size_t, +/** + * Get information, available for optimisation, about the font + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_ACCELERATORS` + * or `LIBPARSEPCF_BDF_ACCELERATORS`, extracted using the + * `libparsepcf_get_tables` function + * @param meta Output parameter for the list of glyph names + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + * + * `LIBPARSEPCF_BDF_ACCELERATORS` shall be prefered over + * `LIBPARSEPCF_ACCELERATORS` of both tables are present. + * `LIBPARSEPCF_BDF_ACCELERATORS` is more accurate and refers + * only to the encoded characters in the font, whereas + * `LIBPARSEPCF_ACCELERATORS` includes all glyphs + */ +int libparsepcf_get_accelerators(const void *, size_t, const struct libparsepcf_table *, struct libparsepcf_accelerators *); + -int libparsepcf_get_swidth_count(const char *, size_t, const struct libparsepcf_table *, size_t *); +/** + * Get number of scalable glyph widths available in the file + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_SWIDTHS` + * or `LIBPARSEPCF_SWIDTHS`, extracted using the + * `libparsepcf_get_tables` function + * @param count Output parameter for glyph metric count + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ +int libparsepcf_get_swidth_count(const void *, size_t, + const struct libparsepcf_table *, + size_t *); -int libparsepcf_get_swidths(const char *, size_t, const struct libparsepcf_table *, int32_t *, size_t, size_t); +/** + * Get number of scalable glyph widths available in the file + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_SWIDTHS` + * or `LIBPARSEPCF_SWIDTHS`, extracted using the + * `libparsepcf_get_tables` function + * @param widths Output parameter for the glyph's widths; each width + * is encoded with the unit milli-em + * @param first The index of the first glyph's width to store in + * `width`, the first glyph in the file has the index 0 + * @param count The number of glyph's widths to store in `widths`; + * may not exceed the number of glyph as retrieved by + * `libparsepcf_get_swidth_count` (stored in it's last + * argument) minus `first` + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ +int libparsepcf_get_swidths(const void *, size_t, + const struct libparsepcf_table *, + int32_t *, size_t, size_t); +/** + * The tables, in the file, and metadata available in the tables + */ struct libparsepcf_font { + /** + * The `LIBPARSEPCF_PROPERTIES` table, + * `NULL` if the table is missing + */ const struct libparsepcf_table *prob_table; + + /** + * Data extracted for `LIBPARSEPCF_PROPERTIES` + * using `libparsepcf_get_properties` + * + * Only set if `.prob_table` is non-`NULL` + */ struct libparsepcf_properties props; + + /** + * The `LIBPARSEPCF_BDF_ACCELERATORS` table, + * or if missing, the `LIBPARSEPCF_ACCELERATORS` + * table; `NULL` if both are missing + */ const struct libparsepcf_table *accel_table; + + /** + * Data extracted for `LIBPARSEPCF_BDF_ACCELERATORS` + * or, if not present, `LIBPARSEPCF_ACCELERATORS` + * using `libparsepcf_get_accelerators` + * + * Only set if `.accel_table` is non-`NULL` + */ struct libparsepcf_accelerators accels; + + /** + * The `LIBPARSEPCF_METRICS` table + * + * This will be non-`NULL` as `libparsepcf_preparse_font` + * fails with `EBFONT` if the table is missing + */ const struct libparsepcf_table *mtx_table; + + /** + * The number of glyph layout metrics available in the font + * + * This will be the same as `.glyph_count` + */ size_t metrics; + + /** + * The `LIBPARSEPCF_INK_METRICS` table, `NULL` + * if the table is missing + * + * If `NULL`, the ink metrics are the same as the + * layout metrics and `.mtx_table` should be used + * instead + */ const struct libparsepcf_table *inkmtx_table; + + /** + * The number of glyph ink metrics available in the font + * + * This will be the same as `.glyph_count` provided + * that `.inkmtx_table` is non-`NULL` + * + * Only set if `.inkmtx_table` is non-`NULL` + */ size_t ink_metrics; + + /** + * The `LIBPARSEPCF_BDF_ENCODINGS` table + * + * This will be non-`NULL` as `libparsepcf_preparse_font` + * fails with `EBFONT` if the table is missing + */ const struct libparsepcf_table *enc_table; + + /** + * Data extracted for `LIBPARSEPCF_BDF_ENCODINGS` + * using `libparsepcf_get_encoding` + */ struct libparsepcf_encoding encoding; + + /** + * The `LIBPARSEPCF_BITMAPS` table, + * `NULL` if the table is missing + */ const struct libparsepcf_table *bitmap_table; + + /** + * Data extracted for `LIBPARSEPCF_BITMAPS` + * using `libparsepcf_get_bitmaps` + * + * Only set if `.bitmaps_table` is non-`NULL` + */ struct libparsepcf_bitmaps bitmaps; + + /** + * The `LIBPARSEPCF_SWIDTHS` table, + * `NULL` if the table is missing + */ const struct libparsepcf_table *swidth_table; + + /** + * The number of scalable glyph widths available + * in the font + * + * Only set if `.swidth_table` is non-`NULL` + */ size_t swidths; - + + + /** + * The `LIBPARSEPCF_GLYPH_NAMES` table, + * `NULL` if the table is missing + */ const struct libparsepcf_table *name_table; + + /** + * Data extracted for `LIBPARSEPCF_GLYPH_NAMES` + * using `libparsepcf_get_glyph_names` + * + * Only set if `.names_table` is non-`NULL` + */ struct libparsepcf_glyph_names names; + + /** + * The number of glyphs available in the file + */ size_t glyph_count; + + + /** + * The array of all tables in the file + * + * For internal use + */ struct libparsepcf_table *_tables; }; -int libparsepcf_preparse_font(const char *, size_t, struct libparsepcf_font *); +/** + * Identify all tables in the file and extract the + * metadata in each table + * + * @param file The file content + * @param size The file size + * @param font Output parameter for the table data + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ +int libparsepcf_preparse_font(const void *, size_t, struct libparsepcf_font *); +/** + * Deallocate memory allocated by `libparsepcf_preparse_font` + * and erase the object's content + * + * @param font The object to erase, and allocations to deallocate; + * `font` itself will not be deallocated, only memory + * stored inside it + */ void libparsepcf_destroy_preparsed_font(struct libparsepcf_font *); diff --git a/libparsepcf_destroy_preparsed_font.c b/libparsepcf_destroy_preparsed_font.c index 36ec493..ded8cb7 100644 --- a/libparsepcf_destroy_preparsed_font.c +++ b/libparsepcf_destroy_preparsed_font.c @@ -5,6 +5,8 @@ void libparsepcf_destroy_preparsed_font(struct libparsepcf_font *font) { - free(font->_tables); - memset(font, 0, sizeof(*font)); + if (font) { + free(font->_tables); + *font = (struct libparsepcf_font){0}; + } } diff --git a/libparsepcf_get_accelerators.c b/libparsepcf_get_accelerators.c index b9688b7..66c8f2f 100644 --- a/libparsepcf_get_accelerators.c +++ b/libparsepcf_get_accelerators.c @@ -3,10 +3,11 @@ int -libparsepcf_get_accelerators(const char *file, size_t size, +libparsepcf_get_accelerators(const void *file, size_t size, const struct libparsepcf_table *table, struct libparsepcf_accelerators *out) { + const char *text = file; int msb = table->format & LIBPARSEPCF_BYTE; int with_ink_bounds = table->format & LIBPARSEPCF_ACCELERATOR_WITH_INK_BOUNDS; size_t pos; @@ -18,56 +19,56 @@ libparsepcf_get_accelerators(const char *file, size_t size, pos = table->offset; - if (table->format != libparsepcf_parse_lsb_uint32__(&file[pos])) + if (table->format != libparsepcf_parse_lsb_uint32__(&text[pos])) goto ebfont; pos += 4; - out->no_overlap = !!file[pos + 0]; - out->constant_metrics = !!file[pos + 1]; - out->terminal_font = !!file[pos + 2]; - out->constant_width = !!file[pos + 3]; - out->ink_inside = !!file[pos + 4]; - out->ink_metrics = !!file[pos + 5]; - out->draw_rtl = !!file[pos + 6]; + out->no_overlap = !!text[pos + 0]; + out->constant_metrics = !!text[pos + 1]; + out->terminal_font = !!text[pos + 2]; + out->constant_width = !!text[pos + 3]; + out->ink_inside = !!text[pos + 4]; + out->ink_metrics = !!text[pos + 5]; + out->draw_rtl = !!text[pos + 6]; out->have_ink_bounds = !!with_ink_bounds; pos += 8; - out->font_ascent = PARSE_INT32(&file[pos + 0], msb); - out->font_descent = PARSE_INT32(&file[pos + 4], msb); - out->max_overlap = PARSE_INT32(&file[pos + 8], msb); + out->font_ascent = PARSE_INT32(&text[pos + 0], msb); + out->font_descent = PARSE_INT32(&text[pos + 4], msb); + out->max_overlap = PARSE_INT32(&text[pos + 8], msb); pos += 12; - out->min_bounds.left_side_bearing = PARSE_INT16(&file[pos + 0], msb); - out->min_bounds.right_side_bearing = PARSE_INT16(&file[pos + 2], msb); - out->min_bounds.character_width = PARSE_INT16(&file[pos + 4], msb); - out->min_bounds.character_ascent = PARSE_INT16(&file[pos + 6], msb); - out->min_bounds.character_descent = PARSE_INT16(&file[pos + 8], msb); - out->min_bounds.character_attributes = PARSE_UINT16(&file[pos + 10], msb); + out->min_bounds.left_side_bearing = PARSE_INT16(&text[pos + 0], msb); + out->min_bounds.right_side_bearing = PARSE_INT16(&text[pos + 2], msb); + out->min_bounds.character_width = PARSE_INT16(&text[pos + 4], msb); + out->min_bounds.character_ascent = PARSE_INT16(&text[pos + 6], msb); + out->min_bounds.character_descent = PARSE_INT16(&text[pos + 8], msb); + out->min_bounds.character_attributes = PARSE_UINT16(&text[pos + 10], msb); pos += 12; - out->max_bounds.left_side_bearing = PARSE_INT16(&file[pos + 0], msb); - out->max_bounds.right_side_bearing = PARSE_INT16(&file[pos + 2], msb); - out->max_bounds.character_width = PARSE_INT16(&file[pos + 4], msb); - out->max_bounds.character_ascent = PARSE_INT16(&file[pos + 6], msb); - out->max_bounds.character_descent = PARSE_INT16(&file[pos + 8], msb); - out->max_bounds.character_attributes = PARSE_UINT16(&file[pos + 10], msb); + out->max_bounds.left_side_bearing = PARSE_INT16(&text[pos + 0], msb); + out->max_bounds.right_side_bearing = PARSE_INT16(&text[pos + 2], msb); + out->max_bounds.character_width = PARSE_INT16(&text[pos + 4], msb); + out->max_bounds.character_ascent = PARSE_INT16(&text[pos + 6], msb); + out->max_bounds.character_descent = PARSE_INT16(&text[pos + 8], msb); + out->max_bounds.character_attributes = PARSE_UINT16(&text[pos + 10], msb); pos += 12; if (with_ink_bounds) { - out->min_ink_bounds.left_side_bearing = PARSE_INT16(&file[pos + 0], msb); - out->min_ink_bounds.right_side_bearing = PARSE_INT16(&file[pos + 2], msb); - out->min_ink_bounds.character_width = PARSE_INT16(&file[pos + 4], msb); - out->min_ink_bounds.character_ascent = PARSE_INT16(&file[pos + 6], msb); - out->min_ink_bounds.character_descent = PARSE_INT16(&file[pos + 8], msb); - out->min_ink_bounds.character_attributes = PARSE_UINT16(&file[pos + 10], msb); + out->min_ink_bounds.left_side_bearing = PARSE_INT16(&text[pos + 0], msb); + out->min_ink_bounds.right_side_bearing = PARSE_INT16(&text[pos + 2], msb); + out->min_ink_bounds.character_width = PARSE_INT16(&text[pos + 4], msb); + out->min_ink_bounds.character_ascent = PARSE_INT16(&text[pos + 6], msb); + out->min_ink_bounds.character_descent = PARSE_INT16(&text[pos + 8], msb); + out->min_ink_bounds.character_attributes = PARSE_UINT16(&text[pos + 10], msb); pos += 12; - out->max_ink_bounds.left_side_bearing = PARSE_INT16(&file[pos + 0], msb); - out->max_ink_bounds.right_side_bearing = PARSE_INT16(&file[pos + 2], msb); - out->max_ink_bounds.character_width = PARSE_INT16(&file[pos + 4], msb); - out->max_ink_bounds.character_ascent = PARSE_INT16(&file[pos + 6], msb); - out->max_ink_bounds.character_descent = PARSE_INT16(&file[pos + 8], msb); - out->max_ink_bounds.character_attributes = PARSE_UINT16(&file[pos + 10], msb); + out->max_ink_bounds.left_side_bearing = PARSE_INT16(&text[pos + 0], msb); + out->max_ink_bounds.right_side_bearing = PARSE_INT16(&text[pos + 2], msb); + out->max_ink_bounds.character_width = PARSE_INT16(&text[pos + 4], msb); + out->max_ink_bounds.character_ascent = PARSE_INT16(&text[pos + 6], msb); + out->max_ink_bounds.character_descent = PARSE_INT16(&text[pos + 8], msb); + out->max_ink_bounds.character_attributes = PARSE_UINT16(&text[pos + 10], msb); pos += 12; } else { memcpy(&out->min_ink_bounds, &out->min_bounds, sizeof(out->min_bounds)); diff --git a/libparsepcf_get_bitmap_offsets.c b/libparsepcf_get_bitmap_offsets.c index 192b07b..8f62f7e 100644 --- a/libparsepcf_get_bitmap_offsets.c +++ b/libparsepcf_get_bitmap_offsets.c @@ -3,11 +3,12 @@ int -libparsepcf_get_bitmap_offsets(const char *file, size_t size, +libparsepcf_get_bitmap_offsets(const void *file, size_t size, const struct libparsepcf_table *table, const struct libparsepcf_bitmaps *meta, - size_t *out, size_t first, size_t count) + size_t *offs, size_t first, size_t count) { + const char *text = file; int msb = table->format & LIBPARSEPCF_BYTE; size_t pos = table->offset + 8 + first * 4; size_t i; @@ -15,8 +16,8 @@ libparsepcf_get_bitmap_offsets(const char *file, size_t size, (void) size; for (i = 0; i < count; i++, pos += 4) { - out[i] = (size_t)PARSE_UINT32(&file[pos + 0], msb); - if (out[i] > meta->bitmap_size) + offs[i] = (size_t)PARSE_UINT32(&text[pos + 0], msb); + if (offs[i] > meta->bitmap_size) goto ebfont; } diff --git a/libparsepcf_get_bitmaps.c b/libparsepcf_get_bitmaps.c index 961da96..cad51f3 100644 --- a/libparsepcf_get_bitmaps.c +++ b/libparsepcf_get_bitmaps.c @@ -3,10 +3,11 @@ int -libparsepcf_get_bitmaps(const char *file, size_t size, +libparsepcf_get_bitmaps(const void *file, size_t size, const struct libparsepcf_table *table, - struct libparsepcf_bitmaps *out) + struct libparsepcf_bitmaps *meta) { + const char *text = file; size_t pos, glyph_pad; int msb = table->format & LIBPARSEPCF_BYTE; @@ -17,31 +18,31 @@ libparsepcf_get_bitmaps(const char *file, size_t size, pos = table->offset; - if (table->format != libparsepcf_parse_lsb_uint32__(&file[pos])) + if (table->format != libparsepcf_parse_lsb_uint32__(&text[pos])) goto ebfont; pos += 4; - out->glyph_count = (size_t)PARSE_UINT32(&file[pos], msb); + meta->glyph_count = (size_t)PARSE_UINT32(&text[pos], msb); pos += 4; if (16 > table->size - (pos - table->offset) || - out->glyph_count > (table->size - (pos - table->offset) - 16) / 4) + meta->glyph_count > (table->size - (pos - table->offset) - 16) / 4) goto ebfont; - pos += out->glyph_count * 4; + pos += meta->glyph_count * 4; glyph_pad = (size_t)(table->format & LIBPARSEPCF_GLYPH_PAD_MASK); - out->bitmap_size = (size_t)PARSE_UINT32(&file[pos + 4 * glyph_pad], msb); + meta->bitmap_size = (size_t)PARSE_UINT32(&text[pos + 4 * glyph_pad], msb); pos += 16; - out->bitmap_data = (const void *)&file[pos]; - if (out->bitmap_size > table->size - (pos - table->offset)) + meta->bitmap_data = (const void *)&text[pos]; + if (meta->bitmap_size > table->size - (pos - table->offset)) goto ebfont; - out->bit_packing = (size_t)1 << ((table->format & LIBPARSEPCF_SCAN_UNIT_MASK) >> 4); - out->row_padding = (size_t)1 << ((table->format & LIBPARSEPCF_GLYPH_PAD_MASK) >> 0); - out->lsbyte = !!(table->format & LIBPARSEPCF_BYTE); - out->lsbit = !!(table->format & LIBPARSEPCF_BIT); + meta->bit_packing = (size_t)1 << ((table->format & LIBPARSEPCF_SCAN_UNIT_MASK) >> 4); + meta->row_padding = (size_t)1 << ((table->format & LIBPARSEPCF_GLYPH_PAD_MASK) >> 0); + meta->lsbyte = !!(table->format & LIBPARSEPCF_BYTE); + meta->lsbit = !!(table->format & LIBPARSEPCF_BIT); - if (out->row_padding < out->bit_packing) + if (meta->row_padding < meta->bit_packing) goto ebfont; return 0; diff --git a/libparsepcf_get_encoding.c b/libparsepcf_get_encoding.c index 34ccd9b..6c28c6a 100644 --- a/libparsepcf_get_encoding.c +++ b/libparsepcf_get_encoding.c @@ -3,10 +3,11 @@ int -libparsepcf_get_encoding(const char *file, size_t size, +libparsepcf_get_encoding(const void *file, size_t size, const struct libparsepcf_table *table, - struct libparsepcf_encoding *out) + struct libparsepcf_encoding *meta) { + const char *text = file; int msb = table->format & LIBPARSEPCF_BYTE; size_t pos; @@ -17,23 +18,24 @@ libparsepcf_get_encoding(const char *file, size_t size, pos = table->offset; - if (table->format != libparsepcf_parse_lsb_uint32__(&file[pos])) + if (table->format != libparsepcf_parse_lsb_uint32__(&text[pos])) goto ebfont; pos += 4; - out->min_byte2 = PARSE_UINT16(&file[pos + 0], msb); - out->max_byte2 = PARSE_UINT16(&file[pos + 2], msb); - out->min_byte1 = PARSE_UINT16(&file[pos + 4], msb); - out->max_byte1 = PARSE_UINT16(&file[pos + 6], msb); - out->default_char = PARSE_UINT16(&file[pos + 8], msb); + meta->min_byte2 = PARSE_UINT16(&text[pos + 0], msb); + meta->max_byte2 = PARSE_UINT16(&text[pos + 2], msb); + meta->min_byte1 = PARSE_UINT16(&text[pos + 4], msb); + meta->max_byte1 = PARSE_UINT16(&text[pos + 6], msb); + meta->default_char = PARSE_UINT16(&text[pos + 8], msb); pos += 10; - if (out->min_byte2 > out->max_byte2 || out->max_byte2 > 255 || - out->min_byte1 > out->max_byte1 || out->max_byte1 > 255) + if (meta->min_byte2 > meta->max_byte2 || meta->max_byte2 > 255 || + meta->min_byte1 > meta->max_byte1 || meta->max_byte1 > 255) goto ebfont; - out->glyph_count = (size_t)(out->max_byte2 - out->min_byte2 + 1) * (size_t)(out->max_byte1 - out->min_byte1 + 1); - if (out->glyph_count > table->size - (pos - table->offset) / 2) + meta->glyph_count = (size_t)(meta->max_byte2 - meta->min_byte2 + 1); + meta->glyph_count *= (size_t)(meta->max_byte1 - meta->min_byte1 + 1); + if (meta->glyph_count > table->size - (pos - table->offset) / 2) goto ebfont; return 0; diff --git a/libparsepcf_get_glyph_indices.c b/libparsepcf_get_glyph_indices.c index c30e148..bb95d3e 100644 --- a/libparsepcf_get_glyph_indices.c +++ b/libparsepcf_get_glyph_indices.c @@ -3,11 +3,12 @@ int -libparsepcf_get_glyph_indices(const char *file, size_t size, +libparsepcf_get_glyph_indices(const void *file, size_t size, const struct libparsepcf_table *table, const struct libparsepcf_encoding *meta, - size_t *out, size_t first, size_t count) + size_t *indices, size_t first, size_t count) { + const char *text = file; int msb = table->format & LIBPARSEPCF_BYTE; size_t pos = table->offset + 14 + first * 2; size_t i; @@ -16,7 +17,7 @@ libparsepcf_get_glyph_indices(const char *file, size_t size, (void) meta; for (i = 0; i < count; i++, pos += 2) - out[i] = (size_t)PARSE_UINT16(&file[pos], msb); + indices[i] = (size_t)PARSE_UINT16(&text[pos], msb); return 0; } diff --git a/libparsepcf_get_glyph_name_subtable.c b/libparsepcf_get_glyph_name_subtable.c index 578bf87..56519bf 100644 --- a/libparsepcf_get_glyph_name_subtable.c +++ b/libparsepcf_get_glyph_name_subtable.c @@ -3,11 +3,12 @@ int -libparsepcf_get_glyph_name_subtable(const char *file, size_t size, +libparsepcf_get_glyph_name_subtable(const void *file, size_t size, const struct libparsepcf_table *table, const struct libparsepcf_glyph_names *meta, - const char **out, size_t first, size_t count) + const char **names, size_t first, size_t count) { + const char *text = file; size_t pos, i, off; int msb = table->format & LIBPARSEPCF_BYTE; @@ -18,11 +19,11 @@ libparsepcf_get_glyph_name_subtable(const char *file, size_t size, pos = table->offset + 8 + first * 4; for (i = 0; i < count; i++, pos += 4) { - off = (size_t)PARSE_UINT32(&file[pos], msb); + off = (size_t)PARSE_UINT32(&text[pos], msb); if (off > meta->strings_size) goto ebfont; - out[i] = &meta->strings[off]; - if (!memchr(out[i], 0, meta->strings_size - off)) + names[i] = &meta->strings[off]; + if (!memchr(names[i], 0, meta->strings_size - off)) goto ebfont; } diff --git a/libparsepcf_get_glyph_names.c b/libparsepcf_get_glyph_names.c index ca690a4..46d5173 100644 --- a/libparsepcf_get_glyph_names.c +++ b/libparsepcf_get_glyph_names.c @@ -3,10 +3,11 @@ int -libparsepcf_get_glyph_names(const char *file, size_t size, +libparsepcf_get_glyph_names(const void *file, size_t size, const struct libparsepcf_table *table, - struct libparsepcf_glyph_names *out) + struct libparsepcf_glyph_names *meta) { + const char *text = file; size_t pos; int msb = table->format & LIBPARSEPCF_BYTE; @@ -17,22 +18,22 @@ libparsepcf_get_glyph_names(const char *file, size_t size, pos = table->offset; - if (table->format != libparsepcf_parse_lsb_uint32__(&file[pos])) + if (table->format != libparsepcf_parse_lsb_uint32__(&text[pos])) goto ebfont; pos += 4; - out->glyph_count = (size_t)PARSE_UINT32(&file[pos], msb); + meta->glyph_count = (size_t)PARSE_UINT32(&text[pos], msb); pos += 4; if (4 > table->size - (pos - table->offset) || - out->glyph_count > (table->size - (pos - table->offset) - 4) / 4) + meta->glyph_count > (table->size - (pos - table->offset) - 4) / 4) goto ebfont; - pos += out->glyph_count * 4; - out->strings_size = (size_t)PARSE_UINT32(&file[pos], msb); + pos += meta->glyph_count * 4; + meta->strings_size = (size_t)PARSE_UINT32(&text[pos], msb); pos += 4; - out->strings = &file[pos]; - if (out->strings_size > table->size - (pos - table->offset)) + meta->strings = &text[pos]; + if (meta->strings_size > table->size - (pos - table->offset)) goto ebfont; return 0; diff --git a/libparsepcf_get_metrics.c b/libparsepcf_get_metrics.c index 5e2fbe0..8994405 100644 --- a/libparsepcf_get_metrics.c +++ b/libparsepcf_get_metrics.c @@ -2,11 +2,16 @@ #include "common.h" +#define PARSE_INT8(TEXT) ((int16_t)((int)*(const uint8_t *)(TEXT) - 128)) + + int -libparsepcf_get_metrics(const char *file, size_t size, +libparsepcf_get_metrics(const void *file, size_t size, const struct libparsepcf_table *table, - struct libparsepcf_metrics *out, size_t first, size_t count) + struct libparsepcf_metrics *metrics, + size_t first, size_t count) { + const char *text = file; size_t pos, i; int msb = table->format & LIBPARSEPCF_BYTE; int compressed = table->format & LIBPARSEPCF_COMPRESSED_METRICS; @@ -18,30 +23,30 @@ libparsepcf_get_metrics(const char *file, size_t size, if (compressed) { for (i = 0; i < count; i++, pos += 5) { - out[i].left_side_bearing = (int16_t)((int)((const uint8_t *)file)[pos + 0] - 128); - out[i].right_side_bearing = (int16_t)((int)((const uint8_t *)file)[pos + 1] - 128); - out[i].character_width = (int16_t)((int)((const uint8_t *)file)[pos + 2] - 128); - out[i].character_ascent = (int16_t)((int)((const uint8_t *)file)[pos + 3] - 128); - out[i].character_descent = (int16_t)((int)((const uint8_t *)file)[pos + 4] - 128); - out[i].character_attributes = 0; - if (out[i].left_side_bearing > out[i].right_side_bearing || - (int32_t)out[i].character_ascent < -(int32_t)out[i].character_descent) - goto ebfont; + metrics[i].left_side_bearing = PARSE_INT8(&text[pos + 0]); + metrics[i].right_side_bearing = PARSE_INT8(&text[pos + 1]); + metrics[i].character_width = PARSE_INT8(&text[pos + 2]); + metrics[i].character_ascent = PARSE_INT8(&text[pos + 3]); + metrics[i].character_descent = PARSE_INT8(&text[pos + 4]); + metrics[i].character_attributes = 0; } } else { for (i = 0; i < count; i++, pos += 12) { - out[i].left_side_bearing = PARSE_INT16(&file[pos + 0], msb); - out[i].right_side_bearing = PARSE_INT16(&file[pos + 2], msb); - out[i].character_width = PARSE_INT16(&file[pos + 4], msb); - out[i].character_ascent = PARSE_INT16(&file[pos + 6], msb); - out[i].character_descent = PARSE_INT16(&file[pos + 8], msb); - out[i].character_attributes = PARSE_UINT16(&file[pos + 10], msb); - if (out[i].left_side_bearing > out[i].right_side_bearing || - (int32_t)out[i].character_ascent < -(int32_t)out[i].character_descent) - goto ebfont; + metrics[i].left_side_bearing = PARSE_INT16(&text[pos + 0], msb); + metrics[i].right_side_bearing = PARSE_INT16(&text[pos + 2], msb); + metrics[i].character_width = PARSE_INT16(&text[pos + 4], msb); + metrics[i].character_ascent = PARSE_INT16(&text[pos + 6], msb); + metrics[i].character_descent = PARSE_INT16(&text[pos + 8], msb); + metrics[i].character_attributes = PARSE_UINT16(&text[pos + 10], msb); } } + for (i = 0; i < count; i++) { + if (metrics[i].left_side_bearing > metrics[i].right_side_bearing || + (int32_t)metrics[i].character_ascent < -(int32_t)metrics[i].character_descent) + goto ebfont; + } + return 0; ebfont: diff --git a/libparsepcf_get_metrics_count.c b/libparsepcf_get_metrics_count.c index fab5544..abaa542 100644 --- a/libparsepcf_get_metrics_count.c +++ b/libparsepcf_get_metrics_count.c @@ -3,8 +3,11 @@ int -libparsepcf_get_metrics_count(const char *file, size_t size, const struct libparsepcf_table *table, size_t *countp) +libparsepcf_get_metrics_count(const void *file, size_t size, + const struct libparsepcf_table *table, + size_t *count) { + const char *text = file; size_t pos; int msb = table->format & LIBPARSEPCF_BYTE; int compressed = table->format & LIBPARSEPCF_COMPRESSED_METRICS; @@ -14,19 +17,19 @@ libparsepcf_get_metrics_count(const char *file, size_t size, const struct libpar pos = table->offset; - if (table->format != libparsepcf_parse_lsb_uint32__(&file[pos])) + if (table->format != libparsepcf_parse_lsb_uint32__(&text[pos])) goto ebfont; pos += 4; if (compressed) { - *countp = (size_t)PARSE_UINT16(&file[pos], msb); + *count = (size_t)PARSE_UINT16(&text[pos], msb); pos += 2; - if (*countp > (size - pos) / 5) + if (*count > (size - pos) / 5) goto ebfont; } else { - *countp = (size_t)PARSE_UINT32(&file[pos], msb); + *count = (size_t)PARSE_UINT32(&text[pos], msb); pos += 4; - if (*countp > (size - pos) / 12) + if (*count > (size - pos) / 12) goto ebfont; } diff --git a/libparsepcf_get_properties.c b/libparsepcf_get_properties.c index f586a5c..9b7e383 100644 --- a/libparsepcf_get_properties.c +++ b/libparsepcf_get_properties.c @@ -3,10 +3,11 @@ int -libparsepcf_get_properties(const char *file, size_t size, +libparsepcf_get_properties(const void *file, size_t size, const struct libparsepcf_table *table, - struct libparsepcf_properties *out) + struct libparsepcf_properties *meta) { + const char *text = file; size_t pos; int msb = table->format & LIBPARSEPCF_BYTE; @@ -17,25 +18,25 @@ libparsepcf_get_properties(const char *file, size_t size, pos = table->offset; - if (table->format != libparsepcf_parse_lsb_uint32__(&file[pos])) + if (table->format != libparsepcf_parse_lsb_uint32__(&text[pos])) goto ebfont; pos += 4; - out->property_count = (size_t)PARSE_UINT32(&file[pos], msb); + meta->property_count = (size_t)PARSE_UINT32(&text[pos], msb); pos += 4; if (4 > table->size - (pos - table->offset) || - out->property_count > (table->size - (pos - table->offset) - 4) / 9) + meta->property_count > (table->size - (pos - table->offset) - 4) / 9) goto ebfont; - pos += out->property_count * 9; - pos += (4 - (out->property_count & 3)) & 3; + pos += meta->property_count * 9; + pos += (4 - (meta->property_count & 3)) & 3; if (pos - table->offset > table->size - 4) goto ebfont; - out->strings_size = (size_t)PARSE_UINT32(&file[pos], msb); + meta->strings_size = (size_t)PARSE_UINT32(&text[pos], msb); pos += 4; - out->strings = &file[pos]; - if (out->strings_size > table->size - (pos - table->offset)) + meta->strings = &text[pos]; + if (meta->strings_size > table->size - (pos - table->offset)) goto ebfont; return 0; diff --git a/libparsepcf_get_property_subtable.c b/libparsepcf_get_property_subtable.c index d19498c..5da1f56 100644 --- a/libparsepcf_get_property_subtable.c +++ b/libparsepcf_get_property_subtable.c @@ -3,12 +3,13 @@ int -libparsepcf_get_property_subtable(const char *file, size_t size, +libparsepcf_get_property_subtable(const void *file, size_t size, const struct libparsepcf_table *table, const struct libparsepcf_properties *meta, struct libparsepcf_property_subtable *props, - size_t first, size_t count) + size_t first, size_t count) { + const char *text = file; int msb = table->format & LIBPARSEPCF_BYTE; size_t pos = table->offset + 8 + first * 9; size_t i, off, maxlen; @@ -16,7 +17,7 @@ libparsepcf_get_property_subtable(const char *file, size_t size, (void) size; for (i = 0; i < count; i++, pos += 9) { - off = (size_t)PARSE_UINT32(&file[pos + 0], msb); + off = (size_t)PARSE_UINT32(&text[pos + 0], msb); if (off > meta->strings_size) goto ebfont; maxlen = meta->strings_size - off; @@ -24,10 +25,10 @@ libparsepcf_get_property_subtable(const char *file, size_t size, if (!memchr(props[i].name, 0, maxlen)) goto ebfont; - props[i].is_string_property = !!file[pos + 4]; + props[i].is_string_property = !!text[pos + 4]; if (props[i].is_string_property) { - off = (size_t)PARSE_UINT32(&file[pos + 5], msb); + off = (size_t)PARSE_UINT32(&text[pos + 5], msb); if (off > meta->strings_size) goto ebfont; maxlen = meta->strings_size - off; @@ -35,7 +36,7 @@ libparsepcf_get_property_subtable(const char *file, size_t size, if (!memchr(props[i].value.string_value, 0, maxlen)) goto ebfont; } else { - props[i].value.signed_value = PARSE_INT32(&file[pos + 5], msb); + props[i].value.signed_value = PARSE_INT32(&text[pos + 5], msb); } } diff --git a/libparsepcf_get_swidth_count.c b/libparsepcf_get_swidth_count.c index 90a5f4a..f6010d0 100644 --- a/libparsepcf_get_swidth_count.c +++ b/libparsepcf_get_swidth_count.c @@ -3,8 +3,11 @@ int -libparsepcf_get_swidth_count(const char *file, size_t size, const struct libparsepcf_table *table, size_t *countp) +libparsepcf_get_swidth_count(const void *file, size_t size, + const struct libparsepcf_table *table, + size_t *count) { + const char *text = file; size_t pos; int msb = table->format & LIBPARSEPCF_BYTE; @@ -13,14 +16,14 @@ libparsepcf_get_swidth_count(const char *file, size_t size, const struct libpars pos = table->offset; - if (table->format != libparsepcf_parse_lsb_uint32__(&file[pos])) + if (table->format != libparsepcf_parse_lsb_uint32__(&text[pos])) goto ebfont; pos += 4; - *countp = (size_t)PARSE_UINT32(&file[pos], msb); + *count = (size_t)PARSE_UINT32(&text[pos], msb); pos += 4; - if (*countp > (size - pos) / 4) + if (*count > (size - pos) / 4) goto ebfont; return 0; diff --git a/libparsepcf_get_swidths.c b/libparsepcf_get_swidths.c index d350b74..f96f14f 100644 --- a/libparsepcf_get_swidths.c +++ b/libparsepcf_get_swidths.c @@ -3,10 +3,11 @@ int -libparsepcf_get_swidths(const char *file, size_t size, +libparsepcf_get_swidths(const void *file, size_t size, const struct libparsepcf_table *table, - int32_t *out, size_t first, size_t count) + int32_t *widths, size_t first, size_t count) { + const char *text = file; int msb = table->format & LIBPARSEPCF_BYTE; size_t pos = table->offset + 8 + 4 * first; size_t i; @@ -14,7 +15,7 @@ libparsepcf_get_swidths(const char *file, size_t size, (void) size; for (i = 0; i < count; i++, pos += 4) - out[i] = PARSE_INT32(&file[pos], msb); + widths[i] = PARSE_INT32(&text[pos], msb); return 0; } diff --git a/libparsepcf_get_table_count.c b/libparsepcf_get_table_count.c index 0eb8741..a5ece0e 100644 --- a/libparsepcf_get_table_count.c +++ b/libparsepcf_get_table_count.c @@ -3,14 +3,15 @@ int -libparsepcf_get_table_count(const char *file, size_t size, size_t *countp) +libparsepcf_get_table_count(const void *file, size_t size, size_t *countp) { + const char *text = file; uint32_t count; - if (size < 8 || file[0] != 1 || file[1] != 'f' || file[2] != 'c' || file[3] != 'p') + if (size < 8 || text[0] != 1 || text[1] != 'f' || text[2] != 'c' || text[3] != 'p') goto ebfont; - count = libparsepcf_parse_lsb_uint32__(&file[4]); + count = libparsepcf_parse_lsb_uint32__(&text[4]); if (count > (size - 8) / 16) goto ebfont; diff --git a/libparsepcf_get_tables.c b/libparsepcf_get_tables.c index 56cffc2..d1963e7 100644 --- a/libparsepcf_get_tables.c +++ b/libparsepcf_get_tables.c @@ -3,22 +3,25 @@ int -libparsepcf_get_tables(const char *file, size_t size, struct libparsepcf_table *tables, size_t first, size_t count) +libparsepcf_get_tables(const void *file, size_t size, + struct libparsepcf_table *tables, + size_t first, size_t count) { + const char *text = file; size_t pos = 8 + first * 16; size_t i; for (i = 0; i < count; i++, pos += 16) { - tables[i].type = libparsepcf_parse_lsb_uint32__(&file[pos + 0]); - tables[i].format = libparsepcf_parse_lsb_uint32__(&file[pos + 4]); - tables[i].size = libparsepcf_parse_lsb_uint32__(&file[pos + 8]); - tables[i].offset = libparsepcf_parse_lsb_uint32__(&file[pos + 12]); + tables[i].type = libparsepcf_parse_lsb_uint32__(&text[pos + 0]); + tables[i].format = libparsepcf_parse_lsb_uint32__(&text[pos + 4]); + tables[i].size = libparsepcf_parse_lsb_uint32__(&text[pos + 8]); + tables[i].offset = libparsepcf_parse_lsb_uint32__(&text[pos + 12]); if ((size_t)tables[i].offset > size) goto ebfont; - /* For some reasons files specify table sizes such that they - * actually except the boundary of the file, despite not using + /* For some reason files specify table sizes such that they + * actually exceed the boundary of the file, despite not using * that much data. Don't including this fix, but instead check * that the table size is not too large, will break your * favourite fonts. */ diff --git a/libparsepcf_preparse_font.c b/libparsepcf_preparse_font.c index 058365a..63c245e 100644 --- a/libparsepcf_preparse_font.c +++ b/libparsepcf_preparse_font.c @@ -3,11 +3,13 @@ int -libparsepcf_preparse_font(const char *file, size_t size, struct libparsepcf_font *font) +libparsepcf_preparse_font(const void *file, size_t size, struct libparsepcf_font *font) { size_t min = SIZE_MAX, max = 0, table_i, table_n; struct libparsepcf_table *tables = NULL; + *font = (struct libparsepcf_font){0}; + if (libparsepcf_get_table_count(file, size, &table_n)) goto fail; tables = calloc(table_n, sizeof(*tables)); -- cgit v1.2.3-70-g09d2