Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: [SystemFontProvider] - Implement GetFontPath for Linux #2295

Merged
merged 6 commits into from
May 29, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public AssetCompilerResult Prepare(AssetCompilerContext context, AssetItem asset
// Try to compile only if we're sure that the sources exist.
if (EnsureSourcesExist(result, assetItem))
{
Prepare((AssetCompilerContext)context, assetItem, assetItem.Location.GetDirectoryAndFileName(), result);
Prepare(context, assetItem, assetItem.Location.GetDirectoryAndFileName(), result);
}

return result;
Expand Down
6 changes: 2 additions & 4 deletions sources/assets/Stride.Core.Assets/Package.cs
Original file line number Diff line number Diff line change
Expand Up @@ -933,12 +933,10 @@ private void LoadAsset(AssetMigrationContext context, PackageLoadingAssetFile as
// Try to load only if asset is not already in the package or assetRef.Asset is null
var assetPath = assetFile.AssetLocation;

var assetFullPath = fileUPath.ToWindowsPath();
var assetFullPath = fileUPath.ToOSPath();
var assetContent = assetFile.AssetContent;

bool aliasOccurred;
AttachedYamlAssetMetadata yamlMetadata;
var asset = LoadAsset(context.Log, Meta.Name, assetFullPath, assetPath.ToWindowsPath(), assetContent, out aliasOccurred, out yamlMetadata);
var asset = LoadAsset(context.Log, Meta.Name, assetFullPath, assetPath.ToOSPath(), assetContent, out var aliasOccurred, out var yamlMetadata);

// Create asset item
var assetItem = new AssetItem(assetPath, asset, this)
Expand Down
129 changes: 84 additions & 45 deletions sources/engine/Stride.Assets/SpriteFont/SystemFontProvider.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
// Copyright (c) .NET Foundation and Contributors (https://dotnetfoundation.org/ & https://stride3d.net) and Silicon Studio Corp. (https://www.siliconstudio.co.jp)
// Distributed under the MIT license. See the LICENSE.md file in the project root for more information.

using System.Linq;
using SharpDX.DirectWrite;
using Stride.Core.Assets.Compiler;
using SharpFont;
using Stride.Assets.SpriteFont.Compiler;
using Stride.Core;
using Stride.Core.Assets.Compiler;
using Stride.Core.Diagnostics;
using Stride.Assets.SpriteFont.Compiler;
using Stride.Graphics.Font;
using System;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: sort usings

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually. System usings are first and then the rest in dictionary order. But that's ok here.

We might even use implicit usings later which would hide those.

using System.Linq;

namespace Stride.Assets.SpriteFont
{
Expand All @@ -17,11 +18,9 @@ public class SystemFontProvider : FontProviderBase
{
private static readonly Logger Log = GlobalLogger.GetLogger("SystemFontProvider");

public const string DefaultFontName = "Arial";

public SystemFontProvider()
{
FontName = DefaultFontName;
FontName = GetDefaultFontName();
}

public SystemFontProvider(string fontName)
Expand Down Expand Up @@ -52,72 +51,112 @@ public SystemFontProvider(string fontName)
/// <inheritdoc/>
public override FontFace GetFontFace()
{
var factory = new Factory();
using var factory = new Factory();

SharpDX.DirectWrite.Font font;
Font font;
using (var fontCollection = factory.GetSystemFontCollection(false))
{
int index;
if (!fontCollection.FindFamilyName(FontName, out index))
if (!fontCollection.FindFamilyName(FontName, out var index))
{
// Lets try to import System.Drawing for old system bitmap fonts (like MS Sans Serif)
throw new FontNotFoundException(FontName);
}

using (var fontFamily = fontCollection.GetFontFamily(index))
{
var weight = Style.IsBold() ? FontWeight.Bold : FontWeight.Regular;
var style = Style.IsItalic() ? SharpDX.DirectWrite.FontStyle.Italic : SharpDX.DirectWrite.FontStyle.Normal;
font = fontFamily.GetFirstMatchingFont(weight, FontStretch.Normal, style);
}
using var fontFamily = fontCollection.GetFontFamily(index);
var weight = Style.IsBold() ? FontWeight.Bold : FontWeight.Regular;
var style = Style.IsItalic() ? SharpDX.DirectWrite.FontStyle.Italic : SharpDX.DirectWrite.FontStyle.Normal;
font = fontFamily.GetFirstMatchingFont(weight, FontStretch.Normal, style);
}

return new FontFace(font);
}

public override string GetFontPath(AssetCompilerResult result = null)
{
using (var factory = new Factory())
if (OperatingSystem.IsWindows())
return GetFontPathWindows(result);
if (OperatingSystem.IsLinux())
{
Font font;
var fontPath = GetFontPathLinux(result);
if (fontPath == null && FontName != GetDefaultFontName())
{
result?.Warning($"Cannot find font family '{FontName}'. Loading default font '{GetDefaultFontName()}' instead");
FontName = GetDefaultFontName();
fontPath = GetFontPathLinux(result);
}
return fontPath;
}
return null;
}

using (var fontCollection = factory.GetSystemFontCollection(false))
private string GetFontPathLinux(AssetCompilerResult result)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIt: code style, empty line between methods

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, I added new line

{
StyleFlags flags = StyleFlags.None;
if (Style.IsBold())
flags |= StyleFlags.Bold;
if (Style.IsItalic())
flags |= StyleFlags.Italic;

string systemFontDirectory = "/usr/share/fonts";
var files = System.IO.Directory.EnumerateFiles(systemFontDirectory, "*.ttf", System.IO.SearchOption.AllDirectories);

var library = new SharpFont.Library();
foreach (string file in files)
{
var face = new Face(library, file);
if (face.FamilyName.Contains(FontName) && face.StyleFlags == flags)
{
int index;
if (!fontCollection.FindFamilyName(FontName, out index))
{
result?.Error($"Cannot find system font '{FontName}'. Make sure it is installed on this machine.");
return null;
}

using (var fontFamily = fontCollection.GetFontFamily(index))
{
var weight = Style.IsBold() ? FontWeight.Bold : FontWeight.Regular;
var style = Style.IsItalic() ? SharpDX.DirectWrite.FontStyle.Italic : SharpDX.DirectWrite.FontStyle.Normal;
font = fontFamily.GetFirstMatchingFont(weight, FontStretch.Normal, style);
if (font == null)
{
result?.Error($"Cannot find style '{Style}' for font family {FontName}. Make sure it is installed on this machine.");
return null;
}
}
return file;
}
}
result?.Error($"Cannot find style '{Style}' for font family '{FontName}'. Make sure it is installed on this machine.");
return null;
}

private string GetFontPathWindows(AssetCompilerResult result)
{
using var factory = new Factory();
Font font;

var fontFace = new FontFace(font);
using (var fontCollection = factory.GetSystemFontCollection(false))
{
if (!fontCollection.FindFamilyName(FontName, out var index))
{
result?.Error($"Cannot find system font '{FontName}'. Make sure it is installed on this machine.");
return null;
}

// get the font path on the hard drive
var file = fontFace.GetFiles().First();
var referenceKey = file.GetReferenceKey();
var originalLoader = (FontFileLoaderNative)file.Loader;
var loader = originalLoader.QueryInterface<LocalFontFileLoader>();
return loader.GetFilePath(referenceKey);
using var fontFamily = fontCollection.GetFontFamily(index);
var weight = Style.IsBold() ? FontWeight.Bold : FontWeight.Regular;
var style = Style.IsItalic() ? SharpDX.DirectWrite.FontStyle.Italic : SharpDX.DirectWrite.FontStyle.Normal;
font = fontFamily.GetFirstMatchingFont(weight, FontStretch.Normal, style);
if (font == null)
{
result?.Error($"Cannot find style '{Style}' for font family {FontName}. Make sure it is installed on this machine.");
return null;
}
}

var fontFace = new FontFace(font);

// get the font path on the hard drive
var file = fontFace.GetFiles().First();
var referenceKey = file.GetReferenceKey();
var originalLoader = (FontFileLoaderNative)file.Loader;
var loader = originalLoader.QueryInterface<LocalFontFileLoader>();
return loader.GetFilePath(referenceKey);
}

/// <inheritdoc/>
public override string GetFontName()
{
return FontName;
}

private static string GetDefaultFontName()
{
//Note : Both macOS and Windows contains Arial
return OperatingSystem.IsLinux() ? "Liberation" : "Arial";
}
}
}