private CCBMFontConfiguration InitializeFont(string fontName, float fontSize, string charset) { if (Director == null) return null; if (m_pData == null) { InitializeTTFAtlas(1024, 1024); } if (String.IsNullOrEmpty(charset)) { charset = " "; } var chars = new CCRawList<char>(); var fontKey = GetFontKey(fontName, fontSize); CCBMFontConfiguration fontConfig; if (!fontConfigurations.TryGetValue(fontKey, out fontConfig)) { fontConfig = new CCBMFontConfiguration(); fontConfigurations.Add(fontKey, fontConfig); } for (int i = 0; i < charset.Length; i++) { var ch = charset[i]; if (!fontConfig.Glyphs.ContainsKey(ch) && chars.IndexOf(ch) == -1) { chars.Add(ch); } } if (chars.Count == 0) { return fontConfig; } CreateFont(fontName, fontSize, chars); fontConfig.CommonHeight = (int)Math.Ceiling(GetFontHeight()); int[] data = null; for (int i = 0; i < chars.Count; i++) { var s = chars[i].ToString(); var charSize = GetMeasureString(s); int w = (int)Math.Ceiling(charSize.Width + 2); int h = (int)Math.Ceiling(charSize.Height + 2); if (data == null || data.Length < (w * h)) { data = new int[w * h]; } unsafe { int stride; byte* pBase = GetBitmapData(s, out stride); int minX = w; int maxX = 0; int minY = h; int maxY = 0; for (int y = 0; y < h; y++) { var row = (int*)(pBase + y * stride); for (int x = 0; x < w; x++) { if (row[x] != 0) { minX = Math.Min(minX, x); maxX = Math.Max(maxX, x); minY = Math.Min(minY, y); maxY = Math.Max(maxY, y); } } } w = Math.Max(maxX - minX + 1, 1); h = Math.Max(maxY - minY + 1, 1); //maxX = minX + w; //maxY = minY + h; int index = 0; for (int y = minY; y <= maxY; y++) { var row = (int*)(pBase + y * stride); for (int x = minX; x <= maxX; x++) { data[index] = row[x]; index++; } } var region = AllocateRegion(w, h); if (region.x >= 0) { SetRegionData(region, data, w); var info = GetKerningInfo(chars[i]); var fontDef = new CCBMFontConfiguration.CCBMGlyphDef() { Character = chars[i], Subrect = new CCRect(region.x, region.y, region.width, region.height), XOffset = minX, // + (int)Math.Ceiling(info.A), YOffset = minY, XAdvance = (int)Math.Ceiling(info.A + info.B + info.C) }; fontConfig.CharacterSet.Add(chars[i]); fontConfig.Glyphs.Add(chars[i], fontDef); } else { CCLog.Log("Texture atlas is full"); } } } m_bTextureDirty = true; return fontConfig; }
public void CreateFontChars() { int nextFontPositionX = 0; int nextFontPositionY = 0; char prev = (char)255; int kerningAmount = 0; CCSize tmpSize = CCSize.Zero; int longestLine = 0; int totalHeight = 0; int quantityOfLines = 1; if (String.IsNullOrEmpty(labelText)) { return; } int stringLen = labelText.Length; var charSet = FontConfiguration.CharacterSet; if (charSet.Count == 0) { throw (new InvalidOperationException( "Can not compute the size of the font because the character set is empty.")); } for (int i = 0; i < stringLen - 1; ++i) { if (labelText[i] == '\n') { quantityOfLines++; } } LineHeight = FontConfiguration.CommonHeight; totalHeight = LineHeight * quantityOfLines; nextFontPositionY = 0 - (LineHeight - LineHeight * quantityOfLines); CCBMFontConfiguration.CCBMGlyphDef fontDef = null; CCRect fontCharTextureRect; CCSize fontCharContentSize; for (int i = 0; i < stringLen; i++) { char c = labelText[i]; if (c == '\n') { nextFontPositionX = 0; nextFontPositionY -= LineHeight; continue; } if (charSet.IndexOf(c) == -1) { CCLog.Log("CocosSharp: CCLabelBMFont: Attempted to use character not defined in this bitmap: {0}", (int)c); continue; } kerningAmount = this.KerningAmountForFirst(prev, c); // unichar is a short, and an int is needed on HASH_FIND_INT if (!FontConfiguration.Glyphs.TryGetValue(c, out fontDef)) { CCLog.Log("CocosSharp: CCLabelBMFont: characer not found {0}", (int)c); continue; } fontCharTextureRect = fontDef.Subrect; fontCharTextureRect.Origin.X += ImageOffset.X; fontCharTextureRect.Origin.Y += ImageOffset.Y; fontCharContentSize = fontCharTextureRect.Size / DefaultTexelToContentSizeRatios; CCSprite fontChar; //bool hasSprite = true; fontChar = (CCSprite)(this[i]); if (fontChar != null) { // Reusing previous Sprite fontChar.Visible = true; // updating previous sprite fontChar.IsTextureRectRotated = false; fontChar.ContentSize = fontCharContentSize; fontChar.TextureRectInPixels = fontCharTextureRect; } else { // New Sprite ? Set correct color, opacity, etc... //if( false ) //{ // /* WIP: Doesn't support many features yet. // But this code is super fast. It doesn't create any sprite. // Ideal for big labels. // */ // fontChar = m_pReusedChar; // fontChar.BatchNode = null; // hasSprite = false; //} //else { fontChar = new CCSprite(TextureAtlas.Texture, fontCharTextureRect); fontChar.ContentSize = fontCharContentSize; AddChild(fontChar, i, i); } // Apply label properties fontChar.IsColorModifiedByOpacity = IsColorModifiedByOpacity; // Color MUST be set before opacity, since opacity might change color if OpacityModifyRGB is on fontChar.UpdateDisplayedColor(DisplayedColor); fontChar.UpdateDisplayedOpacity(DisplayedOpacity); } // See issue 1343. cast( signed short + unsigned integer ) == unsigned integer (sign is lost!) int yOffset = FontConfiguration.CommonHeight - fontDef.YOffset; var fontPos = new CCPoint( (float)nextFontPositionX + fontDef.XOffset + fontDef.Subrect.Size.Width * 0.5f + kerningAmount, (float)nextFontPositionY + yOffset - fontCharTextureRect.Size.Height * 0.5f); fontChar.Position = fontPos; // update kerning nextFontPositionX += fontDef.XAdvance + kerningAmount; prev = c; if (longestLine < nextFontPositionX) { longestLine = nextFontPositionX; } } // If the last character processed has an xAdvance which is less that the width of the characters image, then we need // to adjust the width of the string to take this into account, or the character will overlap the end of the bounding // box if (fontDef.XAdvance < fontDef.Subrect.Size.Width) { tmpSize.Width = longestLine + fontDef.Subrect.Size.Width - fontDef.XAdvance; } else { tmpSize.Width = longestLine; } tmpSize.Height = totalHeight; var tmpDimensions = labelDimensions; labelDimensions = new CCSize( labelDimensions.Width > 0 ? labelDimensions.Width : tmpSize.Width, labelDimensions.Height > 0 ? labelDimensions.Height : tmpSize.Height ); ContentSize = labelDimensions; labelDimensions = tmpDimensions; }
private CCBMFontConfiguration InitializeFont(string fontName, float fontSize, string charset) { if (m_pData == null) { InitializeTTFAtlas(1024, 1024); } if (String.IsNullOrEmpty(charset)) { charset = " "; } var chars = new CCRawList <char>(); var fontKey = GetFontKey(fontName, fontSize); CCBMFontConfiguration fontConfig; if (!fontConfigurations.TryGetValue(fontKey, out fontConfig)) { fontConfig = new CCBMFontConfiguration(); fontConfigurations.Add(fontKey, fontConfig); } for (int i = 0; i < charset.Length; i++) { var ch = charset[i]; if (!fontConfig.Glyphs.ContainsKey(ch) && chars.IndexOf(ch) == -1) { chars.Add(ch); } } if (chars.Count == 0) { return(fontConfig); } CreateFont(fontName, fontSize, chars); fontConfig.CommonHeight = (int)Math.Ceiling(GetFontHeight()); int[] data = null; for (int i = 0; i < chars.Count; i++) { var s = chars[i].ToString(); var charSize = GetMeasureString(s); int w = (int)Math.Ceiling(charSize.Width + 2); int h = (int)Math.Ceiling(charSize.Height + 2); if (data == null || data.Length < (w * h)) { data = new int[w * h]; } unsafe { int stride; byte *pBase = GetBitmapData(s, out stride); int minX = w; int maxX = 0; int minY = h; int maxY = 0; for (int y = 0; y < h; y++) { var row = (int *)(pBase + y * stride); for (int x = 0; x < w; x++) { if (row[x] != 0) { minX = Math.Min(minX, x); maxX = Math.Max(maxX, x); minY = Math.Min(minY, y); maxY = Math.Max(maxY, y); } } } w = Math.Max(maxX - minX + 1, 1); h = Math.Max(maxY - minY + 1, 1); //maxX = minX + w; //maxY = minY + h; int index = 0; for (int y = minY; y <= maxY; y++) { var row = (int *)(pBase + y * stride); for (int x = minX; x <= maxX; x++) { data[index] = row[x]; index++; } } var region = AllocateRegion(w, h); if (region.x >= 0) { SetRegionData(region, data, w); var info = GetKerningInfo(chars[i]); var fontDef = new CCBMFontConfiguration.CCBMGlyphDef() { Character = chars[i], Subrect = new CCRect(region.x, region.y, region.width, region.height), XOffset = minX, // + (int)Math.Ceiling(info.A), YOffset = minY, XAdvance = (int)Math.Ceiling(info.A + info.B + info.C) }; fontConfig.CharacterSet.Add(chars[i]); fontConfig.Glyphs.Add(chars[i], fontDef); } else { CCLog.Log("Texture atlas is full"); } } } isTextureDirty = true; return(fontConfig); }