/vcl/win/source/gdi/salgdi3.cxx
C++ | 2927 lines | 2142 code | 438 blank | 347 comment | 433 complexity | ba4653278a575b9dcd8f2bc228c67501 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-3.0, MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause-No-Nuclear-License-2014
Large files files are truncated, but you can click here to view the full file
- /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
- /*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
- #include <string.h>
- #include <malloc.h>
- #include <svsys.h>
- #include "rtl/logfile.hxx"
- #include "rtl/tencinfo.h"
- #include "rtl/textcvt.h"
- #include "rtl/bootstrap.hxx"
- #include "i18npool/mslangid.hxx"
- #include "i18npool/languagetag.hxx"
- #include "osl/module.h"
- #include "osl/file.hxx"
- #include "osl/thread.hxx"
- #include "osl/process.h"
- #include "basegfx/polygon/b2dpolygon.hxx"
- #include "basegfx/polygon/b2dpolypolygon.hxx"
- #include "basegfx/matrix/b2dhommatrix.hxx"
- #include "basegfx/matrix/b2dhommatrixtools.hxx"
- #include "unotools/fontcfg.hxx" // for IMPL_FONT_ATTR_SYMBOL
- #include "vcl/font.hxx"
- #include "vcl/svapp.hxx"
- #include "tools/poly.hxx"
- #include "tools/debug.hxx"
- #include "tools/stream.hxx"
- #include "tools/helpers.hxx"
- #include <vcl/sysdata.hxx>
- #include "win/wincomp.hxx"
- #include "win/saldata.hxx"
- #include "win/salgdi.h"
- #include "outfont.hxx"
- #include "fontsubset.hxx"
- #include "sallayout.hxx"
- #include "outdev.h" // for ImplGlyphFallbackFontSubstitution
- #include "sft.hxx"
- #include <algorithm>
- #ifdef ENABLE_GRAPHITE
- #include <graphite2/Font.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;
- sal_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(;;)
- {
- aFontFileURL = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(aCacheFile, RTL_TEXTENCODING_UTF8);
- if( !aFontFileURL.Len() )
- break;
- aDFA.maName = read_lenPrefixed_uInt8s_ToOUString<sal_uInt16>(aCacheFile, 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 );
- write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(aCacheFile, rFontFileURL, RTL_TEXTENCODING_UTF8);
- write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(aCacheFile, 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);
- write_lenPrefixed_uInt8s_FromOUString<sal_uInt16>(aCacheFile, rDFA.maStyleName, RTL_TEXTENCODING_UTF8);
- ++aIter;
- }
- // EOF Marker
- write_lenPrefixed_uInt8s_FromOString<sal_uInt16>(aCacheFile, rtl::OString());
- }
- }
- }
- 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; }
- int size() const { return mnByteCount; }
- private:
- unsigned char* mpRawBytes;
- unsigned 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()
- unsigned 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().GetUILanguageTag().getLanguageType();
- LanguageType nDefaultCJK = MsLangId::isCJK(nDefaultLang) ? nDefaultLang : LANGUAGE_CHINESE;
- // change the marked entries to prefered language
- static const int nCount = SAL_N_ELEMENTS(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 = SAL_N_ELEMENTS(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( FontSelectPattern&, rtl::OUString& rMissingChars ) const;
- private:
- HDC mhDC;
- bool HasMissingChars( const PhysicalFontFace*, const rtl::OUString& rMissingChars ) const;
- };
- inline WinGlyphFallbackSubstititution::WinGlyphFallbackSubstititution( HDC hDC )
- : mhDC( hDC )
- {}
- void ImplGetLogFontFromFontSelect( HDC, const FontSelectPattern*,
- LOGFONTW&, bool /*bTestVerticalAvail*/ );
- // does a font face hold the given missing characters?
- bool WinGlyphFallbackSubstititution::HasMissingChars( const PhysicalFontFace* 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 FontSelectPattern
- const Size aSize( pFace->GetWidth(), pFace->GetHeight() );
- // create a FontSelectPattern object for getting s LOGFONT
- const FontSelectPattern 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;
- pCharMap->AddReference();
- int nMatchCount = 0;
- // static const int nMaxMatchCount = 1; // TODO: tolerate more missing characters?
- const sal_Int32 nStrLen = rMissingChars.getLength();
- for( sal_Int32 nStrIdx = 0; nStrIdx < nStrLen; /* ++nStrIdx unreachable code, see the 'break' below */ )
- {
- const sal_UCS4 uChar = rMissingChars.iterateCodePoints( &nStrIdx );
- nMatchCount += pCharMap->HasChar( uChar );
- break; // for now
- }
- pCharMap->DeReference();
- const bool bHasMatches = (nMatchCount > 0);
- return bHasMatches;
- }
- namespace
- {
- //used by 2-level font fallback
- ImplDevFontListData* findDevFontListByLocale(const ImplDevFontList &rDevFontList,
- const com::sun::star::lang::Locale& rLocale )
- {
- // get the default font for a specified locale
- const utl::DefaultFontConfiguration& rDefaults =
- utl::DefaultFontConfiguration::get();
- const rtl::OUString aDefault = rDefaults.getUserInterfaceFont(rLocale);
- return rDevFontList.ImplFindByTokenNames(aDefault);
- }
- }
- // find a fallback font for missing characters
- // TODO: should stylistic matches be searched and prefered?
- bool WinGlyphFallbackSubstititution::FindFontSubstitute( FontSelectPattern& rFontSelData, rtl::OUString& rMissingChars ) const
- {
- // guess a locale matching to the missing chars
- com::sun::star::lang::Locale aLocale;
- LanguageType eLang = LANGUAGE_DONTKNOW;
- sal_Int32 nStrIdx = 0;
- const sal_Int32 nStrLen = rMissingChars.getLength();
- while( nStrIdx < nStrLen )
- {
- const sal_UCS4 uChar = rMissingChars.iterateCodePoints( &nStrIdx );
- eLang = MapCharToLanguage( uChar );
- if( eLang == LANGUAGE_DONTKNOW )
- continue;
- aLocale = LanguageTag( eLang ).getLocale();
- break;
- }
- // fall back to default UI locale if the missing characters are inconclusive
- if( eLang == LANGUAGE_DONTKNOW )
- aLocale = Application::GetSettings().GetUILanguageTag().getLocale();
- // first level fallback:
- // try use the locale specific default fonts defined in VCL.xcu
- const ImplDevFontList* pDevFontList = ImplGetSVData()->maGDIData.mpScreenFontList;
- /*const*/ ImplDevFontListData* pDevFont = findDevFontListByLocale(*pDevFontList, aLocale);
- if( pDevFont )
- {
- const PhysicalFontFace* 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.meItalic, rFontSelData.maSearchName );
- if( pDevFont )
- {
- const PhysicalFontFace* 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 PhysicalFontFace* 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 = (sal_uInt16)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 ImplSalLogFontToFontW( HDC hDC, const LOGFONTW& rLogFont, Font& rFont )
- {
- rtl::OUString aFontName( reinterpret_cast<const sal_Unicode*>(rLogFont.lfFaceName) );
- if (!aFontName.isEmpty())
- {
- 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 );
- }
- }
- // =======================================================================
- #ifdef ENABLE_GRAPHITE
- #ifdef DEBUG
- static FILE * grLogFile = NULL;
- static FILE * grLog()
- {
- std::string logFileName(getenv("TEMP"));
- logFileName.append("\\grface.log");
- if (grLogFile == NULL) grLogFile = fopen(logFileName.c_str(),"w");
- else fflush(grLogFile);
- return grLogFile;
- }
- #undef NDEBUG
- #endif
- const void * getGrTable(const void* appFaceHandle, unsigned int name, size_t *len)
- {
- const GrFontData * fontTables = reinterpret_cast<const GrFontData*>(appFaceHandle);
- return fontTables->getTable(name, len);
- }
- GrFontData::GrFontData(HDC hDC) :
- mhDC(hDC), mpFace(NULL), mnRefCount(1)
- {
- // The face options ensure that the tables are all read at construction
- // time so there is no need to keep the hDC uptodate
- static const char* pGraphiteCacheStr = getenv( "SAL_GRAPHITE_CACHE_SIZE" );
- unsigned long graphiteSegCacheSize = pGraphiteCacheStr ? (atoi(pGraphiteCacheStr)) : 0;
- if (graphiteSegCacheSize > 500)
- mpFace = gr_make_face_with_seg_cache(this, getGrTable,
- graphiteSegCacheSize, gr_face_preloadGlyphs | gr_face_cacheCmap);
- else
- mpFace = gr_make_face(this, getGrTable,
- gr_face_preloadGlyphs | gr_face_cacheCmap);
- #ifdef DEBUG
- fprintf(grLog(), "gr_make_face %lx for WinFontData %lx\n", (unsigned long)mpFace,
- (unsigned long)this);
- #endif
- mhDC = NULL;
- }
- GrFontData::~GrFontData()
- {
- if (mpFace)
- {
- #ifdef DEBUG
- fprintf(grLog(), "gr_face_destroy %lx for WinFontData %lx\n", (unsigned long)mpFace,
- (unsigned long)this);
- #endif
- gr_face_destroy(mpFace);
- mpFace = NULL;
- }
- std::vector<RawFontData*>::iterator i = mvData.begin();
- while (i != mvData.end())
- {
- delete *i;
- ++i;
- }
- mvData.clear();
- }
- const void * GrFontData::getTable(unsigned int name, size_t *len) const
- {
- #ifdef DEBUG
- #undef NDEBUG
- #endif
- assert(mhDC);
- // swap the bytes
- union TtfTag {
- unsigned int i;
- unsigned char c[4];
- };
- TtfTag littleEndianTag;
- littleEndianTag.i = name;
- TtfTag bigEndianTag;
- bigEndianTag.c[0] = littleEndianTag.c[3];
- bigEndianTag.c[1] = littleEndianTag.c[2];
- bigEndianTag.c[2] = littleEndianTag.c[1];
- bigEndianTag.c[3] = littleEndianTag.c[0];
- mvData.push_back(new RawFontData(mhDC, bigEndianTag.i));
- const RawFontData * data = mvData[mvData.size()-1];
- if (data && (data->size() > 0))
- {
- if (len)
- *len = data->size();
- return reinterpret_cast<const void *>(data->get());
- }
- else
- {
- if (len)
- *len = 0;
- return NULL;
- }
- }
- #endif
- ImplWinFontData::ImplWinFontData( const ImplDevFontAttributes& rDFS,
- int nHeight, BYTE eWinCharSet, BYTE nPitchAndFamily )
- : PhysicalFontFace( rDFS, 0 ),
- mnId( 0 ),
- mbDisableGlyphApi( false ),
- mbHasKoreanRange( false ),
- mbHasCJKSupport( false ),
- #ifdef ENABLE_GRAPHITE
- mpGraphiteData(NULL),
- mbHasGraphiteSupport( false ),
- #endif
- mbHasArabicSupport ( false ),
- mbFontCapabilitiesRead( false ),
- mpUnicodeMap( NULL ),
- mpEncodingVector( NULL ),
- mpFontCharSets( NULL ),
- mnFontCharSetCount( 0 ),
- meWinCharSet( eWinCharSet ),
- mnPitchAndFamily( nPitchAndFamily ),
- mbAliasSymbolsHigh( false ),
- mbAliasSymbolsLow( false ),
- mbGsubRead( false )
- {
- 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;
- }
- }
- #ifdef DEBUG
- fprintf(grLog(), "ImplWinFontData::ImplWinFontData() %lx\n", (unsigned long)this);
- #endif
- }
- // -----------------------------------------------------------------------
- ImplWinFontData::~ImplWinFontData()
- {
- delete[] mpFontCharSets;
- if( mpUnicodeMap )
- mpUnicodeMap->DeReference();
- #ifdef ENABLE_GRAPHITE
- if (mpGraphiteData)
- mpGraphiteData->DeReference();
- #ifdef DEBUG
- fprintf(grLog(), "ImplWinFontData::~ImplWinFontData %lx\n", (unsigned long)this);
- #endif
- #endif // ENABLE_GRAPHITE
- delete mpEncodingVector;
- }
- // -----------------------------------------------------------------------
- sal_IntPtr ImplWinFontData::GetFontId() const
- {
- return mnId;
- }
- // -----------------------------------------------------------------------
- static unsigned GetUInt( const unsigned char* p ) { return((p[0]<<24)+(p[1]<<16)+(p[2]<<8)+p[3]);}
- static inline DWORD CalcTag( const char p[4]) { return (p[0]+(p[1]<<8)+(p[2]<<16)+(p[3]<<24)); }
- // -----------------------------------------------------------------------
- void ImplWinFontData::UpdateFromHDC( HDC hDC ) const
- {
- // short circuit if already initialized
- if( mpUnicodeMap != NULL )
- return;
- ReadCmapTable( hDC );
- GetFontCapabilities( hDC );
- #ifdef ENABLE_GRAPHITE
- static const char* pDisableGraphiteText = getenv( "SAL_DISABLE_GRAPHITE" );
- if( !pDisableGraphiteText || (pDisableGraphiteText[0] == '0') )
- {
- const DWORD nSilfTag = CalcTag("Silf");
- const RawFontData aRawFontData( hDC, nSilfTag );
- mbHasGraphiteSupport = (aRawFontData.size() > 0);
- if (mbHasGraphiteSupport)
- {
- #ifdef DEBUG
- fprintf(grLog(), "ImplWinFontData::UpdateFromHDC %lx\n",
- (unsigned long)this);
- #endif
- if (mpGraphiteData == NULL)
- {
- mpGraphiteData = new GrFontData(hDC);
- if (!mpGraphiteData->getFace())
- {
- mbHasGraphiteSupport = false;
- delete mpGraphiteData;
- mpGraphiteData = NULL;
- }
- }
- }
- }
- #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;
- }
- #ifdef ENABLE_GRAPHITE
- const gr_face* ImplWinFontData::GraphiteFace() const
- {
- #ifdef DEBUG
- fprintf(grLog(), "ImplWinFontData::GraphiteFace %lx has face %lx\n",
- (unsigned long)this, mpGraphiteData? mpGraphiteData->getFace(): 0);
- #endif
- return (mpGraphiteData)? mpGraphiteData->getFace() : NULL;
- }
- #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() );
- }
- // -----------------------------------------------------------------------
- const ImplFontCharMap* ImplWinFontData::GetImplFontCharMap() const
- {
- if( !mpUnicodeMap )
- return NULL;
- return mpUnicodeMap;
- }
- bool ImplWinFontData::GetImplFontCapabilities(vcl::FontCapabilities &rFontCapabilities) const
- {
- rFontCapabilities = maFontCapabilities;
- return !rFontCapabilities.maUnicodeRange.empty() || !rFontCapabilities.maCodePageRange.empty();
- }
- // -----------------------------------------------------------------------
- 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 );
- mpUnicodeMap->AddReference();
- }
- void ImplWinFontData::GetFontCapabilities( HDC hDC ) const
- {
- // read this only once per font
- if( mbFontCapabilitiesRead )
- return;
- mbFontCapabilitiesRead = true;
- // GSUB table
- DWORD nLength;
- const DWORD GsubTag = CalcTag( "GSUB" );
- nLength = ::GetFontData( hDC, GsubTag, 0, NULL, 0 );
- if( (nLength != GDI_ERROR) && nLength )
- {
- std::vector<unsigned char> aTable( nLength );
- unsigned char* pTable = &aTable[0];
- ::GetFontData( hDC, GsubTag, 0, pTable, nLength );
- vcl::getTTScripts(maFontCapabilities.maGSUBScriptTags, pTable, nLength);
- }
- // OS/2 table
- const DWORD OS2Tag = CalcTag( "OS/2" );
- nLength = ::GetFontData( hDC, OS2Tag, 0, NULL, 0 );
- if( (nLength != GDI_ERROR) && nLength )
- {
- std::vector<unsigned char> aTable( nLength );
- unsigned char* pTable = &aTable[0];
- ::GetFontData( hDC, OS2Tag, 0, pTable, nLength );
- if (vcl::getTTCoverage(maFontCapabilities.maUnicodeRange, maFontCapabilities.maCodePageRange, pTable, nLength))
- {
- // Check for CJK capabilities of the current font
- // TODO, we have this info already from getTT, decode bits to
- // a readable dynamic_bitset
- sal_uInt32 ulUnicodeRange1 = GetUInt( pTable + 42 );
- sal_uInt32 ulUnicodeRange2 = GetUInt( pTable + 46 );
- mbHasCJKSupport = (ulUnicodeRange2 & 0x2DF00000);
- mbHasKoreanRange= (ulUnicodeRange1 & 0x10000000)
- | (ulUnicodeRange2 & 0x01100000);
- mbHasArabicSupport = (ulUnicodeRange1 & 0x00002000);
- }
- }
- }
- // =======================================================================
- 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…
Large files files are truncated, but you can click here to view the full file