--- psprint/inc/psprint/fontmanager.hxx.old	2006-06-19 12:23:01.000000000 +0200
+++ psprint/inc/psprint/fontmanager.hxx	2007-03-27 14:04:09.195405211 +0200
@@ -49,6 +49,9 @@
 #ifndef _PSPRINT_HELPER_HXX_
 #include <psprint/helper.hxx>
 #endif
+#ifndef _STRING_HXX
+#include <tools/string.hxx>
+#endif
 
 #ifndef _COM_SUN_STAR_LANG_LOCALE_HPP_
 #include <com/sun/star/lang/Locale.hpp>
@@ -413,7 +416,10 @@
     std::hash_multimap< sal_Unicode, sal_uInt8 >	m_aUnicodeToAdobecode;
     std::hash_multimap< sal_uInt8, sal_Unicode >	m_aAdobecodeToUnicode;
 
+    std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash > m_aFontconfigNameToLocalized;
+
     mutable FontCache*							m_pFontCache;
+    bool m_bFontconfigSuccess;
         
     rtl::OString getAfmFile( PrintFont* pFont ) const;
     rtl::OString getFontFile( PrintFont* pFont ) const;
@@ -724,6 +730,11 @@
     false else
      */
     bool matchFont( FastPrintFontInfo& rInfo, const com::sun::star::lang::Locale& rLocale );
+
+    String Substitute(const std::vector<String> &rNames, std::vector<sal_Unicode> &rGlyphs, 
+        const ByteString &rLangAttrib, italic::type eItalic, weight::type eWeight, 
+        width::type eWidth, pitch::type ePitch) const;
+    bool hasFontconfig() const { return m_bFontconfigSuccess; }
 };
 
 } // namespace
--- psprint/source/fontmanager/fontcache.cxx.old	2007-03-27 14:01:23.372903816 +0200
+++ psprint/source/fontmanager/fontcache.cxx	2007-03-27 14:03:24.014723671 +0200
@@ -683,9 +683,9 @@
         FontDirMap::const_iterator entry = dir->second.m_aEntries.find( rFile );
         if( entry != dir->second.m_aEntries.end() )
         {
-            bSuccess = true;
             for( FontCacheEntry::const_iterator font = entry->second.m_aEntry.begin(); font != entry->second.m_aEntry.end(); ++font )
             {
+                bSuccess = true;
                 PrintFontManager::PrintFont* pFont = clonePrintFont( *font );
                 rNewFonts.push_back( pFont );
             }
--- psprint/source/fontmanager/fontconfig.cxx.old	2006-10-24 17:06:22.000000000 +0200
+++ psprint/source/fontmanager/fontconfig.cxx	2007-03-27 14:04:09.195405211 +0200
@@ -47,10 +47,12 @@
 typedef void FcObjectSet;
 typedef void FcPattern;
 typedef void FcFontSet;
+typedef void FcCharSet;
 typedef int FcResult;
 typedef int FcBool;
 typedef int FcMatchKind;
 typedef char FcChar8;
+typedef sal_Int32 FcChar32;
 #endif
 
 #include <cstdio>
@@ -74,6 +76,15 @@
 #ifndef _RTL_USTRBUF_HXX
 #include <rtl/ustrbuf.hxx>
 #endif
+#ifndef _OSL_PROCESS_H_
+#include <osl/process.h>
+#endif
+#ifndef _RTL_LOCALE_HXX_
+#include <rtl/locale.hxx>
+#endif
+#include <utility>
+#include <algorithm>
+
 
 using namespace psp;
 using namespace osl;
@@ -83,6 +94,7 @@
 {
     oslModule		m_pLib;
     FcConfig*		m_pDefConfig;
+    FcFontSet*      m_pOutlineSet;
 
 	FcBool          (*m_pFcInit)();
     FcConfig*		(*m_pFcConfigGetCurrent)();
@@ -91,18 +103,26 @@
     FcPattern*		(*m_pFcPatternCreate)();
     void			(*m_pFcPatternDestroy)(FcPattern*);
     FcFontSet*		(*m_pFcFontList)(FcConfig*,FcPattern*,FcObjectSet*);
+    FcFontSet*      (*m_pFcConfigGetFonts)(FcConfig*,FcSetName);
     FcFontSet*		(*m_pFcFontSetCreate)();
+    FcCharSet*                (*m_pFcCharSetCreate)();
+    FcBool                    (*m_pFcCharSetAddChar)(FcCharSet *, FcChar32);
+    FcBool          (*m_pFcCharSetHasChar)(FcCharSet *, FcChar32);
+    void            (*m_pFcCharSetDestroy)(FcCharSet*);
     void			(*m_pFcFontSetDestroy)(FcFontSet*);
     FcBool			(*m_pFcFontSetAdd)(FcFontSet*,FcPattern*);
+    void            (*m_pFcPatternReference)(FcPattern*);
+    FcResult        (*m_pFcPatternGetCharSet)(const FcPattern*,const char*,int,FcCharSet**);
     FcResult		(*m_pFcPatternGetString)(const FcPattern*,const char*,int,FcChar8**);
     FcResult		(*m_pFcPatternGetInteger)(const FcPattern*,const char*,int,int*);
     FcResult		(*m_pFcPatternGetDouble)(const FcPattern*,const char*,int,double*);
     FcResult		(*m_pFcPatternGetBool)(const FcPattern*,const char*,int,FcBool*);
     void			(*m_pFcDefaultSubstitute)(FcPattern *);
-    FcPattern*		(*m_pFcFontMatch)(FcConfig*,FcPattern*,FcResult*);    
     FcPattern*		(*m_pFcFontSetMatch)(FcConfig*,FcFontSet**, int, FcPattern*,FcResult*);    
     FcBool			(*m_pFcConfigSubstitute)(FcConfig*,FcPattern*,FcMatchKind);
     FcBool			(*m_pFcPatternAddInteger)(FcPattern*,const char*,int);
+    FcBool                    (*m_pFcPatternAddBool)(FcPattern*,const char*,FcBool);
+    FcBool                    (*m_pFcPatternAddCharSet)(FcPattern*,const char*,const FcCharSet*);
     FcBool			(*m_pFcPatternAddString)(FcPattern*,const char*,const FcChar8*);
 
     oslGenericFunction loadSymbol( const char* );
@@ -118,6 +138,7 @@
     { return m_pLib != NULL;}
 
     FcConfig* getDefConfig() { return m_pDefConfig; }
+    FcFontSet* getFontSet() { return m_pOutlineSet; }
 
     FcBool FcInit()
     { return m_pFcInit(); }
@@ -147,14 +168,37 @@
     
     FcFontSet* FcFontList( FcConfig* pConfig, FcPattern* pPattern, FcObjectSet* pSet )
     { return m_pFcFontList( pConfig, pPattern, pSet ); }
-    
+
+    FcFontSet* FcConfigGetFonts( FcConfig* pConfig, FcSetName eSet)
+    { return m_pFcConfigGetFonts( pConfig, eSet ); }
+
     FcFontSet* FcFontSetCreate()
     { return m_pFcFontSetCreate(); }
+
+    FcCharSet* FcCharSetCreate()
+    { return m_pFcCharSetCreate(); }
+
+    FcBool FcCharSetAddChar(FcCharSet *fcs, FcChar32 ucs4)
+    { return m_pFcCharSetAddChar(fcs, ucs4); }
+
+    FcBool FcCharSetHasChar(FcCharSet *fcs, FcChar32 ucs4)
+    { return m_pFcCharSetHasChar(fcs, ucs4); }
+
+    void FcCharSetDestroy( FcCharSet* pSet )
+    { m_pFcCharSetDestroy( pSet );}
+
     void FcFontSetDestroy( FcFontSet* pSet )
     { m_pFcFontSetDestroy( pSet );}
+
     FcBool FcFontSetAdd( FcFontSet* pSet, FcPattern* pPattern )
     { return m_pFcFontSetAdd( pSet, pPattern ); }
 
+    void FcPatternReference( FcPattern* pPattern )
+    { m_pFcPatternReference( pPattern ); }
+
+    FcResult FcPatternGetCharSet( const FcPattern* pPattern, const char* object, int n, FcCharSet** s )
+    { return m_pFcPatternGetCharSet( pPattern, object, n, s ); }
+
     FcResult FcPatternGetString( const FcPattern* pPattern, const char* object, int n, FcChar8** s )
     { return m_pFcPatternGetString( pPattern, object, n, s ); }
 
@@ -168,8 +212,6 @@
     { return m_pFcPatternGetBool( pPattern, object, n, s ); }
     void FcDefaultSubstitute( FcPattern* pPattern )
     { m_pFcDefaultSubstitute( pPattern ); }
-    FcPattern* FcFontMatch( FcConfig* pConfig, FcPattern* pPattern, FcResult* pResult )
-    { return m_pFcFontMatch( pConfig, pPattern, pResult ); }
     FcPattern* FcFontSetMatch( FcConfig* pConfig, FcFontSet **ppFontSet, int nset, FcPattern* pPattern, FcResult* pResult )
     { return m_pFcFontSetMatch ? m_pFcFontSetMatch( pConfig, ppFontSet, nset, pPattern, pResult ) : 0; }
     FcBool FcConfigSubstitute( FcConfig* pConfig, FcPattern* pPattern, FcMatchKind eKind )
@@ -178,6 +220,10 @@
     { return m_pFcPatternAddInteger( pPattern, pObject, nValue ); }
     FcBool FcPatternAddString( FcPattern* pPattern, const char* pObject, const FcChar8* pString )
     { return m_pFcPatternAddString( pPattern, pObject, pString ); }
+    FcBool FcPatternAddBool( FcPattern* pPattern, const char* pObject, bool nValue )
+    { return m_pFcPatternAddBool( pPattern, pObject, nValue ); }
+    FcBool FcPatternAddCharSet(FcPattern* pPattern,const char* pObject,const FcCharSet*pCharSet)
+    { return m_pFcPatternAddCharSet(pPattern,pObject,pCharSet); }
 };
 
 oslGenericFunction FontCfgWrapper::loadSymbol( const char* pSymbol )
@@ -192,7 +238,8 @@
 
 FontCfgWrapper::FontCfgWrapper()
         : m_pLib( NULL ),
-          m_pDefConfig( NULL )
+          m_pDefConfig( NULL ),
+          m_pOutlineSet( NULL )
 {
 #ifdef ENABLE_FONTCONFIG
     OUString aLib( RTL_CONSTASCII_USTRINGPARAM( "libfontconfig.so.1" ) );
@@ -226,12 +273,26 @@
         loadSymbol( "FcPatternDestroy" );
     m_pFcFontList = (FcFontSet*(*)(FcConfig*,FcPattern*,FcObjectSet*))
         loadSymbol( "FcFontList" );
+    m_pFcConfigGetFonts = (FcFontSet*(*)(FcConfig*,FcSetName))
+        loadSymbol( "FcConfigGetFonts" );
     m_pFcFontSetCreate = (FcFontSet*(*)())
         loadSymbol( "FcFontSetCreate" );
+    m_pFcCharSetCreate = (FcCharSet*(*)())
+        loadSymbol( "FcCharSetCreate" );
+    m_pFcCharSetAddChar = (FcBool(*)(FcCharSet*, FcChar32))
+        loadSymbol( "FcCharSetAddChar" );
+    m_pFcCharSetHasChar = (FcBool(*)(FcCharSet*, FcChar32))
+        loadSymbol( "FcCharSetHasChar" );
+    m_pFcCharSetDestroy = (void(*)(FcCharSet*))
+        loadSymbol( "FcCharSetDestroy" );
     m_pFcFontSetDestroy = (void(*)(FcFontSet*))
         loadSymbol( "FcFontSetDestroy" );
     m_pFcFontSetAdd = (FcBool(*)(FcFontSet*,FcPattern*))
         loadSymbol( "FcFontSetAdd" );
+    m_pFcPatternReference = (void(*)(FcPattern*))
+        loadSymbol( "FcPatternReference" );
+    m_pFcPatternGetCharSet = (FcResult(*)(const FcPattern*,const char*,int,FcCharSet**))
+        loadSymbol( "FcPatternGetCharSet" );
     m_pFcPatternGetString = (FcResult(*)(const FcPattern*,const char*,int,FcChar8**))
         loadSymbol( "FcPatternGetString" );
     m_pFcPatternGetInteger = (FcResult(*)(const FcPattern*,const char*,int,int*))
@@ -242,14 +303,16 @@
         loadSymbol( "FcPatternGetBool" );
     m_pFcDefaultSubstitute = (void(*)(FcPattern *))
         loadSymbol( "FcDefaultSubstitute" );
-    m_pFcFontMatch = (FcPattern*(*)(FcConfig*,FcPattern*,FcResult*))
-        loadSymbol( "FcFontMatch" );
     m_pFcFontSetMatch = (FcPattern*(*)(FcConfig*,FcFontSet**,int,FcPattern*,FcResult*))
         loadSymbol( "FcFontSetMatch" );
     m_pFcConfigSubstitute = (FcBool(*)(FcConfig*,FcPattern*,FcMatchKind))
         loadSymbol( "FcConfigSubstitute" );
     m_pFcPatternAddInteger = (FcBool(*)(FcPattern*,const char*,int))
         loadSymbol( "FcPatternAddInteger" );
+    m_pFcPatternAddBool = (FcBool(*)(FcPattern*,const char*,FcBool))
+        loadSymbol( "FcPatternAddBool" );
+    m_pFcPatternAddCharSet = (FcBool(*)(FcPattern*,const char*,const FcCharSet *))
+        loadSymbol( "FcPatternAddCharSet" );
     m_pFcPatternAddString = (FcBool(*)(FcPattern*,const char*,const FcChar8*))
         loadSymbol( "FcPatternAddString" );
 
@@ -261,17 +324,25 @@
             m_pFcPatternCreate				&&
             m_pFcPatternDestroy				&&
             m_pFcFontList					&&
+            m_pFcConfigGetFonts             &&
             m_pFcFontSetCreate				&&
+            m_pFcCharSetCreate				&&
+            m_pFcCharSetAddChar 			&&
+            m_pFcCharSetHasChar             &&
+            m_pFcCharSetDestroy             &&
             m_pFcFontSetDestroy				&&
             m_pFcFontSetAdd					&&
+            m_pFcPatternReference           &&
+			m_pFcPatternGetCharSet			&&
             m_pFcPatternGetString			&&
             m_pFcPatternGetInteger			&&
             m_pFcPatternGetDouble			&&
             m_pFcPatternGetBool				&&
             m_pFcDefaultSubstitute			&&
-            m_pFcFontMatch					&&
             m_pFcConfigSubstitute			&&
             m_pFcPatternAddInteger			&&
+            m_pFcPatternAddCharSet			&&
+            m_pFcPatternAddBool 			&&
             m_pFcPatternAddString
             ) )
     {
@@ -289,10 +360,35 @@
         osl_unloadModule( (oslModule)m_pLib );
         m_pLib = NULL;
     }
