Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using SlimDX.Direct3D9;
- using System.Drawing;
- using SlimDX;
- namespace Gype.UI.D3D9
- {
- [Flags]
- internal enum FontFlags : uint
- {
- NoClip = 1,
- WordWrap = 2,
- LetterWrap = 4
- }
- internal class GdiFontProvider
- {
- public GdiFontProvider(Rendertarget target, string family, int fontSize)
- {
- mTarget = target as Rendertarget9;
- mGdiFont = new System.Drawing.Font(family, fontSize, FontStyle.Bold, GraphicsUnit.Pixel);
- mFontHeight = mGdiFont.Height;
- mVertexShader = new ShaderCompiler<VertexShader>(mTarget.GraphicsDevice, Shaders.Text, "VertexMain", "vs_3_0");
- mPixelShader = new ShaderCompiler<PixelShader>(mTarget.GraphicsDevice, Shaders.Text, "PixelMain", "ps_3_0");
- mMatrixParam = mVertexShader.ConstantTable["orthoProjMatrix"];
- var maxTextureSize = target.GetMaximumTextureSize();
- mTextureSize = Math.Min(Math.Min(maxTextureSize.Height, maxTextureSize.Width), 1024);
- var curChars = GetCodepageChars(System.Globalization.CultureInfo.CurrentCulture.TextInfo.ANSICodePage);
- var usChars = GetCodepageChars(437);
- var arabChars = GetCodepageChars(1256);
- var str = curChars.Union(usChars).Union(arabChars);
- AllocateNewTexture();
- LoadCharRange(str.Except(new char[] { '\0' }).ToArray());
- LoadWhiteSpaces();
- }
- public void DrawString(string str, SlimDX.Vector2 position, SlimDX.Vector2 size, FontFlags flags, Color4 clr, float scale = 0.8f)
- {
- LoadCharRange(str);
- Vector2 curPos = position;
- List<UIVertex> triangleList = new List<UIVertex>();
- foreach (var c in str)
- {
- if (char.IsWhiteSpace(c) && c != ' ')
- continue;
- if (c == ' ')
- {
- curPos.X += mGlyphs[' '].CharWidth * scale;
- continue;
- }
- var glyph = mGlyphs[c];
- var vertices = mTarget.CreateTriangleList(curPos, new Vector2(glyph.CharWidth * scale, mFontHeight * scale), clr);
- vertices[0].TexCoord = glyph.TexCoordTop;
- vertices[1].TexCoord = new Vector2(glyph.TexCoordBottom.X, glyph.TexCoordTop.Y);
- vertices[2].TexCoord = new Vector2(glyph.TexCoordTop.X, glyph.TexCoordBottom.Y);
- vertices[3].TexCoord = vertices[1].TexCoord;
- vertices[4].TexCoord = glyph.TexCoordBottom;
- vertices[5].TexCoord = vertices[2].TexCoord;
- triangleList.AddRange(vertices);
- curPos.X += (glyph.CharWidth + 1.5f) * scale;
- }
- var dev = mTarget.GraphicsDevice;
- dev.VertexShader = mVertexShader.Shader;
- dev.PixelShader = mPixelShader.Shader;
- mVertexShader.SetValue(mMatrixParam, mTarget.OrthoMatrix);
- dev.SetTexture(0, mFontTextures[0]);
- dev.VertexDeclaration = mTarget.UIVertexDeclaration;
- dev.DrawUserPrimitives(PrimitiveType.TriangleList, triangleList.Count / 3, triangleList.ToArray());
- dev.VertexShader = null;
- dev.PixelShader = null;
- }
- private char[] GetCodepageChars(int codepage)
- {
- byte[] letters = new byte[223];
- for (int i = 33; i < 256; ++i)
- {
- letters[i - 33] = (byte)i;
- }
- var encoding = Encoding.GetEncoding(codepage);
- var str = encoding.GetChars(letters);
- return str;
- }
- private void LoadWhiteSpaces()
- {
- var size = mBitmapGraphics.MeasureString(" ", mGdiFont);
- mGlyphs.Add(' ',
- new CharGlyphEntry()
- {
- IgnoreDraw = true,
- CharWidth = (int)size.Width,
- TexCoordBottom = Vector2.Zero,
- TexCoordTop = Vector2.Zero,
- TextureIndex = -1
- }
- );
- }
- private void LoadCharRange(string range)
- {
- LoadCharRange(range.Distinct().ToArray());
- }
- private void LoadCharRange(char[] chars)
- {
- List<char> newChars = new List<char>();
- foreach (char c in chars)
- {
- if (mGlyphs.ContainsKey(c))
- continue;
- newChars.Add(c);
- }
- if (newChars.Count == 0)
- return;
- Bitmap bmp = new Bitmap(mFontHeight * 2, mFontHeight, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
- Graphics g = Graphics.FromImage(bmp);
- SolidBrush brush = new SolidBrush(Color.White);
- foreach (char c in newChars)
- {
- g.Clear(Color.Transparent);
- g.DrawString(c.ToString(), mGdiFont, brush, PointF.Empty);
- int charStart = mFontHeight * 2;
- int charEnd = 0;
- bool startFound = false;
- bool endFound = false;
- for (int x = 0; x < mFontHeight * 2; ++x)
- {
- for (int y = 0; y < mFontHeight; ++y)
- {
- var clr = bmp.GetPixel(x, y);
- if (clr.A == 0)
- continue;
- charStart = x;
- startFound = true;
- break;
- }
- if (startFound)
- break;
- }
- for (int x = mFontHeight * 2 - 1; x >= 0; --x)
- {
- for (int y = 0; y < mFontHeight; ++y)
- {
- var clr = bmp.GetPixel(x, y);
- if (clr.A == 0)
- continue;
- charEnd = x;
- endFound = true;
- break;
- }
- if (endFound)
- break;
- }
- CharGlyphEntry entry = new CharGlyphEntry();
- if (charEnd < charStart)
- {
- entry.IgnoreDraw = true;
- continue;
- }
- entry.CharWidth = (charEnd - charStart) + 1;
- entry.TextureIndex = mFontTextures.Count - 1;
- if ((mCurOfsX + (charEnd - charStart) + 1) > mTextureSize)
- {
- mCurOfsX = 0;
- mCurOfsY += mFontHeight;
- if (mCurOfsY + mFontHeight >= mTextureSize)
- {
- UpdateTexture();
- AllocateNewTexture();
- mCurOfsY = 0;
- }
- }
- entry.TexCoordTop = new SlimDX.Vector2((float)mCurOfsX / mTextureSize, (float)mCurOfsY / mTextureSize);
- entry.TexCoordBottom = new SlimDX.Vector2((float)(mCurOfsX + (charEnd - charStart) + 1) / mTextureSize, (float)(mCurOfsY + mFontHeight) / mTextureSize);
- entry.IgnoreDraw = false;
- mGlyphs.Add(c, entry);
- mBitmapGraphics.DrawImage(bmp, new RectangleF(mCurOfsX, mCurOfsY, (charEnd - charStart) + 1, mFontHeight), new RectangleF(charStart, 0, (charEnd - charStart) + 1, mFontHeight), GraphicsUnit.Pixel);
- mCurOfsX += (charEnd - charStart) + 1;
- }
- UpdateTexture();
- }
- private void UpdateTexture()
- {
- var lockData = mCurrentBitmap.LockBits(new Rectangle(0, 0, mTextureSize, mTextureSize), System.Drawing.Imaging.ImageLockMode.ReadOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
- var surf = mCurrentTexture.GetSurfaceLevel(0);
- Surface.FromStream(surf, new SlimDX.DataStream(lockData.Scan0, mTextureSize * mTextureSize * 4, true, true), Filter.Default, 0, Format.A8R8G8B8, 4 * mTextureSize, new Rectangle(0, 0, mTextureSize, mTextureSize));
- surf.Dispose();
- mCurrentBitmap.UnlockBits(lockData);
- }
- private void AllocateNewTexture()
- {
- if (mCurrentBitmap != null)
- mBitmapGraphics.Clear(Color.Transparent);
- else
- {
- mCurrentBitmap = new Bitmap(mTextureSize, mTextureSize, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
- mBitmapGraphics = Graphics.FromImage(mCurrentBitmap);
- }
- mCurrentTexture = new Texture(mTarget.GraphicsDevice, mTextureSize, mTextureSize, 1, Usage.None, Format.A8R8G8B8, Pool.Managed);
- mFontTextures.Add(mCurrentTexture);
- }
- private class CharGlyphEntry
- {
- public SlimDX.Vector2 TexCoordTop { get; set; }
- public SlimDX.Vector2 TexCoordBottom { get; set; }
- public int CharWidth { get; set; }
- public int TextureIndex { get; set; }
- public bool IgnoreDraw { get; set; }
- }
- private int mFontHeight = 0;
- private int mCurOfsX = 0;
- private int mCurOfsY = 0;
- private Graphics mBitmapGraphics;
- private Bitmap mCurrentBitmap;
- private Texture mCurrentTexture;
- private Dictionary<char, CharGlyphEntry> mGlyphs = new Dictionary<char, CharGlyphEntry>();
- private List<Texture> mFontTextures = new List<Texture>();
- private int mTextureSize;
- private System.Drawing.Font mGdiFont;
- private Rendertarget9 mTarget;
- private ShaderCompiler<VertexShader> mVertexShader;
- private ShaderCompiler<PixelShader> mPixelShader;
- private ConstantDescription mMatrixParam;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment