void fixYOffset(GlyphList &glyphs) { // We try to find the minimum y offset here so we can substract it to make it 0 in the end. // We need to do this, since otherwise the characters will take up too much vertical space. int minYOffset = 0xFFFF; for (GlyphList::const_iterator i = glyphs.begin(), end = glyphs.end(); i != end; ++i) { if (i->pitch == 0) continue; minYOffset = std::min(minYOffset, i->yOffset); } // Adapt all glyphs for (GlyphList::iterator i = glyphs.begin(), end = glyphs.end(); i != end; ++i) { if (i->pitch == 0) continue; i->yOffset -= minYOffset; } }
int main(int argc, char *argv[]) { if (argc < 2 || argc > 3) { printf("Usage:\n\t%s <input ttf font> [outfile]\n", argv[0]); return -1; } const char *font = argv[1]; const char *out = 0; if (argc == 3) out = argv[2]; else out = "sjis.fnt"; if (!initSJIStoUTF32Conversion()) { error("Could not initialize conversion from SJIS to UTF-32."); return -1; } atexit(deinitSJIStoUTF32Conversion); TrueTypeFont *ttf = new TrueTypeFont(); if (!ttf->load(font)) { delete ttf; error("Could not initialize FreeType library."); return -1; } if (!ttf->setSize(16)) { delete ttf; error("Could not setup font '%s' to size 16", font); return -1; } GlyphList glyphs; int chars8x16 = 0; int chars16x16 = 0; ttf->renderASCIIGlyphs(glyphs, chars8x16); ttf->renderKANJIGlyphs(glyphs, chars16x16); if (!ttf->setSize(12)) { delete ttf; error("Could not setup font '%s' to size 12", font); return -1; } GlyphList pceGlyphs; int chars12x12 = 0; ttf->renderKANJIGlyphs(pceGlyphs, chars12x12); delete ttf; ttf = 0; fixYOffset(glyphs); fixYOffset(pceGlyphs); // Check whether we have a character which does not fit within the boundaries for (GlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i) { if (i->pitch == 0) continue; if ((isASCII(i->fB) && !i->checkSize(8, 16)) || (!isASCII(i->fB) && !i->checkSize(16, 16))) { error("Could not fit glyph for %.2X %.2X top: %d bottom: %d, left: %d right: %d, xOffset: %d, yOffset: %d, width: %d, height: %d", i->fB, i->sB, i->yOffset, i->yOffset + i->height, i->xOffset, i->xOffset + i->width, i->xOffset, i->yOffset, i->width, i->height); } } // Check whether we have a character which does not fit within the boundaries for (GlyphList::const_iterator i = pceGlyphs.begin(); i != pceGlyphs.end(); ++i) { if (i->pitch == 0) continue; if (!isASCII(i->fB) && !i->checkSize(12, 12)) { error("Could not fit pce glyph for %.2X %.2X top: %d bottom: %d, left: %d right: %d, xOffset: %d, yOffset: %d, width: %d, height: %d", i->fB, i->sB, i->yOffset, i->yOffset + i->height, i->xOffset, i->xOffset + i->width, i->xOffset, i->yOffset, i->width, i->height); } } const int sjis8x16DataSize = chars8x16 * 16; uint8 *sjis8x16FontData = new uint8[sjis8x16DataSize]; if (!sjis8x16FontData) error("Out of memory"); const int sjis16x16DataSize = chars16x16 * 32; uint8 *sjis16x16FontData = new uint8[sjis16x16DataSize]; if (!sjis16x16FontData) { delete[] sjis8x16FontData; error("Out of memory"); } const int sjis12x12DataSize = chars12x12 * 24; uint8 *sjis12x12FontData = new uint8[sjis16x16DataSize]; if (!sjis12x12FontData) { delete[] sjis8x16FontData; delete[] sjis16x16FontData; error("Out of memory"); } memset(sjis8x16FontData, 0, sjis8x16DataSize); memset(sjis16x16FontData, 0, sjis16x16DataSize); memset(sjis12x12FontData, 0, sjis12x12DataSize); for (GlyphList::const_iterator i = glyphs.begin(); i != glyphs.end(); ++i) { if (isASCII(i->fB)) { int chunk = mapASCIItoChunk(i->fB); if (chunk != -1) i->convertChar8x16(sjis8x16FontData + chunk * 16); } else { int chunk = mapSJIStoChunk(i->fB, i->sB); if (chunk != -1) i->convertChar16x16(sjis16x16FontData + chunk * 32); } } for (GlyphList::const_iterator i = pceGlyphs.begin(), end = pceGlyphs.end(); i != end; ++i) { int chunk = mapSJIStoChunk(i->fB, i->sB); if (chunk != -1) i->convertChar16x16(sjis12x12FontData + chunk * 24); } Common::File sjisFont(out, "wb"); if (sjisFont.isOpen()) { // Write our magic bytes sjisFont.writeUint32BE(MKID_BE('SCVM')); sjisFont.writeUint32BE(MKID_BE('SJIS')); // Write version sjisFont.writeUint32BE(0x00000003); // Write character count sjisFont.writeUint16BE(chars16x16); sjisFont.writeUint16BE(chars8x16); sjisFont.writeUint16BE(chars12x12); sjisFont.write(sjis16x16FontData, sjis16x16DataSize); sjisFont.write(sjis8x16FontData, sjis8x16DataSize); sjisFont.write(sjis12x12FontData, sjis12x12DataSize); delete[] sjis8x16FontData; delete[] sjis16x16FontData; delete[] sjis12x12FontData; if (sjisFont.err()) error("Error while writing to font file: '%s'", out); } else { delete[] sjis8x16FontData; delete[] sjis16x16FontData; delete[] sjis12x12FontData; error("Could not open file '%s' for writing", out); } return 0; }