+
+    m_pOutlineSet = FcFontSetCreate();
+
+    /*
+      add only acceptable outlined fonts to our config, 
+      for future fontconfig use
+    */
+    FcFontSet *pOrig = FcConfigGetFonts(NULL, FcSetSystem);
+
+    if (!pOrig)
+        return;
+
+    for( int i = 0; i < pOrig->nfont; ++i )
+    {
+        FcBool outline = false;
+        FcPattern *pOutlinePattern = pOrig->fonts[i];
+        FcResult eOutRes = 
+			FcPatternGetBool( pOutlinePattern, FC_OUTLINE, 0, &outline );
+        if (eOutRes == FcResultMatch && !outline)
+            continue;
+        FcPatternReference(pOutlinePattern);
+        FcFontSetAdd(m_pOutlineSet, pOutlinePattern);
+    }
 }
 
 FontCfgWrapper::~FontCfgWrapper()
 {
+	if( m_pOutlineSet )
+		FcFontSetDestroy( m_pOutlineSet );
     if( m_pLib )
         osl_unloadModule( (oslModule)m_pLib );
 }
@@ -319,6 +415,94 @@
 #define FC_EMBEDDED_BITMAP "embeddedbitmap"
 #endif
 
+namespace
+{
+    typedef std::pair<FcChar8*, FcChar8*> lang_and_family;
+
+    class localizedsorter
+    {
+            rtl::OLocale maLoc;
+        public:
+            localizedsorter(rtl_Locale* pLoc) : maLoc(pLoc) {}
+            FcChar8* bestname(const std::vector<lang_and_family> &families);
+    };
+
+    FcChar8* localizedsorter::bestname(const std::vector<lang_and_family> &families)
+    {
+        FcChar8* candidate = families.begin()->second;
+        rtl::OString sLangMatch(rtl::OUStringToOString(maLoc.getLanguage().toAsciiLowerCase(), RTL_TEXTENCODING_UTF8));
+        rtl::OString sFullMatch = sLangMatch;
+        sFullMatch += OString('-');
+        sFullMatch += rtl::OUStringToOString(maLoc.getCountry().toAsciiLowerCase(), RTL_TEXTENCODING_UTF8);
+
+        std::vector<lang_and_family>::const_iterator aEnd = families.end();
+        bool alreadyclosematch = false;
+        for (std::vector<lang_and_family>::const_iterator aIter = families.begin(); aIter != aEnd; ++aIter)
+        {
+            const char *pLang = (const char*)aIter->first;
+            //perfect
+            if (strcmp(pLang, sFullMatch.getStr()) == 0)
+            {
+                candidate = aIter->second;
+                break;
+            }
+            else if ((strcmp(pLang, sLangMatch.getStr()) == 0) && (!alreadyclosematch))
+            {
+                candidate = aIter->second;
+                alreadyclosematch = true;
+            }
+        }
+
+        return candidate;
+    }
+
+
+    FcResult lcl_FamilyFromPattern(FontCfgWrapper& rWrapper, FcPattern* pPattern, FcChar8 **family, 
+        std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash > &aFontconfigNameToLocalized)
+    {
+	FcChar8 *origfamily;
+        FcResult eFamilyRes	= rWrapper.FcPatternGetString( pPattern, FC_FAMILY, 0, &origfamily );
+        *family = origfamily;
+
+        if( eFamilyRes == FcResultMatch)
+        {
+            FcChar8* familylang = NULL;
+            if (rWrapper.FcPatternGetString( pPattern, FC_FAMILYLANG, 0, &familylang ) == FcResultMatch)
+            {
+                std::vector< lang_and_family > lang_and_families;
+                lang_and_families.push_back(lang_and_family(familylang, *family));
+                int k = 1;
+                while (1)
+                {
+                    if (rWrapper.FcPatternGetString( pPattern, FC_FAMILYLANG, k, &familylang ) != FcResultMatch)
+                        break;
+                    if (rWrapper.FcPatternGetString( pPattern, FC_FAMILY, k, family ) != FcResultMatch)
+                        break;
+                    lang_and_families.push_back(lang_and_family(familylang, *family));
+                    ++k;
+                }
+
+                //possible to-do, sort by UILocale instead of process locale
+                rtl_Locale* pLoc;
+                osl_getProcessLocale(&pLoc);
+                localizedsorter aSorter(pLoc);
+                *family = aSorter.bestname(lang_and_families);
+
+		std::vector<lang_and_family>::const_iterator aEnd = lang_and_families.end();
+		for (std::vector<lang_and_family>::const_iterator aIter = lang_and_families.begin(); aIter != aEnd; ++aIter)
+		{
+		    const char *candidate = (const char*)(aIter->second);
+		    if (strcmp(candidate, (const char*)(*family)) != 0)
+		        aFontconfigNameToLocalized[OString(candidate)] = OString((const char*)(*family));
+		}
+            }
+        }
+
+        return eFamilyRes;
+    }
+}
+
+
 /*
  * PrintFontManager::initFontconfig
  */
