vcl: PhysicalFontFamily now handles it's own list of font faces

The internal linked list has now been removed from PhysicalFontFace
and a std::vector is used within PhysicalFontFamily, which is the
class that actually should be managing the storage of font face
instances.

Change-Id: I4f0c5f8831c3f3b60b81b814ca8ea8e2f2e1e7a9
Reviewed-on: https://gerrit.libreoffice.org/20922
Reviewed-by: Chris Sherlock <chris.sherlock79@gmail.com>
Tested-by: Chris Sherlock <chris.sherlock79@gmail.com>
This commit is contained in:
Chris Sherlock
2015-12-25 00:40:38 +11:00
parent a4764cfa80
commit a20a52a2f4
4 changed files with 65 additions and 66 deletions

View File

@@ -60,7 +60,6 @@ public:
int GetFontMagic() const { return mnMagic; }
bool IsScalable() const { return (mnHeight == 0); }
bool CheckMagic( int n ) const { return (n == mnMagic); }
PhysicalFontFace* GetNextFace() const { return mpNext; }
bool IsBetterMatch( const FontSelectPattern&, FontMatchStatus& ) const;
sal_Int32 CompareWithSize( const PhysicalFontFace& ) const;
@@ -78,7 +77,6 @@ protected:
private:
friend class PhysicalFontFamily;
const int mnMagic; // poor man's RTTI
PhysicalFontFace* mpNext;
};
#endif // INCLUDED_VCL_INC_PHYSICALFONTFACE_HXX

View File

@@ -52,7 +52,7 @@ public:
ImplFontAttrs GetMatchType() const { return mnMatchType ; }
FontWeight GetMatchWeight() const { return meMatchWeight ; }
FontWidth GetMatchWidth() const { return meMatchWidth ; }
bool IsScalable() const { return mpFirst->IsScalable(); }
bool IsScalable() const { return maFontFaces[0]->IsScalable(); }
int GetMinQuality() const { return mnMinQuality; }
int GetTypeFaces() const { return mnTypeFaces; }
bool AddFontFace( PhysicalFontFace* );
@@ -69,7 +69,8 @@ static void CalcType( ImplFontAttrs& rType, FontWeight& rWeight, Fon
FontFamily eFamily, const utl::FontNameAttr* pFontAttr );
private:
PhysicalFontFace* mpFirst; // linked list of physical font faces
std::vector< PhysicalFontFace* > maFontFaces;
OUString maName; // Fontname (original font family name)
OUString maSearchName; // normalized font family name
OUString maMapNames; // fontname aliases

View File

