public override void DrawStringBaseline(string fontName, float size, string text, float x, float y, Color4 color, bool underline = false, TextShadow shadow = default) { if (string.IsNullOrEmpty(fontName)) { throw new InvalidOperationException("fontName null"); } var pixels = size * (96.0f / 72.0f); drawX = int.MaxValue; drawY = int.MaxValue; StringInfo info = new StringInfo() { Underline = underline ? 1 : 0 }; var hash = info.MakeHash(fontName, text); PGQuad[] quads = null; for (int i = 0; i < cachedStrings.Count; i++) { if (cachedStrings[i].Hash == hash && Math.Abs(cachedStrings[i].Size - size) < 0.001f) { quads = cachedStrings[i].Quads; break; } } if (quads == null) { using var textConv = new UTF8ZHelper(stackalloc byte[256], text); using var fontConv = new UTF8ZHelper(stackalloc byte[256], fontName); fixed(byte *tC = &textConv.ToUTF8Z().GetPinnableReference(), tF = &fontConv.ToUTF8Z().GetPinnableReference()) { pg_drawstring(ctx, (IntPtr)tC, (IntPtr)tF, pixels, TextAlignment.Left, underline ? 1 : 0, 1, 1, 1, 1, (Color4 *)0, (float *)0, (float *)0); } quads = lastQuads; lastQuads = null; cachedStrings.Enqueue(new StringResults() { Hash = hash, Size = size, Quads = quads }); } drawX = (int)x; drawY = (int)y; if (shadow.Enabled) { for (int i = 0; i < quads.Length; i++) { var q = quads[i]; q.Dest.X += drawX + 2; q.Dest.Y += drawY + 2; var t = textures[(int)q.Texture->UserData]; ren.Draw(t, q.Source, q.Dest, shadow.Color); } } for (int i = 0; i < quads.Length; i++) { var q = quads[i]; q.Dest.X += drawX; q.Dest.Y += drawY; var t = textures[(int)q.Texture->UserData]; ren.Draw(t, q.Source, q.Dest, color); } }