@@ -331,20 +515,7 @@
     if( ! rWrapper.isValid() )
         return false;
 
-    FcConfig* pConfig = rWrapper.getDefConfig();
-    FcObjectSet* pOSet = rWrapper.FcObjectSetBuild( FC_FAMILY,
-                                                    FC_STYLE,
-                                                    FC_SLANT,
-                                                    FC_WEIGHT,
-                                                    FC_SPACING,
-                                                    FC_FILE,
-                                                    FC_OUTLINE,
-                                                    FC_INDEX,
-                                                    FC_EMBEDDED_BITMAP,
-                                                    FC_ANTIALIAS,
-                                                    (void *) NULL );
-    FcPattern* pPattern = rWrapper.FcPatternCreate();
-    FcFontSet* pFSet = rWrapper.FcFontList( pConfig, pPattern, pOSet );
+    FcFontSet* pFSet = rWrapper.getFontSet();
 
     if( pFSet )
     {
@@ -363,7 +534,7 @@
             FcBool outline = false, embitmap = true, antialias = true;
             
             FcResult eFileRes	      = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_FILE, 0, &file );
-            FcResult eFamilyRes	      = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_FAMILY, 0, &family );
+            FcResult eFamilyRes       = lcl_FamilyFromPattern(rWrapper, pFSet->fonts[i], &family, m_aFontconfigNameToLocalized );
             FcResult eStyleRes	      = rWrapper.FcPatternGetString( pFSet->fonts[i], FC_STYLE, 0, &style );
             FcResult eSlantRes	      = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_SLANT, 0, &slant );
             FcResult eWeightRes	      = rWrapper.FcPatternGetInteger( pFSet->fonts[i], FC_WEIGHT, 0, &weight );
@@ -389,6 +560,8 @@
                      );
 #endif
 
+            OSL_ASSERT(eOutRes != FcResultMatch || outline);
+
             // only outline fonts are usable to psprint anyway
             if( eOutRes == FcResultMatch && ! outline )
                 continue;
@@ -542,14 +715,6 @@
         }
     }
     
-    // cleanup
-    if( pPattern )
-        rWrapper.FcPatternDestroy( pPattern );
-    if( pFSet )
-        rWrapper.FcFontSetDestroy( pFSet );
-    if( pOSet )
-        rWrapper.FcObjectSetDestroy( pOSet );
-    
     // how does one get rid of the config ?
 #if OSL_DEBUG_LEVEL > 1
     fprintf( stderr, "inserted %d fonts from fontconfig\n", nFonts );
@@ -563,39 +728,14 @@
     FontCfgWrapper::release();
 }
 
-bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star::lang::Locale& rLocale )
+static void addtopattern(FontCfgWrapper& rWrapper, FcPattern *pPattern, 
+	italic::type eItalic, weight::type eWeight, width::type eWidth, pitch::type ePitch)
 {
 #ifdef ENABLE_FONTCONFIG
-    FontCfgWrapper& rWrapper = FontCfgWrapper::get();
-    if( ! rWrapper.isValid() )
-        return false;
-
-    FcConfig* pConfig = rWrapper.getDefConfig();
-    FcPattern* pPattern = rWrapper.FcPatternCreate();
-
-    OString aLangAttrib;
-    // populate pattern with font characteristics
-    if( rLocale.Language.getLength() )
-    {
-        OUStringBuffer aLang(6);
-        aLang.append( rLocale.Language );
-        if( rLocale.Country.getLength() )
-        {
-            aLang.append( sal_Unicode('-') );
-            aLang.append( rLocale.Country );
-        }
-        aLangAttrib = OUStringToOString( aLang.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
-    }
-    if( aLangAttrib.getLength() )
-        rWrapper.FcPatternAddString( pPattern, FC_LANG, (FcChar8*)aLangAttrib.getStr() );
-
-    OString aFamily = OUStringToOString( rInfo.m_aFamilyName, RTL_TEXTENCODING_UTF8 );
-    if( aFamily.getLength() )
-        rWrapper.FcPatternAddString( pPattern, FC_FAMILY, (FcChar8*)aFamily.getStr() );
-    if( rInfo.m_eItalic != italic::Unknown )
+    if( eItalic != italic::Unknown )
     {
         int nSlant = FC_SLANT_ROMAN;
-        switch( rInfo.m_eItalic )
+        switch( eItalic )
         {
             case italic::Italic:	 	nSlant = FC_SLANT_ITALIC;break;
             case italic::Oblique:	 	nSlant = FC_SLANT_OBLIQUE;break;
@@ -604,10 +744,10 @@
         }
         rWrapper.FcPatternAddInteger( pPattern, FC_SLANT, nSlant );
     }
-    if( rInfo.m_eWeight != weight::Unknown )
+    if( eWeight != weight::Unknown )
     {
         int nWeight = FC_WEIGHT_NORMAL;
-        switch( rInfo.m_eWeight )
+        switch( eWeight )
         {
             case weight::Thin:			nWeight = FC_WEIGHT_THIN;break;
             case weight::UltraLight:	nWeight = FC_WEIGHT_ULTRALIGHT;break;
@@ -624,10 +764,10 @@
         }
         rWrapper.FcPatternAddInteger( pPattern, FC_WEIGHT, nWeight );
     }
-    if( rInfo.m_eWidth != width::Unknown )
+    if( eWidth != width::Unknown )
     {
         int nWidth = FC_WIDTH_NORMAL;
-        switch( rInfo.m_eWidth )
+        switch( eWidth )
         {
             case width::UltraCondensed:	nWidth = FC_WIDTH_ULTRACONDENSED;break;
             case width::ExtraCondensed: nWidth = FC_WIDTH_EXTRACONDENSED;break;
@@ -643,10 +783,10 @@
         }
         rWrapper.FcPatternAddInteger( pPattern, FC_WIDTH, nWidth );
     }
-    if( rInfo.m_ePitch != pitch::Unknown )
+    if( ePitch != pitch::Unknown )
     {
         int nSpacing = FC_PROPORTIONAL;
-        switch( rInfo.m_ePitch )
+        switch( ePitch )
         {
             case pitch::Fixed:			nSpacing = FC_MONO;break;
             case pitch::Variable:		nSpacing = FC_PROPORTIONAL;break;
@@ -654,12 +794,148 @@
                 break;
         }
         rWrapper.FcPatternAddInteger( pPattern, FC_SPACING, nSpacing );
+        if (nSpacing == FC_MONO)
+            rWrapper.FcPatternAddString( pPattern, FC_FAMILY, (FcChar8*)"monospace");
     }
+#endif
+}
+
+String PrintFontManager::Substitute(const std::vector<String> &rNames, std::vector<sal_Unicode> &rGlyphs,
+        const ByteString &rLangAttrib, italic::type eItalic, weight::type eWeight,
+        width::type eWidth, pitch::type ePitch) const
+{
+    String aName;
+#ifdef ENABLE_FONTCONFIG
+    FontCfgWrapper& rWrapper = FontCfgWrapper::get();
+    if( ! rWrapper.isValid() )
+        return aName;
+
+    FcFontSet*  pSet = NULL;
+    FcPattern*  pPattern = rWrapper.FcPatternCreate();
+
+    // Prefer scalable fonts
+    rWrapper.FcPatternAddBool( pPattern, FC_SCALABLE, 1 );
+
+    std::vector<String>::const_iterator aEnd = rNames.end();
+    for (std::vector<String>::const_iterator aIter = rNames.begin(); aIter != aEnd; ++aIter)
+    {
+	    OString maTargetName = OUStringToOString(*aIter, RTL_TEXTENCODING_UTF8);
+        rWrapper.FcPatternAddString(pPattern, FC_FAMILY, (FcChar8*)maTargetName.getStr());
+        break;
+    }
+
+    if( rLangAttrib.Len() )
+        rWrapper.FcPatternAddString(pPattern, FC_LANG, (FcChar8*)rLangAttrib.GetBuffer());
+
+    // Add required Unicode characters, if any
+    if (! rGlyphs.empty() )
+    {
+       FcCharSet *unicodes = rWrapper.FcCharSetCreate();
+	    std::vector<sal_Unicode>::const_iterator aGlyphEnd = rGlyphs.end();
+	    for (std::vector<sal_Unicode>::const_iterator aGlyphIter = rGlyphs.begin(); 
+            aGlyphIter != aGlyphEnd; ++aGlyphIter)
+	    {
+            rWrapper.FcCharSetAddChar( unicodes, (FcChar32)*aGlyphIter );
+	    }
+       rWrapper.FcPatternAddCharSet( pPattern, FC_CHARSET, unicodes);
+       rWrapper.FcCharSetDestroy( unicodes );
+    }
+
+    addtopattern(rWrapper, pPattern, eItalic, eWeight, eWidth, ePitch);
+
+    rWrapper.FcConfigSubstitute( NULL, pPattern, FcMatchPattern );
+    rWrapper.FcDefaultSubstitute( pPattern );
+    FcResult eResult = FcResultNoMatch;
+    FcFontSet *pFontSet = rWrapper.getFontSet();
+    FcPattern* pResult = rWrapper.FcFontSetMatch( NULL, &pFontSet, 1, pPattern, &eResult );
+    rWrapper.FcPatternDestroy( pPattern );
+
+    if( pResult )
+    {
+        pSet = rWrapper.FcFontSetCreate();
+        // info: destroying the pSet destroys pResult implicitly
+        // since pResult was "added" to pSet
+        rWrapper.FcFontSetAdd( pSet, pResult );
+    }
+
+    if( pSet )
+    {
+        if( pSet->nfont > 0 )
+        {
+            //extract the closest match
+            FcChar8* family = NULL;
+            FcResult eFileRes = rWrapper.FcPatternGetString( pSet->fonts[0], FC_FAMILY, 0, &family );
+
+            if( eFileRes == FcResultMatch )
+            {
+                OString sFamily((sal_Char*)family);
+                std::hash_map< rtl::OString, rtl::OString, rtl::OStringHash >::const_iterator aI = m_aFontconfigNameToLocalized.find(sFamily);
+                if (aI != m_aFontconfigNameToLocalized.end())
+                    sFamily = aI->second;
+                aName = String( sFamily.getStr(), RTL_TEXTENCODING_UTF8 );
+            }
+
+            if (!rGlyphs.empty() )
+            {
+		std::vector<sal_Unicode> aGlyphs;
+                FcCharSet *unicodes;
+                if (rWrapper.FcPatternGetCharSet(pSet->fonts[0], FC_CHARSET, 0, &unicodes) == FcResultMatch)
+                {
+                    std::vector<sal_Unicode>::iterator aGlyphEnd = rGlyphs.end();
+                    for (std::vector<sal_Unicode>::iterator aGlyphIter = rGlyphs.begin();
+                        aGlyphIter != aGlyphEnd; ++aGlyphIter)
+                    {
+                            if (rWrapper.FcCharSetHasChar( unicodes, (FcChar32)*aGlyphIter ))
+				aGlyphs.push_back(*aGlyphIter);
+                    }
+                }
+		rGlyphs.swap(aGlyphs);
+            }
+
+        }
+    }
+    rWrapper.FcFontSetDestroy( pSet );
+#endif
+    return aName;
+}
+
+bool PrintFontManager::matchFont( FastPrintFontInfo& rInfo, const com::sun::star::lang::Locale& rLocale )
+{
+#ifdef ENABLE_FONTCONFIG
+    FontCfgWrapper& rWrapper = FontCfgWrapper::get();
+    if( ! rWrapper.isValid() )
+        return false;
+
+    FcConfig* pConfig = rWrapper.getDefConfig();
+    FcPattern* pPattern = rWrapper.FcPatternCreate();
+
+    OString aLangAttrib;
+    // populate pattern with font characteristics
+    if( rLocale.Language.getLength() )
+    {
+        OUStringBuffer aLang(6);
+        aLang.append( rLocale.Language );
+        if( rLocale.Country.getLength() )
+        {
+            aLang.append( sal_Unicode('-') );
+            aLang.append( rLocale.Country );
+        }
+        aLangAttrib = OUStringToOString( aLang.makeStringAndClear(), RTL_TEXTENCODING_UTF8 );
+    }
+    if( aLangAttrib.getLength() )
+        rWrapper.FcPatternAddString( pPattern, FC_LANG, (FcChar8*)aLangAttrib.getStr() );
+
+    OString aFamily = OUStringToOString( rInfo.m_aFamilyName, RTL_TEXTENCODING_UTF8 );
+    if( aFamily.getLength() )
+        rWrapper.FcPatternAddString( pPattern, FC_FAMILY, (FcChar8*)aFamily.getStr() );
+
+    addtopattern(rWrapper, pPattern, rInfo.m_eItalic, rInfo.m_eWeight, rInfo.m_eWidth, rInfo.m_ePitch);
 
     rWrapper.FcConfigSubstitute( pConfig, pPattern, FcMatchPattern );
     rWrapper.FcDefaultSubstitute( pPattern );
     FcResult eResult = FcResultNoMatch;
-    FcPattern* pResult = rWrapper.FcFontMatch( pConfig, pPattern, &eResult );
+    FcFontSet *pFontSet = rWrapper.getFontSet();
+    FcPattern* pResult = rWrapper.FcFontSetMatch( pConfig, &pFontSet, 1, pPattern, &eResult );
     bool bSuccess = false;
     if( pResult )
     {
--- psprint/source/fontmanager/fontmanager.cxx.old	2006-09-16 14:34:04.000000000 +0200
+++ psprint/source/fontmanager/fontmanager.cxx	2007-03-27 14:03:24.024723822 +0200
@@ -1165,7 +1165,8 @@
         m_nNextFontID( 1 ),
         m_pAtoms( new MultiAtomProvider() ),
         m_nNextDirAtom( 1 ),
-        m_pFontCache( NULL )
+        m_pFontCache( NULL ),
+	m_bFontconfigSuccess(false)
 {
     for( unsigned int i = 0; i < sizeof( aAdobeCodes )/sizeof( aAdobeCodes[0] ); i++ )
     {
@@ -2124,7 +2125,7 @@
 #endif
 
     // first try fontconfig
-    bool bFontconfigSuccess = initFontconfig();
+    m_bFontconfigSuccess = initFontconfig();
 
     // part one - look for downloadable fonts
     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
@@ -2146,7 +2147,7 @@
     }
 
     // don't search through many directories fontconfig already told us about
-    if( ! bFontconfigSuccess )
+    if( ! m_bFontconfigSuccess )
     {							
         Display *pDisplay = (Display*)pInitDisplay;
         
@@ -2239,7 +2240,7 @@
             }
         }
 #endif /* SOLARIS */
-    } // ! bFontconfigSuccess
+    } // ! m_bFontconfigSuccess
 
     // fill XLFD aliases from fonts.alias files
     initFontsAlias();
--- vcl/inc/outdev.h.old	2006-05-04 17:10:01.000000000 +0200
+++ vcl/inc/outdev.h	2007-03-27 14:03:54.345181199 +0200
@@ -213,7 +213,7 @@
                              const Font& rFont, const Size& rSize, ImplFontSubstEntry* pDevSpecific );
     ImplFontEntry*      GetFallback( ImplDevFontList* pFontList,
                                      const Font& rFont, const Size& rSize,
-                                     int nFallbackLevel );
+                                     int nFallbackLevel, std::vector<sal_Unicode> &rMissingGlyphs );
     void                Release( ImplFontEntry* );
     void                Invalidate();
 };
