| 1 | #nullable enable |
| 2 | using SkiaSharp; |
| 3 | |
| 4 | namespace CascadeIDE.Views.SkiaKit; |
| 5 | |
| 6 | /// <summary>Единые настройки Skia-текста: subpixel AA, hinting, снап baseline к пиксельной сетке.</summary> |
| 7 | internal static class SkiaKitFonts |
| 8 | { |
| 9 | public static SKFont CreateUi(float size, bool bold = false, bool italic = false) |
| 10 | { |
| 11 | var weight = bold ? SKFontStyleWeight.Bold : SKFontStyleWeight.Normal; |
| 12 | var slant = italic ? SKFontStyleSlant.Italic : SKFontStyleSlant.Upright; |
| 13 | var font = new SKFont(SKTypeface.FromFamilyName("Segoe UI", new SKFontStyle(weight, SKFontStyleWidth.Normal, slant)), size); |
| 14 | ApplyTextQuality(font); |
| 15 | return font; |
| 16 | } |
| 17 | |
| 18 | public static SKFont CreateMono(float size) |
| 19 | { |
| 20 | var typeface = SKTypeface.FromFamilyName("Cascadia Mono", SKFontStyle.Normal) |
| 21 | ?? SKTypeface.FromFamilyName("Consolas", SKFontStyle.Normal) |
| 22 | ?? SKTypeface.FromFamilyName("Segoe UI", SKFontStyle.Normal); |
| 23 | var font = new SKFont(typeface, size); |
| 24 | ApplyTextQuality(font); |
| 25 | return font; |
| 26 | } |
| 27 | |
| 28 | public static SKPaint CreateTextPaint(SKColor color) => |
| 29 | new() |
| 30 | { |
| 31 | IsAntialias = true, |
| 32 | Color = color, |
| 33 | Style = SKPaintStyle.Fill, |
| 34 | }; |
| 35 | |
| 36 | public static void DrawText( |
| 37 | SKCanvas canvas, |
| 38 | string text, |
| 39 | float x, |
| 40 | float y, |
| 41 | SKTextAlign align, |
| 42 | SKFont font, |
| 43 | SKPaint paint, |
| 44 | float layoutScale = 1f) |
| 45 | { |
| 46 | if (layoutScale > 0f && layoutScale != 1f) |
| 47 | { |
| 48 | x = SnapForScale(x, layoutScale); |
| 49 | y = SnapForScale(y, layoutScale); |
| 50 | } |
| 51 | |
| 52 | canvas.DrawText(text, x, y, align, font, paint); |
| 53 | } |
| 54 | |
| 55 | internal static void ApplyTextQuality(SKFont font) |
| 56 | { |
| 57 | font.Edging = SKFontEdging.SubpixelAntialias; |
| 58 | font.Subpixel = true; |
| 59 | font.Hinting = SKFontHinting.Normal; |
| 60 | font.LinearMetrics = false; |
| 61 | } |
| 62 | |
| 63 | /// <summary>Снап координаты к физическому пикселю при известном layoutScale (RenderScaling).</summary> |
| 64 | internal static float SnapForScale(float logical, float layoutScale) => |
| 65 | MathF.Round(logical * layoutScale) / layoutScale; |
| 66 | } |
| 67 | |