/OOO330_m20/vcl/win/source/gdi/salgdi3.cxx
C++ | 3229 lines | 2385 code | 466 blank | 378 comment | 498 complexity | d54f0631df34fe719281c43ab2217ee5 MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- /*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org. If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
- // MARKER(update_precomp.py): autogen include statement, do not remove
- #include "precompiled_vcl.hxx"
- #include <string.h>
- #include <malloc.h>
- #include <tools/prewin.h>
- #include <windows.h>
- #include <tools/postwin.h>
- #include <vcl/sysdata.hxx>
- #include "tools/svwin.h"
- #include "wincomp.hxx"
- #include "saldata.hxx"
- #include "salgdi.h"
- #include "vcl/svapp.hxx"
- #include "vcl/outfont.hxx"
- #include "vcl/font.hxx"
- #include "vcl/fontsubset.hxx"
- #include "vcl/sallayout.hxx"
- #include "vcl/outdev.h" // for ImplGlyphFallbackFontSubstitution
- #include "unotools/fontcfg.hxx" // for IMPL_FONT_ATTR_SYMBOL
- #include "rtl/logfile.hxx"
- #include "rtl/tencinfo.h"
- #include "rtl/textcvt.h"
- #include "rtl/bootstrap.hxx"
- #include "i18npool/mslangid.hxx"
- #include "osl/module.h"
- #include "osl/file.hxx"
- #include "osl/thread.hxx"
- #include "osl/process.h"
- #include "tools/poly.hxx"
- #include "tools/debug.hxx"
- #include "tools/stream.hxx"
- #include "basegfx/polygon/b2dpolygon.hxx"
- #include "basegfx/polygon/b2dpolypolygon.hxx"
- #include "basegfx/matrix/b2dhommatrix.hxx"
- #include <basegfx/matrix/b2dhommatrixtools.hxx>
- #include "sft.hxx"
- #ifdef GCP_KERN_HACK
- #include <algorithm>
- #endif
- #ifdef ENABLE_GRAPHITE
- #include <graphite/GrClient.h>
- #include <graphite/WinFont.h>
- #endif
- #include <vector>
- #include <set>
- #include <map>
- using namespace vcl;
- static const int MAXFONTHEIGHT = 2048;
- // -----------
- // - Inlines -
- // -----------
- inline FIXED FixedFromDouble( double d )
- {
- const long l = (long) ( d * 65536. );
- return *(FIXED*) &l;
- }
- // -----------------------------------------------------------------------
- inline int IntTimes256FromFixed(FIXED f)
- {
- int nFixedTimes256 = (f.value << 8) + ((f.fract+0x80) >> 8);
- return nFixedTimes256;
- }
- // =======================================================================
- // these variables can be static because they store system wide settings
- static bool bImplSalCourierScalable = false;
- static bool bImplSalCourierNew = false;
- // =======================================================================
- // -----------------------------------------------------------------------
- // TODO: also support temporary TTC font files
- typedef std::map< String, ImplDevFontAttributes > FontAttrMap;
- class ImplFontAttrCache
- {
- private:
- FontAttrMap aFontAttributes;
- rtl::OUString aCacheFileName;
- String aBaseURL;
- BOOL bModified;
- protected:
- String OptimizeURL( const String& rURL ) const;
- enum{ MAGIC = 0x12349876 }; // change if fontattrcache format changes
- public:
- ImplFontAttrCache( const String& rCacheFileName, const String& rBaseURL );
- ~ImplFontAttrCache();
- ImplDevFontAttributes GetFontAttr( const String& rFontFileName ) const;
- void AddFontAttr( const String& rFontFileName, const ImplDevFontAttributes& );
- };
- ImplFontAttrCache::ImplFontAttrCache( const String& rFileNameURL, const String& rBaseURL ) : aBaseURL( rBaseURL )
- {
- bModified = FALSE;
- aBaseURL.ToLowerAscii(); // Windows only, no problem...
- // open the cache file
- osl::FileBase::getSystemPathFromFileURL( rFileNameURL, aCacheFileName );
- SvFileStream aCacheFile( aCacheFileName, STREAM_READ );
- if( !aCacheFile.IsOpen() )
- return;
- // check the cache version
- sal_uInt32 nCacheMagic;
- aCacheFile >> nCacheMagic;
- if( nCacheMagic != ImplFontAttrCache::MAGIC )
- return; // ignore cache and rewrite if no match
- // read the cache entries from the file
- String aFontFileURL, aFontName;
- ImplDevFontAttributes aDFA;
- for(;;)
- {
- aCacheFile.ReadByteString( aFontFileURL, RTL_TEXTENCODING_UTF8 );
- if( !aFontFileURL.Len() )
- break;
- aCacheFile.ReadByteString( aDFA.maName, RTL_TEXTENCODING_UTF8 );
- short n;
- aCacheFile >> n; aDFA.meWeight = static_cast<FontWeight>(n);
- aCacheFile >> n; aDFA.meItalic = static_cast<FontItalic>(n);
- aCacheFile >> n; aDFA.mePitch = static_cast<FontPitch>(n);
- aCacheFile >> n; aDFA.meWidthType = static_cast<FontWidth>(n);
- aCacheFile >> n; aDFA.meFamily = static_cast<FontFamily>(n);
- aCacheFile >> n; aDFA.mbSymbolFlag = (n != 0);
- aCacheFile.ReadByteStringLine( aDFA.maStyleName, RTL_TEXTENCODING_UTF8 );
- aFontAttributes[ aFontFileURL ] = aDFA;
- }
- }
- ImplFontAttrCache::~ImplFontAttrCache()
- {
- if ( bModified )
- {
- SvFileStream aCacheFile( aCacheFileName, STREAM_WRITE|STREAM_TRUNC );
- if ( aCacheFile.IsWritable() )
- {
- sal_uInt32 nCacheMagic = ImplFontAttrCache::MAGIC;
- aCacheFile << nCacheMagic;
- // write the cache entries to the file
- FontAttrMap::const_iterator aIter = aFontAttributes.begin();
- while ( aIter != aFontAttributes.end() )
- {
- const String rFontFileURL( (*aIter).first );
- const ImplDevFontAttributes& rDFA( (*aIter).second );
- aCacheFile.WriteByteString( rFontFileURL, RTL_TEXTENCODING_UTF8 );
- aCacheFile.WriteByteString( rDFA.maName, RTL_TEXTENCODING_UTF8 );
- aCacheFile << static_cast<short>(rDFA.meWeight);
- aCacheFile << static_cast<short>(rDFA.meItalic);
- aCacheFile << static_cast<short>(rDFA.mePitch);
- aCacheFile << static_cast<short>(rDFA.meWidthType);
- aCacheFile << static_cast<short>(rDFA.meFamily);
- aCacheFile << static_cast<short>(rDFA.mbSymbolFlag != false);
- aCacheFile.WriteByteStringLine( rDFA.maStyleName, RTL_TEXTENCODING_UTF8 );
- aIter++;
- }
- // EOF Marker
- String aEmptyStr;
- aCacheFile.WriteByteString( aEmptyStr, RTL_TEXTENCODING_UTF8 );
- }
- }
- }
- String ImplFontAttrCache::OptimizeURL( const String& rURL ) const
- {
- String aOptimizedFontFileURL( rURL );
- aOptimizedFontFileURL.ToLowerAscii(); // Windows only, no problem...
- if ( aOptimizedFontFileURL.CompareTo( aBaseURL, aBaseURL.Len() ) == COMPARE_EQUAL )
- aOptimizedFontFileURL = aOptimizedFontFileURL.Copy( aBaseURL.Len() );
- return aOptimizedFontFileURL;
- }
- ImplDevFontAttributes ImplFontAttrCache::GetFontAttr( const String& rFontFileName ) const
- {
- ImplDevFontAttributes aDFA;
- FontAttrMap::const_iterator it = aFontAttributes.find( OptimizeURL( rFontFileName ) );
- if( it != aFontAttributes.end() )
- {
- aDFA = it->second;
- }
- return aDFA;
- }
- void ImplFontAttrCache::AddFontAttr( const String& rFontFileName, const ImplDevFontAttributes& rDFA )
- {
- DBG_ASSERT( rFontFileName.Len() && rDFA.maName.Len(), "ImplFontNameCache::AddFontName - invalid data!" );
- if ( rFontFileName.Len() && rDFA.maName.Len() )
- {
- aFontAttributes.insert( FontAttrMap::value_type( OptimizeURL( rFontFileName ), rDFA ) );
- bModified = TRUE;
- }
- }
- // =======================================================================
- // raw font data with a scoped lifetime
- class RawFontData
- {
- public:
- explicit RawFontData( HDC, DWORD nTableTag=0 );
- ~RawFontData() { delete[] mpRawBytes; }
- const unsigned char* get() const { return mpRawBytes; }
- const unsigned char* steal() { unsigned char* p = mpRawBytes; mpRawBytes = NULL; return p; }
- const int size() const { return mnByteCount; }
- private:
- unsigned char* mpRawBytes;
- int mnByteCount;
- };
- RawFontData::RawFontData( HDC hDC, DWORD nTableTag )
- : mpRawBytes( NULL )
- , mnByteCount( 0 )
- {
- // get required size in bytes
- mnByteCount = ::GetFontData( hDC, nTableTag, 0, NULL, 0 );
- if( mnByteCount == GDI_ERROR )
- return;
- else if( !mnByteCount )
- return;
- // allocate the array
- mpRawBytes = new unsigned char[ mnByteCount ];
- // get raw data in chunks small enough for GetFontData()
- int nRawDataOfs = 0;
- DWORD nMaxChunkSize = 0x100000;
- for(;;)
- {
- // calculate remaining raw data to get
- DWORD nFDGet = mnByteCount - nRawDataOfs;
- if( nFDGet <= 0 )
- break;
- // #i56745# limit GetFontData requests
- if( nFDGet > nMaxChunkSize )
- nFDGet = nMaxChunkSize;
- const DWORD nFDGot = ::GetFontData( hDC, nTableTag, nRawDataOfs,
- (void*)(mpRawBytes + nRawDataOfs), nFDGet );
- if( !nFDGot )
- break;
- else if( nFDGot != GDI_ERROR )
- nRawDataOfs += nFDGot;
- else
- {
- // was the chunk too big? reduce it
- nMaxChunkSize /= 2;
- if( nMaxChunkSize < 0x10000 )
- break;
- }
- }
- // cleanup if the raw data is incomplete
- if( nRawDataOfs != mnByteCount )
- {
- delete[] mpRawBytes;
- mpRawBytes = NULL;
- }
- }
- // ===========================================================================
- // platform specific font substitution hooks for glyph fallback enhancement
- // TODO: move into i18n module (maybe merge with svx/ucsubset.*
- // or merge with i18nutil/source/utility/unicode_data.h)
- struct Unicode2LangType
- {
- sal_UCS4 mnMinCode;
- sal_UCS4 mnMaxCode;
- LanguageType mnLangID;
- };
- // entries marked with default-CJK get replaced with the default-CJK language
- #define LANGUAGE_DEFAULT_CJK 0xFFF0
- // map unicode ranges to languages supported by OOo
- // NOTE: due to the binary search used this list must be sorted by mnMinCode
- static Unicode2LangType aLangFromCodeChart[]= {
- {0x0000, 0x007F, LANGUAGE_ENGLISH}, // Basic Latin
- {0x0080, 0x024F, LANGUAGE_ENGLISH}, // Latin Extended-A and Latin Extended-B
- {0x0250, 0x02AF, LANGUAGE_SYSTEM}, // IPA Extensions
- {0x0370, 0x03FF, LANGUAGE_GREEK}, // Greek
- {0x0590, 0x05FF, LANGUAGE_HEBREW}, // Hebrew
- {0x0600, 0x06FF, LANGUAGE_ARABIC_PRIMARY_ONLY}, // Arabic
- {0x0900, 0x097F, LANGUAGE_HINDI}, // Devanagari
- {0x0980, 0x09FF, LANGUAGE_BENGALI}, // Bengali
- {0x0A80, 0x0AFF, LANGUAGE_GUJARATI}, // Gujarati
- {0x0B00, 0x0B7F, LANGUAGE_ORIYA}, // Oriya
- {0x0B80, 0x0BFF, LANGUAGE_TAMIL}, // Tamil
- {0x0C00, 0x0C7F, LANGUAGE_TELUGU}, // Telugu
- {0x0C80, 0x0CFF, LANGUAGE_KANNADA}, // Kannada
- {0x0D00, 0x0D7F, LANGUAGE_MALAYALAM}, // Malayalam
- {0x0D80, 0x0D7F, LANGUAGE_SINHALESE_SRI_LANKA}, // Sinhala
- {0x0E00, 0x0E7F, LANGUAGE_THAI}, // Thai
- {0x0E80, 0x0EFF, LANGUAGE_LAO}, // Lao
- {0x0F00, 0x0FFF, LANGUAGE_TIBETAN}, // Tibetan
- {0x1000, 0x109F, LANGUAGE_BURMESE}, // Burmese
- {0x10A0, 0x10FF, LANGUAGE_GEORGIAN}, // Georgian
- {0x1100, 0x11FF, LANGUAGE_KOREAN}, // Hangul Jamo, Korean-specific
- // {0x1200, 0x139F, LANGUAGE_AMHARIC_ETHIOPIA}, // Ethiopic
- // {0x1200, 0x139F, LANGUAGE_TIGRIGNA_ETHIOPIA}, // Ethiopic
- {0x13A0, 0x13FF, LANGUAGE_CHEROKEE_UNITED_STATES}, // Cherokee
- // {0x1400, 0x167F, LANGUAGE_CANADIAN_ABORIGINAL}, // Canadian Aboriginial Syllabics
- // {0x1680, 0x169F, LANGUAGE_OGHAM}, // Ogham
- // {0x16A0, 0x16F0, LANGUAGE_RUNIC}, // Runic
- // {0x1700, 0x171F, LANGUAGE_TAGALOG}, // Tagalog
- // {0x1720, 0x173F, LANGUAGE_HANUNOO}, // Hanunoo
- // {0x1740, 0x175F, LANGUAGE_BUHID}, // Buhid
- // {0x1760, 0x177F, LANGUAGE_TAGBANWA}, // Tagbanwa
- {0x1780, 0x17FF, LANGUAGE_KHMER}, // Khmer
- {0x18A0, 0x18AF, LANGUAGE_MONGOLIAN}, // Mongolian
- // {0x1900, 0x194F, LANGUAGE_LIMBU}, // Limbu
- // {0x1950, 0x197F, LANGUAGE_TAILE}, // Tai Le
- // {0x1980, 0x19DF, LANGUAGE_TAILUE}, // Tai Lue
- {0x19E0, 0x19FF, LANGUAGE_KHMER}, // Khmer Symbols
- // {0x1A00, 0x1A1F, LANGUAGE_BUGINESE}, // Buginese/Lontara
- // {0x1B00, 0x1B7F, LANGUAGE_BALINESE}, // Balinese
- // {0x1D00, 0x1DFF, LANGUAGE_NONE}, // Phonetic Symbols
- {0x1E00, 0x1EFF, LANGUAGE_ENGLISH}, // Latin Extended Additional
- {0x1F00, 0x1FFF, LANGUAGE_GREEK}, // Greek Extended
- {0x2C60, 0x2C7F, LANGUAGE_ENGLISH}, // Latin Extended-C
- {0x2E80, 0x2FFf, LANGUAGE_CHINESE_SIMPLIFIED}, // CJK Radicals Supplement + Kangxi Radical + Ideographic Description Characters
- {0x3000, 0x303F, LANGUAGE_DEFAULT_CJK}, // CJK Symbols and punctuation
- {0x3040, 0x30FF, LANGUAGE_JAPANESE}, // Japanese Hiragana + Katakana
- {0x3100, 0x312F, LANGUAGE_CHINESE_TRADITIONAL}, // Bopomofo
- {0x3130, 0x318F, LANGUAGE_KOREAN}, // Hangul Compatibility Jamo, Kocrean-specific
- {0x3190, 0x319F, LANGUAGE_JAPANESE}, // Kanbun
- {0x31A0, 0x31BF, LANGUAGE_CHINESE_TRADITIONAL}, // Bopomofo Extended
- {0x31C0, 0x31EF, LANGUAGE_DEFAULT_CJK}, // CJK Ideographs
- {0x31F0, 0x31FF, LANGUAGE_JAPANESE}, // Japanese Katakana Phonetic Extensions
- {0x3200, 0x321F, LANGUAGE_KOREAN}, // Parenthesized Hangul
- {0x3220, 0x325F, LANGUAGE_DEFAULT_CJK}, // Parenthesized Ideographs
- {0x3260, 0x327F, LANGUAGE_KOREAN}, // Circled Hangul
- {0x3280, 0x32CF, LANGUAGE_DEFAULT_CJK}, // Circled Ideographs
- {0x32d0, 0x32FF, LANGUAGE_JAPANESE}, // Japanese Circled Katakana
- {0x3400, 0x4DBF, LANGUAGE_DEFAULT_CJK}, // CJK Unified Ideographs Extension A
- {0x4E00, 0x9FCF, LANGUAGE_DEFAULT_CJK}, // Unified CJK Ideographs
- {0xA720, 0xA7FF, LANGUAGE_ENGLISH}, // Latin Extended-D
- {0xAC00, 0xD7AF, LANGUAGE_KOREAN}, // Hangul Syllables, Korean-specific
- {0xF900, 0xFAFF, LANGUAGE_DEFAULT_CJK}, // CJK Compatibility Ideographs
- {0xFB00, 0xFB4F, LANGUAGE_HEBREW}, // Hebrew Presentation Forms
- {0xFB50, 0xFDFF, LANGUAGE_ARABIC_PRIMARY_ONLY}, // Arabic Presentation Forms-A
- {0xFE70, 0xFEFE, LANGUAGE_ARABIC_PRIMARY_ONLY}, // Arabic Presentation Forms-B
- {0xFF65, 0xFF9F, LANGUAGE_JAPANESE}, // Japanese Halfwidth Katakana variant
- {0xFFA0, 0xFFDC, LANGUAGE_KOREAN}, // Kocrean halfwidth hangual variant
- {0x10140, 0x1018F, LANGUAGE_GREEK}, // Ancient Greak numbers
- {0x1D200, 0x1D24F, LANGUAGE_GREEK}, // Ancient Greek Musical
- {0x20000, 0x2A6DF, LANGUAGE_DEFAULT_CJK}, // CJK Unified Ideographs Extension B
- {0x2F800, 0x2FA1F, LANGUAGE_DEFAULT_CJK} // CJK Compatibility Ideographs Supplement
- };
- // get language matching to the missing char
- LanguageType MapCharToLanguage( sal_UCS4 uChar )
- {
- // entries marked with default-CJK get replaced with the prefered CJK language
- static bool bFirst = true;
- if( bFirst )
- {
- bFirst = false;
- // use method suggested in #i97086# to determnine the systems default language
- // TODO: move into i18npool or sal/osl/w32/nlsupport.c
- LanguageType nDefaultLang = 0;
- HKEY hKey = NULL;
- LONG lResult = ::RegOpenKeyExA( HKEY_LOCAL_MACHINE,
- "SYSTEM\\CurrentControlSet\\Control\\Nls\\Language",
- 0, KEY_QUERY_VALUE, &hKey );
- char aKeyValBuf[16];
- DWORD nKeyValSize = sizeof(aKeyValBuf);
- if( ERROR_SUCCESS == lResult )
- lResult = RegQueryValueExA( hKey, "Default", NULL, NULL, (LPBYTE)aKeyValBuf, &nKeyValSize );
- aKeyValBuf[ sizeof(aKeyValBuf)-1 ] = '\0';
- if( ERROR_SUCCESS == lResult )
- nDefaultLang = (LanguageType)rtl_str_toInt32( aKeyValBuf, 16 );
- // TODO: use the default-CJK language selected in
- // Tools->Options->LangSettings->Languages when it becomes available here
- if( !nDefaultLang )
- nDefaultLang = Application::GetSettings().GetUILanguage();
- LanguageType nDefaultCJK = LANGUAGE_CHINESE;
- switch( nDefaultLang )
- {
- case LANGUAGE_JAPANESE:
- case LANGUAGE_KOREAN:
- case LANGUAGE_KOREAN_JOHAB:
- case LANGUAGE_CHINESE_SIMPLIFIED:
- case LANGUAGE_CHINESE_TRADITIONAL:
- case LANGUAGE_CHINESE_SINGAPORE:
- case LANGUAGE_CHINESE_HONGKONG:
- case LANGUAGE_CHINESE_MACAU:
- nDefaultCJK = nDefaultLang;
- break;
- default:
- nDefaultCJK = LANGUAGE_CHINESE;
- break;
- }
- // change the marked entries to prefered language
- static const int nCount = (sizeof(aLangFromCodeChart) / sizeof(*aLangFromCodeChart));
- for( int i = 0; i < nCount; ++i )
- {
- if( aLangFromCodeChart[ i].mnLangID == LANGUAGE_DEFAULT_CJK )
- aLangFromCodeChart[ i].mnLangID = nDefaultCJK;
- }
- }
- // binary search
- int nLow = 0;
- int nHigh = (sizeof(aLangFromCodeChart) / sizeof(*aLangFromCodeChart)) - 1;
- while( nLow <= nHigh )
- {
- int nMiddle = (nHigh + nLow) / 2;
- if( uChar < aLangFromCodeChart[ nMiddle].mnMinCode )
- nHigh = nMiddle - 1;
- else if( uChar > aLangFromCodeChart[ nMiddle].mnMaxCode )
- nLow = nMiddle + 1;
- else
- return aLangFromCodeChart[ nMiddle].mnLangID;
- }
- return LANGUAGE_DONTKNOW;
- }
- class WinGlyphFallbackSubstititution
- : public ImplGlyphFallbackFontSubstitution
- {
- public:
- explicit WinGlyphFallbackSubstititution( HDC );
- bool FindFontSubstitute( ImplFontSelectData&, rtl::OUString& rMissingChars ) const;
- private:
- HDC mhDC;
- bool HasMissingChars( const ImplFontData*, const rtl::OUString& rMissingChars ) const;
- };
- inline WinGlyphFallbackSubstititution::WinGlyphFallbackSubstititution( HDC hDC )
- : mhDC( hDC )
- {}
- void ImplGetLogFontFromFontSelect( HDC, const ImplFontSelectData*,
- LOGFONTW&, bool /*bTestVerticalAvail*/ );
- // does a font face hold the given missing characters?
- bool WinGlyphFallbackSubstititution::HasMissingChars( const ImplFontData* pFace, const rtl::OUString& rMissingChars ) const
- {
- const ImplWinFontData* pWinFont = static_cast<const ImplWinFontData*>(pFace);
- const ImplFontCharMap* pCharMap = pWinFont->GetImplFontCharMap();
- if( !pCharMap )
- {
- // construct a Size structure as the parameter of constructor of class ImplFontSelectData
- const Size aSize( pFace->GetWidth(), pFace->GetHeight() );
- // create a ImplFontSelectData object for getting s LOGFONT
- const ImplFontSelectData aFSD( *pFace, aSize, (float)aSize.Height(), 0, false );
- // construct log font
- LOGFONTW aLogFont;
- ImplGetLogFontFromFontSelect( mhDC, &aFSD, aLogFont, true );
- // create HFONT from log font
- HFONT hNewFont = ::CreateFontIndirectW( &aLogFont );
- // select the new font into device
- HFONT hOldFont = ::SelectFont( mhDC, hNewFont );
- // read CMAP table to update their pCharMap
- pWinFont->UpdateFromHDC( mhDC );;
- // cleanup temporary font
- ::SelectFont( mhDC, hOldFont );
- ::DeleteFont( hNewFont );
- // get the new charmap
- pCharMap = pWinFont->GetImplFontCharMap();
- }
- // avoid fonts with unknown CMAP subtables for glyph fallback
- if( !pCharMap || pCharMap->IsDefaultMap() )
- return false;
- int nMatchCount = 0;
- // static const int nMaxMatchCount = 1; // TODO: check more missing characters?
- const sal_Int32 nStrLen = rMissingChars.getLength();
- for( sal_Int32 nStrIdx = 0; nStrIdx < nStrLen; ++nStrIdx )
- {
- const sal_UCS4 uChar = rMissingChars.iterateCodePoints( &nStrIdx );
- nMatchCount += pCharMap->HasChar( uChar );
- break; // for now
- }
- const bool bHasMatches = (nMatchCount > 0);
- return bHasMatches;
- }
- // find a fallback font for missing characters
- // TODO: should stylistic matches be searched and prefered?
- bool WinGlyphFallbackSubstititution::FindFontSubstitute( ImplFontSelectData& rFontSelData, rtl::OUString& rMissingChars ) const
- {
- // guess a locale matching to the missing chars
- com::sun::star::lang::Locale aLocale;
- sal_Int32 nStrIdx = 0;
- const sal_Int32 nStrLen = rMissingChars.getLength();
- while( nStrIdx < nStrLen )
- {
- const sal_UCS4 uChar = rMissingChars.iterateCodePoints( &nStrIdx );
- const LanguageType eLang = MapCharToLanguage( uChar );
- if( eLang == LANGUAGE_DONTKNOW )
- continue;
- MsLangId::convertLanguageToLocale( eLang, aLocale );
- break;
- }
- // fall back to default UI locale if the missing characters are inconclusive
- if( nStrIdx >= nStrLen )
- aLocale = Application::GetSettings().GetUILocale();
- // first level fallback:
- // try use the locale specific default fonts defined in VCL.xcu
- const ImplDevFontList* pDevFontList = ImplGetSVData()->maGDIData.mpScreenFontList;
- /*const*/ ImplDevFontListData* pDevFont = pDevFontList->ImplFindByLocale( aLocale );
- if( pDevFont )
- {
- const ImplFontData* pFace = pDevFont->FindBestFontFace( rFontSelData );
- if( HasMissingChars( pFace, rMissingChars ) )
- {
- rFontSelData.maSearchName = pDevFont->GetSearchName();
- return true;
- }
- }
- // are the missing characters symbols?
- pDevFont = pDevFontList->ImplFindByAttributes( IMPL_FONT_ATTR_SYMBOL,
- rFontSelData.meWeight, rFontSelData.meWidthType,
- rFontSelData.meFamily, rFontSelData.meItalic, rFontSelData.maSearchName );
- if( pDevFont )
- {
- const ImplFontData* pFace = pDevFont->FindBestFontFace( rFontSelData );
- if( HasMissingChars( pFace, rMissingChars ) )
- {
- rFontSelData.maSearchName = pDevFont->GetSearchName();
- return true;
- }
- }
- // last level fallback, check each font type face one by one
- const ImplGetDevFontList* pTestFontList = pDevFontList->GetDevFontList();
- // limit the count of fonts to be checked to prevent hangs
- static const int MAX_GFBFONT_COUNT = 600;
- int nTestFontCount = pTestFontList->Count();
- if( nTestFontCount > MAX_GFBFONT_COUNT )
- nTestFontCount = MAX_GFBFONT_COUNT;
-
- for( int i = 0; i < nTestFontCount; ++i )
- {
- const ImplFontData* pFace = pTestFontList->Get( i );
- if( !HasMissingChars( pFace, rMissingChars ) )
- continue;
- rFontSelData.maSearchName = pFace->maName;
- return true;
- }
- return false;
- }
- // =======================================================================
- struct ImplEnumInfo
- {
- HDC mhDC;
- ImplDevFontList* mpList;
- String* mpName;
- LOGFONTA* mpLogFontA;
- LOGFONTW* mpLogFontW;
- UINT mnPreferedCharSet;
- bool mbCourier;
- bool mbImplSalCourierScalable;
- bool mbImplSalCourierNew;
- bool mbPrinter;
- int mnFontCount;
- };
- // =======================================================================
- static CharSet ImplCharSetToSal( BYTE nCharSet )
- {
- rtl_TextEncoding eTextEncoding;
- if ( nCharSet == OEM_CHARSET )
- {
- UINT nCP = (USHORT)GetOEMCP();
- switch ( nCP )
- {
- // It is unclear why these two (undefined?) code page numbers are
- // handled specially here:
- case 1004: eTextEncoding = RTL_TEXTENCODING_MS_1252; break;
- case 65400: eTextEncoding = RTL_TEXTENCODING_SYMBOL; break;
- default:
- eTextEncoding = rtl_getTextEncodingFromWindowsCodePage(nCP);
- break;
- };
- }
- else
- {
- if( nCharSet )
- eTextEncoding = rtl_getTextEncodingFromWindowsCharset( nCharSet );
- else
- eTextEncoding = RTL_TEXTENCODING_UNICODE;
- }
- return eTextEncoding;
- }
- // -----------------------------------------------------------------------
- static FontFamily ImplFamilyToSal( BYTE nFamily )
- {
- switch ( nFamily & 0xF0 )
- {
- case FF_DECORATIVE:
- return FAMILY_DECORATIVE;
- case FF_MODERN:
- return FAMILY_MODERN;
- case FF_ROMAN:
- return FAMILY_ROMAN;
- case FF_SCRIPT:
- return FAMILY_SCRIPT;
- case FF_SWISS:
- return FAMILY_SWISS;
- default:
- break;
- }
- return FAMILY_DONTKNOW;
- }
- // -----------------------------------------------------------------------
- static BYTE ImplFamilyToWin( FontFamily eFamily )
- {
- switch ( eFamily )
- {
- case FAMILY_DECORATIVE:
- return FF_DECORATIVE;
- case FAMILY_MODERN:
- return FF_MODERN;
- case FAMILY_ROMAN:
- return FF_ROMAN;
- case FAMILY_SCRIPT:
- return FF_SCRIPT;
- case FAMILY_SWISS:
- return FF_SWISS;
- case FAMILY_SYSTEM:
- return FF_SWISS;
- default:
- break;
- }
- return FF_DONTCARE;
- }
- // -----------------------------------------------------------------------
- static FontWeight ImplWeightToSal( int nWeight )
- {
- if ( nWeight <= FW_THIN )
- return WEIGHT_THIN;
- else if ( nWeight <= FW_ULTRALIGHT )
- return WEIGHT_ULTRALIGHT;
- else if ( nWeight <= FW_LIGHT )
- return WEIGHT_LIGHT;
- else if ( nWeight < FW_MEDIUM )
- return WEIGHT_NORMAL;
- else if ( nWeight == FW_MEDIUM )
- return WEIGHT_MEDIUM;
- else if ( nWeight <= FW_SEMIBOLD )
- return WEIGHT_SEMIBOLD;
- else if ( nWeight <= FW_BOLD )
- return WEIGHT_BOLD;
- else if ( nWeight <= FW_ULTRABOLD )
- return WEIGHT_ULTRABOLD;
- else
- return WEIGHT_BLACK;
- }
- // -----------------------------------------------------------------------
- static int ImplWeightToWin( FontWeight eWeight )
- {
- switch ( eWeight )
- {
- case WEIGHT_THIN:
- return FW_THIN;
- case WEIGHT_ULTRALIGHT:
- return FW_ULTRALIGHT;
- case WEIGHT_LIGHT:
- return FW_LIGHT;
- case WEIGHT_SEMILIGHT:
- case WEIGHT_NORMAL:
- return FW_NORMAL;
- case WEIGHT_MEDIUM:
- return FW_MEDIUM;
- case WEIGHT_SEMIBOLD:
- return FW_SEMIBOLD;
- case WEIGHT_BOLD:
- return FW_BOLD;
- case WEIGHT_ULTRABOLD:
- return FW_ULTRABOLD;
- case WEIGHT_BLACK:
- return FW_BLACK;
- default:
- break;
- }
- return 0;
- }
- // -----------------------------------------------------------------------
- inline FontPitch ImplLogPitchToSal( BYTE nPitch )
- {
- if ( nPitch & FIXED_PITCH )
- return PITCH_FIXED;
- else
- return PITCH_VARIABLE;
- }
- // -----------------------------------------------------------------------
- inline FontPitch ImplMetricPitchToSal( BYTE nPitch )
- {
- // Sausaecke bei MS !! siehe NT Hilfe
- if ( !(nPitch & TMPF_FIXED_PITCH) )
- return PITCH_FIXED;
- else
- return PITCH_VARIABLE;
- }
- // -----------------------------------------------------------------------
- inline BYTE ImplPitchToWin( FontPitch ePitch )
- {
- if ( ePitch == PITCH_FIXED )
- return FIXED_PITCH;
- else if ( ePitch == PITCH_VARIABLE )
- return VARIABLE_PITCH;
- else
- return DEFAULT_PITCH;
- }
- // -----------------------------------------------------------------------
- static ImplDevFontAttributes WinFont2DevFontAttributes( const ENUMLOGFONTEXA& rEnumFont,
- const NEWTEXTMETRICA& rMetric, DWORD nFontType )
- {
- ImplDevFontAttributes aDFA;
- const LOGFONTA rLogFont = rEnumFont.elfLogFont;
- // get font face attributes
- aDFA.meFamily = ImplFamilyToSal( rLogFont.lfPitchAndFamily );
- aDFA.meWidthType = WIDTH_DONTKNOW;
- aDFA.meWeight = ImplWeightToSal( rLogFont.lfWeight );
- aDFA.meItalic = (rLogFont.lfItalic) ? ITALIC_NORMAL : ITALIC_NONE;
- aDFA.mePitch = ImplLogPitchToSal( rLogFont.lfPitchAndFamily );
- aDFA.mbSymbolFlag = (rLogFont.lfCharSet == SYMBOL_CHARSET);
- // get the font face name
- aDFA.maName = ImplSalGetUniString( rLogFont.lfFaceName );
- // use the face's style name only if it looks reasonable
- const char* pStyleName = (const char*)rEnumFont.elfStyle;
- const char* pEnd = pStyleName + sizeof( rEnumFont.elfStyle );
- const char* p = pStyleName;
- for(; *p && (p < pEnd); ++p )
- if( (0x00 < *p) && (*p < 0x20) )
- break;
- if( p < pEnd )
- aDFA.maStyleName = ImplSalGetUniString( pStyleName );
- // get device specific font attributes
- aDFA.mbOrientation = (nFontType & RASTER_FONTTYPE) == 0;
- aDFA.mbDevice = (rMetric.tmPitchAndFamily & TMPF_DEVICE) != 0;
- aDFA.mbEmbeddable = false;
- aDFA.mbSubsettable = false;
- if( 0 != (rMetric.ntmFlags & (NTM_TT_OPENTYPE | NTM_PS_OPENTYPE))
- || 0 != (rMetric.tmPitchAndFamily & TMPF_TRUETYPE))
- aDFA.mbSubsettable = true;
- else if( 0 != (rMetric.ntmFlags & NTM_TYPE1) ) // TODO: implement subsetting for type1 too
- aDFA.mbEmbeddable = true;
- // heuristics for font quality
- // - standard-type1 > opentypeTT > truetype > non-standard-type1 > raster
- // - subsetting > embedding > none
- aDFA.mnQuality = 0;
- if( rMetric.tmPitchAndFamily & TMPF_TRUETYPE )
- aDFA.mnQuality += 50;
- if( 0 != (rMetric.ntmFlags & (NTM_TT_OPENTYPE | NTM_PS_OPENTYPE)) )
- aDFA.mnQuality += 10;
- if( aDFA.mbSubsettable )
- aDFA.mnQuality += 200;
- else if( aDFA.mbEmbeddable )
- aDFA.mnQuality += 100;
- // #i38665# prefer Type1 versions of the standard postscript fonts
- if( aDFA.mbEmbeddable )
- {
- if( aDFA.maName.EqualsAscii( "AvantGarde" )
- || aDFA.maName.EqualsAscii( "Bookman" )
- || aDFA.maName.EqualsAscii( "Courier" )
- || aDFA.maName.EqualsAscii( "Helvetica" )
- || aDFA.maName.EqualsAscii( "NewCenturySchlbk" )
- || aDFA.maName.EqualsAscii( "Palatino" )
- || aDFA.maName.EqualsAscii( "Symbol" )
- || aDFA.maName.EqualsAscii( "Times" )
- || aDFA.maName.EqualsAscii( "ZapfChancery" )
- || aDFA.maName.EqualsAscii( "ZapfDingbats" ) )
- aDFA.mnQuality += 500;
- }
- // TODO: add alias names
- return aDFA;
- }
- // -----------------------------------------------------------------------
- static ImplDevFontAttributes WinFont2DevFontAttributes( const ENUMLOGFONTEXW& rEnumFont,
- const NEWTEXTMETRICW& rMetric, DWORD nFontType )
- {
- ImplDevFontAttributes aDFA;
- const LOGFONTW rLogFont = rEnumFont.elfLogFont;
- // get font face attributes
- aDFA.meFamily = ImplFamilyToSal( rLogFont.lfPitchAndFamily );
- aDFA.meWidthType = WIDTH_DONTKNOW;
- aDFA.meWeight = ImplWeightToSal( rLogFont.lfWeight );
- aDFA.meItalic = (rLogFont.lfItalic) ? ITALIC_NORMAL : ITALIC_NONE;
- aDFA.mePitch = ImplLogPitchToSal( rLogFont.lfPitchAndFamily );
- aDFA.mbSymbolFlag = (rLogFont.lfCharSet == SYMBOL_CHARSET);
- // get the font face name
- aDFA.maName = reinterpret_cast<const sal_Unicode*>(rLogFont.lfFaceName);
- // use the face's style name only if it looks reasonable
- const wchar_t* pStyleName = rEnumFont.elfStyle;
- const wchar_t* pEnd = pStyleName + sizeof(rEnumFont.elfStyle)/sizeof(*rEnumFont.elfStyle);
- const wchar_t* p = pStyleName;
- for(; *p && (p < pEnd); ++p )
- if( *p < 0x0020 )
- break;
- if( p < pEnd )
- aDFA.maStyleName = reinterpret_cast<const sal_Unicode*>(pStyleName);
- // get device specific font attributes
- aDFA.mbOrientation = (nFontType & RASTER_FONTTYPE) == 0;
- aDFA.mbDevice = (rMetric.tmPitchAndFamily & TMPF_DEVICE) != 0;
- aDFA.mbEmbeddable = false;
- aDFA.mbSubsettable = false;
- if( 0 != (rMetric.ntmFlags & (NTM_TT_OPENTYPE | NTM_PS_OPENTYPE))
- || 0 != (rMetric.tmPitchAndFamily & TMPF_TRUETYPE))
- aDFA.mbSubsettable = true;
- else if( 0 != (rMetric.ntmFlags & NTM_TYPE1) ) // TODO: implement subsetting for type1 too
- aDFA.mbEmbeddable = true;
- // heuristics for font quality
- // - standard-type1 > opentypeTT > truetype > non-standard-type1 > raster
- // - subsetting > embedding > none
- aDFA.mnQuality = 0;
- if( rMetric.tmPitchAndFamily & TMPF_TRUETYPE )
- aDFA.mnQuality += 50;
- if( 0 != (rMetric.ntmFlags & (NTM_TT_OPENTYPE | NTM_PS_OPENTYPE)) )
- aDFA.mnQuality += 10;
- if( aDFA.mbSubsettable )
- aDFA.mnQuality += 200;
- else if( aDFA.mbEmbeddable )
- aDFA.mnQuality += 100;
- // #i38665# prefer Type1 versions of the standard postscript fonts
- if( aDFA.mbEmbeddable )
- {
- if( aDFA.maName.EqualsAscii( "AvantGarde" )
- || aDFA.maName.EqualsAscii( "Bookman" )
- || aDFA.maName.EqualsAscii( "Courier" )
- || aDFA.maName.EqualsAscii( "Helvetica" )
- || aDFA.maName.EqualsAscii( "NewCenturySchlbk" )
- || aDFA.maName.EqualsAscii( "Palatino" )
- || aDFA.maName.EqualsAscii( "Symbol" )
- || aDFA.maName.EqualsAscii( "Times" )
- || aDFA.maName.EqualsAscii( "ZapfChancery" )
- || aDFA.maName.EqualsAscii( "ZapfDingbats" ) )
- aDFA.mnQuality += 500;
- }
- // TODO: add alias names
- return aDFA;
- }
- // -----------------------------------------------------------------------
- static ImplWinFontData* ImplLogMetricToDevFontDataA( const ENUMLOGFONTEXA* pLogFont,
- const NEWTEXTMETRICA* pMetric,
- DWORD nFontType )
- {
- int nHeight = 0;
- if ( nFontType & RASTER_FONTTYPE )
- nHeight = pMetric->tmHeight - pMetric->tmInternalLeading;
- ImplWinFontData* pData = new ImplWinFontData(
- WinFont2DevFontAttributes(*pLogFont, *pMetric, nFontType),
- nHeight,
- pLogFont->elfLogFont.lfCharSet,
- pMetric->tmPitchAndFamily );
- return pData;
- }
- // -----------------------------------------------------------------------
- static ImplWinFontData* ImplLogMetricToDevFontDataW( const ENUMLOGFONTEXW* pLogFont,
- const NEWTEXTMETRICW* pMetric,
- DWORD nFontType )
- {
- int nHeight = 0;
- if ( nFontType & RASTER_FONTTYPE )
- nHeight = pMetric->tmHeight - pMetric->tmInternalLeading;
- ImplWinFontData* pData = new ImplWinFontData(
- WinFont2DevFontAttributes(*pLogFont, *pMetric, nFontType),
- nHeight,
- pLogFont->elfLogFont.lfCharSet,
- pMetric->tmPitchAndFamily );
- return pData;
- }
- // -----------------------------------------------------------------------
- void ImplSalLogFontToFontA( HDC hDC, const LOGFONTA& rLogFont, Font& rFont )
- {
- String aFontName( ImplSalGetUniString( rLogFont.lfFaceName ) );
- if ( aFontName.Len() )
- {
- rFont.SetName( aFontName );
- rFont.SetCharSet( ImplCharSetToSal( rLogFont.lfCharSet ) );
- rFont.SetFamily( ImplFamilyToSal( rLogFont.lfPitchAndFamily ) );
- rFont.SetPitch( ImplLogPitchToSal( rLogFont.lfPitchAndFamily ) );
- rFont.SetWeight( ImplWeightToSal( rLogFont.lfWeight ) );
- long nFontHeight = rLogFont.lfHeight;
- if ( nFontHeight < 0 )
- nFontHeight = -nFontHeight;
- long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY );
- if( !nDPIY )
- nDPIY = 600;
- nFontHeight *= 72;
- nFontHeight += nDPIY/2;
- nFontHeight /= nDPIY;
- rFont.SetSize( Size( 0, nFontHeight ) );
- rFont.SetOrientation( (short)rLogFont.lfEscapement );
- if ( rLogFont.lfItalic )
- rFont.SetItalic( ITALIC_NORMAL );
- else
- rFont.SetItalic( ITALIC_NONE );
- if ( rLogFont.lfUnderline )
- rFont.SetUnderline( UNDERLINE_SINGLE );
- else
- rFont.SetUnderline( UNDERLINE_NONE );
- if ( rLogFont.lfStrikeOut )
- rFont.SetStrikeout( STRIKEOUT_SINGLE );
- else
- rFont.SetStrikeout( STRIKEOUT_NONE );
- }
- }
- // -----------------------------------------------------------------------
- void ImplSalLogFontToFontW( HDC hDC, const LOGFONTW& rLogFont, Font& rFont )
- {
- XubString aFontName( reinterpret_cast<const xub_Unicode*>(rLogFont.lfFaceName) );
- if ( aFontName.Len() )
- {
- rFont.SetName( aFontName );
- rFont.SetCharSet( ImplCharSetToSal( rLogFont.lfCharSet ) );
- rFont.SetFamily( ImplFamilyToSal( rLogFont.lfPitchAndFamily ) );
- rFont.SetPitch( ImplLogPitchToSal( rLogFont.lfPitchAndFamily ) );
- rFont.SetWeight( ImplWeightToSal( rLogFont.lfWeight ) );
- long nFontHeight = rLogFont.lfHeight;
- if ( nFontHeight < 0 )
- nFontHeight = -nFontHeight;
- long nDPIY = GetDeviceCaps( hDC, LOGPIXELSY );
- if( !nDPIY )
- nDPIY = 600;
- nFontHeight *= 72;
- nFontHeight += nDPIY/2;
- nFontHeight /= nDPIY;
- rFont.SetSize( Size( 0, nFontHeight ) );
- rFont.SetOrientation( (short)rLogFont.lfEscapement );
- if ( rLogFont.lfItalic )
- rFont.SetItalic( ITALIC_NORMAL );
- else
- rFont.SetItalic( ITALIC_NONE );
- if ( rLogFont.lfUnderline )
- rFont.SetUnderline( UNDERLINE_SINGLE );
- else
- rFont.SetUnderline( UNDERLINE_NONE );
- if ( rLogFont.lfStrikeOut )
- rFont.SetStrikeout( STRIKEOUT_SINGLE );
- else
- rFont.SetStrikeout( STRIKEOUT_NONE );
- }
- }
- // =======================================================================
- ImplWinFontData::ImplWinFontData( const ImplDevFontAttributes& rDFS,
- int nHeight, WIN_BYTE eWinCharSet, WIN_BYTE nPitchAndFamily )
- : ImplFontData( rDFS, 0 ),
- meWinCharSet( eWinCharSet ),
- mnPitchAndFamily( nPitchAndFamily ),
- mpFontCharSets( NULL ),
- mpUnicodeMap( NULL ),
- mbGsubRead( false ),
- mbDisableGlyphApi( false ),
- mbHasKoreanRange( false ),
- mbHasCJKSupport( false ),
- #ifdef ENABLE_GRAPHITE
- mbHasGraphiteSupport( false ),
- #endif
- mbHasArabicSupport ( false ),
- mbAliasSymbolsLow( false ),
- mbAliasSymbolsHigh( false ),
- mnId( 0 ),
- mpEncodingVector( NULL )
- {
- SetBitmapSize( 0, nHeight );
- if( eWinCharSet == SYMBOL_CHARSET )
- {
- if( (nPitchAndFamily & TMPF_TRUETYPE) != 0 )
- {
- // truetype fonts need their symbols as U+F0xx
- mbAliasSymbolsHigh = true;
- }
- else if( (nPitchAndFamily & (TMPF_VECTOR|TMPF_DEVICE))
- == (TMPF_VECTOR|TMPF_DEVICE) )
- {
- // scalable device fonts (e.g. builtin printer fonts)
- // need their symbols as U+00xx
- mbAliasSymbolsLow = true;
- }
- else if( (nPitchAndFamily & (TMPF_VECTOR|TMPF_TRUETYPE)) == 0 )
- {
- // bitmap fonts need their symbols as U+F0xx
- mbAliasSymbolsHigh = true;
- }
- }
- }
- // -----------------------------------------------------------------------
- ImplWinFontData::~ImplWinFontData()
- {
- delete[] mpFontCharSets;
- if( mpUnicodeMap )
- mpUnicodeMap->DeReference();
- delete mpEncodingVector;
- }
- // -----------------------------------------------------------------------
- sal_IntPtr ImplWinFontData::GetFontId() const
- {
- return mnId;
- }
- // -----------------------------------------------------------------------
- void ImplWinFontData::UpdateFromHDC( HDC hDC ) const
- {
- // short circuit if already initialized
- if( mpUnicodeMap != NULL )
- return;
- ReadCmapTable( hDC );
- ReadOs2Table( hDC );
- #ifdef ENABLE_GRAPHITE
- static const char* pDisableGraphiteText = getenv( "SAL_DISABLE_GRAPHITE" );
- if( !pDisableGraphiteText || (pDisableGraphiteText[0] == '0') )
- {
- mbHasGraphiteSupport = gr::WinFont::FontHasGraphiteTables(hDC);
- }
- #endif
- // even if the font works some fonts have problems with the glyph API
- // => the heuristic below tries to figure out which fonts have the problem
- TEXTMETRICA aTextMetric;
- if( ::GetTextMetricsA( hDC, &aTextMetric ) )
- if( !(aTextMetric.tmPitchAndFamily & TMPF_TRUETYPE)
- || (aTextMetric.tmPitchAndFamily & TMPF_DEVICE) )
- mbDisableGlyphApi = true;
- #if 0
- // #110548# more important than #107885# => TODO: better solution
- DWORD nFLI = GetFontLanguageInfo( hDC );
- if( 0 == (nFLI & GCP_GLYPHSHAPE) )
- mbDisableGlyphApi = true;
- #endif
- }
- // -----------------------------------------------------------------------
- bool ImplWinFontData::HasGSUBstitutions( HDC hDC ) const
- {
- if( !mbGsubRead )
- ReadGsubTable( hDC );
- return !maGsubTable.empty();
- }
- // -----------------------------------------------------------------------
- bool ImplWinFontData::IsGSUBstituted( sal_UCS4 cChar ) const
- {
- return( maGsubTable.find( cChar ) != maGsubTable.end() );
- }
- // -----------------------------------------------------------------------
- ImplFontCharMap* ImplWinFontData::GetImplFontCharMap() const
- {
- if( !mpUnicodeMap )
- return NULL;
- mpUnicodeMap->AddReference();
- return mpUnicodeMap;
- }
- // -----------------------------------------------------------------------
- static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
- static unsigned GetUShort( const unsigned char* p ){ return((p[0]<<8)+p[1]);}
- //static signed GetSShort( const unsigned char* p ){ return((short)((p[0]<<8)+p[1]));}
- static inline DWORD CalcTag( const char p[4]) { return (p[0]+(p[1]<<8)+(p[2]<<16)+(p[3]<<24)); }
- void ImplWinFontData::ReadOs2Table( HDC hDC ) const
- {
- const DWORD Os2Tag = CalcTag( "OS/2" );
- DWORD nLength = ::GetFontData( hDC, Os2Tag, 0, NULL, 0 );
- if( (nLength == GDI_ERROR) || !nLength )
- return;
- std::vector<unsigned char> aOS2map( nLength );
- unsigned char* pOS2map = &aOS2map[0];
- ::GetFontData( hDC, Os2Tag, 0, pOS2map, nLength );
- sal_uInt32 nVersion = GetUShort( pOS2map );
- if ( nVersion >= 0x0001 && nLength >= 58 )
- {
- // We need at least version 0x0001 (TrueType rev 1.66)
- // to have access to the needed struct members.
- sal_uInt32 ulUnicodeRange1 = GetUInt( pOS2map + 42 );
- sal_uInt32 ulUnicodeRange2 = GetUInt( pOS2map + 46 );
- #if 0
- sal_uInt32 ulUnicodeRange3 = GetUInt( pOS2map + 50 );
- sal_uInt32 ulUnicodeRange4 = GetUInt( pOS2map + 54 );
- #endif
- // Check for CJK capabilities of the current font
- mbHasCJKSupport = (ulUnicodeRange2 & 0x2DF00000);
- mbHasKoreanRange= (ulUnicodeRange1 & 0x10000000)
- | (ulUnicodeRange2 & 0x01100000);
- mbHasArabicSupport = (ulUnicodeRange1 & 0x00002000);
- }
- }
- // -----------------------------------------------------------------------
- void ImplWinFontData::ReadGsubTable( HDC hDC ) const
- {
- mbGsubRead = true;
- // check the existence of a GSUB table
- const DWORD GsubTag = CalcTag( "GSUB" );
- DWORD nRC = ::GetFontData( hDC, GsubTag, 0, NULL, 0 );
- if( (nRC == GDI_ERROR) || !nRC )
- return;
- // parse the GSUB table through sft
- // TODO: parse it directly
- // sft needs the full font file data => get it
- const RawFontData aRawFontData( hDC );
- if( !aRawFontData.get() )
- return;
- // open font file
- sal_uInt32 nFaceNum = 0;
- if( !*aRawFontData.get() ) // TTC candidate
- nFaceNum = ~0U; // indicate "TTC font extracts only"
- TrueTypeFont* pTTFont = NULL;
- ::OpenTTFontBuffer( (void*)aRawFontData.get(), aRawFontData.size(), nFaceNum, &pTTFont );
- if( !pTTFont )
- return;
- // add vertically substituted characters to list
- static const sal_Unicode aGSUBCandidates[] = {
- 0x0020, 0x0080, // ASCII
- 0x2000, 0x2600, // misc
- 0x3000, 0x3100, // CJK punctutation
- 0x3300, 0x3400, // squared words
- 0xFF00, 0xFFF0, // halfwidth|fullwidth forms
- 0 };
- for( const sal_Unicode* pPair = aGSUBCandidates; *pPair; pPair += 2 )
- for( sal_Unicode cChar = pPair[0]; cChar < pPair[1]; ++cChar )
- if( ::MapChar( pTTFont, cChar, 0 ) != ::MapChar( pTTFont, cChar, 1 ) )
- maGsubTable.insert( cChar ); // insert GSUBbed unicodes
- CloseTTFont( pTTFont );
- }
- // -----------------------------------------------------------------------
- void ImplWinFontData::ReadCmapTable( HDC hDC ) const
- {
- if( mpUnicodeMap != NULL )
- return;
- bool bIsSymbolFont = (meWinCharSet == SYMBOL_CHARSET);
- // get the CMAP table from the font which is selected into the DC
- const DWORD nCmapTag = CalcTag( "cmap" );
- const RawFontData aRawFontData( hDC, nCmapTag );
- // parse the CMAP table if available
- if( aRawFontData.get() ) {
- CmapResult aResult;
- ParseCMAP( aRawFontData.get(), aRawFontData.size(), aResult );
- mbDisableGlyphApi |= aResult.mbRecoded;
- aResult.mbSymbolic = bIsSymbolFont;
- if( aResult.mnRangeCount > 0 )
- mpUnicodeMap = new ImplFontCharMap( aResult );
- }
- if( !mpUnicodeMap )
- mpUnicodeMap = ImplFontCharMap::GetDefaultMap( bIsSymbolFont );
- }
- // =======================================================================
- void WinSalGraphics::SetTextColor( SalColor nSalColor )
- {
- COLORREF aCol = PALETTERGB( SALCOLOR_RED( nSalColor ),
- SALCOLOR_GREEN( nSalColor ),
- SALCOLOR_BLUE( nSalColor ) );
- if( !mbPrinter &&
- GetSalData()->mhDitherPal &&
- ImplIsSysColorEntry( nSalColor ) )
- {
- aCol = PALRGB_TO_RGB( aCol );
- }
- ::SetTextColor( mhDC, aCol );
- }
- // -----------------------------------------------------------------------
- int CALLBACK SalEnumQueryFontProcExW( const ENUMLOGFONTEXW*,
- const NEWTEXTMETRICEXW*,
- DWORD, LPARAM lParam )
- {
- *((bool*)(void*)lParam) = true;
- return 0;
- }
- // -----------------------------------------------------------------------
- int CALLBACK SalEnumQueryFontProcExA( const ENUMLOGFONTEXA*,
- const NEWTEXTMETRICEXA*,
- DWORD, LPARAM lParam )
- {
- *((bool*)(void*)lParam) = true;
- return 0;
- }
- // -----------------------------------------------------------------------
- bool ImplIsFontAvailable( HDC hDC, const UniString& rName )
- {
- bool bAvailable = false;
- if ( aSalShlData.mbWNT )
- {
- // Test, if Font available
- LOGFONTW aLogFont;
- memset( &aLogFont, 0, sizeof( aLogFont ) );
- aLogFont.lfCharSet = DEFAULT_CHARSET;
- UINT nNameLen = rName.Len();
- if ( nNameLen > (sizeof( aLogFont.lfFaceName )/sizeof( wchar_t ))-1 )
- nNameLen = (sizeof( aLogFont.lfFaceName )/sizeof( wchar_t ))-1;
- memcpy( aLogFont.lfFaceName, rName.GetBuffer(), nNameLen*sizeof( wchar_t ) );
- aLogFont.lfFaceName[nNameLen] = 0;
- EnumFontFamiliesExW( hDC, &aLogFont, (FONTENUMPROCW)SalEnumQueryFontProcExW,
- (LPARAM)(void*)&bAvailable, 0 );
- }
- else
- {
- ByteString aTemp = ImplSalGetWinAnsiString( rName );
- // Test, if Font available
- LOGFONTA aLogFont;
- memset( &aLogFont, 0, sizeof( aLogFont ) );
- aLogFont.lfCharSet = DEFAULT_CHARSET;
- UINT nNameLen = aTemp.Len();
- if ( nNameLen > sizeof( aLogFont.lfFaceName )-1 )
- nNameLen = sizeof( aLogFont.lfFaceName )-1;
- memcpy( aLogFont.lfFaceName, aTemp.GetBuffer(), nNameLen );
- aLogFont.lfFaceName[nNameLen] = 0;
- EnumFontFamiliesExA( hDC, &aLogFont, (FONTENUMPROCA)SalEnumQueryFontProcExA,
- (LPARAM)(void*)&bAvailable, 0 );
- }
- return bAvailable;
- }
- // -----------------------------------------------------------------------
- void ImplGetLogFontFromFontSelect( HDC hDC,
- const ImplFontSelectData* pFont,
- LOGFONTW& rLogFont,
- bool /*bTestVerticalAvail*/ )
- {
- UniString aName;
- if ( pFont->mpFontData )
- aName = pFont->mpFontData->maName;
- else
- aName = pFont->maName.GetToken( 0 );
- UINT nNameLen = aName.Len();
- if ( nNameLen > (sizeof( rLogFont.lfFaceName )/sizeof( wchar_t ))-1 )
- nNameLen = (sizeof( rLogFont.lfFaceName )/sizeof( wchar_t ))-1;
- memcpy( rLogFont.lfFaceName, aName.GetBuffer(), nNameLen*sizeof( wchar_t ) );
- rLogFont.lfFaceName[nNameLen] = 0;
- if( !pFont->mpFontData )
- {
- rLogFont.lfCharSet = pFont->IsSymbolFont() ? SYMBOL_CHARSET : DEFAULT_CHARSET;
- rLogFont.lfPitchAndFamily = ImplPitchToWin( pFont->mePitch )
- | ImplFamilyToWin( pFont->meFamily );
- }
- else
- {
- const ImplWinFontData* pWinFontData = static_cast<const ImplWinFontData*>( pFont->mpFontData );
- rLogFont.lfCharSet = pWinFontData->GetCharSet();
- rLogFont.lfPitchAndFamily = pWinFontData->GetPitchAndFamily();
- }
- rLogFont.lfWeight = ImplWeightToWin( pFont->meWeight );
- rLogFont.lfHeight = (LONG)-pFont->mnHeight;
- rLogFont.lfWidth = (LONG)pFont->mnWidth;
- rLogFont.lfUnderline = 0;
- rLogFont.lfStrikeOut = 0;
- rLogFont.lfItalic = (pFont->meItalic) != ITALIC_NONE;
- rLogFont.lfEscapement = pFont->mnOrientation;
- rLogFont.lfOrientation = rLogFont.lfEscapement;
- rLogFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
- rLogFont.lfQuality = DEFAULT_QUALITY;
- rLogFont.lfOutPrecision = OUT_TT_PRECIS;
- if ( pFont->mnOrientation )
- rLogFont.lfClipPrecision |= CLIP_LH_ANGLES;
- // disable antialiasing if requested
- if ( pFont->mbNonAntialiased )
- rLogFont.lfQuality = NONANTIALIASED_QUALITY;
- // select vertical mode if requested and available
- if( pFont->mbVertical && nNameLen )
- {
- // vertical fonts start with an '@'
- memmove( &rLogFont.lfFaceName[1], &rLogFont.lfFaceName[0],
- sizeof(rLogFont.lfFaceName)-sizeof(rLogFont.lfFaceName[0]) );
- rLogFont.lfFaceName[0] = '@';
- // check availability of vertical mode for this font
- bool bAvailable = false;
- EnumFontFamiliesExW( hDC, &rLogFont, (FONTENUMPROCW)SalEnumQueryFontProcExW,
- (LPARAM)&bAvailable, 0 );
- if( !bAvailable )
- {
- // restore non-vertical name if not vertical mode isn't available
- memcpy( &rLogFont.lfFaceName[0], aName.GetBuffer(), nNameLen*sizeof(wchar_t) );
- if( nNameLen < LF_FACESIZE )
- rLogFont.lfFaceName[nNameLen] = '\0';
- }
- }
- }
- // -----------------------------------------------------------------------
- static void ImplGetLogFontFromFontSelect( HDC hDC,
- const…
Large files files are truncated, but you can click here to view the full file