--- vcl/inc/outfont.hxx.old	2006-07-13 12:12:00.000000000 +0200
+++ vcl/inc/outfont.hxx	2007-03-27 14:03:24.034723972 +0200
@@ -230,6 +230,7 @@
     ImplDevFontListData*    FindFontFamily( const String& rFontName ) const;
     ImplDevFontListData*    ImplFindByFont( ImplFontSelectData&, bool bPrinter, ImplFontSubstEntry* pDevSpecificSubst ) const;
     ImplDevFontListData*    ImplFindBySearchName( const String& ) const;
+    ImplDevFontListData*    ImplGetFontconfigSubstitute( ImplFontSelectData &rFontSelData, ImplFontSubstEntry* pDevSpecific );
 
     bool                    HasFallbacks() const;
     void                    SetFallbacks( ImplDevFontListData**, int nCount );
@@ -333,6 +334,10 @@
                         ImplFontEntry( const ImplFontSelectData& );
     virtual             ~ImplFontEntry() {}
 
+    // cache of Unicode characters and replacement font names
+    typedef ::std::hash_map<sal_Unicode,String> UnicodeFallbackList;
+    UnicodeFallbackList maUnicodeFallbackList;
+
 public: // TODO: make data members private
     ImplFontSelectData  maFontSelData;      // FontSelectionData
     ImplFontMetricData  maMetric;           // Font Metric
@@ -343,6 +348,16 @@
     short               mnOwnOrientation;   // text angle if lower layers don't rotate text themselves
     short               mnOrientation;      // text angle in 3600 system
     bool                mbInit;             // true if maMetric member is valid
+
+    void                AddFallbackForUnicode( sal_Unicode ch, String fallback )
+                            { maUnicodeFallbackList[ch] = fallback; }
+    String              GetFallbackForUnicode( sal_Unicode ch )
+                            {
+                                UnicodeFallbackList::const_iterator it = maUnicodeFallbackList.find( ch );
+                                if ( it != maUnicodeFallbackList.end() )
+                                    return (*it).second;
+                                return String();
+                            }
 };
 
 
--- vcl/inc/sallayout.hxx.old	2006-12-21 13:02:27.000000000 +0100
+++ vcl/inc/sallayout.hxx	2007-03-27 14:04:44.025930622 +0200
@@ -103,6 +103,7 @@
     bool    GetRun( int* nMinRunPos, int* nEndRunPos, bool* bRTL ) const;
     bool    GetNextPos( int* nCharPos, bool* bRTL );
     bool    PosIsInRun( int nCharPos ) const;
+    bool    PosIsInAnyRun( int nCharPos ) const;
 };
 
 // -----------------
@@ -282,6 +283,8 @@
     ImplFontData*	 GetFallbackFontData( int nFallbackLevel ) const
     { return mpFallbackFonts[ nFallbackLevel ]; }
 
+    void SetInComplete(bool bInComplete = true);
+
 protected:
     virtual         ~MultiSalLayout();
 
@@ -300,6 +303,7 @@
     ImplFontData*	mpFallbackFonts[ MAX_FALLBACK ];
     ImplLayoutRuns  maFallbackRuns[ MAX_FALLBACK ];
     int             mnLevel;
+    bool            mbInComplete;
 };
 
 // --------------------
--- vcl/source/gdi/makefile.mk.old	2006-10-05 15:10:13.000000000 +0200
+++ vcl/source/gdi/makefile.mk	2007-03-27 14:03:24.034723972 +0200
@@ -52,6 +52,10 @@
 CDEFS+=-D_STD_NO_NAMESPACE -D_VOS_NO_NAMESPACE -D_UNO_NO_NAMESPACE
 .ENDIF
 
+.IF "$(ENABLE_FONTCONFIG)" != ""
+CDEFS += -DENABLE_FONTCONFIG
+.ENDIF
+
 # --- Files --------------------------------------------------------
 
 SLOFILES=	$(SLO)$/salmisc.obj 	\
--- vcl/source/gdi/outdev3.cxx.old	2006-12-21 13:02:52.000000000 +0100
+++ vcl/source/gdi/outdev3.cxx	2007-03-27 14:04:44.035930772 +0200
@@ -168,6 +168,9 @@
 #include <memory>
 #include <algorithm>
 
+#include <psprint/fontmanager.hxx>
+#include <i18npool/mslangid.hxx>
+
 // =======================================================================
 
 DBG_NAMEEX( OutputDevice )
@@ -2659,6 +2662,126 @@
     }
 }
 
