Guest User

MakeMWFont

a guest
Jan 21st, 2011
92
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // MakeMwFont.cpp : Defines the entry point for the console application.
  2. //
  3.  
  4. #include "stdafx.h"
  5.  
  6. using namespace std;
  7.  
  8. char texarray[1024][1024][4];
  9. char fntarray[14632];
  10. float * asfloat = (float*)fntarray;
  11. char buf[4000];
  12.  
  13. struct FNTINFO
  14. {
  15.     float left;
  16.     float top;
  17.     float right;
  18.     float bottom;
  19.     float width;
  20.     float height;
  21.     float kerning;
  22.     float ascent;
  23. };
  24. FNTINFO fntinfo[256];
  25.  
  26. const int maxW = 1024;
  27. const int maxH = 1024;
  28.  
  29. int _tmain(int argc, _TCHAR* argv[])
  30. {
  31.     puts("Font Name (example: Verdana) :");
  32.     gets_s(buf);
  33.     string fontname = buf;
  34.  
  35.     puts("Font Size (example: 16 for normal, 20 for large) :");
  36.     gets_s(buf);
  37.     long fontsize = atoi(buf);
  38.  
  39.     puts("Bold? (y for yes, n for no)");
  40.     gets_s(buf);
  41.     bool bold = ( (buf[0]=='y') || (buf[0]=='Y') );
  42.  
  43.     puts("Anti-aliased? (y for yes, n for no)");
  44.     gets_s(buf);
  45.     bool antialiased = ( (buf[0]=='y') || (buf[0]=='Y') );
  46.  
  47.     HDC dc = CreateCompatibleDC(GetDC(0));
  48.     assert(dc);
  49.  
  50.     void * pixelbuffer;
  51.     BITMAPINFO bmi;
  52.     ZeroMemory(&bmi, sizeof(bmi));
  53.     bmi.bmiHeader.biBitCount = 32;
  54.     bmi.bmiHeader.biCompression = BI_RGB;
  55.     bmi.bmiHeader.biWidth = maxW;
  56.     bmi.bmiHeader.biHeight = -maxH;
  57.     bmi.bmiHeader.biPlanes = 1;
  58.     bmi.bmiHeader.biSize = sizeof(bmi);
  59.     bmi.bmiHeader.biXPelsPerMeter = 3600;
  60.     bmi.bmiHeader.biYPelsPerMeter = 3600;
  61.     HBITMAP hbm = CreateDIBSection(dc, &bmi, DIB_RGB_COLORS, &pixelbuffer, NULL, 0);
  62.     assert(hbm);
  63.     assert(pixelbuffer);
  64.  
  65.     RGBQUAD * pixels = (RGBQUAD*)pixelbuffer;
  66.     memset(pixelbuffer, 0xFF, maxW*maxH*4); // make background white
  67.  
  68.     HBITMAP origbm = (HBITMAP)SelectObject(dc, hbm);
  69.  
  70.     HFONT hfont = CreateFont(fontsize, 0, 0, 0,
  71.                         bold?FW_BOLD:FW_NORMAL, FALSE, FALSE, FALSE,
  72.                         ANSI_CHARSET, OUT_RASTER_PRECIS, CLIP_DEFAULT_PRECIS,
  73.                         antialiased?ANTIALIASED_QUALITY:NONANTIALIASED_QUALITY,
  74.                         DEFAULT_PITCH|FF_DONTCARE, fontname.c_str());
  75.     assert(hfont);
  76.  
  77.     HFONT origfont = (HFONT)SelectObject(dc, hfont);
  78.  
  79.     ABCFLOAT charwidths[256];
  80.     BOOL success = GetCharABCWidthsFloat(dc, 0, 255, charwidths);
  81.     assert(success);
  82.     for (int c=0; c<256; ++c)
  83.     {
  84.         // swap out space for unprintable chars
  85.         if (!isprint(c))
  86.         {
  87.             charwidths[c] = charwidths[' '];
  88.         }
  89.     }
  90.  
  91.     TEXTMETRIC textinfo;
  92.     success = GetTextMetrics(dc, &textinfo);
  93.     assert(success);
  94.  
  95.  
  96.  
  97.     // Patch up the font name so it's a good filename
  98.     for (int i=0; i<fontname.size(); ++i)
  99.     {
  100.         if (isspace(fontname[i]))
  101.         {
  102.             fontname[i] = '_';
  103.         }
  104.     }
  105.  
  106.  
  107.     // First, the .tex file.
  108.     long texSize;
  109.     long testW = 0;
  110.     long accum = 0;
  111.     for (int c=0; c<256; ++c)
  112.     {
  113.         if (c%0x0F == 0)
  114.         {
  115.             accum = 0;
  116.         }
  117.  
  118.         if (isprint(c))
  119.         {
  120.             // we want an extra column of pixels on left and right
  121.             // to keep the texturing engine from accidentally picking
  122.             // up adjacent characters
  123.             accum += 2 + charwidths[c].abcfA + charwidths[c].abcfB + charwidths[c].abcfC;
  124.         }
  125.  
  126.         if (accum > testW)
  127.         {
  128.             testW = accum;
  129.         }
  130.     }
  131.     // we want two rows of pixels on top and bottom, as well
  132.     long testH = (textinfo.tmHeight+2)*14; // 16 rows of 16 chars, but the first 32 are non-printable
  133.     long testS = max(testW,testH);
  134.     if (testS <= 128)
  135.     {
  136.         texSize = 128;
  137.     }
  138.     else if (testS <= 256)
  139.     {
  140.         texSize = 256;
  141.     }
  142.     else if (testS <= 512)
  143.     {
  144.         texSize = 512;
  145.     }
  146.     else if (testS <= 1024)
  147.     {
  148.         texSize = 1024;
  149.     }
  150.     else
  151.     {
  152.         puts("Cannot fit the font into 1024x1024 texture.");
  153.     }
  154.  
  155.     sprintf_s(buf, "%s%s%s_%d_0_Lod_A.tex",
  156.         fontname.c_str(),
  157.         bold?"_Bold":"",
  158.         antialiased?"_AA":"",
  159.         fontsize);
  160.     FILE * texout = fopen(buf, "wb");
  161.     assert(texout);
  162.  
  163.     fwrite(&texSize, 4, 1, texout);
  164.     fwrite(&texSize, 4, 1, texout);
  165.     int left = 0;
  166.     int top = 0;
  167.     int tallest = 0;
  168.     char disp[2] = " ";
  169.     HDC dbgDC = GetDC(0);
  170.     for (int c = 0; c<256; ++c)
  171.     {
  172.         if ((c&0x0F) == 0)
  173.         {
  174.             left = 0;
  175.             top += tallest;
  176.         }
  177.  
  178.         if (isprint(c))
  179.         {
  180.             disp[0] = c;
  181.  
  182.             SIZE sz;
  183.             GetTextExtentPoint32(dc, disp, 1, &sz);
  184.  
  185.             assert(sz.cx == (long)(charwidths[c].abcfA + charwidths[c].abcfB + charwidths[c].abcfC));
  186.  
  187.             // make sure we've cleared out previous characters...
  188.             for (int y=0; y<sz.cy+2; ++y)
  189.             {
  190.                 for (int x=0; x<sz.cx+2; ++x)
  191.                 {
  192.                     pixels[y*maxW + x].rgbRed = 0xFF;
  193.                     pixels[y*maxW + x].rgbGreen = 0xFF;
  194.                     pixels[y*maxW + x].rgbBlue = 0xFF;
  195.                     pixels[y*maxW + x].rgbReserved = 0xFF;
  196.                 }
  197.             }
  198.  
  199.             // offset by 1 so that we have some padding around the character.
  200.             TextOut(dc, 1, 1, disp, 1);
  201.  
  202.             for (int y=0; y<sz.cy+2; ++y)
  203.             {
  204.                 for (int x=0; x<sz.cx+2; ++x)
  205.                 {
  206.                     COLORREF clr = RGB( pixels[y*maxW + x].rgbRed,
  207.                                         pixels[y*maxW + x].rgbGreen,
  208.                                         pixels[y*maxW + x].rgbBlue);
  209.                     texarray[left+x][top+y][0] = 0xFF;
  210.                     texarray[left+x][top+y][1] = 0xFF;
  211.                     texarray[left+x][top+y][2] = 0xFF;
  212.                     texarray[left+x][top+y][3] = 0xFF - (unsigned char)(pixels[y*maxW + x].rgbRed);
  213.                 }
  214.             }
  215.  
  216.             fntinfo[c].left = (float)(left+1)/(float)texSize;
  217.             fntinfo[c].top = (float)(top+1)/(float)texSize;
  218.             fntinfo[c].right = (float)(left+sz.cx)/(float)texSize;
  219.             fntinfo[c].bottom = (float)(top+sz.cy)/(float)texSize;
  220.             fntinfo[c].width = sz.cx;
  221.             fntinfo[c].height = sz.cy;
  222.             fntinfo[c].ascent = ceil((double)textinfo.tmAscent) + 2;
  223.             fntinfo[c].kerning = ceil(charwidths[c].abcfA);
  224.  
  225.             left += sz.cx + 2;
  226.             if (sz.cy + 2 > tallest)
  227.             {
  228.                 tallest = sz.cy + 2;
  229.             }
  230.         }
  231.         else
  232.         {
  233.             //disp[0] = ' '; // don't put funky boxes in for the non-printable chars...
  234.  
  235.             // ignore non-printables
  236.             fntinfo[c].left = 0.0;
  237.             fntinfo[c].top = 0.0;
  238.             fntinfo[c].right = 0.0;
  239.             fntinfo[c].bottom = 0.0;
  240.             fntinfo[c].width = 0.0;
  241.             fntinfo[c].height = 0.0;
  242.             fntinfo[c].ascent = 0.0;
  243.             fntinfo[c].kerning = 0.0;
  244.         }
  245.     }
  246.     for (int y=0; y<texSize; ++y)
  247.     {
  248.         for (int x=0; x<texSize; ++x)
  249.         {
  250.             for (int comp=0; comp<4; ++comp)
  251.             {
  252.                 fwrite(&texarray[x][y][comp], 1, 1, texout);
  253.             }
  254.         }
  255.     }
  256.     fclose(texout);
  257.  
  258.  
  259.  
  260.     // Now for the .fnt file.
  261.     sprintf_s(buf, "%s%s%s_%d.fnt",
  262.         fontname.c_str(),
  263.         bold?"_Bold":"",
  264.         antialiased?"_AA":"",
  265.         fontsize);
  266.     FILE * fntout = fopen(buf, "wb");
  267.     float fval;
  268.     long ival;
  269.  
  270.     fval = fontsize;
  271.     fwrite(&fval, 4, 1, fntout);
  272.  
  273.     ival = 1;
  274.     fwrite(&ival, 4, 1, fntout);
  275.     fwrite(&ival, 4, 1, fntout);
  276.  
  277.     sprintf_s(buf, "%s%s%s_%d_0_Lod_A",
  278.         fontname.c_str(),
  279.         bold?"_Bold":"",
  280.         antialiased?"_AA":"",
  281.         fontsize);
  282.     long namelen = strlen(buf);
  283.     fwrite(buf, 1, namelen, fntout);
  284.  
  285.     ZeroMemory(buf, sizeof(buf));
  286.     fwrite(buf, 1, (296-12)-namelen, fntout);
  287.  
  288.     for (int c=0; c<256; ++c)
  289.     {
  290.         fval = 0.0;
  291.         fwrite(&fval, 4, 1, fntout);
  292.  
  293.         fwrite(&fntinfo[c].left, 4, 1, fntout);
  294.         fwrite(&fntinfo[c].top, 4, 1, fntout);
  295.  
  296.         fwrite(&fntinfo[c].right, 4, 1, fntout);
  297.         fwrite(&fntinfo[c].top, 4, 1, fntout);
  298.  
  299.         fwrite(&fntinfo[c].left, 4, 1, fntout);
  300.         fwrite(&fntinfo[c].bottom, 4, 1, fntout);
  301.  
  302.         fwrite(&fntinfo[c].right, 4, 1, fntout);
  303.         fwrite(&fntinfo[c].bottom, 4, 1, fntout);
  304.  
  305.         fwrite(&fntinfo[c].width, 4, 1, fntout);
  306.         fwrite(&fntinfo[c].height, 4, 1, fntout);
  307.  
  308.         fval = 0.0;
  309.         fwrite(&fval, 4, 1, fntout);
  310.  
  311.         fwrite(&fntinfo[c].kerning, 4, 1, fntout);
  312.         fwrite(&fntinfo[c].ascent, 4, 1, fntout);
  313.     }
  314.  
  315.     fclose(fntout);
  316.  
  317.  
  318.     DeleteObject(SelectObject(dc,origfont));
  319.     DeleteObject(SelectObject(dc,origbm));
  320.     DeleteDC(dc);
  321.     return 0;
  322. }
RAW Paste Data