From f172c340ad6bcc254b0d2fb7a5a2e22e112cfbcc Mon Sep 17 00:00:00 2001 From: "H. Utku Maden" Date: Sat, 23 Mar 2024 11:56:10 +0300 Subject: [PATCH] Initial commit. --- .gitignore | 6 ++ FT.cs | 120 ++++++++++++++++++++++++++++ FTError.cs | 7 ++ FTLoadFlags.cs | 28 +++++++ FTRenderMode.cs | 12 +++ FaceFlag.cs | 28 +++++++ Quik.FreeType.csproj | 28 +++++++ Structures.cs | 183 +++++++++++++++++++++++++++++++++++++++++++ build_native.sh | 8 ++ 9 files changed, 420 insertions(+) create mode 100644 .gitignore create mode 100644 FT.cs create mode 100644 FTError.cs create mode 100644 FTLoadFlags.cs create mode 100644 FTRenderMode.cs create mode 100644 FaceFlag.cs create mode 100644 Quik.FreeType.csproj create mode 100644 Structures.cs create mode 100644 build_native.sh 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