Files
GTASource/rage/scaleform/Src/GFxPlayer/GFxLoadProcess.cpp
expvintl 419f2e4752 init
2025-02-23 17:40:52 +08:00

760 lines
26 KiB
C++

/**********************************************************************
Filename : GFxLoadProcess.ccp
Content : GFxLoadProcess - tracks loading and binding state.
Created :
Authors :
Copyright : (c) 2001-2006 Scaleform Corp. All Rights Reserved.
Notes : This file contains class declarations used in
GFxPlayerImpl.cpp only. Declarations that need to be
visible by other player files should be placed
in GFxCharacter.h.
Licensees may use this file in accordance with the valid Scaleform
Commercial License Agreement provided with the software.
This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING
THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR ANY PURPOSE.
**********************************************************************/
#include "GFxLoadProcess.h"
#include "GJPEGUtil.h"
#include "GFile.h"
#include "GFxAudio.h"
// For GFxMovieRoot::IsPathAbsolute
//#include "GFxPlayerImpl.h"
// ***** GFxLoadStates
GFxLoadStates::GFxLoadStates() : ThreadedLoading(false)
{
//printf("GFxLoadStates::GFxLoadStates : %x, thread : %d\n", this, GetCurrentThreadId());
}
GFxLoadStates::GFxLoadStates(GFxLoaderImpl* pimpl, GFxStateBag* pstates,
GFxMovieDefBindStates *pbindStates)
: ThreadedLoading(false)
{
//printf("GFxLoadStates::GFxLoadStates : %x, thread : %d\n", this, GetCurrentThreadId());
pLoaderImpl = pimpl;
pWeakResourceLib = pimpl->GetWeakLib();
// If pstates is null, states comde from loader.
if (!pstates)
pstates = pimpl;
// Capture states.
// We may override bind states when loading fonts from FontLib.
pBindStates = pbindStates ? *new GFxMovieDefBindStates(pbindStates) :
*new GFxMovieDefBindStates(pstates);
pLog = pstates->GetLog();
pParseControl = pstates->GetParseControl();
pProgressHandler = pstates->GetProgressHandler();
pFontCacheManager = pstates->GetFontCacheManager();
pTaskManager = pstates->GetTaskManager();
// Record render config so that it can be used for image creation during loading.
pRenderConfig = pstates->GetRenderConfig();
pJpegSupport = pstates->GetJpegSupport();
pZlibSupport = pstates->GetZlibSupport();
pPNGSupport = pstates->GetPNGSupport();
#ifndef GFC_NO_VIDEO
pVideoPlayerState = pstates->GetVideo();
#endif
#ifndef GFC_NO_SOUND
pAudioState = pstates->GetAudio();
#endif
}
GFxLoadStates::~GFxLoadStates()
{
//printf("GFxLoadStates::~GFxLoadStates : %x, thread : %d\n", this, GetCurrentThreadId());
}
// Obtains an image creator, but only if image data is not supposed to
// be preserved; considers GFxLoader::LoadKeepBindData flag from arguments.
GFxImageCreator* GFxLoadStates::GetLoadTimeImageCreator(UInt loadConstants) const
{
// Image creator is only used as a key if it is bound to, as specified
// by flags and IsKeepingImageData member.
GFxImageCreator* pkeyImageCreator = 0;
if (!(loadConstants & GFxLoader::LoadKeepBindData) &&
pBindStates->pImageCreator &&
!pBindStates->pImageCreator->IsKeepingImageData())
{
pkeyImageCreator = pBindStates->pImageCreator.GetPtr();
}
return pkeyImageCreator;
}
// Initializes the relative path.
void GFxLoadStates::SetRelativePathForDataDef(GFxMovieDataDef* pdef)
{
GASSERT(pdef != 0);
// Extract and store relative path from parent def.
RelativePath = pdef->GetFileURL();
if (!GFxURLBuilder::ExtractFilePath(&RelativePath))
RelativePath.Clear();
}
// Implementation that allows us to override the log.
GFile* GFxLoadStates::OpenFile(const char *pfilename, UInt loadConstants)
{
if (!pBindStates->pFileOpener)
{
// Don't even have a way to open the file.
if (pLog && !(loadConstants & GFxLoader::LoadQuietOpen))
pLog->LogError(
"Error: GFxLoader failed to open '%s', GFxFileOpener not installed\n",
pfilename);
return 0;
}
return pBindStates->pFileOpener->OpenFileEx(pfilename, (loadConstants & GFxLoader::LoadQuietOpen)? 0 : pLog);
}
// Perform filename translation and/or copy by relying on translator.
void GFxLoadStates::BuildURL(GString *pdest, const GFxURLBuilder::LocationInfo &loc) const
{
GASSERT(pdest);
GFxURLBuilder* pbuilder = pBindStates->pURLBulider;
if (!pbuilder)
GFxURLBuilder::DefaultBuildURL(pdest, loc);
else
pbuilder->BuildURL(pdest, loc);
}
// Helper that clones load states, pBindSates.
// The only thing left un-copied is GFxMovieDefBindStates::pDataDef
GFxLoadStates* GFxLoadStates::CloneForImport() const
{
GPtr<GFxMovieDefBindStates> pnewBindStates = *new GFxMovieDefBindStates(pBindStates);
GFxLoadStates* pnewStates = new GFxLoadStates;
if (pnewStates)
{
pnewStates->pBindStates = pnewBindStates;
pnewStates->pLoaderImpl = pLoaderImpl;
pnewStates->pLog = pLog;
pnewStates->pProgressHandler = pProgressHandler;
pnewStates->pTaskManager = pTaskManager;
pnewStates->pFontCacheManager = pFontCacheManager;
pnewStates->pParseControl = pParseControl;
pnewStates->pWeakResourceLib = pWeakResourceLib;
pnewStates->pJpegSupport = pJpegSupport;
pnewStates->pZlibSupport = pZlibSupport;
pnewStates->pPNGSupport = pPNGSupport;
// Must copy RenderConfig, even though it's not a binding state.
pnewStates->pRenderConfig = pRenderConfig;
#ifndef GFC_NO_SOUND
pnewStates->pAudioState = pAudioState;
#endif
#ifndef GFC_NO_VIDEO
pnewStates->pVideoPlayerState = pVideoPlayerState;
#endif
}
return pnewStates;
}
bool GFxLoadStates::SubmitBackgroundTask(GFxLoaderTask* ptask)
{
if (!pTaskManager)
return false;
// pLoaderImpl->RegisterLoadProcess(ptask);
if (!pTaskManager->AddTask(ptask))
{
// pLoaderImpl->UnRegisterLoadProcess(ptask);
return false;
}
return true;
}
// ***** GFxLoadProcess
GFxLoadProcess::GFxLoadProcess(GFxMovieDataDef* pdataDef,
GFxLoadStates *pstates, UInt loadFlags)
: GFxLoaderTask(pstates, Id_MovieDataLoad), ProcessInfo(pdataDef->GetHeap())
{
#ifdef GFC_DEBUG_COUNT_TAGS
TagCounts.Add(GFxTag_PlaceObject, TagCountType("PlaceObject", sizeof(GFxPlaceObject)));
TagCounts.Add(GFxTag_PlaceObject2, TagCountType("PlaceObject2", sizeof(GFxPlaceObject2)));
TagCounts.Add(GFxTag_PlaceObject3, TagCountType("PlaceObject3", sizeof(GFxPlaceObject3)));
TagCounts.Add(GFxTag_SetBackgroundColor, TagCountType("SetBackgroundColor", sizeof(GFxSetBackgroundColor)));
TagCounts.Add(GFxTag_RemoveObject, TagCountType("RemoveObject", sizeof(GFxRemoveObject)));
TagCounts.Add(GFxTag_RemoveObject2, TagCountType("RemoveObject2", sizeof(GFxRemoveObject2)));
TagCounts.Add(GFxTag_DoAction, TagCountType("DoAction", 0));
TagCounts.Add(GFxTag_DoInitAction, TagCountType("DoInitAction", 0));
#endif
// Save states.
//pStates = pstates;
// Cache parse flags for quick accesss.
ParseFlags = pstates->pParseControl.GetPtr() ?
pstates->pParseControl->GetParseFlags() : 0;
// Initialize other data used during loading.
pLoadData = pdataDef->pData;
pDataDef_Unsafe = pdataDef; // For GFxSpriteDef argument only!
pTimelineDef = 0;
pJpegIn = 0;
LoadFlags = loadFlags;
LoadState = LS_LoadingRoot;
// Avoid resizing frame arrays to 0 (extra allocations). // Anachronism
//FrameTags[0].SetSizePolicy(GArrayPolicy::Buffer_NoShrink);
//FrameTags[1].SetSizePolicy(GArrayPolicy::Buffer_NoShrink);
//InitActionTags.SetSizePolicy(GArrayPolicy::Buffer_NoShrink);
ImportIndex = 0;
ImportDataCount = 0;
ResourceDataCount = 0;
FontDataCount = 0;
// Clear linked lists.
pImportData = pImportDataLast = 0;
pResourceData = pResourceDataLast = 0;
pFontData = pFontDataLast = 0;
pAltStream = NULL;
pTempBindData = 0;
}
GFxLoadProcess::~GFxLoadProcess()
{
#ifdef GFC_DEBUG_COUNT_TAGS
GFC_DEBUG_MESSAGE(1, ">");
GFC_DEBUG_MESSAGE1(1, "> Loading %s..",FilePath.ToCStr());
GHashIdentity<GFxTagType, TagCountType>::ConstIterator iter = TagCounts.Begin();
for (; iter != TagCounts.End(); ++iter)
{
const TagCountType& count = iter->Second;
GFC_DEBUG_MESSAGE3(1, "> %s loaded: %d (CSZ: %db)", count.Name, count.Count, count.ClassSize);
}
GFC_DEBUG_MESSAGE(1, ">");
#endif
// Clear JPEG loader if it was used.
if (pJpegIn)
delete pJpegIn;
// Notify any waiters that our task thread is done with
// all of its references to loaded data.
#ifndef GFC_NO_THREADSUPPORT
GPtr<GFxLoadUpdateSync> ploadSync = pLoadData->GetFrameUpdateSync();
#endif
ProcessInfo.ShutDown();
pLoadData.Clear();
pBindProcess.Clear();
#ifndef GFC_NO_THREADSUPPORT
ploadSync->NotifyLoadFinished();
#endif
}
bool GFxLoadProcess::BeginSWFLoading(GFile *pfile)
{
#ifdef GFC_DEBUG_COUNT_TAGS
FilePath = pfile->GetFilePath();
#endif
// Read header while logging messages as appropriate, fail on wrong file format.
if (!ProcessInfo.Initialize(pfile, GetLog(), pLoadStates->GetZlibSupport(), pLoadStates->pParseControl, true))
return false;
pLoadData->BeginSWFLoading(ProcessInfo.Header);
return true;
}
void GFxLoadProcess::ReadRgbaTag(GColor *pc, GFxTagType tagType)
{
if (tagType <= GFxTag_DefineShape2)
GetStream()->ReadRgb(pc);
else
GetStream()->ReadRgba(pc);
}
GFxTimelineDef::Frame GFxLoadProcess::TagArrayToFrame(ExecuteTagArrayType &tagArray)
{
GFxTimelineDef::Frame frame;
if (tagArray.GetSize())
{
UPInt memSize = sizeof(GASExecuteTag*) * tagArray.GetSize();
if ((frame.pTagPtrList = (GASExecuteTag**)AllocTagMemory(memSize)) != 0)
{
memcpy(frame.pTagPtrList, &tagArray[0], memSize);
frame.TagCount = (UInt)tagArray.GetSize();
}
tagArray.Clear();
}
return frame;
}
// Apply frame tags that have been accumulated to the MovieDef.
void GFxLoadProcess::CommitFrameTags()
{
// Add frame to time-line. Timeline can be either MovieDataDef or SpriteDef.
if (LoadState == LS_LoadingSprite)
{
GASSERT(pTimelineDef);
pTimelineDef->SetLoadingPlaylistFrame(TagArrayToFrame(FrameTags[LoadState]));
}
else
{
pLoadData->SetLoadingPlaylistFrame(TagArrayToFrame(FrameTags[LoadState]));
pLoadData->SetLoadingInitActionFrame(TagArrayToFrame(InitActionTags));
}
}
// Cleans up frame tags; only used if loading was canceled.
void GFxLoadProcess::CleanupFrameTags()
{
UPInt i;
for(i=0; i<FrameTags[LS_LoadingSprite].GetSize(); i++)
FrameTags[LS_LoadingSprite][i]->~GASExecuteTag();
for(i=0; i<FrameTags[LS_LoadingRoot].GetSize(); i++)
FrameTags[LS_LoadingRoot][i]->~GASExecuteTag();
for(i=0; i<InitActionTags.GetSize(); i++)
InitActionTags[i]->~GASExecuteTag();
FrameTags[LS_LoadingSprite].Clear();
FrameTags[LS_LoadingRoot].Clear();
InitActionTags.Clear();
}
// Adds a new resource and generates a handle for it.
GFxResourceHandle GFxLoadProcess::AddDataResource(GFxResourceId rid, const GFxResourceData &resData)
{
// We get back a handle with a new bind index.
GFxResourceHandle rh = pLoadData->AddNewResourceHandle(rid);
GFxMovieDataDef::DefBindingData& bd = pLoadData->BindData;
GFxResourceDataNode* pnode = pLoadData->AllocMovieDefClass<GFxResourceDataNode>();
if (pnode)
{
pnode->Data = resData;
pnode->BindIndex = rh.GetBindIndex();
// Initialize beginnings of local and global lists.
if (!pResourceData)
pResourceData = pnode;
// Insert data in the end of the global list.
if (!bd.pResourceNodes)
bd.pResourceNodes = pnode;
else
bd.pResourceNodesLast->pNext = pnode;
bd.pResourceNodesLast = pnode;
ResourceDataCount++;
}
return rh;
}
static GFxFontResourceCreator static_inst;
GFxResourceHandle GFxLoadProcess::AddFontDataResource(GFxResourceId rid, GFxFont* pfontData)
{
// We get back a handler with bind index.
GFxResourceData resData(&static_inst, pfontData);
GFxResourceHandle rh = AddDataResource(rid, resData);
GFxFontDataUseNode* pfnode = pLoadData->AllocMovieDefClass<GFxFontDataUseNode>();
if (pfnode)
{
GFxMovieDataDef::DefBindingData& bd = pLoadData->BindData;
pfnode->Id = rid;
pfnode->pFontData = pfontData;
pfnode->BindIndex = rh.GetBindIndex();
// Initialize this node as the beginning of the list.
if (!pFontData)
pFontData = pfnode;
// Insert data in the end of the global list.
if (!bd.pFonts)
bd.pFonts = pfnode;
else
bd.pFontsLast->pNext = pfnode;
bd.pFontsLast = pfnode;
FontDataCount++;
}
return rh;
}
void GFxLoadProcess::AddImportData(GFxImportData* pnode)
{
pnode->ImportIndex = ImportIndex;
ImportIndex++;
// Insert data node in a list.
if (!pImportData)
pImportData = pnode;
GFxMovieDataDef::DefBindingData& bd = pLoadData->BindData;
if (!bd.pImports)
bd.pImports = pnode;
else
bd.pImportsLast->pNext = pnode;
bd.pImportsLast = pnode;
ImportDataCount++;
}
// Add a dynamically-loaded image resource, with unique key.
// This is normally used for SWF embedded images.
void GFxLoadProcess::AddImageResource(GFxResourceId rid, GImage *pimage)
{
GFxImageCreator* pkeyImageCreator = pLoadStates->GetLoadTimeImageCreator(LoadFlags);
// Image creator is only used as a key if it is bound to, based on flags.
if (pkeyImageCreator)
{
GFxImageCreateInfo icreateInfo;
GPtr<GImageInfoBase> pimageInfo;
icreateInfo.pHeap = GetLoadHeap();
icreateInfo.SetStates(0, pLoadStates->GetRenderConfig(),
pLoadStates->GetLog(),pLoadStates->GetJpegSupport(), pLoadStates->GetPNGSupport());
icreateInfo.ThreadedLoading = pLoadStates->IsThreadedLoading();
if (pimage)
icreateInfo.SetImage(pimage);
if (GetBindStates()->pImageCreator)
pimageInfo= *GetBindStates()->pImageCreator->CreateImage(icreateInfo);
GPtr<GFxImageResource> pch = *GHEAP_NEW(icreateInfo.pHeap) GFxImageResource(pimageInfo.GetPtr());
AddResource(rid, pch);
}
else
{
// Creation of image resource is delayed due to late binding.
// Create image resource data instead. This data will be used during binding.
GFxResourceData rdata = GFxImageResourceCreator::CreateImageResourceData(pimage);
AddDataResource(rid, rdata);
}
}
// Creates a frame binding object; should be called only when
// a root frame is finished. Clears the internal import/font/resource lists.
GFxFrameBindData* GFxLoadProcess::CreateFrameBindData()
{
GFxFrameBindData* pbdata = pLoadData->AllocMovieDefClass<GFxFrameBindData>();
if (pbdata)
{
// Frame and Bytes loaded will be assigned by the caller.
// pbdata->Frame = ?;
// pbdata->FrameBytesLoaded= ?;
pbdata->ImportCount = ImportDataCount;
pbdata->pImportData = pImportData;
pbdata->FontCount = FontDataCount;
pbdata->pFontData = pFontData;
pbdata->ResourceCount = ResourceDataCount;
pbdata->pResourceData = pResourceData;
ImportDataCount = 0;
ResourceDataCount = 0;
FontDataCount = 0;
// Clear data pointers. We do not clear the data Last pointers,
// allowing a full list of imports to be built up in the MovieDef.
pImportData = 0;
pResourceData = 0;
pFontData = 0;
}
return pbdata;
}
// ***** GFxImageResourceCreator - Image creator from files
// Creates/Loads resource based on data and loading process
bool GFxImageFileResourceCreator::CreateResource(DataHandle hdata, GFxResourceBindData *pbindData,
GFxLoadStates *pls, GMemoryHeap *pbindHeap) const
{
GFxImageFileInfo *prfi = (GFxImageFileInfo*) hdata;
GASSERT(prfi);
GUNUSED(pbindHeap); // Don't use bindHeap for shared resources.
// Make a new fileInfo so that it can have a modified filename.
GPtr<GFxImageFileInfo> pimageFileInfo = *GNEW GFxImageFileInfo(*prfi);
// Ensure format
// TBD: If we always save the format for texture tags in gfxexport we
// would not need to do this. Verify.
if ((pimageFileInfo->Format == GFxLoader::File_Unknown) && pimageFileInfo->pExporterInfo)
pimageFileInfo->Format =
(GFxFileConstants::FileFormatType) pimageFileInfo->pExporterInfo->Format;
// Translate filename.
GFxURLBuilder::LocationInfo loc(GFxURLBuilder::File_ImageImport,
prfi->FileName, pls->GetRelativePath());
pls->BuildURL(&pimageFileInfo->FileName, loc);
// Now that we have a correct file object we need to match it against
// the library so as to check if is is already loaded
GMemoryHeap* pimageHeap = pls->GetLib()->GetImageHeap();
GFxResourceKey imageKey =
GFxImageResource::CreateImageFileKey(pimageFileInfo,
pls->GetFileOpener(),
pls->GetBindStates()->pImageCreator,
pimageHeap);
GString errorMessage;
GFxResourceLib::BindHandle bh;
GPtr<GFxImageResource> pimageRes = 0;
if (pls->GetLib()->BindResourceKey(&bh, imageKey) == GFxResourceLib::RS_NeedsResolve)
{
// If not found, create an object of the right type.
GFxImageCreateInfo ico;
ico.SetType(GFxImageCreateInfo::Input_File);
ico.Use = prfi->Use;
if (prfi->Flags & GFxImageFileInfo::Wrappable)
ico.SetTextureUsage(GTexture::Usage_Wrap);
else
ico.SetTextureUsage (0);
ico.pHeap = pimageHeap;
ico.pFileInfo = pimageFileInfo.GetPtr();
ico.SetStates(pls->GetFileOpener(), pls->GetRenderConfig(),
pls->GetLog(), pls->GetJpegSupport(),pls->GetPNGSupport());
ico.ThreadedLoading = pls->IsThreadedLoading();
ico.pExportName = prfi->ExportName.ToCStr();
GPtr<GImageInfoBase> pimage;
GFxImageCreator* pcreator = pls->GetBindStates()->pImageCreator;
if (pcreator)
pimage = *pcreator->CreateImage(ico);
else
GFC_DEBUG_WARNING(1, "Image resource creation failed - GFxImageCreator not installed");
if (pimage)
pimageRes = *GHEAP_NEW(ico.pHeap) GFxImageResource(pimage.GetPtr(), imageKey, ico.Use);
// Need to read header first.
if (pimageRes)
bh.ResolveResource(pimageRes);
else
{
errorMessage = "Failed to load image '";
errorMessage += pimageFileInfo->FileName;
errorMessage += "'";
bh.CancelResolve(errorMessage.ToCStr());
}
}
else
{
// If Available and Waiting resources will be resolved here.
if ((pimageRes = *(GFxImageResource*)bh.WaitForResolve()).GetPtr() == 0)
{
errorMessage = bh.GetResolveError();
}
}
// If there was an error, display it
if (!pimageRes)
{
pls->pLog->LogError("Error: %s\n", errorMessage.ToCStr());
return 0;
}
// Pass resource ownership to BindData.
pbindData->pResource = pimageRes;
return 1;
}
GFxResourceData GFxImageFileResourceCreator::CreateImageFileResourceData(GFxImageFileInfo * prfi)
{
static GFxImageFileResourceCreator inst;
return GFxResourceData(&inst, prfi);
}
// Creates/Loads resource based on GImage during binding process
bool GFxImageResourceCreator::CreateResource(DataHandle hdata, GFxResourceBindData *pbindData,
GFxLoadStates *pls, GMemoryHeap *pbindHeap) const
{
GImage *pimage = (GImage*) hdata;
GASSERT(pimage);
// Create resource from image.
GFxImageCreateInfo icreateInfo(pimage, GFxResource::Use_None);
icreateInfo.SetStates(0, pls->GetRenderConfig(), pls->GetLog(),
pls->GetJpegSupport(),pls->GetPNGSupport());
icreateInfo.ThreadedLoading = pls->IsThreadedLoading();
icreateInfo.pHeap = pbindHeap;
GPtr<GImageInfoBase> pimageInfo;
GFxImageCreator* pcreator = pls->GetBindStates()->pImageCreator;
if (!pcreator)
{
GFC_DEBUG_WARNING(1, "Image resource creation failed - GFxImageCreator not installed");
return 0;
}
if (pcreator)
pimageInfo= *pcreator->CreateImage(icreateInfo);
if (!pimageInfo)
return 0;
GPtr<GFxImageResource> pimageRes = *GHEAP_NEW(pbindHeap) GFxImageResource(pimageInfo.GetPtr());
if (!pimageRes)
return 0;
// Pass resource ownership to BindData.
pbindData->pResource = pimageRes;
return 1;
}
GFxResourceData GFxImageResourceCreator::CreateImageResourceData(GImage* pimage)
{
static GFxImageResourceCreator inst;
//!AB: pimage might be NULL if ZLIB is not linked and zlib-compresed image is found.
if (pimage)
return GFxResourceData(&inst, pimage);
else
return GFxResourceData();
}
bool GFxSubImageResourceCreator::CreateResource(DataHandle hdata, GFxResourceBindData *pbindData,
GFxLoadStates *pls, GMemoryHeap *pbindHeap) const
{
GFxSubImageResourceInfo* pinfo = (GFxSubImageResourceInfo*)hdata;
GASSERT(pinfo);
GUNUSED(pls);
GFxImageResource* pimageRes = pinfo->Image;
if (!pimageRes)
{
GFxResourceHandle rh;
pbindData->pBinding->GetOwnerDefImpl()->GetDataDef()->GetResourceHandle(&rh, pinfo->ImageId);
GFxResource* pres = rh.GetResource(pbindData->pBinding);
if (pres && pres->GetResourceType() == GFxResource::RT_Image)
pimageRes = (GFxImageResource*)pres;
}
if (pimageRes)
{
GImageInfoBase* pbaseimage = pimageRes->GetImageInfo();
if (pbaseimage->GetImageInfoType() == GImageInfoBase::IIT_ImageInfo)
((GImageInfo*)pbaseimage)->SetTextureUsage(0);
pbindData->pResource =
*GHEAP_NEW(pbindHeap) GFxSubImageResource(pimageRes, GFxResourceId(0),
pinfo->Rect, pbindHeap);
return 1;
}
return 0;
}
GFxResourceData GFxSubImageResourceCreator::CreateSubImageResourceData(GFxSubImageResourceInfo* pinfo)
{
static GFxSubImageResourceCreator inst;
return GFxResourceData(&inst, pinfo);
}
// ***** GFxFontResourceCreator - Font resource creator to use during binding
// Creates/Loads resource based on data and loading process.
bool GFxFontResourceCreator::CreateResource(DataHandle hdata, GFxResourceBindData *pbindData,
GFxLoadStates *pls, GMemoryHeap *pbindHeap) const
{
GFxFont *pfd = (GFxFont*) hdata;
GASSERT(pfd);
// 1) Traverse through potential substitute fonts to see if substitution
// needs to take place.
// FontResourceCreator may be responsible for substituting glyphs from
// other files with '_glyphs' in their name.
GArray<GPtr<GFxMovieDefImpl> >& fontDefs = pls->SubstituteFontMovieDefs;
for(UInt ifontDef=0; ifontDef<fontDefs.GetSize(); ifontDef++)
{
GFxMovieDefImpl* pdefImpl = fontDefs[ifontDef];
GFxFontDataUseNode* psourceFont =
pdefImpl->GetDataDef()->GetFirstFont();
// Search imports for the font with the same name which has glyphs.
for(; psourceFont != 0; psourceFont = psourceFont->pNext)
{
GFxFont *psourceFontData = psourceFont->pFontData;
if (psourceFontData->GetGlyphShapeCount() > 0)
{
if (pfd->MatchSubstituteFont(psourceFontData))
{
// Set our binding.
// Note: Unlike us, the source is guaranteed to be fully loaded when
// this takes place, so we can just look up its binding.
// Set binding together with its internal table.
pdefImpl->GetResourceBinding().
GetResourceData(pbindData, psourceFont->BindIndex);
return 1;
}
}
}
}
// 2) Not substitution. Create a font based on our data.
// First, try to create a system font if the shape has no glyphs.
if (!pfd->HasVectorOrRasterGlyphs() && pfd->GetName())
{
// Just set not resolved flag for the font. This will instruct
// FontManager to search this font through FontLib or FontProvider
pfd->SetNotResolvedFlag();
}
// If this is not a system font, create one based on out FontData.
if (!pbindData->pResource)
{
// Our GFxMovieDefImpl's pBinding should have been provided by caller.
pbindData->pResource = *GHEAP_NEW(pbindHeap) GFxFontResource(pfd, pbindData->pBinding);
}
// We could do font glyph rendering here, however it is better to delay it
// till the end of frame binding so that textures from several fonts
// can be potentially combined.
return pbindData->pResource ? 1 : 0;
}