gpt4 book ai didi

c# - PrivateFontCollection 系列在迭代次数增加时不可靠

转载 作者:可可西里 更新时间:2023-11-01 10:31:24 33 4
gpt4 key购买 nike

我已将 MemoryStream 加载到 PrivateFontCollection 并打印 Font-Family 计数。

我已经完成了 10 次这些过程,并且我希望每次迭代都获得相同的输出。我想要两次迭代的正确输出,有时第一次迭代也会出错。我无法获得一致的输出。

为我提供一个使用 PrivateFontCollection 获得一致输出的解决方案。
注意:Fonts 文件夹包含 5 种不同的字体。

private static void Work()
{
string fontPath = @"D:\fonts";
PrivateFontCollection fontCollection = null;
for (int i = 1; i < 11; i++)
{
var fileList = Directory.GetFiles(fontPath, "*.ttf", SearchOption.TopDirectoryOnly);
fontCollection = SafeLoadFontFamily(fileList);
Console.WriteLine(i+" Iteration and families count:"+fontCollection.Families.Length);
fontCollection.Dispose();
}
Console.ReadKey();
}
private static PrivateFontCollection SafeLoadFontFamily(IEnumerable<string> fontList)
{
if (fontList == null) return null;
var fontCollection = new PrivateFontCollection();

foreach (string fontFile in fontList)
{
if (!File.Exists(fontFile)) continue;
byte[] fontBytes = File.ReadAllBytes(fontFile);
var fontData = Marshal.AllocCoTaskMem(fontBytes.Length);
Marshal.Copy(fontBytes, 0, fontData, fontBytes.Length);
fontCollection.AddMemoryFont(fontData, fontBytes.Length);
}
return fontCollection;
}

10次的预期输出:
1 次迭代和族数:5
2 迭代和族数:5
3 迭代和族数:5
4 迭代和家族数:5
5 次迭代和族数:5
6 迭代和家族数:5
7 迭代和家族数:5
8 次迭代和族数:5
9 次迭代和族数:5
10 次迭代和族数:5

实际输出:[不一致的输出]
1 次迭代和族数:5
2 迭代和族数:5
3 迭代和族数:5
4 迭代和家族数:5
5 次迭代和族数:4
6 迭代和族数:3
7 迭代和族数:3
8 次迭代和族数:4
9 迭代和家族计数:4
10 次迭代和族数:4

最佳答案

如果您只想打印存储在目录中的每个字体文件的字体系列的名称,您可以使用类似这样的方法来简化代码。

它在打印家族名称之前按名称对字体文件进行排序。

string fontsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fonts");
var fontFiles = Directory.GetFiles(fontsPath).OrderBy(s => s).ToList();

fontFiles.ForEach(f => {
using (var fontCollection = new PrivateFontCollection())
{
fontCollection.AddFontFile(f);
Console.WriteLine(fontCollection.Families[0].Name);
};
});

如果您想保留字体家族名称列表(用于其他用途),请将每个家族名称添加到 List<string> (作为一个字段,在这里):

//  As a field
List<string> fontNames = new List<string>();


// Inside a method
var fontFiles = Directory.GetFiles(fontsPath).ToList();
fontFiles.ForEach(f => {
using (var fontCollection = new PrivateFontCollection())
{
fontCollection.AddFontFile(f);
fontNames.Add(fontCollection.Families[0].Name);
};
});
fontNames = fontNames.OrderBy(s => s).ToList();
fontNames.ForEach(familyName => Console.WriteLine(familyName));

使用 PrivateFontCollection.AddMemoryFont() .此方法可用于字体文件和来自作为项目资源添加的字体的字体数据(它只是一个字节数组)。

重要:PrivateFontCollection这些方法返回必须在 Form.FormClosing 中处理掉 Form.FormClosed (或处理应用程序终止的位置)。

调用这些传递文件路径集合的方法:

// Field/Class object
PrivateFontCollection fontCollection = null;
// (...)
// Somewhere else
string fontsPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "fonts");
var fontFiles = Directory.GetFiles(fontsPath);

fontCollection = UnsafeLoadFontFamily(fontFiles);
// Or...
fontCollection = SafeLoadFontFamily(fontFiles);

fontCollection.Families.OrderBy(f => f.Name).ToList().ForEach(font =>
{
Console.WriteLine(font.GetName(0));
});

使用 unsafe模式和一个字节*指针:
(必须在项目的 Properties -> Build 面板中启用不安全代码)

private unsafe PrivateFontCollection UnsafeLoadFontFamily(IEnumerable<string> fontList)
{
if (fontList.Length == 0) return null;
var fontCollection = new PrivateFontCollection();

foreach (string fontFile in fontList)
{
if (!File.Exists(fontFile)) continue;
byte[] fontData = File.ReadAllBytes(fontFile);
fixed (byte* fontPtr = fontData)
{
fontCollection.AddMemoryFont(new IntPtr(fontPtr), fontData.Length);
}
}
return fontCollection;
}

使用 Marshal.AllocCoTaskMem()Marshal.Copy() .
不要打电话 Marshal.FreeCoTaskMem()这里。可能会出现字体损坏。调用PrivateFontCollection.Dispose()相反,如前所述。

private PrivateFontCollection SafeLoadFontFamily(IEnumerable<string> fontList)
{
if (fontList == null) return null;
var fontCollection = new PrivateFontCollection();

foreach (string fontFile in fontList)
{
if (!File.Exists(fontFile)) continue;
byte[] fontBytes = File.ReadAllBytes(fontFile);
var fontData = Marshal.AllocCoTaskMem(fontBytes.Length);
Marshal.Copy(fontBytes, 0, fontData, fontBytes.Length);
fontCollection.AddMemoryFont(fontData, fontBytes.Length);
}
return fontCollection;
}

打印字体集内容:

string fontPath = [The Fonts Path];
PrivateFontCollection fontCollection = null;
for (int i = 0; i < 5; i++) {
var fileList = Directory.GetFiles(fontPath, "*.ttf", SearchOption.TopDirectoryOnly);
fontCollection = SafeLoadFontFamily(fileList);
fontCollection.Families.ToList().ForEach(ff => Console.WriteLine(ff.Name));
fontCollection.Dispose();
}

System.Windows.Media 提供 Fonts.GetFontFamilies()方法,以防万一。

关于c# - PrivateFontCollection 系列在迭代次数增加时不可靠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57230437/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com