+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <assert.h>
+#include <endian.h>
+
+#include "aaf.h"
+
+int read_aaf(FILE * in, struct aaf * _aaf)
+{
+ size_t elements = 0;
+ int i;
+
+ assert(in != NULL);
+ assert(_aaf != NULL);
+
+ elements = fread(_aaf, sizeof(struct aaf), 1, in);
+ if (elements == 0) {
+ perror("Unable to correctly read input file");
+ return 1;
+ }
+
+ if (strncmp("AAFF", _aaf->signature, 4) != 0) {
+ fprintf(stderr, "Invalid sigature of input file\n");
+ return 2;
+ }
+
+ _aaf->max_h = be16toh(_aaf->max_h);
+ _aaf->gap_h = be16toh(_aaf->gap_h);
+ _aaf->space_width = be16toh(_aaf->space_width);
+ _aaf->gap_v = be16toh(_aaf->gap_v);
+
+ for (i = 0; i < AAF_GLYPH_MAX; i++) {
+ _aaf->glyphs[i].w = be16toh(_aaf->glyphs[i].w);
+ _aaf->glyphs[i].h = be16toh(_aaf->glyphs[i].h);
+ _aaf->glyphs[i].off = be32toh(_aaf->glyphs[i].off);
+ }
+
+ return 0;
+}
+
+void free_aaf_glyph_data(struct aaf_glyph_data ** data)
+{
+ int i;
+
+ assert(data);
+
+ for (i = 0; i < AAF_GLYPH_MAX; i++) {
+ if (data[i]) {
+ free(data[i]->pixels);
+ free(data[i]);
+ data[i] = NULL;
+ }
+ }
+
+ free(data);
+ data = NULL;
+}
+
+struct aaf_glyph_data ** read_aaf_glyph_data(FILE * in, struct aaf * _aaf)
+{
+ struct aaf_glyph_data ** data = NULL;
+ long offset;
+ int i;
+
+ assert(in != NULL);
+ assert(_aaf != NULL);
+
+ offset = ftell(in);
+
+ data = malloc(sizeof(struct aaf_glyph_data*) * AAF_GLYPH_MAX);
+
+ for (i = 0; i < AAF_GLYPH_MAX; i++) {
+ const struct aaf_glyph * glyph = &(_aaf->glyphs[i]);
+
+ data[i] = NULL;
+
+ if ((glyph->w * glyph->h) == 0) {
+ continue;
+ }
+
+ data[i] = malloc(sizeof(struct aaf_glyph_data));
+ if (data[i] == NULL) {
+ perror("Unable to allocate memory for glyph data");
+ free_aaf_glyph_data(data);
+ fseek(in, offset, SEEK_SET);
+ return NULL;
+ }
+
+ data[i]->pixels = malloc(sizeof(uint8_t) * glyph->w * glyph->h);
+ if (data[i]->pixels == NULL) {
+ perror("Unable to allocate memory for glyph pixel data");
+ free_aaf_glyph_data(data);
+ fseek(in, offset, SEEK_SET);
+ return NULL;
+ }
+
+ fseek(in, sizeof(struct aaf) + glyph->off, SEEK_SET);
+ fread(data[i]->pixels, sizeof(uint8_t), glyph->w * glyph->h, in);
+ }
+
+ fseek(in, offset, SEEK_SET);
+
+ return data;
+}
+
+int write_aaf_glyph_as_pgm(FILE * out, const struct aaf_glyph * glyph, const struct aaf_glyph_data * data)
+{
+ int w = 0;
+ int h = 0;
+ int error = 0;
+
+ assert(out != NULL);
+ assert(glyph != NULL);
+ assert(data != NULL);
+
+ error = fprintf(out, "%s\n%d %d\n%d\n",
+ "P2",
+ glyph->w,
+ glyph->h,
+ 9
+ );
+
+ if (error < 0) {
+ perror("Unable to write PGM header");
+ return error;
+ }
+
+ for (h = 0; h < glyph->h; h++) {
+ for (w = 0; w < glyph->w; w++) {
+ error = fprintf(out, "%d",
+ data->pixels[h * glyph->w + w]
+ );
+
+ if (error < 0) {
+ perror("Unabe to write PGM image data");
+ return error;
+ }
+
+ if (w + 1 < glyph->w) {
+ fputc(' ', out);
+ }
+ }
+
+ fputc('\n', out);
+ }
+
+ return 0;
+}