diff options
Diffstat (limited to '')
-rw-r--r-- | Makefile | 3 | ||||
-rw-r--r-- | demo.c | 42 | ||||
-rw-r--r-- | libparsepcf.h | 109 | ||||
-rw-r--r-- | libparsepcf_get_bitmaps.c | 4 | ||||
-rw-r--r-- | libparsepcf_get_encoding.c | 8 |
5 files changed, 121 insertions, 45 deletions
@@ -10,7 +10,7 @@ OS = linux include mk/$(OS).mk -LIB_MAJOR = 1 +LIB_MAJOR = 2 LIB_MINOR = 0 LIB_VERSION = $(LIB_MAJOR).$(LIB_MINOR) LIB_NAME = parsepcf @@ -52,6 +52,7 @@ SRC = $(OBJ:.o=.c) all: libparsepcf.a libparsepcf.$(LIBEXT) demo $(OBJ): $(HDR) $(LOBJ): $(HDR) +demo.o: $(HDR) demo: demo.o libparsepcf.a $(CC) -o $@ demo.o libparsepcf.a $(LDFLAGS) @@ -165,8 +165,8 @@ print_bitmaps(void) printf("\tsize: %zu\n", bitmaps.bitmap_size); printf("\tpacking: %zu\n", bitmaps.bit_packing); printf("\tpadding: %zu\n", bitmaps.row_padding); - printf("\tlsbyte: %i\n", bitmaps.lsbyte); - printf("\tlsbit: %i\n", bitmaps.lsbit); + printf("\tmsbyte_first: %i\n", bitmaps.msbyte_first); + printf("\tmsbit_first: %i\n", bitmaps.msbit_first); if (!bitmaps.glyph_count) return; bitmaptab = calloc(bitmaps.glyph_count, sizeof(*bitmaptab)); @@ -205,17 +205,17 @@ print_bdf_encodings(void) printf(" BDF ENCODINGS:\n"); printf("\trange2: [%u, %u]\n", encoding.min_byte2, encoding.max_byte2); printf("\trange1: [%u, %u]\n", encoding.min_byte1, encoding.max_byte1); - printf("\tdefault: %u\n", encoding.default_char); - printf("\tnglyph: %zu\n", encoding.glyph_count); - if (!encoding.glyph_count) + printf("\tdefault: %u\n", encoding.default_glyph); + printf("\tnchar: %zu\n", encoding.char_count); + if (!encoding.char_count) return; - indices = calloc(encoding.glyph_count, sizeof(*indices)); + indices = calloc(encoding.char_count, sizeof(*indices)); if (libparsepcf_get_glyph_indices(file, len, &tables[table_i], &encoding, - indices, 0, encoding.glyph_count)) { + indices, 0, encoding.char_count)) { perror("libparsepcf_get_glyph_indices"); exit(1); } - for (index_i = 0; index_i < encoding.glyph_count; index_i++) { + for (index_i = 0; index_i < encoding.char_count; index_i++) { if (indices[index_i] == LIBPARSEPCF_NOT_ENCODED) printf("\t#%#zx: not encoded\n", index_i); else @@ -498,10 +498,10 @@ print_glyph(size_t glyph) /* Draw glyph */ for (x = 0; x < width; x++) { - bit = font.bitmaps.lsbit ? 7 - x % 8 : x % 8; + bit = font.bitmaps.msbit_first ? 7 - x % 8 : x % 8; byte = x / 8; - if (!font.bitmaps.lsbyte) - byte = ((byte & ~packing) | (packing - (byte & packing))); + if (font.bitmaps.msbyte_first != font.bitmaps.msbit_first) + byte ^= packing; /* Use <> to mark dots outside of the glyph box */ if (mtx.left_side_bearing < 0 && @@ -521,7 +521,7 @@ print_glyph(size_t glyph) } printf("\033[%sm%s\033[%sm", - ((bitmap[byte] >> bit) & 1) ? "1;37" : "2;37", pixel, + (bitmap[byte] & (1 << bit)) ? "1;37" : "2;37", pixel, (int64_t)y + 1 == (int64_t)mtx.character_ascent ? "0;4" : "0"); } @@ -650,11 +650,11 @@ draw_glyph(size_t glyph, int32_t *xp, char ***linesp, int32_t *leftp, int32_t *r ypos = (size_t)(*ascentp - mtx.character_ascent); for (y = 0; y < height; y++, bitmap += row_size) { for (x = 0; x < width; x++) { - bit = font.bitmaps.lsbit ? 7 - x % 8 : x % 8; + bit = font.bitmaps.msbit_first ? 7 - x % 8 : x % 8; byte = x / 8; - if (!font.bitmaps.lsbyte) - byte = ((byte & ~packing) | (packing - (byte & packing))); - if ((bitmap[byte] >> bit) & 1) + if (font.bitmaps.msbyte_first != font.bitmaps.msbit_first) + byte ^= packing; + if (bitmap[byte] & (1 << bit)) (*linesp)[y + ypos][x + xpos] |= 1; } } @@ -679,7 +679,7 @@ print_line(const char *str) if (n) { if ((*s & 0xC0) != 0x80) { n = 0; - glyph = (size_t)font.encoding.default_char; + glyph = (size_t)font.encoding.default_glyph; goto have_glyph; } else { n -= 1; @@ -687,7 +687,7 @@ print_line(const char *str) codepoint |= *s++ & 0x3F; } } else if ((*s & 0xC0) == 0x80) { - glyph = (size_t)font.encoding.default_char; + glyph = (size_t)font.encoding.default_glyph; s++; goto have_glyph; } else if (*s & 0x80) { @@ -709,7 +709,7 @@ print_line(const char *str) if (codepoint > UINT32_C(0xFFFF) || codepoint < (uint32_t)font.encoding.min_byte2 || codepoint > (uint32_t)font.encoding.max_byte2) { - glyph = (size_t)font.encoding.default_char; + glyph = (size_t)font.encoding.default_glyph; goto have_glyph; } glyph = codepoint - (uint32_t)font.encoding.min_byte2; @@ -721,7 +721,7 @@ print_line(const char *str) hi > (uint32_t)font.encoding.max_byte1 || lo < (uint32_t)font.encoding.min_byte2 || lo > (uint32_t)font.encoding.max_byte2) { - glyph = (size_t)font.encoding.default_char; + glyph = (size_t)font.encoding.default_glyph; goto have_glyph; } glyph = (size_t)(uint16_t)(hi * k + lo - m); @@ -734,7 +734,7 @@ print_line(const char *str) have_glyph: if (glyph == LIBPARSEPCF_NOT_ENCODED) - glyph = (size_t)font.encoding.default_char; + glyph = (size_t)font.encoding.default_glyph; draw_glyph(glyph, &xpos, &lines, &left, &right, &ascent, &descent); } diff --git a/libparsepcf.h b/libparsepcf.h index eef98c8..f7e6941 100644 --- a/libparsepcf.h +++ b/libparsepcf.h @@ -9,7 +9,6 @@ /* Based on documentation from FontForge: https://fontforge.org/docs/techref/pcf-format.html */ - /** * Table metadata */ @@ -399,28 +398,113 @@ struct libparsepcf_bitmaps { /** * The size of `.bitmap_data` + * + * Used internally to detect corruption */ size_t bitmap_size; + /** + * For each row in a glyph, cells' ink status are + * encoded in bits that are packed into groups of + * units, and the bits are ordered according to + * `.msbit_first` within each group. This field + * specifies the number of bytes in each group. + * + * This will always be a power of two and + * no greater than `.row_padding` + */ size_t bit_packing; /** - * The number of bytes each row is - * padded to align to + * 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; + /** + * This field specify the order of the bytes for + * each group of bits as described in the documentation + * of `.bit_packing`. The value will be either 0 or 1 + * + * If 0, the bytes in each glyph cell group is ordered + * such that the least significant bit octet is stored + * in the first byte + * + * If 1, the bytes in each glyph cell group is ordered + * such that the least significant bit octet is stored + * in the first byte + */ + int msbyte_first; /* called "lsbyte" in 1.0 */ + + /** + * Will either be 0 or 1 + * + * If 0, glyph cells (left to right) are encoded from + * the least significant bit to the most significant + * bit within each byte + * + * If 1, glyph cells (left to right) are encoded from + * the most significant bit to the least significant + * bit within each byte + */ + int msbit_first; /* called "lsbit" in 1.0 */ + + /** + * Bitmap data, `libparsepcf_get_bitmap_offsets` should be + * be used to find where in this buffer the bitmap for a + * particular glyph begins, and the `LIBPARSEPCF_INK_METRICS` + * table shall be used (along with information in this + * structure) to decode the bitmap data; if the table + * `LIBPARSEPCF_INK_METRICS` is missing the + * `LIBPARSEPCF_METRICS` (layout metrics) should be used + * instead + * + * Bitmaps are in row-major order, top to bottom, + * and in column-minor order, left to right + * + * Set bits represent ink-on, cleared bits represent ink-off + */ const uint8_t *bitmap_data; }; +/** + * Get the bitmaps metadata for the glyphs in the file + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_BITMAPS`, + * extracted using the `libparsepcf_get_tables` function + * @param meta Output parameter for the glyph bitmap metadata + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ int libparsepcf_get_bitmaps(const void *, size_t, const struct libparsepcf_table *, struct libparsepcf_bitmaps *); +/** + * Get the offsets to the bitmaps for glyphs in the file + * + * The first four arguments shall be the same as + * passed into `libparsepcf_get_bitmaps` + * + * @param file The file content + * @param size The file size + * @param table The table in the file with the `.type` `LIBPARSEPCF_BITMAPS`, + * extracted using the `libparsepcf_get_tables` function + * @param meta Glyph bitmap metadata + * @param offs Output parameter for the bitmap offsets + * @param first The index of the first glyph whose bitmap offset to store + * in `offs`, the first glyph in the file has the index 0 + * @param count The number of glyphs whose bitmap offsets to store in `offs`; + * may not exceed the number of properties (`.glyph_count`) + * as retrieved by `libparsepcf_get_bitmaps` minus `first` + * @return 0 on success, -1 on failure + * + * @throws EBFONT The file is not a properly formatted PCF file + */ int libparsepcf_get_bitmap_offsets(const void *, size_t, const struct libparsepcf_table *, const struct libparsepcf_bitmaps *, @@ -501,25 +585,16 @@ struct libparsepcf_encoding { * 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; + uint16_t default_glyph; /* called "default_char" in 1.0 */ /** * 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`. - * - * 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" + * `.max_byte1 - .min_byte1 + 1` */ - size_t glyph_count; + size_t char_count; /* called "glyph_count" in 1.0 */ }; /** diff --git a/libparsepcf_get_bitmaps.c b/libparsepcf_get_bitmaps.c index cad51f3..8265db3 100644 --- a/libparsepcf_get_bitmaps.c +++ b/libparsepcf_get_bitmaps.c @@ -39,8 +39,8 @@ libparsepcf_get_bitmaps(const void *file, size_t size, 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); + meta->msbyte_first = !!(table->format & LIBPARSEPCF_BYTE); + meta->msbit_first = !!(table->format & LIBPARSEPCF_BIT); if (meta->row_padding < meta->bit_packing) goto ebfont; diff --git a/libparsepcf_get_encoding.c b/libparsepcf_get_encoding.c index 6c28c6a..86b790d 100644 --- a/libparsepcf_get_encoding.c +++ b/libparsepcf_get_encoding.c @@ -26,16 +26,16 @@ libparsepcf_get_encoding(const void *file, size_t size, 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); + meta->default_glyph = PARSE_UINT16(&text[pos + 8], msb); pos += 10; if (meta->min_byte2 > meta->max_byte2 || meta->max_byte2 > 255 || meta->min_byte1 > meta->max_byte1 || meta->max_byte1 > 255) goto ebfont; - 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) + meta->char_count = (size_t)(meta->max_byte2 - meta->min_byte2 + 1); + meta->char_count *= (size_t)(meta->max_byte1 - meta->min_byte1 + 1); + if (meta->char_count > table->size - (pos - table->offset) / 2) goto ebfont; return 0; |