PrivateFontCollection系列不可靠,迭代次数更多 [英] PrivateFontCollection Families are not reliable with more iterations

查看:77
本文介绍了PrivateFontCollection系列不可靠,迭代次数更多的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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< string> (此处为字段):

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 模式和字节*指针:
(必须在项目的 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 提供 查看全文

登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