Fallback Resources
The fallback resources feature of Prysm 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:
- Add fallback formats to the system settings when initializing the system:
...
// Create system settings
cohtml::SystemSettings sysSettings;
...
// 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);
- 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 Cohtml and
signal success
. If no URL is valid, thensignal failure
.
Here is a pseudocode implementation:
virtual void MyResponseHandler::OnResourceRequest(
const cohtml::IAsyncResourceRequest* request,
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 Cohtml
auto destPtr = response->GetSpace(rawData.size());
// Copy file bytes
MyApp::CopyData(destPtr, rawData, rawData.size());
response->Finish(cohtml::IAsyncResourceResponse::Success);
}