[Libreoffice-commits] core.git: 2 commits - vcl/inc vcl/Library_vcl.mk vcl/source

Chris Sherlock chris.sherlock79 at gmail.com
Thu Jan 7 03:24:04 PST 2016


 vcl/Library_vcl.mk                 |    3 
 vcl/inc/fontentry.hxx              |    4 
 vcl/source/font/fontattributes.cxx |  348 ++++++++++++++++++++
 vcl/source/font/fontcache.cxx      |  366 +++++++++++++++++++++
 vcl/source/font/fontentry.cxx      |  134 +++++++
 vcl/source/outdev/font.cxx         |  641 -------------------------------------
 6 files changed, 852 insertions(+), 644 deletions(-)

New commits:
commit f952a9f7139b079deb0aa8a31d1d5e2437846216
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date:   Thu Jan 7 22:09:33 2016 +1100

    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

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 89132a5..6f24942 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -393,8 +393,10 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/font/PhysicalFontCollection \
     vcl/source/font/PhysicalFontFace \
     vcl/source/font/PhysicalFontFamily \
+    vcl/source/font/fontattributes \
     vcl/source/font/fontselect \
     vcl/source/font/fontentry \
+    vcl/source/font/fontcache \
     vcl/source/fontsubset/cff \
     vcl/source/fontsubset/fontsubset \
     vcl/source/fontsubset/gsub \
diff --git a/vcl/source/font/fontattributes.cxx b/vcl/source/font/fontattributes.cxx
new file mode 100644
index 0000000..c27be5b
--- /dev/null
+++ b/vcl/source/font/fontattributes.cxx
@@ -0,0 +1,348 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "i18nlangtag/mslangid.hxx"
+
+#include <unotools/configmgr.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/print.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/edit.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/sysdata.hxx>
+#include <vcl/fontcharmap.hxx>
+
+#include "sallayout.hxx"
+#include "svdata.hxx"
+
+#include "impfont.hxx"
+#include "outdata.hxx"
+#include "fontentry.hxx"
+#include "fontattributes.hxx"
+
+#include "outdev.h"
+#include "window.h"
+
+#include "PhysicalFontCollection.hxx"
+#include "PhysicalFontFace.hxx"
+#include "PhysicalFontFamily.hxx"
+
+#include "svids.hrc"
+
+#include <config_graphite.h>
+#if ENABLE_GRAPHITE
+#include "graphite_features.hxx"
+#endif
+
+#include "../gdi/pdfwriter_impl.hxx"
+
+#include <boost/functional/hash.hpp>
+#include <cmath>
+#include <cstring>
+#include <memory>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::rtl;
+using namespace ::utl;
+
+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;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/font/fontcache.cxx b/vcl/source/font/fontcache.cxx
new file mode 100644
index 0000000..1b4b110
--- /dev/null
+++ b/vcl/source/font/fontcache.cxx
@@ -0,0 +1,366 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "i18nlangtag/mslangid.hxx"
+
+#include <unotools/configmgr.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/print.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/edit.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/sysdata.hxx>
+#include <vcl/fontcharmap.hxx>
+
+#include "sallayout.hxx"
+#include "svdata.hxx"
+
+#include "impfont.hxx"
+#include "outdata.hxx"
+#include "fontentry.hxx"
+#include "fontattributes.hxx"
+
+#include "outdev.h"
+#include "window.h"
+
+#include "PhysicalFontCollection.hxx"
+#include "PhysicalFontFace.hxx"
+#include "PhysicalFontFamily.hxx"
+
+#include "svids.hrc"
+
+#include <config_graphite.h>
+#if ENABLE_GRAPHITE
+#include "graphite_features.hxx"
+#endif
+
+#include "../gdi/pdfwriter_impl.hxx"
+
+#include <boost/functional/hash.hpp>
+#include <cmath>
+#include <cstring>
+#include <memory>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::rtl;
+using namespace ::utl;
+
+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");
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
index 4593900..6a0faa9 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 )
commit 50261ea4b7242e365717c77a9370afd1044a97e3
Author: Chris Sherlock <chris.sherlock79 at gmail.com>
Date:   Thu Jan 7 21:51:12 2016 +1100

    vcl: reorganize ImplFontEntry functions
    
    I have moved all ImplFontEntry functions into vcl/source/font/fontentry.cxx
    and also created a new hash function that hashes std::pair<sal_UCS4,FontWeight>
    types by specializing std::hash.
    
    Change-Id: Ibbe07c38b98e3c976836a895dbfdcaecd5daff8d

diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 27142a0..89132a5 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -394,6 +394,7 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
     vcl/source/font/PhysicalFontFace \
     vcl/source/font/PhysicalFontFamily \
     vcl/source/font/fontselect \
+    vcl/source/font/fontentry \
     vcl/source/fontsubset/cff \
     vcl/source/fontsubset/fontsubset \
     vcl/source/fontsubset/gsub \
diff --git a/vcl/inc/fontentry.hxx b/vcl/inc/fontentry.hxx
index 2768423..d654788 100644
--- a/vcl/inc/fontentry.hxx
+++ b/vcl/inc/fontentry.hxx
@@ -61,9 +61,7 @@ private:
     // cache of Unicode characters and replacement font names
     // TODO: a fallback map can be shared with many other ImplFontEntries
     // TODO: at least the ones which just differ in orientation, stretching or height
-    typedef ::std::pair<sal_UCS4,FontWeight> GFBCacheKey;
-    struct GFBCacheKey_Hash{ size_t operator()( const GFBCacheKey& ) const; };
-    typedef ::std::unordered_map<GFBCacheKey,OUString,GFBCacheKey_Hash> UnicodeFallbackList;
+    typedef ::std::unordered_map< ::std::pair<sal_UCS4,FontWeight>, OUString > UnicodeFallbackList;
     UnicodeFallbackList* mpUnicodeFallbackList;
 };
 
diff --git a/vcl/source/font/fontentry.cxx b/vcl/source/font/fontentry.cxx
new file mode 100644
index 0000000..ebcf556
--- /dev/null
+++ b/vcl/source/font/fontentry.cxx
@@ -0,0 +1,134 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ *   Licensed to the Apache Software Foundation (ASF) under one or more
+ *   contributor license agreements. See the NOTICE file distributed
+ *   with this work for additional information regarding copyright
+ *   ownership. The ASF licenses this file to you under the Apache
+ *   License, Version 2.0 (the "License"); you may not use this file
+ *   except in compliance with the License. You may obtain a copy of
+ *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "i18nlangtag/mslangid.hxx"
+
+#include <unotools/configmgr.hxx>
+#include <vcl/virdev.hxx>
+#include <vcl/print.hxx>
+#include <vcl/outdev.hxx>
+#include <vcl/edit.hxx>
+#include <vcl/settings.hxx>
+#include <vcl/sysdata.hxx>
+#include <vcl/fontcharmap.hxx>
+
+#include "sallayout.hxx"
+#include "svdata.hxx"
+
+#include "impfont.hxx"
+#include "outdata.hxx"
+#include "fontentry.hxx"
+#include "fontattributes.hxx"
+
+#include "outdev.h"
+#include "window.h"
+
+#include "PhysicalFontCollection.hxx"
+#include "PhysicalFontFace.hxx"
+#include "PhysicalFontFamily.hxx"
+
+#include "svids.hrc"
+
+#include <config_graphite.h>
+#if ENABLE_GRAPHITE
+#include "graphite_features.hxx"
+#endif
+
+#include "../gdi/pdfwriter_impl.hxx"
+
+#include <boost/functional/hash.hpp>
+#include <cmath>
+#include <cstring>
+#include <memory>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::rtl;
+using namespace ::utl;
+
+// extend std namespace to add custom hash needed for ImplFontEntry
+
+namespace std
+{
+    template <> struct hash< pair< sal_UCS4, FontWeight > >
+    {
+        size_t operator()(const pair< sal_UCS4, FontWeight >& rData) const
+        {
+            size_t h1 = hash<sal_UCS4>()(rData.first);
+            size_t h2 = hash<int>()(rData.second);
+            return h1 ^ h2;
+        }
+    };
+}
+
+
+ImplFontEntry::ImplFontEntry( const FontSelectPattern& rFontSelData )
+    : m_pFontCache(nullptr)
+    , maFontSelData( rFontSelData )
+    , maFontAttributes( rFontSelData )
+    , mpConversion( nullptr )
+    , mnLineHeight( 0 )
+    , mnRefCount( 1 )
+    , mnSetFontFlags( 0 )
+    , mnOwnOrientation( 0 )
+    , mnOrientation( 0 )
+    , mbInit( false )
+    , mpUnicodeFallbackList( nullptr )
+{
+    maFontSelData.mpFontEntry = this;
+}
+
+ImplFontEntry::~ImplFontEntry()
+{
+    delete mpUnicodeFallbackList;
+    m_pFontCache = nullptr;
+}
+
+void ImplFontEntry::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
+{
+    if( !mpUnicodeFallbackList )
+        mpUnicodeFallbackList = new UnicodeFallbackList;
+    (*mpUnicodeFallbackList)[ std::pair< sal_UCS4, FontWeight >(cChar,eWeight) ] = rFontName;
+}
+
+bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, OUString* pFontName ) const
+{
+    if( !mpUnicodeFallbackList )
+        return false;
+
+    UnicodeFallbackList::const_iterator it = mpUnicodeFallbackList->find( std::pair< sal_UCS4, FontWeight >(cChar,eWeight) );
+    if( it == mpUnicodeFallbackList->end() )
+        return false;
+
+    *pFontName = (*it).second;
+    return true;
+}
+
+void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
+{
+    UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( std::pair< sal_UCS4,FontWeight >(cChar,eWeight) );
+    if( it == mpUnicodeFallbackList->end() )
+        return;
+    if( (*it).second == rFontName )
+        mpUnicodeFallbackList->erase( it );
+}
+
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
index 915cc89..4593900 100644
--- a/vcl/source/outdev/font.cxx
+++ b/vcl/source/outdev/font.cxx
@@ -979,66 +979,6 @@ vcl::Font OutputDevice::GetDefaultFont( DefaultFontType nType, LanguageType eLan
     return aFont;
 }
 
