diff --git a/.vscode/launch.json b/.vscode/launch.json index d02425400d8..85e8eb0d09a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -8,12 +8,24 @@ "name": "MGCB Editor (Mac)", "type": "coreclr", "request": "launch", - "preLaunchTask": "mgcb-editor-mac", - "program": "${workspaceFolder}/Artifacts/MonoGame.Content.Builder.Editor/Mac/Debug/MGCB Editor.app/Contents/MacOS/mgcb-editor-mac", + "preLaunchTask": "Build: mgcb-editor-mac", + "program": "${workspaceFolder}/Artifacts/MonoGame.Content.Builder.Editor/Mac/Debug/osx-arm64/MGCB Editor.app/Contents/MacOS/mgcb-editor-mac", "args": [], "cwd": "${workspaceFolder}/Artifacts/MonoGame.Content.Builder.Editor/Mac/Debug", "console": "internalConsole", "stopAtEntry": false + }, + { + "name": "MGCB", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "Build: mgcb", + "program": "${workspaceFolder}/Artifacts/MonoGame.Content.Builder/Debug/mgcb", + "args": [ + "/@:/Users/harry/Projects/ContentTest/Untitled.mgcb", "/rebuild" + ], + "console": "internalConsole", + "stopAtEntry": false } ] } diff --git a/.vscode/tasks.json b/.vscode/tasks.json index ff4ce21d72a..60219e91483 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,7 +2,19 @@ "version": "2.0.0", "tasks": [ { - "label": "mgcb-editor-mac", + "label": "Build: mgcb", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/Tools/MonoGame.Content.Builder/MonoGame.Content.Builder.csproj", + "/property:GenerateFullPaths=true", + "/consoleloggerparameters:NoSummary" + ], + "problemMatcher": "$msCompile" + }, + { + "label": "Build: mgcb-editor-mac", "command": "dotnet", "type": "process", "args": [ diff --git a/MonoGame.Framework.Content.Pipeline/Graphics/Font/IFontImporter.cs b/MonoGame.Framework.Content.Pipeline/Graphics/Font/IFontImporter.cs index cc69accff76..19f6e8d091f 100644 --- a/MonoGame.Framework.Content.Pipeline/Graphics/Font/IFontImporter.cs +++ b/MonoGame.Framework.Content.Pipeline/Graphics/Font/IFontImporter.cs @@ -11,6 +11,6 @@ internal interface IFontImporter float LineSpacing { get; } - int YOffsetMin { get; } + long YOffsetMin { get; } } } diff --git a/MonoGame.Framework.Content.Pipeline/Graphics/Font/SharpFontImporter.cs b/MonoGame.Framework.Content.Pipeline/Graphics/Font/SharpFontImporter.cs index eb33b1f9ef8..bea4814ebc0 100644 --- a/MonoGame.Framework.Content.Pipeline/Graphics/Font/SharpFontImporter.cs +++ b/MonoGame.Framework.Content.Pipeline/Graphics/Font/SharpFontImporter.cs @@ -5,126 +5,109 @@ using System; using System.Collections.Generic; using System.Runtime.InteropServices; -using SharpFont; +using FreeTypeAPI; namespace Microsoft.Xna.Framework.Content.Pipeline.Graphics { // Uses FreeType to rasterize TrueType fonts into a series of glyph bitmaps. - internal class SharpFontImporter : IFontImporter + unsafe internal class SharpFontImporter : IFontImporter { // Properties hold the imported font data. public IEnumerable Glyphs { get; private set; } public float LineSpacing { get; private set; } - public int YOffsetMin { get; private set; } + public long YOffsetMin { get; private set; } // Size of the temp surface used for GDI+ rasterization. const int MaxGlyphSize = 1024; - Library lib = null; - public void Import(FontDescription options, string fontName) { - lib = new Library(); - // Create a bunch of GDI+ objects. - var face = CreateFontFace(options, fontName); - try - { - // Which characters do we want to include? - var characters = options.Characters; + CheckError(FreeType.FT_Init_FreeType(out FT_Library* library)); - var glyphList = new List(); - var glyphMaps = new Dictionary(); - - // Rasterize each character in turn. - foreach (char character in characters) - { - uint glyphIndex = face.GetCharIndex(character); - if (!glyphMaps.TryGetValue(glyphIndex, out GlyphData glyphData)) - { - glyphData = ImportGlyph(glyphIndex, face); - glyphMaps.Add(glyphIndex, glyphData); - } + // Create a bunch of GDI+ objects. + var face = CreateFontFace(library, options, fontName); - var glyph = new Glyph(character, glyphData); - glyphList.Add(glyph); - } - Glyphs = glyphList; + // Which characters do we want to include? + var characters = options.Characters; - // Store the font height. - LineSpacing = face.Size.Metrics.Height >> 6; + var glyphList = new List(); + var glyphMaps = new Dictionary(); - // The height used to calculate the Y offset for each character. - YOffsetMin = -face.Size.Metrics.Ascender >> 6; - } - finally + // Rasterize each character in turn. + foreach (char character in characters) { - if (face != null) - face.Dispose(); - if (lib != null) + uint glyphIndex = FreeType.FT_Get_Char_Index(face, character); + if (!glyphMaps.TryGetValue(glyphIndex, out GlyphData glyphData)) { - lib.Dispose(); - lib = null; + glyphData = ImportGlyph(glyphIndex, face); + glyphMaps.Add(glyphIndex, glyphData); } + + var glyph = new Glyph(character, glyphData); + glyphList.Add(glyph); } + Glyphs = glyphList; + + // Store the font height. + LineSpacing = face->size->metrics.height >> 6; + + // The height used to calculate the Y offset for each character. + YOffsetMin = -face->size->metrics.ascender >> 6; } + private void CheckError(int error) + { + if (error == 0) + return; + + throw new Exception("An error occured in freetype."); // TODO: Fill the error + } // Attempts to instantiate the requested GDI+ font object. - private Face CreateFontFace(FontDescription options, string fontName) + private FT_Face* CreateFontFace(FT_Library* library, FontDescription options, string fontName) { - try - { - const uint dpi = 96; - var face = lib.NewFace(fontName, 0); - var fixedSize = ((int)options.Size) << 6; - face.SetCharSize(0, fixedSize, dpi, dpi); + const uint dpi = 96; - if (face.FamilyName == "Microsoft Sans Serif" && options.FontName != "Microsoft Sans Serif") - throw new PipelineException(string.Format("Font {0} is not installed on this computer.", options.FontName)); + CheckError(FreeType.FT_New_Face(library, fontName, 0, out FT_Face* face)); - return face; + var fixedSize = ((int)options.Size) << 6; + CheckError(FreeType.FT_Set_Char_Size(face, 0, fixedSize, dpi, dpi)); - // A font substitution must have occurred. - //throw new Exception(string.Format("Can't find font '{0}'.", options.FontName)); - } - catch - { - throw; - } + return face; } // Rasterizes a single character glyph. - private GlyphData ImportGlyph(uint glyphIndex, Face face) + private GlyphData ImportGlyph(uint glyphIndex, FT_Face* face) { - face.LoadGlyph(glyphIndex, LoadFlags.Default, LoadTarget.Normal); - face.Glyph.RenderGlyph(RenderMode.Normal); + CheckError(FreeType.FT_Load_Glyph(face, glyphIndex)); + CheckError(FreeType.FT_Render_Glyph(face->glyph)); // Render the character. BitmapContent glyphBitmap = null; - if (face.Glyph.Bitmap.Width > 0 && face.Glyph.Bitmap.Rows > 0) + if (face->glyph->bitmap.width > 0 && face->glyph->bitmap.rows > 0) { - glyphBitmap = new PixelBitmapContent(face.Glyph.Bitmap.Width, face.Glyph.Bitmap.Rows); - byte[] gpixelAlphas = new byte[face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows]; + glyphBitmap = new PixelBitmapContent((int)face->glyph->bitmap.width, (int)face->glyph->bitmap.rows); + byte[] gpixelAlphas = new byte[face->glyph->bitmap.width * face->glyph->bitmap.rows]; //if the character bitmap has 1bpp we have to expand the buffer data to get the 8bpp pixel data //each byte in bitmap.bufferdata contains the value of to 8 pixels in the row //if bitmap is of width 10, each row has 2 bytes with 10 valid bits, and the last 6 bits of 2nd byte must be discarded - if (face.Glyph.Bitmap.PixelMode == PixelMode.Mono) + if ((FT_Pixel_Mode)face->glyph->bitmap.pixel_mode == FT_Pixel_Mode.FT_PIXEL_MODE_MONO) { //variables needed for the expansion, amount of written data, length of the data to write - int written = 0, length = face.Glyph.Bitmap.Width * face.Glyph.Bitmap.Rows; + int written = 0, length = (int)(face->glyph->bitmap.width * face->glyph->bitmap.rows); for (int i = 0; written < length; i++) { //width in pixels of each row - int width = face.Glyph.Bitmap.Width; + int width = (int)face->glyph->bitmap.width; while (width > 0) { //valid data in the current byte int stride = MathHelper.Min(8, width); //copy the valid bytes to pixeldata //System.Array.Copy(ExpandByte(face.Glyph.Bitmap.BufferData[i]), 0, gpixelAlphas, written, stride); - ExpandByteAndCopy(face.Glyph.Bitmap.BufferData[i], stride, gpixelAlphas, written); + ExpandByteAndCopy(face->glyph->bitmap.buffer[i], stride, gpixelAlphas, written); written += stride; width -= stride; if (width > 0) @@ -133,35 +116,37 @@ private GlyphData ImportGlyph(uint glyphIndex, Face face) } } else - Marshal.Copy(face.Glyph.Bitmap.Buffer, gpixelAlphas, 0, gpixelAlphas.Length); + { + gpixelAlphas = new Span(face->glyph->bitmap.buffer, gpixelAlphas.Length).ToArray(); + } glyphBitmap.SetPixelData(gpixelAlphas); } if (glyphBitmap == null) { - var gHA = face.Glyph.Metrics.HorizontalAdvance >> 6; - var gVA = face.Size.Metrics.Height >> 6; + var gHA = face->glyph->metrics.horiAdvance >> 6; + var gVA = face->size->metrics.height >> 6; gHA = gHA > 0 ? gHA : gVA; gVA = gVA > 0 ? gVA : gHA; - glyphBitmap = new PixelBitmapContent(gHA, gVA); + glyphBitmap = new PixelBitmapContent((int)gHA, (int)gVA); } // not sure about this at all var abc = new ABCFloat(); - abc.A = face.Glyph.Metrics.HorizontalBearingX >> 6; - abc.B = face.Glyph.Metrics.Width >> 6; - abc.C = (face.Glyph.Metrics.HorizontalAdvance >> 6) - (abc.A + abc.B); - abc.A -= face.Glyph.BitmapLeft; - abc.B += face.Glyph.BitmapLeft; + abc.A = face->glyph->metrics.horiBearingX >> 6; + abc.B = face->glyph->metrics.width >> 6; + abc.C = (face->glyph->metrics.horiAdvance >> 6) - (abc.A + abc.B); + abc.A -= face->glyph->bitmap_left; + abc.B += face->glyph->bitmap_left; // Construct the output Glyph object. return new GlyphData(glyphIndex, glyphBitmap) { - XOffset = -(face.Glyph.Advance.X >> 6), - XAdvance = face.Glyph.Metrics.HorizontalAdvance >> 6, - YOffset = -(face.Glyph.Metrics.HorizontalBearingY >> 6), + XOffset = -(face->glyph->advance.x >> 6), + XAdvance = face->glyph->metrics.horiAdvance >> 6, + YOffset = -(face->glyph->metrics.horiBearingY >> 6), CharacterWidths = abc }; } diff --git a/MonoGame.Framework.Content.Pipeline/MonoGame.Framework.Content.Pipeline.csproj b/MonoGame.Framework.Content.Pipeline/MonoGame.Framework.Content.Pipeline.csproj index 05ae4a62d78..efaebd872f9 100644 --- a/MonoGame.Framework.Content.Pipeline/MonoGame.Framework.Content.Pipeline.csproj +++ b/MonoGame.Framework.Content.Pipeline/MonoGame.Framework.Content.Pipeline.csproj @@ -57,9 +57,6 @@ ..\ThirdParty\Dependencies\NVTT\Nvidia.TextureTools.dll - - ..\ThirdParty\Dependencies\SharpFont\x64\SharpFont.dll - ..\ThirdParty\Dependencies\ATI.TextureConverter\ATI.TextureConverter.dll @@ -84,6 +81,8 @@ + + @@ -91,15 +90,9 @@ - - - libFreeImage.so - runtimes\linux-x64\native\libFreeImage.so - PreserveNewest - runtimes\linux-x64\native PreserveNewest @@ -120,15 +113,6 @@ runtimes\linux-x64\native PreserveNewest - - libfreetype6.so - runtimes\linux-x64\native\libfreetype6.so - PreserveNewest - - - runtimes\linux-x64\native - PreserveNewest - linux\ffmpeg runtimes\linux-x64\native\linux @@ -140,11 +124,6 @@ PreserveNewest - - libFreeImage.dylib - runtimes\osx\native\libFreeImage.dylib - PreserveNewest - runtimes\osx\native PreserveNewest @@ -165,11 +144,6 @@ runtimes\osx\native PreserveNewest - - libfreetype6.dylib - runtimes\osx\native\libfreetype6.dylib - PreserveNewest - runtimes\osx\native PreserveNewest @@ -193,10 +167,6 @@ runtimes\win-x64\native PreserveNewest - - runtimes\win-x64\native - PreserveNewest - runtimes\win-x64\native PreserveNewest @@ -209,10 +179,6 @@ runtimes\win-x64\native PreserveNewest - - runtimes\win-x64\native - PreserveNewest - diff --git a/MonoGame.Framework.Content.Pipeline/Processors/FontDescriptionProcessor.cs b/MonoGame.Framework.Content.Pipeline/Processors/FontDescriptionProcessor.cs index c493b554c74..8e417f60def 100644 --- a/MonoGame.Framework.Content.Pipeline/Processors/FontDescriptionProcessor.cs +++ b/MonoGame.Framework.Content.Pipeline/Processors/FontDescriptionProcessor.cs @@ -1,82 +1,82 @@ -// MonoGame - Copyright (C) MonoGame Foundation, Inc -// This file is subject to the terms and conditions defined in -// file 'LICENSE.txt', which is part of this source code package. - -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Linq; -using Microsoft.Win32; -using Microsoft.Xna.Framework.Content.Pipeline.Graphics; -using MonoGame.Framework.Utilities; -using Glyph = Microsoft.Xna.Framework.Content.Pipeline.Graphics.Glyph; - -namespace Microsoft.Xna.Framework.Content.Pipeline.Processors -{ - [ContentProcessor(DisplayName = "Sprite Font Description - MonoGame")] - public class FontDescriptionProcessor : ContentProcessor - { - [DefaultValue(true)] - public virtual bool PremultiplyAlpha { get; set; } - - [DefaultValue(typeof(TextureProcessorOutputFormat), "Compressed")] - public virtual TextureProcessorOutputFormat TextureFormat { get; set; } - - public FontDescriptionProcessor() - { - PremultiplyAlpha = true; - TextureFormat = TextureProcessorOutputFormat.Compressed; - } - - public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context) - { - var output = new SpriteFontContent(input); +// MonoGame - Copyright (C) MonoGame Foundation, Inc +// This file is subject to the terms and conditions defined in +// file 'LICENSE.txt', which is part of this source code package. + +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Linq; +using Microsoft.Win32; +using Microsoft.Xna.Framework.Content.Pipeline.Graphics; +using MonoGame.Framework.Utilities; +using Glyph = Microsoft.Xna.Framework.Content.Pipeline.Graphics.Glyph; + +namespace Microsoft.Xna.Framework.Content.Pipeline.Processors +{ + [ContentProcessor(DisplayName = "Sprite Font Description - MonoGame")] + public class FontDescriptionProcessor : ContentProcessor + { + [DefaultValue(true)] + public virtual bool PremultiplyAlpha { get; set; } + + [DefaultValue(typeof(TextureProcessorOutputFormat), "Compressed")] + public virtual TextureProcessorOutputFormat TextureFormat { get; set; } + + public FontDescriptionProcessor() + { + PremultiplyAlpha = true; + TextureFormat = TextureProcessorOutputFormat.Compressed; + } + + public override SpriteFontContent Process(FontDescription input, ContentProcessorContext context) + { + var output = new SpriteFontContent(input); var fontFile = FindFont(input.FontName, input.Style.ToString()); if (string.IsNullOrWhiteSpace(fontFile)) - { - var directories = new List { Path.GetDirectoryName(input.Identity.SourceFilename) }; + { + var directories = new List { Path.GetDirectoryName(input.Identity.SourceFilename) }; var extensions = new string[] { "", ".ttf", ".ttc", ".otf" }; // Add special per platform directories if (CurrentPlatform.OS == OS.Windows) directories.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "Fonts")); else if (CurrentPlatform.OS == OS.MacOSX) - { + { directories.Add(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library", "Fonts")); directories.Add("/Library/Fonts"); - directories.Add("/System/Library/Fonts/Supplemental"); + directories.Add("/System/Library/Fonts/Supplemental"); } foreach (var dir in directories) - { - foreach (var ext in extensions) - { + { + foreach (var ext in extensions) + { fontFile = Path.Combine(dir, input.FontName + ext); - if (File.Exists(fontFile)) - break; + if (File.Exists(fontFile)) + break; } if (File.Exists(fontFile)) break; - } - } - - if (!File.Exists(fontFile)) + } + } + + if (!File.Exists(fontFile)) throw new FileNotFoundException("Could not find \"" + input.FontName + "\" font file."); context.Logger.LogMessage("Building Font {0}", fontFile); // Get the platform specific texture profile. - var texProfile = TextureProfile.ForPlatform(context.TargetPlatform); - + var texProfile = TextureProfile.ForPlatform(context.TargetPlatform); + { if (!File.Exists(fontFile)) { throw new Exception(string.Format("Could not load {0}", fontFile)); } var lineSpacing = 0f; - int yOffsetMin = 0; + long yOffsetMin = 0; var glyphs = ImportFont(input, out lineSpacing, out yOffsetMin, context, fontFile); var glyphData = new HashSet(glyphs.Select(x => x.Data)); @@ -85,12 +85,12 @@ public override SpriteFontContent Process(FontDescription input, ContentProcesso foreach (GlyphData glyph in glyphData) { GlyphCropper.Crop(glyph); - } - - // We need to know how to pack the glyphs. - bool requiresPot, requiresSquare; - texProfile.Requirements(context, TextureFormat, out requiresPot, out requiresSquare); - + } + + // We need to know how to pack the glyphs. + bool requiresPot, requiresSquare; + texProfile.Requirements(context, TextureFormat, out requiresPot, out requiresSquare); + var face = GlyphPacker.ArrangeGlyphs(glyphData.ToArray(), requiresPot, requiresSquare); // Adjust line and character spacing. @@ -98,7 +98,7 @@ public override SpriteFontContent Process(FontDescription input, ContentProcesso output.VerticalLineSpacing = (int)lineSpacing; foreach (Glyph glyph in glyphs) - { + { output.CharacterMap.Add(glyph.Character); var texRect = glyph.Data.Subrect; @@ -117,59 +117,59 @@ public override SpriteFontContent Process(FontDescription input, ContentProcesso { output.Kerning.Add(new Vector3(0, texRect.Width, 0)); } - } - + } + output.Texture.Faces[0].Add(face); - } - - if (PremultiplyAlpha) - { - var bmp = output.Texture.Faces[0][0]; - var data = bmp.GetPixelData(); - var idx = 0; - for (; idx < data.Length;) - { - var r = data[idx]; - - // Special case of simply copying the R component into the A, since R is the value of white alpha we want - data[idx + 0] = r; - data[idx + 1] = r; - data[idx + 2] = r; - data[idx + 3] = r; - - idx += 4; - } - - bmp.SetPixelData(data); - } - else - { - var bmp = output.Texture.Faces[0][0]; - var data = bmp.GetPixelData(); - var idx = 0; - for (; idx < data.Length;) - { - var r = data[idx]; - - // Special case of simply moving the R component into the A and setting RGB to solid white, since R is the value of white alpha we want - data[idx + 0] = 255; - data[idx + 1] = 255; - data[idx + 2] = 255; - data[idx + 3] = r; - - idx += 4; - } - - bmp.SetPixelData(data); - } - - // Perform the final texture conversion. + } + + if (PremultiplyAlpha) + { + var bmp = output.Texture.Faces[0][0]; + var data = bmp.GetPixelData(); + var idx = 0; + for (; idx < data.Length;) + { + var r = data[idx]; + + // Special case of simply copying the R component into the A, since R is the value of white alpha we want + data[idx + 0] = r; + data[idx + 1] = r; + data[idx + 2] = r; + data[idx + 3] = r; + + idx += 4; + } + + bmp.SetPixelData(data); + } + else + { + var bmp = output.Texture.Faces[0][0]; + var data = bmp.GetPixelData(); + var idx = 0; + for (; idx < data.Length;) + { + var r = data[idx]; + + // Special case of simply moving the R component into the A and setting RGB to solid white, since R is the value of white alpha we want + data[idx + 0] = 255; + data[idx + 1] = 255; + data[idx + 2] = 255; + data[idx + 3] = r; + + idx += 4; + } + + bmp.SetPixelData(data); + } + + // Perform the final texture conversion. texProfile.ConvertTexture(context, output.Texture, TextureFormat, true); - return output; + return output; } - private static Glyph[] ImportFont(FontDescription options, out float lineSpacing, out int yOffsetMin, ContentProcessorContext context, string fontName) + private static Glyph[] ImportFont(FontDescription options, out float lineSpacing, out long yOffsetMin, ContentProcessorContext context, string fontName) { // Which importer knows how to read this source font? IFontImporter importer; @@ -228,11 +228,11 @@ private static Glyph[] ImportFont(FontDescription options, out float lineSpacing } return glyphs.ToArray(); - } - + } + private string FindFont(string name, string style) - { - if (CurrentPlatform.OS == OS.Windows) + { + if (CurrentPlatform.OS == OS.Windows) { var fontDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Windows), "Fonts"); foreach (var key in new RegistryKey[] { Registry.LocalMachine, Registry.CurrentUser }) @@ -253,10 +253,10 @@ private string FindFont(string name, string style) return Path.IsPathRooted(fontPath) ? fontPath : Path.Combine(fontDirectory, fontPath); } } - } - } - else if (CurrentPlatform.OS == OS.Linux) - { + } + } + else if (CurrentPlatform.OS == OS.Linux) + { string s, e; ExternalTool.Run("/bin/bash", string.Format("-c \"fc-match -f '%{{file}}:%{{family}}\\n' '{0}:style={1}'\"", name, style), out s, out e); s = s.Trim(); @@ -284,10 +284,10 @@ private string FindFont(string name, string style) return string.Empty; } - return split[0]; + return split[0]; } - return String.Empty; - } - } -} + return String.Empty; + } + } +} diff --git a/MonoGame.Framework.Content.Pipeline/Utilities/FreeImageAPI.cs b/MonoGame.Framework.Content.Pipeline/Utilities/FreeImageAPI.cs index 618625490ba..e7bce8fdaef 100644 --- a/MonoGame.Framework.Content.Pipeline/Utilities/FreeImageAPI.cs +++ b/MonoGame.Framework.Content.Pipeline/Utilities/FreeImageAPI.cs @@ -94,7 +94,7 @@ internal enum FREE_IMAGE_COLOR_CHANNEL partial class FreeImage { - private const string NativeLibName = "FreeImage"; + private const string NativeLibName = "freeimage"; [DllImport(NativeLibName, EntryPoint = "FreeImage_ConvertFromRawBits")] public static extern IntPtr ConvertFromRawBits(byte[] bits, int width, int height, int pitch, uint bpp, uint red_mask, uint green_mask, uint blue_mask, bool topdown); diff --git a/MonoGame.Framework.Content.Pipeline/Utilities/FreeTypeAPI.cs b/MonoGame.Framework.Content.Pipeline/Utilities/FreeTypeAPI.cs new file mode 100644 index 00000000000..07a87c0bf45 --- /dev/null +++ b/MonoGame.Framework.Content.Pipeline/Utilities/FreeTypeAPI.cs @@ -0,0 +1,269 @@ +// MonoGame - Copyright (C) MonoGame Foundation, Inc +// This file is subject to the terms and conditions defined in +// file 'LICENSE.txt', which is part of this source code package. + +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; + +namespace FreeTypeAPI +{ + enum FT_Pixel_Mode + { + FT_PIXEL_MODE_NONE = 0, + FT_PIXEL_MODE_MONO, + FT_PIXEL_MODE_GRAY, + FT_PIXEL_MODE_GRAY2, + FT_PIXEL_MODE_GRAY4, + FT_PIXEL_MODE_LCD, + FT_PIXEL_MODE_LCD_V, + FT_PIXEL_MODE_BGRA, + + FT_PIXEL_MODE_MAX + }; + + enum FT_Render_Mode + { + FT_RENDER_MODE_NORMAL = 0, + FT_RENDER_MODE_LIGHT, + FT_RENDER_MODE_MONO, + FT_RENDER_MODE_LCD, + FT_RENDER_MODE_LCD_V, + FT_RENDER_MODE_SDF, + + FT_RENDER_MODE_MAX + } + + enum FT_Glyph_Format + { + None = 0, + Composite = ('c' << 24 | 'o' << 16 | 'm' << 8 | 'p'), + Bitmap = ('b' << 24 | 'i' << 16 | 't' << 8 | 's'), + Outline = ('o' << 24 | 'u' << 16 | 't' << 8 | 'l'), + Plotter = ('p' << 24 | 'l' << 16 | 'o' << 8 | 't') + } + + [UnsafeValueType] + unsafe struct FT_Library + { + public nint memory; + + public int version_major; + public int version_minor; + public int version_patch; + + public uint num_modules; + + public fixed long modules[128]; + + public FT_ListRec renderers; + public nint cur_renderer; + public nint auto_hinter; + + public fixed long debug_hooks[4]; + + public fixed long lcd_geometry[6]; + + public int refcount; + + }; + + struct FT_Generic + { + public nint data; + public nint finalizer; + } + + struct FT_BBox + { + public long xMin, yMin, xMax, yMax; + } + + struct FT_ListRec + { + public nint head, tail; + } + + struct FT_Vector + { + public long x, y; + } + + struct FT_Matrix + { + public long xx, xy, yx, yy; + } + + struct FT_Glyph_Metrics + { + public long width, height, horiBearingX, horiBearingY, horiAdvance, vertBearingX, vertBearingY, vertAdvance; + } + + struct FT_Size_Metrics + { + public ushort x_ppem; + public ushort y_ppem; + + public long x_scale; + public long y_scale; + + public long ascender; + public long descender; + public long height; + public long max_advance; + } + + unsafe struct FT_Size + { + public FT_Face* face; + public FT_Generic generic; + public FT_Size_Metrics metrics; + nint inter; + } + + unsafe struct FT_Bitmap + { + public uint rows; + public uint width; + public int pitch; + public byte* buffer; + public ushort num_grays; + public byte pixel_mode; + public byte palette_mode; + public nint palette; + } + + unsafe struct FT_Outline + { + public ushort n_contours; + public ushort n_points; + + public FT_Vector* points; + public byte* tags; + public ushort* contours; + + public int flags; + } + + struct FT_SubGlyph + { + public int index; + public ushort flags; + public int arg1; + public int arg2; + FT_Matrix transform; + } + + unsafe struct FT_Face + { + public long num_faces; + public long face_index; + + public long face_flags; + public long style_flags; + + public long num_glyphs; + + public nint family_name; + public nint style_name; + + public int num_fixed_sizes; + public nint available_sizes; + + public int num_charmaps; + public nint charmaps; + + public FT_Generic generic; + + public FT_BBox bbox; + + public ushort units_per_EM; + public short ascender; + public short descender; + public short height; + + public short max_advance_width; + public short max_advance_height; + + public short underline_position; + public short underline_thickness; + + public FT_GlyphSlot* glyph; + public FT_Size* size; + public nint charmap; + + public nint driver; + public nint memory; + public nint stream; + + public FT_ListRec sizes_list; + + public FT_Generic autohint; + public nint extensions; + + nint intern; + }; + + unsafe struct FT_GlyphSlot + { + public FT_Library* library; + public FT_Face* face; + public FT_GlyphSlot* next; + public uint glyph_index; /* new in 2.10; was reserved previously */ + public FT_Generic generic; + + public FT_Glyph_Metrics metrics; + public long linearHoriAdvance; + public long linearVertAdvance; + public FT_Vector advance; + + public FT_Glyph_Format format; + + public FT_Bitmap bitmap; + public int bitmap_left; + public int bitmap_top; + + public FT_Outline outline; + + public uint num_subglyphs; + public FT_SubGlyph* subglyphs; + + public nint control_data; + public long control_len; + + public long lsb_delta; + public long rsb_delta; + + public nint other; + + nint intern; + } + + internal unsafe partial class FreeType + { + private const string Library = "freetype"; + + [LibraryImport(Library, StringMarshalling = StringMarshalling.Utf8)] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + public static partial int FT_Init_FreeType(out FT_Library* library); + + [LibraryImport(Library, StringMarshalling = StringMarshalling.Utf8)] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + public static partial int FT_New_Face(FT_Library* library, string filepathname, long face_index, out FT_Face* aface); + + [LibraryImport(Library, StringMarshalling = StringMarshalling.Utf8)] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + public static partial uint FT_Get_Char_Index(FT_Face* face, ulong charcode); + + [LibraryImport(Library, StringMarshalling = StringMarshalling.Utf8)] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + public static partial int FT_Load_Glyph(FT_Face* face, uint glyph_index, int load_flags = 0); + + [LibraryImport(Library, StringMarshalling = StringMarshalling.Utf8)] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + public static partial int FT_Render_Glyph(FT_GlyphSlot* slot, FT_Render_Mode render_mode = FT_Render_Mode.FT_RENDER_MODE_NORMAL); + + [LibraryImport(Library, StringMarshalling = StringMarshalling.Utf8)] + [UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])] + public static partial int FT_Set_Char_Size(FT_Face* face, long char_width, long char_height, uint horz_resolution, uint vert_resolution); + } +} diff --git a/Tools/MonoGame.Content.Builder.Editor/Common/PipelineController.cs b/Tools/MonoGame.Content.Builder.Editor/Common/PipelineController.cs index 6257d691715..faf72bf1621 100644 --- a/Tools/MonoGame.Content.Builder.Editor/Common/PipelineController.cs +++ b/Tools/MonoGame.Content.Builder.Editor/Common/PipelineController.cs @@ -32,6 +32,7 @@ public partial class PipelineController : IController #if DEBUG Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "../../../MonoGame.Content.Builder/Debug/mgcb.dll"), Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "../../../../../../MonoGame.Content.Builder/Debug/mgcb.dll"), + "/Users/harry/GitHub/MonoGame/Artifacts/MonoGame.Content.Builder/Debug/mgcb.dll" #else Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "../../../MonoGame.Content.Builder/Release/mgcb.dll"), Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? "", "../../../../../../MonoGame.Content.Builder/Release/mgcb.dll"), diff --git a/Tools/MonoGame.Content.Builder.Editor/MonoGame.Content.Builder.Editor.Mac.csproj b/Tools/MonoGame.Content.Builder.Editor/MonoGame.Content.Builder.Editor.Mac.csproj index 8ed9809e1a9..8beb28bb796 100644 --- a/Tools/MonoGame.Content.Builder.Editor/MonoGame.Content.Builder.Editor.Mac.csproj +++ b/Tools/MonoGame.Content.Builder.Editor/MonoGame.Content.Builder.Editor.Mac.csproj @@ -13,7 +13,7 @@ MGCB Editor $(AssemblyTitle) false - osx-x64 + osx-x64;osx-arm64