void ReleaseFontAtlas() { if (m_BitmapChars != null) { foreach (ANTBitmapChar ch in m_BitmapChars) { ch.Dispose(); } m_BitmapChars.Clear(); m_BitmapChars = null; foreach (ANTBitmapFont font in m_BitmapFonts) { font.Dispose(); } m_BitmapFonts.Clear(); m_BitmapFonts = null; if (m_pShowAtlas != null) { m_pShowAtlas.Dispose(); m_pShowAtlas = null; } ReleaseTexture(); ReleaseLibrary(); } }
void CreateBranches(ANTBitmapChar pFTBitmapChar) { int dx = m_width - pFTBitmapChar.GetWidth(); int dy = m_height - pFTBitmapChar.GetHeight(); // we split to give one very small leaf and one very big one // because it allows more efficent use of space // if you don't do this, the bottom right corner never gets used if (dx < dy) { // split so the top is cut in half and the rest is one big rect below m_Leaf1 = new TreeNode(); m_Leaf1.Set(m_x + pFTBitmapChar.GetWidth(), m_y, m_width - pFTBitmapChar.GetWidth(), pFTBitmapChar.GetHeight()); m_Leaf2 = new TreeNode(); m_Leaf2.Set(m_x, m_y + pFTBitmapChar.GetHeight(), m_width, m_height - pFTBitmapChar.GetHeight()); } else { // m_Leaf1 = left (cut in half) m_Leaf1 = new TreeNode(); m_Leaf1.Set(m_x, m_y + pFTBitmapChar.GetHeight(), pFTBitmapChar.GetWidth(), m_height - pFTBitmapChar.GetHeight()); // m_Leaf2 = right (not cut) m_Leaf2 = new TreeNode(); m_Leaf2.Set(m_x + pFTBitmapChar.GetWidth(), m_y, m_width - pFTBitmapChar.GetWidth(), m_height); } }
public bool Add(ANTBitmapChar pFTBitmapChar) { if (pFTBitmapChar.IsEmpty()) { return(true); } if (IsEmpty()) { if (Fits(pFTBitmapChar)) { CreateBranches(pFTBitmapChar); pFTBitmapChar.SetXY(m_x, m_y); return(true); } return(false); } if (m_Leaf1.Add(pFTBitmapChar)) { return(true); } if (m_Leaf2.Add(pFTBitmapChar)) { return(true); } return(false); }
public void CreateAtlas() { int totalPixels = 0; foreach (ANTBitmapChar ch in m_BitmapChars) { totalPixels += ch.GetNumPixels(); } int ixSize = 0; int texWidth = 32; int texHeight = 32; while (true) { if (totalPixels <= texWidth * texHeight) { break; } GetNextTextureSize(ref texWidth, ref texHeight, ixSize); ixSize++; } m_BitmapChars.Sort(new GreaterSizeComparer()); while (!BinPack(texWidth, texHeight)) { GetNextTextureSize(ref texWidth, ref texHeight, ixSize); ixSize++; } byte[] pData = new byte[texWidth * texHeight]; Array.Clear(pData, 0, pData.Length); foreach (ANTBitmapChar ch in m_BitmapChars) { ch.DrawToBitmap(pData, texWidth, texHeight); ch.ReleaseGlyph(); } foreach (ANTBitmapFont font in m_BitmapFonts) { font.FinishCreating(); } if (!m_UseKerning) { ReleaseLibrary(); } m_Texture = pData; m_Bitmap = ToBitmap(m_Texture, texWidth, texHeight); m_pShowAtlas = new ANTBitmapChar(); m_pShowAtlas.SetXY(0, 0); m_pShowAtlas.SetSize(texWidth, texHeight); }
public void AddFont(string strFileName, int size, string szLetters) { if (string.IsNullOrEmpty(strFileName) || !Alt.IO.VirtualFile.Exists(strFileName)) { return; } if (m_Library == null) { if (ANT.ANT_Init_AltNETType(out m_Library) != ANT_Error.ANT_Err_Ok) { throw new Exception("ANT_Init_FreeType failed"); } } // The Object In Which FreeType Holds Information On A Given // Font Is Called A "face". ANT_Face face; string file = strFileName; // This Is Where We Load In The Font Information From The File. if (ANT.ANT_New_Face(m_Library, file, 0, out face) != ANT_Error.ANT_Err_Ok) { throw new Exception("no font: " + file); } // FreeType Measures Font Size In Terms Of 1/64ths Of Pixels. ANT.ANT_Set_Char_Size(face, size * 64, size * 64, 72, 72); int len = szLetters.Length; int n; ANTBitmapChar pFTBitmapChar; ANT_Glyph pGlyph; ANTBitmapFont pANTBitmapFont = new ANTBitmapFont(this); pANTBitmapFont.LineHeight = face.size.metrics.height >> 6; pANTBitmapFont.SetFTFace(face); m_BitmapFonts.Add(pANTBitmapFont); char c; int height; int yOffset; int ixGlyph; for (n = 0; n < len; n++) { c = szLetters[n]; // check that the character hasn't already been processed if (pANTBitmapFont.GetChar(c) == null) { // Load The Glyph For Our Character. ixGlyph = ANT.ANT_Get_Char_Index(face, c); if (ixGlyph == 0) { Console.WriteLine("character doesn't exist in font: '" + c + "'"); } else { if (ANT.ANT_Load_Glyph(face, ixGlyph, ANT_LOAD.ANT_LOAD_DEFAULT) != ANT_Error.ANT_Err_Ok) { throw new Exception("ANT_Load_Glyph failed"); } // Move The Face's Glyph Into A Glyph Object. if (ANT.ANT_Get_Glyph(face.glyph, out pGlyph) != ANT_Error.ANT_Err_Ok) { throw new Exception("ANT_Get_Glyph failed"); } pFTBitmapChar = new ANTBitmapChar(c); // all metrics dimensions are multiplied by 64, so we have to divide by 64 height = face.glyph.metrics.height >> 6; yOffset = pANTBitmapFont.LineHeight - (face.glyph.metrics.horiBearingY >> 6); pFTBitmapChar.SetOffsets(face.glyph.metrics.horiBearingX >> 6, yOffset); pFTBitmapChar.SetSize(face.glyph.metrics.width >> 6, height); pFTBitmapChar.SetXAdvance(face.glyph.metrics.horiAdvance >> 6); pFTBitmapChar.SetGlyph(pGlyph); m_BitmapChars.Add(pFTBitmapChar); pANTBitmapFont.AddChar(c, pFTBitmapChar); } } } }
public void AddChar(int charCode, ANTBitmapChar pFTBitmapChar) { m_mapBitmapChar[charCode] = pFTBitmapChar; }
bool Fits(ANTBitmapChar pFTBitmapChar) { return(pFTBitmapChar.GetWidth() <= m_width && pFTBitmapChar.GetHeight() <= m_height); }