PrivateFontCollection Families 不可靠,迭代次数越多 [英] PrivateFontCollection Families are not reliable with more iterations
问题描述
我已将 MemoryStream 加载到 PrivateFontCollection 并打印字体系列计数.
I've load the MemoryStream to a PrivateFontCollection and print the Font-Family count.
我已经完成了 10 次这些过程,我希望每次迭代都有相同的输出.我想要两次迭代的正确输出,有时第一次迭代也会出错.我无法获得一致的输出.
I've done these process for 10 times and I want the same output for every iteration. I want correct output for two iterations and sometimes the first iteration is also going wrong. I can't have a consistent output.
为我提供使用 PrivateFontCollection 获得一致输出的解决方案.
注意:字体文件夹包含 5 种不同的字体.
Provide me a solution to have a consistent output using PrivateFontCollection.
Note: Fonts folder contains 5 different fonts.
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
Expected output for 10 times:
1 Iteration and families count:5
2 Iteration and families count:5
3 Iteration and families count:5
4 Iteration and families count:5
5 Iteration and families count:5
6 Iteration and families count:5
7 Iteration and families count:5
8 Iteration and families count:5
9 Iteration and families count:5
10 Iteration and families count:5
实际输出:[不一致输出]
1 迭代和家庭计数:5
2 迭代和家庭计数:5
3 迭代和家庭计数:5
4 迭代和家庭计数:5
5 迭代和家庭计数:4
6 迭代和家庭计数:3
7 迭代和家庭计数:3
8 迭代和家庭计数:4
9 迭代和家庭计数:4
10 次迭代和家庭计数:4
Actual output:[ inconsistent output]
1 Iteration and families count:5
2 Iteration and families count:5
3 Iteration and families count:5
4 Iteration and families count:5
5 Iteration and families count:4
6 Iteration and families count:3
7 Iteration and families count:3
8 Iteration and families count:4
9 Iteration and families count:4
10 Iteration and families count:4
推荐答案
如果您只想打印存储在目录中的每个 Font 文件的 Font Family 名称,您可以使用类似这样的东西来简化您的代码.
If all you want to do is to print the name of the Font Family of each Font file stored in a directory, you can simplify your code with something like this.
它在打印姓氏之前按名称对字体文件进行排序.
It orders the Font files by name before printing the Family name.
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
(此处作为字段):
If you instead want to preserve the list of the Fonts Family names (for other uses), add each Family name to a List<string>
(as a Field, here):
// 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().此方法可用于字体文件和作为项目资源添加的字体中的字体数据(它只是一个字节数组).
Using PrivateFontCollection.AddMemoryFont(). This method can be used for both Font Files and font data from a Font added as a Project Resource (it's just a byte array).
重要:这些方法返回的 PrivateFontCollection
必须在 Form.FormClosing
或 Form.FormClosed
(或处理应用程序终止的地方).
Important: The PrivateFontCollection
that these methods return MUST be disposed of in the Form.FormClosing
or Form.FormClosed
(or where the application's termination is handled).
通过文件路径集合调用这些方法:
Call these methods passing a collection of file paths:
// 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
模式和 byte* 指针:
(必须在项目的Properties -> Build
面板中启用不安全代码)
Using unsafe
mode and a byte* pointer:
(Unsafe code must be enabled in the Project's Properties -> Build
panel)
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()
.
Using Marshal.AllocCoTaskMem() and Marshal.Copy().
Do not call Marshal.FreeCoTaskMem() here. Font curruption may occur. Call PrivateFontCollection.Dispose()
instead, as already mentioned.
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() 方法,以防万一.
这篇关于PrivateFontCollection Families 不可靠,迭代次数越多的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!