我已经将MemoryStream加载到PrivateFontCollection中,并打印字体-家庭计数。
我已经做了10次了,每次迭代都需要相同的输出。我想要两个迭代的正确输出,有时第一次迭代也会出错。我不能有一个一致的输出。
为我提供一个使用PrivateFontCollection实现一致输出的解决方案。
注意:字体文件夹包含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
发布于 2019-07-27 10:55:58
如果您要做的只是打印存储在目录中的每个字体文件的字体家族的名称,您可以使用这样的方法简化您的代码。
在打印家族名称之前,它按名称对字体文件进行排序。
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()。此方法既可用于字体文件,也可用于添加为的字体数据(它只是一个字节数组)。
Form.FormClosing
重要:这些方法返回的PrivateFontCollection
必须在或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()方法,以防万一。
https://stackoverflow.com/questions/57230437
复制相似问题