|
|
|
@@ -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 );
|
|
|
|
|