diff options
author | Chris Sherlock <chris.sherlock79@gmail.com> | 2016-01-07 22:09:33 +1100 |
---|---|---|
committer | Chris Sherlock <chris.sherlock79@gmail.com> | 2016-01-07 22:23:08 +1100 |
commit | f952a9f7139b079deb0aa8a31d1d5e2437846216 (patch) | |
tree | dbc2306e584d16d5d8c88bac6730be3a7cd0f073 /vcl/source/outdev | |
parent | 50261ea4b7242e365717c77a9370afd1044a97e3 (diff) |
vcl: migrate font functions from outdev/font.cxx to own files
I have moved all ImplFontAttributes and ImplFontCache functions from
vcl/source/outdev/font.cxx to vcl/source/font/fontattributes.cxx and
vcl/source/font/fontcache.cxx accordingly.
Change-Id: I12ca80799828a772482424da171cc76bffaac43d
Diffstat (limited to 'vcl/source/outdev')
-rw-r--r-- | vcl/source/outdev/font.cxx | 581 |
1 files changed, 0 insertions, 581 deletions
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx index 4593900da3cf..6a0faa965dad 100644 --- a/vcl/source/outdev/font.cxx +++ b/vcl/source/outdev/font.cxx @@ -1011,305 +1011,6 @@ FontSelectPatternAttributes::FontSelectPatternAttributes( const vcl::Font& rFont mnWidth = -mnWidth; } -size_t ImplFontCache::IFSD_Hash::operator()( const FontSelectPattern& rFSD ) const -{ - return rFSD.hashCode(); -} - -bool ImplFontCache::IFSD_Equal::operator()(const FontSelectPattern& rA, const FontSelectPattern& rB) const -{ - // check normalized font family name - if( rA.maSearchName != rB.maSearchName ) - return false; - - // check font transformation - if( (rA.mnHeight != rB.mnHeight) - || (rA.mnWidth != rB.mnWidth) - || (rA.mnOrientation != rB.mnOrientation) ) - return false; - - // check mapping relevant attributes - if( (rA.mbVertical != rB.mbVertical) - || (rA.meLanguage != rB.meLanguage) ) - return false; - - // check font face attributes - if( (rA.GetWeight() != rB.GetWeight()) - || (rA.GetSlantType() != rB.GetSlantType()) -// || (rA.meFamily != rB.meFamily) // TODO: remove this mostly obsolete member - || (rA.GetPitch() != rB.GetPitch()) ) - return false; - - // check style name - if( rA.GetStyleName() != rB.GetStyleName() ) - return false; - - // Symbol fonts may recode from one type to another So they are only - // safely equivalent for equal targets - if ( - (rA.mpFontData && rA.mpFontData->IsSymbolFont()) || - (rB.mpFontData && rB.mpFontData->IsSymbolFont()) - ) - { - if (rA.maTargetName != rB.maTargetName) - return false; - } - -#if ENABLE_GRAPHITE - // check for features - if ((rA.maTargetName.indexOf(grutils::GrFeatureParser::FEAT_PREFIX) - != -1 || - rB.maTargetName.indexOf(grutils::GrFeatureParser::FEAT_PREFIX) - != -1) && rA.maTargetName != rB.maTargetName) - return false; -#endif - - if (rA.mbEmbolden != rB.mbEmbolden) - return false; - - if (rA.maItalicMatrix != rB.maItalicMatrix) - return false; - - return true; -} - -ImplFontCache::ImplFontCache() -: mpFirstEntry( nullptr ), - mnRef0Count( 0 ) -{} - -ImplFontCache::~ImplFontCache() -{ - FontInstanceList::iterator it = maFontInstanceList.begin(); - for(; it != maFontInstanceList.end(); ++it ) - { - ImplFontEntry* pEntry = (*it).second; - delete pEntry; - } -} - -ImplFontEntry* ImplFontCache::GetFontEntry( PhysicalFontCollection* pFontList, - const vcl::Font& rFont, const Size& rSize, float fExactHeight ) -{ - OUString aSearchName = rFont.GetName(); - - // initialize internal font request object - FontSelectPattern aFontSelData( rFont, aSearchName, rSize, fExactHeight ); - return GetFontEntry( pFontList, aFontSelData ); -} - -ImplFontEntry* ImplFontCache::GetFontEntry( PhysicalFontCollection* pFontList, - FontSelectPattern& aFontSelData ) -{ - // check if a directly matching logical font instance is already cached, - // the most recently used font usually has a hit rate of >50% - ImplFontEntry *pEntry = nullptr; - PhysicalFontFamily* pFontFamily = nullptr; - IFSD_Equal aIFSD_Equal; - if( mpFirstEntry && aIFSD_Equal( aFontSelData, mpFirstEntry->maFontSelData ) ) - pEntry = mpFirstEntry; - else - { - FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData ); - if( it != maFontInstanceList.end() ) - pEntry = (*it).second; - } - - if( !pEntry ) // no direct cache hit - { - // find the best matching logical font family and update font selector accordingly - pFontFamily = pFontList->FindFontFamilyByFont( aFontSelData ); - DBG_ASSERT( (pFontFamily != nullptr), "ImplFontCache::Get() No logical font found!" ); - if( pFontFamily ) - aFontSelData.maSearchName = pFontFamily->GetSearchName(); - - // check if an indirectly matching logical font instance is already cached - FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData ); - if( it != maFontInstanceList.end() ) - { - // we have an indirect cache hit - pEntry = (*it).second; - } - } - - PhysicalFontFace* pFontData = nullptr; - - if (!pEntry && pFontFamily)// no cache hit => find the best matching physical font face - { - bool bOrigWasSymbol = aFontSelData.mpFontData && aFontSelData.mpFontData->IsSymbolFont(); - pFontData = pFontFamily->FindBestFontFace( aFontSelData ); - aFontSelData.mpFontData = pFontData; - bool bNewIsSymbol = aFontSelData.mpFontData && aFontSelData.mpFontData->IsSymbolFont(); - - if (bNewIsSymbol != bOrigWasSymbol) - { - // it is possible, though generally unlikely, that at this point we - // will attempt to use a symbol font as a last-ditch fallback for a - // non-symbol font request or vice versa, and by changing - // aFontSelData.mpFontData to/from a symbol font we may now find - // something in the cache that can be reused which previously - // wasn't a candidate - FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData ); - if( it != maFontInstanceList.end() ) - pEntry = (*it).second; - } - } - - if( pEntry ) // cache hit => use existing font instance - { - // increase the font instance's reference count - Acquire(pEntry); - } - - if (!pEntry && pFontData)// still no cache hit => create a new font instance - { - // create a new logical font instance from this physical font face - pEntry = pFontData->CreateFontInstance( aFontSelData ); - pEntry->m_pFontCache = this; - - // if we're subtituting from or to a symbol font we may need a symbol - // conversion table - if( pFontData->IsSymbolFont() || aFontSelData.IsSymbolFont() ) - { - if( aFontSelData.maTargetName != aFontSelData.maSearchName ) - pEntry->mpConversion = ConvertChar::GetRecodeData( aFontSelData.maTargetName, aFontSelData.maSearchName ); - } - -#ifdef MACOSX - //It might be better to dig out the font version of the target font - //to see if it's a modern re-coded apple symbol font in case that - //font shows up on a different platform - if (!pEntry->mpConversion && - aFontSelData.maTargetName.equalsIgnoreAsciiCase("symbol") && - aFontSelData.maSearchName.equalsIgnoreAsciiCase("symbol")) - { - pEntry->mpConversion = ConvertChar::GetRecodeData( "Symbol", "AppleSymbol" ); - } -#endif - - // add the new entry to the cache - maFontInstanceList[ aFontSelData ] = pEntry; - } - - mpFirstEntry = pEntry; - return pEntry; -} - -ImplFontEntry* ImplFontCache::GetGlyphFallbackFont( PhysicalFontCollection* pFontCollection, - FontSelectPattern& rFontSelData, int nFallbackLevel, OUString& rMissingCodes ) -{ - // get a candidate font for glyph fallback - // unless the previously selected font got a device specific substitution - // e.g. PsPrint Arial->Helvetica for udiaeresis when Helvetica doesn't support it - if( nFallbackLevel >= 1) - { - PhysicalFontFamily* pFallbackData = nullptr; - - //fdo#33898 If someone has EUDC installed then they really want that to - //be used as the first-choice glyph fallback seeing as it's filled with - //private area codes with don't make any sense in any other font so - //prioritise it here if it's available. Ideally we would remove from - //rMissingCodes all the glyphs which it is able to resolve as an - //optimization, but that's tricky to achieve cross-platform without - //sufficient heavy-weight code that's likely to undo the value of the - //optimization - if (nFallbackLevel == 1) - pFallbackData = pFontCollection->FindFontFamily("EUDC"); - if (!pFallbackData) - pFallbackData = pFontCollection->GetGlyphFallbackFont(rFontSelData, rMissingCodes, nFallbackLevel-1); - // escape when there are no font candidates - if( !pFallbackData ) - return nullptr; - // override the font name - rFontSelData.SetFamilyName( pFallbackData->GetFamilyName() ); - // clear the cached normalized name - rFontSelData.maSearchName.clear(); - } - - ImplFontEntry* pFallbackFont = GetFontEntry( pFontCollection, rFontSelData ); - return pFallbackFont; -} - -void ImplFontCache::Acquire(ImplFontEntry* pEntry) -{ - assert(pEntry->m_pFontCache == this); - - if (0 == pEntry->mnRefCount++) - --mnRef0Count; -} - -void ImplFontCache::Release(ImplFontEntry* pEntry) -{ - static const int FONTCACHE_MAX = getenv("LO_TESTNAME") ? 1 : 50; - - assert(pEntry->mnRefCount > 0 && "ImplFontCache::Release() - font refcount underflow"); - if( --pEntry->mnRefCount > 0 ) - return; - - if (++mnRef0Count < FONTCACHE_MAX) - return; - - assert(CountUnreferencedEntries() == mnRef0Count); - - // remove unused entries from font instance cache - FontInstanceList::iterator it_next = maFontInstanceList.begin(); - while( it_next != maFontInstanceList.end() ) - { - FontInstanceList::iterator it = it_next++; - ImplFontEntry* pFontEntry = (*it).second; - if( pFontEntry->mnRefCount > 0 ) - continue; - - maFontInstanceList.erase( it ); - delete pFontEntry; - --mnRef0Count; - assert(mnRef0Count>=0 && "ImplFontCache::Release() - refcount0 underflow"); - - if( mpFirstEntry == pFontEntry ) - mpFirstEntry = nullptr; - } - - assert(mnRef0Count==0 && "ImplFontCache::Release() - refcount0 mismatch"); -} - -int ImplFontCache::CountUnreferencedEntries() const -{ - size_t nCount = 0; - // count unreferenced entries - for (FontInstanceList::const_iterator it = maFontInstanceList.begin(); - it != maFontInstanceList.end(); ++it) - { - const ImplFontEntry* pFontEntry = it->second; - if (pFontEntry->mnRefCount > 0) - continue; - ++nCount; - } - return nCount; -} - -void ImplFontCache::Invalidate() -{ - assert(CountUnreferencedEntries() == mnRef0Count); - - // delete unreferenced entries - FontInstanceList::iterator it = maFontInstanceList.begin(); - for(; it != maFontInstanceList.end(); ++it ) - { - ImplFontEntry* pFontEntry = (*it).second; - if( pFontEntry->mnRefCount > 0 ) - continue; - - delete pFontEntry; - --mnRef0Count; - } - - // #112304# make sure the font cache is really clean - mpFirstEntry = nullptr; - maFontInstanceList.clear(); - - assert(mnRef0Count==0 && "ImplFontCache::Invalidate() - mnRef0Count non-zero"); -} - void OutputDevice::ImplInitFontList() const { if( !mpFontCollection->Count() ) @@ -1545,288 +1246,6 @@ void OutputDevice::SetFontOrientation( ImplFontEntry* const pFontEntry ) const } } -bool ImplFontAttributes::CompareDeviceIndependentFontAttributes(const ImplFontAttributes& rOther) const -{ - if (maFamilyName != rOther.maFamilyName) - return false; - - if (maStyleName != rOther.maStyleName) - return false; - - if (meWeight != rOther.meWeight) - return false; - - if (meItalic != rOther.meItalic) - return false; - - if (meFamily != rOther.meFamily) - return false; - - if (mePitch != rOther.mePitch) - return false; - - if (meWidthType != rOther.meWidthType) - return false; - - if (mbSymbolFlag != rOther.mbSymbolFlag) - return false; - - return true; -} - -ImplFontAttributes::ImplFontAttributes() - : mnWidth ( 0 ) - , mnOrientation( 0 ) - , mnAscent( 0 ) - , mnDescent( 0 ) - , mnIntLeading( 0 ) - , mnExtLeading( 0 ) - , mnSlant( 0 ) - , mnMinKashida( 0 ) - , mbScalableFont( false ) - , mbTrueTypeFont( false ) - , mbKernableFont( false ) - , mbFullstopCentered( false ) - , mnBulletOffset( 0 ) - , mnUnderlineSize( 0 ) - , mnUnderlineOffset( 0 ) - , mnBUnderlineSize( 0 ) - , mnBUnderlineOffset( 0 ) - , mnDUnderlineSize( 0 ) - , mnDUnderlineOffset1( 0 ) - , mnDUnderlineOffset2( 0 ) - , mnWUnderlineSize( 0 ) - , mnWUnderlineOffset( 0 ) - , mnAboveUnderlineSize( 0 ) - , mnAboveUnderlineOffset( 0 ) - , mnAboveBUnderlineSize( 0 ) - , mnAboveBUnderlineOffset( 0 ) - , mnAboveDUnderlineSize( 0 ) - , mnAboveDUnderlineOffset1( 0 ) - , mnAboveDUnderlineOffset2( 0 ) - , mnAboveWUnderlineSize( 0 ) - , mnAboveWUnderlineOffset( 0 ) - , mnStrikeoutSize( 0 ) - , mnStrikeoutOffset( 0 ) - , mnBStrikeoutSize( 0 ) - , mnBStrikeoutOffset( 0 ) - , mnDStrikeoutSize( 0 ) - , mnDStrikeoutOffset1( 0 ) - , mnDStrikeoutOffset2( 0 ) -{ - // empty -} - -ImplFontAttributes::ImplFontAttributes( const FontSelectPattern& rFontSelData ) - : mnWidth ( rFontSelData.mnWidth ) - , mnOrientation( (short)(rFontSelData.mnOrientation) ) - , mnAscent( 0 ) - , mnDescent( 0 ) - , mnIntLeading( 0 ) - , mnExtLeading( 0 ) - , mnSlant( 0 ) - , mnMinKashida( 0 ) - , mbScalableFont( false ) - , mbTrueTypeFont( false ) - , mbKernableFont( false ) - , mbFullstopCentered( false ) - , mnBulletOffset( 0 ) - , mnUnderlineSize( 0 ) - , mnUnderlineOffset( 0 ) - , mnBUnderlineSize( 0 ) - , mnBUnderlineOffset( 0 ) - , mnDUnderlineSize( 0 ) - , mnDUnderlineOffset1( 0 ) - , mnDUnderlineOffset2( 0 ) - , mnWUnderlineSize( 0 ) - , mnWUnderlineOffset( 0 ) - , mnAboveUnderlineSize( 0 ) - , mnAboveUnderlineOffset( 0 ) - , mnAboveBUnderlineSize( 0 ) - , mnAboveBUnderlineOffset( 0 ) - , mnAboveDUnderlineSize( 0 ) - , mnAboveDUnderlineOffset1( 0 ) - , mnAboveDUnderlineOffset2( 0 ) - , mnAboveWUnderlineSize( 0 ) - , mnAboveWUnderlineOffset( 0 ) - , mnStrikeoutSize( 0 ) - , mnStrikeoutOffset( 0 ) - , mnBStrikeoutSize( 0 ) - , mnBStrikeoutOffset( 0 ) - , mnDStrikeoutSize( 0 ) - , mnDStrikeoutOffset1( 0 ) - , mnDStrikeoutOffset2( 0 ) -{ - // intialize the used font name - if( rFontSelData.mpFontData ) - { - SetFamilyName( rFontSelData.mpFontData->GetFamilyName() ); - SetStyleName( rFontSelData.mpFontData->GetStyleName() ); - SetBuiltInFontFlag( rFontSelData.mpFontData->IsBuiltInFont() ); - SetKernableFlag( true ); - } - else - { - sal_Int32 nTokenPos = 0; - SetFamilyName( GetNextFontToken( rFontSelData.GetFamilyName(), nTokenPos ) ); - SetStyleName( rFontSelData.GetStyleName() ); - SetBuiltInFontFlag( false ); - SetKernableFlag( false ); - } -} - - -void ImplFontAttributes::ImplInitTextLineSize( const OutputDevice* pDev ) -{ - long nDescent = mnDescent; - if ( nDescent <= 0 ) - { - nDescent = mnAscent / 10; - if ( !nDescent ) - nDescent = 1; - } - - // #i55341# for some fonts it is not a good idea to calculate - // their text line metrics from the real font descent - // => work around this problem just for these fonts - if( 3*nDescent > mnAscent ) - nDescent = mnAscent / 3; - - long nLineHeight = ((nDescent*25)+50) / 100; - if ( !nLineHeight ) - nLineHeight = 1; - long nLineHeight2 = nLineHeight / 2; - if ( !nLineHeight2 ) - nLineHeight2 = 1; - - long nBLineHeight = ((nDescent*50)+50) / 100; - if ( nBLineHeight == nLineHeight ) - nBLineHeight++; - long nBLineHeight2 = nBLineHeight/2; - if ( !nBLineHeight2 ) - nBLineHeight2 = 1; - - long n2LineHeight = ((nDescent*16)+50) / 100; - if ( !n2LineHeight ) - n2LineHeight = 1; - long n2LineDY = n2LineHeight; - /* #117909# - * add some pixels to minimum double line distance on higher resolution devices - */ - long nMin2LineDY = 1 + pDev->GetDPIY()/150; - if ( n2LineDY < nMin2LineDY ) - n2LineDY = nMin2LineDY; - long n2LineDY2 = n2LineDY/2; - if ( !n2LineDY2 ) - n2LineDY2 = 1; - - long nUnderlineOffset = mnDescent/2 + 1; - long nStrikeoutOffset = -((mnAscent - mnIntLeading) / 3); - - mnUnderlineSize = nLineHeight; - mnUnderlineOffset = nUnderlineOffset - nLineHeight2; - - mnBUnderlineSize = nBLineHeight; - mnBUnderlineOffset = nUnderlineOffset - nBLineHeight2; - - mnDUnderlineSize = n2LineHeight; - mnDUnderlineOffset1 = nUnderlineOffset - n2LineDY2 - n2LineHeight; - mnDUnderlineOffset2 = mnDUnderlineOffset1 + n2LineDY + n2LineHeight; - - long nWCalcSize = mnDescent; - if ( nWCalcSize < 6 ) - { - if ( (nWCalcSize == 1) || (nWCalcSize == 2) ) - mnWUnderlineSize = nWCalcSize; - else - mnWUnderlineSize = 3; - } - else - mnWUnderlineSize = ((nWCalcSize*50)+50) / 100; - - // Don't assume that wavelines are never placed below the descent, because for most fonts the waveline - // is drawn into the text - mnWUnderlineOffset = nUnderlineOffset; - - mnStrikeoutSize = nLineHeight; - mnStrikeoutOffset = nStrikeoutOffset - nLineHeight2; - - mnBStrikeoutSize = nBLineHeight; - mnBStrikeoutOffset = nStrikeoutOffset - nBLineHeight2; - - mnDStrikeoutSize = n2LineHeight; - mnDStrikeoutOffset1 = nStrikeoutOffset - n2LineDY2 - n2LineHeight; - mnDStrikeoutOffset2 = mnDStrikeoutOffset1 + n2LineDY + n2LineHeight; - - const vcl::Font& rFont ( pDev->GetFont() ); - bool bCentered = true; - if (MsLangId::isCJK(rFont.GetLanguage())) - { - const OUString sFullstop( sal_Unicode( 0x3001 ) ); // Fullwidth fullstop - Rectangle aRect; - pDev->GetTextBoundRect( aRect, sFullstop ); - const sal_uInt16 nH = rFont.GetSize().Height(); - const sal_uInt16 nB = aRect.Left(); - // Use 18.75% as a threshold to define a centered fullwidth fullstop. - // In general, nB/nH < 5% for most Japanese fonts. - bCentered = nB > (((nH >> 1)+nH)>>3); - } - SetFullstopCenteredFlag( bCentered ); - - mnBulletOffset = ( pDev->GetTextWidth( OUString( sal_Unicode( 0x20 ) ) ) - pDev->GetTextWidth( OUString( sal_Unicode( 0xb7 ) ) ) ) >> 1 ; - -} - -void ImplFontAttributes::ImplInitAboveTextLineSize() -{ - long nIntLeading = mnIntLeading; - // TODO: assess usage of nLeading below (changed in extleading CWS) - // if no leading is available, we assume 15% of the ascent - if ( nIntLeading <= 0 ) - { - nIntLeading = mnAscent*15/100; - if ( !nIntLeading ) - nIntLeading = 1; - } - - long nLineHeight = ((nIntLeading*25)+50) / 100; - if ( !nLineHeight ) - nLineHeight = 1; - - long nBLineHeight = ((nIntLeading*50)+50) / 100; - if ( nBLineHeight == nLineHeight ) - nBLineHeight++; - - long n2LineHeight = ((nIntLeading*16)+50) / 100; - if ( !n2LineHeight ) - n2LineHeight = 1; - - long nCeiling = -mnAscent; - - mnAboveUnderlineSize = nLineHeight; - mnAboveUnderlineOffset = nCeiling + (nIntLeading - nLineHeight + 1) / 2; - - mnAboveBUnderlineSize = nBLineHeight; - mnAboveBUnderlineOffset = nCeiling + (nIntLeading - nBLineHeight + 1) / 2; - - mnAboveDUnderlineSize = n2LineHeight; - mnAboveDUnderlineOffset1 = nCeiling + (nIntLeading - 3*n2LineHeight + 1) / 2; - mnAboveDUnderlineOffset2 = nCeiling + (nIntLeading + n2LineHeight + 1) / 2; - - long nWCalcSize = nIntLeading; - if ( nWCalcSize < 6 ) - { - if ( (nWCalcSize == 1) || (nWCalcSize == 2) ) - mnAboveWUnderlineSize = nWCalcSize; - else - mnAboveWUnderlineSize = 3; - } - else - mnAboveWUnderlineSize = ((nWCalcSize*50)+50) / 100; - - mnAboveWUnderlineOffset = nCeiling + (nIntLeading + 1) / 2; -} - void OutputDevice::ImplDrawEmphasisMark( long nBaseX, long nX, long nY, const tools::PolyPolygon& rPolyPoly, bool bPolyLine, const Rectangle& rRect1, const Rectangle& rRect2 ) |