教程19:资源提供者
资源提供者
在Noesis中,可以使用资源提供程序自定义加载资源的过程。每种资源都有一个提供程序:Xaml,Texture和Font。通常在Noesis初始化后设置每个提供程序。
Noesis::GUI::SetXamlProvider(xamlProvider);
Noesis::GUI::SetTextureProvider(textureProvider);
Noesis::GUI::SetFontProvider(fontProvider);
这三种提供程序共享相同的文件抽象,即Stream接口。
class Stream: public BaseComponent
{
public:
/// Set the current position within the stream
virtual void SetPosition(uint32_t pos) = 0;
/// Returns the current position within the stream
virtual uint32_t GetPosition() const = 0;
/// Returns the length of the stream in bytes
virtual uint32_t GetLength() const = 0;
/// Reads data at the current position and advances it by the number of bytes read
/// Returns the total number of bytes read. This can be less than the number of bytes requested
virtual uint32_t Read(void* buffer, uint32_t size) = 0;
};
XAML提供者
实现xamls提供程序的基类是XamlProvider。
class XamlProvider: public BaseComponent
{
public:
// Loads the specified XAML file. Returns null if no xaml found
virtual Ptr<Stream> LoadXaml(const char* uri) = 0;
};
实现很简单。您基本上必须为所请求的每个uri提供一个流。您可以在应用程序框架中找到两个XamlProvider实现,LocalXamlProvider用于从磁盘加载XAML,EmbeddedXamlProvider用于加载嵌入在可执行文件中的XAML。
纹理提供者
纹理提供程序有点复杂,因为您需要实现两个不同的功能。在主线程中,布局过程需要有关纹理尺寸的信息。您可以通过GetTextureInfo函数提供该信息。真正加载纹理的函数是LoadTexture,它总是从渲染线程调用。
class TextureProvider: public BaseComponent
{
public:
/// Returns metadata for the given texture. 0 x 0 is returned if no texture found
virtual TextureInfo GetTextureInfo(const char* uri) = 0;
/// Returns a texture compatible with the given device. Null is returned if no texture found
virtual Ptr<Texture> LoadTexture(const char* uri, RenderDevice* device) = 0;
};
该应用程序框架提供了一个辅助类,FileTextureProvider,将从图像为您创建纹理。它公开了一个虚拟函数,您必须实现该虚拟函数来加载请求的文件名。
class FileTextureProvider: public Noesis::TextureProvider
{
protected:
virtual Ptr<Stream> OpenStream(const char* uri) const = 0;
};
与XamlProvider相似,您可以在应用程序框架中找到LocalTextureProvider和EmbeddedTextureProvider实现。
字体提供者
字体提供程序的实现更为复杂。负责加载字体的基类是FontProvider。
class FontProvider: public BaseComponent
{
public:
/// Finds the font in the given folder that best matches the specified properties
/// BaseUri is the directory where the search is performed or nullptr for system fonts
/// Returns a null stream if no matching found
virtual FontSource MatchFont(const char* baseUri, const char* familyName, FontWeight weight,
FontStretch stretch, FontStyle style) = 0;
/// Returns true if the requested font family exists in given directory
/// BaseUri is the directory where the search is performed or nullptr for system fonts
virtual bool FamilyExists(const char* baseUri, const char* familyName) = 0;
};
为了帮助实现此提供程序,有一个中间类CachedFontProvider可以扫描文件夹并从.ttf和.otf文件中提取家族信息。它还基于W3C规范实现字体匹配算法。
CachedFontProvider公开了两个虚拟函数ScanFolder和OpenFont:
- 在ScanFolder中,您必须注册给定文件夹中所有可用的字体。通过调用RegisterFont注册每种字体。
- OpenFont是负责提供与每个已注册文件名相对应的流的功能。
class CachedFontProvider: public FontProvider
{
protected:
/// Registers a font filename in the given folder. Each time this function is invoked, the
/// given filename is opened and scanned (through OpenFont). It is recommened deferring
/// this call as much as possible (for example, until ScanFolder is invoked)
void RegisterFont(const char* folder, const char* filename);
/// First time a font is requested from a folder, this function is invoked to give inheritors
/// the opportunity to register faces found in that folder
virtual void ScanFolder(const char* folder);
/// Returns a stream to a previously registered filename
virtual Ptr<Stream> OpenFont(const char* folder, const char* filename) const = 0;
};
注意
默认情况下,CachedFontProvider也将扫描系统字体。可以通过执行“ SetUseSystemFonts(false)”来禁用它。
与其他提供程序类似,LocalFontProvider和EmbeddedFontProvider是应用程序框架中可用的示例实现。