/* See LICENSE file for copyright and license details. */ #ifndef LIBPARSEPCF_H #define LIBPARSEPCF_H #include #include /* Based on documentation from FontForge: https://fontforge.org/docs/techref/pcf-format.html */ /** * Table metadata */ struct libparsepcf_table { /** * The table type, support values are: * - LIBPARSEPCF_PROPERTIES * - LIBPARSEPCF_ACCELERATORS * - LIBPARSEPCF_METRICS * - LIBPARSEPCF_BITMAPS * - LIBPARSEPCF_INK_METRICS * - LIBPARSEPCF_BDF_ENCODINGS * - LIBPARSEPCF_SWIDTHS * - LIBPARSEPCF_GLYPH_NAMES * - LIBPARSEPCF_BDF_ACCELERATORS * * (The set in these values are non-overlapping, * however they cannot be combined.) */ uint32_t type; /** * How the data in the table is formatted * * This is only unsed internally, and supported * values are not exposed the the user */ uint32_t format; /** * The size of the table */ uint32_t size; /** * The table's offset in the file * * (The file is padded with NUL bytes to align * each table to a 4 byte boundary) */ uint32_t offset; }; /* Table types: */ #define LIBPARSEPCF_PROPERTIES (UINT32_C(1) << 0) #define LIBPARSEPCF_ACCELERATORS (UINT32_C(1) << 1) #define LIBPARSEPCF_METRICS (UINT32_C(1) << 2) #define LIBPARSEPCF_BITMAPS (UINT32_C(1) << 3) #define LIBPARSEPCF_INK_METRICS (UINT32_C(1) << 4) #define LIBPARSEPCF_BDF_ENCODINGS (UINT32_C(1) << 5) #define LIBPARSEPCF_SWIDTHS (UINT32_C(1) << 6) #define LIBPARSEPCF_GLYPH_NAMES (UINT32_C(1) << 7) #define LIBPARSEPCF_BDF_ACCELERATORS (UINT32_C(1) << 8) /** * Get the number of tables in the file * * @param file The file content * @param size The file size * @param countp Output parameter for the number of tables in the file * @return 0 on success, -1 on failure * * @throws EBFONT The file is not a properly formatted PCF file */ int libparsepcf_get_table_count(const char *, size_t, size_t *); /** * Get table metadata from the file * * @param file The file content * @param size The file size * @param tables Output buffer for the table metadata * @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` * @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); struct libparsepcf_properties { size_t property_count; size_t strings_size; const char *strings; }; struct libparsepcf_property_subtable { const char *name; int is_string_property; union { int32_t signed_value; const char *string_value; } value; }; int libparsepcf_get_properties(const char *, size_t, const struct libparsepcf_table *, struct libparsepcf_properties *); int libparsepcf_get_property_subtable(const char *, size_t, const struct libparsepcf_table *, const struct libparsepcf_properties *, struct libparsepcf_property_subtable *, size_t, size_t); struct libparsepcf_metrics { int16_t left_side_bearing; int16_t right_side_bearing; int16_t character_width; int16_t character_ascent; int16_t character_descent; uint16_t character_attributes; }; int libparsepcf_get_metrics_count(const char *, size_t, const struct libparsepcf_table *, size_t *); int libparsepcf_get_metrics(const char *, size_t, const struct libparsepcf_table *, struct libparsepcf_metrics *, size_t, size_t); struct libparsepcf_glyph_names { size_t glyph_count; size_t strings_size; const char *strings; }; int libparsepcf_get_glyph_names(const char *, size_t, const struct libparsepcf_table *, struct libparsepcf_glyph_names *); int libparsepcf_get_glyph_name_subtable(const char *, size_t, const struct libparsepcf_table *, const struct libparsepcf_glyph_names *, const char **, size_t, size_t); struct libparsepcf_bitmaps { size_t glyph_count; size_t bitmap_size; size_t bit_packing; size_t row_padding; int lsbyte; int lsbit; const uint8_t *bitmap_data; }; int libparsepcf_get_bitmaps(const char *, size_t, const struct libparsepcf_table *, struct libparsepcf_bitmaps *); int libparsepcf_get_bitmap_offsets(const char *, size_t, const struct libparsepcf_table *, const struct libparsepcf_bitmaps *, size_t *, size_t, size_t); struct libparsepcf_encoding { uint16_t min_byte2; uint16_t max_byte2; uint16_t min_byte1; uint16_t max_byte1; 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 * * 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 */ }; #define LIBPARSEPCF_NOT_ENCODED ((size_t)0xFFFFUL) int libparsepcf_get_encoding(const char *, size_t, const struct libparsepcf_table *, struct libparsepcf_encoding *); int libparsepcf_get_glyph_indices(const char *, size_t, const struct libparsepcf_table *, const struct libparsepcf_encoding *, size_t *, size_t, size_t); 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 */ uint8_t no_overlap : 1; 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 */ uint8_t terminal_font : 1; 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; uint8_t draw_rtl : 1; /** * If 0, .ink_min_bounds and .ink_max_bounds are just copies of * .min_bounds and max_bounds */ uint8_t have_ink_bounds : 1; int32_t font_ascent; int32_t font_descent; int32_t max_overlap; struct libparsepcf_metrics min_bounds; struct libparsepcf_metrics max_bounds; struct libparsepcf_metrics min_ink_bounds; struct libparsepcf_metrics max_ink_bounds; }; int libparsepcf_get_accelerators(const char *, size_t, const struct libparsepcf_table *, struct libparsepcf_accelerators *); int libparsepcf_get_swidth_count(const char *, 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); struct libparsepcf_font { const struct libparsepcf_table *prob_table; struct libparsepcf_properties props; const struct libparsepcf_table *accel_table; struct libparsepcf_accelerators accels; const struct libparsepcf_table *mtx_table; size_t metrics; const struct libparsepcf_table *inkmtx_table; size_t ink_metrics; const struct libparsepcf_table *enc_table; struct libparsepcf_encoding encoding; const struct libparsepcf_table *bitmap_table; struct libparsepcf_bitmaps bitmaps; const struct libparsepcf_table *swidth_table; size_t swidths; const struct libparsepcf_table *name_table; struct libparsepcf_glyph_names names; size_t glyph_count; struct libparsepcf_table *_tables; }; int libparsepcf_preparse_font(const char *, size_t, struct libparsepcf_font *); void libparsepcf_destroy_preparsed_font(struct libparsepcf_font *); #endif