+
+// -----------------------------------------------------------------------
+
+String GetFcSubstitute(const ImplFontSelectData &rFontSelData, std::vector<sal_Unicode> &rGlyphs)
+{
+#ifndef ENABLE_FONTCONFIG
+    String empty;
+    return empty;
+#else
+    std::vector<String> aNames;
+    if( rFontSelData.GetFamilyName().Len() )
+    {
+        sal_uInt16 nIndex = 0;
+	String aTempName;
+        do
+        {
+                aTempName = GetNextFontToken(rFontSelData.GetFamilyName(), nIndex);
+		aNames.push_back(aTempName);
+        }
+        while (nIndex != STRING_NOTFOUND);
+    }
+
+    ByteString aLangAttrib = MsLangId::convertLanguageToIsoByteString( rFontSelData.meLanguage );
+
+    psp::italic::type eItalic = psp::italic::Unknown;
+    if( rFontSelData.GetSlant() != ITALIC_DONTKNOW )
+    {
+        switch( rFontSelData.GetSlant() )
+        {
+            case ITALIC_NORMAL:  eItalic = psp::italic::Italic; break;
+            case ITALIC_OBLIQUE: eItalic = psp::italic::Oblique; break;
+            default:
+                break;
+        }
+    }
+
+    psp::weight::type eWeight = psp::weight::Unknown;
+    if( rFontSelData.GetWeight() != WEIGHT_DONTKNOW )
+    {
+        switch( rFontSelData.GetWeight() )
+        {
+            case WEIGHT_THIN:		eWeight = psp::weight::Thin; break;
+            case WEIGHT_ULTRALIGHT:	eWeight = psp::weight::UltraLight; break;
+            case WEIGHT_LIGHT:		eWeight = psp::weight::Light; break;
+            case WEIGHT_SEMILIGHT:	eWeight = psp::weight::SemiLight; break;
+            case WEIGHT_NORMAL:		eWeight = psp::weight::Normal; break;
+            case WEIGHT_MEDIUM:		eWeight = psp::weight::Medium; break;
+            case WEIGHT_SEMIBOLD:	eWeight = psp::weight::SemiBold; break;
+            case WEIGHT_BOLD:		eWeight = psp::weight::Bold; break;
+            case WEIGHT_ULTRABOLD:	eWeight = psp::weight::UltraBold; break;
+            case WEIGHT_BLACK:		eWeight = psp::weight::Black; break;
+            default:
+                break;
+        }
+    }
+
+    psp::width::type eWidth = psp::width::Unknown;
+    if( rFontSelData.GetWidthType() != WIDTH_DONTKNOW )
+    {
+        switch( rFontSelData.GetWidthType() )
+        {
+            case WIDTH_ULTRA_CONDENSED:	eWidth = psp::width::UltraCondensed; break;
+            case WIDTH_EXTRA_CONDENSED: eWidth = psp::width::ExtraCondensed; break;
+            case WIDTH_CONDENSED:	eWidth = psp::width::Condensed; break;
+            case WIDTH_SEMI_CONDENSED:	eWidth = psp::width::SemiCondensed; break;
+            case WIDTH_NORMAL:		eWidth = psp::width::Normal; break;
+            case WIDTH_SEMI_EXPANDED:	eWidth = psp::width::SemiExpanded; break;
+            case WIDTH_EXPANDED:	eWidth = psp::width::Expanded; break;
+            case WIDTH_EXTRA_EXPANDED:	eWidth = psp::width::ExtraExpanded; break;
+            case WIDTH_ULTRA_EXPANDED:	eWidth = psp::width::UltraExpanded; break;
+            default:
+                break;
+        }
+    }
+
+    psp::pitch::type ePitch = psp::pitch::Unknown;
+    if( rFontSelData.GetPitch() != PITCH_DONTKNOW )
+    {
+        switch(  rFontSelData.GetPitch() )
+        {
+            case PITCH_FIXED:    ePitch=psp::pitch::Fixed; break;
+            case PITCH_VARIABLE: ePitch=psp::pitch::Variable; break;
+            default:
+                break;
+        }
+    }
+
+    const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
+    return rMgr.Substitute(aNames, rGlyphs, aLangAttrib, eItalic, eWeight, eWidth, ePitch);
+#endif
+}
+
+// -----------------------------------------------------------------------
+
+ImplDevFontListData *ImplDevFontList::ImplGetFontconfigSubstitute( ImplFontSelectData &rFontSelData, ImplFontSubstEntry* pDevSpecific )
+{
+    // We dont' actually want to talk to Fontconfig at all for symbol fonts
+    if (rFontSelData.IsSymbolFont())
+        return 0;
+    // StarSymbol is a unicode font, but it still deserves the symbol flag
+    if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
+        ||  0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
+        return 0;
+
+    std::vector<sal_Unicode> aDummy;
+    String aName(GetFcSubstitute(rFontSelData, aDummy));
+    if (!aName.Len())
+        return 0;
+
+    String aUserName(aName);
+    ImplGetEnglishSearchFontName( aName );
+    ImplFontSubstitute( aName, FONT_SUBSTITUTE_ALWAYS, pDevSpecific );
+    ImplDevFontListData *pFontFamily = ImplFindBySearchName( aName );
+    if (pFontFamily)
+        rFontSelData.maTargetName = aUserName;
+
+    return pFontFamily;
+}
+
+
 // -----------------------------------------------------------------------
 
 ImplFontEntry* ImplFontCache::Get( ImplDevFontList* pFontList,
@@ -2696,8 +2819,12 @@
 
     if( !pEntry ) // no direct cache hit
     {
-        // find the best matching logical font family and update font selector accordingly
-        pFontFamily = pFontList->ImplFindByFont( aFontSelData, mbPrinter, pDevSpecific );
+        pFontFamily = pFontList->ImplGetFontconfigSubstitute( aFontSelData, pDevSpecific );
+        if (!pFontFamily)
+        {
+            // find the best matching logical font family and update font selector accordingly
+            pFontFamily = pFontList->ImplFindByFont( aFontSelData, mbPrinter, pDevSpecific );
+        }
         DBG_ASSERT( (pFontFamily != NULL), "ImplFontCache::Get() No logical font found!" );
         if( pFontFamily )
             aFontSelData.maSearchName = pFontFamily->GetSearchName();
@@ -3024,115 +3151,119 @@
 // -----------------------------------------------------------------------
 
 ImplFontEntry* ImplFontCache::GetFallback( ImplDevFontList* pFontList,
-    const Font& rOrigFont, const Size& rSize, int nFallbackLevel )
+     const Font& rOrigFont, const Size& rSize, int nFallbackLevel,
+     std::vector<sal_Unicode> &rMissingGlyphs )
 {
-    // make sure the fontlist knows it's fallbacks
-    if( !pFontList->HasFallbacks() )
+    ImplFontEntry*      pFallbackFont = NULL;
+    bool                cached = false;
+    bool                new_entry = false;
+    bool                symbolFont = false;
+    ImplFontEntry*      pOrigFontEntry = Get( pFontList, rOrigFont, rSize, NULL );
+    ImplFontSelectData  aSelData( rOrigFont, rOrigFont.GetName(), rSize );
+    sal_uInt16          nToken = 0;
+    String              aOrigFontName( GetNextFontToken(rOrigFont.GetName(), nToken) );
+
+    
+    const FontNameAttr* fontAttr = FontSubstConfiguration::get()->getSubstInfo( aOrigFontName );
+
+    // We dont' actually want to talk to Fontconfig at all for symbol fonts
+    if ( pFontList && fontAttr && (fontAttr->Type & IMPL_FONT_ATTR_SYMBOL) )
     {
-        // normalized family names of fonts suited for glyph fallback
-        // if a font is available related fonts can be ignored
-        // TODO: implement dynamic lists
-        static const char* aGlyphFallbackList[] = {
-            // empty strings separate the names of unrelated fonts
-            "eudc", "",
-            "arialunicodems", "cyberbit", "code2000", "",
-            "andalesansui", "",
-            "starsymbol", "opensymbol", "",
-            "msmincho", "fzmingti", "fzheiti", "ipamincho", "sazanamimincho", "kochimincho", "",
-            "sunbatang", "sundotum", "baekmukdotum", "gulim", "batang", "dotum", "",
-            "hgmincholightj", "msunglightsc", "msunglighttc", "hymyeongjolightk", "",
-            "tahoma", "timesnewroman", "lucidatypewriter", "lucidasans", "nimbussansl", "",
-            "shree", "mangal", "raavi", "shruti", "tunga", "latha", "",
-            "shayyalmt", "naskmt", "",
-            "david", "nachlieli", "lucidagrande", "",
-            "norasi", "angsanaupc", "",
-            "khmerossystem", "",
-	    "phetsarathot", "",
-            0
-        };
-
-        bool bHasEudc = false;
-        int nMaxLevel = 0;
-        int nBestQuality = 0;
-        ImplDevFontListData** pFallbackList = NULL;
-        for( const char** ppNames = &aGlyphFallbackList[0];; ++ppNames )
+        if ( fontAttr->Substitutions.size() )
         {
-            // advance to next sub-list when end-of-sublist marker
-            if( !**ppNames )    // #i46456# check for empty string, i.e., deref string itself not only ptr to it
+            ::std::vector< String >::const_iterator it = fontAttr->Substitutions.begin();
+            while ( it != fontAttr->Substitutions.end() )
             {
-                if( nBestQuality > 0 )
-                    if( ++nMaxLevel >= MAX_FALLBACK )
-                        break;
-                if( !ppNames[1] )
+                // Since *it is the "search name" like "standardsymbolsl"
+                // we have to find the Family Name (Standard Symbols L) for Fontconfig
+                ImplDevFontListData* pFontFamily = pFontList->FindFontFamily( *it );
+                if (pFontFamily)
+                {
+                    aSelData.maSearchName = pFontFamily->GetFamilyName();
                     break;
-                nBestQuality = 0;
-                continue;
+                }
+                ++it;
             }
+        }
+        symbolFont = true;
+        cached = true;
+    }
 
-            // test if the glyph fallback candidate font is available and scalable
-            String aTokenName( *ppNames, RTL_TEXTENCODING_UTF8 );
-            ImplDevFontListData* pFallbackFont = pFontList->FindFontFamily( aTokenName );
-            if( !pFallbackFont )
-                continue;
-            if( !pFallbackFont->IsScalable() )
-                continue;
+    std::vector<sal_Unicode> aGlyphs(rMissingGlyphs);
 
-            // keep the best font of the glyph fallback sub-list
-            if( nBestQuality < pFallbackFont->GetMinQuality() )
-            {
-                nBestQuality = pFallbackFont->GetMinQuality();
-                // store available glyph fallback fonts
-                if( !pFallbackList )
-                    pFallbackList = new ImplDevFontListData*[ MAX_FALLBACK ];
-                pFallbackList[ nMaxLevel ] = pFallbackFont;
-                if( !bHasEudc && !nMaxLevel )
-                    bHasEudc = (0 == strncmp( *ppNames, "eudc", 5 ));
-            }
-        }
+    // Try cached fallbacks first
+    if ( !symbolFont && !rMissingGlyphs.empty() )
+    {
+        aSelData.maSearchName = pOrigFontEntry->GetFallbackForUnicode( rMissingGlyphs[0] );
+        if ( aSelData.maSearchName.Len() )
+            cached = true;
+    }
 
-        // sort the list of fonts for glyph fallback by quality (highest first)
-        // #i33947# keep the EUDC font at the front of the list
-        // an insertion sort is good enough for this short list
-        const int nSortStart = bHasEudc ? 1 : 0;
-        for( int i = nSortStart+1, j; i < nMaxLevel; ++i )
-        {
-            ImplDevFontListData* pTestFont = pFallbackList[ i ];
-            int nTestQuality = pTestFont->GetMinQuality();
-            for( j = i; --j >= nSortStart; )
-                if( nTestQuality > pFallbackList[j]->GetMinQuality() )
-                    pFallbackList[ j+1 ] = pFallbackList[ j ];
-                else
-                    break;
-            pFallbackList[ j+1 ] = pTestFont;
-        }
+    if ( !cached )
+    {
+        String aName(GetFcSubstitute( aSelData, aGlyphs ));
+        if (aName.Len())
+            aSelData.maSearchName = aName;
+    }
 
-#if defined(HDU_DEBUG)
-        for( int i = 0; i < nMaxLevel; ++i )
+    if (!rMissingGlyphs.empty())
+    {
+        std::vector<sal_Unicode>::const_iterator aEnd = aGlyphs.end();
+        for (std::vector<sal_Unicode>::const_iterator aI = aGlyphs.begin(); aI != aEnd; ++aI)
         {
-            ImplDevFontListData* pFont = pFallbackList[ i ];
-            ByteString aFontName( pFont->GetFamilyName(), RTL_TEXTENCODING_UTF8 );
-            fprintf( stderr, "GlyphFallbackFont[%d] (quality=%05d): \"%s\"\n",
-                i, pFont->GetMinQuality(), aFontName.GetBuffer() );
+            std::vector<sal_Unicode>::iterator aNewEnd = 
+                std::remove(rMissingGlyphs.begin(), rMissingGlyphs.end(), *aI);
+            if (aNewEnd != rMissingGlyphs.end())
+                rMissingGlyphs.erase(aNewEnd);
+            //In this case only the first missing symbol has been taken into account and is
+            //known safe to replace
+            if (cached || symbolFont)
+                break;
         }
-#endif
-
-        pFontList->SetFallbacks( pFallbackList, nMaxLevel );
     }
 
-    Font aFallbackFont = rOrigFont;
-
-    // nFallbackLevel==0 => original font without device specific substitution
-    // nFallbackLevel>=1 => use a font from the glyph fallback font list
-    if( nFallbackLevel>=1 )
+    // Check our font instance cache first, if not found then
+    // add this ImplFontSelectData to the cache along with its ImplFontEntry
+    FontInstanceList::const_iterator it = maFontInstanceList.find( aSelData );
+    if (it != maFontInstanceList.end())
+        pFallbackFont = (*it).second;
+    else
     {
-        ImplDevFontListData* pFallbackData = pFontList->GetFallback( nFallbackLevel-1 );
-        if( !pFallbackData )
-            return NULL;
+        // find the best matching physical font face
+        ImplDevFontListData* pFontFamily = pFontList->FindFontFamily( aSelData.maSearchName );
+        if (pFontFamily)
+        {
+            ImplFontData* pFontData = pFontFamily->FindBestFontFace( aSelData );
 
-        aFallbackFont.SetName( pFallbackData->GetSearchName() );
+            // create a new logical font instance from this physical font face
+            aSelData.mpFontData = pFontData;
+            pFallbackFont = pFontData->CreateFontInstance( aSelData );
+
+            // if we found a different symbol font we need a symbol conversion table
+            if( pFontData->IsSymbolFont() )
+                if( aSelData.maTargetName != aSelData.maSearchName )
+                    pFallbackFont->mpConversion = ImplGetRecodeData( aSelData.maTargetName, aSelData.maSearchName );
+            // add the new entry to the cache
+            maFontInstanceList[ aSelData ] = pFallbackFont;
+            new_entry = true;
+        }
+        else
+        {
+            ByteString l( aSelData.maSearchName, RTL_TEXTENCODING_UTF8 );
+            //fprintf (stderr, "--- Couldn't get FontFamily for '%s'\n", l.GetBuffer());
+        }
     }
 
-    ImplFontEntry* pFallbackFont = Get( pFontList, aFallbackFont, rSize, NULL );
+    // Cache the fallback font for each of the missing Unicode chars
+    if ( !symbolFont && aSelData.maSearchName.Len() )
+    {
+        std::vector<sal_Unicode>::const_iterator aEnd = aGlyphs.end();
+        for (std::vector<sal_Unicode>::const_iterator aI = aGlyphs.begin(); aI != aEnd; ++aI)
+        {
+            if (!pOrigFontEntry->GetFallbackForUnicode(*aI).Len())
+                pOrigFontEntry->AddFallbackForUnicode(*aI, aSelData.maSearchName);
+        }
+    }
 
     if( pFallbackFont && !pFallbackFont->mbInit )
     {
@@ -3142,6 +3273,27 @@
         pFallbackFont->maMetric.maStyleName = String();
     }
 
+    if ( pFallbackFont && !new_entry )
+    {
+        // increase the font instance's reference count
+        if( !pFallbackFont->mnRefCount++ )
+            --mnRef0Count;
+    }
+
+#if 0
+    sal_uInt16 nTok = 0;
+    ByteString n( GetNextFontToken(rOrigFont.GetName(), nTok), RTL_TEXTENCODING_UTF8);
+    ByteString m;
+    if (pFallbackFont)
+    {
+        nTok = 0;
+        ByteString tS( GetNextFontToken(pFallbackFont->maFontSelData.mpFontData->GetFamilyName(), nTok), RTL_TEXTENCODING_UTF8 );
+        m.Assign( tS );
+    }
+    fprintf (stderr, "Glyph fallback '%s'->'%s' %s\n", n.GetBuffer(), pFallbackFont ? m.GetBuffer() : "none",
+                new_entry ? "(new)" : "(cached)");
+#endif
+
     return pFallbackFont;
 }
 
