1.14.0.5
Hummingbird
A modern user interface library for games
Fallback Resources

Fallback resources is a feature of Hummingbird that allows developers to choose to load different formats from those specified in the HTML. This is very convenient for image formats, for example, because developers would prefer to use ASTC compressed images on Android, ETC2 images on iOS, DDS on Windows, etc.. This can be done very easily with our fallback feature.

Example usage can be found in the SampleImageFallbackFormats sample. To use this feature we have to do the following steps:

  1. Add fallback formats to the system settings when initializing the system:
...
// Create system settings
...
// Create fallback formats data
SystemSettings::FallBackFormats formats;
std::vector<const char*> extensionsData;
std::vector<const char*> baseExtensions;
std::vector<SystemSettings::FallBackFormats::FallBackFormat> allFallbackFormats;
allFallbackFormats.resize(1);
// On iOS we will fallback from png to ktx format
#if defined(PLATFORM_IOS)
baseExtensions.push_back("png");
extensionsData.push_back("ktx");
// On Android we will fallback from png to astc format
#elif defined(PLATFORM_ANDROID)
baseExtensions.push_back("png");
extensionsData.push_back("astc");
// On Windows or Mac we will fallback from png to dds format
#elif defined(PLATFORM_WIN) || defined(PLATFORM_MACOSX)
baseExtensions.push_back("png");
extensionsData.push_back("dds");
#endif
// We add png again in case we do not find
// astc, dds or ktx and will try to load png
extensionsData.push_back("png");
formats.Formats = allFallbackFormats.data();
formats.FormatsSize = unsigned(allFallbackFormats.size());
for (auto i = 0u; i < allFallbackFormats.size(); ++i)
{
formats.Formats[i].BaseFormat = baseExtensions[i];
formats.Formats[i].Extensions = extensionsData.data();
formats.Formats[i].ExtensionsSize = unsigned(extensionsData.size());
}
sysSettings.Formats = formats;
...
// Initialize other things
...
// Initialize the system
m_System = m_Library->CreateSystem(sysSettings);
  1. Override cohtml::IAsyncResourceHandler::OnResourceRequest in the resource handler.
  • In the OnResourceRequest method we get the first fallback format that we have specified.
  • If this format is not found, we call cohtml::IAsyncResourceRequest::GetFallbackURLs(). This method will return all the remaining fallback URLs as an array.
  • We traverse this array and try to load the given URLs until an existing one is found. Copy file data to Hummingbird and signal success. If no URL is valid, then signal failure.

Here is a pseudocode implementation:

virtual void MyResponseHandler::OnResourceRequest(
html::IAsyncResourceResponse* response) override
{
std::string url = request->GetURL();
auto rawData = MyApp::GetFileBytes(url);
if (!rawData)
{
// Try other fallback formats that we have specified
// by calling IAsyncResourceRequest::GetFallbackURLs
cohtml::IAsyncResourceRequest::FallbackURLsData fallbackData = request->GetFallbackURLs();
for (unsigned i = 0; i < fallbackData.Count; ++i)
{
rawData = MyApp::GetFileBytes(fallbackData.Data[i]);
if (rawData)
{
// We found a existing file with fallback URL
break;
}
}
if (!rawData)
{
// We have not found the any of the fallback URLs
response->Finish(cohtml::IAsyncResourceResponse::Failure);
return;
}
}
// We allocate space for the raw data in Hummingbird
auto destPtr = response->GetSpace(rawData.size());
// Copy file bytes in Hummingbird
MyApp::CopyData(destPtr, rawData, rawData.size());
response->Finish(cohtml::IAsyncResourceResponse::Success);
}