我一直在与从嵌入文件加载字体以与DirectWrite一起使用的斗争中失败。我正在写一个简单的益智游戏,它有一个C#/XAML接口,但也使用SurfaceImageSource添加一些DirectX内容。
我已经编写了一个WinRT组件,它可以处理所有DirectX代码,并且工作得很好。我的一些DirectX内容是使用DirectWrite API绘制的文本。只要我使用IDWriteFactory::GetSystemFontCollection()等从系统加载已安装的字体,我就可以绘制所有我喜欢的文本。但是,我似乎找不到从嵌入式文件加载自定义字体的方法。
据我所知,Metro应用程序不允许像传统应用程序那样从文件系统加载文件。因此,采用普通文件路径的IDWriteFactory::CreateFontFileReference()方法对我来说毫无价值,对吧?我需要从ms-appx URL加载我的文件。
因此,我在WinRT组件中编写了一个自定义字体加载器,它实现了IDWriteFontCollectionLoader接口(如果您以前从未做过,这将是一项艰巨的工作),该接口使用新的StorageFileAPI从ms-appx URL加载字体。现在,我可以加载我的IDWriteFontFile,并且可以获得IDWriteFontFace。但是,如果我尝试调用字体上任何真正有用的方法,它会返回E_UNEXPECTED。我可以获得字形的数量和字形索引,但如果我尝试调用类似于GetGlyphRunOutline()或GetDesignGlyphMetrics()东西,它会以E_UNEXPECTED失败。使用使用GetGlyphRunOutline()生成ID2D1PathGeometry的同一绘图代码非常有效,只要我安装了字体文件,并通过从IDWriteFactory::GetSystemFontCollection()始的一系列调用获得IDWriteFontFace。我使用的是普通的真字体。
那么,如何在Metro应用程序中将嵌入文件中的自定义字体加载到DirectWrite中呢?我可能只是错过了一些简单的东西,因为我确信其他人会希望能够以这种方式加载自定义字体。
我有一个示例项目(或者可以很容易地准备一个),供任何可以帮助我识别问题的人使用。
我已经并排加载了两个IDWriteFontFace对象,并试图弄清楚有效对象和中断对象之间的区别。为了找出它失败的原因,我需要看到的是隐藏在IDWriteFontFace接口后面的不透明内容。请帮忙!
问题也发布在这里:用DirectX Forum 构建Metro风格的游戏
答案是…不要编写IDWriteFontCollectionLoader!您可以将IDWriteFactory::CreateFontFileReference()与StorageFileAPI一起使用。从我参加的所有微软会议会谈中,我的印象是,在Metro中,您将无法直接访问本机文件系统;前进的方法是使用StorageFileneneneba API,该API使用ms-appxURL引用资源等。我知道这样做是为了并发,并允许操作系统通过创建文件系统沙盒将自己与从商店下载的Metro应用程序隔离开来。我认为这是准确的。但是,我觉得我被引导去相信,我们永远无法获得本机文件系统路径。这不是真的IStorageFile提供了一种方法。只需使用IStorageFile。路径。我从未查看过它,因为我只是假设Path属性将包含我用于创建对象的ms-appx URL。微软提供这个可能正是为了解决我上面的问题:调用需要本机路径的遗留COM接口。
如果你试图访问自己的应用程序包之外的本机文件系统路径,我还没有做任何测试来确定WinRT框架是否真的会对你进行沙盒处理。我打赌它确实。。。