This commit is contained in:
firedef 2022-03-14 16:07:33 +03:00
Родитель 648c7a3fc7
Коммит f23a16d3e6
7 изменённых файлов: 204 добавлений и 20 удалений

Просмотреть файл

@ -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;
}