public void Write(string imagePath) { using (FileStream stream = new FileStream(imagePath, FileMode.Create)) { using (GZipStream gzip = new GZipStream(stream, CompressionMode.Compress)) { using (Bitmap bmp = RenderToBitmap()) { using (BinaryWriter writer = new BinaryWriter(gzip)) { writer.Write("FontMatrix001"); writer.Write(m_TextureSize); FontResource[] resources = new FontResource[] { XLarge, Large, Heading, Regular, Small, Monospaced }; writer.Write(resources.Length); for (int i = 0; i < resources.Length; i++) { resources[i].Write(writer); StructHelper.WriteStructure(writer, m_BiggestCharSize[i]); Dictionary<char, RectangleF> lookup = m_CharLookup[i]; writer.Write(lookup.Count); foreach (KeyValuePair<char, RectangleF> rect in lookup) { writer.Write(rect.Key); StructHelper.WriteStructure(writer, rect.Value); } } using (Stream imageStream = new MemoryStream()) { bmp.Save(imageStream, ImageFormat.Png); writer.Write((int)imageStream.Length); imageStream.Position = 0; imageStream.CopyTo(gzip, 4096); } } } } } }
public static FontMatrix Read(string imagePath) { using (FileStream stream = new FileStream(imagePath, FileMode.Open)) { using (GZipStream gzip = new GZipStream(stream, CompressionMode.Decompress)) { FontMatrix matrix = new FontMatrix(); using (BinaryReader reader = new BinaryReader(gzip)) { string formatName = reader.ReadString(); if (formatName != "FontMatrix001") { throw new Exception("Font Matrix format is incorrect '" + formatName + "'"); } matrix.TextureSize = reader.ReadInt32(); matrix.XLarge = new FontResource(); matrix.Large = new FontResource(); matrix.Heading = new FontResource(); matrix.Regular = new FontResource(); matrix.Small = new FontResource(); matrix.Monospaced = new FontResource(); FontResource[] resources = new FontResource[] { matrix.XLarge, matrix.Large, matrix.Heading, matrix.Regular, matrix.Small, matrix.Monospaced }; reader.ReadInt32(); for (int i = 0; i < resources.Length; i++) { resources[i].Read(reader); matrix.m_BiggestCharSize[i] = StructHelper.ReadStructure<Rectangle>(reader); int count = reader.ReadInt32(); Dictionary<char, RectangleF> lookup = new Dictionary<char, RectangleF>(count); for (int c = 0; c < count; c++) { char @char = reader.ReadChar(); RectangleF rect = StructHelper.ReadStructure<RectangleF>(reader); lookup.Add(@char, rect); } matrix.m_CharLookup[i] = lookup; } int length = reader.ReadInt32(); using (Stream imageStream = new MemoryStream(reader.ReadBytes(length))) { Bitmap bmp = (Bitmap)Bitmap.FromStream(imageStream); // bmp.Save(@"c:\test2.png", ImageFormat.Png); matrix.m_Bitmap = bmp; } } return matrix; } } }
public Bitmap RenderToBitmap() { /* char[] AllChars = new char[] { '0','1','2','3','4','5','6','7','8','9', 'a', 'b', 'c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z', 'A', 'B', 'C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z', '!','"','$','%','^','&','*','(',')','-','+','_','=','`','¬','\\','|',',','.','/','<','>','?',';',':','\'','@', '~','#','[',']','{','}',' ', }; */ int bmpSize = m_TextureSize; float tSize = 1f / (float)bmpSize; Bitmap bmp = new Bitmap(bmpSize, bmpSize, PixelFormat.Format32bppArgb); using (Graphics graphics = Graphics.FromImage(bmp)) { graphics.Clear(Color.Transparent); FontResource[] resources = new FontResource[] { XLarge, Large, Heading, Regular, Small, Monospaced }; float x = 0f, y = 0f; bool first = true; foreach (FontResource res in resources) { if (res.Disposed) { res.LoadResources(); } graphics.TextRenderingHint = res.RenderingHint; float w = 0, h = 0; float hScaleFactor = 1.1f; Dictionary<char, RectangleF> lookup = new Dictionary<char, RectangleF>(); foreach (char @char in AllChars) { SizeF size = graphics.MeasureString(@char.ToString(), res.Font, bmpSize, StringFormat.GenericTypographic); if (size.Width > w) { w = size.Width; } if (size.Height > h) { h = size.Height; } } //Rectangle maxCharBounds = new Rectangle(0, 0, (int)(w + 0.5f), (int)(h + 0.5f)); Rectangle maxCharBounds = new Rectangle(0, 0, (int)(w + 0.5f), (int)(h * hScaleFactor)); if (first == true) { graphics.FillRectangle(Brushes.White, maxCharBounds); x += maxCharBounds.Width; int diff = 8 - (maxCharBounds.Width % 8); x += diff; first = false; } float xScale = 1f; foreach (char @char in AllChars) { if (@char == ' ') { float spaceWidth; if (res.FontType == FontType.Monospaced) { spaceWidth = maxCharBounds.Width; } else { spaceWidth = maxCharBounds.Width * 0.33f; } lookup.Add(@char, new RectangleF(x * tSize, y * tSize, spaceWidth * tSize * xScale, (float)maxCharBounds.Height * tSize)); x += (int)(spaceWidth + 0.5f); int diff = 8 - ((int)(spaceWidth + 0.5f) % 8); x += diff; } else { SizeF currentSize = graphics.MeasureString(@char.ToString(), res.Font, maxCharBounds.Width, StringFormat.GenericTypographic); graphics.DrawString(@char.ToString(), res.Font, Brushes.White, new PointF(x, y), StringFormat.GenericTypographic); lookup.Add(@char, new RectangleF(x * tSize, y * tSize, currentSize.Width * tSize * xScale, (float)maxCharBounds.Height * tSize)); x += (int)(currentSize.Width + 0.5f); int diff = 8 - ((int)(currentSize.Width + 0.5f) % 8); x += diff; } if (x + maxCharBounds.Width + (8 - (maxCharBounds.Width % 8)) > bmpSize) { x = 0f; y += maxCharBounds.Height; int diff = 8 - (maxCharBounds.Height % 8); y += diff; } } x = 0f; y += maxCharBounds.Height; int diffy = 8 - (maxCharBounds.Height % 8); y += diffy; m_BiggestCharSize[(int)res.FontType] = maxCharBounds; m_CharLookup[(int)res.FontType] = lookup; } } /* BitmapData data = null; try { data = bmp.LockBits(new Rectangle(0, 0, bmpSize, bmpSize), ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb); byte[] dest = new byte[data.Stride * bmpSize]; Marshal.Copy(data.Scan0, dest, 0, dest.Length); m_Texture = new Texture2D(GameEnvironment.Device, new Texture2DDescription() { Format = SlimDX.DXGI.Format.R16G16B16A16_Float, // .R16_Float, Width = bmpSize, Height = bmpSize, MipLevels = 1, ArraySize = 1, BindFlags = BindFlags.ShaderResource, CpuAccessFlags = CpuAccessFlags.Write, OptionFlags = ResourceOptionFlags.None, Usage = ResourceUsage.Dynamic, SampleDescription = new SlimDX.DXGI.SampleDescription(1, 0) }); DataRectangle dataRect = m_Texture.Map(0, MapMode.WriteDiscard, MapFlags.None); float cScale = 1f / 255f; for (int i = 0; i < bmpSize * bmpSize * 4; i += 4) { dataRect.Data.Write(new Half4(new Half((float)dest[i + 0] * cScale), new Half((float)dest[i + 1] * cScale), new Half((float)dest[i + 2] * cScale), new Half((float)dest[i + 3] * cScale))); } m_Texture.Unmap(0); m_TextureView = new ShaderResourceView(GameEnvironment.Device, m_Texture, new ShaderResourceViewDescription() { Dimension = ShaderResourceViewDimension.Texture2D, Format = SlimDX.DXGI.Format.R16G16B16A16_Float, //.R16_Float, ArraySize = 1, MipLevels = 1, MostDetailedMip = 0, }); } finally { if (data != null) { bmp.UnlockBits(data); } } */ //bmp.Save(@"c:\test.png", ImageFormat.Png); return bmp; }