@@ -6101,7 +6253,7 @@
     // do glyph fallback if needed
     // #105768# avoid fallback for very small font sizes
     if( aLayoutArgs.NeedFallback() )
-        if( mpFontEntry && (mpFontEntry->maFontSelData.mnHeight >= 6) )
+        if( mpFontEntry && (mpFontEntry->maFontSelData.mnHeight >= 3) )
             pSalLayout = ImplGlyphFallbackLayout( pSalLayout, aLayoutArgs );
 
     // position, justify, etc. the layout
@@ -6145,6 +6297,12 @@
         rLayoutArgs.ResetPos();
     }
 #endif
+    int nCharPos = -1;
+    bool bRTL = false;
+    std::vector<sal_Unicode> aGlyphs;
+    while (rLayoutArgs.GetNextPos( &nCharPos, &bRTL))
+        aGlyphs.push_back(rLayoutArgs.mpStr[ nCharPos ]);
+    rLayoutArgs.ResetPos();
 
     ImplFontSelectData aFontSelData = mpFontEntry->maFontSelData;
     Size aFontSize( aFontSelData.mnWidth, aFontSelData.mnHeight );
@@ -6161,13 +6319,13 @@
     {
         // find a font family suited for glyph fallback
         ImplFontEntry* pFallbackFont = mpFontCache->GetFallback( mpFontList,
-            maFont, aFontSize, nFallbackLevel-nDevSpecificFallback );
+            maFont, aFontSize, nFallbackLevel-nDevSpecificFallback, aGlyphs );
         if( !pFallbackFont )
             break;
 
         aFontSelData.mpFontEntry = pFallbackFont;
         aFontSelData.mpFontData = pFallbackFont->maFontSelData.mpFontData;
-        if( mpFontEntry )
+        if( mpFontEntry && nFallbackLevel < MAX_FALLBACK-1)
         {
             // ignore fallback font if it is the same as the original font
             if( mpFontEntry->maFontSelData.mpFontData == aFontSelData.mpFontData )
@@ -6195,15 +6353,24 @@
         SalLayout* pFallback = mpGraphics->GetTextLayout( rLayoutArgs, nFallbackLevel );
         if( pFallback )
         {
+            int nTemp = rLayoutArgs.mnFlags;
+
+            if (nFallbackLevel == MAX_FALLBACK-1)
+                rLayoutArgs.mnFlags = rLayoutArgs.mnFlags ^= SAL_LAYOUT_FOR_FALLBACK;
+
             if( pFallback->LayoutText( rLayoutArgs ) )
             {
                 if( !pMultiSalLayout )
                     pMultiSalLayout = new MultiSalLayout( *pSalLayout );
                 pMultiSalLayout->AddFallback( *pFallback,
                     rLayoutArgs.maRuns, aFontSelData.mpFontData );
+                if (nFallbackLevel == MAX_FALLBACK-1)
+                    pMultiSalLayout->SetInComplete();
             }
             else
                 pFallback->Release();
+
+            rLayoutArgs.mnFlags = nTemp;
         }
 
         mpFontCache->Release( pFallbackFont );
--- vcl/source/gdi/sallayout.cxx.old	2007-02-08 17:28:57.000000000 +0100
+++ vcl/source/gdi/sallayout.cxx	2007-03-27 14:04:44.035930772 +0200
@@ -458,6 +458,27 @@
     return true;
 }
 
