commit f172c340ad6bcc254b0d2fb7a5a2e22e112cfbcc Author: H. Utku Maden Date: Sat Mar 23 11:56:10 2024 +0300 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c27cc2c --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +**/bin +**/obj +**/out +**/runtimes +**/.vs* +**/.atom diff --git a/FT.cs b/FT.cs new file mode 100644 index 0000000..9fd7cec --- /dev/null +++ b/FT.cs @@ -0,0 +1,120 @@ +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace Quik.FreeType +{ + public static class FT + { + private const string freetype2 = "freetype"; + + private static readonly string[] LibraryNames = new string[] + { + //FIXME: This is wrong on so many levels, but, i need to do this + // in order to get a change of this running. + "runtimes/win-x64/native/libfreetype.dll", + "runtimes/win-x86/native/libfreetype.dll", + "runtimes/linux-arm/native/libfreetype.so", + "runtimes/linux-arm64/native/libfreetype.so", + "runtimes/linux-x64/native/libfreetype.so", + "runtimes/native/libfreetype.dylib", + "libfreetype.dll", + "libfreetype.so", + "libfreetype.dylib", + }; + + static FT() + { + NativeLibrary.SetDllImportResolver(Assembly.GetExecutingAssembly(), Resolver); + } + + private static IntPtr Resolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) + { + if (libraryName != freetype2) + return IntPtr.Zero; + + foreach (string name in LibraryNames) + { + if (NativeLibrary.TryLoad(name, assembly, searchPath, out IntPtr handle)) + { + return handle; + } + } + + return NativeLibrary.Load(libraryName); + } + + [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 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); + } +} \ No newline at end of file diff --git a/FTError.cs b/FTError.cs new file mode 100644 index 0000000..d80c4b7 --- /dev/null +++ b/FTError.cs @@ -0,0 +1,7 @@ +namespace Quik.FreeType +{ + public enum FTError : int + { + None = 0, + } +} \ No newline at end of file diff --git a/FTLoadFlags.cs b/FTLoadFlags.cs new file mode 100644 index 0000000..ad8ff4a --- /dev/null +++ b/FTLoadFlags.cs @@ -0,0 +1,28 @@ +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 + } +} \ No newline at end of file diff --git a/FTRenderMode.cs b/FTRenderMode.cs new file mode 100644 index 0000000..c3cd212 --- /dev/null +++ b/FTRenderMode.cs @@ -0,0 +1,12 @@ +namespace Quik.FreeType +{ + public enum FTRenderMode + { + Normal = 0, + Light, + Mono, + Lcd, + LcdVertical, + Sdf + } +} \ No newline at end of file diff --git a/FaceFlag.cs b/FaceFlag.cs new file mode 100644 index 0000000..dde662f --- /dev/null +++ b/FaceFlag.cs @@ -0,0 +1,28 @@ +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 + } +} \ No newline at end of file diff --git a/Quik.FreeType.csproj b/Quik.FreeType.csproj new file mode 100644 index 0000000..4ecbbeb --- /dev/null +++ b/Quik.FreeType.csproj @@ -0,0 +1,28 @@ + + + + net6.0 + 7.3 + true + linux-arm;linux-arm64;linux-x64;win-x86;win-x64 + + + + + True + Quik.FreeType + 1.0.0 + FreeType Authors, H. Utku Maden + + A C# wrapper for the FreeType font loading library. + + + + + + runtimes + true + PreserveNewest + + + diff --git a/Structures.cs b/Structures.cs new file mode 100644 index 0000000..6a4eca8 --- /dev/null +++ b/Structures.cs @@ -0,0 +1,183 @@ +using System; +using System.Runtime.InteropServices; + +// Disable unused warnings for native types. +#pragma warning disable CS0649 + +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; + } +} \ No newline at end of file diff --git a/build_native.sh b/build_native.sh new file mode 100644 index 0000000..ca44911 --- /dev/null +++ b/build_native.sh @@ -0,0 +1,8 @@ +#!/bin/bash +cd $(dirname "$0") + +# Apply the patch file that makes it easier to build freetype. +# Note that this doesn't work all that well on windows. +cat ../lib/freetype_patch.diff | git -C ../lib/freetype apply + +QUIK_ADDITIONAL_CMAKE=-DBUILD_SHARED_LIBS\=true DST=$PWD ../sh/quik_build_native.sh ../lib/freetype