aboutsummaryrefslogtreecommitdiffstats
path: root/demo.c
diff options
context:
space:
mode:
authorMattias Andrée <maandree@kth.se>2021-10-29 23:00:19 +0200
committerMattias Andrée <maandree@kth.se>2021-10-29 23:00:19 +0200
commit52f4424f2dcffa5e20e55c52a5777ce9212d05c5 (patch)
tree74bde882b97c6cdd5e8fdfd1342fbb5dcef0d00b /demo.c
downloadlibparsepcf-52f4424f2dcffa5e20e55c52a5777ce9212d05c5.tar.gz
libparsepcf-52f4424f2dcffa5e20e55c52a5777ce9212d05c5.tar.bz2
libparsepcf-52f4424f2dcffa5e20e55c52a5777ce9212d05c5.tar.xz
First commit
Signed-off-by: Mattias Andrée <maandree@kth.se>
Diffstat (limited to 'demo.c')
-rw-r--r--demo.c580
1 files changed, 580 insertions, 0 deletions
diff --git a/demo.c b/demo.c
new file mode 100644
index 0000000..c277da2
--- /dev/null
+++ b/demo.c
@@ -0,0 +1,580 @@
+#include "libparsepcf.h"
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static char *file = NULL;
+static size_t len = 0;
+
+static size_t table_n;
+static size_t table_i;
+static struct libparsepcf_table *tables;
+
+static struct libparsepcf_font font;
+
+
+static void
+load_file(void)
+{
+ size_t size = 0;
+ ssize_t r;
+
+ if (isatty(STDIN_FILENO)) {
+ fprintf(stderr, "An uncompressed PCF file is required as standard input\n");
+ exit(1);
+ }
+
+ for (;;) {
+ if (size == len) {
+ file = realloc(file, size += 8096);
+ if (!file) {
+ perror("realloc");
+ exit(1);
+ }
+ }
+ r = read(STDIN_FILENO, &file[len], size - len);
+ if (r <= 0) {
+ if (!r)
+ break;
+ perror("read");
+ exit(1);
+ }
+ len += (size_t)r;
+ }
+}
+
+
+static void
+print_properties(void)
+{
+ size_t prop_i;
+ struct libparsepcf_properties props;
+ struct libparsepcf_property_subtable *proptab;
+
+ if (libparsepcf_get_properties(file, len, &tables[table_i], &props)) {
+ perror("libparsepcf_get_properties");
+ exit(1);
+ }
+ printf(" PROPERTIES:\n");
+ printf("\tnprops: %zu\n", props.property_count);
+ printf("\tstrlen: %zu\n", props.strings_size);
+ if (!props.property_count)
+ return;
+ proptab = calloc(props.property_count, sizeof(*proptab));
+ if (!proptab) {
+ perror("calloc");
+ exit(1);
+ }
+ if (libparsepcf_get_property_subtable(file, len, &tables[table_i], &props,
+ proptab, 0, props.property_count)) {
+ perror("libparsepcf_get_property_subtable");
+ exit(1);
+ }
+ for (prop_i = 0; prop_i < props.property_count; prop_i++) {
+ printf("\t #%zu\n", prop_i);
+ printf("\t\tname: %s\n", proptab[prop_i].name);
+ if (proptab[prop_i].is_string_property)
+ printf("\t\tvalue: \"%s\"\n", proptab[prop_i].value.string_value);
+ else
+ printf("\t\tvalue: %i\n", proptab[prop_i].value.signed_value);
+ }
+ free(proptab);
+}
+
+
+static void
+print_metrics(const char *header)
+{
+ struct libparsepcf_metrics *metrics;
+ size_t mtx_i, mtx_n;
+
+ if (libparsepcf_get_metrics_count(file, len, &tables[table_i], &mtx_n)) {
+ perror("libparsepcf_get_metrics_count");
+ exit(1);
+ }
+ metrics = calloc(mtx_n, sizeof(*metrics));
+ if (!metrics) {
+ perror("calloc");
+ exit(1);
+ }
+ if (libparsepcf_get_metrics(file, len, &tables[table_i], metrics, 0, mtx_n)) {
+ perror("libparsepcf_get_metrics");
+ exit(1);
+ }
+ printf(" %s:\n", header);
+ printf("\tcount: %zu\n", mtx_n);
+ for (mtx_i = 0; mtx_i < mtx_n; mtx_i++) {
+ printf("\t#%zu: lsb=%i, rsb=%i, width=%i, ascent=%i, descent=%i, attributes=%x\n",
+ mtx_i, metrics[mtx_i].left_side_bearing, metrics[mtx_i].right_side_bearing,
+ metrics[mtx_i].character_width, metrics[mtx_i].character_ascent,
+ metrics[mtx_i].character_descent, metrics[mtx_i].character_attributes);
+ }
+ free(metrics);
+}
+
+
+static void
+print_glyph_names(void)
+{
+ size_t name_i;
+ struct libparsepcf_glyph_names names;
+ const char **nametab;
+
+ if (libparsepcf_get_glyph_names(file, len, &tables[table_i], &names)) {
+ perror("libparsepcf_get_glyph_names");
+ exit(1);
+ }
+ printf(" GLYPH NAMES:\n");
+ printf("\tnglyph: %zu\n", names.glyph_count);
+ printf("\tstrlen: %zu\n", names.strings_size);
+ if (!names.glyph_count)
+ return;
+ nametab = calloc(names.glyph_count, sizeof(*nametab));
+ if (!nametab) {
+ perror("calloc");
+ exit(1);
+ }
+ if (libparsepcf_get_glyph_name_subtable(file, len, &tables[table_i], &names,
+ nametab, 0, names.glyph_count)) {
+ perror("libparsepcf_get_glyph_name_subtable");
+ exit(1);
+ }
+ for (name_i = 0; name_i < names.glyph_count; name_i++)
+ printf("\t #%zu: %s\n", name_i, nametab[name_i]);
+ free(nametab);
+}
+
+
+static void
+print_bitmaps(void)
+{
+ size_t bitmap_i;
+ struct libparsepcf_bitmaps bitmaps;
+ size_t *bitmaptab;
+
+ if (libparsepcf_get_bitmaps(file, len, &tables[table_i], &bitmaps)) {
+ perror("libparsepcf_get_bitmaps");
+ exit(1);
+ }
+ printf(" BITMAPS:\n");
+ printf("\tnglyph: %zu\n", bitmaps.glyph_count);
+ 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);
+ if (!bitmaps.glyph_count)
+ return;
+ bitmaptab = calloc(bitmaps.glyph_count, sizeof(*bitmaptab));
+ if (!bitmaptab) {
+ perror("calloc");
+ exit(1);
+ }
+ if (libparsepcf_get_bitmap_offsets(file, len, &tables[table_i], &bitmaps,
+ bitmaptab, 0, bitmaps.glyph_count)) {
+ perror("libparsepcf_get_bitmap_offsets");
+ exit(1);
+ }
+ for (bitmap_i = 0; bitmap_i < bitmaps.glyph_count; bitmap_i++) {
+ 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]);
+ }
+ free(bitmaptab);
+}
+
+
+static void
+print_bdf_encodings(void)
+{
+ struct libparsepcf_encoding encoding;
+ size_t *indices;
+ size_t index_i;
+
+ if (libparsepcf_get_encoding(file, len, &tables[table_i], &encoding)) {
+ perror("libparsepcf_get_encoding:");
+ exit(1);
+ }
+ 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)
+ return;
+ indices = calloc(encoding.glyph_count, sizeof(*indices));
+ if (libparsepcf_get_glyph_indices(file, len, &tables[table_i], &encoding,
+ indices, 0, encoding.glyph_count)) {
+ perror("libparsepcf_get_glyph_indices");
+ exit(1);
+ }
+ for (index_i = 0; index_i < encoding.glyph_count; index_i++) {
+ if (indices[index_i] == LIBPARSEPCF_NOT_ENCODED)
+ printf("\t#%#zx: not encoded\n", index_i);
+ else
+ printf("\t#%#zx: %zu\n", index_i, indices[index_i]);
+ }
+ free(indices);
+}
+
+
+static void
+print_accelerators(const char *header)
+{
+ struct libparsepcf_accelerators accel;
+
+ if (libparsepcf_get_accelerators(file, len, &tables[table_i], &accel)) {
+ perror("libparsepcf_get_accelerators:");
+ exit(1);
+ }
+ printf(" %s:\n", header);
+ printf("\tno overlap: %i\n", accel.no_overlap);
+ printf("\tconstant metrics: %i\n", accel.constant_metrics);
+ printf("\tterminal font: %i\n", accel.terminal_font);
+ printf("\tconstant width: %i\n", accel.constant_width);
+ printf("\tink inside: %i\n", accel.ink_inside);
+ printf("\tink metrics: %i\n", accel.ink_metrics);
+ printf("\tdraw rtl: %i\n", accel.draw_rtl);
+ printf("\thave ink bounds: %i\n", accel.have_ink_bounds);
+ printf("\tfont ascent: %i\n", accel.font_ascent);
+ printf("\tfont descent: %i\n", accel.font_descent);
+ printf("\tmax overlap: %i\n", accel.max_overlap);
+ printf("\tmin bounds: lsb=%i, rsb=%i, width=%i, ascent=%i, descent=%i, attributes=%x\n",
+ accel.min_bounds.left_side_bearing, accel.min_bounds.right_side_bearing,
+ accel.min_bounds.character_width, accel.min_bounds.character_ascent,
+ accel.min_bounds.character_descent, accel.min_bounds.character_attributes);
+ printf("\tmax bounds: lsb=%i, rsb=%i, width=%i, ascent=%i, descent=%i, attributes=%x\n",
+ accel.max_bounds.left_side_bearing, accel.max_bounds.right_side_bearing,
+ accel.max_bounds.character_width, accel.max_bounds.character_ascent,
+ accel.max_bounds.character_descent, accel.max_bounds.character_attributes);
+ if (accel.have_ink_bounds) {
+ printf("\tmin ink bounds: lsb=%i, rsb=%i, width=%i, ascent=%i, descent=%i, attributes=%x\n",
+ accel.min_ink_bounds.left_side_bearing, accel.min_ink_bounds.right_side_bearing,
+ accel.min_ink_bounds.character_width, accel.min_ink_bounds.character_ascent,
+ accel.min_ink_bounds.character_descent, accel.min_ink_bounds.character_attributes);
+ printf("\tmax ink bounds: lsb=%i, rsb=%i, width=%i, ascent=%i, descent=%i, attributes=%x\n",
+ accel.max_ink_bounds.left_side_bearing, accel.max_ink_bounds.right_side_bearing,
+ accel.max_ink_bounds.character_width, accel.max_ink_bounds.character_ascent,
+ accel.max_ink_bounds.character_descent, accel.max_ink_bounds.character_attributes);
+ }
+}
+
+
+static void
+print_swidths(void)
+{
+ size_t sw_i, sw_n;
+ int32_t *swidths;
+
+ if (libparsepcf_get_swidth_count(file, len, &tables[table_i], &sw_n)) {
+ perror("libparsepcf_get_swidth_count");
+ exit(1);
+ }
+ printf(" SWIDTHS:\n");
+ printf("\tnglyph: %zu\n", sw_n);
+ if (!sw_n)
+ return;
+ swidths = calloc(sw_n, sizeof(*swidths));
+ if (libparsepcf_get_swidths(file, len, &tables[table_i], swidths, 0, sw_n)) {
+ perror("libparsepcf_get_swidths");
+ exit(1);
+ }
+ for (sw_i = 0; sw_i < sw_n; sw_i++)
+ printf("\t#%zu: %i milli-ems\n", sw_i, swidths[sw_i]);
+}
+
+
+static void
+print_font(void)
+{
+ if (libparsepcf_get_table_count(file, len, &table_n)) {
+ perror("libparsepcf_get_table_count");
+ exit(1);
+ }
+ fprintf(stderr, "size: %zu\n", len);
+ fprintf(stderr, "ntables: %zu\n", table_n);
+
+ tables = calloc(table_n, sizeof(*tables));
+ if (!tables) {
+ perror("calloc");
+ exit(1);
+ }
+ if (libparsepcf_get_tables(file, len, tables, 0, table_n)) {
+ perror("libparsepcf_get_tables");
+ exit(1);
+ }
+
+ for (table_i = 0; table_i < table_n; table_i++) {
+ printf("table #%zu: type=%#x, format=%#x, offset=%u, size=%u, (end=%u)\n",
+ table_i, tables[table_i].type, tables[table_i].format,
+ tables[table_i].offset, tables[table_i].size,
+ tables[table_i].offset + tables[table_i].size);
+
+ switch (tables[table_i].type) {
+#if 1
+ case LIBPARSEPCF_PROPERTIES: /* X font atoms */
+ print_properties();
+ break;
+#endif
+#if 0
+ case LIBPARSEPCF_METRICS: /* bitmap size */
+ print_metrics("METRICS");
+ break;
+#endif
+#if 0
+ case LIBPARSEPCF_INK_METRICS: /* minimium bounding box metrics */
+ print_metrics("INK METRICS");
+ break;
+#endif
+#if 0
+ case LIBPARSEPCF_GLYPH_NAMES: /* PostScript names */
+ print_glyph_names();
+ break;
+#endif
+#if 0
+ case LIBPARSEPCF_BITMAPS:
+ print_bitmaps();
+ break;
+#endif
+#if 0
+ case LIBPARSEPCF_BDF_ENCODINGS:
+ print_bdf_encodings();
+ break;
+#endif
+#if 1
+ case LIBPARSEPCF_ACCELERATORS:
+ print_accelerators("ACCELERATORS");
+ break;
+#endif
+#if 1
+ case LIBPARSEPCF_BDF_ACCELERATORS: /* prefered over LIBPARSEPCF_ACCELERATORS */
+ print_accelerators("BDF ACCELERATORS");
+ break;
+#endif
+#if 0
+ case LIBPARSEPCF_SWIDTHS:
+ print_swidths();
+ break;
+#endif
+ default:
+ (void) print_properties;
+ (void) print_metrics;
+ (void) print_glyph_names;
+ (void) print_bitmaps;
+ (void) print_bdf_encodings;
+ (void) print_accelerators;
+ (void) print_swidths;
+ break;
+ }
+ }
+
+ free(tables);
+}
+
+
+static void
+print_glyph_info(size_t glyph, const struct libparsepcf_metrics *mtx)
+{
+ struct libparsepcf_metrics inkmtx;
+ const char *name;
+ int32_t s32;
+
+ if (font.name_table) {
+ if (libparsepcf_get_glyph_name_subtable(file, len, font.name_table, &font.names, &name, glyph, 1)) {
+ perror("libparsepcf_get_glyph_name_subtable");
+ exit(1);
+ }
+ printf("glyph name: %s\n", name);
+ }
+ if (font.swidth_table) {
+ if (libparsepcf_get_swidths(file, len, font.swidth_table, &s32, glyph, 1)) {
+ perror("libparsepcf_get_swidths");
+ exit(1);
+ }
+ printf("scalable width: %i milli-ems\n", s32);
+ }
+ printf("metrics:\n");
+ printf(" left side bearing: %i\n", mtx->left_side_bearing);
+ printf(" right side bearing: %i\n", mtx->right_side_bearing);
+ printf(" character width: %i\n", mtx->character_width);
+ printf(" character ascent: %i\n", mtx->character_ascent);
+ printf(" character descent: %i\n", mtx->character_descent);
+ printf(" character attributes: %u\n", mtx->character_attributes);
+ if (font.inkmtx_table) {
+ if (libparsepcf_get_metrics(file, len, font.inkmtx_table, &inkmtx, glyph, 1)) {
+ perror("libparsepcf_get_metrics");
+ exit(1);
+ }
+ printf("ink metrics:\n");
+ printf(" left side bearing: %i\n", inkmtx.left_side_bearing);
+ printf(" right side bearing: %i\n", inkmtx.right_side_bearing);
+ printf(" character width: %i\n", inkmtx.character_width);
+ printf(" character ascent: %i\n", inkmtx.character_ascent);
+ printf(" character descent: %i\n", inkmtx.character_descent);
+ printf(" character attributes: %u\n", inkmtx.character_attributes);
+ }
+ if (font.accel_table) {
+ printf("font ascent: %i\n", font.accels.font_ascent);
+ printf("font descent: %i\n", font.accels.font_descent);
+ }
+}
+
+
+static void
+print_glyph(size_t glyph)
+{
+ struct libparsepcf_metrics mtx;
+ size_t width, height, bitmap_size, bitmap_offset;
+ size_t row_size, padding, y, x, bit, byte, packing;
+ int32_t font_ascent, font_descent;
+ size_t extra_left, extra_right, print_width;
+ const uint8_t *bitmap;
+ const char *pixel;
+
+ if (glyph >= font.glyph_count) {
+ fprintf(stderr, "specified glyph does not exist\n");
+ exit(1);
+ }
+ if (libparsepcf_get_metrics(file, len, font.mtx_table, &mtx, glyph, 1)) {
+ perror("libparsepcf_get_metrics");
+ exit(1);
+ }
+ padding = font.bitmaps.row_padding - 1;
+ packing = font.bitmaps.bit_packing - 1;
+ width = (size_t)((int32_t)mtx.right_side_bearing - (int32_t)mtx.left_side_bearing);
+ height = (size_t)((int32_t)mtx.character_ascent + (int32_t)mtx.character_descent);
+ row_size = width / 8 + !!(width & 7);
+ row_size = row_size + ((font.bitmaps.row_padding - (row_size & padding)) & padding);
+ if (font.accel_table) {
+ font_ascent = font.accels.font_ascent;
+ font_descent = font.accels.font_descent;
+ } else {
+ font_ascent = mtx.character_ascent;
+ font_descent = mtx.character_descent;
+ }
+
+ print_glyph_info(glyph, &mtx);
+
+ if (libparsepcf_get_bitmap_offsets(file, len, font.bitmap_table, &font.bitmaps, &bitmap_offset, glyph, 1)) {
+ perror("libparsepcf_get_bitmap_offsets");
+ exit(1);
+ }
+ bitmap_size = font.bitmaps.bitmap_size - bitmap_offset;
+ bitmap = &font.bitmaps.bitmap_data[bitmap_offset];
+ if (height && row_size > bitmap_size / height) {
+ perror("bitmap is smaller than expected");
+ exit(1);
+ }
+ printf("\n");
+
+ font_ascent = 15;
+ font_descent = 5;
+
+ extra_left = mtx.left_side_bearing > 0 ? (size_t)mtx.left_side_bearing : 0;
+ extra_right = mtx.character_width > mtx.right_side_bearing ? (size_t)(mtx.character_width - mtx.right_side_bearing) : 0;
+ print_width = extra_left + width + extra_right;
+
+ /* If the font's ascent is greater than the character's, print the excees in black */
+ if (font_ascent > mtx.character_ascent) {
+ for (y = 0; y < (size_t)(font_ascent - mtx.character_ascent); y++) {
+ for (x = 0; x < print_width; x++)
+ printf("\033[1;30m[]");
+ printf("\033[0m\n");
+ }
+ }
+
+ for (y = 0; y < height; y++, bitmap += row_size) {
+ /* Draw baseline */
+ if (y + 1 == mtx.character_ascent)
+ printf("\033[4m");
+
+ /* If glyph is offset for caret, print offset in black */
+ for (x = 0; x < extra_left; x++)
+ printf("\033[1;30m[]");
+
+ /* Draw glyph */
+ for (x = 0; x < width; x++) {
+ bit = font.bitmaps.lsbit ? 7 - x % 8 : x % 8;
+ byte = x / 8;
+ if (!font.bitmaps.lsbyte)
+ byte = ((byte & ~packing) | (packing - (byte & packing)));
+
+ /* Use <> to mark dots outside of the glyph box */
+ if (mtx.left_side_bearing < 0 &&
+ x < (size_t)-mtx.left_side_bearing) {
+ pixel = "<>";
+ } else if (mtx.right_side_bearing > mtx.character_width &&
+ x >= mtx.character_width + mtx.left_side_bearing) {
+ pixel = "<>";
+ } else if (mtx.character_ascent > font_ascent &&
+ y < (size_t)(mtx.character_ascent - font_ascent)) {
+ pixel = "<>";
+ } else if (mtx.character_descent > font_descent &&
+ y >= (size_t)(mtx.character_ascent + font_descent)) {
+ pixel = "<>";
+ } else {
+ pixel = "[]";
+ }
+
+ printf("\033[%sm%s", ((bitmap[byte] >> bit) & 1) ? "1;37" : "2;37", pixel);
+ }
+
+ /* If horizontal advance is larger than character width, print extent in black */
+ for (x = 0; x < extra_right; x++)
+ printf("\033[1;30m[]");
+
+ printf("\033[0m\n");
+ }
+
+ /* If the font's descent is greater than the character's, print the excees in black */
+ if (font_descent > mtx.character_descent) {
+ for (y = 0; y < (size_t)(font_descent - mtx.character_descent); y++) {
+ for (x = 0; x < print_width; x++)
+ printf("\033[1;30m[]");
+ printf("\033[0m\n");
+ }
+ }
+}
+
+
+static void
+print_line(const char *str, size_t strlen) /* TODO */
+{
+}
+
+
+int
+main(int argc, char *argv[])
+{
+ size_t glyph;
+ if (argc) {
+ argc--;
+ argv++;
+ }
+ load_file();
+ if (!argc) {
+ print_font();
+ } else {
+ if (libparsepcf_preparse_font(file, len, &font)) {
+ perror("libparsepcf_preparse_font");
+ exit(1);
+ }
+ if (argc == 2 && !strcmp(argv[0], "-g")) {
+ glyph = (size_t)strtoul(argv[1], NULL, 0);
+ print_glyph(glyph);
+ } else if (argc == 2 && !strcmp(argv[0], "-x")) {
+ glyph = (size_t)strtoul(argv[1], NULL, 16);
+ print_glyph(glyph);
+ } else {
+ for (; argc--; argv++)
+ print_line(*argv, strlen(*argv));
+ }
+ libparsepcf_destroy_preparsed_font(&font);
+ }
+ free(file);
+ return 0;
+}