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

245 lines
7.8 KiB
C++

/**********************************************************************
Filename : GFxFontLib.cpp
Content : Implementation of font sharing and lookup through
a list of registed GFxMovieDef's.
Created : July 9, 2007
Authors : Michael Antonov
Copyright : (c) 2001-2007 Scaleform Corp. All Rights Reserved.
Notes :
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 "GFxFontLib.h"
#include "GFxFontResource.h"
#include "GFxMovieDef.h"
#include "GFxLoadProcess.h"
// ***** GFxFontLib class
// GFxFontLib stores smart pointers to GFxMovieDataDef instead of
// GFxMovieDefImpl. This is important to avoid circular ref-counting
// cycles between the states, movie def and font lib. The actual
// DefImpl is instead looked up through CreateMovie, which in most cases
// will just return a new pointer from GFxResourceLib.
// An additional benefit we get from such late binding is the use of
// correct states for the imported font movies; these states are taken
// from the context that referenced the font. These states affect
// texture packing, image creation and other aspects of loading.
// GFxFontLibImpl is used to hide the implementation details of GFxFontLib.
class GFxFontLibImpl : public GNewOverrideBase<GStat_Default_Mem>
{
public:
// A list of GFxMovieDataDef pointers to movies
// that serve as a source for fonts
GArray<GPtr<GFxMovieDataDef> > FontMovies;
};
//------------------------------------------------------------------------
GFxFontLib::GFxFontLib()
: GFxState(GFxState::State_FontLib),
pImpl(new GFxFontLibImpl)
{
}
GFxFontLib::~GFxFontLib()
{
delete pImpl;
}
void GFxFontLib::AddFontsFrom(GFxMovieDef* md, bool pin)
{
GFxMovieDefImpl *pmdi = (GFxMovieDefImpl*)md;
if (pImpl && pmdi)
{
pImpl->FontMovies.PushBack(pmdi->GetDataDef());
if (pin)
md->PinResource();
}
}
bool GFxFontLib::AreAllMoviesLoaded() const
{
if (!pImpl)
return true;
for (UPInt i = 0; i<pImpl->FontMovies.GetSize(); i++)
{
GFxMovieDataDef *pdataDef = pImpl->FontMovies[i];
if (pdataDef->GetLoadState() < GFxMovieDataDef::LS_LoadFinished)
return false;
}
return true;
}
// *** FontResult - stores smart pointers to result with hidden implementation
void GFxFontLib::FontResult::SetResult(GFxMovieDef* pmovieDef, GFxFontResource* pfont)
{
if (pmovieDef)
pmovieDef->AddRef();
if (pfont)
pfont->AddRef();
if (pMovieDef)
pMovieDef->Release();
if (pFontResource)
pFontResource->Release();
pMovieDef = pmovieDef;
pFontResource = pfont;
}
GFxFontLib::FontResult::~FontResult()
{
if (pMovieDef)
pMovieDef->Release();
if (pFontResource)
pFontResource->Release();
}
// Finds or creates a font of specified style by searching all of the
// registered GFxMovieDef objects. The font resource is created to be compatible
// with puserDef's binding states and utilizing pstates for non-binding
// state values.
bool GFxFontLib::FindFont(FontResult *presult,
const char* pfontname, UInt fontFlags,
GFxMovieDef* puserDef, GFxStateBag *pstates, GFxResourceWeakLib* pweakLib)
{
// We keep device font bits for matching so that FontManager can correctly
// try device fonts before non-device ones.
fontFlags &= GFxFont::FF_CreateFont_Mask| GFxFont::FF_DeviceFont;
// First, find a matching font in our MovieDefs.
if (!pImpl)
return 0;
UInt i, fontBindIndex = 0;
GFxMovieDataDef *pdataDef = 0;
bool fontFound = 0;
GPtr<GFxMovieDefImpl> pfontDefImpl;
for (i = 0; (i<pImpl->FontMovies.GetSize()) && !fontFound; i++)
{
// TBD: We will need to do something about threading here, since it is legit
// to call GetFontResource while loading still hasn't completed.
pdataDef = pImpl->FontMovies[i];
// Make sure that MovieDataDef has finished loading,
// otherwise all fonts wouldn't be there yet.
pdataDef->WaitForLoadFinish();
// Font traversal IS thread safe due to the way linked list is updated.
GFxFontDataUseNode* pfont = pdataDef->GetFirstFont();
for(; pfont != 0; pfont = pfont->pNext)
{
if (pfont->pFontData->MatchFont(pfontname, fontFlags))
{
fontBindIndex = pfont->BindIndex;
fontFound = 1;
break;
}
}
}
if (!fontFound)
return 0;
if (puserDef)
{
GFxMovieDefImpl* pudi = (GFxMovieDefImpl*) puserDef;
// Create loadStates with:
// 1) Binding states from puserDef
// 2) Dynamic states from psharedStates. These will probably come
// from GFxMovieRoot for the instance which is using this font.
GPtr<GFxLoadStates> pls = *new GFxLoadStates(pudi->pLoaderImpl,
pstates,
pudi->pBindStates);
// Get movieDef. Most of the time this will just look up MovieDefImpl
// in the library without performing the actual binding.
pfontDefImpl =
*pudi->pLoaderImpl->CreateMovie_LoadState(pls, pdataDef, pudi->GetLoadFlags() |
GFxLoader::LoadWaitCompletion);
}
else if (pweakLib)
{
// if userDef is NULL - try to create a MovieDefImpl from scratch.
// This is a hacky solution and useful only for DrawText API with using FontLib.
// Create loadStates with:
// 1) New binding states with states from 'pstates'
// 2) Resource lib from parameter
GPtr<GFxLoaderImpl> loaderImpl = *new GFxLoaderImpl(pstates, pweakLib->GetResourceLib());
GPtr<GFxMovieDefBindStates> bs = *new GFxMovieDefBindStates(pstates);
GPtr<GFxLoadStates> pls = *new GFxLoadStates(loaderImpl, pstates, bs);
// Get movieDef. Most of the time this will just look up MovieDefImpl
// in the library without performing the actual binding.
pfontDefImpl =
*loaderImpl->CreateMovie_LoadState(pls, pdataDef, GFxLoader::LoadWaitCompletion);
}
if (!pfontDefImpl)
return 0;
// TBD: Threading - Should we wait for binding to complete?
GFxResourceBindData rbd;
pfontDefImpl->GetResourceBinding().GetResourceData(&rbd, fontBindIndex);
if (rbd.pResource)
{
GASSERT(rbd.pResource->GetResourceType() == GFxResource::RT_Font);
presult->SetResult(pfontDefImpl, (GFxFontResource*) rbd.pResource.GetPtr());
return 1;
}
return 0;
}
// Loads font names into destination string array
void GFxFontLib::LoadFontNames(GStringHash<GString>& fontnames)
{
if (!pImpl)
return;
for (UInt i = 0; (i<pImpl->FontMovies.GetSize()); i++)
{
// TBD: We will need to do something about threading here, since it is legit
// to call GetFontResource while loading still hasn't completed.
GFxMovieDataDef* pdataDef = pImpl->FontMovies[i];
// Make sure that MovieDataDef has finished loading,
// otherwise all fonts wouldn't be there yet.
pdataDef->WaitForLoadFinish();
// Font traversal IS thread safe due to the way linked list is updated.
GFxFontDataUseNode* pfont = pdataDef->GetFirstFont();
for(; pfont != 0; pfont = pfont->pNext)
{
GString fontname(pfont->pFontData->GetName());
fontnames.Set(fontname, fontname);
}
}
}