Remove old test projects.
This commit is contained in:
parent
41b7bebba5
commit
8d2afd0955
@ -1,83 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Quik.FreeType
|
||||
{
|
||||
public static class FT
|
||||
{
|
||||
private const string freetype2 = "freetype";
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_Init_FreeType")]
|
||||
public static extern FTError InitFreeType(out FTLibrary library);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_Done_FreeType")]
|
||||
public static extern FTError DoneFreeType(FTLibrary library);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_New_Face")]
|
||||
public static extern FTError NewFace(
|
||||
FTLibrary library,
|
||||
[MarshalAs(UnmanagedType.LPStr)] string path,
|
||||
long faceIndex,
|
||||
out FTFace face);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_New_Memory_Face")]
|
||||
public static extern FTError NewMemoryFace(
|
||||
FTLibrary library,
|
||||
IntPtr buffer,
|
||||
long size,
|
||||
long faceIndex,
|
||||
out FTFace face);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_New_Memory_Face")]
|
||||
public static extern FTError NewMemoryFace(
|
||||
FTLibrary library,
|
||||
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] byte[] buffer,
|
||||
long size,
|
||||
long faceIndex,
|
||||
out FTFace face);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_New_Memory_Face")]
|
||||
public static extern FTError NewMemoryFace(
|
||||
FTLibrary library,
|
||||
[MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] Span<byte> buffer,
|
||||
long size,
|
||||
long faceIndex,
|
||||
out FTFace face);
|
||||
|
||||
// public static extern FTError OpenFace(FTLibrary library, in FTOpenArgs args, long faceIndex, out FTFace face);
|
||||
|
||||
// [DllImport(freetype2, EntryPoint = "FT_Attach_File")]
|
||||
// public static extern FTError AttachFile(FTFace face, [MarshalAs(UnmanagedType.LPStr)] string filePathName);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_Set_Char_Size")]
|
||||
public static extern FTError SetCharSize(
|
||||
FTFace library,
|
||||
long charWidth,
|
||||
long charHeight,
|
||||
uint horizontalResolution,
|
||||
uint verticalResolution);
|
||||
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_Get_Char_Index")]
|
||||
public static extern uint GetCharIndex(FTFace face, ulong charCode);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_Load_Glyph")]
|
||||
public static extern FTError LoadGlyph(FTFace face, uint charIndex, FTLoadFlags flags);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_Render_Glyph")]
|
||||
public static extern FTError RenderGlyph(FTGlyphSlot slot, FTRenderMode mode);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_Done_Face")]
|
||||
public static extern FTError DoneFace(FTFace face);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_Bitmap_Init")]
|
||||
public static extern void BitmapInit(ref FTBitmap bitmap);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_Bitmap_Convert")]
|
||||
public static extern void BitmapConvert(FTLibrary library, in FTBitmap source, ref FTBitmap target,
|
||||
int alignment);
|
||||
|
||||
[DllImport(freetype2, EntryPoint = "FT_Bitmap_Done")]
|
||||
public static extern void BitmapDone(FTLibrary library, ref FTBitmap bitmap);
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
namespace Quik.FreeType
|
||||
{
|
||||
public enum FTError : int
|
||||
{
|
||||
None = 0,
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Quik.FreeType
|
||||
{
|
||||
[Flags]
|
||||
public enum FTLoadFlags
|
||||
{
|
||||
Default = 0,
|
||||
NoScale = 1 << 0,
|
||||
NoHinting = 1 << 1,
|
||||
Render = 1 << 2,
|
||||
NoBitmap = 1 << 3,
|
||||
VerticalLayout = 1 << 4,
|
||||
ForceAutoHint = 1 << 5,
|
||||
CropBitmap = 1 << 6,
|
||||
Pedantic = 1 << 7,
|
||||
IgnoreGlobalAdvanceWidth = 1 << 9,
|
||||
NoRecurse = 1 << 10,
|
||||
IgnoreTransform = 1 << 11,
|
||||
Monochrome= 1 << 12,
|
||||
LinearDesign = 1 << 13,
|
||||
SbitsOnly = 1 << 14,
|
||||
NoAutoHint = 1 << 15,
|
||||
Color = 1 << 20,
|
||||
ComputeMetrics = 1 << 21,
|
||||
BitmapMetricsOnly = 1 << 22
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
namespace Quik.FreeType
|
||||
{
|
||||
public enum FTRenderMode
|
||||
{
|
||||
Normal = 0,
|
||||
Light,
|
||||
Mono,
|
||||
Lcd,
|
||||
LcdVertical,
|
||||
Sdf
|
||||
}
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Quik.FreeType
|
||||
{
|
||||
[Flags]
|
||||
public enum FaceFlag : int
|
||||
{
|
||||
Scalable = 1 << 0,
|
||||
FixedSizes = 1 << 1,
|
||||
FixedWidth = 1 << 2,
|
||||
Sfnt = 1 << 3,
|
||||
Horizontal = 1 << 4,
|
||||
Vertical = 1 << 5,
|
||||
Kerning = 1 << 6,
|
||||
FastGlyphs = 1 << 7,
|
||||
MultipleMasters = 1 << 8,
|
||||
GlyphNames = 1 << 9,
|
||||
ExternalStream = 1 << 10,
|
||||
Hinter = 1 << 11,
|
||||
CidKeyed = 1 << 12,
|
||||
Tricky = 1 << 13,
|
||||
Color = 1 << 14,
|
||||
Variation = 1 << 15,
|
||||
Svg = 1 << 16,
|
||||
Sbix = 1 << 17,
|
||||
SbixOverlay = 1 << 18
|
||||
}
|
||||
}
|
@ -1,181 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Quik.Typography;
|
||||
|
||||
namespace Quik.FreeType
|
||||
{
|
||||
public class FreeTypeFont : QuikFont, IDisposable
|
||||
{
|
||||
|
||||
private FreeTypeFontManager _owner;
|
||||
private FTLibrary _library;
|
||||
private FTFace _face;
|
||||
private List<Atlas> _textures = new List<Atlas>();
|
||||
private Dictionary<int, GlyphEntry> _entries = new Dictionary<int, GlyphEntry>();
|
||||
|
||||
public override float Ascender => _face.ScaledSize.Ascender / 64f;
|
||||
public override float Descender => _face.ScaledSize.Descender / 64f;
|
||||
|
||||
internal FreeTypeFont(FreeTypeFontManager owner, FileInfo file, QuikFontStyle style)
|
||||
{
|
||||
Style = style;
|
||||
_owner = owner;
|
||||
_library = owner._library;
|
||||
|
||||
if (FT.NewFace(_library, file.FullName, 0, out _face) != FTError.None)
|
||||
{
|
||||
throw new Exception("Could not load font file.");
|
||||
}
|
||||
|
||||
FT.SetCharSize(_face, 0, (long)(style.Size * 64), 96, 96);
|
||||
|
||||
_textures.Add(new Atlas(owner.Context.TextureManager, _library));
|
||||
}
|
||||
|
||||
public override QuikFontStyle Style { get; }
|
||||
|
||||
public override bool HasCharacter(int character)
|
||||
{
|
||||
return FT.GetCharIndex(_face, (ulong)character) != 0;
|
||||
}
|
||||
|
||||
public override void GetCharacter(int character, out QuikTexture texture, out QuikGlyph glyph)
|
||||
{
|
||||
GlyphEntry entry;
|
||||
|
||||
if (_entries.TryGetValue(character, out entry))
|
||||
{
|
||||
texture = entry.Atlas.Texture;
|
||||
glyph = entry.Metrics;
|
||||
return;
|
||||
}
|
||||
|
||||
entry = new GlyphEntry();
|
||||
entry.Character = character;
|
||||
|
||||
uint index = FT.GetCharIndex(_face, (ulong) character);
|
||||
FT.LoadGlyph(_face, index, FTLoadFlags.Default);
|
||||
FT.RenderGlyph(_face.Glyph, FTRenderMode.Normal);
|
||||
|
||||
entry.Atlas = _textures[_textures.Count - 1];
|
||||
if (!entry.Atlas.CanFit(_face.Glyph))
|
||||
{
|
||||
entry.Atlas = new Atlas(_owner.Context.TextureManager, _library);
|
||||
_textures.Add(entry.Atlas);
|
||||
}
|
||||
entry.Atlas.AttachGlyph(_face.Glyph, out QRectangle uvs);
|
||||
|
||||
entry.Metrics = new QuikGlyph(
|
||||
character,
|
||||
uvs,
|
||||
new QVec2(_face.Glyph.Metrics.Width / 64f, _face.Glyph.Metrics.Height / 64f),
|
||||
new QVec2(_face.Glyph.Metrics.HorizontalBearingX / 64f, _face.Glyph.Metrics.HorizontalBearingY / 64f),
|
||||
new QVec2(_face.Glyph.Metrics.VerticalBearingX / 64f , _face.Glyph.Metrics.VerticalBearingY / 64f),
|
||||
new QVec2(_face.Glyph.Metrics.HorizontalAdvance / 64f, _face.Glyph.Metrics.VerticalAdvance / 64f));
|
||||
|
||||
_entries[character] = entry;
|
||||
|
||||
texture = entry.Atlas.Texture;
|
||||
glyph = entry.Metrics;
|
||||
}
|
||||
|
||||
public bool IsDisposed { get; private set; } = false;
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (IsDisposed) return;
|
||||
|
||||
if (disposing)
|
||||
{
|
||||
foreach (Atlas atlas in _textures)
|
||||
{
|
||||
atlas.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
FT.DoneFace(_face);
|
||||
IsDisposed = true;
|
||||
}
|
||||
|
||||
public void Dispose() => Dispose(true);
|
||||
|
||||
private class Atlas : IDisposable
|
||||
{
|
||||
public QuikTexture Texture;
|
||||
|
||||
private QVec2 _pointer = new QVec2();
|
||||
private float _verticalAdvance = 0;
|
||||
private FTLibrary _ft;
|
||||
private FTBitmap _bitmap;
|
||||
|
||||
public Atlas(IQuikTextureManager textureManager, FTLibrary ft)
|
||||
{
|
||||
Texture = textureManager.CreateTexture(
|
||||
new QVec2(4096, 4096),
|
||||
false,
|
||||
QuikImageFormat.RgbaU8);
|
||||
|
||||
FT.BitmapInit(ref _bitmap);
|
||||
_ft = ft;
|
||||
}
|
||||
|
||||
public bool CanFit(in FTGlyphSlot slot)
|
||||
{
|
||||
// FIXME: the atlas will overflow.
|
||||
return true;
|
||||
}
|
||||
|
||||
public void AttachGlyph(in FTGlyphSlot slot, out QRectangle UVs)
|
||||
{
|
||||
FT.BitmapConvert(_ft, slot.Bitmap, ref _bitmap, 1);
|
||||
|
||||
QRectangle position =
|
||||
new QRectangle(
|
||||
_pointer + new QVec2(_bitmap.Width + 1, _bitmap.Rows + 1),
|
||||
_pointer + new QVec2(1, 1));
|
||||
|
||||
Texture.SubImage(
|
||||
_bitmap.Buffer,
|
||||
QuikImageFormat.AlphaU8,
|
||||
position,
|
||||
0,
|
||||
1);
|
||||
|
||||
_pointer.X += _bitmap.Width + 2;
|
||||
_verticalAdvance = Math.Max(_verticalAdvance, slot.Bitmap.Rows + 2);
|
||||
|
||||
UVs = new QRectangle(
|
||||
position.Right / 4096,
|
||||
position.Bottom / 4096,
|
||||
position.Left / 4096,
|
||||
position.Top / 4096
|
||||
);
|
||||
}
|
||||
|
||||
private bool _isDisposed = false;
|
||||
|
||||
public void Dispose(bool disposing)
|
||||
{
|
||||
if (_isDisposed) return;
|
||||
if (disposing)
|
||||
{
|
||||
Texture.Dispose();
|
||||
}
|
||||
FT.BitmapDone(_ft, ref _bitmap);
|
||||
_isDisposed = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
private class GlyphEntry
|
||||
{
|
||||
public int Character;
|
||||
public Atlas Atlas;
|
||||
public QuikGlyph Metrics;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Quik.Typography;
|
||||
|
||||
namespace Quik.FreeType
|
||||
{
|
||||
public class FreeTypeFontManager : IQuikFontManager, IDisposable
|
||||
{
|
||||
public QuikContext Context { get; set; }
|
||||
|
||||
internal FTLibrary _library;
|
||||
private Dictionary<string, FontCacheEntry> _cache = new Dictionary<string, FontCacheEntry>();
|
||||
private Dictionary<QuikFontStyle, FreeTypeFont> _fonts= new Dictionary<QuikFontStyle, FreeTypeFont>();
|
||||
|
||||
public event FreeTypeFontManagerFontFinder FontNotFound;
|
||||
|
||||
public FreeTypeFontManager()
|
||||
{
|
||||
FT.InitFreeType(out _library);
|
||||
|
||||
// FIXME: There are operating system specific ways to achieve this. This is
|
||||
// definitely not the best way to do this.
|
||||
|
||||
// Scan the fonts folder and build up a font cache.
|
||||
string path = Environment.GetFolderPath(Environment.SpecialFolder.Fonts);
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
if (OperatingSystem.IsLinux())
|
||||
{
|
||||
path = "/usr/share/fonts";
|
||||
}
|
||||
else if (OperatingSystem.IsWindows())
|
||||
{
|
||||
path = Path.Combine(
|
||||
Environment.GetFolderPath(Environment.SpecialFolder.Windows),
|
||||
"Fonts");
|
||||
}
|
||||
// For macOS I don't know. Too bad.
|
||||
}
|
||||
|
||||
DirectoryInfo directory = new DirectoryInfo(path);
|
||||
ScanDirectoryForFonts(directory);
|
||||
}
|
||||
|
||||
private void ScanDirectoryForFonts(DirectoryInfo directory)
|
||||
{
|
||||
foreach (FileSystemInfo node in directory.GetFileSystemInfos())
|
||||
{
|
||||
if (node.Attributes.HasFlag(FileAttributes.Directory))
|
||||
{
|
||||
ScanDirectoryForFonts(node as DirectoryInfo);
|
||||
}
|
||||
else
|
||||
{
|
||||
ScanFileForFonts(node as FileInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ScanFileForFonts(FileInfo file)
|
||||
{
|
||||
if (file is null) return;
|
||||
|
||||
if (FT.NewFace(_library, file.FullName, 0, out FTFace face) == FTError.None)
|
||||
{
|
||||
FontCacheEntry entry;
|
||||
string name = face.FamilyName;
|
||||
string style = face.StyleName;
|
||||
|
||||
if (name is null)
|
||||
goto done_face;
|
||||
|
||||
if (_cache.ContainsKey(name))
|
||||
{
|
||||
entry = _cache[name];
|
||||
}
|
||||
else
|
||||
{
|
||||
entry = new FontCacheEntry();
|
||||
entry.Family = name;
|
||||
_cache[name] = entry;
|
||||
}
|
||||
|
||||
switch (style.ToLowerInvariant())
|
||||
{
|
||||
case "regular":
|
||||
entry.Regular = file;
|
||||
break;
|
||||
case "bold":
|
||||
entry.Bold = file;
|
||||
break;
|
||||
case "italic":
|
||||
entry.Italic = file;
|
||||
break;
|
||||
}
|
||||
|
||||
done_face:
|
||||
FT.DoneFace(face);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
// Nothing to do.
|
||||
}
|
||||
|
||||
public QuikFont GetFont(QuikFontStyle fontStyle)
|
||||
{
|
||||
FreeTypeFont font;
|
||||
|
||||
if (_fonts.TryGetValue(fontStyle, out font))
|
||||
return font;
|
||||
|
||||
FileInfo file = FindFont(fontStyle);
|
||||
if (file == null)
|
||||
{
|
||||
FontNotFound?.Invoke(fontStyle, ref file);
|
||||
if (file == null)
|
||||
{
|
||||
throw new Exception("Could not find the font you are looking for.");
|
||||
}
|
||||
}
|
||||
|
||||
font = new FreeTypeFont(this, file, fontStyle);
|
||||
_fonts.Add(fontStyle, font);
|
||||
return font;
|
||||
}
|
||||
|
||||
private FileInfo FindFont(QuikFontStyle fontStyle)
|
||||
{
|
||||
FontCacheEntry entry;
|
||||
if (_cache.TryGetValue(fontStyle.Family, out entry))
|
||||
{
|
||||
switch (fontStyle.Type)
|
||||
{
|
||||
case QuikFontType.Normal:
|
||||
return entry.Regular;
|
||||
case QuikFontType.Bold:
|
||||
return entry.Bold;
|
||||
case QuikFontType.Italic:
|
||||
return entry.Italic;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
// IDisposable
|
||||
private void ReleaseUnmanagedResources()
|
||||
{
|
||||
FT.DoneFreeType(_library);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ReleaseUnmanagedResources();
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
~FreeTypeFontManager()
|
||||
{
|
||||
ReleaseUnmanagedResources();
|
||||
}
|
||||
|
||||
private class FontCacheEntry
|
||||
{
|
||||
public string Family;
|
||||
public FileInfo Regular;
|
||||
public FileInfo Bold;
|
||||
public FileInfo Italic;
|
||||
}
|
||||
}
|
||||
|
||||
public delegate void FreeTypeFontManagerFontFinder(QuikFontStyle style, ref FileInfo info);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<LangVersion>7.3</LangVersion>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Quik\Quik.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,180 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Quik.FreeType
|
||||
{
|
||||
public struct FTLibrary
|
||||
{
|
||||
private IntPtr _handle;
|
||||
public IntPtr Handle => _handle;
|
||||
}
|
||||
|
||||
public unsafe struct FTFace
|
||||
{
|
||||
private IntPtr _handle;
|
||||
public IntPtr Handle => _handle;
|
||||
private unsafe FTFaceInternal* Ptr => (FTFaceInternal*)_handle;
|
||||
|
||||
public long NumberOfGlyphs => Ptr->NumberOfGlyphs;
|
||||
public long FaceIndex => Ptr->FaceIndex;
|
||||
public FaceFlag FaceFlags => (FaceFlag)Ptr->FaceFlags;
|
||||
public long StyleFlags => Ptr->StyleFlags;
|
||||
public string FamilyName => Marshal.PtrToStringUTF8(Ptr->FamilyName);
|
||||
public string StyleName => Marshal.PtrToStringUTF8(Ptr->StyleName);
|
||||
public int NumberOfFixedSizes => Ptr->NumberOfFixedSizes;
|
||||
public int NumberOfCharMaps => Ptr->NumberOfCharMaps;
|
||||
public FTGlyphSlot Glyph => Ptr->Glyph;
|
||||
public short Ascender => Ptr->Ascender;
|
||||
public short Descender => Ptr->Descender;
|
||||
public ref readonly FTSizeMetrics ScaledSize => ref ((FTSize*)Ptr->Size)->Metrics;
|
||||
}
|
||||
|
||||
public struct FTBox
|
||||
{
|
||||
public long XMin;
|
||||
public long YMin;
|
||||
public long XMax;
|
||||
public long YMax;
|
||||
}
|
||||
|
||||
internal struct FTFaceInternal
|
||||
{
|
||||
public long NumberOfFaces;
|
||||
public long FaceIndex;
|
||||
public long FaceFlags;
|
||||
public long StyleFlags;
|
||||
public long NumberOfGlyphs;
|
||||
public IntPtr FamilyName;
|
||||
public IntPtr StyleName;
|
||||
public int NumberOfFixedSizes;
|
||||
public IntPtr AvailableSizes;
|
||||
public int NumberOfCharMaps;
|
||||
public IntPtr Charmaps;
|
||||
public FTGeneric Generic;
|
||||
public FTBox BoundingBox;
|
||||
public ushort UnitsPerEm;
|
||||
public short Ascender;
|
||||
public short Descender;
|
||||
public short Height;
|
||||
public short MaxAdvanceWidth;
|
||||
public short MaxAdvanceHeight;
|
||||
public short UnderlinePosition;
|
||||
public short UnderlineThickness;
|
||||
public FTGlyphSlot Glyph;
|
||||
public IntPtr Size;
|
||||
public IntPtr Charmap;
|
||||
|
||||
// Rest of the struct is private to implementation.
|
||||
}
|
||||
|
||||
public struct FTGeneric
|
||||
{
|
||||
public IntPtr Data;
|
||||
public IntPtr Finalizer;
|
||||
}
|
||||
|
||||
public struct FTVector
|
||||
{
|
||||
public long X;
|
||||
public long Y;
|
||||
}
|
||||
|
||||
public struct FTBitmap
|
||||
{
|
||||
public uint Rows;
|
||||
public uint Width;
|
||||
public int Pitch;
|
||||
public IntPtr Buffer;
|
||||
public ushort NumberOfGrays;
|
||||
public byte PixelMode;
|
||||
public byte PaletteMode;
|
||||
public IntPtr Palette;
|
||||
}
|
||||
|
||||
public struct FTOutline
|
||||
{
|
||||
public short NumberOfContours;
|
||||
public short NumberOfPoints;
|
||||
public IntPtr Points;
|
||||
public IntPtr Tags;
|
||||
public IntPtr Contours;
|
||||
public int Flags;
|
||||
}
|
||||
|
||||
internal struct FTGlyphSlotInternal
|
||||
{
|
||||
public FTLibrary Library;
|
||||
public FTFace Face;
|
||||
public FTGlyphSlot Next;
|
||||
public uint GlyphIndex;
|
||||
public FTGeneric Generic;
|
||||
public FTGlyphMetrics Metrics;
|
||||
public long LinearHorizontalAdvance;
|
||||
public long LinearVerticalAdvance;
|
||||
public FTVector Advance;
|
||||
public int Format;
|
||||
public FTBitmap Bitmap;
|
||||
public int BitmapLeft;
|
||||
public int BitmapTop;
|
||||
public FTOutline Outline;
|
||||
public uint NumberOfSubGlyphs;
|
||||
public IntPtr SubGlyphs;
|
||||
public IntPtr ControlData;
|
||||
public long ControlLength;
|
||||
public long LsbDelta;
|
||||
public long RsbDelta;
|
||||
public IntPtr Other;
|
||||
public IntPtr Internal;
|
||||
}
|
||||
|
||||
public unsafe struct FTGlyphSlot
|
||||
{
|
||||
private IntPtr _handle;
|
||||
public IntPtr Handle => _handle;
|
||||
private FTGlyphSlotInternal* Ptr => (FTGlyphSlotInternal*) _handle;
|
||||
|
||||
public FTLibrary Library => Ptr->Library;
|
||||
public FTFace Face => Ptr->Face;
|
||||
public FTGlyphSlot Next => Ptr->Next;
|
||||
public uint GlyphIndex => Ptr->GlyphIndex;
|
||||
public ref readonly FTGlyphMetrics Metrics => ref Ptr->Metrics;
|
||||
public long LinearHorizontalAdvance => Ptr->LinearHorizontalAdvance;
|
||||
public long LinearVerticalAdvance => Ptr->LinearVerticalAdvance;
|
||||
public FTVector Advance => Ptr->Advance;
|
||||
public ref readonly FTBitmap Bitmap => ref Ptr->Bitmap;
|
||||
public long BitmapLeft => Ptr->BitmapLeft;
|
||||
public long BitmapTop => Ptr->BitmapTop;
|
||||
}
|
||||
|
||||
public struct FTGlyphMetrics
|
||||
{
|
||||
public long Width;
|
||||
public long Height;
|
||||
public long HorizontalBearingX;
|
||||
public long HorizontalBearingY;
|
||||
public long HorizontalAdvance;
|
||||
public long VerticalBearingX;
|
||||
public long VerticalBearingY;
|
||||
public long VerticalAdvance;
|
||||
}
|
||||
|
||||
public struct FTSizeMetrics
|
||||
{
|
||||
public short Xppem;
|
||||
public short Yppem;
|
||||
public long XScale;
|
||||
public long YScale;
|
||||
public long Ascender;
|
||||
public long Descender;
|
||||
public long Height;
|
||||
public long MaxAdvance;
|
||||
}
|
||||
|
||||
public struct FTSize
|
||||
{
|
||||
public IntPtr Face;
|
||||
public FTGeneric Generic;
|
||||
public FTSizeMetrics Metrics;
|
||||
private IntPtr Privates;
|
||||
}
|
||||
}
|
30
Quik.sln
30
Quik.sln
@ -1,14 +1,10 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
#
|
||||
#
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quik", "Quik\Quik.csproj", "{B86B2B99-DAE4-43CE-A040-1D8E143B94A7}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quik.OpenTK", "Quik.OpenTK\Quik.OpenTK.csproj", "{586E5E28-1D07-4CC2-B04F-0BC420564F57}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuikTestApplication", "QuikTestApplication\QuikTestApplication.csproj", "{49AEF502-692A-48A4-8076-EF2228925280}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Quik.FreeType", "Quik.FreeType\Quik.FreeType.csproj", "{53B95098-F304-47E6-A08C-DAFA589F5BCF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@ -43,29 +39,5 @@ Global
|
||||
{586E5E28-1D07-4CC2-B04F-0BC420564F57}.Release|x64.Build.0 = Release|Any CPU
|
||||
{586E5E28-1D07-4CC2-B04F-0BC420564F57}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{586E5E28-1D07-4CC2-B04F-0BC420564F57}.Release|x86.Build.0 = Release|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Release|x64.Build.0 = Release|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{49AEF502-692A-48A4-8076-EF2228925280}.Release|x86.Build.0 = Release|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Release|x64.Build.0 = Release|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{53B95098-F304-47E6-A08C-DAFA589F5BCF}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
@ -1,183 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using Quik;
|
||||
using Quik.VertexGenerator;
|
||||
using OpenTK.Mathematics;
|
||||
using OpenTK.Graphics.OpenGL4;
|
||||
using OpenTK.Windowing.Common;
|
||||
using OpenTK.Windowing.Desktop;
|
||||
using OpenTK.Windowing.GraphicsLibraryFramework;
|
||||
using Quik.FreeType;
|
||||
using Quik.OpenTK;
|
||||
using Quik.Typography;
|
||||
using Quik.Controls;
|
||||
using Quik.OpenGL;
|
||||
using GL = Quik.OpenGL.GL;
|
||||
using static Quik.OpenGL.GLEnum;
|
||||
using Quik.CommandMachine;
|
||||
|
||||
namespace QuikTestApplication
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public const string vertex =
|
||||
@"#version 140
|
||||
uniform mat4 matrix;
|
||||
in vec2 position;
|
||||
in vec2 texcoord;
|
||||
in vec4 color;
|
||||
out vec2 ftexcoord;
|
||||
out vec4 fcolor;
|
||||
|
||||
void main()
|
||||
{
|
||||
fcolor = color;
|
||||
ftexcoord = texcoord;
|
||||
gl_Position = matrix * vec4(position.xy, 0, 1);
|
||||
}
|
||||
";
|
||||
|
||||
public const string fragment =
|
||||
@"#version 140
|
||||
in vec2 ftexcoord;
|
||||
in vec4 fcolor;
|
||||
out vec4 outcolor;
|
||||
|
||||
uniform sampler2D texture0;
|
||||
uniform vec2 texture0offset;
|
||||
|
||||
void main()
|
||||
{
|
||||
outcolor = fcolor * texture(texture0, ftexcoord + texture0offset);
|
||||
}
|
||||
";
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
NativeWindowSettings windowSettings = NativeWindowSettings.Default;
|
||||
windowSettings.NumberOfSamples = 4;
|
||||
NativeWindow window = new NativeWindow(windowSettings);
|
||||
|
||||
window.Context.MakeCurrent();
|
||||
GL.LoadBindings(new GLFWBindingsContext().GetProcAddress);
|
||||
|
||||
FreeTypeFontManager fontManager = new FreeTypeFontManager();
|
||||
QuikContext context = new QuikContext(new OpenGLTextureManager(), fontManager);
|
||||
|
||||
VertexGeneratorEngine engine = new VertexGeneratorEngine();
|
||||
CommandQueue cmdQueue = new CommandQueue();
|
||||
GL30Driver gldriver;
|
||||
|
||||
RootControl root = new RootControl(context);
|
||||
Button button = new Button()
|
||||
{
|
||||
Bounds = new QRectangle(120, 60, 20, 20),
|
||||
Text = "button",
|
||||
Padding = 8,
|
||||
NormalStroke = new QuikStrokeStyle(new QColor(0xccccccff), 4f),
|
||||
HoverStroke = new QuikStrokeStyle(new QColor(0x1010ccff), 4f),
|
||||
ActiveStroke = new QuikStrokeStyle(new QColor(0x999999ff), 4f),
|
||||
};
|
||||
button.Clicked += (sender, args) => {
|
||||
if (!args.Buttons.HasFlag(Quik.MouseButton.Primary))
|
||||
return;
|
||||
|
||||
Button xbutton = (Button)sender;
|
||||
|
||||
if (xbutton.Text == "button")
|
||||
{
|
||||
xbutton.Text = "le button";
|
||||
}
|
||||
else
|
||||
{
|
||||
xbutton.Text = "button";
|
||||
}
|
||||
};
|
||||
root.MouseEnter += (_,_) => Console.WriteLine("enter");
|
||||
root.MouseLeave += (_,_) => Console.WriteLine("leave");
|
||||
root.MouseMove += (_,_) => Console.WriteLine("move");
|
||||
root.MouseDown += (_,_) => Console.WriteLine("down");
|
||||
root.MouseUp += (_,_) => Console.WriteLine("up");
|
||||
root.Add(button);
|
||||
|
||||
GL.Enable(GL_MULTISAMPLE);
|
||||
|
||||
gldriver = new GL30Driver();
|
||||
|
||||
window.Context.SwapInterval = 0;
|
||||
Stopwatch stopwatch = Stopwatch.StartNew();
|
||||
float lastMs = stopwatch.ElapsedMilliseconds;
|
||||
int frames = 0;
|
||||
for (;!window.IsExiting;)
|
||||
{
|
||||
NativeWindow.ProcessWindowEvents(false);
|
||||
window.ProcessEvents(0.0f);
|
||||
window.TryGetCurrentMonitorDpi(out float dpi, out _);
|
||||
|
||||
if (window.IsFocused)
|
||||
{
|
||||
var mouseState = window.MouseState;
|
||||
QVec2 postion = new QVec2(mouseState.Position.X, window.ClientSize.Y - mouseState.Position.Y) * (dpi/72f);
|
||||
Quik.MouseButton buttons =
|
||||
(mouseState.IsButtonDown(OpenTK.Windowing.GraphicsLibraryFramework.MouseButton.Button1) ? Quik.MouseButton.Primary : 0) |
|
||||
(mouseState.IsButtonDown(OpenTK.Windowing.GraphicsLibraryFramework.MouseButton.Button2) ? Quik.MouseButton.Secondary : 0) |
|
||||
(mouseState.IsButtonDown(OpenTK.Windowing.GraphicsLibraryFramework.MouseButton.Button3) ? Quik.MouseButton.Tertiary : 0);
|
||||
|
||||
root.NotifyMouse(new Quik.MouseState(postion, buttons));
|
||||
}
|
||||
|
||||
root.Bounds = new QRectangle(
|
||||
window.ClientSize.X,
|
||||
window.ClientSize.Y,
|
||||
0,
|
||||
0);
|
||||
root.NotifyUpdate();
|
||||
|
||||
cmdQueue.Clear();
|
||||
root.NotifyPaint(cmdQueue);
|
||||
|
||||
engine.Reset();
|
||||
engine.ProcessCommands(root.Bounds, cmdQueue);
|
||||
|
||||
DrawQueue drawQueue = engine.DrawQueue;
|
||||
|
||||
GL.Clear(GL_COLOR_BUFFER_BIT);
|
||||
gldriver.Draw(drawQueue);
|
||||
|
||||
window.Context.SwapBuffers();
|
||||
|
||||
frames++;
|
||||
float ms = stopwatch.ElapsedMilliseconds;
|
||||
if (ms - lastMs > 1000)
|
||||
{
|
||||
Console.WriteLine("Frames: {0}", frames*(ms - lastMs)/1000);
|
||||
frames = 0;
|
||||
lastMs = ms;
|
||||
Console.WriteLine("Vertex Usage: {0} ; Element Usage: {1} Calls: {2}", drawQueue.VertexCount, drawQueue.ElementCount, drawQueue.DrawCallCount);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class TextFontManager : IQuikFontManager
|
||||
{
|
||||
public QuikContext Context { get; set; }
|
||||
|
||||
private TestFont _font;
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
}
|
||||
|
||||
public QuikFont GetFont(QuikFontStyle fontStyle)
|
||||
{
|
||||
if (_font is null)
|
||||
{
|
||||
_font = new TestFont(Context);
|
||||
}
|
||||
|
||||
return _font;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Quik.FreeType\Quik.FreeType.csproj" />
|
||||
<ProjectReference Include="..\Quik.OpenTK\Quik.OpenTK.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="font.dat" />
|
||||
<EmbeddedResource Include="font.dat" />
|
||||
<None Remove="font.xml" />
|
||||
<EmbeddedResource Include="font.xml" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
@ -1,126 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Xml;
|
||||
using Quik;
|
||||
using Quik.Typography;
|
||||
|
||||
namespace QuikTestApplication
|
||||
{
|
||||
public class TestFont : QuikFont
|
||||
{
|
||||
public override QuikFontStyle Style => _style;
|
||||
|
||||
private static QuikFontStyle _style;
|
||||
private static HashSet<int> _characters = new HashSet<int>();
|
||||
private static Dictionary<int, QuikGlyph> _glyphs = new Dictionary<int, QuikGlyph>();
|
||||
|
||||
public static byte[] TextureData { get; private set; } = Array.Empty<byte>();
|
||||
public static QVec2 TextureSize { get; private set; }
|
||||
|
||||
public QuikTexture Texture { get; }
|
||||
|
||||
public override float Ascender => throw new NotImplementedException();
|
||||
|
||||
public override float Descender => throw new NotImplementedException();
|
||||
|
||||
public TestFont(QuikContext context)
|
||||
{
|
||||
Texture = context.TextureManager.CreateTexture(TextureSize, false, QuikImageFormat.RgbaU8);
|
||||
unsafe
|
||||
{
|
||||
fixed (byte* ptr = &TextureData[0])
|
||||
{
|
||||
Texture.Image((IntPtr)ptr, QuikImageFormat.RgbaU8, TextureSize, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static TestFont()
|
||||
{
|
||||
using (Stream str = typeof(TestFont).Assembly.GetManifestResourceStream("QuikTestApplication.font.xml"))
|
||||
{
|
||||
XmlDocument document = new XmlDocument();
|
||||
document.Load(str);
|
||||
|
||||
string family = document.DocumentElement.Attributes["name"].Value;
|
||||
float fontSize = float.Parse(document.DocumentElement.Attributes["size"].Value);
|
||||
QuikFontType style = QuikFontType.Normal;
|
||||
if (document.DocumentElement.Attributes["bold"].Value == "true")
|
||||
style = QuikFontType.Bold;
|
||||
if (document.DocumentElement.Attributes["italic"].Value == "true")
|
||||
style = QuikFontType.Italic;
|
||||
|
||||
_style = new QuikFontStyle(family, fontSize, style);
|
||||
|
||||
QVec2 atlasSize = default;
|
||||
atlasSize.X = float.Parse(document.DocumentElement.Attributes["width"].Value);
|
||||
atlasSize.Y = float.Parse(document.DocumentElement.Attributes["height"].Value);
|
||||
|
||||
TextureSize = atlasSize;
|
||||
|
||||
foreach (XmlElement element in document.SelectNodes("/font/character"))
|
||||
{
|
||||
QRectangle UVs;
|
||||
QVec2 origin;
|
||||
float advance;
|
||||
int chr = element.Attributes["text"].Value[0];
|
||||
|
||||
QVec2 pos;
|
||||
QVec2 size;
|
||||
pos.X = float.Parse(element.Attributes["x"].Value);
|
||||
pos.Y = float.Parse(element.Attributes["y"].Value);
|
||||
size.X = float.Parse(element.Attributes["width"].Value);
|
||||
size.Y = float.Parse(element.Attributes["height"].Value);
|
||||
UVs = new QRectangle(
|
||||
(pos.X + size.X)/atlasSize.X,
|
||||
pos.Y/atlasSize.Y,
|
||||
pos.X/atlasSize.X,
|
||||
(size.Y + pos.Y)/atlasSize.Y);
|
||||
|
||||
origin.X = float.Parse(element.Attributes["origin-x"].Value);
|
||||
origin.Y = float.Parse(element.Attributes["origin-y"].Value);
|
||||
|
||||
advance = float.Parse(element.Attributes["advance"].Value);
|
||||
|
||||
QuikGlyph glyph = new QuikGlyph(chr, UVs, size, origin, default, new QVec2(advance, 0));
|
||||
_glyphs.Add(chr, glyph);
|
||||
_characters.Add(chr);
|
||||
}
|
||||
}
|
||||
|
||||
using (Stream str = typeof(TestFont).Assembly.GetManifestResourceStream("QuikTestApplication.font.dat"))
|
||||
{
|
||||
TextureData = new byte[(int)str.Length];
|
||||
str.Read(TextureData, 0, (int)str.Length);
|
||||
}
|
||||
|
||||
// Evil pointer stuff. Beware!
|
||||
Span<uint> head = MemoryMarshal.Cast<byte, uint>(TextureData);
|
||||
for (int i = 0; i < head.Length; i++)
|
||||
{
|
||||
if (head[i] == 0xff000000)
|
||||
{
|
||||
head[i] = 0x00000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override bool HasCharacter(int character)
|
||||
{
|
||||
return _characters.Contains((char) character);
|
||||
}
|
||||
|
||||
public override void GetCharacter(int character, out QuikTexture texture, out QuikGlyph glyph)
|
||||
{
|
||||
if (!_glyphs.TryGetValue(character, out glyph))
|
||||
{
|
||||
glyph = _glyphs['?'];
|
||||
}
|
||||
|
||||
texture = Texture;
|
||||
}
|
||||
}
|
||||
}
|
Binary file not shown.
Binary file not shown.
Before Width: | Height: | Size: 24 KiB |
@ -1,98 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<font name="monospace" bold="false" italic="false" width="512" height="128" size="32">
|
||||
<character text=" " x="69" y="84" width="3" height="3" origin-x="1" origin-y="1" advance="19"/>
|
||||
<character text="!" x="116" y="59" width="6" height="25" origin-x="-7" origin-y="24" advance="19"/>
|
||||
<character text=""" x="487" y="59" width="11" height="11" origin-x="-4" origin-y="24" advance="19"/>
|
||||
<character text="#" x="373" y="0" width="22" height="25" origin-x="1" origin-y="24" advance="19"/>
|
||||
<character text="$" x="48" y="0" width="18" height="31" origin-x="-1" origin-y="25" advance="19"/>
|
||||
<character text="%" x="417" y="0" width="21" height="25" origin-x="1" origin-y="24" advance="19"/>
|
||||
<character text="&" x="438" y="0" width="21" height="25" origin-x="1" origin-y="24" advance="19"/>
|
||||
<character text="'" x="498" y="59" width="5" height="11" origin-x="-7" origin-y="24" advance="19"/>
|
||||
<character text="(" x="66" y="0" width="10" height="31" origin-x="-5" origin-y="25" advance="19"/>
|
||||
<character text=")" x="76" y="0" width="10" height="31" origin-x="-4" origin-y="25" advance="19"/>
|
||||
<character text="*" x="423" y="59" width="17" height="17" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="+" x="359" y="59" width="19" height="19" origin-x="0" origin-y="20" advance="19"/>
|
||||
<character text="," x="440" y="59" width="8" height="12" origin-x="-5" origin-y="7" advance="19"/>
|
||||
<character text="-" x="58" y="84" width="11" height="5" origin-x="-4" origin-y="12" advance="19"/>
|
||||
<character text="." x="29" y="84" width="7" height="7" origin-x="-6" origin-y="6" advance="19"/>
|
||||
<character text="/" x="145" y="0" width="18" height="29" origin-x="0" origin-y="24" advance="19"/>
|
||||
<character text="0" x="198" y="34" width="18" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="1" x="360" y="34" width="17" height="25" origin-x="-2" origin-y="24" advance="19"/>
|
||||
<character text="2" x="377" y="34" width="17" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="3" x="394" y="34" width="17" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="4" x="103" y="34" width="19" height="25" origin-x="0" origin-y="24" advance="19"/>
|
||||
<character text="5" x="411" y="34" width="17" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="6" x="216" y="34" width="18" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="7" x="428" y="34" width="17" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="8" x="234" y="34" width="18" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="9" x="252" y="34" width="18" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text=":" x="378" y="59" width="7" height="19" origin-x="-6" origin-y="18" advance="19"/>
|
||||
<character text=";" x="122" y="59" width="8" height="23" origin-x="-5" origin-y="18" advance="19"/>
|
||||
<character text="<" x="385" y="59" width="19" height="18" origin-x="0" origin-y="19" advance="19"/>
|
||||
<character text="=" x="468" y="59" width="19" height="11" origin-x="0" origin-y="16" advance="19"/>
|
||||
<character text=">" x="404" y="59" width="19" height="18" origin-x="0" origin-y="19" advance="19"/>
|
||||
<character text="?" x="68" y="59" width="16" height="25" origin-x="-2" origin-y="24" advance="19"/>
|
||||
<character text="@" x="105" y="0" width="21" height="29" origin-x="1" origin-y="23" advance="19"/>
|
||||
<character text="A" x="459" y="0" width="21" height="25" origin-x="1" origin-y="24" advance="19"/>
|
||||
<character text="B" x="270" y="34" width="18" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="C" x="445" y="34" width="17" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="D" x="288" y="34" width="18" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="E" x="462" y="34" width="17" height="25" origin-x="-2" origin-y="24" advance="19"/>
|
||||
<character text="F" x="479" y="34" width="17" height="25" origin-x="-2" origin-y="24" advance="19"/>
|
||||
<character text="G" x="122" y="34" width="19" height="25" origin-x="0" origin-y="24" advance="19"/>
|
||||
<character text="H" x="306" y="34" width="18" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="I" x="84" y="59" width="16" height="25" origin-x="-2" origin-y="24" advance="19"/>
|
||||
<character text="J" x="100" y="59" width="16" height="25" origin-x="0" origin-y="24" advance="19"/>
|
||||
<character text="K" x="63" y="34" width="20" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="L" x="0" y="59" width="17" height="25" origin-x="-2" origin-y="24" advance="19"/>
|
||||
<character text="M" x="141" y="34" width="19" height="25" origin-x="0" origin-y="24" advance="19"/>
|
||||
<character text="N" x="324" y="34" width="18" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="O" x="160" y="34" width="19" height="25" origin-x="0" origin-y="24" advance="19"/>
|
||||
<character text="P" x="17" y="59" width="17" height="25" origin-x="-2" origin-y="24" advance="19"/>
|
||||
<character text="Q" x="126" y="0" width="19" height="29" origin-x="0" origin-y="24" advance="19"/>
|
||||
<character text="R" x="83" y="34" width="20" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="S" x="342" y="34" width="18" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="T" x="480" y="0" width="21" height="25" origin-x="1" origin-y="24" advance="19"/>
|
||||
<character text="U" x="34" y="59" width="17" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="V" x="0" y="34" width="21" height="25" origin-x="1" origin-y="24" advance="19"/>
|
||||
<character text="W" x="395" y="0" width="22" height="25" origin-x="1" origin-y="24" advance="19"/>
|
||||
<character text="X" x="21" y="34" width="21" height="25" origin-x="1" origin-y="24" advance="19"/>
|
||||
<character text="Y" x="42" y="34" width="21" height="25" origin-x="1" origin-y="24" advance="19"/>
|
||||
<character text="Z" x="179" y="34" width="19" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="[" x="96" y="0" width="9" height="31" origin-x="-6" origin-y="25" advance="19"/>
|
||||
<character text="\" x="163" y="0" width="18" height="29" origin-x="0" origin-y="24" advance="19"/>
|
||||
<character text="]" x="86" y="0" width="10" height="31" origin-x="-4" origin-y="25" advance="19"/>
|
||||
<character text="^" x="448" y="59" width="20" height="11" origin-x="0" origin-y="25" advance="19"/>
|
||||
<character text="_" x="36" y="84" width="22" height="5" origin-x="1" origin-y="-4" advance="19"/>
|
||||
<character text="`" x="0" y="84" width="10" height="8" origin-x="-3" origin-y="27" advance="19"/>
|
||||
<character text="a" x="246" y="59" width="17" height="20" origin-x="-1" origin-y="19" advance="19"/>
|
||||
<character text="b" x="307" y="0" width="17" height="26" origin-x="-2" origin-y="25" advance="19"/>
|
||||
<character text="c" x="263" y="59" width="16" height="20" origin-x="-2" origin-y="19" advance="19"/>
|
||||
<character text="d" x="253" y="0" width="18" height="26" origin-x="0" origin-y="25" advance="19"/>
|
||||
<character text="e" x="152" y="59" width="19" height="20" origin-x="0" origin-y="19" advance="19"/>
|
||||
<character text="f" x="341" y="0" width="16" height="26" origin-x="-2" origin-y="25" advance="19"/>
|
||||
<character text="g" x="200" y="0" width="18" height="27" origin-x="0" origin-y="19" advance="19"/>
|
||||
<character text="h" x="357" y="0" width="16" height="26" origin-x="-2" origin-y="25" advance="19"/>
|
||||
<character text="i" x="271" y="0" width="18" height="26" origin-x="-1" origin-y="25" advance="19"/>
|
||||
<character text="j" x="5" y="0" width="13" height="33" origin-x="-1" origin-y="25" advance="19"/>
|
||||
<character text="k" x="289" y="0" width="18" height="26" origin-x="-2" origin-y="25" advance="19"/>
|
||||
<character text="l" x="324" y="0" width="17" height="26" origin-x="-1" origin-y="25" advance="19"/>
|
||||
<character text="m" x="171" y="59" width="19" height="20" origin-x="0" origin-y="19" advance="19"/>
|
||||
<character text="n" x="279" y="59" width="16" height="20" origin-x="-2" origin-y="19" advance="19"/>
|
||||
<character text="o" x="228" y="59" width="18" height="20" origin-x="-1" origin-y="19" advance="19"/>
|
||||
<character text="p" x="218" y="0" width="18" height="27" origin-x="-1" origin-y="19" advance="19"/>
|
||||
<character text="q" x="236" y="0" width="17" height="27" origin-x="-1" origin-y="19" advance="19"/>
|
||||
<character text="r" x="295" y="59" width="16" height="20" origin-x="-4" origin-y="19" advance="19"/>
|
||||
<character text="s" x="311" y="59" width="16" height="20" origin-x="-2" origin-y="19" advance="19"/>
|
||||
<character text="t" x="51" y="59" width="17" height="25" origin-x="-1" origin-y="24" advance="19"/>
|
||||
<character text="u" x="327" y="59" width="16" height="20" origin-x="-2" origin-y="19" advance="19"/>
|
||||
<character text="v" x="190" y="59" width="19" height="20" origin-x="0" origin-y="19" advance="19"/>
|
||||
<character text="w" x="130" y="59" width="22" height="20" origin-x="1" origin-y="19" advance="19"/>
|
||||
<character text="x" x="209" y="59" width="19" height="20" origin-x="0" origin-y="19" advance="19"/>
|
||||
<character text="y" x="181" y="0" width="19" height="27" origin-x="0" origin-y="19" advance="19"/>
|
||||
<character text="z" x="343" y="59" width="16" height="20" origin-x="-2" origin-y="19" advance="19"/>
|
||||
<character text="{" x="18" y="0" width="15" height="32" origin-x="-2" origin-y="25" advance="19"/>
|
||||
<character text="|" x="0" y="0" width="5" height="34" origin-x="-7" origin-y="25" advance="19"/>
|
||||
<character text="}" x="33" y="0" width="15" height="32" origin-x="-2" origin-y="25" advance="19"/>
|
||||
<character text="~" x="10" y="84" width="19" height="7" origin-x="0" origin-y="14" advance="19"/>
|
||||
</font>
|
Loading…
Reference in New Issue
Block a user