add fonts manager
This commit is contained in:
Родитель
648c7a3fc7
Коммит
f23a16d3e6
|
@ -1,5 +1,8 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using FreeTypeSharp.Native;
|
||||
using SomeChartsAvaloniaExamples.elements;
|
||||
using SomeChartsUi.ui.text;
|
||||
|
||||
namespace SomeChartsAvaloniaExamples;
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@ using SomeChartsUi.elements.other;
|
|||
using SomeChartsUi.themes.colors;
|
||||
using SomeChartsUi.themes.themes;
|
||||
using SomeChartsUi.ui.elements;
|
||||
using SomeChartsUi.ui.text;
|
||||
using SomeChartsUi.utils.shaders;
|
||||
using SomeChartsUiAvalonia.controls.gl;
|
||||
using SomeChartsUiAvalonia.controls.skia;
|
||||
|
@ -198,6 +199,8 @@ public static class ElementsExamples {
|
|||
|
||||
public static void RunPieChart() {
|
||||
AvaloniaRunUtils.RunAfterStart(() => {
|
||||
Fonts.FetchAvailableFontsFromPath("data/");
|
||||
|
||||
AvaloniaGlChartsCanvas canvas = AvaloniaRunUtils.AddGlCanvas();
|
||||
const int rulerOffset = 1_000_000;
|
||||
|
||||
|
|
|
@ -24,10 +24,8 @@ public class PieChart : RenderableBase, IDownsample {
|
|||
|
||||
public PieChart(ChartsCanvas owner) : base(owner) {
|
||||
_textMesh = canvas.factory.CreateTextMesh(this);
|
||||
uint resolution = 32;
|
||||
font = Font.LoadFromPath("data/FiraCode-VariableFont_wght.ttf", renderer.owner, resolution);
|
||||
Font fallbackFont = Font.LoadFromPath("data/NotoSansJP-Regular.otf", renderer.owner, resolution);
|
||||
font.fallbacks.Add(fallbackFont);
|
||||
|
||||
font = canvas.GetDefaultFont();
|
||||
}
|
||||
|
||||
public float downsampleMultiplier { get; set; } = .5f;
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using SomeChartsUi.backends;
|
||||
using SomeChartsUi.ui.canvas.controls;
|
||||
using SomeChartsUi.ui.layers;
|
||||
using SomeChartsUi.ui.text;
|
||||
|
||||
namespace SomeChartsUi.ui.canvas;
|
||||
|
||||
|
@ -9,6 +10,9 @@ public class ChartsCanvas {
|
|||
public readonly ChartCanvasRenderer renderer;
|
||||
public readonly ChartCanvasTransform transform;
|
||||
|
||||
public List<Font> fallbackFonts = new();
|
||||
public Font? defaultFont;
|
||||
|
||||
public ChartCanvasControllerBase? controller;
|
||||
|
||||
public TimeSpan renderTime;
|
||||
|
@ -20,6 +24,7 @@ public class ChartsCanvas {
|
|||
backend.renderer = renderer;
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
private List<CanvasLayer> layers => renderer.layers;
|
||||
private Dictionary<string, int> layerNames => renderer.layerNames;
|
||||
|
||||
|
@ -38,4 +43,36 @@ public class ChartsCanvas {
|
|||
|
||||
public CanvasLayer? GetLayer(string name) => layerNames.TryGetValue(name, out int i) ? layers[i] : null;
|
||||
public CanvasLayer GetLayer(int i) => layers[i];
|
||||
|
||||
public void LoadDefaultFonts() {
|
||||
// some asian fonts
|
||||
AddFallbackFromName("NotoSansJP");
|
||||
|
||||
defaultFont ??= LoadAny("OpenSans", "Comfortaa", "NotoSans");
|
||||
}
|
||||
|
||||
private void AddFallbackFromName(string name) {
|
||||
Font? f = Font.TryLoad(name, this);
|
||||
if (f == null) return;
|
||||
fallbackFonts.Add(f);
|
||||
}
|
||||
|
||||
private void AddFallbackFromPath(string path) {
|
||||
fallbackFonts.Add(Font.LoadFromPath(path, this));
|
||||
}
|
||||
|
||||
private Font LoadAny(params string[] names) {
|
||||
Font? f;
|
||||
foreach (string name in names) {
|
||||
f = Font.TryLoad(name, this);
|
||||
if (f != null) return f.WithFallbacks(fallbackFonts);
|
||||
}
|
||||
|
||||
throw new FileNotFoundException($"not found any of fonts: \n{string.Join("\n", names)}");
|
||||
}
|
||||
|
||||
public Font GetDefaultFont() {
|
||||
if (defaultFont == null) LoadDefaultFonts();
|
||||
return defaultFont!;
|
||||
}
|
||||
}
|
|
@ -4,27 +4,59 @@ using SomeChartsUi.ui.canvas;
|
|||
|
||||
namespace SomeChartsUi.ui.text;
|
||||
|
||||
public class Font {
|
||||
public string family;
|
||||
public bool isBold;
|
||||
public bool isExpanded;
|
||||
public bool isItalic;
|
||||
public FontTextures textures;
|
||||
public List<Font> fallbacks = new();
|
||||
public record Font(string name, bool isBold, bool isItalic, bool isExpanded, FontTextures textures, ChartsCanvas _owner) {
|
||||
private static List<Font> _loadedFonts = new();
|
||||
|
||||
public Font(string family, bool isBold, bool isItalic, bool isExpanded, FontTextures textures) {
|
||||
this.family = family;
|
||||
this.isBold = isBold;
|
||||
this.isItalic = isItalic;
|
||||
this.isExpanded = isExpanded;
|
||||
this.textures = textures;
|
||||
}
|
||||
public string name = name;
|
||||
public bool isBold = isBold;
|
||||
public bool isExpanded = isExpanded;
|
||||
public bool isItalic = isItalic;
|
||||
public FontTextures textures = textures;
|
||||
public List<Font> fallbacks = new();
|
||||
private ChartsCanvas _owner = _owner;
|
||||
|
||||
public static Font LoadFromPath(string path, ChartsCanvas canvas, uint resolution = 32) {
|
||||
using FileStream fs = new(path, FileMode.Open);
|
||||
string name = Path.GetFileName(path)[..^4];
|
||||
Font? existingFont = TryGetLoadedFont(name);
|
||||
if (existingFont != null) return existingFont;
|
||||
|
||||
using FileStream fs = new(path, FileMode.Open, FileAccess.Read);
|
||||
FT.FT_New_Face(FreeType.ftLib.Native, path, 0, out IntPtr face).CheckError();
|
||||
FreeTypeFaceFacade faceF = new(FreeType.ftLib, face);
|
||||
|
||||
return new("todo", false, false, false, canvas.factory.CreateFontTextureAtlas(faceF, resolution));
|
||||
Font font = new(name, false, false, false, canvas.factory.CreateFontTextureAtlas(faceF, resolution), canvas);
|
||||
_loadedFonts.Add(font);
|
||||
return font;
|
||||
}
|
||||
|
||||
public static Font? TryGetLoadedFont(string name) => _loadedFonts.FirstOrDefault(v => v.name == name);
|
||||
|
||||
public static Font? TryLoad(string name, ChartsCanvas canvas, uint resolution = 32) {
|
||||
Font? existingFont = TryGetLoadedFont(name);
|
||||
if (existingFont != null) return existingFont;
|
||||
|
||||
string? path = Fonts.TryFind(name);
|
||||
return path == null ? null : LoadFromPath(path, canvas, resolution);
|
||||
}
|
||||
|
||||
public Font WithFallback(Font fallback) {
|
||||
fallbacks.Add(fallback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Font WithFallbacks(IEnumerable<Font> fallback) {
|
||||
fallbacks.AddRange(fallback);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Font WithFallbackPath(string path) {
|
||||
fallbacks.Add(LoadFromPath(path, _owner));
|
||||
return this;
|
||||
}
|
||||
|
||||
public Font WithFallbackName(string name) {
|
||||
Font? fallback = TryLoad(name, _owner);
|
||||
if (fallback != null) fallbacks.Add(fallback);
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
using FreeTypeSharp.Native;
|
||||
using SomeChartsUi.ui.canvas;
|
||||
|
||||
namespace SomeChartsUi.ui.text;
|
||||
|
||||
public class FontFamily {
|
||||
public List<FontFamilyItem> fonts = new();
|
||||
}
|
||||
|
||||
public class FontFamilyItem {
|
||||
private Font? _font;
|
||||
|
||||
public string name;
|
||||
public string path;
|
||||
|
||||
public FontFamilyItem(string name, string path) {
|
||||
this.name = name;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public Font GetFont(ChartsCanvas canvas) {
|
||||
if (_font != null) return _font;
|
||||
_font = Font.LoadFromPath(path, canvas);
|
||||
|
||||
return _font;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
namespace SomeChartsUi.ui.text;
|
||||
|
||||
public static class Fonts {
|
||||
public static List<InstalledFontData> availableFonts;
|
||||
public static HashSet<string> loadedPaths = new();
|
||||
|
||||
static Fonts() {
|
||||
FetchAvailableFonts();
|
||||
}
|
||||
|
||||
private static void FetchAvailableFonts() {
|
||||
availableFonts = new();
|
||||
|
||||
List<string> paths = new();
|
||||
paths.Add(Environment.GetFolderPath(Environment.SpecialFolder.Fonts));
|
||||
|
||||
// Linux additional paths for fonts
|
||||
// '~/.fonts' already added using environment special folder
|
||||
if (Environment.OSVersion.Platform == PlatformID.Unix) {
|
||||
paths.Add("/usr/share/fonts");
|
||||
paths.Add("/usr/local/share/fonts");
|
||||
}
|
||||
|
||||
foreach (string path in paths)
|
||||
FetchAvailableFontsFromPath(path);
|
||||
}
|
||||
|
||||
public static void FetchAvailableFontsFromPath(string path) {
|
||||
if (!Directory.Exists(path)) return;
|
||||
if (loadedPaths.Contains(path)) return;
|
||||
|
||||
string[] ttfPaths = Directory.GetFiles(path, "*.ttf", SearchOption.AllDirectories);
|
||||
string[] otfPaths = Directory.GetFiles(path, "*.otf", SearchOption.AllDirectories);
|
||||
|
||||
AddFonts(ttfPaths);
|
||||
AddFonts(otfPaths);
|
||||
|
||||
loadedPaths.Add(path);
|
||||
}
|
||||
|
||||
public static void AddFonts(string[] paths) {
|
||||
foreach (string path in paths) AddFont(path);
|
||||
}
|
||||
|
||||
public static void AddFont(string path) {
|
||||
string name = Path.GetFileName(path)[..^4];
|
||||
AddFont(name, path);
|
||||
}
|
||||
|
||||
public static void AddFont(string name, string path) {
|
||||
if (availableFonts.FindIndex(v => string.Equals(v.path, path, StringComparison.CurrentCultureIgnoreCase)) != -1) return;
|
||||
availableFonts.Add(new(name, path));
|
||||
}
|
||||
|
||||
public static string? TryFindExact(string name) => availableFonts.FirstOrDefault(v => string.Equals(v.name, name, StringComparison.CurrentCultureIgnoreCase))?.path;
|
||||
|
||||
public static string? TryFind(string name) {
|
||||
string? result = TryFindExact(name);
|
||||
if (result != null || name.Contains('-')) return result;
|
||||
|
||||
result = TryFindExact($"{name}-regular");
|
||||
if (result != null) return result;
|
||||
|
||||
return availableFonts.FirstOrDefault(v => string.Equals(v.name.Split('-', 2)[0], name, StringComparison.CurrentCultureIgnoreCase))?.path;
|
||||
}
|
||||
|
||||
public static FontFamily GetFamily(string name) {
|
||||
name = name.Split('-', 2)[0];
|
||||
FontFamily family = new();
|
||||
|
||||
IEnumerable<InstalledFontData> fonts = availableFonts.Where(v => string.Equals(v.name.Split('-', 2)[0], name, StringComparison.CurrentCultureIgnoreCase));
|
||||
foreach ((string fName, string fPath) in fonts) {
|
||||
FontFamilyItem item = new(fName, fPath);
|
||||
family.fonts.Add(item);
|
||||
}
|
||||
|
||||
return family;
|
||||
}
|
||||
}
|
||||
|
||||
public record InstalledFontData(string name, string path) {
|
||||
public string name = name;
|
||||
public string path = path;
|
||||
}
|
Загрузка…
Ссылка в новой задаче