// COPYRIGHT (C) Tom. ALL RIGHTS RESERVED. // THE AntdUI PROJECT IS AN WINFORM LIBRARY LICENSED UNDER THE Apache-2.0 License. // LICENSED UNDER THE Apache License, VERSION 2.0 (THE "License") // YOU MAY NOT USE THIS FILE EXCEPT IN COMPLIANCE WITH THE License. // YOU MAY OBTAIN A COPY OF THE LICENSE AT // // http://www.apache.org/licenses/LICENSE-2.0 // // UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, SOFTWARE // DISTRIBUTED UNDER THE LICENSE IS DISTRIBUTED ON AN "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. // SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING PERMISSIONS AND // LIMITATIONS UNDER THE License. // GITEE: https://gitee.com/antdui/AntdUI // GITHUB: https://github.com/AntdUI/AntdUI // CSDN: https://blog.csdn.net/v_132 // QQ: 17379620 using System; using System.Collections.Generic; using System.Drawing; namespace AntdUI { /// /// 修正文本渲染 /// public static class CorrectionTextRendering { internal static Dictionary tmpChinese = new Dictionary(); internal static Dictionary tmpEnglish = new Dictionary(); static bool enable = false; static string defTextChinese = "不"; static string defTextEnglish = "X"; static int defFontSize = 20; internal static void Set(string familie) { enable = true; using (var font = new Font(familie, defFontSize)) { int size = Helper.GDI(g => { return (int)(g.MeasureString(defTextChinese, font).Height * 1.2F); }); float valChinese = GetFontOffset(font, size, defTextChinese); float valEnglish = GetFontOffset(font, size, defTextEnglish); if (valChinese <= 1 && valChinese >= -1) { //误差 1以内可以接受 lock (tmpChinese) { if (tmpChinese.ContainsKey(familie)) tmpChinese.Remove(familie); } } else { var oy = valChinese / defFontSize; lock (tmpChinese) { if (tmpChinese.ContainsKey(familie)) tmpChinese[familie] = oy; else tmpChinese.Add(familie, oy); } } if (valEnglish <= 1 && valEnglish >= -1) { //误差 1以内可以接受 lock (tmpEnglish) { if (tmpEnglish.ContainsKey(familie)) tmpEnglish.Remove(familie); } } else { var oy = valEnglish / defFontSize; lock (tmpEnglish) { if (tmpEnglish.ContainsKey(familie)) tmpEnglish[familie] = oy; else tmpEnglish.Add(familie, oy); } } } } static float GetFontOffset(Font font, int size, string text) { float cs = size / 2F; using (var s_f = Helper.SF_NoWrap()) { using (var bmp = new Bitmap(size, size)) { using (var g_o = Graphics.FromImage(bmp).High()) { g_o.DrawString(text, font, Brushes.Black, new Rectangle(0, 0, bmp.Width, bmp.Height), s_f); } TextRealY(bmp, out var ry, out var rheight); float ready = ry + rheight / 2F; return cs - ready; } } } /// /// 获取文本真实Y高度 /// /// 图片 /// Y /// 高度 public static void TextRealY(Bitmap bmp, out int y, out int h) { y = TextRealY(bmp); h = TextRealHeight(bmp, y); } static int TextRealY(Bitmap bmp) { for (int y = 0; y < bmp.Height; y++) { for (int x = 0; x < bmp.Width; x++) { if (bmp.GetPixel(x, y).A > 0) return y - 1; } } return 0; } static int TextRealHeight(Bitmap bmp, int _y) { for (int y = bmp.Height - 1; y > _y; y--) { int count = 0; for (int x = 0; x < bmp.Width; x++) { if (bmp.GetPixel(x, y).A > 0) count++; } if (count > 0) return (y + 1) - _y; } return bmp.Height - _y; } #region 渲染字体 public static void DrawStr(this Graphics g, string? s, Font font, Brush brush, RectangleF layoutRectangle) { CORE(font, s, ref layoutRectangle); g.DrawString(s, font, brush, layoutRectangle, null); } public static void DrawStr(this Graphics g, string? s, Font font, Brush brush, Rectangle layoutRectangle, StringFormat? format) { CORE(font, s, ref layoutRectangle); g.DrawString(s, font, brush, layoutRectangle, format); } public static void DrawStr(this Graphics g, string? s, Font font, Brush brush, RectangleF layoutRectangle, StringFormat? format) { CORE(font, s, ref layoutRectangle); g.DrawString(s, font, brush, layoutRectangle, format); } #endregion #region 误差核心 static void CORE(Font font, string? text, ref RectangleF layoutRectangle) { if (enable && text != null) { if (text.ContainsChinese()) { if (tmpChinese.TryGetValue(font.Name, out var oy)) layoutRectangle.Offset(0, oy * font.Size); } else if (tmpEnglish.TryGetValue(font.Name, out var oy)) layoutRectangle.Offset(0, oy * font.Size); } } static void CORE(Font font, string? text, ref Rectangle layoutRectangle) { if (enable && text != null) { if (text.ContainsChinese()) { if (tmpChinese.TryGetValue(font.Name, out var oy)) layoutRectangle.Offset(0, (int)Math.Round(oy * font.Size)); } else if (tmpEnglish.TryGetValue(font.Name, out var oy)) layoutRectangle.Offset(0, (int)Math.Round(oy * font.Size)); } } static bool ContainsChinese(this string input) { return System.Text.RegularExpressions.Regex.IsMatch(input, @"[\u4e00-\u9fa5]"); } #endregion } }