@@ -30,7 +30,6 @@ PhysicalFontFace::PhysicalFontFace( const ImplDevFontAttributes& rDFA, int nMagi
, mnWidth(0)
, mnHeight(0)
, mnMagic( nMagic )
, mpNext( nullptr )
{
// StarSymbol is a unicode font, but it still deserves the symbol flag
if( !IsSymbolFont() )

View File

@@ -90,8 +90,7 @@ static ImplFontAttrs lcl_IsCJKFont( const OUString& rFontName )
}
PhysicalFontFamily::PhysicalFontFamily( const OUString& rSearchName )
: mpFirst( nullptr ),
maSearchName( rSearchName ),
: maSearchName( rSearchName ),
mnTypeFaces( 0 ),
mnMatchType( ImplFontAttrs::None ),
meMatchWeight( WEIGHT_DONTKNOW ),
@@ -104,96 +103,90 @@ PhysicalFontFamily::PhysicalFontFamily( const OUString& rSearchName )
PhysicalFontFamily::~PhysicalFontFamily()
{
// release all physical font faces
while( mpFirst )
for( std::vector< PhysicalFontFace* >::iterator it=maFontFaces.begin(); it != maFontFaces.end(); )
{
PhysicalFontFace* pFace = mpFirst;
mpFirst = pFace->GetNextFace();
delete pFace;
delete *it;
it = maFontFaces.erase( it );
}
}
bool PhysicalFontFamily::AddFontFace( PhysicalFontFace* pNewData )
bool PhysicalFontFamily::AddFontFace( PhysicalFontFace* pNewFontFace )
{
pNewData->mpNext = nullptr;
if( !mpFirst )
if( maFontFaces.empty() )
{
maName = pNewData->GetFamilyName();
maMapNames = pNewData->maMapNames;
meFamily = pNewData->GetFamilyType();
mePitch = pNewData->GetPitch();
mnMinQuality = pNewData->mnQuality;
maName = pNewFontFace->GetFamilyName();
maMapNames = pNewFontFace->maMapNames;
meFamily = pNewFontFace->GetFamilyType();
mePitch = pNewFontFace->GetPitch();
mnMinQuality = pNewFontFace->mnQuality;
}
else
{
if( meFamily == FAMILY_DONTKNOW )
meFamily = pNewData->GetFamilyType();
meFamily = pNewFontFace->GetFamilyType();
if( mePitch == PITCH_DONTKNOW )
mePitch = pNewData->GetPitch();
if( mnMinQuality > pNewData->mnQuality )
mnMinQuality = pNewData->mnQuality;
mePitch = pNewFontFace->GetPitch();
if( mnMinQuality > pNewFontFace->mnQuality )
mnMinQuality = pNewFontFace->mnQuality;
}
// set attributes for attribute based font matching
if( pNewData->IsScalable() )
if( pNewFontFace->IsScalable() )
mnTypeFaces |= FONT_FAMILY_SCALABLE;
if( pNewData->IsSymbolFont() )
if( pNewFontFace->IsSymbolFont() )
mnTypeFaces |= FONT_FAMILY_SYMBOL;
else
mnTypeFaces |= FONT_FAMILY_NONESYMBOL;
if( pNewData->GetWeight() != WEIGHT_DONTKNOW )
if( pNewFontFace->GetWeight() != WEIGHT_DONTKNOW )
{
if( pNewData->GetWeight() >= WEIGHT_SEMIBOLD )
if( pNewFontFace->GetWeight() >= WEIGHT_SEMIBOLD )
mnTypeFaces |= FONT_FAMILY_BOLD;
else if( pNewData->GetWeight() <= WEIGHT_SEMILIGHT )
else if( pNewFontFace->GetWeight() <= WEIGHT_SEMILIGHT )
mnTypeFaces |= FONT_FAMILY_LIGHT;
else
mnTypeFaces |= FONT_FAMILY_NORMAL;
}
if( pNewData->GetSlant() == ITALIC_NONE )
if( pNewFontFace->GetSlant() == ITALIC_NONE )
mnTypeFaces |= FONT_FAMILY_NONEITALIC;
else if( (pNewData->GetSlant() == ITALIC_NORMAL)
|| (pNewData->GetSlant() == ITALIC_OBLIQUE) )
else if( (pNewFontFace->GetSlant() == ITALIC_NORMAL)
|| (pNewFontFace->GetSlant() == ITALIC_OBLIQUE) )
mnTypeFaces |= FONT_FAMILY_ITALIC;
// reassign name (sharing saves memory)
if( pNewData->GetFamilyName() == GetFamilyName() )
pNewData->SetFamilyName( GetFamilyName() );
if( pNewFontFace->GetFamilyName() == GetFamilyName() )
pNewFontFace->SetFamilyName( GetFamilyName() );
// insert new physical font face into linked list
// TODO: get rid of linear search?
PhysicalFontFace* pData;
PhysicalFontFace** ppHere = &mpFirst;
for(; (pData=*ppHere) != nullptr; ppHere=&pData->mpNext )
for(std::vector< PhysicalFontFace* >::iterator it=maFontFaces.begin(); it != maFontFaces.end(); ++it )
{
sal_Int32 eComp = pNewData->CompareWithSize( *pData );
PhysicalFontFace* pFoundFontFace = *it;
sal_Int32 eComp = pNewFontFace->CompareWithSize( *pFoundFontFace );
if( eComp > 0 )
continue;
if( eComp < 0 )
break;
// ignore duplicate if its quality is worse
if( pNewData->mnQuality < pData->mnQuality )
if( pNewFontFace->mnQuality < pFoundFontFace->mnQuality )
return false;
// keep the device font if its quality is good enough
if( (pNewData->mnQuality == pData->mnQuality)
&& (pData->mbDevice || !pNewData->mbDevice) )
if( (pNewFontFace->mnQuality == pFoundFontFace->mnQuality) && (pFoundFontFace->mbDevice || !pNewFontFace->mbDevice) )
return false;
// replace existing font face with a better one
pNewData->mpNext = pData->mpNext;
*ppHere = pNewData;
delete pData;
delete pFoundFontFace;
it = maFontFaces.erase( it );
maFontFaces.push_back( pNewFontFace );
return true;
}
// insert into or append to list of physical font faces
pNewData->mpNext = pData;
*ppHere = pNewData;
maFontFaces.push_back( pNewFontFace );
return true;
}
@@ -218,16 +211,16 @@ void PhysicalFontFamily::InitMatchData( const utl::FontSubstConfiguration& rFont
PhysicalFontFace* PhysicalFontFamily::FindBestFontFace( const FontSelectPattern& rFSD ) const
{
if( !mpFirst )
if( maFontFaces.empty() )
return nullptr;
if( !mpFirst->GetNextFace() )
return mpFirst;
if( maFontFaces.size() == 1)
return maFontFaces[0];
// FontName+StyleName should map to FamilyName+StyleName
const OUString& rSearchName = rFSD.maTargetName;
OUString aTargetStyleName;
const OUString* pTargetStyleName = nullptr;
if( (rSearchName.getLength() > maSearchName.getLength())
if((rSearchName.getLength() > maSearchName.getLength())
&& rSearchName.startsWith( maSearchName ) )
{
aTargetStyleName = rSearchName.copy(maSearchName.getLength() + 1);
@@ -235,12 +228,14 @@ PhysicalFontFace* PhysicalFontFamily::FindBestFontFace( const FontSelectPattern&
}
// TODO: linear search improve!
PhysicalFontFace* pFontFace = mpFirst;
PhysicalFontFace* pBestFontFace = pFontFace;
PhysicalFontFace* pBestFontFace = maFontFaces[0];
FontMatchStatus aFontMatchStatus = {0,0,0, pTargetStyleName};
for(; pFontFace; pFontFace = pFontFace->GetNextFace() )
if( pFontFace->IsBetterMatch( rFSD, aFontMatchStatus ) )
pBestFontFace = pFontFace;
for( std::vector< PhysicalFontFace* >::const_iterator it=maFontFaces.begin(); it != maFontFaces.end(); ++it )
{
PhysicalFontFace* pFoundFontFace = *it;
if( pFoundFontFace->IsBetterMatch( rFSD, aFontMatchStatus ) )
pBestFontFace = pFoundFontFace;
}
return pBestFontFace;
}
@@ -250,19 +245,23 @@ PhysicalFontFace* PhysicalFontFamily::FindBestFontFace( const FontSelectPattern&
void PhysicalFontFamily::UpdateDevFontList( ImplDeviceFontList& rDevFontList ) const
{
PhysicalFontFace* pPrevFace = nullptr;
for( PhysicalFontFace* pFace = mpFirst; pFace; pFace = pFace->GetNextFace() )
for(std::vector< PhysicalFontFace* >::const_iterator it=maFontFaces.begin(); it != maFontFaces.end(); ++it )
{
if( !pPrevFace || pFace->CompareIgnoreSize( *pPrevFace ) )
rDevFontList.Add( pFace );
pPrevFace = pFace;
PhysicalFontFace* pFoundFontFace = *it;
if( !pPrevFace || pFoundFontFace->CompareIgnoreSize( *pPrevFace ) )
rDevFontList.Add( pFoundFontFace );
pPrevFace = pFoundFontFace;
}
}
void PhysicalFontFamily::GetFontHeights( std::set<int>& rHeights ) const
{
// add all available font heights
for( const PhysicalFontFace* pFace = mpFirst; pFace; pFace = pFace->GetNextFace() )
rHeights.insert( pFace->GetHeight() );
for( std::vector< PhysicalFontFace* >::const_iterator it=maFontFaces.begin(); it != maFontFaces.end(); ++it )
{
PhysicalFontFace *pFoundFontFace = *it;
rHeights.insert( pFoundFontFace->GetHeight() );
}
}
void PhysicalFontFamily::UpdateCloneFontList( PhysicalFontCollection& rFontCollection,
@@ -272,14 +271,16 @@ void PhysicalFontFamily::UpdateCloneFontList( PhysicalFontCollection& rFontColle
OUString aFamilyName = GetEnglishSearchFontName( GetFamilyName() );
PhysicalFontFamily* pFamily = rFontCollection.FindOrCreateFontFamily( aFamilyName );
for( PhysicalFontFace* pFace = mpFirst; pFace; pFace = pFace->GetNextFace() )
for( std::vector< PhysicalFontFace* >::const_iterator it=maFontFaces.begin(); it != maFontFaces.end(); ++it )
{
if( bScalable && !pFace->IsScalable() )
PhysicalFontFace *pFoundFontFace = *it;
if( bScalable && !pFoundFontFace->IsScalable() )
continue;
if( bEmbeddable && !pFace->IsEmbeddable() && !pFace->IsSubsettable() )
if( bEmbeddable && !pFoundFontFace->IsEmbeddable() && !pFoundFontFace->IsSubsettable() )
continue;
PhysicalFontFace* pClonedFace = pFace->Clone();
PhysicalFontFace* pClonedFace = pFoundFontFace->Clone();
assert( pClonedFace->GetFamilyName().replaceAll("-", "").trim() == GetFamilyName().replaceAll("-", "").trim() );
assert( rFontCollection.FindOrCreateFontFamily( GetEnglishSearchFontName( pClonedFace->GetFamilyName() ) ) == pFamily );