123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211 |
- using FontStashSharp.Interfaces;
- using System;
- #if MONOGAME || FNA
- using Microsoft.Xna.Framework;
- using Microsoft.Xna.Framework.Graphics;
- #elif STRIDE
- using Stride.Core.Mathematics;
- using Stride.Graphics;
- #else
- using System.Drawing;
- using System.Numerics;
- #endif
- namespace FontStashSharp
- {
- public partial class DynamicSpriteFont : SpriteFontBase
- {
- internal readonly Int32Map<DynamicFontGlyph> Glyphs = new Int32Map<DynamicFontGlyph>();
- private readonly Int32Map<int> Kernings = new Int32Map<int>();
- private FontMetrics[] IndexedMetrics;
- public FontSystem FontSystem { get; private set; }
- internal DynamicSpriteFont(FontSystem system, float size, int lineHeight) : base(size, lineHeight)
- {
- if (system == null)
- {
- throw new ArgumentNullException(nameof(system));
- }
- FontSystem = system;
- RenderFontSizeMultiplicator = FontSystem.FontResolutionFactor;
- }
- private DynamicFontGlyph GetGlyphWithoutBitmap(int codepoint)
- {
- DynamicFontGlyph glyph;
- if (Glyphs.TryGetValue(codepoint, out glyph))
- {
- return glyph;
- }
- int fontSourceIndex;
- var g = FontSystem.GetCodepointIndex(codepoint, out fontSourceIndex);
- if (g == null)
- {
- Glyphs[codepoint] = null;
- return null;
- }
- var fontSize = FontSize * FontSystem.FontResolutionFactor;
- var font = FontSystem.FontSources[fontSourceIndex];
- double advance, x0, y0, x1, y1;
- font.GetGlyphMetrics(codepoint, fontSize, out advance, out x0, out y0, out x1, out y1);
- var effectPad = Math.Max(FontSystem.BlurAmount, FontSystem.StrokeAmount);
- var gw = x1 - x0 + effectPad * 2;
- var gh = y1 - y0 + effectPad * 2;
- glyph = new DynamicFontGlyph
- {
- Codepoint = codepoint,
- Id = g.Value,
- FontSize = fontSize,
- FontSourceIndex = fontSourceIndex,
- RenderOffset = new Point((int)x0, (int)y0),
- Size = new Point((int)gw, (int)gh),
- XAdvance = (int)advance,
- };
- Glyphs[codepoint] = glyph;
- return glyph;
- }
- #if MONOGAME || FNA || STRIDE
- private DynamicFontGlyph GetGlyphInternal(GraphicsDevice device, int codepoint)
- #else
- private DynamicFontGlyph GetGlyphInternal(ITexture2DManager device, int codepoint)
- #endif
- {
- var glyph = GetGlyphWithoutBitmap(codepoint);
- if (glyph == null)
- {
- return null;
- }
- if (device == null || glyph.Texture != null)
- return glyph;
- FontSystem.RenderGlyphOnAtlas(device, glyph);
- return glyph;
- }
- #if MONOGAME || FNA || STRIDE
- private DynamicFontGlyph GetDynamicGlyph(GraphicsDevice device, int codepoint)
- #else
- private DynamicFontGlyph GetDynamicGlyph(ITexture2DManager device, int codepoint)
- #endif
- {
- var result = GetGlyphInternal(device, codepoint);
- if (result == null && FontSystem.DefaultCharacter != null)
- {
- result = GetGlyphInternal(device, FontSystem.DefaultCharacter.Value);
- }
- return result;
- }
- #if MONOGAME || FNA || STRIDE
- protected internal override FontGlyph GetGlyph(GraphicsDevice device, int codepoint)
- #else
- protected internal override FontGlyph GetGlyph(ITexture2DManager device, int codepoint)
- #endif
- {
- return GetDynamicGlyph(device, codepoint);
- }
- private void GetMetrics(int fontSourceIndex, out FontMetrics result)
- {
- if (IndexedMetrics == null || IndexedMetrics.Length != FontSystem.FontSources.Count)
- {
- IndexedMetrics = new FontMetrics[FontSystem.FontSources.Count];
- for (var i = 0; i < IndexedMetrics.Length; ++i)
- {
- double ascent, descent, lineHeight;
- FontSystem.FontSources[i].GetMetricsForSize(FontSize * RenderFontSizeMultiplicator, out ascent, out descent, out lineHeight);
- IndexedMetrics[i] = new FontMetrics((int)ascent, (int)descent, (int)lineHeight);
- }
- }
- result = IndexedMetrics[fontSourceIndex];
- }
- internal override void PreDraw(TextSource source, out int ascent, out int lineHeight)
- {
- // Determine ascent and lineHeight from first character
- ascent = 0;
- lineHeight = 0;
- while (true)
- {
- int codepoint;
- if (!source.GetNextCodepoint(out codepoint))
- {
- break;
- }
- var glyph = GetDynamicGlyph(null, codepoint);
- if (glyph == null)
- {
- continue;
- }
- FontMetrics metrics;
- GetMetrics(glyph.FontSourceIndex, out metrics);
- ascent = metrics.Ascent;
- lineHeight = metrics.LineHeight;
- break;
- }
- source.Reset();
- }
- internal override Bounds InternalTextBounds(TextSource source, Vector2 position, float characterSpacing, float lineSpacing)
- {
- if (source.IsNull)
- return Bounds.Empty;
- var bounds = base.InternalTextBounds(source, position, characterSpacing, lineSpacing);
- bounds.X2 += FontSystem.StrokeAmount * 2;
- return bounds;
- }
- private static int GetKerningsKey(int glyph1, int glyph2)
- {
- return ((glyph1 << 16) | (glyph1 >> 16)) ^ glyph2;
- }
- internal override float GetKerning(FontGlyph glyph, FontGlyph prevGlyph)
- {
- if (!FontSystem.UseKernings)
- {
- return 0.0f;
- }
- var dynamicGlyph = (DynamicFontGlyph)glyph;
- var dynamicPrevGlyph = (DynamicFontGlyph)prevGlyph;
- if (dynamicGlyph.FontSourceIndex != dynamicPrevGlyph.FontSourceIndex)
- {
- return 0.0f;
- }
- var key = GetKerningsKey(prevGlyph.Codepoint, dynamicGlyph.Codepoint);
- var result = 0;
- if (!Kernings.TryGetValue(key, out result))
- {
- var fontSource = FontSystem.FontSources[dynamicGlyph.FontSourceIndex];
- result = fontSource.GetGlyphKernAdvance(prevGlyph.Id, dynamicGlyph.Id, dynamicGlyph.FontSize);
- Kernings[key] = result;
- }
- return result;
- }
- }
- }
|