diff --git a/GraphicsManager/GraphicsManager.csproj b/GraphicsManager/GraphicsManager.csproj index b221b32..d54d7d2 100644 --- a/GraphicsManager/GraphicsManager.csproj +++ b/GraphicsManager/GraphicsManager.csproj @@ -10,7 +10,7 @@ False https://git.jacobtech.com/JacobTech.com/GraphicsManager git - 1.0.0-beta1 + 1.0.1-beta01 diff --git a/GraphicsManager/Objects/Core/Font.cs b/GraphicsManager/Objects/Core/Font.cs index 6a38c40..5e9ea14 100755 --- a/GraphicsManager/Objects/Core/Font.cs +++ b/GraphicsManager/Objects/Core/Font.cs @@ -1,25 +1,48 @@ using System.Diagnostics; using System.Reflection; +using System.Security.Cryptography; using SharpFont; namespace GraphicsManager.Objects.Core; public class Font { - private static List? System = null; private List _Faces = new(); - private Library lib; - - internal Font() + internal static Library lib = new(); + public IReadOnlyList Fonts => _Faces.AsReadOnly(); + internal static Dictionary AllFileFonts = new(); + internal static Dictionary AllMemoryFonts = new(); + internal static List? _SystemPre = null; + private static List AllFonts = new(); + private static bool Backup = false; + + internal void AddSystemFontFace(string path) + { + Console.WriteLine("Added font: " + path); + if (!AllFileFonts.ContainsKey(path)) AllFileFonts.Add(path, new(lib, path, 0)); + if (!_Faces.Contains(AllFileFonts[path])) + { + foreach (Font ft in AllFonts) + { + ft._Faces.Add(AllFileFonts[path]); + } + } + } + + private Font() { Name = null!; Assembly = null!; Embeded = false; - if (lib is null) lib = new(); //TODO add more systemfont dection methods - if (System is null) + if (!Backup) { - System = new(); + AllMemoryFonts.Add(SHA256.HashData(Tools.GetResourceBytes("GraphicsManager.Resources.Fonts.TektonPro-Regular.otf")), new Face(lib, Tools.GetResourceBytes("GraphicsManager.Resources.Fonts.TektonPro-Regular.otf"), 0)); + Backup = true; + } + if (_SystemPre is null) + { + _SystemPre = new(); if (OperatingSystem.IsLinux()) { try @@ -38,7 +61,7 @@ public class Font string[] files = proc.StandardOutput.ReadToEnd().Split($": {Environment.NewLine}"); for (int i = 0; i < files.Length; i++) { - System!.Add(new Face(lib, files[i], 0)); + _SystemPre.Add(files[i]); } } catch @@ -46,11 +69,7 @@ public class Font } } } - - for (int i = 0; i < System!.Count; i++) _Faces.Add(System![i]); - //TODO add a reserved backup font } - public IReadOnlyList Faces => _Faces.AsReadOnly(); public void SetEmbeddedFont(string Font, Assembly? Assembly = null) { _ = Font ?? throw new ArgumentNullException(nameof(Font)); @@ -59,9 +78,14 @@ public class Font byte[] f = (Assembly is null ? Tools.GetResourceBytes(Base + Font) : Tools.GetResourceBytes(Assembly!, $"{Base}{Font}")); - if (HasTopFont) _Faces[0] = new Face(lib, f, 0); - else _Faces.Insert(0, new Face(lib, f, 0)); - HasTopFont = true; + byte[] hash = SHA256.HashData(f); + if (AllMemoryFonts.ContainsKey(hash)) AllMemoryFonts.Add(hash, new(lib, f, 0)); + if (!_Faces.Contains(AllMemoryFonts[hash])) _Faces.Insert(0, AllMemoryFonts[hash]); + else + { + _Faces.Remove(AllMemoryFonts[hash]); + _Faces.Insert(0, AllMemoryFonts[hash]); + } this.Assembly = Assembly; this.Embeded = true; this.Name = Font; @@ -77,17 +101,28 @@ public class Font Name = Font, HasTopFont = true }; + AllFonts.Add(fontclass); string Base = "GraphicsManager.Resources.Fonts."; if (Assembly is not null) Base = string.Empty; byte[] f = (Assembly is null ? Tools.GetResourceBytes(Base + Font) : Tools.GetResourceBytes(Assembly!, $"{Base}{Font}")); - fontclass._Faces.Insert(0, new Face(fontclass.lib, f, 0)); + byte[] hash = SHA256.HashData(f); + if (AllMemoryFonts.ContainsKey(hash)) AllMemoryFonts.Add(hash, new(lib, f, 0)); + fontclass._Faces.Insert(0, AllMemoryFonts[hash]); return fontclass; } - public static Font MakeFontFromSystem(uint PixelHeight = 20) => new Font() { PixelHeight = PixelHeight}; - + private static Font? Cache = null; + public static Font MakeFontFromSystem(uint PixelHeight = 20) + { + if (Cache is null) + { + Cache = new() { PixelHeight = PixelHeight }; + AllFonts.Add(Cache); + } + return Cache; + } public static Font MakeFontFromFile(string Font) { _ = Font ?? throw new ArgumentNullException(nameof(Font)); @@ -98,7 +133,8 @@ public class Font Name = Font, HasTopFont = true }; - fontclass._Faces.Insert(0, new Face(fontclass.lib, Font, 0)); + AllFonts.Add(fontclass); + fontclass._Faces.Insert(0, new Face(lib, Font, 0)); return fontclass; } diff --git a/GraphicsManager/Objects/Core/Texture.cs b/GraphicsManager/Objects/Core/Texture.cs index a2f637c..108556d 100755 --- a/GraphicsManager/Objects/Core/Texture.cs +++ b/GraphicsManager/Objects/Core/Texture.cs @@ -1,12 +1,24 @@ using GraphicsManager.Structs; -using OpenTK.Graphics.OpenGL4; +using OpenTK.Graphics.ES30; using OpenTK.Mathematics; using OpenTK.Windowing.Desktop; using SharpFont; using SixLabors.ImageSharp; using SixLabors.ImageSharp.PixelFormats; using SixLabors.ImageSharp.Processing; +using GL = OpenTK.Graphics.OpenGL4.GL; using Image = SixLabors.ImageSharp.Image; +using PixelFormat = OpenTK.Graphics.OpenGL4.PixelFormat; +using PixelInternalFormat = OpenTK.Graphics.OpenGL4.PixelInternalFormat; +using PixelStoreParameter = OpenTK.Graphics.OpenGL4.PixelStoreParameter; +using PixelType = OpenTK.Graphics.OpenGL4.PixelType; +using TextureMagFilter = OpenTK.Graphics.OpenGL4.TextureMagFilter; +using TextureMinFilter = OpenTK.Graphics.OpenGL4.TextureMinFilter; +using TextureParameterName = OpenTK.Graphics.OpenGL4.TextureParameterName; +using TextureTarget = OpenTK.Graphics.OpenGL4.TextureTarget; +using TextureUnit = OpenTK.Graphics.OpenGL4.TextureUnit; +using TextureWrapMode = OpenTK.Graphics.OpenGL4.TextureWrapMode; +using VertexAttribPointerType = OpenTK.Graphics.OpenGL4.VertexAttribPointerType; namespace GraphicsManager.Objects.Core; @@ -46,35 +58,35 @@ public class Texture { } - internal static Character GetChar(Font l, char charter, Face[] faces) + internal static Character GetChar(Font l, char charter) { - Character t = new(); - for (int i = 0; i < faces.Length; i++) + int last = 0; + for (int i = 0; i < l.Fonts.Count; i++) { try { try { - faces[i].SetPixelSizes(0, l.PixelHeight); + l.Fonts[i].SetPixelSizes(0, l.PixelHeight); + last = i; } catch (Exception e) { continue; } - faces[i].SelectCharmap(Encoding.Unicode); + l.Fonts[i].SelectCharmap(Encoding.Unicode); ushort temp = ((ushort)charter); - if (faces[i].GetCharIndex(temp) == 0) continue; - faces[i].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); - GlyphSlot glyph = faces[i].Glyph; + if (l.Fonts[i].GetCharIndex(temp) == 0) continue; + l.Fonts[i].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); + GlyphSlot glyph = l.Fonts[i].Glyph; FTBitmap bitmap = glyph.Bitmap; - t = new() + return new() { Size = new Vector2(bitmap.Width, bitmap.Rows), Bearing = new Vector2(glyph.BitmapLeft, glyph.BitmapTop), Advance = glyph.Advance.X.Value, }; - return t; } catch (Exception ex) { @@ -82,14 +94,65 @@ public class Texture continue; } } + for (int i = 0; i < Font._SystemPre.Count; i++) + { + try + { + Face tmp = new(Font.lib, Font._SystemPre[i], 0); + try + { + tmp.SetPixelSizes(0, l.PixelHeight); + } + catch (Exception e) + { + tmp.Dispose(); + continue; + } + tmp.SelectCharmap(Encoding.Unicode); + ushort temp2 = ((ushort)charter); + if (tmp.GetCharIndex(temp2) == 0) + { + tmp.Dispose(); + continue; + } + tmp.LoadChar(temp2, LoadFlags.Render, LoadTarget.Normal); + GlyphSlot glyph2 = tmp.Glyph; + FTBitmap bitmap2 = glyph2.Bitmap; + l.AddSystemFontFace(Font._SystemPre[i]); + return new() + { + Size = new Vector2(bitmap2.Width, bitmap2.Rows), + Bearing = new Vector2(glyph2.BitmapLeft, glyph2.BitmapTop), + Advance = glyph2.Advance.X.Value, + }; + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + l.Fonts[last].SetPixelSizes(0, l.PixelHeight); + + l.Fonts[last].SelectCharmap(Encoding.Unicode); + ushort temp22 = ((ushort)charter); + l.Fonts[last].LoadChar(temp22, LoadFlags.Render, LoadTarget.Normal); + GlyphSlot glyph22 = l.Fonts[0].Glyph; + FTBitmap bitmap22 = glyph22.Bitmap; + + return new() + { + Size = new Vector2(bitmap22.Width, bitmap22.Rows), + Bearing = new Vector2(glyph22.BitmapLeft, glyph22.BitmapTop), + Advance = (int)glyph22.Advance.X.Value, + }; - return t; } - internal static Texture TextureForChar(IGLFWGraphicsContext con, Font l, char charter, Face[] faces) + internal static Texture TextureForChar(IGLFWGraphicsContext con, Font l, char charter) { - Texture t = new(); - for (int i = 0; i < faces.Length; i++) + Texture? t = null; + int last = 0; + for (int i = 0; i < l.Fonts.Count; i++) { try { @@ -97,7 +160,8 @@ public class Texture if (Label._characters[con][l].ContainsKey(charter)) return Label._characters[con][l][(ushort)charter].Texture; try { - faces[i].SetPixelSizes(0, l.PixelHeight); + l.Fonts[i].SetPixelSizes(0, l.PixelHeight); + last = i; } catch (Exception e) { @@ -108,13 +172,13 @@ public class Texture GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); GL.ActiveTexture(TextureUnit.Texture0); - faces[i].SelectCharmap(Encoding.Unicode); + l.Fonts[i].SelectCharmap(Encoding.Unicode); ushort temp = ((ushort)charter); - if (faces[i].GetCharIndex(temp) == 0) continue; - faces[i].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); - GlyphSlot glyph = faces[i].Glyph; + if (l.Fonts[i].GetCharIndex(temp) == 0) continue; + l.Fonts[i].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); + GlyphSlot glyph = l.Fonts[i].Glyph; FTBitmap bitmap = glyph.Bitmap; - + t = new(); t.handel = GL.GenTexture(); GL.BindTexture(TextureTarget.Texture2D, t.handel); GL.TexImage2D(TextureTarget.Texture2D, 0, @@ -131,6 +195,7 @@ public class Texture }; Label._characters[con][l].Add(temp, cha); + return t; } catch (Exception ex) { @@ -139,6 +204,91 @@ public class Texture } } + if (t is null) + { + for (int i = 0; i < Font._SystemPre.Count; i++) + { + try + { + Face tmp = new(Font.lib, Font._SystemPre[i], 0); + try + { + tmp.SetPixelSizes(0, l.PixelHeight); + } + catch (Exception e) + { + tmp.Dispose(); + continue; + } + GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); + + GL.ActiveTexture(TextureUnit.Texture0); + tmp.SelectCharmap(Encoding.Unicode); + ushort temp2 = ((ushort)charter); + if (tmp.GetCharIndex(temp2) == 0) + { + tmp.Dispose(); + continue; + } + tmp.LoadChar(temp2, LoadFlags.Render, LoadTarget.Normal); + GlyphSlot glyph2 = tmp.Glyph; + FTBitmap bitmap2 = glyph2.Bitmap; + l.AddSystemFontFace(Font._SystemPre[i]); + t = new(); + t.handel = GL.GenTexture(); + GL.BindTexture(TextureTarget.Texture2D, t.handel); + GL.TexImage2D(TextureTarget.Texture2D, 0, + PixelInternalFormat.R8, bitmap2.Width, bitmap2.Rows, 0, + PixelFormat.Red, PixelType.UnsignedByte, bitmap2.Buffer); + Character cha2 = new() + { + Size = new Vector2(bitmap2.Width, bitmap2.Rows), + Bearing = new Vector2(glyph2.BitmapLeft, glyph2.BitmapTop), + Advance = (int)glyph2.Advance.X.Value, + Texture = t, + }; + + Label._characters[con][l].Add(temp2, cha2); + return t; + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + if (!Label._characters[con].ContainsKey(l)) Label._characters[con].Add(l, new Dictionary()); + if (Label._characters[con][l].ContainsKey(charter)) return Label._characters[con][l][(ushort)charter].Texture; + l.Fonts[last].SetPixelSizes(0, l.PixelHeight); + + + GL.PixelStore(PixelStoreParameter.UnpackAlignment, 1); + + GL.ActiveTexture(TextureUnit.Texture0); + l.Fonts[last].SelectCharmap(Encoding.Unicode); + ushort temp = ((ushort)charter); + l.Fonts[last].LoadChar(temp, LoadFlags.Render, LoadTarget.Normal); + GlyphSlot glyph = l.Fonts[0].Glyph; + FTBitmap bitmap = glyph.Bitmap; + if (t is null) t = new(); + else return t; + t.handel = GL.GenTexture(); + GL.BindTexture(TextureTarget.Texture2D, t.handel); + GL.TexImage2D(TextureTarget.Texture2D, 0, + PixelInternalFormat.R8, bitmap.Width, bitmap.Rows, 0, + PixelFormat.Red, PixelType.UnsignedByte, bitmap.Buffer); + + + Character cha = new() + { + Size = new Vector2(bitmap.Width, bitmap.Rows), + Bearing = new Vector2(glyph.BitmapLeft, glyph.BitmapTop), + Advance = (int)glyph.Advance.X.Value, + Texture = t, + }; + + Label._characters[con][l].Add(temp, cha); + } + return t; } diff --git a/GraphicsManager/Objects/Label.cs b/GraphicsManager/Objects/Label.cs index c0d83d5..a13701d 100755 --- a/GraphicsManager/Objects/Label.cs +++ b/GraphicsManager/Objects/Label.cs @@ -15,7 +15,7 @@ namespace GraphicsManager.Objects; public class Label : IRenderObject { public static readonly Dictionary DefaultTextShader = new(); - public static readonly Font DefaultFont = new(); + public static readonly Font DefaultFont = Font.MakeFontFromSystem(); public ContextMenu? ContextMenu { get; set; } = null; public IParent? Parent { get; private set; } public ObjectAnchor Anchor { get; set; } = ObjectAnchor.Left | ObjectAnchor.Top; @@ -74,7 +74,7 @@ public class Label : IRenderObject character = value[i]; else character = PasswordChar.Value; - Character cha = Texture.GetChar(Font, character, Font.Faces.ToArray()); + Character cha = Texture.GetChar(Font, character); if (character == '\n') { @@ -155,9 +155,10 @@ public class Label : IRenderObject c = PasswordChar.Value; if (!_characters[Window!.Context][Font].ContainsKey(c)) { - var f = Texture.TextureForChar(Window!.Context, Font, c, Font.Faces.ToArray()); + var f = Texture.TextureForChar(Window!.Context, Font, c); f.LoadText(); } + if (!_characters[Window!.Context][Font].ContainsKey(c)) continue; Character ch = _characters[Window!.Context][Font][c]; int maxx = 0; if (c == '\n')