/* See LICENSE file for copyright and license details. */
#ifndef LIBPARSEPCF_H
#define LIBPARSEPCF_H
#include <stddef.h>
#include <stdint.h>
/* 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