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 RenderToTexture2D(IEnumerable lines, HorizontalAlignment horizontalAlignment, bool changeColor, float red, float green, float blue, float alpha) { ImageData sourceImageData = ImageData.FromTexture2D(this.Texture); if (changeColor) { sourceImageData.ApplyColorOperation(ColorOperation.Add, red, green, blue, alpha); } 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; for (int i = 0; i < line.Length; i++) { char character = line[i]; BitmapCharacterInfo characterInfo = GetCharacterInfo(character); bool isLast = i == line.Length - 1; if (isLast) { requiredWidth += characterInfo.GetPixelWidth(Texture) + characterInfo.GetPixelXOffset(LineHeightInPixels); } else { requiredWidth += characterInfo.GetXAdvanceInPixels(LineHeightInPixels); } } widths.Add(requiredWidth); maxWidthSoFar = System.Math.Max(requiredWidth, maxWidthSoFar); } ImageData imageData = new ImageData(maxWidthSoFar, requiredHeight); 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; Rectangle sourceRectangle = new Rectangle( sourceLeft, sourceTop, sourceWidth, sourceHeight); imageData.Blit(sourceImageData, sourceRectangle, point); point.X -= xOffset; point.X += characterInfo.GetXAdvanceInPixels(LineHeightInPixels); } point.X = 0; lineNumber++; } // We don't want // to generate mipmaps // because text is usually // rendered pixel-perfect. const bool generateMipmaps = false; return(imageData.ToTexture2D(generateMipmaps, FlatRedBallServices.GraphicsDevice)); }
public void SetFontPattern(string 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=", fontPattern.Length, StringComparison.Ordinal); if (index != -1) { int ID = StringFunctions.GetIntAfter("char id=", fontPattern, index); sizeOfArray = System.Math.Max(sizeOfArray, ID + 1); } else { // index is -1, but let's try a regular IndexOf: int forwardIndexOf = fontPattern.IndexOf("char id="); if (forwardIndexOf != -1 && index == -1) { throw new Exception("How is this possible? LastIndexOf \"char id=\" is returning a value of -1, while IndexOf for the same string is returning an index value)"); } else { string message = "Could not find the last index of the string \"char id=\" in the font pattern. " + "This means that the font file has no characters. Font files must have at least one defined character"; throw new Exception(message); } } #endregion mCharacterInfo = new BitmapCharacterInfo[sizeOfArray]; mLineHeightInPixels = StringFunctions.GetIntAfter( "lineHeight=", fontPattern); // This font may not reference any textures at all - if it doesn't have any // characters set in the .bmfc. I don't think we should crash here if so: 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; } // 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=", 0, StringComparison.Ordinal); while (index != -1) { int ID = StringFunctions.GetIntAfter("char id=", fontPattern, index); if (ID == -1) { // The bitmap font may have something like this as the first character: // char id=-1 x=149 y=84 width=10 height=18 xoffset=1 yoffset=7 xadvance=12 page=0 chnl=15 // We don't use that, but we don't want to crash on it, so continue onward. int indexOfID = fontPattern.IndexOf("char id=", index, StringComparison.Ordinal); index = indexOfID + ID.ToString().Length; continue; } else { #if DEBUG if (ID >= mCharacterInfo.Length) { string message = $"Error trying to access character with int {ID} which is character {(char)ID}"; message += $"This is happening in the font string at index {index} which has the following characters:"; int startIndex = System.Math.Max(0, index); int endIndex = System.Math.Min(fontPattern.Length - 1, index + 100); message += fontPattern.Substring(startIndex, endIndex - startIndex); throw new IndexOutOfRangeException(message); } #endif mCharacterInfo[ID] = FillBitmapCharacterInfo(ID, fontPattern, mTextures[0].Width, mTextures[0].Height, mLineHeightInPixels, index); int indexOfID = fontPattern.IndexOf("char id=", index, StringComparison.Ordinal); if (indexOfID != -1) { index = indexOfID + ID.ToString().Length; } else { index = -1; } } } #region Get Kearning Info index = fontPattern.IndexOf("kerning ", 0, StringComparison.Ordinal); if (index != -1) { index = fontPattern.IndexOf("first=", index, StringComparison.Ordinal); 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, StringComparison.Ordinal); } } #endregion } //mCharacterInfo[32].ScaleX = .23f; }