/// <summary> /// Create a bitmap font from the specified dynamic font. /// </summary> static public bool CreateFont (Font ttf, int size, int faceIndex, bool kerning, string characters, int padding, out BMFont font, out Texture2D tex) { font = null; tex = null; if (ttf == null || !isPresent) return false; IntPtr lib = IntPtr.Zero; IntPtr face = IntPtr.Zero; if (FT_Init_FreeType(out lib) != 0) { Debug.LogError("Failed to initialize FreeType"); return false; } string fileName = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) + UnityEditor.AssetDatabase.GetAssetPath(ttf); if (!File.Exists(fileName)) { Debug.LogError("Unable to use the chosen font."); } else if (FT_New_Face(lib, fileName, faceIndex, out face) != 0) { Debug.LogError("Unable to use the chosen font (FT_New_Face)."); } else { font = new BMFont(); font.charSize = size; Color32 white = Color.white; List<int> entries = new List<int>(); List<Texture2D> textures = new List<Texture2D>(); FT_FaceRec faceRec = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec)); FT_Set_Pixel_Sizes(face, 0, (uint)size); // Calculate the baseline value that would let the printed font be centered vertically //int ascender = (faceRec.met.ascender >> 6); //int descender = (faceRec.descender >> 6); //int baseline = ((ascender - descender) >> 1); //if ((baseline & 1) == 1) --baseline; //Debug.Log(ascender + " " + descender + " " + baseline); // Space character is not renderable FT_Load_Glyph(face, FT_Get_Char_Index(face, 32), FT_LOAD_DEFAULT); FT_GlyphSlotRec space = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec)); // Space is not visible and doesn't have a texture BMGlyph spaceGlyph = font.GetGlyph(32, true); spaceGlyph.offsetX = 0; spaceGlyph.offsetY = 0; spaceGlyph.advance = (space.metrics.horiAdvance >> 6); spaceGlyph.channel = 15; spaceGlyph.x = 0; spaceGlyph.y = 0; spaceGlyph.width = 0; spaceGlyph.height = 0; // Save kerning information if (kerning) { for (int b = 0; b < characters.Length; ++b) { uint ch2 = characters[b]; if (ch2 == 32) continue; FT_Vector vec; if (FT_Get_Kerning(face, ch2, 32, 0, out vec) != 0) continue; int offset = (vec.x >> 6); if (offset != 0) spaceGlyph.SetKerning((int)ch2, offset); } } // Run through all requested characters foreach (char ch in characters) { uint charIndex = FT_Get_Char_Index(face, (uint)ch); FT_Load_Glyph(face, charIndex, FT_LOAD_DEFAULT); FT_GlyphSlotRec glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec)); FT_Render_Glyph(ref glyph, FT_Render_Mode.FT_RENDER_MODE_NORMAL); if (glyph.bitmap.width > 0 && glyph.bitmap.rows > 0) { byte[] buffer = new byte[glyph.bitmap.width * glyph.bitmap.rows]; Marshal.Copy(glyph.bitmap.buffer, buffer, 0, buffer.Length); Texture2D texture = new Texture2D(glyph.bitmap.width, glyph.bitmap.rows, UnityEngine.TextureFormat.ARGB32, false); Color32[] colors = new Color32[buffer.Length]; for (int i = 0, y = 0; y < glyph.bitmap.rows; ++y) { for (int x = 0; x < glyph.bitmap.width; ++x) { white.a = buffer[i++]; colors[x + glyph.bitmap.width * (glyph.bitmap.rows - y - 1)] = white; } } // Save the texture texture.SetPixels32(colors); texture.Apply(); textures.Add(texture); entries.Add(ch); // Record the metrics BMGlyph bmg = font.GetGlyph(ch, true); bmg.offsetX = (glyph.metrics.horiBearingX >> 6); bmg.offsetY = -(glyph.metrics.horiBearingY >> 6); bmg.advance = (glyph.metrics.horiAdvance >> 6); bmg.channel = 15; // Save kerning information if (kerning) { for (int b = 0; b < characters.Length; ++b) { uint ch2 = characters[b]; if (ch2 == ch) continue; FT_Vector vec; if (FT_Get_Kerning(face, ch2, ch, 0, out vec) != 0) continue; int offset = (vec.x >> 6); if (offset != 0) bmg.SetKerning((int)ch2, offset); } } } } // Create a packed texture with all the characters tex = new Texture2D(32, 32, TextureFormat.ARGB32, false); Rect[] rects = tex.PackTextures(textures.ToArray(), padding); // Make the RGB channel pure white Color32[] cols = tex.GetPixels32(); for (int i = 0, imax = cols.Length; i < imax; ++i) { Color32 c = cols[i]; c.r = 255; c.g = 255; c.b = 255; cols[i] = c; } tex.SetPixels32(cols); tex.Apply(); font.texWidth = tex.width; font.texHeight = tex.height; int min = int.MaxValue; int max = int.MinValue; // Other glyphs are visible and need to be added for (int i = 0, imax = entries.Count; i < imax; ++i) { // Destroy the texture now that it's a part of an atlas UnityEngine.Object.DestroyImmediate(textures[i]); textures[i] = null; Rect rect = rects[i]; // Set the texture coordinates BMGlyph glyph = font.GetGlyph(entries[i], true); glyph.x = Mathf.RoundToInt(rect.x * font.texWidth); glyph.y = Mathf.RoundToInt(rect.y * font.texHeight); glyph.width = Mathf.RoundToInt(rect.width * font.texWidth); glyph.height = Mathf.RoundToInt(rect.height * font.texHeight); // Flip the Y since the UV coordinate system is different glyph.y = font.texHeight - glyph.y - glyph.height; max = Mathf.Max(max, -glyph.offsetY); min = Mathf.Min(min, -glyph.offsetY - glyph.height); } int baseline = size + min; baseline += ((max - min - size) >> 1); // Offset all glyphs so that they are not using the baseline for (int i = 0, imax = entries.Count; i < imax; ++i) { BMGlyph glyph = font.GetGlyph(entries[i], true); glyph.offsetY += baseline; } } if (face != IntPtr.Zero) FT_Done_Face(face); #if !UNITY_3_5 if (lib != IntPtr.Zero) FT_Done_FreeType(lib); #endif return (tex != null); }
/// <summary> /// Reload the font data. /// </summary> public static void Load(BMFont font, string name, byte[] bytes) { font.Clear(); if (bytes != null) { int offset = 0; char[] separator = new char[1] { ' ' }; while (offset < bytes.Length) { string line = ReadLine(bytes, ref offset); if (string.IsNullOrEmpty(line)) break; string[] split = line.Split(separator, System.StringSplitOptions.RemoveEmptyEntries); if (split[0] == "char") { // Expected data style: // char id=13 x=506 y=62 width=3 height=3 xoffset=-1 yoffset=50 xadvance=0 page=0 chnl=15 if (split.Length > 8) { int id = GetInt(split[1]); BMGlyph glyph = font.GetGlyph(id, true); if (glyph != null) { glyph.x = GetInt(split[2]); glyph.y = GetInt(split[3]); glyph.width = GetInt(split[4]); glyph.height = GetInt(split[5]); glyph.offsetX = GetInt(split[6]); glyph.offsetY = GetInt(split[7]); glyph.advance = GetInt(split[8]); } else Debug.Log("Char: " + split[1] + " (" + id + ") is NULL"); } else { Debug.LogError("Unexpected number of entries for the 'char' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "kerning") { // Expected data style: // kerning first=84 second=244 amount=-5 if (split.Length > 3) { int first = GetInt(split[1]); int second = GetInt(split[2]); int amount = GetInt(split[3]); BMGlyph glyph = font.GetGlyph(second, true); if (glyph != null) glyph.SetKerning(first, amount); } else { Debug.LogError("Unexpected number of entries for the 'kerning' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "common") { // Expected data style: // common lineHeight=64 base=51 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=1 redChnl=4 greenChnl=4 blueChnl=4 if (split.Length > 5) { font.charSize = GetInt(split[1]); font.baseOffset = GetInt(split[2]); font.texWidth = GetInt(split[3]); font.texHeight = GetInt(split[4]); int pages = GetInt(split[5]); if (pages != 1) { Debug.LogError("Font '" + name + "' must be created with only 1 texture, not " + pages); break; } } else { Debug.LogError("Unexpected number of entries for the 'common' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "page") { // Expected data style: // page id=0 file="textureName.png" if (split.Length > 2) { font.spriteName = GetString(split[2]).Replace("\"", ""); } } } } }
/// <summary> /// Reload the font data. /// </summary> public static void Load(BMFont font, string name, byte[] bytes) { font.Clear(); if (bytes != null) { BmByteReader reader = new BmByteReader(bytes); char[] separator = new char[] { ' ' }; while (reader.canRead) { string line = reader.ReadLine(); if (string.IsNullOrEmpty(line)) break; string[] split = line.Split(separator, System.StringSplitOptions.RemoveEmptyEntries); int len = split.Length; if (split[0] == "char") { // Expected data style: // char id=13 x=506 y=62 width=3 height=3 xoffset=-1 yoffset=50 xadvance=0 page=0 chnl=15 int channel = (len > 10) ? GetInt(split[10]) : 15; if (len > 9 && GetInt(split[9]) > 0) { Debug.LogError("Your font was exported with more than one texture. Only one texture is supported by NGUI.\n" + "You need to re-export your font, enlarging the texture's dimensions until everything fits into just one texture."); break; } if (len > 8) { int id = GetInt(split[1]); BMGlyph glyph = font.GetGlyph(id, true); if (glyph != null) { glyph.x = GetInt(split[2]); glyph.y = GetInt(split[3]); glyph.width = GetInt(split[4]); glyph.height = GetInt(split[5]); glyph.offsetX = GetInt(split[6]); glyph.offsetY = GetInt(split[7]); glyph.advance = GetInt(split[8]); glyph.channel = channel; } else Debug.Log("Char: " + split[1] + " (" + id + ") is NULL"); } else { Debug.LogError("Unexpected number of entries for the 'char' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "kerning") { // Expected data style: // kerning first=84 second=244 amount=-5 if (len > 3) { int first = GetInt(split[1]); int second = GetInt(split[2]); int amount = GetInt(split[3]); BMGlyph glyph = font.GetGlyph(second, true); if (glyph != null) glyph.SetKerning(first, amount); } else { Debug.LogError("Unexpected number of entries for the 'kerning' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "common") { // Expected data style: // common lineHeight=64 base=51 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=1 redChnl=4 greenChnl=4 blueChnl=4 if (len > 5) { font.charSize = GetInt(split[1]); font.baseOffset = GetInt(split[2]); font.texWidth = GetInt(split[3]); font.texHeight = GetInt(split[4]); int pages = GetInt(split[5]); if (pages != 1) { Debug.LogError("Font '" + name + "' must be created with only 1 texture, not " + pages); break; } } else { Debug.LogError("Unexpected number of entries for the 'common' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "page") { // Expected data style: // page id=0 file="textureName.png" if (len > 2) { font.spriteName = GetString(split[2]).Replace("\"", ""); font.spriteName = font.spriteName.Replace(".png", ""); font.spriteName = font.spriteName.Replace(".tga", ""); } } } } }
/// <summary> /// Get the printed size of the specified string. The returned value is in local coordinates. Multiply by transform's scale to get pixels. /// </summary> public Vector2 CalculatePrintedSize(string text, bool encoding, SymbolStyle symbolStyle) { if (mReplacement != null) { return(mReplacement.CalculatePrintedSize(text, encoding, symbolStyle)); } Vector2 v = Vector2.zero; if (UseDynamicFont || (mFont != null && mFont.isValid && !string.IsNullOrEmpty(text))) { if (encoding) { text = NGUITools.StripSymbols(text); } if (UseDynamicFont) { dynamicFont.RequestCharactersInTexture(text, dynamicFontSize, dynamicFontStyle); } CharacterInfo charInfo; int length = text.Length; int maxX = 0; int x = 0; int y = 0; int prev = 0; int lineHeight = (charSize + mSpacingY); for (int i = 0; i < length; ++i) { char c = text[i]; // Start a new line if (c == '\n') { if (x > maxX) { maxX = x; } x = 0; y += lineHeight; prev = 0; continue; } // Skip invalid characters if (c < ' ') { prev = 0; continue; } if (UseDynamicFont) { if (dynamicFont.GetCharacterInfo(c, out charInfo, dynamicFontSize, dynamicFontStyle)) { x += (int)(mSpacingX + charInfo.width); } else { } } else { // See if there is a symbol matching this text BMSymbol symbol = (encoding && symbolStyle != SymbolStyle.None) ? mFont.MatchSymbol(text, i, length) : null; if (symbol == null) { // Get the glyph for this character BMGlyph glyph = mFont.GetGlyph(c); if (glyph != null) { x += mSpacingX + ((prev != 0) ? glyph.advance + glyph.GetKerning(prev) : glyph.advance); prev = c; } } else { // Symbol found -- use it x += mSpacingX + symbol.width; i += symbol.length - 1; prev = 0; } } } // Convert from pixel coordinates to local coordinates float scale = (charSize > 0) ? 1f / charSize : 1f; v.x = scale * ((x > maxX) ? x : maxX); v.y = scale * (y + lineHeight); } return(v); }
/// <summary> /// Reload the font data. /// </summary> public static void Load(BMFont font, string name, byte[] bytes) { font.Clear(); if (bytes != null) { ByteReader reader = new ByteReader(bytes); char[] separator = new char[] { ' ' }; while (reader.canRead) { string line = reader.ReadLine(); if (string.IsNullOrEmpty(line)) { break; } string[] split = line.Split(separator, System.StringSplitOptions.RemoveEmptyEntries); int len = split.Length; if (split[0] == "char") { // Expected data style: // char id=13 x=506 y=62 width=3 height=3 xoffset=-1 yoffset=50 xadvance=0 page=0 chnl=15 int channel = (len > 10) ? GetInt(split[10]) : 15; if (len > 9 && GetInt(split[9]) > 0) { Debug.LogError("Your font was exported with more than one texture. Only one texture is supported by NGUI.\n" + "You need to re-export your font, enlarging the texture's dimensions until everything fits into just one texture."); break; } if (len > 8) { int id = GetInt(split[1]); BMGlyph glyph = font.GetGlyph(id, true); if (glyph != null) { glyph.x = GetInt(split[2]); glyph.y = GetInt(split[3]); glyph.width = GetInt(split[4]); glyph.height = GetInt(split[5]); glyph.offsetX = GetInt(split[6]); glyph.offsetY = GetInt(split[7]); glyph.advance = GetInt(split[8]); glyph.channel = channel; } else { Debug.Log("Char: " + split[1] + " (" + id + ") is NULL"); } } else { Debug.LogError("Unexpected number of entries for the 'char' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "kerning") { // Expected data style: // kerning first=84 second=244 amount=-5 if (len > 3) { int first = GetInt(split[1]); int second = GetInt(split[2]); int amount = GetInt(split[3]); BMGlyph glyph = font.GetGlyph(second, true); if (glyph != null) { glyph.SetKerning(first, amount); } } else { Debug.LogError("Unexpected number of entries for the 'kerning' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "common") { // Expected data style: // common lineHeight=64 base=51 scaleW=512 scaleH=512 pages=1 packed=0 alphaChnl=1 redChnl=4 greenChnl=4 blueChnl=4 if (len > 5) { font.charSize = GetInt(split[1]); font.baseOffset = GetInt(split[2]); font.texWidth = GetInt(split[3]); font.texHeight = GetInt(split[4]); int pages = GetInt(split[5]); if (pages != 1) { Debug.LogError("Font '" + name + "' must be created with only 1 texture, not " + pages); break; } } else { Debug.LogError("Unexpected number of entries for the 'common' field (" + name + ", " + split.Length + "):\n" + line); break; } } else if (split[0] == "page") { // Expected data style: // page id=0 file="textureName.png" if (len > 2) { font.spriteName = GetString(split[2]).Replace("\"", ""); font.spriteName = font.spriteName.Replace(".png", ""); font.spriteName = font.spriteName.Replace(".tga", ""); } } } } }
/// <summary> /// Create a bitmap font from the specified dynamic font. /// </summary> static public bool CreateFont(Font ttf, int size, int faceIndex, bool kerning, string characters, out BMFont font, out Texture2D tex) { font = null; tex = null; if (ttf == null || !isPresent) { return(false); } IntPtr lib = IntPtr.Zero; IntPtr face = IntPtr.Zero; if (FT_Init_FreeType(out lib) != 0) { Debug.LogError("Failed to initialize FreeType"); return(false); } string fileName = Application.dataPath.Substring(0, Application.dataPath.Length - "Assets".Length) + UnityEditor.AssetDatabase.GetAssetPath(ttf); if (!File.Exists(fileName)) { Debug.LogError("Unable to use the chosen font."); } else if (FT_New_Face(lib, fileName, faceIndex, out face) != 0) { Debug.LogError("Unable to use the chosen font (FT_New_Face)."); } else { font = new BMFont(); font.charSize = size; Color32 white = Color.white; List <int> entries = new List <int>(); List <Texture2D> textures = new List <Texture2D>(); FT_FaceRec faceRec = (FT_FaceRec)Marshal.PtrToStructure(face, typeof(FT_FaceRec)); FT_Set_Pixel_Sizes(face, 0, (uint)size); // Calculate the baseline value that would let the printed font be centered vertically //int ascender = (faceRec.met.ascender >> 6); //int descender = (faceRec.descender >> 6); //int baseline = ((ascender - descender) >> 1); //if ((baseline & 1) == 1) --baseline; //Debug.Log(ascender + " " + descender + " " + baseline); // Space character is not renderable FT_Load_Glyph(face, FT_Get_Char_Index(face, 32), FT_LOAD_DEFAULT); FT_GlyphSlotRec space = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec)); // Space is not visible and doesn't have a texture BMGlyph spaceGlyph = font.GetGlyph(32, true); spaceGlyph.offsetX = 0; spaceGlyph.offsetY = 0; spaceGlyph.advance = (space.metrics.horiAdvance >> 6); spaceGlyph.channel = 15; spaceGlyph.x = 0; spaceGlyph.y = 0; spaceGlyph.width = 0; spaceGlyph.height = 0; // Save kerning information if (kerning) { for (int b = 0; b < characters.Length; ++b) { uint ch2 = characters[b]; if (ch2 == 32) { continue; } FT_Vector vec; if (FT_Get_Kerning(face, ch2, 32, 0, out vec) != 0) { continue; } int offset = (vec.x >> 6); if (offset != 0) { spaceGlyph.SetKerning((int)ch2, offset); } } } // Run through all requested characters foreach (char ch in characters) { uint charIndex = FT_Get_Char_Index(face, (uint)ch); FT_Load_Glyph(face, charIndex, FT_LOAD_DEFAULT); FT_GlyphSlotRec glyph = (FT_GlyphSlotRec)Marshal.PtrToStructure(faceRec.glyph, typeof(FT_GlyphSlotRec)); FT_Render_Glyph(ref glyph, FT_Render_Mode.FT_RENDER_MODE_NORMAL); if (glyph.bitmap.width > 0 && glyph.bitmap.rows > 0) { byte[] buffer = new byte[glyph.bitmap.width * glyph.bitmap.rows]; Marshal.Copy(glyph.bitmap.buffer, buffer, 0, buffer.Length); Texture2D texture = new Texture2D(glyph.bitmap.width, glyph.bitmap.rows, UnityEngine.TextureFormat.ARGB32, false); Color32[] colors = new Color32[buffer.Length]; for (int i = 0, y = 0; y < glyph.bitmap.rows; ++y) { for (int x = 0; x < glyph.bitmap.width; ++x) { white.a = buffer[i++]; colors[x + glyph.bitmap.width * (glyph.bitmap.rows - y - 1)] = white; } } // Save the texture texture.SetPixels32(colors); texture.Apply(); textures.Add(texture); entries.Add(ch); // Record the metrics BMGlyph bmg = font.GetGlyph(ch, true); bmg.offsetX = (glyph.metrics.horiBearingX >> 6); bmg.offsetY = -(glyph.metrics.horiBearingY >> 6); bmg.advance = (glyph.metrics.horiAdvance >> 6); bmg.channel = 15; // Save kerning information if (kerning) { for (int b = 0; b < characters.Length; ++b) { uint ch2 = characters[b]; if (ch2 == ch) { continue; } FT_Vector vec; if (FT_Get_Kerning(face, ch2, ch, 0, out vec) != 0) { continue; } int offset = (vec.x >> 6); if (offset != 0) { bmg.SetKerning((int)ch2, offset); } } } } } // Create a packed texture with all the characters tex = new Texture2D(32, 32, TextureFormat.ARGB32, false); Rect[] rects = tex.PackTextures(textures.ToArray(), 1); // Make the RGB channel pure white Color32[] cols = tex.GetPixels32(); for (int i = 0, imax = cols.Length; i < imax; ++i) { Color32 c = cols[i]; c.r = 255; c.g = 255; c.b = 255; cols[i] = c; } tex.SetPixels32(cols); tex.Apply(); font.texWidth = tex.width; font.texHeight = tex.height; int min = int.MaxValue; int max = int.MinValue; // Other glyphs are visible and need to be added for (int i = 0, imax = entries.Count; i < imax; ++i) { // Destroy the texture now that it's a part of an atlas UnityEngine.Object.DestroyImmediate(textures[i]); textures[i] = null; Rect rect = rects[i]; // Set the texture coordinates BMGlyph glyph = font.GetGlyph(entries[i], true); glyph.x = Mathf.RoundToInt(rect.x * font.texWidth); glyph.y = Mathf.RoundToInt(rect.y * font.texHeight); glyph.width = Mathf.RoundToInt(rect.width * font.texWidth); glyph.height = Mathf.RoundToInt(rect.height * font.texHeight); // Flip the Y since the UV coordinate system is different glyph.y = font.texHeight - glyph.y - glyph.height; max = Mathf.Max(max, -glyph.offsetY); min = Mathf.Min(min, -glyph.offsetY - glyph.height); } int baseline = size + min; baseline += ((max - min - size) >> 1); // Offset all glyphs so that they are not using the baseline for (int i = 0, imax = entries.Count; i < imax; ++i) { BMGlyph glyph = font.GetGlyph(entries[i], true); glyph.offsetY += baseline; } } if (face != IntPtr.Zero) { FT_Done_Face(face); } #if !UNITY_3_5 if (lib != IntPtr.Zero) { FT_Done_FreeType(lib); } #endif return(tex != null); }
/// <summary> /// Get the printed size of the specified string. The returned value is in pixels. /// </summary> ///change by chenzhiwei return value v.z is line count public Vector3 CalculatePrintedSize(string text, int size, bool encoding, SymbolStyle symbolStyle) { if (mReplacement != null) { return(mReplacement.CalculatePrintedSize(text, size, encoding, symbolStyle)); } #if DYNAMIC_FONT if (isDynamic) { return(NGUIText.CalculatePrintedSize(text, mDynamicFont, size, mDynamicFontStyle, encoding)); } #endif Vector3 v = Vector3.zero; if (mFont != null && mFont.isValid && !string.IsNullOrEmpty(text)) { if (encoding) { text = NGUIText.StripSymbols(text); } int length = text.Length; int maxX = 0; int x = 0; int y = 0; int prev = 0; int fs = size; int lineHeight = (fs + mSpacingY); bool useSymbols = encoding && symbolStyle != SymbolStyle.None && hasSymbols; for (int i = 0; i < length; ++i) { char c = text[i]; // Start a new line if (c == '\n') { if (x > maxX) { maxX = x; } x = 0; y += lineHeight; v.z++; prev = 0; continue; } // Skip invalid characters if (c < ' ') { prev = 0; continue; } // See if there is a symbol matching this text BMSymbol symbol = useSymbols ? MatchSymbol(text, i, length) : null; if (symbol == null) { // Get the glyph for this character BMGlyph glyph = mFont.GetGlyph(c); if (glyph != null) { x += mSpacingX + ((prev != 0) ? glyph.advance + glyph.GetKerning(prev) : glyph.advance); prev = c; } } else { // Symbol found -- use it x += mSpacingX + symbol.width; i += symbol.length - 1; prev = 0; } } // Convert from pixel coordinates to local coordinates v.x = ((x > maxX) ? x : maxX); v.y = (y + lineHeight); v.z++; } return(v); }
/// <summary> /// Get the printed size of the specified string. The returned value is in pixels. /// </summary> public Vector2 CalculatePrintedSize(string text) { if (mReplacement != null) { return(mReplacement.CalculatePrintedSize(text)); } #if DYNAMIC_FONT if (isDynamic) { NGUIText.current.size = mDynamicFontSize; NGUIText.current.style = mDynamicFontStyle; return(NGUIText.CalculatePrintedSize(mDynamicFont, text)); } #endif Vector2 v = Vector2.zero; if (mFont != null && mFont.isValid && !string.IsNullOrEmpty(text)) { if (NGUIText.current.encoding) { text = NGUIText.StripSymbols(text); } int x = 0; int y = 0; int prev = 0; int maxX = 0; int length = text.Length; int lineHeight = NGUIText.current.size + NGUIText.current.spacingY; bool useSymbols = NGUIText.current.encoding && NGUIText.current.symbolStyle != NGUIText.SymbolStyle.None && hasSymbols; for (int i = 0; i < length; ++i) { char c = text[i]; // Start a new line if (c == '\n') { if (x > maxX) { maxX = x; } x = 0; y += lineHeight; prev = 0; continue; } // Skip invalid characters if (c < ' ') { prev = 0; continue; } // See if there is a symbol matching this text BMSymbol symbol = useSymbols ? MatchSymbol(text, i, length) : null; if (symbol == null) { // Get the glyph for this character BMGlyph glyph = mFont.GetGlyph(c); if (glyph != null) { x += NGUIText.current.spacingX + ((prev != 0) ? glyph.advance + glyph.GetKerning(prev) : glyph.advance); prev = c; } } else { // Symbol found -- use it x += NGUIText.current.spacingX + symbol.width; i += symbol.length - 1; prev = 0; } } // Padding is always between characters, so it's one less than the number of characters v.x = ((x > maxX) ? x : maxX); v.y = (y + NGUIText.current.size); } return(v); }
/// <summary> /// Get the printed size of the specified string. The returned value is in local coordinates. Multiply by transform's scale to get pixels. /// </summary> public Vector2 CalculatePrintedSize(string text, bool encoding, SymbolStyle symbolStyle) { if (mReplacement != null) { return(mReplacement.CalculatePrintedSize(text, encoding, symbolStyle)); } Vector2 v = Vector2.zero; bool dynamic = isDynamic; #if DYNAMIC_FONT if (dynamic || (mFont != null && mFont.isValid && !string.IsNullOrEmpty(text))) #else if (mFont != null && mFont.isValid && !string.IsNullOrEmpty(text)) #endif { if (encoding) { text = NGUITools.StripSymbols(text); } #if DYNAMIC_FONT if (dynamic) { mDynamicFont.textureRebuildCallback = OnFontChanged; mDynamicFont.RequestCharactersInTexture(text, mDynamicFontSize, mDynamicFontStyle); mDynamicFont.textureRebuildCallback = null; } #endif int length = text.Length; int maxX = 0; int x = 0; int y = 0; int prev = 0; int fs = size; int lineHeight = (fs + mSpacingY); bool useSymbols = encoding && symbolStyle != SymbolStyle.None && hasSymbols; for (int i = 0; i < length; ++i) { char c = text[i]; // Start a new line if (c == '\n') { if (x > maxX) { maxX = x; } x = 0; y += lineHeight; prev = 0; continue; } // Skip invalid characters if (c < ' ') { prev = 0; continue; } if (!dynamic) { // See if there is a symbol matching this text BMSymbol symbol = useSymbols ? MatchSymbol(text, i, length) : null; if (symbol == null) { // Get the glyph for this character BMGlyph glyph = mFont.GetGlyph(c); if (glyph != null) { x += mSpacingX + ((prev != 0) ? glyph.advance + glyph.GetKerning(prev) : glyph.advance); prev = c; } } else { // Symbol found -- use it x += mSpacingX + symbol.width; i += symbol.length - 1; prev = 0; } } #if DYNAMIC_FONT else { if (mDynamicFont.GetCharacterInfo(c, out mChar, mDynamicFontSize, mDynamicFontStyle)) { x += (int)(mSpacingX + mChar.width); } } #endif } // Convert from pixel coordinates to local coordinates float scale = (fs > 0) ? 1f / fs : 1f; v.x = scale * ((x > maxX) ? x : maxX); v.y = scale * (y + lineHeight); } return(v); }
public Vector2 CalculatePrintedSize(string text, bool encoding, SymbolStyle symbolStyle) { if (mReplacement != null) { return(mReplacement.CalculatePrintedSize(text, encoding, symbolStyle)); } Vector2 zero = Vector2.zero; bool isDynamic = this.isDynamic; if (isDynamic || (mFont != null && mFont.isValid && !string.IsNullOrEmpty(text))) { if (encoding) { text = NGUITools.StripSymbols(text); } if (isDynamic) { Font.textureRebuilt += OnFontChanged; // mDynamicFont.textureRebuildCallback = OnFontChanged; mDynamicFont.RequestCharactersInTexture(text, mDynamicFontSize, mDynamicFontStyle); // mDynamicFont.textureRebuildCallback = null; Font.textureRebuilt -= OnFontChanged; } int length = text.Length; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; int size = this.size; int num5 = size + mSpacingY; bool flag = encoding && symbolStyle != 0 && hasSymbols; for (int i = 0; i < length; i++) { char c = text[i]; if (c == '\n') { if (num2 > num) { num = num2; } num2 = 0; num3 += num5; num4 = 0; } else if (c < ' ') { num4 = 0; } else if (!isDynamic) { BMSymbol bMSymbol = (!flag) ? null : MatchSymbol(text, i, length); if (bMSymbol == null) { BMGlyph glyph = mFont.GetGlyph(c); if (glyph != null) { num2 += mSpacingX + ((num4 == 0) ? glyph.advance : (glyph.advance + glyph.GetKerning(num4))); num4 = c; } } else { num2 += mSpacingX + bMSymbol.width; i += bMSymbol.length - 1; num4 = 0; } } else if (mDynamicFont.GetCharacterInfo(c, out mChar, mDynamicFontSize, mDynamicFontStyle)) { num2 += (int)((float)mSpacingX + mChar.width); } } float num6 = (size <= 0) ? 1f : (1f / (float)size); zero.x = num6 * (float)((num2 <= num) ? num : num2); zero.y = num6 * (float)(num3 + num5); } return(zero); }