aboutsummaryrefslogblamecommitdiffstats
path: root/libparsepcf.h
blob: 6931898aa0e5921f1de8e7637d3254531074def1 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11










                                                                                               



                 
                          














                                                        
                      






                                                       
                        



                                
                      






                                                      













                                                       






























                                                                                             

























                                                                                              
 
















                                                                                                    
 
















                                                                               
 




















                                                                      
 

































                                                                                                           
 
















































                                                                                                               
 




































                                                                               
/* 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