| | 1 | | using System; |
| | 2 | | using System.Collections.Generic; |
| | 3 | | using System.Drawing; |
| | 4 | | using Imagini.Drawing; |
| | 5 | | using Imagini.ImageSharp; |
| | 6 | |
|
| | 7 | | namespace Imagini.Fonts.Renderers |
| | 8 | | { |
| | 9 | | public class GraphicsTextRenderer : Resource, ITextRenderer |
| | 10 | | { |
| 99 | 11 | | public SpriteFont Font { get; private set; } |
| | 12 | | private Graphics _graphics; |
| | 13 | |
|
| 6 | 14 | | private List<Texture> _pages = new List<Texture>(); |
| | 15 | |
|
| 6 | 16 | | public GraphicsTextRenderer(Graphics graphics, SpriteFont font, |
| 6 | 17 | | TextureScalingQuality quality = TextureScalingQuality.Linear) |
| | 18 | | { |
| 6 | 19 | | Font = font; |
| 6 | 20 | | _graphics = graphics; |
| 36 | 21 | | foreach(var page in font.Pages) |
| | 22 | | { |
| 0 | 23 | | var texture = TextureFactory.FromImage(_graphics, quality, |
| 0 | 24 | | page.Texture); |
| 12 | 25 | | texture.BlendMode = BlendMode.AlphaBlend; |
| 12 | 26 | | page.Texture.Dispose(); // dispose and unset the original image |
| 12 | 27 | | page.Texture = null; |
| 12 | 28 | | _pages.Add(texture); |
| | 29 | | } |
| 6 | 30 | | } |
| | 31 | |
|
| | 32 | | public void Draw(string text, PointF position, Color color, |
| | 33 | | FontDrawingOptions options = new FontDrawingOptions()) |
| | 34 | | { |
| 8 | 35 | | if (options.Equals(default(FontDrawingOptions))) |
| 4 | 36 | | options = FontDrawingOptions.Default; |
| | 37 | |
|
| 8 | 38 | | if (options.Scale <= 0.0f) |
| 0 | 39 | | return; |
| | 40 | |
|
| 48 | 41 | | foreach (var tex in _pages) |
| 16 | 42 | | tex.ColorMod = color; |
| | 43 | |
|
| 8 | 44 | | var scale = options.Scale; |
| 8 | 45 | | var scaledSpacing = (int)(options.LetterSpacing * scale); |
| | 46 | |
|
| 8 | 47 | | var pageIndex = 0; |
| 8 | 48 | | var page = Font.Pages[0]; |
| 8 | 49 | | var x = (int)position.X; |
| 8 | 50 | | var y = (int)position.Y; |
| 8 | 51 | | var scaledFontSize = (int)(Font.Font.Size * scale); |
| 208 | 52 | | foreach(var symbol in text) |
| | 53 | | { |
| 96 | 54 | | if (_pages.Count > 1) |
| | 55 | | { |
| 48 | 56 | | if (symbol < page.Start || symbol > page.End) |
| | 57 | | { |
| 22 | 58 | | pageIndex = Font.GetPageIndex(symbol); |
| 28 | 59 | | if (pageIndex < 0) pageIndex = 0; |
| 22 | 60 | | page = Font.Pages[pageIndex]; |
| | 61 | | } |
| | 62 | | } |
| 96 | 63 | | var srcRect = page.GetGlyph(symbol); |
| 96 | 64 | | if (char.IsWhiteSpace(symbol)) |
| | 65 | | { |
| 8 | 66 | | x += srcRect.IsEmpty ? scaledFontSize : (int)(srcRect.Width * scale); |
| 8 | 67 | | x += scaledSpacing; |
| 8 | 68 | | continue; |
| | 69 | | } |
| 88 | 70 | | if (srcRect.IsEmpty) |
| | 71 | | { |
| | 72 | | // symbol not found, replace with a rectangle |
| 12 | 73 | | _graphics.DrawRect(new Rectangle(x, y, scaledFontSize, scaledFontSize)); |
| 12 | 74 | | x += scaledFontSize + 1 + scaledSpacing; |
| 12 | 75 | | continue; |
| | 76 | | } |
| | 77 | |
|
| 76 | 78 | | var scaledWidth = scale == 1.0f ? srcRect.Width : (int)(srcRect.Width * scale); |
| 76 | 79 | | var scaledHeight = scale == 1.0f ? srcRect.Height: (int)(srcRect.Height * scale); |
| 76 | 80 | | var dstRect = new Rectangle(x, y, scaledWidth, scaledHeight); |
| 76 | 81 | | _graphics.Draw(_pages[pageIndex], srcRect, dstRect); |
| 76 | 82 | | x += scaledWidth + scaledSpacing; |
| | 83 | | } |
| 8 | 84 | | } |
| | 85 | |
|
| | 86 | | public void Draw(string text, PointF position, FontDrawingOptions options = default(FontDrawingOptions)) |
| | 87 | | { |
| 6 | 88 | | Draw(text, position, _graphics.GetDrawingColor(), options); |
| 6 | 89 | | } |
| | 90 | |
|
| | 91 | | public void Dispose() |
| | 92 | | { |
| 6 | 93 | | if (IsDisposed) return; |
| 6 | 94 | | base.Destroy(); |
| 6 | 95 | | } |
| | 96 | |
|
| | 97 | | public Size Measure(string text, FontDrawingOptions options = new FontDrawingOptions()) |
| | 98 | | { |
| 4 | 99 | | if (options.Equals(default(FontDrawingOptions))) |
| 2 | 100 | | options = FontDrawingOptions.Default; |
| 4 | 101 | | if (options.Scale <= 0.0f) |
| 0 | 102 | | return Size.Empty; |
| | 103 | |
|
| 4 | 104 | | var scale = options.Scale; |
| 4 | 105 | | var scaledSpacing = (int)(options.LetterSpacing * scale); |
| | 106 | |
|
| 4 | 107 | | var pageIndex = 0; |
| 4 | 108 | | var page = Font.Pages[0]; |
| 4 | 109 | | int x = 0; |
| 4 | 110 | | var scaledFontSize = (int)(Font.Font.Size * scale); |
| 104 | 111 | | foreach(var symbol in text) |
| | 112 | | { |
| 48 | 113 | | if (_pages.Count > 1) |
| | 114 | | { |
| 22 | 115 | | if (symbol < page.Start || symbol > page.End) |
| | 116 | | { |
| 12 | 117 | | pageIndex = Font.GetPageIndex(symbol); |
| 18 | 118 | | if (pageIndex < 0) pageIndex = 0; |
| 12 | 119 | | page = Font.Pages[pageIndex]; |
| | 120 | | } |
| | 121 | | } |
| 48 | 122 | | var srcRect = page.GetGlyph(symbol); |
| 48 | 123 | | if (char.IsWhiteSpace(symbol)) |
| | 124 | | { |
| 4 | 125 | | x += srcRect.IsEmpty ? scaledFontSize : (int)(srcRect.Width * scale); |
| 4 | 126 | | x += scaledSpacing; |
| 4 | 127 | | continue; |
| | 128 | | } |
| 44 | 129 | | if (srcRect.IsEmpty) |
| | 130 | | { |
| | 131 | | // symbol not found, replace with a rectangle |
| 6 | 132 | | x += scaledFontSize + 1 + scaledSpacing; |
| 6 | 133 | | continue; |
| | 134 | | } |
| 38 | 135 | | x += (int)(srcRect.Width * scale) + scaledSpacing; |
| | 136 | | } |
| 4 | 137 | | return new Size(x, scaledFontSize); |
| | 138 | | } |
| | 139 | | } |
| | 140 | | } |