+bool ImplLayoutRuns::PosIsInAnyRun( int nCharPos ) const
+{
+    bool bRet = false;
+    int nRunIndex = mnRunIndex;
+
+    ImplLayoutRuns *pThis = const_cast<ImplLayoutRuns*>(this);
+
+    pThis->ResetPos();
+
+    for (int i = 0; i < maRuns.size(); i+=2)
+    {
+        if ((bRet = PosIsInRun( nCharPos )))
+            break;
+        pThis->NextRun();
+    }
+
+    pThis->mnRunIndex = nRunIndex;
+    return bRet;
+}
+
+
 // -----------------------------------------------------------------------
 
 bool ImplLayoutRuns::GetNextPos( int* nCharPos, bool* bRightToLeft )
@@ -1540,13 +1561,20 @@
 
 MultiSalLayout::MultiSalLayout( SalLayout& rBaseLayout )
 :   SalLayout(),
-    mnLevel( 1 )
+    mnLevel( 1 ),
+    mbInComplete( false )
 {
     //maFallbackRuns[0].Clear();
     mpLayouts[ 0 ]  = &rBaseLayout;
     mnUnitsPerPixel = rBaseLayout.GetUnitsPerPixel();
 }
 
+void MultiSalLayout::SetInComplete(bool bInComplete)
+{
+    mbInComplete = bInComplete;
+    maFallbackRuns[mnLevel-1] = ImplLayoutRuns();
+}
+
 // -----------------------------------------------------------------------
 
 MultiSalLayout::~MultiSalLayout()
@@ -1576,7 +1604,8 @@
 {
     if( mnLevel <= 1 )
         return false;
-    maFallbackRuns[ mnLevel-1 ] = rArgs.maRuns;
+    if (!mbInComplete)
+        maFallbackRuns[ mnLevel-1 ] = rArgs.maRuns;
     return true;
 }
 
@@ -1675,7 +1704,12 @@
 
         // remove unused parts of component
         if( n > 0 )
-            mpLayouts[n]->Simplify( false );
+        {
+            if (mbInComplete && (n == mnLevel-1))
+                mpLayouts[n]->Simplify( true );
+            else
+                mpLayouts[n]->Simplify( false );
+        }
 
         // prepare merging components
         nStartNew[ nLevel ] = nStartOld[ nLevel ] = 0;
@@ -1710,7 +1744,7 @@
     {
         // find best fallback level
         for( n = 0; n < nLevel; ++n )
-            if( nValid[n] && !maFallbackRuns[n].PosIsInRun( nActiveCharPos ) )
+            if( nValid[n] && !maFallbackRuns[n].PosIsInAnyRun( nActiveCharPos ) )
                 // fallback level n wins when it requested no further fallback
                 break;
         int nFBLevel = n;
@@ -1732,9 +1766,13 @@
         if( n > 0 )
         {
             // drop the NotDef glyphs in the base layout run if a fallback run exists
-            while( maFallbackRuns[ n-1 ].PosIsInRun( nCharPos[0] ) )
+            while ( 
+                    (maFallbackRuns[ n-1 ].PosIsInRun( nCharPos[0] ) ) &&
+                    (!maFallbackRuns[ n ].PosIsInAnyRun( nCharPos[0] ) )
+                  )
             {
-                mpLayouts[0]->DropGlyph( nStartOld[0] );
+                if (!(mbInComplete && (n == mnLevel-1)))
+                    mpLayouts[0]->DropGlyph( nStartOld[0] );
                 nStartOld[0] = nStartNew[0];
                 nValid[0] = mpLayouts[0]->GetNextGlyphs( 1, &nDummy, aPos,
                     nStartNew[0], &nGlyphAdv[0], &nCharPos[0] );
@@ -1752,6 +1790,7 @@
 
             // proceed to next glyph
             nStartOld[n] = nStartNew[n];
+            int nOrigCharPos = nCharPos[n];
             nValid[n] = mpLayouts[n]->GetNextGlyphs( 1, &nDummy, aPos,
                 nStartNew[n], &nGlyphAdv[n], &nCharPos[n] );
 
@@ -1764,6 +1803,23 @@
                 break;
             }
 
+            //If the next character is one which belongs to the next level, then we
+            //are finished here for now, and we'll pick up after the next level has
+            //been processed
+            if ((n+1 < nLevel) && (abs(nCharPos[n] - nOrigCharPos)))
+            {
+                if (nOrigCharPos < nCharPos[n])
+                {
+                    if (nCharPos[n+1] > nOrigCharPos && (nCharPos[n+1] < nCharPos[n]))
+                        break;
+                }
+                else if (nOrigCharPos > nCharPos[n])
+                {
+                    if (nCharPos[n+1] > nCharPos[n] && (nCharPos[n+1] < nOrigCharPos))
+                        break;
+                }
+            }
+
             // break at end of layout run
             if( n > 0 )
             {
@@ -1839,7 +1895,8 @@
 
 void MultiSalLayout::DrawText( SalGraphics& rGraphics ) const
 {
-    for( int i = mnLevel; --i >= 0; )
+    int nLevel = mbInComplete ? mnLevel-1 : mnLevel;
+    for( int i = nLevel; --i >= 0; )
     {
         SalLayout& rLayout = *mpLayouts[ i ];
         rLayout.DrawBase() = maDrawBase;
--- vcl/source/glyphs/gcach_layout.cxx.old	2006-12-21 13:06:58.000000000 +0100
+++ vcl/source/glyphs/gcach_layout.cxx	2007-03-27 14:10:54.501519162 +0200
@@ -402,6 +402,11 @@
 
 // -----------------------------------------------------------------------
 
+static bool lcl_CharIsJoiner(sal_Unicode cChar)
+{
+	return ((cChar == 0x200C) || (cChar == 0x200D));
+}
+
 bool IcuLayoutEngine::operator()( ServerFontLayout& rLayout, ImplLayoutArgs& rArgs )
 {
     LEUnicode* pIcuChars;
@@ -514,7 +519,14 @@
             if( !nGlyphIndex )
             {
                 if( nCharPos >= 0 )
+                {
                     rArgs.NeedFallback( nCharPos, bRightToLeft );
+                    if ( (nCharPos > 0) && lcl_CharIsJoiner(rArgs.mpStr[nCharPos-1]) )
+                        rArgs.NeedFallback( nCharPos-1, bRightToLeft );
+                    else if ( (nCharPos + 1 < nRawRunGlyphCount) && lcl_CharIsJoiner(rArgs.mpStr[nCharPos+1]) )
+                        rArgs.NeedFallback( nCharPos+1, bRightToLeft );
+                }
+
                 if( SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags )
                     continue;
             }
--- vcl/source/window/makefile.mk.old	2006-10-05 12:56:30.000000000 +0200
+++ vcl/source/window/makefile.mk	2007-03-27 14:03:24.034723972 +0200
@@ -46,6 +46,10 @@
 .INCLUDE :	settings.mk
 .INCLUDE :  $(PRJ)$/util$/makefile2.pmk
 
+.IF "$(ENABLE_FONTCONFIG)" != ""
+CDEFS += -DENABLE_FONTCONFIG
+.ENDIF
+
 # --- Files --------------------------------------------------------
 
 SLOFILES= \
--- vcl/source/window/window.cxx.old	2007-01-26 13:14:38.000000000 +0100
+++ vcl/source/window/window.cxx	2007-03-27 14:03:24.044724123 +0200
@@ -200,6 +200,7 @@
 #endif
 
 #include <pdfextoutdevdata.hxx>
+#include <psprint/fontmanager.hxx>
 #include "lazydelete.hxx"
 
 using namespace rtl;
@@ -346,6 +347,12 @@
 
 bool Window::ImplCheckUIFont( const Font& rFont )
 {
+#ifndef WNT
+    const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
+    if (rMgr.hasFontconfig())
+        return true;
+#endif
+
     String aTestText;
     aTestText.Append( Button::GetStandardText( BUTTON_OK ) );
     aTestText.Append( Button::GetStandardText( BUTTON_CANCEL ) );
--- vcl/util/makefile.mk.old	2007-01-19 13:56:23.000000000 +0100
+++ vcl/util/makefile.mk	2007-03-27 14:03:24.044724123 +0200
@@ -177,6 +177,7 @@
             $(BASEGFXLIB)		\
             $(ICUUCLIB)			\
             $(ICULELIB)			\
+            -lpsp$(VERSION)$(DLLPOSTFIX)	\
 			$(JVMACCESSLIB)
 SHL1USE_EXPORTS=ordinal
 