-ImplFontEntry::ImplFontEntry( const FontSelectPattern& rFontSelData )
-    : m_pFontCache(nullptr)
-    , maFontSelData( rFontSelData )
-    , maFontAttributes( rFontSelData )
-    , mpConversion( nullptr )
-    , mnLineHeight( 0 )
-    , mnRefCount( 1 )
-    , mnSetFontFlags( 0 )
-    , mnOwnOrientation( 0 )
-    , mnOrientation( 0 )
-    , mbInit( false )
-    , mpUnicodeFallbackList( nullptr )
-{
-    maFontSelData.mpFontEntry = this;
-}
-
-ImplFontEntry::~ImplFontEntry()
-{
-    delete mpUnicodeFallbackList;
-    m_pFontCache = nullptr;
-}
-
-size_t ImplFontEntry::GFBCacheKey_Hash::operator()( const GFBCacheKey& rData ) const
-{
-    boost::hash<sal_UCS4> a;
-    boost::hash<int > b;
-    return a(rData.first) ^ b(rData.second);
-}
-
-void ImplFontEntry::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
-{
-    if( !mpUnicodeFallbackList )
-        mpUnicodeFallbackList = new UnicodeFallbackList;
-    (*mpUnicodeFallbackList)[ GFBCacheKey(cChar,eWeight) ] = rFontName;
-}
-
-bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, OUString* pFontName ) const
-{
-    if( !mpUnicodeFallbackList )
-        return false;
-
-    UnicodeFallbackList::const_iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) );
-    if( it == mpUnicodeFallbackList->end() )
-        return false;
-
-    *pFontName = (*it).second;
-    return true;
-}
-
-void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
-{
-//  DBG_ASSERT( mpUnicodeFallbackList, "ImplFontEntry::IgnoreFallbackForUnicode no list" );
-    UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) );
-//  DBG_ASSERT( it != mpUnicodeFallbackList->end(), "ImplFontEntry::IgnoreFallbackForUnicode no match" );
-    if( it == mpUnicodeFallbackList->end() )
-        return;
-    if( (*it).second == rFontName )
-        mpUnicodeFallbackList->erase( it );
-}
-
 FontSelectPatternAttributes::FontSelectPatternAttributes( const vcl::Font& rFont,
     const OUString& rSearchName, const Size& rSize, float fExactHeight )
     : maSearchName( rSearchName )


More information about the Libreoffice-commits mailing list