Example #1
0
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;
	}
}
Example #2
0
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;
}