--- vcl/win/source/gdi/salgdi3.cxx 2009-05-22 16:48:24.000000000 +0800 +++ ../source3.0/OOO300_m9/vcl/win/source/gdi/salgdi3.cxx 2009-05-22 16:57:43.000000000 +0800 @@ -52,6 +52,10 @@ #include #include #include + +//enable ImplGlyphFallbackFontSubstitution declaration. +#include + #include #include #include @@ -310,7 +314,119 @@ } // ======================================================================= +// platform specific font substitution hooks +//glyph fallback enhancement + +class ImplWinFontData; +static ImplWinFontData* ImplLogMetricToDevFontDataW( const ENUMLOGFONTEXW*, + const NEWTEXTMETRICW*, DWORD ); + +//CALLBACK function to get substitute font supporting missing characters. +struct ImplSubstituteInfo +{ + HDC mhDC; + ImplFontSelectData* mpFontSelData; + String* mpName; + rtl::OUString* mpMissingString; + LOGFONTA* mpLogFontA; + LOGFONTW* mpLogFontW; + int mFound; +}; + +//The function is a callback function used with the EnumFontFamiliesExW function. +//It is used to process the fonts. It is called once for each enumerated font. + +int CALLBACK SalGetSubstituteFontProcExW( const ENUMLOGFONTEXW* pLogFont, + const NEWTEXTMETRICEXW* pMetric, + DWORD nFontType, LPARAM lParam ) +{ + ImplSubstituteInfo* pSubInfo = (ImplSubstituteInfo*)(void*)lParam; + // Ignore vertical fonts + if ( pLogFont->elfLogFont.lfFaceName[0] != '@' ) + { + String aName( reinterpret_cast(pLogFont->elfLogFont.lfFaceName) ); + pSubInfo->mpName = &aName; + + if(pSubInfo->mpFontSelData->maTargetName == *pSubInfo->mpName) + return 1; + + if( (nFontType & RASTER_FONTTYPE) && !(nFontType & DEVICE_FONTTYPE) ) + return 1; + + const LOGFONTW rLogFont = pLogFont->elfLogFont; + + HFONT hNewFont = ::CreateFontIndirectW( &rLogFont ); + HFONT hOldFont = ::SelectFont( pSubInfo->mhDC, hNewFont ); + ImplWinFontData* pData = ImplLogMetricToDevFontDataW( pLogFont, &(pMetric->ntmTm), nFontType ); + pData->UpdateFromHDC(pSubInfo->mhDC); + + ::SelectFont( pSubInfo->mhDC, hOldFont ); + ::DeleteFont( hNewFont ); + + sal_UCS4 cChar = 0; + sal_Int32 nStrIndex = 0; + sal_Int32 nStrlength = pSubInfo->mpMissingString->getLength(); + + while( nStrIndex < nStrlength) { + cChar = pSubInfo->mpMissingString->iterateCodePoints( &nStrIndex ); + if(!(pData->HasChar(cChar))) + return 1; + } + + if(nStrIndex == nStrlength) + { + pSubInfo->mpFontSelData->maSearchName = *pSubInfo->mpName; + pSubInfo->mFound = 1; + return 0; + } + } + + return 1; +} + +class WinGlyphFallbackSubstititution +: public ImplGlyphFallbackFontSubstitution +{ + // TODO: add a cache + HDC mhDC; +public: + void SetHDC(HDC hdc) {mhDC = hdc;} + bool FindFontSubstitute( ImplFontSelectData&, rtl::OUString& rMissingCodes ) const; +}; + +//get fallback font for missing character +bool WinGlyphFallbackSubstititution::FindFontSubstitute(ImplFontSelectData& rFontSelData, rtl::OUString& rMissingCodes) const{ + + ImplSubstituteInfo aInfo; + aInfo.mhDC = this->mhDC; + aInfo.mpFontSelData = &rFontSelData; + aInfo.mpName = NULL; + aInfo.mpLogFontA = NULL; + aInfo.mpLogFontW = NULL; + aInfo.mFound = 0; + aInfo.mpMissingString = &rMissingCodes; + if ( aSalShlData.mbWNT ) { + LOGFONTW aLogFont; + memset( &aLogFont, 0, sizeof( aLogFont ) ); + aLogFont.lfCharSet = DEFAULT_CHARSET; + aInfo.mpLogFontW = &aLogFont; + + EnumFontFamiliesExW( mhDC, &aLogFont, + (FONTENUMPROCW)SalGetSubstituteFontProcExW, (LPARAM)(void*)&aInfo, 0 ); + } + else { + return false; + } + + if(aInfo.mFound) + return true; + else + return false; +} + + +// ======================================================================= struct ImplEnumInfo { HDC mhDC; @@ -2237,6 +2353,11 @@ bImplSalCourierScalable = aInfo.mbImplSalCourierScalable; bImplSalCourierNew = aInfo.mbImplSalCourierNew; } + + //set font fallback hook + static WinGlyphFallbackSubstititution aSubstFallback; + aSubstFallback.SetHDC(mhDC); + pFontList->SetFallbackHook( &aSubstFallback ); } // ----------------------------------------------------------------------------