#include #include #include #include #include "netpbm/mallocvar.h" #include "pm.h" #include "ppmdfont.h" extern struct ppmd_font ppmd_standardfont; static const struct ppmd_font * currentFontP = &ppmd_standardfont; static void readGlyphHeader(FILE * const ifP, struct ppmd_glyphHeader * const glyphHeaderP) { glyphHeaderP->commandCount = fgetc(ifP); glyphHeaderP->skipBefore = fgetc(ifP); glyphHeaderP->skipAfter = fgetc(ifP); } static void readGlyphCommand(FILE * const ifP, struct ppmd_glyphCommand * const glyphCommandP) { glyphCommandP->verb = fgetc(ifP); glyphCommandP->x = fgetc(ifP); glyphCommandP->y = fgetc(ifP); } static void readCharacter(FILE * const ifP, struct ppmd_glyph * const glyphP) { unsigned int commandNum; struct ppmd_glyphCommand * commandList; readGlyphHeader(ifP, &glyphP->header); MALLOCARRAY(commandList, glyphP->header.commandCount); if (commandList == NULL) pm_error("Insufficient memory to create a %u-command " "command list.", glyphP->header.commandCount); for (commandNum = 0; commandNum < glyphP->header.commandCount; ++commandNum) { readGlyphCommand(ifP, &commandList[commandNum]); } glyphP->commandList = commandList; } static void readFontHeader(FILE * const ifP, struct ppmd_fontHeader * const fontHeaderP) { size_t rc; rc = fread(&fontHeaderP->signature, 1, sizeof(fontHeaderP->signature), ifP); if (rc != sizeof(fontHeaderP->signature)) pm_error("Unable to read the header from the font file. " "errno=%d (%s)", errno, strerror(errno)); fontHeaderP->format = fgetc(ifP); fontHeaderP->characterCount = fgetc(ifP); fontHeaderP->firstCodePoint = fgetc(ifP); } void ppmd_set_font(const struct ppmd_font * const newFontP) { currentFontP = newFontP; } const struct ppmd_font * ppmd_get_font(void) { return currentFontP; } void ppmd_read_font(FILE * const ifP, const struct ppmd_font ** const fontPP) { unsigned int relativeCodePoint; struct ppmd_glyph * glyphTable; struct ppmd_font * fontP; MALLOCVAR(fontP); if (fontP == NULL) pm_error("Insufficient memory for font header"); readFontHeader(ifP, &fontP->header); MALLOCARRAY(glyphTable, fontP->header.characterCount); if (glyphTable == NULL) pm_error("Insufficient memory to store %u characters", fontP->header.characterCount); for (relativeCodePoint = 0; relativeCodePoint < fontP->header.characterCount; ++relativeCodePoint) { readCharacter(ifP, &glyphTable[relativeCodePoint]); } fontP->glyphTable = glyphTable; *fontPP = fontP; } void ppmd_free_font(const struct ppmd_font * const fontP) { unsigned int relativeCodePoint; for (relativeCodePoint = 0; relativeCodePoint < fontP->header.characterCount; ++relativeCodePoint) { free((void*)fontP->glyphTable[relativeCodePoint].commandList); } free((void*)fontP->glyphTable); free((void*)fontP); }