static bool ProcessFace(FT_Face& face, const string& filename, u32 fontHeight) { string imageName; string specsName; if (!outputFileName.empty()) { imageName = outputFileName + ".png"; specsName = outputFileName + ".lua"; } else { string basename = filename; const string::size_type lastOf = filename.find_last_of('.'); if (lastOf != string::npos) { basename = filename.substr(0, lastOf); if (debugLevel >= 1) { logOutput.Print("basename = %s\n", basename.c_str()); } } char heightText[64]; sprintf(heightText, "_%i", fontHeight); char outlineText[64]; sprintf(outlineText, "_%i", outlineRadius); imageName = basename + heightText + ".png"; specsName = basename + heightText + ".lua"; } logOutput.Print("Processing %s @ %i\n", filename.c_str(), fontHeight); if (debugLevel >= 1) { PrintFaceInfo(face); } u32 maxPixelXsize = 0; u32 maxPixelYsize = 0; for (u32 g = minChar; g <= maxChar; g++) { Glyph* glyph = new Glyph(face, g); if (!glyph->valid) { continue; } glyphs.push_back(glyph); if (outlineRadius> 0) { glyph->Outline(outlineRadius); } if (debugLevel >= 2) { PrintGlyphInfo(face->glyph, g); } if (maxPixelXsize < glyph->xsize) { maxPixelXsize = glyph->xsize; } if (maxPixelYsize < glyph->ysize) { maxPixelYsize = glyph->ysize; } } const u32 xskip = maxPixelXsize + (2 * (padding + stuffing)); const u32 yskip = maxPixelYsize + (2 * (padding + stuffing)); const u32 xdivs = (xTexSize / xskip); const u32 ydivs = ((maxChar - minChar + 1) / xdivs) + 1; yTexSize = ydivs * yskip; u32 binSize = 1; while (binSize < yTexSize) { binSize = binSize << 1; } yTexSize = binSize; if (debugLevel >= 1) { logOutput.Print("xTexSize = %i\n", xTexSize); logOutput.Print("yTexSize = %i\n", yTexSize); logOutput.Print("xdivs = %i\n", xdivs); logOutput.Print("ydivs = %i\n", ydivs); logOutput.Print("maxPixelXsize = %i\n", maxPixelXsize); logOutput.Print("maxPixelYsize = %i\n", maxPixelYsize); } FILE* specFile = fopen(specsName.c_str(), "wt"); if (specFile == NULL) { logOutput.Print("%s: %s\n", specsName.c_str(), strerror(errno)); return false; } u32 yStep; if (FT_IS_SCALABLE(face)) { yStep = (fontHeight * face->height) / face->units_per_EM; } else { yStep = (face->height / 64); if (yStep == 0) { // some fonts do not provide a face->height, so make one up yStep = (5 * fontHeight) / 4; } } fprintf(specFile, "\n"); fprintf(specFile, "local fontSpecs = {\n"); fprintf(specFile, " srcFile = [[%s]],\n", filename.c_str()); fprintf(specFile, " family = [[%s]],\n", face->family_name); fprintf(specFile, " style = [[%s]],\n", face->style_name); fprintf(specFile, " yStep = %i,\n", yStep); fprintf(specFile, " height = %i,\n", fontHeight); fprintf(specFile, " xTexSize = %i,\n", xTexSize); fprintf(specFile, " yTexSize = %i,\n", yTexSize); fprintf(specFile, " outlineRadius = %i,\n", outlineRadius); fprintf(specFile, " outlineWeight = %i,\n", outlineWeight); fprintf(specFile, "}\n"); fprintf(specFile, "\n"); fprintf(specFile, "local glyphs = {}\n"); fprintf(specFile, "\n"); ILuint img; ilGenImages(1, &img); if (img == 0) { logOutput.Print("ERROR: ilGenImages() == 0\n"); return false; } ilBindImage(img); ilTexImage(xTexSize, yTexSize, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL); ilClearColor(1.0f, 1.0f, 1.0f, 0.0f); ilClearImage(); u32 xcell = 0; u32 ycell = 0; for (int g = 0; g < (int)glyphs.size(); g++) { Glyph* glyph = glyphs[g]; const u32 txOffset = (xcell * xskip) + (padding + stuffing); const u32 tyOffset = (ycell * yskip) + (padding + stuffing); ilSetPixels( txOffset, tyOffset, 0, glyph->xsize, glyph->ysize, 1, IL_RGBA, IL_UNSIGNED_BYTE, glyph->pixels ); glyph->txn += txOffset; glyph->tyn += tyOffset; glyph->txp += txOffset; glyph->typ += tyOffset; glyph->SaveSpecs(specFile); if (debugLevel >= 2) { PrintGlyphInfo(face->glyph, g); } xcell++; if (xcell >= xdivs) { xcell = 0; ycell++; } } fprintf(specFile, "\n"); fprintf(specFile, "fontSpecs.glyphs = glyphs\n"); fprintf(specFile, "\n"); fprintf(specFile, "return fontSpecs\n"); fprintf(specFile, "\n"); fclose(specFile); logOutput.Print("Saved: %s\n", specsName.c_str()); ilEnable(IL_FILE_OVERWRITE); ilHint(IL_COMPRESSION_HINT, IL_USE_COMPRESSION); ilSetInteger(IL_PNG_INTERLACE, 0); ilSetString(IL_PNG_TITLE_STRING, imageName.c_str()); ilSetString(IL_PNG_AUTHNAME_STRING, "FontTexture"); ilSetString(IL_PNG_DESCRIPTION_STRING, (outlineRadius> 0) ? "outlined" : "plain"); ilSaveImage((char*)imageName.c_str()); ilDisable(IL_FILE_OVERWRITE); logOutput.Print("Saved: %s\n", imageName.c_str()); ilDeleteImages(1, &img); return true; }