public Rectangle GetCharacterRect(char c, int lineNumber, ref Point point, out Rectangle destinationRectangle, out int pageIndex, float fontScale = 1) { BitmapCharacterInfo characterInfo = GetCharacterInfo(c); int sourceLeft = characterInfo.GetPixelLeft(Texture); int sourceTop = characterInfo.GetPixelTop(Texture); int sourceWidth = characterInfo.GetPixelRight(Texture) - sourceLeft; int sourceHeight = characterInfo.GetPixelBottom(Texture) - sourceTop; int distanceFromTop = characterInfo.GetPixelDistanceFromTop(LineHeightInPixels); // There could be some offset for this character int xOffset = characterInfo.GetPixelXOffset(LineHeightInPixels); point.X += (int)(xOffset * fontScale); point.Y = (int)((lineNumber * LineHeightInPixels + distanceFromTop) * fontScale); var sourceRectangle = new Microsoft.Xna.Framework.Rectangle( sourceLeft, sourceTop, sourceWidth, sourceHeight); pageIndex = characterInfo.PageNumber; destinationRectangle = new Rectangle(point.X, point.Y, (int)(sourceWidth * fontScale), (int)(sourceHeight * fontScale)); point.X -= (int)(xOffset * fontScale); point.X += (int)(characterInfo.GetXAdvanceInPixels(LineHeightInPixels) * fontScale); return(sourceRectangle); }
public int MeasureString(string line) { int toReturn = 0; for (int i = 0; i < line.Length; i++) { char character = line[i]; BitmapCharacterInfo characterInfo = GetCharacterInfo(character); if (characterInfo != null) { bool isLast = i == line.Length - 1; if (isLast) { toReturn += characterInfo.GetPixelWidth(Texture) + characterInfo.GetPixelXOffset(LineHeightInPixels); } else { toReturn += characterInfo.GetXAdvanceInPixels(LineHeightInPixels); } } } return(toReturn); }
public float DistanceFromTopOfLine(int asciiNumber) { BitmapCharacterInfo characterInfo = null; if (asciiNumber < mCharacterInfo.Length) { characterInfo = mCharacterInfo[asciiNumber]; } else { characterInfo = mCharacterInfo[' ']; } return(characterInfo.DistanceFromTopOfLine); }
private BitmapCharacterInfo FillBitmapCharacterInfo(int characterID, string fontString, int textureWidth, int textureHeight, int lineHeightInPixels, int startingIndex) { BitmapCharacterInfo characterInfoToReturn = new BitmapCharacterInfo(); int indexOfID = fontString.IndexOf("char id=" + characterID, startingIndex); if (indexOfID != -1) { characterInfoToReturn.TULeft = StringFunctions.GetIntAfter("x=", fontString, indexOfID) / (float)textureWidth; characterInfoToReturn.TVTop = StringFunctions.GetIntAfter("y=", fontString, indexOfID) / (float)textureHeight; characterInfoToReturn.TURight = characterInfoToReturn.TULeft + StringFunctions.GetIntAfter("width=", fontString, indexOfID) / (float)textureWidth; characterInfoToReturn.TVBottom = characterInfoToReturn.TVTop + StringFunctions.GetIntAfter("height=", fontString, indexOfID) / (float)textureHeight; characterInfoToReturn.DistanceFromTopOfLine = // 1 sclY means 2 height 2 * StringFunctions.GetIntAfter("yoffset=", fontString, indexOfID) / (float)lineHeightInPixels; characterInfoToReturn.ScaleX = StringFunctions.GetIntAfter("width=", fontString, indexOfID) / (float)lineHeightInPixels; characterInfoToReturn.ScaleY = StringFunctions.GetIntAfter("height=", fontString, indexOfID) / (float)lineHeightInPixels; characterInfoToReturn.Spacing = 2 * StringFunctions.GetIntAfter("xadvance=", fontString, indexOfID) / (float)lineHeightInPixels; characterInfoToReturn.XOffset = 2 * StringFunctions.GetIntAfter("xoffset=", fontString, indexOfID) / (float)lineHeightInPixels; characterInfoToReturn.PageNumber = StringFunctions.GetIntAfter("page=", fontString, indexOfID); // characterInfoToReturn.Spacing = 25 * StringFunctions.GetIntAfter("xadvance=", fontString, indexOfID) / // (float)(textureWidth); } return(characterInfoToReturn); }
public void AssignCharacterTextureCoordinates(int asciiNumber, out float tVTop, out float tVBottom, out float tULeft, out float tURight) { BitmapCharacterInfo characterInfo = null; if (asciiNumber < mCharacterInfo.Length) { characterInfo = mCharacterInfo[asciiNumber]; } else { // Just return the coordinates for the space character characterInfo = mCharacterInfo[' ']; } tVTop = characterInfo.TVTop; tVBottom = characterInfo.TVBottom; tULeft = characterInfo.TULeft; tURight = characterInfo.TURight; }
private Texture2D RenderToTexture2DUsingImageData(IEnumerable lines, HorizontalAlignment horizontalAlignment, SystemManagers managers) { ImageData[] imageDatas = new ImageData[this.mTextures.Length]; for (int i = 0; i < imageDatas.Length; i++) { // Only use the existing buffer on one-page fonts var bufferToUse = mColorBuffer; if (i > 0) { bufferToUse = null; } imageDatas[i] = ImageData.FromTexture2D(this.mTextures[i], managers, bufferToUse); } Point point = new Point(); int maxWidthSoFar = 0; int requiredWidth = 0; int requiredHeight = 0; List <int> widths = new List <int>(); foreach (string line in lines) { requiredHeight += LineHeightInPixels; requiredWidth = 0; requiredWidth = MeasureString(line); widths.Add(requiredWidth); maxWidthSoFar = System.Math.Max(requiredWidth, maxWidthSoFar); } const int MaxWidthAndHeight = 2048; // change this later? maxWidthSoFar = System.Math.Min(maxWidthSoFar, MaxWidthAndHeight); requiredHeight = System.Math.Min(requiredHeight, MaxWidthAndHeight); ImageData imageData = null; if (maxWidthSoFar != 0) { imageData = new ImageData(maxWidthSoFar, requiredHeight, managers); int lineNumber = 0; foreach (string line in lines) { point.X = 0; if (horizontalAlignment == HorizontalAlignment.Right) { point.X = maxWidthSoFar - widths[lineNumber]; } else if (horizontalAlignment == HorizontalAlignment.Center) { point.X = (maxWidthSoFar - widths[lineNumber]) / 2; } foreach (char c in line) { BitmapCharacterInfo characterInfo = GetCharacterInfo(c); int sourceLeft = characterInfo.GetPixelLeft(Texture); int sourceTop = characterInfo.GetPixelTop(Texture); int sourceWidth = characterInfo.GetPixelRight(Texture) - sourceLeft; int sourceHeight = characterInfo.GetPixelBottom(Texture) - sourceTop; int distanceFromTop = characterInfo.GetPixelDistanceFromTop(LineHeightInPixels); // There could be some offset for this character int xOffset = characterInfo.GetPixelXOffset(LineHeightInPixels); point.X += xOffset; point.Y = lineNumber * LineHeightInPixels + distanceFromTop; Microsoft.Xna.Framework.Rectangle sourceRectangle = new Microsoft.Xna.Framework.Rectangle( sourceLeft, sourceTop, sourceWidth, sourceHeight); int pageIndex = characterInfo.PageNumber; imageData.Blit(imageDatas[pageIndex], sourceRectangle, point); point.X -= xOffset; point.X += characterInfo.GetXAdvanceInPixels(LineHeightInPixels); } point.X = 0; lineNumber++; } } if (imageData != null) { // We don't want // to generate mipmaps // because text is usually // rendered pixel-perfect. const bool generateMipmaps = false; return(imageData.ToTexture2D(generateMipmaps)); } else { return(null); } }
private Texture2D RenderToTexture2DUsingRenderStates(IEnumerable <string> lines, HorizontalAlignment horizontalAlignment, SystemManagers managers, Texture2D toReplace = null) { if (managers == null) { managers = SystemManagers.Default; } ////////////////// Early out ///////////////////////// if (managers.Renderer.GraphicsDevice.GraphicsDeviceStatus != GraphicsDeviceStatus.Normal) { return(null); } ///////////////// End early out ////////////////////// RenderTarget2D renderTarget = null; Point point = new Point(); int requiredWidth; int requiredHeight; List <int> widths; GetRequiredWithAndHeight(lines, out requiredWidth, out requiredHeight, out widths); if (requiredWidth != 0) { var oldViewport = managers.Renderer.GraphicsDevice.Viewport; if (toReplace != null && requiredWidth == toReplace.Width && requiredHeight == toReplace.Height) { renderTarget = toReplace as RenderTarget2D; } else { renderTarget = new RenderTarget2D(managers.Renderer.GraphicsDevice, requiredWidth, requiredHeight); } managers.Renderer.GraphicsDevice.SetRenderTarget(renderTarget); SpriteBatch spriteBatch = managers.Renderer.SpriteBatch; { managers.Renderer.GraphicsDevice.Clear(Color.Transparent); spriteBatch.Begin(); int lineNumber = 0; foreach (string line in lines) { // scoot over to leave room for the outline point.X = mOutlineThickness; if (horizontalAlignment == HorizontalAlignment.Right) { point.X = requiredWidth - widths[lineNumber]; } else if (horizontalAlignment == HorizontalAlignment.Center) { point.X = (requiredWidth - widths[lineNumber]) / 2; } foreach (char c in line) { BitmapCharacterInfo characterInfo = GetCharacterInfo(c); int sourceLeft = characterInfo.GetPixelLeft(Texture); int sourceTop = characterInfo.GetPixelTop(Texture); int sourceWidth = characterInfo.GetPixelRight(Texture) - sourceLeft; int sourceHeight = characterInfo.GetPixelBottom(Texture) - sourceTop; int distanceFromTop = characterInfo.GetPixelDistanceFromTop(LineHeightInPixels); // There could be some offset for this character int xOffset = characterInfo.GetPixelXOffset(LineHeightInPixels); point.X += xOffset; point.Y = lineNumber * LineHeightInPixels + distanceFromTop; Microsoft.Xna.Framework.Rectangle sourceRectangle = new Microsoft.Xna.Framework.Rectangle( sourceLeft, sourceTop, sourceWidth, sourceHeight); int pageIndex = characterInfo.PageNumber; Rectangle destinationRectangle = new Rectangle(point.X, point.Y, sourceWidth, sourceHeight); spriteBatch.Draw(mTextures[pageIndex], destinationRectangle, sourceRectangle, Color.White); point.X -= xOffset; point.X += characterInfo.GetXAdvanceInPixels(LineHeightInPixels); } point.X = 0; lineNumber++; } spriteBatch.End(); } managers.Renderer.GraphicsDevice.SetRenderTarget(null); managers.Renderer.GraphicsDevice.Viewport = oldViewport; } return(renderTarget); }
public void SetFontPattern(string fontPattern) { mOutlineThickness = StringFunctions.GetIntAfter(" outline=", fontPattern); #region Identify the size of the character array to create int sizeOfArray = 256; // now loop through the file and look for numbers after "char id=" // Vic says: This used to // go through the entire file // to find the last character index. // I think they're ordered by character // index, so we can just find the last one // and save some time. int index = fontPattern.LastIndexOf("char id="); if (index != -1) { int ID = StringFunctions.GetIntAfter("char id=", fontPattern, index); sizeOfArray = System.Math.Max(sizeOfArray, ID + 1); } #endregion mCharacterInfo = new BitmapCharacterInfo[sizeOfArray]; mLineHeightInPixels = StringFunctions.GetIntAfter( "lineHeight=", fontPattern); if (mTextures.Length > 0) { BitmapCharacterInfo space = FillBitmapCharacterInfo(' ', fontPattern, mTextures[0].Width, mTextures[0].Height, mLineHeightInPixels, 0); for (int i = 0; i < sizeOfArray; i++) { mCharacterInfo[i] = space; } index = fontPattern.IndexOf("char id="); while (index != -1) { int ID = StringFunctions.GetIntAfter("char id=", fontPattern, index); mCharacterInfo[ID] = FillBitmapCharacterInfo(ID, fontPattern, mTextures[0].Width, mTextures[0].Height, mLineHeightInPixels, index); int indexOfID = fontPattern.IndexOf("char id=", index); if (indexOfID != -1) { index = indexOfID + ID.ToString().Length; } else { index = -1; } } #region Get Kearning Info index = fontPattern.IndexOf("kerning "); if (index != -1) { index = fontPattern.IndexOf("first=", index); while (index != -1) { int ID = StringFunctions.GetIntAfter("first=", fontPattern, index); int secondCharacter = StringFunctions.GetIntAfter("second=", fontPattern, index); int kearningAmount = StringFunctions.GetIntAfter("amount=", fontPattern, index); mCharacterInfo[ID].SecondLetterKearning.Add(secondCharacter, kearningAmount); index = fontPattern.IndexOf("first=", index + 1); } } #endregion } //mCharacterInfo[32].ScaleX = .23f; }
private BitmapCharacterInfo FillBitmapCharacterInfo(int characterID, string fontString, int textureWidth, int textureHeight, int lineHeightInPixels, int startingIndex) { BitmapCharacterInfo characterInfoToReturn = new BitmapCharacterInfo(); int indexOfID = fontString.IndexOf("char id=" + characterID, startingIndex); if (indexOfID != -1) { if (mAtlasedTexture != null) { characterInfoToReturn.TULeft = (mAtlasedTexture.SourceRectangle.X + StringFunctions.GetIntAfter("x=", fontString, indexOfID)) / (float)textureWidth; characterInfoToReturn.TURight = characterInfoToReturn.TULeft + StringFunctions.GetIntAfter("width=", fontString, indexOfID) / (float)textureWidth; characterInfoToReturn.TVTop = (mAtlasedTexture.SourceRectangle.Y + StringFunctions.GetIntAfter("y=", fontString, indexOfID)) / (float)textureHeight; characterInfoToReturn.TVBottom = characterInfoToReturn.TVTop + StringFunctions.GetIntAfter("height=", fontString, indexOfID) / (float)textureHeight; } else { characterInfoToReturn.TULeft = StringFunctions.GetIntAfter("x=", fontString, indexOfID) / (float)textureWidth; characterInfoToReturn.TVTop = StringFunctions.GetIntAfter("y=", fontString, indexOfID) / (float)textureHeight; characterInfoToReturn.TURight = characterInfoToReturn.TULeft + StringFunctions.GetIntAfter("width=", fontString, indexOfID) / (float)textureWidth; characterInfoToReturn.TVBottom = characterInfoToReturn.TVTop + StringFunctions.GetIntAfter("height=", fontString, indexOfID) / (float)textureHeight; } characterInfoToReturn.DistanceFromTopOfLine = // 1 sclY means 2 height 2 * StringFunctions.GetIntAfter("yoffset=", fontString, indexOfID) / (float)lineHeightInPixels; characterInfoToReturn.ScaleX = StringFunctions.GetIntAfter("width=", fontString, indexOfID) / (float)lineHeightInPixels; characterInfoToReturn.ScaleY = StringFunctions.GetIntAfter("height=", fontString, indexOfID) / (float)lineHeightInPixels; characterInfoToReturn.Spacing = 2 * StringFunctions.GetIntAfter("xadvance=", fontString, indexOfID) / (float)lineHeightInPixels; characterInfoToReturn.XOffset = 2 * StringFunctions.GetIntAfter("xoffset=", fontString, indexOfID) / (float)lineHeightInPixels; characterInfoToReturn.PageNumber = StringFunctions.GetIntAfter("page=", fontString, indexOfID); // characterInfoToReturn.Spacing = 25 * StringFunctions.GetIntAfter("xadvance=", fontString, indexOfID) / // (float)(textureWidth); } return characterInfoToReturn; }
public void SetFontPattern(string fontPattern) { mOutlineThickness = StringFunctions.GetIntAfter(" outline=", fontPattern); #region Identify the size of the character array to create int sizeOfArray = 256; // now loop through the file and look for numbers after "char id=" // Vic says: This used to // go through the entire file // to find the last character index. // I think they're ordered by character // index, so we can just find the last one // and save some time. int index = fontPattern.LastIndexOf("char id="); if (index != -1) { int ID = StringFunctions.GetIntAfter("char id=", fontPattern, index); sizeOfArray = System.Math.Max(sizeOfArray, ID + 1); } #endregion mCharacterInfo = new BitmapCharacterInfo[sizeOfArray]; mLineHeightInPixels = StringFunctions.GetIntAfter( "lineHeight=", fontPattern); BaselineY = StringFunctions.GetIntAfter( "base=", fontPattern); if (mTextures.Length > 0 && mTextures[0] != null) { //ToDo: Atlas support ************************************************************** BitmapCharacterInfo space = FillBitmapCharacterInfo(' ', fontPattern, mTextures[0].Width, mTextures[0].Height, mLineHeightInPixels, 0); for (int i = 0; i < sizeOfArray; i++) { mCharacterInfo[i] = space; } // Make the tab character be equivalent to 4 spaces: mCharacterInfo['t'].ScaleX = space.ScaleX * 4; mCharacterInfo['t'].Spacing = space.Spacing * 4; index = fontPattern.IndexOf("char id="); while (index != -1) { int ID = StringFunctions.GetIntAfter("char id=", fontPattern, index); //ToDo: Atlas support ************************************************************* mCharacterInfo[ID] = FillBitmapCharacterInfo(ID, fontPattern, mTextures[0].Width, mTextures[0].Height, mLineHeightInPixels, index); int indexOfID = fontPattern.IndexOf("char id=", index); if (indexOfID != -1) { index = indexOfID + ID.ToString().Length; } else { index = -1; } } #region Get Kearning Info index = fontPattern.IndexOf("kerning "); if (index != -1) { index = fontPattern.IndexOf("first=", index); while (index != -1) { int ID = StringFunctions.GetIntAfter("first=", fontPattern, index); int secondCharacter = StringFunctions.GetIntAfter("second=", fontPattern, index); int kearningAmount = StringFunctions.GetIntAfter("amount=", fontPattern, index); if (mCharacterInfo[ID].SecondLetterKearning.ContainsKey(secondCharacter)) { throw new InvalidOperationException($"Trying to add the character {secondCharacter} to the mCharacterInfo {ID}, but this entry already exists"); } mCharacterInfo[ID].SecondLetterKearning.Add(secondCharacter, kearningAmount); index = fontPattern.IndexOf("first=", index + 1); } } #endregion } //mCharacterInfo[32].ScaleX = .23f; }