summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorChris Sherlock <chris.sherlock79@gmail.com>2014-04-15 00:13:51 +1000
committerChris Sherlock <chris.sherlock79@gmail.com>2014-04-16 07:33:58 +1000
commitd92ee5d8bebdd6f120c7478127a1be5f78d4b1af (patch)
tree9bae335954f2182e786f97db10d865df21d5ac77 /vcl
parent5a35cb3e7fdb67f4f75435ab8869f8d973ae5daf (diff)
Split outdev3.cxx
Split outdev3.cxx into font and text functions Change-Id: I535dbbce055246865d4d5b62fb1ea5b991fb4663
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Library_vcl.mk3
-rw-r--r--vcl/source/outdev/font.cxx2397
-rw-r--r--vcl/source/outdev/text.cxx (renamed from vcl/source/outdev/outdev3.cxx)2305
3 files changed, 2399 insertions, 2306 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index b6660074c8e6..b1fd7e8d52fe 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -242,7 +242,8 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/outdev/blend \
vcl/source/outdev/mask \
vcl/source/outdev/bitmap \
- vcl/source/outdev/outdev3 \
+ vcl/source/outdev/font \
+ vcl/source/outdev/text \
vcl/source/outdev/pixel \
vcl/source/outdev/rect \
vcl/source/outdev/line \
diff --git a/vcl/source/outdev/font.cxx b/vcl/source/outdev/font.cxx
new file mode 100644
index 000000000000..c1565f743b14
--- /dev/null
+++ b/vcl/source/outdev/font.cxx
@@ -0,0 +1,2397 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include "i18nlangtag/mslangid.hxx"
+#include "i18nlangtag/languagetag.hxx"
+
+#include "rtl/tencinfo.h"
+#include "rtl/logfile.hxx"
+
+#include "tools/debug.hxx"
+#include "tools/poly.hxx"
+
+#include "basegfx/polygon/b2dpolygon.hxx"
+#include "basegfx/polygon/b2dpolypolygon.hxx"
+#include "basegfx/matrix/b2dhommatrix.hxx"
+
+#include "vcl/metric.hxx"
+#include "vcl/metaact.hxx"
+#include "vcl/gdimtf.hxx"
+#include "vcl/virdev.hxx"
+#include "vcl/print.hxx"
+#include "vcl/event.hxx"
+#include "vcl/window.hxx"
+#include "vcl/svapp.hxx"
+#include "vcl/bmpacc.hxx"
+#include "vcl/outdev.hxx"
+#include "vcl/edit.hxx"
+#include <vcl/settings.hxx>
+// declare system types in sysdata.hxx
+#include <svsys.h>
+#include "vcl/sysdata.hxx"
+#include "vcl/unohelp.hxx"
+#include "vcl/controllayout.hxx"
+
+#include "salgdi.hxx"
+#include "sallayout.hxx"
+#include "svdata.hxx"
+#include "impfont.hxx"
+#include "outdata.hxx"
+#include "outfont.hxx"
+#include "outdev.h"
+#include "PhysicalFontCollection.hxx"
+#include "PhysicalFontFace.hxx"
+#include "PhysicalFontFamily.hxx"
+
+#include "textlayout.hxx"
+#include "svids.hrc"
+#include "window.h"
+
+#include "unotools/fontcvt.hxx"
+#include "unotools/fontcfg.hxx"
+
+#include "osl/file.h"
+
+#include <config_graphite.h>
+#if ENABLE_GRAPHITE
+#include "graphite_features.hxx"
+#endif
+
+#include "../gdi/pdfwriter_impl.hxx"
+
+#include "com/sun/star/beans/PropertyValues.hpp"
+#include "com/sun/star/i18n/XBreakIterator.hpp"
+#include "com/sun/star/i18n/WordType.hpp"
+#include "com/sun/star/linguistic2/LinguServiceManager.hpp"
+#include <comphelper/processfactory.hxx>
+
+#include "sal/alloca.h"
+
+#include <cmath>
+#include <cstring>
+
+#include <memory>
+#include <algorithm>
+
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+using namespace ::rtl;
+using namespace ::vcl;
+using namespace ::utl;
+
+void ImplRotatePos( long nOriginX, long nOriginY, long& rX, long& rY,
+ int nOrientation )
+{
+ if ( (nOrientation >= 0) && !(nOrientation % 900) )
+ {
+ if ( (nOrientation >= 3600) )
+ nOrientation %= 3600;
+
+ if ( nOrientation )
+ {
+ rX -= nOriginX;
+ rY -= nOriginY;
+
+ if ( nOrientation == 900 )
+ {
+ long nTemp = rX;
+ rX = rY;
+ rY = -nTemp;
+ }
+ else if ( nOrientation == 1800 )
+ {
+ rX = -rX;
+ rY = -rY;
+ }
+ else /* ( nOrientation == 2700 ) */
+ {
+ long nTemp = rX;
+ rX = -rY;
+ rY = nTemp;
+ }
+
+ rX += nOriginX;
+ rY += nOriginY;
+ }
+ }
+ else
+ {
+ double nRealOrientation = nOrientation*F_PI1800;
+ double nCos = cos( nRealOrientation );
+ double nSin = sin( nRealOrientation );
+
+ // Translation...
+ long nX = rX-nOriginX;
+ long nY = rY-nOriginY;
+
+ // Rotation...
+ rX = +((long)(nCos*nX + nSin*nY)) + nOriginX;
+ rY = -((long)(nSin*nX - nCos*nY)) + nOriginY;
+ }
+}
+
+void OutputDevice::ImplClearFontData( const bool bNewFontLists )
+{
+ // the currently selected logical font is no longer needed
+ if ( mpFontEntry )
+ {
+ mpFontCache->Release( mpFontEntry );
+ mpFontEntry = NULL;
+ }
+
+ mbInitFont = true;
+ mbNewFont = true;
+
+ if ( bNewFontLists )
+ {
+ if ( mpGetDevFontList )
+ {
+ delete mpGetDevFontList;
+ mpGetDevFontList = NULL;
+ }
+ if ( mpGetDevSizeList )
+ {
+ delete mpGetDevSizeList;
+ mpGetDevSizeList = NULL;
+ }
+
+ // release all physically selected fonts on this device
+ if( ImplGetGraphics() )
+ mpGraphics->ReleaseFonts();
+ }
+
+// if ( GetOutDevType() == OUTDEV_PRINTER || mpPDFWriter )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if( mpFontCache && mpFontCache != pSVData->maGDIData.mpScreenFontCache )
+ mpFontCache->Invalidate();
+
+ if ( bNewFontLists )
+ {
+ // we need a graphics
+ if ( ImplGetGraphics() )
+ {
+ if( mpFontCollection && mpFontCollection != pSVData->maGDIData.mpScreenFontList )
+ mpFontCollection->Clear();
+
+ if( mpPDFWriter )
+ {
+ if( mpFontCollection && mpFontCollection != pSVData->maGDIData.mpScreenFontList )
+ delete mpFontCollection;
+ if( mpFontCache && mpFontCache != pSVData->maGDIData.mpScreenFontCache )
+ delete mpFontCache;
+ mpFontCollection = 0;
+ mpFontCache = 0;
+ }
+ }
+ }
+ }
+
+ // also update child windows if needed
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ Window* pChild = ((Window*)this)->mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplClearFontData( true );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+}
+
+void OutputDevice::ImplRefreshFontData( const bool bNewFontLists )
+{
+// if ( GetOutDevType() == OUTDEV_PRINTER || mpPDFWriter )
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+
+ if ( bNewFontLists )
+ {
+ // we need a graphics
+ if ( ImplGetGraphics() )
+ {
+ if( mpPDFWriter )
+ {
+ mpFontCollection = pSVData->maGDIData.mpScreenFontList->Clone( true, true );
+ mpFontCache = new ImplFontCache();
+ }
+ else
+ {
+ mpGraphics->GetDevFontList( mpFontCollection );
+ }
+ }
+ }
+ }
+
+ // also update child windows if needed
+ if ( GetOutDevType() == OUTDEV_WINDOW )
+ {
+ Window* pChild = ((Window*)this)->mpWindowImpl->mpFirstChild;
+ while ( pChild )
+ {
+ pChild->ImplRefreshFontData( true );
+ pChild = pChild->mpWindowImpl->mpNext;
+ }
+ }
+}
+
+void OutputDevice::ImplUpdateFontData( bool bNewFontLists )
+{
+ ImplClearFontData( bNewFontLists );
+ ImplRefreshFontData( bNewFontLists );
+}
+
+void OutputDevice::ImplUpdateAllFontData( bool bNewFontLists )
+{
+ ImplSVData* pSVData = ImplGetSVData();
+
+ ImplUpdateFontDataForAllFrames( &OutputDevice::ImplClearFontData, bNewFontLists );
+
+ // clear global font lists to have them updated
+ pSVData->maGDIData.mpScreenFontCache->Invalidate();
+ if ( bNewFontLists )
+ {
+ pSVData->maGDIData.mpScreenFontList->Clear();
+ Window * pFrame = pSVData->maWinData.mpFirstFrame;
+ if ( pFrame )
+ {
+ if ( pFrame->ImplGetGraphics() )
+ {
+ // Stupid typecast here and somewhere ((OutputDevice*)&aVDev)->, because bug in .NET2002 compiler
+ OutputDevice *pDevice = (OutputDevice*)pFrame;
+ pDevice->mpGraphics->ClearDevFontCache();
+ pDevice->mpGraphics->GetDevFontList(pFrame->mpWindowImpl->mpFrameData->mpFontCollection);
+ }
+ }
+ }
+
+ ImplUpdateFontDataForAllFrames( &OutputDevice::ImplRefreshFontData, bNewFontLists );
+}
+
+void OutputDevice::ImplUpdateFontDataForAllFrames( const FontUpdateHandler_t pHdl, const bool bNewFontLists )
+{
+ ImplSVData* const pSVData = ImplGetSVData();
+
+ // update all windows
+ Window* pFrame = pSVData->maWinData.mpFirstFrame;
+ while ( pFrame )
+ {
+ ( pFrame->*pHdl )( bNewFontLists );
+
+ Window* pSysWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
+ while ( pSysWin )
+ {
+ ( pSysWin->*pHdl )( bNewFontLists );
+ pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
+ }
+
+ pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
+ }
+
+ // update all virtual devices
+ VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev;
+ while ( pVirDev )
+ {
+ ( pVirDev->*pHdl )( bNewFontLists );
+ pVirDev = pVirDev->mpNext;
+ }
+
+ // update all printers
+ Printer* pPrinter = pSVData->maGDIData.mpFirstPrinter;
+ while ( pPrinter )
+ {
+ ( pPrinter->*pHdl )( bNewFontLists );
+ pPrinter = pPrinter->mpNext;
+ }
+}
+
+void OutputDevice::BeginFontSubstitution()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ pSVData->maGDIData.mbFontSubChanged = false;
+}
+
+void OutputDevice::EndFontSubstitution()
+{
+ ImplSVData* pSVData = ImplGetSVData();
+ if ( pSVData->maGDIData.mbFontSubChanged )
+ {
+ ImplUpdateAllFontData( false );
+
+ Application* pApp = GetpApp();
+ DataChangedEvent aDCEvt( DATACHANGED_FONTSUBSTITUTION );
+ pApp->DataChanged( aDCEvt );
+ pApp->NotifyAllWindows( aDCEvt );
+ pSVData->maGDIData.mbFontSubChanged = false;
+ }
+}
+
+void OutputDevice::AddFontSubstitute( const OUString& rFontName,
+ const OUString& rReplaceFontName,
+ sal_uInt16 nFlags )
+{
+ ImplDirectFontSubstitution*& rpSubst = ImplGetSVData()->maGDIData.mpDirectFontSubst;
+ if( !rpSubst )
+ rpSubst = new ImplDirectFontSubstitution();
+ rpSubst->AddFontSubstitute( rFontName, rReplaceFontName, nFlags );
+ ImplGetSVData()->maGDIData.mbFontSubChanged = true;
+}
+
+void ImplDirectFontSubstitution::AddFontSubstitute( const OUString& rFontName,
+ const OUString& rSubstFontName, sal_uInt16 nFlags )
+{
+ maFontSubstList.push_back( ImplFontSubstEntry( rFontName, rSubstFontName, nFlags ) );
+}
+
+ImplFontSubstEntry::ImplFontSubstEntry( const OUString& rFontName,
+ const OUString& rSubstFontName, sal_uInt16 nSubstFlags )
+: maName( rFontName )
+, maReplaceName( rSubstFontName )
+, mnFlags( nSubstFlags )
+{
+ maSearchName = rFontName;
+ maSearchReplaceName = rSubstFontName;
+ GetEnglishSearchFontName( maSearchName );
+ GetEnglishSearchFontName( maSearchReplaceName );
+}
+
+void OutputDevice::RemoveFontSubstitute( sal_uInt16 n )
+{
+ ImplDirectFontSubstitution* pSubst = ImplGetSVData()->maGDIData.mpDirectFontSubst;
+ if( pSubst )
+ pSubst->RemoveFontSubstitute( n );
+}
+
+void ImplDirectFontSubstitution::RemoveFontSubstitute( int nIndex )
+{
+ FontSubstList::iterator it = maFontSubstList.begin();
+ for( int nCount = 0; (it != maFontSubstList.end()) && (nCount++ != nIndex); ++it ) ;
+ if( it != maFontSubstList.end() )
+ maFontSubstList.erase( it );
+}
+
+sal_uInt16 OutputDevice::GetFontSubstituteCount()
+{
+ const ImplDirectFontSubstitution* pSubst = ImplGetSVData()->maGDIData.mpDirectFontSubst;
+ if( !pSubst )
+ return 0;
+ int nCount = pSubst->GetFontSubstituteCount();
+ return (sal_uInt16)nCount;
+}
+
+bool ImplDirectFontSubstitution::FindFontSubstitute( OUString& rSubstName,
+ const OUString& rSearchName, sal_uInt16 nFlags ) const
+{
+ // TODO: get rid of O(N) searches
+ FontSubstList::const_iterator it = maFontSubstList.begin();
+ for(; it != maFontSubstList.end(); ++it )
+ {
+ const ImplFontSubstEntry& rEntry = *it;
+ if( ((rEntry.mnFlags & nFlags) || !nFlags)
+ && (rEntry.maSearchName == rSearchName) )
+ {
+ rSubstName = rEntry.maSearchReplaceName;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void ImplFontSubstitute( OUString& rFontName )
+{
+#ifdef DBG_UTIL
+ OUString aTempName = rFontName;
+ GetEnglishSearchFontName( aTempName );
+ DBG_ASSERT( aTempName == rFontName, "ImplFontSubstitute() called without a searchname" );
+#endif
+
+ OUString aSubstFontName;
+
+ // apply user-configurable font replacement (eg, from the list in Tools->Options)
+ const ImplDirectFontSubstitution* pSubst = ImplGetSVData()->maGDIData.mpDirectFontSubst;
+ if( pSubst && pSubst->FindFontSubstitute( aSubstFontName, rFontName, FONT_SUBSTITUTE_ALWAYS ) )
+ {
+ rFontName = aSubstFontName;
+ return;
+ }
+}
+
+//hidpi TODO: This routine has hard-coded font-sizes that break places such as DialControl
+Font OutputDevice::GetDefaultFont( sal_uInt16 nType, LanguageType eLang,
+ sal_uLong nFlags, const OutputDevice* pOutDev )
+{
+ if (!pOutDev) // default is NULL
+ pOutDev = Application::GetDefaultDevice();
+
+ LanguageTag aLanguageTag(
+ ( eLang == LANGUAGE_NONE || eLang == LANGUAGE_SYSTEM || eLang == LANGUAGE_DONTKNOW ) ?
+ Application::GetSettings().GetUILanguageTag() :
+ LanguageTag( eLang ));
+
+ utl::DefaultFontConfiguration& rDefaults = utl::DefaultFontConfiguration::get();
+ OUString aDefault = rDefaults.getDefaultFont( aLanguageTag, nType );
+ OUString aSearch;
+
+ if( !aDefault.isEmpty() )
+ aSearch = aDefault;
+ else
+ aSearch = rDefaults.getUserInterfaceFont( aLanguageTag ); // use the UI font as a fallback
+
+ Font aFont;
+ aFont.SetPitch( PITCH_VARIABLE );
+
+ switch ( nType )
+ {
+ case DEFAULTFONT_SANS_UNICODE:
+ case DEFAULTFONT_UI_SANS:
+ aFont.SetFamily( FAMILY_SWISS );
+ break;
+
+ case DEFAULTFONT_SANS:
+ case DEFAULTFONT_LATIN_HEADING:
+ case DEFAULTFONT_LATIN_SPREADSHEET:
+ case DEFAULTFONT_LATIN_DISPLAY:
+ aFont.SetFamily( FAMILY_SWISS );
+ break;
+
+ case DEFAULTFONT_SERIF:
+ case DEFAULTFONT_LATIN_TEXT:
+ case DEFAULTFONT_LATIN_PRESENTATION:
+ aFont.SetFamily( FAMILY_ROMAN );
+ break;
+
+ case DEFAULTFONT_FIXED:
+ case DEFAULTFONT_LATIN_FIXED:
+ case DEFAULTFONT_UI_FIXED:
+ aFont.SetPitch( PITCH_FIXED );
+ aFont.SetFamily( FAMILY_MODERN );
+ break;
+
+ case DEFAULTFONT_SYMBOL:
+ aFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
+ break;
+
+ case DEFAULTFONT_CJK_TEXT:
+ case DEFAULTFONT_CJK_PRESENTATION:
+ case DEFAULTFONT_CJK_SPREADSHEET:
+ case DEFAULTFONT_CJK_HEADING:
+ case DEFAULTFONT_CJK_DISPLAY:
+ aFont.SetFamily( FAMILY_SYSTEM ); // don't care, but don't use font subst config later...
+ break;
+
+ case DEFAULTFONT_CTL_TEXT:
+ case DEFAULTFONT_CTL_PRESENTATION:
+ case DEFAULTFONT_CTL_SPREADSHEET:
+ case DEFAULTFONT_CTL_HEADING:
+ case DEFAULTFONT_CTL_DISPLAY:
+ aFont.SetFamily( FAMILY_SYSTEM ); // don't care, but don't use font subst config later...
+ break;
+ }
+
+ if ( !aSearch.isEmpty() )
+ {
+ aFont.SetHeight( 12 ); // corresponds to nDefaultHeight
+ aFont.SetWeight( WEIGHT_NORMAL );
+ aFont.SetLanguage( eLang );
+
+ if ( aFont.GetCharSet() == RTL_TEXTENCODING_DONTKNOW )
+ aFont.SetCharSet( osl_getThreadTextEncoding() );
+
+ // Should we only return available fonts on the given device
+ if ( pOutDev )
+ {
+ pOutDev->ImplInitFontList();
+
+ // Search Font in the FontList
+ OUString aName;
+ OUString aSearchName;
+ sal_Int32 nIndex = 0;
+ do
+ {
+ aSearchName = GetNextFontToken( aSearch, nIndex );
+ GetEnglishSearchFontName( aSearchName );
+ PhysicalFontFamily* pFontFamily = pOutDev->mpFontCollection->ImplFindBySearchName( aSearchName );
+ if( pFontFamily )
+ {
+ AddTokenFontName( aName, pFontFamily->GetFamilyName() );
+ if( nFlags & DEFAULTFONT_FLAGS_ONLYONE )
+ break;
+ }
+ }
+ while ( nIndex != -1 );
+ aFont.SetName( aName );
+ }
+
+ // No Name, than set all names
+ if ( aFont.GetName().isEmpty() )
+ {
+ if ( nFlags & DEFAULTFONT_FLAGS_ONLYONE )
+ {
+ if( !pOutDev )
+ {
+ SAL_WARN ("vcl.gdi", "No default window has been set for the application - we really shouldn't be able to get here");
+ sal_Int32 nIndex = 0;
+ aFont.SetName( aSearch.getToken( 0, ';', nIndex ) );
+ }
+ else
+ {
+ pOutDev->ImplInitFontList();
+
+ aFont.SetName( aSearch );
+
+ // convert to pixel height
+ Size aSize = pOutDev->ImplLogicToDevicePixel( aFont.GetSize() );
+ if ( !aSize.Height() )
+ {
+ // use default pixel height only when logical height is zero
+ if ( aFont.GetHeight() )
+ aSize.Height() = 1;
+ else
+ aSize.Height() = (12*pOutDev->mnDPIY)/72;
+ }
+
+ // use default width only when logical width is zero
+ if( (0 == aSize.Width()) && (0 != aFont.GetSize().Width()) )
+ aSize.Width() = 1;
+
+ // get the name of the first available font
+ float fExactHeight = static_cast<float>(aSize.Height());
+ ImplFontEntry* pEntry = pOutDev->mpFontCache->GetFontEntry( pOutDev->mpFontCollection, aFont, aSize, fExactHeight );
+ if (pEntry)
+ {
+ if( pEntry->maFontSelData.mpFontData )
+ aFont.SetName( pEntry->maFontSelData.mpFontData->GetFamilyName() );
+ else
+ aFont.SetName( pEntry->maFontSelData.maTargetName );
+ }
+ }
+ }
+ else
+ aFont.SetName( aSearch );
+ }
+ }
+
+#if OSL_DEBUG_LEVEL > 2
+ const char* s = "DEFAULTFONT_SANS_UNKNOWN";
+ switch ( nType )
+ {
+ case DEFAULTFONT_SANS_UNICODE: s = "DEFAULTFONT_SANS_UNICODE"; break;
+ case DEFAULTFONT_UI_SANS: s = "DEFAULTFONT_UI_SANS"; break;
+
+ case DEFAULTFONT_SANS: s = "DEFAULTFONT_SANS"; break;
+ case DEFAULTFONT_LATIN_HEADING: s = "DEFAULTFONT_LATIN_HEADING"; break;
+ case DEFAULTFONT_LATIN_SPREADSHEET: s = "DEFAULTFONT_LATIN_SPREADSHEET"; break;
+ case DEFAULTFONT_LATIN_DISPLAY: s = "DEFAULTFONT_LATIN_DISPLAY"; break;
+
+ case DEFAULTFONT_SERIF: s = "DEFAULTFONT_SERIF"; break;
+ case DEFAULTFONT_LATIN_TEXT: s = "DEFAULTFONT_LATIN_TEXT"; break;
+ case DEFAULTFONT_LATIN_PRESENTATION: s = "DEFAULTFONT_LATIN_PRESENTATION"; break;
+
+ case DEFAULTFONT_FIXED: s = "DEFAULTFONT_FIXED"; break;
+ case DEFAULTFONT_LATIN_FIXED: s = "DEFAULTFONT_LATIN_FIXED"; break;
+ case DEFAULTFONT_UI_FIXED: s = "DEFAULTFONT_UI_FIXED"; break;
+
+ case DEFAULTFONT_SYMBOL: s = "DEFAULTFONT_SYMBOL"; break;
+
+ case DEFAULTFONT_CJK_TEXT: s = "DEFAULTFONT_CJK_TEXT"; break;
+ case DEFAULTFONT_CJK_PRESENTATION: s = "DEFAULTFONT_CJK_PRESENTATION"; break;
+ case DEFAULTFONT_CJK_SPREADSHEET: s = "DEFAULTFONT_CJK_SPREADSHEET"; break;
+ case DEFAULTFONT_CJK_HEADING: s = "DEFAULTFONT_CJK_HEADING"; break;
+ case DEFAULTFONT_CJK_DISPLAY: s = "DEFAULTFONT_CJK_DISPLAY"; break;
+
+ case DEFAULTFONT_CTL_TEXT: s = "DEFAULTFONT_CTL_TEXT"; break;
+ case DEFAULTFONT_CTL_PRESENTATION: s = "DEFAULTFONT_CTL_PRESENTATION"; break;
+ case DEFAULTFONT_CTL_SPREADSHEET: s = "DEFAULTFONT_CTL_SPREADSHEET"; break;
+ case DEFAULTFONT_CTL_HEADING: s = "DEFAULTFONT_CTL_HEADING"; break;
+ case DEFAULTFONT_CTL_DISPLAY: s = "DEFAULTFONT_CTL_DISPLAY"; break;
+ }
+ fprintf( stderr, " OutputDevice::GetDefaultFont() Type=\"%s\" lang=%d flags=%ld FontName=\"%s\"\n",
+ s, eLang, nFlags,
+ OUStringToOString( aFont.GetName(), RTL_TEXTENCODING_UTF8 ).getStr()
+ );
+#endif
+
+ return aFont;
+}
+
+ImplFontEntry::ImplFontEntry( const FontSelectPattern& rFontSelData )
+ : maFontSelData( rFontSelData )
+ , maMetric( rFontSelData )
+ , mpConversion( NULL )
+ , mnLineHeight( 0 )
+ , mnRefCount( 1 )
+ , mnSetFontFlags( 0 )
+ , mnOwnOrientation( 0 )
+ , mnOrientation( 0 )
+ , mbInit( false )
+ , mpUnicodeFallbackList( NULL )
+{
+ maFontSelData.mpFontEntry = this;
+}
+
+ImplFontEntry::~ImplFontEntry()
+{
+ delete mpUnicodeFallbackList;
+}
+
+size_t ImplFontEntry::GFBCacheKey_Hash::operator()( const GFBCacheKey& rData ) const
+{
+ boost::hash<sal_UCS4> a;
+ boost::hash<int > b;
+ return a(rData.first) ^ b(rData.second);
+}
+
+void ImplFontEntry::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
+{
+ if( !mpUnicodeFallbackList )
+ mpUnicodeFallbackList = new UnicodeFallbackList;
+ (*mpUnicodeFallbackList)[ GFBCacheKey(cChar,eWeight) ] = rFontName;
+}
+
+bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, OUString* pFontName ) const
+{
+ if( !mpUnicodeFallbackList )
+ return false;
+
+ UnicodeFallbackList::const_iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) );
+ if( it == mpUnicodeFallbackList->end() )
+ return false;
+
+ *pFontName = (*it).second;
+ return true;
+}
+
+void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
+{
+// DBG_ASSERT( mpUnicodeFallbackList, "ImplFontEntry::IgnoreFallbackForUnicode no list" );
+ UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) );
+// DBG_ASSERT( it != mpUnicodeFallbackList->end(), "ImplFontEntry::IgnoreFallbackForUnicode no match" );
+ if( it == mpUnicodeFallbackList->end() )
+ return;
+ if( (*it).second == rFontName )
+ mpUnicodeFallbackList->erase( it );
+}
+
+FontSelectPatternAttributes::FontSelectPatternAttributes( const Font& rFont,
+ const OUString& rSearchName, const Size& rSize, float fExactHeight )
+ : maSearchName( rSearchName )
+ , mnWidth( rSize.Width() )
+ , mnHeight( rSize.Height() )
+ , mfExactHeight( fExactHeight)
+ , mnOrientation( rFont.GetOrientation() )
+ , meLanguage( rFont.GetLanguage() )
+ , mbVertical( rFont.IsVertical() )
+ , mbNonAntialiased( false )
+ , mbEmbolden( false )
+{
+ maTargetName = GetFamilyName();
+
+ rFont.GetFontAttributes( *this );
+
+ // normalize orientation between 0 and 3600
+ if( 3600 <= (unsigned)mnOrientation )
+ {
+ if( mnOrientation >= 0 )
+ mnOrientation %= 3600;
+ else
+ mnOrientation = 3600 - (-mnOrientation % 3600);
+ }
+
+ // normalize width and height
+ if( mnHeight < 0 )
+ mnHeight = -mnHeight;
+ if( mnWidth < 0 )
+ mnWidth = -mnWidth;
+}
+
+FontSelectPattern::FontSelectPattern( const Font& rFont,
+ const OUString& rSearchName, const Size& rSize, float fExactHeight)
+ : FontSelectPatternAttributes(rFont, rSearchName, rSize, fExactHeight)
+ , mpFontData( NULL )
+ , mpFontEntry( NULL )
+{
+}
+
+// NOTE: this ctor is still used on Windows. Do not remove.
+#ifdef WNT
+FontSelectPatternAttributes::FontSelectPatternAttributes( const PhysicalFontFace& rFontData,
+ const Size& rSize, float fExactHeight, int nOrientation, bool bVertical )
+ : ImplFontAttributes( rFontData )
+ , mnWidth( rSize.Width() )
+ , mnHeight( rSize.Height() )
+ , mfExactHeight( fExactHeight )
+ , mnOrientation( nOrientation )
+ , meLanguage( 0 )
+ , mbVertical( bVertical )
+ , mbNonAntialiased( false )
+ , mbEmbolden( false )
+{
+ maTargetName = maSearchName = GetFamilyName();
+ // NOTE: no normalization for width/height/orientation
+}
+
+FontSelectPattern::FontSelectPattern( const PhysicalFontFace& rFontData,
+ const Size& rSize, float fExactHeight, int nOrientation, bool bVertical )
+ : FontSelectPatternAttributes(rFontData, rSize, fExactHeight, nOrientation, bVertical)
+ , mpFontData( &rFontData )
+ , mpFontEntry( NULL )
+{
+}
+#endif
+
+void FontSelectPattern::copyAttributes(const FontSelectPatternAttributes &rAttributes)
+{
+ static_cast<FontSelectPatternAttributes&>(*this) = rAttributes;
+}
+
+size_t ImplFontCache::IFSD_Hash::operator()( const FontSelectPattern& rFSD ) const
+{
+ return rFSD.hashCode();
+}
+
+size_t FontSelectPatternAttributes::hashCode() const
+{
+ // TODO: does it pay off to improve this hash function?
+ static FontNameHash aFontNameHash;
+ size_t nHash = aFontNameHash( maSearchName );
+#if ENABLE_GRAPHITE
+ // check for features and generate a unique hash if necessary
+ if (maTargetName.indexOf(grutils::GrFeatureParser::FEAT_PREFIX)
+ != -1)
+ {
+ nHash = aFontNameHash( maTargetName );
+ }
+#endif
+ nHash += 11 * mnHeight;
+ nHash += 19 * GetWeight();
+ nHash += 29 * GetSlant();
+ nHash += 37 * mnOrientation;
+ nHash += 41 * meLanguage;
+ if( mbVertical )
+ nHash += 53;
+ return nHash;
+}
+
+bool FontSelectPatternAttributes::operator==(const FontSelectPatternAttributes& rOther) const
+{
+ if (static_cast<const ImplFontAttributes&>(*this) != static_cast<const ImplFontAttributes&>(rOther))
+ return false;
+
+ if (maTargetName != rOther.maTargetName)
+ return false;
+
+ if (maSearchName != rOther.maSearchName)
+ return false;
+
+ if (mnWidth != rOther.mnWidth)
+ return false;
+
+ if (mnHeight != rOther.mnHeight)
+ return false;
+
+ if (mfExactHeight != rOther.mfExactHeight)
+ return false;
+
+ if (mnOrientation != rOther.mnOrientation)
+ return false;
+
+ if (meLanguage != rOther.meLanguage)
+ return false;
+
+ if (mbVertical != rOther.mbVertical)
+ return false;
+
+ if (mbNonAntialiased != rOther.mbNonAntialiased)
+ return false;
+
+ if (mbEmbolden != rOther.mbEmbolden)
+ return false;
+
+ if (maItalicMatrix != rOther.maItalicMatrix)
+ return false;
+
+ return true;
+}
+
+bool ImplFontCache::IFSD_Equal::operator()(const FontSelectPattern& rA, const FontSelectPattern& rB) const
+{
+ // check normalized font family name
+ if( rA.maSearchName != rB.maSearchName )
+ return false;
+
+ // check font transformation
+ if( (rA.mnHeight != rB.mnHeight)
+ || (rA.mnWidth != rB.mnWidth)
+ || (rA.mnOrientation != rB.mnOrientation) )
+ return false;
+
+ // check mapping relevant attributes
+ if( (rA.mbVertical != rB.mbVertical)
+ || (rA.meLanguage != rB.meLanguage) )
+ return false;
+
+ // check font face attributes
+ if( (rA.GetWeight() != rB.GetWeight())
+ || (rA.GetSlant() != rB.GetSlant())
+// || (rA.meFamily != rB.meFamily) // TODO: remove this mostly obsolete member
+ || (rA.GetPitch() != rB.GetPitch()) )
+ return false;
+
+ // check style name
+ if( rA.GetStyleName() != rB.GetStyleName() )
+ return false;
+
+ // Symbol fonts may recode from one type to another So they are only
+ // safely equivalent for equal targets
+ if (
+ (rA.mpFontData && rA.mpFontData->IsSymbolFont()) ||
+ (rB.mpFontData && rB.mpFontData->IsSymbolFont())
+ )
+ {
+ if (rA.maTargetName != rB.maTargetName)
+ return false;
+ }
+
+#if ENABLE_GRAPHITE
+ // check for features
+ if ((rA.maTargetName.indexOf(grutils::GrFeatureParser::FEAT_PREFIX)
+ != -1 ||
+ rB.maTargetName.indexOf(grutils::GrFeatureParser::FEAT_PREFIX)
+ != -1) && rA.maTargetName != rB.maTargetName)
+ return false;
+#endif
+
+ if (rA.mbEmbolden != rB.mbEmbolden)
+ return false;
+
+ if (rA.maItalicMatrix != rB.maItalicMatrix)
+ return false;
+
+ return true;
+}
+
+ImplFontCache::ImplFontCache()
+: mpFirstEntry( NULL ),
+ mnRef0Count( 0 )
+{}
+
+ImplFontCache::~ImplFontCache()
+{
+ FontInstanceList::iterator it = maFontInstanceList.begin();
+ for(; it != maFontInstanceList.end(); ++it )
+ {
+ ImplFontEntry* pEntry = (*it).second;
+ delete pEntry;
+ }
+}
+
+ImplFontEntry* ImplFontCache::GetFontEntry( PhysicalFontCollection* pFontList,
+ const Font& rFont, const Size& rSize, float fExactHeight )
+{
+ OUString aSearchName = rFont.GetName();
+
+ // initialize internal font request object
+ FontSelectPattern aFontSelData( rFont, aSearchName, rSize, fExactHeight );
+ return GetFontEntry( pFontList, aFontSelData );
+}
+
+ImplFontEntry* ImplFontCache::GetFontEntry( PhysicalFontCollection* pFontList,
+ FontSelectPattern& aFontSelData )
+{
+ // check if a directly matching logical font instance is already cached,
+ // the most recently used font usually has a hit rate of >50%
+ ImplFontEntry *pEntry = NULL;
+ PhysicalFontFamily* pFontFamily = NULL;
+ IFSD_Equal aIFSD_Equal;
+ if( mpFirstEntry && aIFSD_Equal( aFontSelData, mpFirstEntry->maFontSelData ) )
+ pEntry = mpFirstEntry;
+ else
+ {
+ FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData );
+ if( it != maFontInstanceList.end() )
+ pEntry = (*it).second;
+ }
+
+ if( !pEntry ) // no direct cache hit
+ {
+ // find the best matching logical font family and update font selector accordingly
+ pFontFamily = pFontList->ImplFindByFont( aFontSelData );
+ DBG_ASSERT( (pFontFamily != NULL), "ImplFontCache::Get() No logical font found!" );
+ if( pFontFamily )
+ aFontSelData.maSearchName = pFontFamily->GetSearchName();
+
+ // check if an indirectly matching logical font instance is already cached
+ FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData );
+ if( it != maFontInstanceList.end() )
+ {
+ // we have an indirect cache hit
+ pEntry = (*it).second;
+ }
+ }
+
+ PhysicalFontFace* pFontData = NULL;
+
+ if (!pEntry && pFontFamily)// no cache hit => find the best matching physical font face
+ {
+ bool bOrigWasSymbol = aFontSelData.mpFontData && aFontSelData.mpFontData->IsSymbolFont();
+ pFontData = pFontFamily->FindBestFontFace( aFontSelData );
+ aFontSelData.mpFontData = pFontData;
+ bool bNewIsSymbol = aFontSelData.mpFontData && aFontSelData.mpFontData->IsSymbolFont();
+
+ if (bNewIsSymbol != bOrigWasSymbol)
+ {
+ // it is possible, though generally unlikely, that at this point we
+ // will attempt to use a symbol font as a last-ditch fallback for a
+ // non-symbol font request or vice versa, and by changing
+ // aFontSelData.mpFontData to/from a symbol font we may now find
+ // something in the cache that can be reused which previously
+ // wasn't a candidate
+ FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData );
+ if( it != maFontInstanceList.end() )
+ pEntry = (*it).second;
+ }
+ }
+
+ if( pEntry ) // cache hit => use existing font instance
+ {
+ // increase the font instance's reference count
+ if( !pEntry->mnRefCount++ )
+ --mnRef0Count;
+ }
+
+ if (!pEntry && pFontData)// still no cache hit => create a new font instance
+ {
+ // create a new logical font instance from this physical font face
+ pEntry = pFontData->CreateFontInstance( aFontSelData );
+
+ // if we're subtituting from or to a symbol font we may need a symbol
+ // conversion table
+ if( pFontData->IsSymbolFont() || aFontSelData.IsSymbolFont() )
+ {
+ if( aFontSelData.maTargetName != aFontSelData.maSearchName )
+ pEntry->mpConversion = ConvertChar::GetRecodeData( aFontSelData.maTargetName, aFontSelData.maSearchName );
+ }
+
+#ifdef MACOSX
+ //It might be better to dig out the font version of the target font
+ //to see if it's a modern re-coded apple symbol font in case that
+ //font shows up on a different platform
+ if (!pEntry->mpConversion &&
+ aFontSelData.maTargetName.equalsIgnoreAsciiCase("symbol") &&
+ aFontSelData.maSearchName.equalsIgnoreAsciiCase("symbol"))
+ {
+ pEntry->mpConversion = ConvertChar::GetRecodeData( OUString("Symbol"), OUString("AppleSymbol") );
+ }
+#endif
+
+ // add the new entry to the cache
+ maFontInstanceList[ aFontSelData ] = pEntry;
+ }
+
+ mpFirstEntry = pEntry;
+ return pEntry;
+}
+
+ImplFontEntry* ImplFontCache::GetGlyphFallbackFont( PhysicalFontCollection* pFontCollection,
+ FontSelectPattern& rFontSelData, int nFallbackLevel, OUString& rMissingCodes )
+{
+ // get a candidate font for glyph fallback
+ // unless the previously selected font got a device specific substitution
+ // e.g. PsPrint Arial->Helvetica for udiaeresis when Helvetica doesn't support it
+ if( nFallbackLevel >= 1)
+ {
+ PhysicalFontFamily* pFallbackData = NULL;
+
+ //fdo#33898 If someone has EUDC installed then they really want that to
+ //be used as the first-choice glyph fallback seeing as it's filled with
+ //private area codes with don't make any sense in any other font so
+ //prioritise it here if it's available. Ideally we would remove from
+ //rMissingCodes all the glyphs which it is able to resolve as an
+ //optimization, but that's tricky to achieve cross-platform without
+ //sufficient heavy-weight code that's likely to undo the value of the
+ //optimization
+ if (nFallbackLevel == 1)
+ pFallbackData = pFontCollection->FindFontFamily(OUString("EUDC"));
+ if (!pFallbackData)
+ pFallbackData = pFontCollection->GetGlyphFallbackFont(rFontSelData, rMissingCodes, nFallbackLevel-1);
+ // escape when there are no font candidates
+ if( !pFallbackData )
+ return NULL;
+ // override the font name
+ rFontSelData.SetFamilyName( pFallbackData->GetFamilyName() );
+ // clear the cached normalized name
+ rFontSelData.maSearchName = "";
+ }
+
+ ImplFontEntry* pFallbackFont = GetFontEntry( pFontCollection, rFontSelData );
+ return pFallbackFont;
+}
+
+void ImplFontCache::Release( ImplFontEntry* pEntry )
+{
+ static const int FONTCACHE_MAX = 50;
+
+ DBG_ASSERT( (pEntry->mnRefCount > 0), "ImplFontCache::Release() - font refcount underflow" );
+ if( --pEntry->mnRefCount > 0 )
+ return;
+
+ if( ++mnRef0Count < FONTCACHE_MAX )
+ return;
+
+ // remove unused entries from font instance cache
+ FontInstanceList::iterator it_next = maFontInstanceList.begin();
+ while( it_next != maFontInstanceList.end() )
+ {
+ FontInstanceList::iterator it = it_next++;
+ ImplFontEntry* pFontEntry = (*it).second;
+ if( pFontEntry->mnRefCount > 0 )
+ continue;
+
+ maFontInstanceList.erase( it );
+ delete pFontEntry;
+ --mnRef0Count;
+ DBG_ASSERT( (mnRef0Count>=0), "ImplFontCache::Release() - refcount0 underflow" );
+
+ if( mpFirstEntry == pFontEntry )
+ mpFirstEntry = NULL;
+ }
+
+ DBG_ASSERT( (mnRef0Count==0), "ImplFontCache::Release() - refcount0 mismatch" );
+}
+
+void ImplFontCache::Invalidate()
+{
+ // delete unreferenced entries
+ FontInstanceList::iterator it = maFontInstanceList.begin();
+ for(; it != maFontInstanceList.end(); ++it )
+ {
+ ImplFontEntry* pFontEntry = (*it).second;
+ if( pFontEntry->mnRefCount > 0 )
+ continue;
+
+ delete pFontEntry;
+ --mnRef0Count;
+ }
+
+ // #112304# make sure the font cache is really clean
+ mpFirstEntry = NULL;
+ maFontInstanceList.clear();
+
+ DBG_ASSERT( (mnRef0Count==0), "ImplFontCache::Invalidate() - mnRef0Count non-zero" );
+}
+
+FontEmphasisMark OutputDevice::ImplGetEmphasisMarkStyle( const Font& rFont )
+{
+ FontEmphasisMark nEmphasisMark = rFont.GetEmphasisMark();
+
+ // If no Position is set, then calculate the default position, which
+ // depends on the language
+ if ( !(nEmphasisMark & (EMPHASISMARK_POS_ABOVE | EMPHASISMARK_POS_BELOW)) )
+ {
+ LanguageType eLang = rFont.GetLanguage();
+ // In Chinese Simplified the EmphasisMarks are below/left
+ if (MsLangId::isSimplifiedChinese(eLang))
+ nEmphasisMark |= EMPHASISMARK_POS_BELOW;
+ else
+ {
+ eLang = rFont.GetCJKContextLanguage();
+ // In Chinese Simplified the EmphasisMarks are below/left
+ if (MsLangId::isSimplifiedChinese(eLang))
+ nEmphasisMark |= EMPHASISMARK_POS_BELOW;
+ else
+ nEmphasisMark |= EMPHASISMARK_POS_ABOVE;
+ }
+ }
+
+ return nEmphasisMark;
+}
+
+void OutputDevice::ImplInitFontList() const
+{
+ if( !mpFontCollection->Count() )
+ {
+ if( mpGraphics || ImplGetGraphics() )
+ {
+ SAL_INFO( "vcl.gdi", "OutputDevice::ImplInitFontList()" );
+ mpGraphics->GetDevFontList( mpFontCollection );
+
+ // There is absolutely no way there should be no fonts available on the device
+ if( !mpFontCollection->Count() )
+ {
+ OUString aError( "Application error: no fonts and no vcl resource found on your system" );
+ ResMgr* pMgr = ImplGetResMgr();
+ if( pMgr )
+ {
+ OUString aResStr(ResId(SV_ACCESSERROR_NO_FONTS, *pMgr).toString());
+ if( !aResStr.isEmpty() )
+ aError = aResStr;
+ }
+ Application::Abort( aError );
+ }
+ }
+ }
+}
+
+void OutputDevice::ImplInitFont() const
+{
+ DBG_TESTSOLARMUTEX();
+
+ if (!mpFontEntry)
+ return;
+
+ if ( mbInitFont )
+ {
+ if ( meOutDevType != OUTDEV_PRINTER )
+ {
+ // decide if antialiasing is appropriate
+ bool bNonAntialiased = (GetAntialiasing() & ANTIALIASING_DISABLE_TEXT) != 0;
+ const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
+ bNonAntialiased |= ((rStyleSettings.GetDisplayOptions() & DISPLAY_OPTION_AA_DISABLE) != 0);
+ bNonAntialiased |= (int(rStyleSettings.GetAntialiasingMinPixelHeight()) > mpFontEntry->maFontSelData.mnHeight);
+ mpFontEntry->maFontSelData.mbNonAntialiased = bNonAntialiased;
+ }
+
+ // select font in the device layers
+ mpFontEntry->mnSetFontFlags = mpGraphics->SetFont( &(mpFontEntry->maFontSelData), 0 );
+ mbInitFont = false;
+ }
+}
+
+bool OutputDevice::ImplNewFont() const
+{
+ DBG_TESTSOLARMUTEX();
+
+ // get correct font list on the PDF writer if necessary
+ if( mpPDFWriter )
+ {
+ const ImplSVData* pSVData = ImplGetSVData();
+ if( mpFontCollection == pSVData->maGDIData.mpScreenFontList
+ || mpFontCache == pSVData->maGDIData.mpScreenFontCache )
+ const_cast<OutputDevice&>(*this).ImplUpdateFontData( true );
+ }
+
+ if ( !mbNewFont )
+ return true;
+
+ // we need a graphics
+ if ( !mpGraphics && !ImplGetGraphics() )
+ return false;
+ SalGraphics* pGraphics = mpGraphics;
+ ImplInitFontList();
+
+ // convert to pixel height
+ // TODO: replace integer based aSize completely with subpixel accurate type
+ float fExactHeight = ImplFloatLogicHeightToDevicePixel( static_cast<float>(maFont.GetHeight()) );
+ Size aSize = ImplLogicToDevicePixel( maFont.GetSize() );
+ if ( !aSize.Height() )
+ {
+ // use default pixel height only when logical height is zero
+ if ( maFont.GetSize().Height() )
+ aSize.Height() = 1;
+ else
+ aSize.Height() = (12*mnDPIY)/72;
+ fExactHeight = static_cast<float>(aSize.Height());
+ }
+
+ // select the default width only when logical width is zero
+ if( (0 == aSize.Width()) && (0 != maFont.GetSize().Width()) )
+ aSize.Width() = 1;
+
+ // get font entry
+ ImplFontEntry* pOldEntry = mpFontEntry;
+ mpFontEntry = mpFontCache->GetFontEntry( mpFontCollection, maFont, aSize, fExactHeight );
+ if( pOldEntry )
+ mpFontCache->Release( pOldEntry );
+
+ ImplFontEntry* pFontEntry = mpFontEntry;
+
+ if (!pFontEntry)
+ return false;
+
+ // mark when lower layers need to get involved
+ mbNewFont = false;
+ if( pFontEntry != pOldEntry )
+ mbInitFont = true;
+
+ // select font when it has not been initialized yet
+ if ( !pFontEntry->mbInit )
+ {
+ ImplInitFont();
+
+ // get metric data from device layers
+ if ( pGraphics )
+ {
+ pFontEntry->mbInit = true;
+
+ pFontEntry->maMetric.mnOrientation = sal::static_int_cast<short>(pFontEntry->maFontSelData.mnOrientation);
+ pGraphics->GetFontMetric( &(pFontEntry->maMetric) );
+
+ pFontEntry->maMetric.ImplInitTextLineSize( this );
+ pFontEntry->maMetric.ImplInitAboveTextLineSize();
+
+ pFontEntry->mnLineHeight = pFontEntry->maMetric.mnAscent + pFontEntry->maMetric.mnDescent;
+
+ if( pFontEntry->maFontSelData.mnOrientation
+ && !pFontEntry->maMetric.mnOrientation
+ && (meOutDevType != OUTDEV_PRINTER) )
+ {
+ pFontEntry->mnOwnOrientation = sal::static_int_cast<short>(pFontEntry->maFontSelData.mnOrientation);
+ pFontEntry->mnOrientation = pFontEntry->mnOwnOrientation;
+ }
+ else
+ pFontEntry->mnOrientation = pFontEntry->maMetric.mnOrientation;
+ }
+ }
+
+ // enable kerning array if requested
+ if ( maFont.GetKerning() & KERNING_FONTSPECIFIC )
+ {
+ // TODO: test if physical font supports kerning and disable if not
+ if( pFontEntry->maMetric.mbKernableFont )
+ mbKerning = true;
+ }
+ else
+ mbKerning = false;
+ if ( maFont.GetKerning() & KERNING_ASIAN )
+ mbKerning = true;
+
+ // calculate EmphasisArea
+ mnEmphasisAscent = 0;
+ mnEmphasisDescent = 0;
+ if ( maFont.GetEmphasisMark() & EMPHASISMARK_STYLE )
+ {
+ FontEmphasisMark nEmphasisMark = ImplGetEmphasisMarkStyle( maFont );
+ long nEmphasisHeight = (pFontEntry->mnLineHeight*250)/1000;
+ if ( nEmphasisHeight < 1 )
+ nEmphasisHeight = 1;
+ if ( nEmphasisMark & EMPHASISMARK_POS_BELOW )
+ mnEmphasisDescent = nEmphasisHeight;
+ else
+ mnEmphasisAscent = nEmphasisHeight;
+ }
+
+ // calculate text offset depending on TextAlignment
+ TextAlign eAlign = maFont.GetAlign();
+ if ( eAlign == ALIGN_BASELINE )
+ {
+ mnTextOffX = 0;
+ mnTextOffY = 0;
+ }
+ else if ( eAlign == ALIGN_TOP )
+ {
+ mnTextOffX = 0;
+ mnTextOffY = +pFontEntry->maMetric.mnAscent + mnEmphasisAscent;
+ if ( pFontEntry->mnOrientation )
+ ImplRotatePos( 0, 0, mnTextOffX, mnTextOffY, pFontEntry->mnOrientation );
+ }
+ else // eAlign == ALIGN_BOTTOM
+ {
+ mnTextOffX = 0;
+ mnTextOffY = -pFontEntry->maMetric.mnDescent + mnEmphasisDescent;
+ if ( pFontEntry->mnOrientation )
+ ImplRotatePos( 0, 0, mnTextOffX, mnTextOffY, pFontEntry->mnOrientation );
+ }
+
+ mbTextLines = ((maFont.GetUnderline() != UNDERLINE_NONE) && (maFont.GetUnderline() != UNDERLINE_DONTKNOW)) ||
+ ((maFont.GetOverline() != UNDERLINE_NONE) && (maFont.GetOverline() != UNDERLINE_DONTKNOW)) ||
+ ((maFont.GetStrikeout() != STRIKEOUT_NONE) && (maFont.GetStrikeout() != STRIKEOUT_DONTKNOW));
+ mbTextSpecial = maFont.IsShadow() || maFont.IsOutline() ||
+ (maFont.GetRelief() != RELIEF_NONE);
+
+ // #95414# fix for OLE objects which use scale factors very creatively
+ if( mbMap && !aSize.Width() )
+ {
+ int nOrigWidth = pFontEntry->maMetric.mnWidth;
+ float fStretch = (float)maMapRes.mnMapScNumX * maMapRes.mnMapScDenomY;
+ fStretch /= (float)maMapRes.mnMapScNumY * maMapRes.mnMapScDenomX;
+ int nNewWidth = (int)(nOrigWidth * fStretch + 0.5);
+ if( (nNewWidth != nOrigWidth) && (nNewWidth != 0) )
+ {
+ Size aOrigSize = maFont.GetSize();
+ const_cast<Font&>(maFont).SetSize( Size( nNewWidth, aSize.Height() ) );
+ mbMap = false;
+ mbNewFont = true;
+ ImplNewFont(); // recurse once using stretched width
+ mbMap = true;
+ const_cast<Font&>(maFont).SetSize( aOrigSize );
+ }
+ }
+
+ return true;
+}
+
+bool ImplFontAttributes::operator==(const ImplFontAttributes& rOther) const
+{
+ if (maName != rOther.maName)
+ return false;
+
+ if (maStyleName != rOther.maStyleName)
+ return false;
+
+ if (meWeight != rOther.meWeight)
+ return false;
+
+ if (meItalic != rOther.meItalic)
+ return false;
+
+ if (meFamily != rOther.meFamily)
+ return false;
+
+ if (mePitch != rOther.mePitch)
+ return false;
+
+ if (meWidthType != rOther.meWidthType)
+ return false;
+
+ if (mbSymbolFlag != rOther.mbSymbolFlag)
+ return false;
+
+ return true;
+}
+
+ImplFontMetricData::ImplFontMetricData( const FontSelectPattern& rFontSelData )
+ : ImplFontAttributes( rFontSelData )
+ , mnWidth ( rFontSelData.mnWidth)
+ , mnOrientation( (short)(rFontSelData.mnOrientation))
+ , mnAscent( 0 )
+ , mnDescent( 0 )
+ , mnIntLeading( 0 )
+ , mnExtLeading( 0 )
+ , mnSlant( 0 )
+ , mnMinKashida( 0 )
+ , mnUnderlineSize( 0 )
+ , mnUnderlineOffset( 0 )
+ , mnBUnderlineSize( 0 )
+ , mnBUnderlineOffset( 0 )
+ , mnDUnderlineSize( 0 )
+ , mnDUnderlineOffset1( 0 )
+ , mnDUnderlineOffset2( 0 )
+ , mnWUnderlineSize( 0 )
+ , mnWUnderlineOffset( 0 )
+ , mnAboveUnderlineSize( 0 )
+ , mnAboveUnderlineOffset( 0 )
+ , mnAboveBUnderlineSize( 0 )
+ , mnAboveBUnderlineOffset( 0 )
+ , mnAboveDUnderlineSize( 0 )
+ , mnAboveDUnderlineOffset1( 0 )
+ , mnAboveDUnderlineOffset2( 0 )
+ , mnAboveWUnderlineSize( 0 )
+ , mnAboveWUnderlineOffset( 0 )
+ , mnStrikeoutSize( 0 )
+ , mnStrikeoutOffset( 0 )
+ , mnBStrikeoutSize( 0 )
+ , mnBStrikeoutOffset( 0 )
+ , mnDStrikeoutSize( 0 )
+ , mnDStrikeoutOffset1( 0 )
+ , mnDStrikeoutOffset2( 0 )
+{
+ // intialize the used font name
+ if( rFontSelData.mpFontData )
+ {
+ SetFamilyName( rFontSelData.mpFontData->GetFamilyName() );
+ SetStyleName( rFontSelData.mpFontData->GetStyleName() );
+ mbDevice = rFontSelData.mpFontData->mbDevice;
+ mbKernableFont = true;
+ }
+ else
+ {
+ sal_Int32 nTokenPos = 0;
+ SetFamilyName( GetNextFontToken( rFontSelData.GetFamilyName(), nTokenPos ) );
+ SetStyleName( rFontSelData.GetStyleName() );
+ mbDevice = false;
+ mbKernableFont = false;
+ }
+}
+
+void ImplFontMetricData::ImplInitTextLineSize( const OutputDevice* pDev )
+{
+ long nDescent = mnDescent;
+ if ( nDescent <= 0 )
+ {
+ nDescent = mnAscent / 10;
+ if ( !nDescent )
+ nDescent = 1;
+ }
+
+ // #i55341# for some fonts it is not a good idea to calculate
+ // their text line metrics from the real font descent
+ // => work around this problem just for these fonts
+ if( 3*nDescent > mnAscent )
+ nDescent = mnAscent / 3;
+
+ long nLineHeight = ((nDescent*25)+50) / 100;
+ if ( !nLineHeight )
+ nLineHeight = 1;
+ long nLineHeight2 = nLineHeight / 2;
+ if ( !nLineHeight2 )
+ nLineHeight2 = 1;
+
+ long nBLineHeight = ((nDescent*50)+50) / 100;
+ if ( nBLineHeight == nLineHeight )
+ nBLineHeight++;
+ long nBLineHeight2 = nBLineHeight/2;
+ if ( !nBLineHeight2 )
+ nBLineHeight2 = 1;
+
+ long n2LineHeight = ((nDescent*16)+50) / 100;
+ if ( !n2LineHeight )
+ n2LineHeight = 1;
+ long n2LineDY = n2LineHeight;
+ /* #117909#
+ * add some pixels to minimum double line distance on higher resolution devices
+ */
+ long nMin2LineDY = 1 + pDev->ImplGetDPIY()/150;
+ if ( n2LineDY < nMin2LineDY )
+ n2LineDY = nMin2LineDY;
+ long n2LineDY2 = n2LineDY/2;
+ if ( !n2LineDY2 )
+ n2LineDY2 = 1;
+
+ long nUnderlineOffset = mnDescent/2 + 1;
+ long nStrikeoutOffset = -((mnAscent - mnIntLeading) / 3);
+
+ mnUnderlineSize = nLineHeight;
+ mnUnderlineOffset = nUnderlineOffset - nLineHeight2;
+
+ mnBUnderlineSize = nBLineHeight;
+ mnBUnderlineOffset = nUnderlineOffset - nBLineHeight2;
+
+ mnDUnderlineSize = n2LineHeight;
+ mnDUnderlineOffset1 = nUnderlineOffset - n2LineDY2 - n2LineHeight;
+ mnDUnderlineOffset2 = mnDUnderlineOffset1 + n2LineDY + n2LineHeight;
+
+ long nWCalcSize = mnDescent;
+ if ( nWCalcSize < 6 )
+ {
+ if ( (nWCalcSize == 1) || (nWCalcSize == 2) )
+ mnWUnderlineSize = nWCalcSize;
+ else
+ mnWUnderlineSize = 3;
+ }
+ else
+ mnWUnderlineSize = ((nWCalcSize*50)+50) / 100;
+
+ // #109280# the following line assures that wavelnes are never placed below the descent, however
+ // for most fonts the waveline then is drawn into the text, so we better keep the old solution
+ // pFontEntry->maMetric.mnWUnderlineOffset = pFontEntry->maMetric.mnDescent + 1 - pFontEntry->maMetric.mnWUnderlineSize;
+ mnWUnderlineOffset = nUnderlineOffset;
+
+ mnStrikeoutSize = nLineHeight;
+ mnStrikeoutOffset = nStrikeoutOffset - nLineHeight2;
+
+ mnBStrikeoutSize = nBLineHeight;
+ mnBStrikeoutOffset = nStrikeoutOffset - nBLineHeight2;
+
+ mnDStrikeoutSize = n2LineHeight;
+ mnDStrikeoutOffset1 = nStrikeoutOffset - n2LineDY2 - n2LineHeight;
+ mnDStrikeoutOffset2 = mnDStrikeoutOffset1 + n2LineDY + n2LineHeight;
+}
+
+void ImplFontMetricData::ImplInitAboveTextLineSize()
+{
+ long nIntLeading = mnIntLeading;
+ // TODO: assess usage of nLeading below (changed in extleading CWS)
+ // if no leading is available, we assume 15% of the ascent
+ if ( nIntLeading <= 0 )
+ {
+ nIntLeading = mnAscent*15/100;
+ if ( !nIntLeading )
+ nIntLeading = 1;
+ }
+
+ long nLineHeight = ((nIntLeading*25)+50) / 100;
+ if ( !nLineHeight )
+ nLineHeight = 1;
+
+ long nBLineHeight = ((nIntLeading*50)+50) / 100;
+ if ( nBLineHeight == nLineHeight )
+ nBLineHeight++;
+
+ long n2LineHeight = ((nIntLeading*16)+50) / 100;
+ if ( !n2LineHeight )
+ n2LineHeight = 1;
+
+ long nCeiling = -mnAscent;
+
+ mnAboveUnderlineSize = nLineHeight;
+ mnAboveUnderlineOffset = nCeiling + (nIntLeading - nLineHeight + 1) / 2;
+
+ mnAboveBUnderlineSize = nBLineHeight;
+ mnAboveBUnderlineOffset = nCeiling + (nIntLeading - nBLineHeight + 1) / 2;
+
+ mnAboveDUnderlineSize = n2LineHeight;
+ mnAboveDUnderlineOffset1 = nCeiling + (nIntLeading - 3*n2LineHeight + 1) / 2;
+ mnAboveDUnderlineOffset2 = nCeiling + (nIntLeading + n2LineHeight + 1) / 2;
+
+ long nWCalcSize = nIntLeading;
+ if ( nWCalcSize < 6 )
+ {
+ if ( (nWCalcSize == 1) || (nWCalcSize == 2) )
+ mnAboveWUnderlineSize = nWCalcSize;
+ else
+ mnAboveWUnderlineSize = 3;
+ }
+ else
+ mnAboveWUnderlineSize = ((nWCalcSize*50)+50) / 100;
+
+ mnAboveWUnderlineOffset = nCeiling + (nIntLeading + 1) / 2;
+}
+
+void OutputDevice::ImplGetEmphasisMark( PolyPolygon& rPolyPoly, bool& rPolyLine,
+ Rectangle& rRect1, Rectangle& rRect2,
+ long& rYOff, long& rWidth,
+ FontEmphasisMark eEmphasis,
+ long nHeight, short /*nOrient*/ )
+{
+ static const sal_uInt8 aAccentPolyFlags[24] =
+ {
+ 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 2, 0, 2, 2
+ };
+
+ static const long aAccentPos[48] =
+ {
+ 78, 0,
+ 348, 79,
+ 599, 235,
+ 843, 469,
+ 938, 574,
+ 990, 669,
+ 990, 773,
+ 990, 843,
+ 964, 895,
+ 921, 947,
+ 886, 982,
+ 860, 999,
+ 825, 999,
+ 764, 999,
+ 721, 964,
+ 686, 895,
+ 625, 791,
+ 556, 660,
+ 469, 504,
+ 400, 400,
+ 261, 252,
+ 61, 61,
+ 0, 27,
+ 9, 0
+ };
+
+ rWidth = 0;
+ rYOff = 0;
+ rPolyLine = false;
+
+ if ( !nHeight )
+ return;
+
+ FontEmphasisMark nEmphasisStyle = eEmphasis & EMPHASISMARK_STYLE;
+ long nDotSize = 0;
+ switch ( nEmphasisStyle )
+ {
+ case EMPHASISMARK_DOT:
+ // Dot has 55% of the height
+ nDotSize = (nHeight*550)/1000;
+ if ( !nDotSize )
+ nDotSize = 1;
+ if ( nDotSize <= 2 )
+ rRect1 = Rectangle( Point(), Size( nDotSize, nDotSize ) );
+ else
+ {
+ long nRad = nDotSize/2;
+ Polygon aPoly( Point( nRad, nRad ), nRad, nRad );
+ rPolyPoly.Insert( aPoly );
+ }
+ rYOff = ((nHeight*250)/1000)/2; // Center to the another EmphasisMarks
+ rWidth = nDotSize;
+ break;
+
+ case EMPHASISMARK_CIRCLE:
+ // Dot has 80% of the height
+ nDotSize = (nHeight*800)/1000;
+ if ( !nDotSize )
+ nDotSize = 1;
+ if ( nDotSize <= 2 )
+ rRect1 = Rectangle( Point(), Size( nDotSize, nDotSize ) );
+ else
+ {
+ long nRad = nDotSize/2;
+ Polygon aPoly( Point( nRad, nRad ), nRad, nRad );
+ rPolyPoly.Insert( aPoly );
+ // BorderWidth is 15%
+ long nBorder = (nDotSize*150)/1000;
+ if ( nBorder <= 1 )
+ rPolyLine = true;
+ else
+ {
+ Polygon aPoly2( Point( nRad, nRad ),
+ nRad-nBorder, nRad-nBorder );
+ rPolyPoly.Insert( aPoly2 );
+ }
+ }
+ rWidth = nDotSize;
+ break;
+
+ case EMPHASISMARK_DISC:
+ // Dot has 80% of the height
+ nDotSize = (nHeight*800)/1000;
+ if ( !nDotSize )
+ nDotSize = 1;
+ if ( nDotSize <= 2 )
+ rRect1 = Rectangle( Point(), Size( nDotSize, nDotSize ) );
+ else
+ {
+ long nRad = nDotSize/2;
+ Polygon aPoly( Point( nRad, nRad ), nRad, nRad );
+ rPolyPoly.Insert( aPoly );
+ }
+ rWidth = nDotSize;
+ break;
+
+ case EMPHASISMARK_ACCENT:
+ // Dot has 80% of the height
+ nDotSize = (nHeight*800)/1000;
+ if ( !nDotSize )
+ nDotSize = 1;
+ if ( nDotSize <= 2 )
+ {
+ if ( nDotSize == 1 )
+ {
+ rRect1 = Rectangle( Point(), Size( nDotSize, nDotSize ) );
+ rWidth = nDotSize;
+ }
+ else
+ {
+ rRect1 = Rectangle( Point(), Size( 1, 1 ) );
+ rRect2 = Rectangle( Point( 1, 1 ), Size( 1, 1 ) );
+ }
+ }
+ else
+ {
+ Polygon aPoly( sizeof( aAccentPos ) / sizeof( long ) / 2,
+ (const Point*)aAccentPos,
+ aAccentPolyFlags );
+ double dScale = ((double)nDotSize)/1000.0;
+ aPoly.Scale( dScale, dScale );
+ Polygon aTemp;
+ aPoly.AdaptiveSubdivide( aTemp );
+ Rectangle aBoundRect = aTemp.GetBoundRect();
+ rWidth = aBoundRect.GetWidth();
+ nDotSize = aBoundRect.GetHeight();
+ rPolyPoly.Insert( aTemp );
+ }
+ break;
+ }
+
+ // calculate position
+ long nOffY = 1+(mnDPIY/300); // one visible pixel space
+ long nSpaceY = nHeight-nDotSize;
+ if ( nSpaceY >= nOffY*2 )
+ rYOff += nOffY;
+ if ( !(eEmphasis & EMPHASISMARK_POS_BELOW) )
+ rYOff += nDotSize;
+}
+
+void OutputDevice::ImplDrawEmphasisMark( long nBaseX, long nX, long nY,
+ const PolyPolygon& rPolyPoly, bool bPolyLine,
+ const Rectangle& rRect1, const Rectangle& rRect2 )
+{
+ if( IsRTLEnabled() )
+ // --- RTL --- mirror at basex
+ nX = nBaseX - (nX - nBaseX - 1);
+
+ nX -= mnOutOffX;
+ nY -= mnOutOffY;
+
+ if ( rPolyPoly.Count() )
+ {
+ if ( bPolyLine )
+ {
+ Polygon aPoly = rPolyPoly.GetObject( 0 );
+ aPoly.Move( nX, nY );
+ DrawPolyLine( aPoly );
+ }
+ else
+ {
+ PolyPolygon aPolyPoly = rPolyPoly;
+ aPolyPoly.Move( nX, nY );
+ DrawPolyPolygon( aPolyPoly );
+ }
+ }
+
+ if ( !rRect1.IsEmpty() )
+ {
+ Rectangle aRect( Point( nX+rRect1.Left(),
+ nY+rRect1.Top() ), rRect1.GetSize() );
+ DrawRect( aRect );
+ }
+
+ if ( !rRect2.IsEmpty() )
+ {
+ Rectangle aRect( Point( nX+rRect2.Left(),
+ nY+rRect2.Top() ), rRect2.GetSize() );
+
+ DrawRect( aRect );
+ }
+}
+
+void OutputDevice::ImplDrawEmphasisMarks( SalLayout& rSalLayout )
+{
+ Color aOldLineColor = GetLineColor();
+ Color aOldFillColor = GetFillColor();
+ bool bOldMap = mbMap;
+ GDIMetaFile* pOldMetaFile = mpMetaFile;
+ mpMetaFile = NULL;
+ EnableMapMode( false );
+
+ FontEmphasisMark nEmphasisMark = ImplGetEmphasisMarkStyle( maFont );
+ PolyPolygon aPolyPoly;
+ Rectangle aRect1;
+ Rectangle aRect2;
+ long nEmphasisYOff;
+ long nEmphasisWidth;
+ long nEmphasisHeight;
+ bool bPolyLine;
+
+ if ( nEmphasisMark & EMPHASISMARK_POS_BELOW )
+ nEmphasisHeight = mnEmphasisDescent;
+ else
+ nEmphasisHeight = mnEmphasisAscent;
+
+ ImplGetEmphasisMark( aPolyPoly, bPolyLine,
+ aRect1, aRect2,
+ nEmphasisYOff, nEmphasisWidth,
+ nEmphasisMark,
+ nEmphasisHeight, mpFontEntry->mnOrientation );
+
+ if ( bPolyLine )
+ {
+ SetLineColor( GetTextColor() );
+ SetFillColor();
+ }
+ else
+ {
+ SetLineColor();
+ SetFillColor( GetTextColor() );
+ }
+
+ Point aOffset = Point(0,0);
+
+ if ( nEmphasisMark & EMPHASISMARK_POS_BELOW )
+ aOffset.Y() += mpFontEntry->maMetric.mnDescent + nEmphasisYOff;
+ else
+ aOffset.Y() -= mpFontEntry->maMetric.mnAscent + nEmphasisYOff;
+
+ long nEmphasisWidth2 = nEmphasisWidth / 2;
+ long nEmphasisHeight2 = nEmphasisHeight / 2;
+ aOffset += Point( nEmphasisWidth2, nEmphasisHeight2 );
+
+ Point aOutPoint;
+ Rectangle aRectangle;
+ for( int nStart = 0;;)
+ {
+ sal_GlyphId aGlyphId;
+ if( !rSalLayout.GetNextGlyphs( 1, &aGlyphId, aOutPoint, nStart ) )
+ break;
+
+ if( !mpGraphics->GetGlyphBoundRect( aGlyphId, aRectangle ) )
+ continue;
+
+ if( !rSalLayout.IsSpacingGlyph( aGlyphId ) )
+ {
+ Point aAdjPoint = aOffset;
+ aAdjPoint.X() += aRectangle.Left() + (aRectangle.GetWidth() - nEmphasisWidth) / 2;
+ if ( mpFontEntry->mnOrientation )
+ ImplRotatePos( 0, 0, aAdjPoint.X(), aAdjPoint.Y(), mpFontEntry->mnOrientation );
+ aOutPoint += aAdjPoint;
+ aOutPoint -= Point( nEmphasisWidth2, nEmphasisHeight2 );
+ ImplDrawEmphasisMark( rSalLayout.DrawBase().X(),
+ aOutPoint.X(), aOutPoint.Y(),
+ aPolyPoly, bPolyLine, aRect1, aRect2 );
+ }
+ }
+
+ SetLineColor( aOldLineColor );
+ SetFillColor( aOldFillColor );
+ EnableMapMode( bOldMap );
+ mpMetaFile = pOldMetaFile;
+}
+
+void OutputDevice::SetFont( const Font& rNewFont )
+{
+
+ Font aFont( rNewFont );
+ aFont.SetLanguage(rNewFont.GetLanguage());
+ if ( mnDrawMode & (DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT | DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT | DRAWMODE_SETTINGSTEXT |
+ DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL | DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
+ DRAWMODE_GHOSTEDFILL | DRAWMODE_SETTINGSFILL ) )
+ {
+ Color aTextColor( aFont.GetColor() );
+
+ if ( mnDrawMode & DRAWMODE_BLACKTEXT )
+ aTextColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITETEXT )
+ aTextColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
+ {
+ const sal_uInt8 cLum = aTextColor.GetLuminance();
+ aTextColor = Color( cLum, cLum, cLum );
+ }
+ else if ( mnDrawMode & DRAWMODE_SETTINGSTEXT )
+ aTextColor = GetSettings().GetStyleSettings().GetFontColor();
+
+ if ( mnDrawMode & DRAWMODE_GHOSTEDTEXT )
+ {
+ aTextColor = Color( (aTextColor.GetRed() >> 1 ) | 0x80,
+ (aTextColor.GetGreen() >> 1 ) | 0x80,
+ (aTextColor.GetBlue() >> 1 ) | 0x80 );
+ }
+
+ aFont.SetColor( aTextColor );
+
+ bool bTransFill = aFont.IsTransparent();
+ if ( !bTransFill )
+ {
+ Color aTextFillColor( aFont.GetFillColor() );
+
+ if ( mnDrawMode & DRAWMODE_BLACKFILL )
+ aTextFillColor = Color( COL_BLACK );
+ else if ( mnDrawMode & DRAWMODE_WHITEFILL )
+ aTextFillColor = Color( COL_WHITE );
+ else if ( mnDrawMode & DRAWMODE_GRAYFILL )
+ {
+ const sal_uInt8 cLum = aTextFillColor.GetLuminance();
+ aTextFillColor = Color( cLum, cLum, cLum );
+ }
+ else if( mnDrawMode & DRAWMODE_SETTINGSFILL )
+ aTextFillColor = GetSettings().GetStyleSettings().GetWindowColor();
+ else if ( mnDrawMode & DRAWMODE_NOFILL )
+ {
+ aTextFillColor = Color( COL_TRANSPARENT );
+ bTransFill = true;
+ }
+
+ if ( !bTransFill && (mnDrawMode & DRAWMODE_GHOSTEDFILL) )
+ {
+ aTextFillColor = Color( (aTextFillColor.GetRed() >> 1) | 0x80,
+ (aTextFillColor.GetGreen() >> 1) | 0x80,
+ (aTextFillColor.GetBlue() >> 1) | 0x80 );
+ }
+
+ aFont.SetFillColor( aTextFillColor );
+ }
+ }
+
+ if ( mpMetaFile )
+ {
+ mpMetaFile->AddAction( new MetaFontAction( aFont ) );
+ // the color and alignment actions don't belong here
+ // TODO: get rid of them without breaking anything...
+ mpMetaFile->AddAction( new MetaTextAlignAction( aFont.GetAlign() ) );
+ mpMetaFile->AddAction( new MetaTextFillColorAction( aFont.GetFillColor(), !aFont.IsTransparent() ) );
+ }
+
+ if ( !maFont.IsSameInstance( aFont ) )
+ {
+ // Optimization MT/HDU: COL_TRANSPARENT means SetFont should ignore the font color,
+ // because SetTextColor() is used for this.
+ // #i28759# maTextColor might have been changed behind our back, commit then, too.
+ if( aFont.GetColor() != COL_TRANSPARENT
+ && (aFont.GetColor() != maFont.GetColor() || aFont.GetColor() != maTextColor ) )
+ {
+ maTextColor = aFont.GetColor();
+ mbInitTextColor = true;
+ if( mpMetaFile )
+ mpMetaFile->AddAction( new MetaTextColorAction( aFont.GetColor() ) );
+ }
+ maFont = aFont;
+ mbNewFont = true;
+
+ if( mpAlphaVDev )
+ {
+ // #i30463#
+ // Since SetFont might change the text color, apply that only
+ // selectively to alpha vdev (which normally paints opaque text
+ // with COL_BLACK)
+ if( aFont.GetColor() != COL_TRANSPARENT )
+ {
+ mpAlphaVDev->SetTextColor( COL_BLACK );
+ aFont.SetColor( COL_TRANSPARENT );
+ }
+
+ mpAlphaVDev->SetFont( aFont );
+ }
+ }
+}
+
+SalLayout* OutputDevice::getFallbackFont(ImplFontEntry &rFallbackFont,
+ FontSelectPattern &rFontSelData, int nFallbackLevel,
+ ImplLayoutArgs& rLayoutArgs) const
+{
+ rFallbackFont.mnSetFontFlags = mpGraphics->SetFont( &rFontSelData, nFallbackLevel );
+
+ rLayoutArgs.ResetPos();
+ SalLayout* pFallback = mpGraphics->GetTextLayout( rLayoutArgs, nFallbackLevel );
+
+ if (!pFallback)
+ return NULL;
+
+ if (!pFallback->LayoutText(rLayoutArgs))
+ {
+ // there is no need for a font that couldn't resolve anything
+ pFallback->Release();
+ return NULL;
+ }
+
+ pFallback->AdjustLayout( rLayoutArgs );
+
+ return pFallback;
+}
+
+SalLayout* OutputDevice::ImplGlyphFallbackLayout( SalLayout* pSalLayout, ImplLayoutArgs& rLayoutArgs ) const
+{
+ // prepare multi level glyph fallback
+ MultiSalLayout* pMultiSalLayout = NULL;
+ ImplLayoutRuns aLayoutRuns = rLayoutArgs.maRuns;
+ rLayoutArgs.PrepareFallback();
+ rLayoutArgs.mnFlags |= SAL_LAYOUT_FOR_FALLBACK;
+
+ // get list of unicodes that need glyph fallback
+ int nCharPos = -1;
+ bool bRTL = false;
+ OUStringBuffer aMissingCodeBuf;
+ while( rLayoutArgs.GetNextPos( &nCharPos, &bRTL) )
+ aMissingCodeBuf.append( rLayoutArgs.mpStr[ nCharPos ] );
+ rLayoutArgs.ResetPos();
+ OUString aMissingCodes = aMissingCodeBuf.makeStringAndClear();
+
+ FontSelectPattern aFontSelData = mpFontEntry->maFontSelData;
+
+ // try if fallback fonts support the missing unicodes
+ for( int nFallbackLevel = 1; nFallbackLevel < MAX_FALLBACK; ++nFallbackLevel )
+ {
+ // find a font family suited for glyph fallback
+#ifndef FONTFALLBACK_HOOKS_DISABLED
+ // GetGlyphFallbackFont() needs a valid aFontSelData.mpFontEntry
+ // if the system-specific glyph fallback is active
+ aFontSelData.mpFontEntry = mpFontEntry; // reset the fontentry to base-level
+#endif
+ ImplFontEntry* pFallbackFont = mpFontCache->GetGlyphFallbackFont( mpFontCollection,
+ aFontSelData, nFallbackLevel, aMissingCodes );
+ if( !pFallbackFont )
+ break;
+
+ aFontSelData.mpFontEntry = pFallbackFont;
+ aFontSelData.mpFontData = pFallbackFont->maFontSelData.mpFontData;
+ if( mpFontEntry && nFallbackLevel < MAX_FALLBACK-1)
+ {
+ // ignore fallback font if it is the same as the original font
+ if( mpFontEntry->maFontSelData.mpFontData == aFontSelData.mpFontData )
+ {
+ mpFontCache->Release( pFallbackFont );
+ continue;
+ }
+ }
+
+ // create and add glyph fallback layout to multilayout
+ SalLayout* pFallback = getFallbackFont(*pFallbackFont, aFontSelData,
+ nFallbackLevel, rLayoutArgs);
+ if (pFallback)
+ {
+ if( !pMultiSalLayout )
+ pMultiSalLayout = new MultiSalLayout( *pSalLayout );
+ pMultiSalLayout->AddFallback( *pFallback,
+ rLayoutArgs.maRuns, aFontSelData.mpFontData );
+ if (nFallbackLevel == MAX_FALLBACK-1)
+ pMultiSalLayout->SetInComplete();
+ }
+
+ mpFontCache->Release( pFallbackFont );
+
+ // break when this fallback was sufficient
+ if( !rLayoutArgs.PrepareFallback() )
+ break;
+ }
+
+ if( pMultiSalLayout && pMultiSalLayout->LayoutText( rLayoutArgs ) )
+ pSalLayout = pMultiSalLayout;
+
+ // restore orig font settings
+ pSalLayout->InitFont();
+ rLayoutArgs.maRuns = aLayoutRuns;
+
+ return pSalLayout;
+}
+
+int OutputDevice::GetDevFontCount() const
+{
+
+ if( !mpGetDevFontList )
+ mpGetDevFontList = mpFontCollection->GetDevFontList();
+ return mpGetDevFontList->Count();
+}
+
+FontInfo OutputDevice::GetDevFont( int nDevFontIndex ) const
+{
+
+ FontInfo aFontInfo;
+
+ ImplInitFontList();
+
+ int nCount = GetDevFontCount();
+ if( nDevFontIndex < nCount )
+ {
+ const PhysicalFontFace& rData = *mpGetDevFontList->Get( nDevFontIndex );
+ aFontInfo.SetName( rData.GetFamilyName() );
+ aFontInfo.SetStyleName( rData.GetStyleName() );
+ aFontInfo.SetCharSet( rData.IsSymbolFont() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
+ aFontInfo.SetFamily( rData.GetFamilyType() );
+ aFontInfo.SetPitch( rData.GetPitch() );
+ aFontInfo.SetWeight( rData.GetWeight() );
+ aFontInfo.SetItalic( rData.GetSlant() );
+ aFontInfo.SetWidthType( rData.GetWidthType() );
+ if( rData.IsScalable() )
+ aFontInfo.mpImplMetric->mnMiscFlags |= ImplFontMetric::SCALABLE_FLAG;
+ if( rData.mbDevice )
+ aFontInfo.mpImplMetric->mnMiscFlags |= ImplFontMetric::DEVICE_FLAG;
+ }
+
+ return aFontInfo;
+}
+
+bool OutputDevice::AddTempDevFont( const OUString& rFileURL, const OUString& rFontName )
+{
+
+ ImplInitFontList();
+
+ if( !mpGraphics && !ImplGetGraphics() )
+ return false;
+
+ bool bRC = mpGraphics->AddTempDevFont( mpFontCollection, rFileURL, rFontName );
+ if( !bRC )
+ return false;
+
+ if( mpAlphaVDev )
+ mpAlphaVDev->AddTempDevFont( rFileURL, rFontName );
+
+ mpFontCache->Invalidate();
+ return true;
+}
+
+int OutputDevice::GetDevFontSizeCount( const Font& rFont ) const
+{
+
+ delete mpGetDevSizeList;
+
+ ImplInitFontList();
+ mpGetDevSizeList = mpFontCollection->GetDevSizeList( rFont.GetName() );
+ return mpGetDevSizeList->Count();
+}
+
+Size OutputDevice::GetDevFontSize( const Font& rFont, int nSizeIndex ) const
+{
+
+ // check range
+ int nCount = GetDevFontSizeCount( rFont );
+ if ( nSizeIndex >= nCount )
+ return Size();
+
+ // when mapping is enabled round to .5 points
+ Size aSize( 0, mpGetDevSizeList->Get( nSizeIndex ) );
+ if ( mbMap )
+ {
+ aSize.Height() *= 10;
+ MapMode aMap( MAP_10TH_INCH, Point(), Fraction( 1, 72 ), Fraction( 1, 72 ) );
+ aSize = PixelToLogic( aSize, aMap );
+ aSize.Height() += 5;
+ aSize.Height() /= 10;
+ long nRound = aSize.Height() % 5;
+ if ( nRound >= 3 )
+ aSize.Height() += (5-nRound);
+ else
+ aSize.Height() -= nRound;
+ aSize.Height() *= 10;
+ aSize = LogicToPixel( aSize, aMap );
+ aSize = PixelToLogic( aSize );
+ aSize.Height() += 5;
+ aSize.Height() /= 10;
+ }
+ return aSize;
+}
+
+bool OutputDevice::IsFontAvailable( const OUString& rFontName ) const
+{
+
+ PhysicalFontFamily* pFound = mpFontCollection->FindFontFamily( rFontName );
+ return (pFound != NULL);
+}
+
+FontMetric OutputDevice::GetFontMetric() const
+{
+
+ FontMetric aMetric;
+ if( mbNewFont && !ImplNewFont() )
+ return aMetric;
+
+ ImplFontEntry* pEntry = mpFontEntry;
+ ImplFontMetricData* pMetric = &(pEntry->maMetric);
+
+ // prepare metric
+ aMetric.Font::operator=( maFont );
+
+ // set aMetric with info from font
+ aMetric.SetName( maFont.GetName() );
+ aMetric.SetStyleName( pMetric->GetStyleName() );
+ aMetric.SetSize( PixelToLogic( Size( pMetric->mnWidth, pMetric->mnAscent+pMetric->mnDescent-pMetric->mnIntLeading ) ) );
+ aMetric.SetCharSet( pMetric->IsSymbolFont() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
+ aMetric.SetFamily( pMetric->GetFamilyType() );
+ aMetric.SetPitch( pMetric->GetPitch() );
+ aMetric.SetWeight( pMetric->GetWeight() );
+ aMetric.SetItalic( pMetric->GetSlant() );
+ aMetric.SetWidthType( pMetric->GetWidthType() );
+ if ( pEntry->mnOwnOrientation )
+ aMetric.SetOrientation( pEntry->mnOwnOrientation );
+ else
+ aMetric.SetOrientation( pMetric->mnOrientation );
+ if( !pEntry->maMetric.mbKernableFont )
+ aMetric.SetKerning( maFont.GetKerning() & ~KERNING_FONTSPECIFIC );
+
+ // set remaining metric fields
+ aMetric.mpImplMetric->mnMiscFlags = 0;
+ if( pMetric->mbDevice )
+ aMetric.mpImplMetric->mnMiscFlags |= ImplFontMetric::DEVICE_FLAG;
+ if( pMetric->mbScalableFont )
+ aMetric.mpImplMetric->mnMiscFlags |= ImplFontMetric::SCALABLE_FLAG;
+ aMetric.mpImplMetric->mnAscent = ImplDevicePixelToLogicHeight( pMetric->mnAscent+mnEmphasisAscent );
+ aMetric.mpImplMetric->mnDescent = ImplDevicePixelToLogicHeight( pMetric->mnDescent+mnEmphasisDescent );
+ aMetric.mpImplMetric->mnIntLeading = ImplDevicePixelToLogicHeight( pMetric->mnIntLeading+mnEmphasisAscent );
+ aMetric.mpImplMetric->mnExtLeading = ImplDevicePixelToLogicHeight( pMetric->mnExtLeading );
+ aMetric.mpImplMetric->mnLineHeight = ImplDevicePixelToLogicHeight( pMetric->mnAscent+pMetric->mnDescent+mnEmphasisAscent+mnEmphasisDescent );
+ aMetric.mpImplMetric->mnSlant = ImplDevicePixelToLogicHeight( pMetric->mnSlant );
+
+#ifdef UNX
+ // backwards compatible line metrics after fixing #i60945#
+ if( (meOutDevType == OUTDEV_VIRDEV)
+ && static_cast<const VirtualDevice*>(this)->ForceZeroExtleadBug() )
+ aMetric.mpImplMetric->mnExtLeading = 0;
+#endif
+
+ return aMetric;
+}
+
+FontMetric OutputDevice::GetFontMetric( const Font& rFont ) const
+{
+ // select font, query metrics, select original font again
+ Font aOldFont = GetFont();
+ const_cast<OutputDevice*>(this)->SetFont( rFont );
+ FontMetric aMetric( GetFontMetric() );
+ const_cast<OutputDevice*>(this)->SetFont( aOldFont );
+ return aMetric;
+}
+
+/** OutputDevice::GetSysFontData
+ *
+ * @param nFallbacklevel Fallback font level (0 = best matching font)
+ *
+ * Retrieve detailed font information in platform independent structure
+ *
+ * @return SystemFontData
+ **/
+SystemFontData OutputDevice::GetSysFontData(int nFallbacklevel) const
+{
+ SystemFontData aSysFontData;
+ aSysFontData.nSize = sizeof(aSysFontData);
+
+ if (!mpGraphics) ImplGetGraphics();
+ if (mpGraphics) aSysFontData = mpGraphics->GetSysFontData(nFallbacklevel);
+
+ return aSysFontData;
+}
+
+long OutputDevice::GetMinKashida() const
+{
+ if( mbNewFont && !ImplNewFont() )
+ return 0;
+
+ ImplFontEntry* pEntry = mpFontEntry;
+ ImplFontMetricData* pMetric = &(pEntry->maMetric);
+ return ImplDevicePixelToLogicWidth( pMetric->mnMinKashida );
+}
+
+sal_Int32 OutputDevice::ValidateKashidas ( const OUString& rTxt,
+ sal_Int32 nIdx, sal_Int32 nLen,
+ sal_Int32 nKashCount,
+ const sal_Int32* pKashidaPos,
+ sal_Int32* pKashidaPosDropped ) const
+{
+ // do layout
+ SalLayout* pSalLayout = ImplLayout( rTxt, nIdx, nLen );
+ if( !pSalLayout )
+ return 0;
+ sal_Int32 nDropped = 0;
+ for( int i = 0; i < nKashCount; ++i )
+ {
+ if( !pSalLayout->IsKashidaPosValid( pKashidaPos[ i ] ))
+ {
+ pKashidaPosDropped[ nDropped ] = pKashidaPos [ i ];
+ ++nDropped;
+ }
+ }
+ pSalLayout->Release();
+ return nDropped;
+}
+
+bool OutputDevice::GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr,
+ int nIndex, int nLen, int nBase, MetricVector& rVector )
+{
+
+ rVector.clear();
+
+ if(nLen == 0x0FFFF)
+ {
+ SAL_INFO("sal.rtl.xub",
+ "GetGlyphBoundRects Suspicious arguments nLen:" << nLen);
+ }
+
+ if( nIndex >= rStr.getLength() )
+ return false;
+
+ if( nLen < 0 || nIndex + nLen >= rStr.getLength() )
+ {
+ nLen = rStr.getLength() - nIndex;
+ }
+
+ Rectangle aRect;
+ for( int i = 0; i < nLen; i++ )
+ {
+ if( !GetTextBoundRect( aRect, rStr, nBase, nIndex + i, 1 ) )
+ break;
+ aRect.Move( rOrigin.X(), rOrigin.Y() );
+ rVector.push_back( aRect );
+ }
+
+ return (nLen == (int)rVector.size());
+}
+
+bool OutputDevice::GetFontCapabilities( FontCapabilities& rFontCapabilities ) const
+{
+ // we need a graphics
+ if( !mpGraphics && !ImplGetGraphics() )
+ return false;
+
+ if( mbNewFont )
+ ImplNewFont();
+ if( mbInitFont )
+ ImplInitFont();
+ if( !mpFontEntry )
+ return false;
+
+ return mpGraphics->GetImplFontCapabilities(rFontCapabilities);
+}
+
+bool OutputDevice::GetFontCharMap( FontCharMap& rFontCharMap ) const
+{
+ rFontCharMap.Reset();
+
+ // we need a graphics
+ if( !mpGraphics && !ImplGetGraphics() )
+ return false;
+
+ if( mbNewFont )
+ ImplNewFont();
+ if( mbInitFont )
+ ImplInitFont();
+ if( !mpFontEntry )
+ return false;
+
+#ifdef ENABLE_IFC_CACHE // a little font charmap cache helps considerably
+ static const int NMAXITEMS = 16;
+ static int nUsedItems = 0, nCurItem = 0;
+
+ struct CharMapCacheItem { const PhysicalFontFace* mpFontData; FontCharMap maCharMap; };
+ static CharMapCacheItem aCache[ NMAXITEMS ];
+
+ const PhysicalFontFace* pFontData = mpFontEntry->maFontSelData.mpFontData;
+
+ int i;
+ for( i = nUsedItems; --i >= 0; )
+ if( pFontData == aCache[i].mpFontData )
+ break;
+ if( i >= 0 ) // found in cache
+ {
+ rFontCharMap.Reset( aCache[i].maCharMap.mpImpl );
+ }
+ else // need to cache
+#endif // ENABLE_IFC_CACHE
+ {
+ const ImplFontCharMap* pNewMap = mpGraphics->GetImplFontCharMap();
+ rFontCharMap.Reset( pNewMap );
+
+#ifdef ENABLE_IFC_CACHE
+ // manage cache round-robin and insert data
+ CharMapCacheItem& rItem = aCache[ nCurItem ];
+ rItem.mpFontData = pFontData;
+ rItem.maCharMap.Reset( pNewMap );
+
+ if( ++nCurItem >= NMAXITEMS )
+ nCurItem = 0;
+
+ if( ++nUsedItems >= NMAXITEMS )
+ nUsedItems = NMAXITEMS;
+#endif // ENABLE_IFC_CACHE
+ }
+
+ if( rFontCharMap.IsDefaultMap() )
+ return false;
+ return true;
+}
+
+sal_Int32 OutputDevice::HasGlyphs( const Font& rTempFont, const OUString& rStr,
+ sal_Int32 nIndex, sal_Int32 nLen ) const
+{
+ if( nIndex >= rStr.getLength() )
+ return nIndex;
+ sal_Int32 nEnd;
+ if( nLen == -1 )
+ nEnd = rStr.getLength();
+ else
+ nEnd = std::min( rStr.getLength(), nIndex + nLen );
+
+ DBG_ASSERT( nIndex < nEnd, "StartPos >= EndPos?" );
+ DBG_ASSERT( nEnd <= rStr.getLength(), "String too short" );
+
+ // to get the map temporarily set font
+ const Font aOrigFont = GetFont();
+ const_cast<OutputDevice&>(*this).SetFont( rTempFont );
+ FontCharMap aFontCharMap;
+ bool bRet = GetFontCharMap( aFontCharMap );
+ const_cast<OutputDevice&>(*this).SetFont( aOrigFont );
+
+ // if fontmap is unknown assume it doesn't have the glyphs
+ if( !bRet )
+ return nIndex;
+
+ for( sal_Int32 i = nIndex; nIndex < nEnd; ++i, ++nIndex )
+ if( ! aFontCharMap.HasChar( rStr[i] ) )
+ return nIndex;
+
+ return -1;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/outdev/outdev3.cxx b/vcl/source/outdev/text.cxx
index 08d71ce7c399..3bf4e3e88bbf 100644
--- a/vcl/source/outdev/outdev3.cxx
+++ b/vcl/source/outdev/text.cxx
@@ -81,12 +81,6 @@
#include "com/sun/star/linguistic2/LinguServiceManager.hpp"
#include <comphelper/processfactory.hxx>
-#if defined UNX
-#define GLYPH_FONT_HEIGHT 128
-#else
-#define GLYPH_FONT_HEIGHT 256
-#endif
-
#include "sal/alloca.h"
#include <cmath>
@@ -106,1009 +100,6 @@ using namespace ::utl;
#define UNDERLINE_LAST UNDERLINE_BOLDWAVE
#define STRIKEOUT_LAST STRIKEOUT_X
-static void ImplRotatePos( long nOriginX, long nOriginY, long& rX, long& rY,
- int nOrientation )
-{
- if ( (nOrientation >= 0) && !(nOrientation % 900) )
- {
- if ( (nOrientation >= 3600) )
- nOrientation %= 3600;
-
- if ( nOrientation )
- {
- rX -= nOriginX;
- rY -= nOriginY;
-
- if ( nOrientation == 900 )
- {
- long nTemp = rX;
- rX = rY;
- rY = -nTemp;
- }
- else if ( nOrientation == 1800 )
- {
- rX = -rX;
- rY = -rY;
- }
- else /* ( nOrientation == 2700 ) */
- {
- long nTemp = rX;
- rX = -rY;
- rY = nTemp;
- }
-
- rX += nOriginX;
- rY += nOriginY;
- }
- }
- else
- {
- double nRealOrientation = nOrientation*F_PI1800;
- double nCos = cos( nRealOrientation );
- double nSin = sin( nRealOrientation );
-
- // Translation...
- long nX = rX-nOriginX;
- long nY = rY-nOriginY;
-
- // Rotation...
- rX = +((long)(nCos*nX + nSin*nY)) + nOriginX;
- rY = -((long)(nSin*nX - nCos*nY)) + nOriginY;
- }
-}
-
-void OutputDevice::ImplClearFontData( const bool bNewFontLists )
-{
- // the currently selected logical font is no longer needed
- if ( mpFontEntry )
- {
- mpFontCache->Release( mpFontEntry );
- mpFontEntry = NULL;
- }
-
- mbInitFont = true;
- mbNewFont = true;
-
- if ( bNewFontLists )
- {
- if ( mpGetDevFontList )
- {
- delete mpGetDevFontList;
- mpGetDevFontList = NULL;
- }
- if ( mpGetDevSizeList )
- {
- delete mpGetDevSizeList;
- mpGetDevSizeList = NULL;
- }
-
- // release all physically selected fonts on this device
- if( ImplGetGraphics() )
- mpGraphics->ReleaseFonts();
- }
-
-// if ( GetOutDevType() == OUTDEV_PRINTER || mpPDFWriter )
- {
- ImplSVData* pSVData = ImplGetSVData();
-
- if( mpFontCache && mpFontCache != pSVData->maGDIData.mpScreenFontCache )
- mpFontCache->Invalidate();
-
- if ( bNewFontLists )
- {
- // we need a graphics
- if ( ImplGetGraphics() )
- {
- if( mpFontCollection && mpFontCollection != pSVData->maGDIData.mpScreenFontList )
- mpFontCollection->Clear();
-
- if( mpPDFWriter )
- {
- if( mpFontCollection && mpFontCollection != pSVData->maGDIData.mpScreenFontList )
- delete mpFontCollection;
- if( mpFontCache && mpFontCache != pSVData->maGDIData.mpScreenFontCache )
- delete mpFontCache;
- mpFontCollection = 0;
- mpFontCache = 0;
- }
- }
- }
- }
-
- // also update child windows if needed
- if ( GetOutDevType() == OUTDEV_WINDOW )
- {
- Window* pChild = ((Window*)this)->mpWindowImpl->mpFirstChild;
- while ( pChild )
- {
- pChild->ImplClearFontData( true );
- pChild = pChild->mpWindowImpl->mpNext;
- }
- }
-}
-
-void OutputDevice::ImplRefreshFontData( const bool bNewFontLists )
-{
-// if ( GetOutDevType() == OUTDEV_PRINTER || mpPDFWriter )
- {
- ImplSVData* pSVData = ImplGetSVData();
-
- if ( bNewFontLists )
- {
- // we need a graphics
- if ( ImplGetGraphics() )
- {
- if( mpPDFWriter )
- {
- mpFontCollection = pSVData->maGDIData.mpScreenFontList->Clone( true, true );
- mpFontCache = new ImplFontCache();
- }
- else
- {
- mpGraphics->GetDevFontList( mpFontCollection );
- }
- }
- }
- }
-
- // also update child windows if needed
- if ( GetOutDevType() == OUTDEV_WINDOW )
- {
- Window* pChild = ((Window*)this)->mpWindowImpl->mpFirstChild;
- while ( pChild )
- {
- pChild->ImplRefreshFontData( true );
- pChild = pChild->mpWindowImpl->mpNext;
- }
- }
-}
-
-void OutputDevice::ImplUpdateFontData( bool bNewFontLists )
-{
- ImplClearFontData( bNewFontLists );
- ImplRefreshFontData( bNewFontLists );
-}
-
-void OutputDevice::ImplUpdateAllFontData( bool bNewFontLists )
-{
- ImplSVData* pSVData = ImplGetSVData();
-
- ImplUpdateFontDataForAllFrames( &OutputDevice::ImplClearFontData, bNewFontLists );
-
- // clear global font lists to have them updated
- pSVData->maGDIData.mpScreenFontCache->Invalidate();
- if ( bNewFontLists )
- {
- pSVData->maGDIData.mpScreenFontList->Clear();
- Window * pFrame = pSVData->maWinData.mpFirstFrame;
- if ( pFrame )
- {
- if ( pFrame->ImplGetGraphics() )
- {
- // Stupid typecast here and somewhere ((OutputDevice*)&aVDev)->, because bug in .NET2002 compiler
- OutputDevice *pDevice = (OutputDevice*)pFrame;
- pDevice->mpGraphics->ClearDevFontCache();
- pDevice->mpGraphics->GetDevFontList(pFrame->mpWindowImpl->mpFrameData->mpFontCollection);
- }
- }
- }
-
- ImplUpdateFontDataForAllFrames( &OutputDevice::ImplRefreshFontData, bNewFontLists );
-}
-
-void OutputDevice::ImplUpdateFontDataForAllFrames( const FontUpdateHandler_t pHdl, const bool bNewFontLists )
-{
- ImplSVData* const pSVData = ImplGetSVData();
-
- // update all windows
- Window* pFrame = pSVData->maWinData.mpFirstFrame;
- while ( pFrame )
- {
- ( pFrame->*pHdl )( bNewFontLists );
-
- Window* pSysWin = pFrame->mpWindowImpl->mpFrameData->mpFirstOverlap;
- while ( pSysWin )
- {
- ( pSysWin->*pHdl )( bNewFontLists );
- pSysWin = pSysWin->mpWindowImpl->mpNextOverlap;
- }
-
- pFrame = pFrame->mpWindowImpl->mpFrameData->mpNextFrame;
- }
-
- // update all virtual devices
- VirtualDevice* pVirDev = pSVData->maGDIData.mpFirstVirDev;
- while ( pVirDev )
- {
- ( pVirDev->*pHdl )( bNewFontLists );
- pVirDev = pVirDev->mpNext;
- }
-
- // update all printers
- Printer* pPrinter = pSVData->maGDIData.mpFirstPrinter;
- while ( pPrinter )
- {
- ( pPrinter->*pHdl )( bNewFontLists );
- pPrinter = pPrinter->mpNext;
- }
-}
-
-void OutputDevice::BeginFontSubstitution()
-{
- ImplSVData* pSVData = ImplGetSVData();
- pSVData->maGDIData.mbFontSubChanged = false;
-}
-
-void OutputDevice::EndFontSubstitution()
-{
- ImplSVData* pSVData = ImplGetSVData();
- if ( pSVData->maGDIData.mbFontSubChanged )
- {
- ImplUpdateAllFontData( false );
-
- Application* pApp = GetpApp();
- DataChangedEvent aDCEvt( DATACHANGED_FONTSUBSTITUTION );
- pApp->DataChanged( aDCEvt );
- pApp->NotifyAllWindows( aDCEvt );
- pSVData->maGDIData.mbFontSubChanged = false;
- }
-}
-
-void OutputDevice::AddFontSubstitute( const OUString& rFontName,
- const OUString& rReplaceFontName,
- sal_uInt16 nFlags )
-{
- ImplDirectFontSubstitution*& rpSubst = ImplGetSVData()->maGDIData.mpDirectFontSubst;
- if( !rpSubst )
- rpSubst = new ImplDirectFontSubstitution();
- rpSubst->AddFontSubstitute( rFontName, rReplaceFontName, nFlags );
- ImplGetSVData()->maGDIData.mbFontSubChanged = true;
-}
-
-void ImplDirectFontSubstitution::AddFontSubstitute( const OUString& rFontName,
- const OUString& rSubstFontName, sal_uInt16 nFlags )
-{
- maFontSubstList.push_back( ImplFontSubstEntry( rFontName, rSubstFontName, nFlags ) );
-}
-
-ImplFontSubstEntry::ImplFontSubstEntry( const OUString& rFontName,
- const OUString& rSubstFontName, sal_uInt16 nSubstFlags )
-: maName( rFontName )
-, maReplaceName( rSubstFontName )
-, mnFlags( nSubstFlags )
-{
- maSearchName = rFontName;
- maSearchReplaceName = rSubstFontName;
- GetEnglishSearchFontName( maSearchName );
- GetEnglishSearchFontName( maSearchReplaceName );
-}
-
-void OutputDevice::RemoveFontSubstitute( sal_uInt16 n )
-{
- ImplDirectFontSubstitution* pSubst = ImplGetSVData()->maGDIData.mpDirectFontSubst;
- if( pSubst )
- pSubst->RemoveFontSubstitute( n );
-}
-
-void ImplDirectFontSubstitution::RemoveFontSubstitute( int nIndex )
-{
- FontSubstList::iterator it = maFontSubstList.begin();
- for( int nCount = 0; (it != maFontSubstList.end()) && (nCount++ != nIndex); ++it ) ;
- if( it != maFontSubstList.end() )
- maFontSubstList.erase( it );
-}
-
-sal_uInt16 OutputDevice::GetFontSubstituteCount()
-{
- const ImplDirectFontSubstitution* pSubst = ImplGetSVData()->maGDIData.mpDirectFontSubst;
- if( !pSubst )
- return 0;
- int nCount = pSubst->GetFontSubstituteCount();
- return (sal_uInt16)nCount;
-}
-
-bool ImplDirectFontSubstitution::FindFontSubstitute( OUString& rSubstName,
- const OUString& rSearchName, sal_uInt16 nFlags ) const
-{
- // TODO: get rid of O(N) searches
- FontSubstList::const_iterator it = maFontSubstList.begin();
- for(; it != maFontSubstList.end(); ++it )
- {
- const ImplFontSubstEntry& rEntry = *it;
- if( ((rEntry.mnFlags & nFlags) || !nFlags)
- && (rEntry.maSearchName == rSearchName) )
- {
- rSubstName = rEntry.maSearchReplaceName;
- return true;
- }
- }
-
- return false;
-}
-
-void ImplFontSubstitute( OUString& rFontName )
-{
-#ifdef DBG_UTIL
- OUString aTempName = rFontName;
- GetEnglishSearchFontName( aTempName );
- DBG_ASSERT( aTempName == rFontName, "ImplFontSubstitute() called without a searchname" );
-#endif
-
- OUString aSubstFontName;
-
- // apply user-configurable font replacement (eg, from the list in Tools->Options)
- const ImplDirectFontSubstitution* pSubst = ImplGetSVData()->maGDIData.mpDirectFontSubst;
- if( pSubst && pSubst->FindFontSubstitute( aSubstFontName, rFontName, FONT_SUBSTITUTE_ALWAYS ) )
- {
- rFontName = aSubstFontName;
- return;
- }
-}
-
-//hidpi TODO: This routine has hard-coded font-sizes that break places such as DialControl
-Font OutputDevice::GetDefaultFont( sal_uInt16 nType, LanguageType eLang,
- sal_uLong nFlags, const OutputDevice* pOutDev )
-{
- if (!pOutDev) // default is NULL
- pOutDev = Application::GetDefaultDevice();
-
- LanguageTag aLanguageTag(
- ( eLang == LANGUAGE_NONE || eLang == LANGUAGE_SYSTEM || eLang == LANGUAGE_DONTKNOW ) ?
- Application::GetSettings().GetUILanguageTag() :
- LanguageTag( eLang ));
-
- utl::DefaultFontConfiguration& rDefaults = utl::DefaultFontConfiguration::get();
- OUString aDefault = rDefaults.getDefaultFont( aLanguageTag, nType );
- OUString aSearch;
-
- if( !aDefault.isEmpty() )
- aSearch = aDefault;
- else
- aSearch = rDefaults.getUserInterfaceFont( aLanguageTag ); // use the UI font as a fallback
-
- Font aFont;
- aFont.SetPitch( PITCH_VARIABLE );
-
- switch ( nType )
- {
- case DEFAULTFONT_SANS_UNICODE:
- case DEFAULTFONT_UI_SANS:
- aFont.SetFamily( FAMILY_SWISS );
- break;
-
- case DEFAULTFONT_SANS:
- case DEFAULTFONT_LATIN_HEADING:
- case DEFAULTFONT_LATIN_SPREADSHEET:
- case DEFAULTFONT_LATIN_DISPLAY:
- aFont.SetFamily( FAMILY_SWISS );
- break;
-
- case DEFAULTFONT_SERIF:
- case DEFAULTFONT_LATIN_TEXT:
- case DEFAULTFONT_LATIN_PRESENTATION:
- aFont.SetFamily( FAMILY_ROMAN );
- break;
-
- case DEFAULTFONT_FIXED:
- case DEFAULTFONT_LATIN_FIXED:
- case DEFAULTFONT_UI_FIXED:
- aFont.SetPitch( PITCH_FIXED );
- aFont.SetFamily( FAMILY_MODERN );
- break;
-
- case DEFAULTFONT_SYMBOL:
- aFont.SetCharSet( RTL_TEXTENCODING_SYMBOL );
- break;
-
- case DEFAULTFONT_CJK_TEXT:
- case DEFAULTFONT_CJK_PRESENTATION:
- case DEFAULTFONT_CJK_SPREADSHEET:
- case DEFAULTFONT_CJK_HEADING:
- case DEFAULTFONT_CJK_DISPLAY:
- aFont.SetFamily( FAMILY_SYSTEM ); // don't care, but don't use font subst config later...
- break;
-
- case DEFAULTFONT_CTL_TEXT:
- case DEFAULTFONT_CTL_PRESENTATION:
- case DEFAULTFONT_CTL_SPREADSHEET:
- case DEFAULTFONT_CTL_HEADING:
- case DEFAULTFONT_CTL_DISPLAY:
- aFont.SetFamily( FAMILY_SYSTEM ); // don't care, but don't use font subst config later...
- break;
- }
-
- if ( !aSearch.isEmpty() )
- {
- aFont.SetHeight( 12 ); // corresponds to nDefaultHeight
- aFont.SetWeight( WEIGHT_NORMAL );
- aFont.SetLanguage( eLang );
-
- if ( aFont.GetCharSet() == RTL_TEXTENCODING_DONTKNOW )
- aFont.SetCharSet( osl_getThreadTextEncoding() );
-
- // Should we only return available fonts on the given device
- if ( pOutDev )
- {
- pOutDev->ImplInitFontList();
-
- // Search Font in the FontList
- OUString aName;
- OUString aSearchName;
- sal_Int32 nIndex = 0;
- do
- {
- aSearchName = GetNextFontToken( aSearch, nIndex );
- GetEnglishSearchFontName( aSearchName );
- PhysicalFontFamily* pFontFamily = pOutDev->mpFontCollection->ImplFindBySearchName( aSearchName );
- if( pFontFamily )
- {
- AddTokenFontName( aName, pFontFamily->GetFamilyName() );
- if( nFlags & DEFAULTFONT_FLAGS_ONLYONE )
- break;
- }
- }
- while ( nIndex != -1 );
- aFont.SetName( aName );
- }
-
- // No Name, than set all names
- if ( aFont.GetName().isEmpty() )
- {
- if ( nFlags & DEFAULTFONT_FLAGS_ONLYONE )
- {
- if( !pOutDev )
- {
- SAL_WARN ("vcl.gdi", "No default window has been set for the application - we really shouldn't be able to get here");
- sal_Int32 nIndex = 0;
- aFont.SetName( aSearch.getToken( 0, ';', nIndex ) );
- }
- else
- {
- pOutDev->ImplInitFontList();
-
- aFont.SetName( aSearch );
-
- // convert to pixel height
- Size aSize = pOutDev->ImplLogicToDevicePixel( aFont.GetSize() );
- if ( !aSize.Height() )
- {
- // use default pixel height only when logical height is zero
- if ( aFont.GetHeight() )
- aSize.Height() = 1;
- else
- aSize.Height() = (12*pOutDev->mnDPIY)/72;
- }
-
- // use default width only when logical width is zero
- if( (0 == aSize.Width()) && (0 != aFont.GetSize().Width()) )
- aSize.Width() = 1;
-
- // get the name of the first available font
- float fExactHeight = static_cast<float>(aSize.Height());
- ImplFontEntry* pEntry = pOutDev->mpFontCache->GetFontEntry( pOutDev->mpFontCollection, aFont, aSize, fExactHeight );
- if (pEntry)
- {
- if( pEntry->maFontSelData.mpFontData )
- aFont.SetName( pEntry->maFontSelData.mpFontData->GetFamilyName() );
- else
- aFont.SetName( pEntry->maFontSelData.maTargetName );
- }
- }
- }
- else
- aFont.SetName( aSearch );
- }
- }
-
-#if OSL_DEBUG_LEVEL > 2
- const char* s = "DEFAULTFONT_SANS_UNKNOWN";
- switch ( nType )
- {
- case DEFAULTFONT_SANS_UNICODE: s = "DEFAULTFONT_SANS_UNICODE"; break;
- case DEFAULTFONT_UI_SANS: s = "DEFAULTFONT_UI_SANS"; break;
-
- case DEFAULTFONT_SANS: s = "DEFAULTFONT_SANS"; break;
- case DEFAULTFONT_LATIN_HEADING: s = "DEFAULTFONT_LATIN_HEADING"; break;
- case DEFAULTFONT_LATIN_SPREADSHEET: s = "DEFAULTFONT_LATIN_SPREADSHEET"; break;
- case DEFAULTFONT_LATIN_DISPLAY: s = "DEFAULTFONT_LATIN_DISPLAY"; break;
-
- case DEFAULTFONT_SERIF: s = "DEFAULTFONT_SERIF"; break;
- case DEFAULTFONT_LATIN_TEXT: s = "DEFAULTFONT_LATIN_TEXT"; break;
- case DEFAULTFONT_LATIN_PRESENTATION: s = "DEFAULTFONT_LATIN_PRESENTATION"; break;
-
- case DEFAULTFONT_FIXED: s = "DEFAULTFONT_FIXED"; break;
- case DEFAULTFONT_LATIN_FIXED: s = "DEFAULTFONT_LATIN_FIXED"; break;
- case DEFAULTFONT_UI_FIXED: s = "DEFAULTFONT_UI_FIXED"; break;
-
- case DEFAULTFONT_SYMBOL: s = "DEFAULTFONT_SYMBOL"; break;
-
- case DEFAULTFONT_CJK_TEXT: s = "DEFAULTFONT_CJK_TEXT"; break;
- case DEFAULTFONT_CJK_PRESENTATION: s = "DEFAULTFONT_CJK_PRESENTATION"; break;
- case DEFAULTFONT_CJK_SPREADSHEET: s = "DEFAULTFONT_CJK_SPREADSHEET"; break;
- case DEFAULTFONT_CJK_HEADING: s = "DEFAULTFONT_CJK_HEADING"; break;
- case DEFAULTFONT_CJK_DISPLAY: s = "DEFAULTFONT_CJK_DISPLAY"; break;
-
- case DEFAULTFONT_CTL_TEXT: s = "DEFAULTFONT_CTL_TEXT"; break;
- case DEFAULTFONT_CTL_PRESENTATION: s = "DEFAULTFONT_CTL_PRESENTATION"; break;
- case DEFAULTFONT_CTL_SPREADSHEET: s = "DEFAULTFONT_CTL_SPREADSHEET"; break;
- case DEFAULTFONT_CTL_HEADING: s = "DEFAULTFONT_CTL_HEADING"; break;
- case DEFAULTFONT_CTL_DISPLAY: s = "DEFAULTFONT_CTL_DISPLAY"; break;
- }
- fprintf( stderr, " OutputDevice::GetDefaultFont() Type=\"%s\" lang=%d flags=%ld FontName=\"%s\"\n",
- s, eLang, nFlags,
- OUStringToOString( aFont.GetName(), RTL_TEXTENCODING_UTF8 ).getStr()
- );
-#endif
-
- return aFont;
-}
-
-ImplFontEntry::ImplFontEntry( const FontSelectPattern& rFontSelData )
- : maFontSelData( rFontSelData )
- , maMetric( rFontSelData )
- , mpConversion( NULL )
- , mnLineHeight( 0 )
- , mnRefCount( 1 )
- , mnSetFontFlags( 0 )
- , mnOwnOrientation( 0 )
- , mnOrientation( 0 )
- , mbInit( false )
- , mpUnicodeFallbackList( NULL )
-{
- maFontSelData.mpFontEntry = this;
-}
-
-ImplFontEntry::~ImplFontEntry()
-{
- delete mpUnicodeFallbackList;
-}
-
-size_t ImplFontEntry::GFBCacheKey_Hash::operator()( const GFBCacheKey& rData ) const
-{
- boost::hash<sal_UCS4> a;
- boost::hash<int > b;
- return a(rData.first) ^ b(rData.second);
-}
-
-void ImplFontEntry::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
-{
- if( !mpUnicodeFallbackList )
- mpUnicodeFallbackList = new UnicodeFallbackList;
- (*mpUnicodeFallbackList)[ GFBCacheKey(cChar,eWeight) ] = rFontName;
-}
-
-bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, OUString* pFontName ) const
-{
- if( !mpUnicodeFallbackList )
- return false;
-
- UnicodeFallbackList::const_iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) );
- if( it == mpUnicodeFallbackList->end() )
- return false;
-
- *pFontName = (*it).second;
- return true;
-}
-
-void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
-{
-// DBG_ASSERT( mpUnicodeFallbackList, "ImplFontEntry::IgnoreFallbackForUnicode no list" );
- UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) );
-// DBG_ASSERT( it != mpUnicodeFallbackList->end(), "ImplFontEntry::IgnoreFallbackForUnicode no match" );
- if( it == mpUnicodeFallbackList->end() )
- return;
- if( (*it).second == rFontName )
- mpUnicodeFallbackList->erase( it );
-}
-
-FontSelectPatternAttributes::FontSelectPatternAttributes( const Font& rFont,
- const OUString& rSearchName, const Size& rSize, float fExactHeight )
- : maSearchName( rSearchName )
- , mnWidth( rSize.Width() )
- , mnHeight( rSize.Height() )
- , mfExactHeight( fExactHeight)
- , mnOrientation( rFont.GetOrientation() )
- , meLanguage( rFont.GetLanguage() )
- , mbVertical( rFont.IsVertical() )
- , mbNonAntialiased( false )
- , mbEmbolden( false )
-{
- maTargetName = GetFamilyName();
-
- rFont.GetFontAttributes( *this );
-
- // normalize orientation between 0 and 3600
- if( 3600 <= (unsigned)mnOrientation )
- {
- if( mnOrientation >= 0 )
- mnOrientation %= 3600;
- else
- mnOrientation = 3600 - (-mnOrientation % 3600);
- }
-
- // normalize width and height
- if( mnHeight < 0 )
- mnHeight = -mnHeight;
- if( mnWidth < 0 )
- mnWidth = -mnWidth;
-}
-
-FontSelectPattern::FontSelectPattern( const Font& rFont,
- const OUString& rSearchName, const Size& rSize, float fExactHeight)
- : FontSelectPatternAttributes(rFont, rSearchName, rSize, fExactHeight)
- , mpFontData( NULL )
- , mpFontEntry( NULL )
-{
-}
-
-// NOTE: this ctor is still used on Windows. Do not remove.
-#ifdef WNT
-FontSelectPatternAttributes::FontSelectPatternAttributes( const PhysicalFontFace& rFontData,
- const Size& rSize, float fExactHeight, int nOrientation, bool bVertical )
- : ImplFontAttributes( rFontData )
- , mnWidth( rSize.Width() )
- , mnHeight( rSize.Height() )
- , mfExactHeight( fExactHeight )
- , mnOrientation( nOrientation )
- , meLanguage( 0 )
- , mbVertical( bVertical )
- , mbNonAntialiased( false )
- , mbEmbolden( false )
-{
- maTargetName = maSearchName = GetFamilyName();
- // NOTE: no normalization for width/height/orientation
-}
-
-FontSelectPattern::FontSelectPattern( const PhysicalFontFace& rFontData,
- const Size& rSize, float fExactHeight, int nOrientation, bool bVertical )
- : FontSelectPatternAttributes(rFontData, rSize, fExactHeight, nOrientation, bVertical)
- , mpFontData( &rFontData )
- , mpFontEntry( NULL )
-{
-}
-#endif
-
-void FontSelectPattern::copyAttributes(const FontSelectPatternAttributes &rAttributes)
-{
- static_cast<FontSelectPatternAttributes&>(*this) = rAttributes;
-}
-
-size_t ImplFontCache::IFSD_Hash::operator()( const FontSelectPattern& rFSD ) const
-{
- return rFSD.hashCode();
-}
-
-size_t FontSelectPatternAttributes::hashCode() const
-{
- // TODO: does it pay off to improve this hash function?
- static FontNameHash aFontNameHash;
- size_t nHash = aFontNameHash( maSearchName );
-#if ENABLE_GRAPHITE
- // check for features and generate a unique hash if necessary
- if (maTargetName.indexOf(grutils::GrFeatureParser::FEAT_PREFIX)
- != -1)
- {
- nHash = aFontNameHash( maTargetName );
- }
-#endif
- nHash += 11 * mnHeight;
- nHash += 19 * GetWeight();
- nHash += 29 * GetSlant();
- nHash += 37 * mnOrientation;
- nHash += 41 * meLanguage;
- if( mbVertical )
- nHash += 53;
- return nHash;
-}
-
-bool FontSelectPatternAttributes::operator==(const FontSelectPatternAttributes& rOther) const
-{
- if (static_cast<const ImplFontAttributes&>(*this) != static_cast<const ImplFontAttributes&>(rOther))
- return false;
-
- if (maTargetName != rOther.maTargetName)
- return false;
-
- if (maSearchName != rOther.maSearchName)
- return false;
-
- if (mnWidth != rOther.mnWidth)
- return false;
-
- if (mnHeight != rOther.mnHeight)
- return false;
-
- if (mfExactHeight != rOther.mfExactHeight)
- return false;
-
- if (mnOrientation != rOther.mnOrientation)
- return false;
-
- if (meLanguage != rOther.meLanguage)
- return false;
-
- if (mbVertical != rOther.mbVertical)
- return false;
-
- if (mbNonAntialiased != rOther.mbNonAntialiased)
- return false;
-
- if (mbEmbolden != rOther.mbEmbolden)
- return false;
-
- if (maItalicMatrix != rOther.maItalicMatrix)
- return false;
-
- return true;
-}
-
-bool ImplFontCache::IFSD_Equal::operator()(const FontSelectPattern& rA, const FontSelectPattern& rB) const
-{
- // check normalized font family name
- if( rA.maSearchName != rB.maSearchName )
- return false;
-
- // check font transformation
- if( (rA.mnHeight != rB.mnHeight)
- || (rA.mnWidth != rB.mnWidth)
- || (rA.mnOrientation != rB.mnOrientation) )
- return false;
-
- // check mapping relevant attributes
- if( (rA.mbVertical != rB.mbVertical)
- || (rA.meLanguage != rB.meLanguage) )
- return false;
-
- // check font face attributes
- if( (rA.GetWeight() != rB.GetWeight())
- || (rA.GetSlant() != rB.GetSlant())
-// || (rA.meFamily != rB.meFamily) // TODO: remove this mostly obsolete member
- || (rA.GetPitch() != rB.GetPitch()) )
- return false;
-
- // check style name
- if( rA.GetStyleName() != rB.GetStyleName() )
- return false;
-
- // Symbol fonts may recode from one type to another So they are only
- // safely equivalent for equal targets
- if (
- (rA.mpFontData && rA.mpFontData->IsSymbolFont()) ||
- (rB.mpFontData && rB.mpFontData->IsSymbolFont())
- )
- {
- if (rA.maTargetName != rB.maTargetName)
- return false;
- }
-
-#if ENABLE_GRAPHITE
- // check for features
- if ((rA.maTargetName.indexOf(grutils::GrFeatureParser::FEAT_PREFIX)
- != -1 ||
- rB.maTargetName.indexOf(grutils::GrFeatureParser::FEAT_PREFIX)
- != -1) && rA.maTargetName != rB.maTargetName)
- return false;
-#endif
-
- if (rA.mbEmbolden != rB.mbEmbolden)
- return false;
-
- if (rA.maItalicMatrix != rB.maItalicMatrix)
- return false;
-
- return true;
-}
-
-ImplFontCache::ImplFontCache()
-: mpFirstEntry( NULL ),
- mnRef0Count( 0 )
-{}
-
-ImplFontCache::~ImplFontCache()
-{
- FontInstanceList::iterator it = maFontInstanceList.begin();
- for(; it != maFontInstanceList.end(); ++it )
- {
- ImplFontEntry* pEntry = (*it).second;
- delete pEntry;
- }
-}
-
-ImplFontEntry* ImplFontCache::GetFontEntry( PhysicalFontCollection* pFontList,
- const Font& rFont, const Size& rSize, float fExactHeight )
-{
- OUString aSearchName = rFont.GetName();
-
- // initialize internal font request object
- FontSelectPattern aFontSelData( rFont, aSearchName, rSize, fExactHeight );
- return GetFontEntry( pFontList, aFontSelData );
-}
-
-ImplFontEntry* ImplFontCache::GetFontEntry( PhysicalFontCollection* pFontList,
- FontSelectPattern& aFontSelData )
-{
- // check if a directly matching logical font instance is already cached,
- // the most recently used font usually has a hit rate of >50%
- ImplFontEntry *pEntry = NULL;
- PhysicalFontFamily* pFontFamily = NULL;
- IFSD_Equal aIFSD_Equal;
- if( mpFirstEntry && aIFSD_Equal( aFontSelData, mpFirstEntry->maFontSelData ) )
- pEntry = mpFirstEntry;
- else
- {
- FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData );
- if( it != maFontInstanceList.end() )
- pEntry = (*it).second;
- }
-
- if( !pEntry ) // no direct cache hit
- {
- // find the best matching logical font family and update font selector accordingly
- pFontFamily = pFontList->ImplFindByFont( aFontSelData );
- DBG_ASSERT( (pFontFamily != NULL), "ImplFontCache::Get() No logical font found!" );
- if( pFontFamily )
- aFontSelData.maSearchName = pFontFamily->GetSearchName();
-
- // check if an indirectly matching logical font instance is already cached
- FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData );
- if( it != maFontInstanceList.end() )
- {
- // we have an indirect cache hit
- pEntry = (*it).second;
- }
- }
-
- PhysicalFontFace* pFontData = NULL;
-
- if (!pEntry && pFontFamily)// no cache hit => find the best matching physical font face
- {
- bool bOrigWasSymbol = aFontSelData.mpFontData && aFontSelData.mpFontData->IsSymbolFont();
- pFontData = pFontFamily->FindBestFontFace( aFontSelData );
- aFontSelData.mpFontData = pFontData;
- bool bNewIsSymbol = aFontSelData.mpFontData && aFontSelData.mpFontData->IsSymbolFont();
-
- if (bNewIsSymbol != bOrigWasSymbol)
- {
- // it is possible, though generally unlikely, that at this point we
- // will attempt to use a symbol font as a last-ditch fallback for a
- // non-symbol font request or vice versa, and by changing
- // aFontSelData.mpFontData to/from a symbol font we may now find
- // something in the cache that can be reused which previously
- // wasn't a candidate
- FontInstanceList::iterator it = maFontInstanceList.find( aFontSelData );
- if( it != maFontInstanceList.end() )
- pEntry = (*it).second;
- }
- }
-
- if( pEntry ) // cache hit => use existing font instance
- {
- // increase the font instance's reference count
- if( !pEntry->mnRefCount++ )
- --mnRef0Count;
- }
-
- if (!pEntry && pFontData)// still no cache hit => create a new font instance
- {
- // create a new logical font instance from this physical font face
- pEntry = pFontData->CreateFontInstance( aFontSelData );
-
- // if we're subtituting from or to a symbol font we may need a symbol
- // conversion table
- if( pFontData->IsSymbolFont() || aFontSelData.IsSymbolFont() )
- {
- if( aFontSelData.maTargetName != aFontSelData.maSearchName )
- pEntry->mpConversion = ConvertChar::GetRecodeData( aFontSelData.maTargetName, aFontSelData.maSearchName );
- }
-
-#ifdef MACOSX
- //It might be better to dig out the font version of the target font
- //to see if it's a modern re-coded apple symbol font in case that
- //font shows up on a different platform
- if (!pEntry->mpConversion &&
- aFontSelData.maTargetName.equalsIgnoreAsciiCase("symbol") &&
- aFontSelData.maSearchName.equalsIgnoreAsciiCase("symbol"))
- {
- pEntry->mpConversion = ConvertChar::GetRecodeData( OUString("Symbol"), OUString("AppleSymbol") );
- }
-#endif
-
- // add the new entry to the cache
- maFontInstanceList[ aFontSelData ] = pEntry;
- }
-
- mpFirstEntry = pEntry;
- return pEntry;
-}
-
-ImplFontEntry* ImplFontCache::GetGlyphFallbackFont( PhysicalFontCollection* pFontCollection,
- FontSelectPattern& rFontSelData, int nFallbackLevel, OUString& rMissingCodes )
-{
- // get a candidate font for glyph fallback
- // unless the previously selected font got a device specific substitution
- // e.g. PsPrint Arial->Helvetica for udiaeresis when Helvetica doesn't support it
- if( nFallbackLevel >= 1)
- {
- PhysicalFontFamily* pFallbackData = NULL;
-
- //fdo#33898 If someone has EUDC installed then they really want that to
- //be used as the first-choice glyph fallback seeing as it's filled with
- //private area codes with don't make any sense in any other font so
- //prioritise it here if it's available. Ideally we would remove from
- //rMissingCodes all the glyphs which it is able to resolve as an
- //optimization, but that's tricky to achieve cross-platform without
- //sufficient heavy-weight code that's likely to undo the value of the
- //optimization
- if (nFallbackLevel == 1)
- pFallbackData = pFontCollection->FindFontFamily(OUString("EUDC"));
- if (!pFallbackData)
- pFallbackData = pFontCollection->GetGlyphFallbackFont(rFontSelData, rMissingCodes, nFallbackLevel-1);
- // escape when there are no font candidates
- if( !pFallbackData )
- return NULL;
- // override the font name
- rFontSelData.SetFamilyName( pFallbackData->GetFamilyName() );
- // clear the cached normalized name
- rFontSelData.maSearchName = "";
- }
-
- ImplFontEntry* pFallbackFont = GetFontEntry( pFontCollection, rFontSelData );
- return pFallbackFont;
-}
-
-void ImplFontCache::Release( ImplFontEntry* pEntry )
-{
- static const int FONTCACHE_MAX = 50;
-
- DBG_ASSERT( (pEntry->mnRefCount > 0), "ImplFontCache::Release() - font refcount underflow" );
- if( --pEntry->mnRefCount > 0 )
- return;
-
- if( ++mnRef0Count < FONTCACHE_MAX )
- return;
-
- // remove unused entries from font instance cache
- FontInstanceList::iterator it_next = maFontInstanceList.begin();
- while( it_next != maFontInstanceList.end() )
- {
- FontInstanceList::iterator it = it_next++;
- ImplFontEntry* pFontEntry = (*it).second;
- if( pFontEntry->mnRefCount > 0 )
- continue;
-
- maFontInstanceList.erase( it );
- delete pFontEntry;
- --mnRef0Count;
- DBG_ASSERT( (mnRef0Count>=0), "ImplFontCache::Release() - refcount0 underflow" );
-
- if( mpFirstEntry == pFontEntry )
- mpFirstEntry = NULL;
- }
-
- DBG_ASSERT( (mnRef0Count==0), "ImplFontCache::Release() - refcount0 mismatch" );
-}
-
-void ImplFontCache::Invalidate()
-{
- // delete unreferenced entries
- FontInstanceList::iterator it = maFontInstanceList.begin();
- for(; it != maFontInstanceList.end(); ++it )
- {
- ImplFontEntry* pFontEntry = (*it).second;
- if( pFontEntry->mnRefCount > 0 )
- continue;
-
- delete pFontEntry;
- --mnRef0Count;
- }
-
- // #112304# make sure the font cache is really clean
- mpFirstEntry = NULL;
- maFontInstanceList.clear();
-
- DBG_ASSERT( (mnRef0Count==0), "ImplFontCache::Invalidate() - mnRef0Count non-zero" );
-}
-
ImplMultiTextLineInfo::ImplMultiTextLineInfo()
{
mpLines = new PImplTextLineInfo[MULTITEXTLINEINFO_RESIZE];
@@ -1144,32 +135,6 @@ void ImplMultiTextLineInfo::Clear()
mnLines = 0;
}
-FontEmphasisMark OutputDevice::ImplGetEmphasisMarkStyle( const Font& rFont )
-{
- FontEmphasisMark nEmphasisMark = rFont.GetEmphasisMark();
-
- // If no Position is set, then calculate the default position, which
- // depends on the language
- if ( !(nEmphasisMark & (EMPHASISMARK_POS_ABOVE | EMPHASISMARK_POS_BELOW)) )
- {
- LanguageType eLang = rFont.GetLanguage();
- // In Chinese Simplified the EmphasisMarks are below/left
- if (MsLangId::isSimplifiedChinese(eLang))
- nEmphasisMark |= EMPHASISMARK_POS_BELOW;
- else
- {
- eLang = rFont.GetCJKContextLanguage();
- // In Chinese Simplified the EmphasisMarks are below/left
- if (MsLangId::isSimplifiedChinese(eLang))
- nEmphasisMark |= EMPHASISMARK_POS_BELOW;
- else
- nEmphasisMark |= EMPHASISMARK_POS_ABOVE;
- }
- }
-
- return nEmphasisMark;
-}
-
bool OutputDevice::ImplIsUnderlineAbove( const Font& rFont )
{
if ( !rFont.IsVertical() )
@@ -1183,57 +148,6 @@ bool OutputDevice::ImplIsUnderlineAbove( const Font& rFont )
return false;
}
-void OutputDevice::ImplInitFontList() const
-{
- if( !mpFontCollection->Count() )
- {
- if( mpGraphics || ImplGetGraphics() )
- {
- SAL_INFO( "vcl.gdi", "OutputDevice::ImplInitFontList()" );
- mpGraphics->GetDevFontList( mpFontCollection );
-
- // There is absolutely no way there should be no fonts available on the device
- if( !mpFontCollection->Count() )
- {
- OUString aError( "Application error: no fonts and no vcl resource found on your system" );
- ResMgr* pMgr = ImplGetResMgr();
- if( pMgr )
- {
- OUString aResStr(ResId(SV_ACCESSERROR_NO_FONTS, *pMgr).toString());
- if( !aResStr.isEmpty() )
- aError = aResStr;
- }
- Application::Abort( aError );
- }
- }
- }
-}
-
-void OutputDevice::ImplInitFont() const
-{
- DBG_TESTSOLARMUTEX();
-
- if (!mpFontEntry)
- return;
-
- if ( mbInitFont )
- {
- if ( meOutDevType != OUTDEV_PRINTER )
- {
- // decide if antialiasing is appropriate
- bool bNonAntialiased = (GetAntialiasing() & ANTIALIASING_DISABLE_TEXT) != 0;
- const StyleSettings& rStyleSettings = GetSettings().GetStyleSettings();
- bNonAntialiased |= ((rStyleSettings.GetDisplayOptions() & DISPLAY_OPTION_AA_DISABLE) != 0);
- bNonAntialiased |= (int(rStyleSettings.GetAntialiasingMinPixelHeight()) > mpFontEntry->maFontSelData.mnHeight);
- mpFontEntry->maFontSelData.mbNonAntialiased = bNonAntialiased;
- }
-
- // select font in the device layers
- mpFontEntry->mnSetFontFlags = mpGraphics->SetFont( &(mpFontEntry->maFontSelData), 0 );
- mbInitFont = false;
- }
-}
-
void OutputDevice::ImplInitTextColor()
{
DBG_TESTSOLARMUTEX();
@@ -1245,169 +159,6 @@ void OutputDevice::ImplInitTextColor()
}
}
-bool OutputDevice::ImplNewFont() const
-{
- DBG_TESTSOLARMUTEX();
-
- // get correct font list on the PDF writer if necessary
- if( mpPDFWriter )
- {
- const ImplSVData* pSVData = ImplGetSVData();
- if( mpFontCollection == pSVData->maGDIData.mpScreenFontList
- || mpFontCache == pSVData->maGDIData.mpScreenFontCache )
- const_cast<OutputDevice&>(*this).ImplUpdateFontData( true );
- }
-
- if ( !mbNewFont )
- return true;
-
- // we need a graphics
- if ( !mpGraphics && !ImplGetGraphics() )
- return false;
- SalGraphics* pGraphics = mpGraphics;
- ImplInitFontList();
-
- // convert to pixel height
- // TODO: replace integer based aSize completely with subpixel accurate type
- float fExactHeight = ImplFloatLogicHeightToDevicePixel( static_cast<float>(maFont.GetHeight()) );
- Size aSize = ImplLogicToDevicePixel( maFont.GetSize() );
- if ( !aSize.Height() )
- {
- // use default pixel height only when logical height is zero
- if ( maFont.GetSize().Height() )
- aSize.Height() = 1;
- else
- aSize.Height() = (12*mnDPIY)/72;
- fExactHeight = static_cast<float>(aSize.Height());
- }
-
- // select the default width only when logical width is zero
- if( (0 == aSize.Width()) && (0 != maFont.GetSize().Width()) )
- aSize.Width() = 1;
-
- // get font entry
- ImplFontEntry* pOldEntry = mpFontEntry;
- mpFontEntry = mpFontCache->GetFontEntry( mpFontCollection, maFont, aSize, fExactHeight );
- if( pOldEntry )
- mpFontCache->Release( pOldEntry );
-
- ImplFontEntry* pFontEntry = mpFontEntry;
-
- if (!pFontEntry)
- return false;
-
- // mark when lower layers need to get involved
- mbNewFont = false;
- if( pFontEntry != pOldEntry )
- mbInitFont = true;
-
- // select font when it has not been initialized yet
- if ( !pFontEntry->mbInit )
- {
- ImplInitFont();
-
- // get metric data from device layers
- if ( pGraphics )
- {
- pFontEntry->mbInit = true;
-
- pFontEntry->maMetric.mnOrientation = sal::static_int_cast<short>(pFontEntry->maFontSelData.mnOrientation);
- pGraphics->GetFontMetric( &(pFontEntry->maMetric) );
-
- pFontEntry->maMetric.ImplInitTextLineSize( this );
- pFontEntry->maMetric.ImplInitAboveTextLineSize();
-
- pFontEntry->mnLineHeight = pFontEntry->maMetric.mnAscent + pFontEntry->maMetric.mnDescent;
-
- if( pFontEntry->maFontSelData.mnOrientation
- && !pFontEntry->maMetric.mnOrientation
- && (meOutDevType != OUTDEV_PRINTER) )
- {
- pFontEntry->mnOwnOrientation = sal::static_int_cast<short>(pFontEntry->maFontSelData.mnOrientation);
- pFontEntry->mnOrientation = pFontEntry->mnOwnOrientation;
- }
- else
- pFontEntry->mnOrientation = pFontEntry->maMetric.mnOrientation;
- }
- }
-
- // enable kerning array if requested
- if ( maFont.GetKerning() & KERNING_FONTSPECIFIC )
- {
- // TODO: test if physical font supports kerning and disable if not
- if( pFontEntry->maMetric.mbKernableFont )
- mbKerning = true;
- }
- else
- mbKerning = false;
- if ( maFont.GetKerning() & KERNING_ASIAN )
- mbKerning = true;
-
- // calculate EmphasisArea
- mnEmphasisAscent = 0;
- mnEmphasisDescent = 0;
- if ( maFont.GetEmphasisMark() & EMPHASISMARK_STYLE )
- {
- FontEmphasisMark nEmphasisMark = ImplGetEmphasisMarkStyle( maFont );
- long nEmphasisHeight = (pFontEntry->mnLineHeight*250)/1000;
- if ( nEmphasisHeight < 1 )
- nEmphasisHeight = 1;
- if ( nEmphasisMark & EMPHASISMARK_POS_BELOW )
- mnEmphasisDescent = nEmphasisHeight;
- else
- mnEmphasisAscent = nEmphasisHeight;
- }
-
- // calculate text offset depending on TextAlignment
- TextAlign eAlign = maFont.GetAlign();
- if ( eAlign == ALIGN_BASELINE )
- {
- mnTextOffX = 0;
- mnTextOffY = 0;
- }
- else if ( eAlign == ALIGN_TOP )
- {
- mnTextOffX = 0;
- mnTextOffY = +pFontEntry->maMetric.mnAscent + mnEmphasisAscent;
- if ( pFontEntry->mnOrientation )
- ImplRotatePos( 0, 0, mnTextOffX, mnTextOffY, pFontEntry->mnOrientation );
- }
- else // eAlign == ALIGN_BOTTOM
- {
- mnTextOffX = 0;
- mnTextOffY = -pFontEntry->maMetric.mnDescent + mnEmphasisDescent;
- if ( pFontEntry->mnOrientation )
- ImplRotatePos( 0, 0, mnTextOffX, mnTextOffY, pFontEntry->mnOrientation );
- }
-
- mbTextLines = ((maFont.GetUnderline() != UNDERLINE_NONE) && (maFont.GetUnderline() != UNDERLINE_DONTKNOW)) ||
- ((maFont.GetOverline() != UNDERLINE_NONE) && (maFont.GetOverline() != UNDERLINE_DONTKNOW)) ||
- ((maFont.GetStrikeout() != STRIKEOUT_NONE) && (maFont.GetStrikeout() != STRIKEOUT_DONTKNOW));
- mbTextSpecial = maFont.IsShadow() || maFont.IsOutline() ||
- (maFont.GetRelief() != RELIEF_NONE);
-
- // #95414# fix for OLE objects which use scale factors very creatively
- if( mbMap && !aSize.Width() )
- {
- int nOrigWidth = pFontEntry->maMetric.mnWidth;
- float fStretch = (float)maMapRes.mnMapScNumX * maMapRes.mnMapScDenomY;
- fStretch /= (float)maMapRes.mnMapScNumY * maMapRes.mnMapScDenomX;
- int nNewWidth = (int)(nOrigWidth * fStretch + 0.5);
- if( (nNewWidth != nOrigWidth) && (nNewWidth != 0) )
- {
- Size aOrigSize = maFont.GetSize();
- const_cast<Font&>(maFont).SetSize( Size( nNewWidth, aSize.Height() ) );
- mbMap = false;
- mbNewFont = true;
- ImplNewFont(); // recurse once using stretched width
- mbMap = true;
- const_cast<Font&>(maFont).SetSize( aOrigSize );
- }
- }
-
- return true;
-}
-
void OutputDevice::ImplDrawTextRect( long nBaseX, long nBaseY,
long nDistX, long nDistY, long nWidth, long nHeight )
{
@@ -1532,223 +283,6 @@ void OutputDevice::ImplInitAboveTextLineSize()
mpFontEntry->maMetric.ImplInitAboveTextLineSize();
}
-bool ImplFontAttributes::operator==(const ImplFontAttributes& rOther) const
-{
- if (maName != rOther.maName)
- return false;
-
- if (maStyleName != rOther.maStyleName)
- return false;
-
- if (meWeight != rOther.meWeight)
- return false;
-
- if (meItalic != rOther.meItalic)
- return false;
-
- if (meFamily != rOther.meFamily)
- return false;
-
- if (mePitch != rOther.mePitch)
- return false;
-
- if (meWidthType != rOther.meWidthType)
- return false;
-
- if (mbSymbolFlag != rOther.mbSymbolFlag)
- return false;
-
- return true;
-}
-
-ImplFontMetricData::ImplFontMetricData( const FontSelectPattern& rFontSelData )
- : ImplFontAttributes( rFontSelData )
- , mnWidth ( rFontSelData.mnWidth)
- , mnOrientation( (short)(rFontSelData.mnOrientation))
- , mnAscent( 0 )
- , mnDescent( 0 )
- , mnIntLeading( 0 )
- , mnExtLeading( 0 )
- , mnSlant( 0 )
- , mnMinKashida( 0 )
- , mnUnderlineSize( 0 )
- , mnUnderlineOffset( 0 )
- , mnBUnderlineSize( 0 )
- , mnBUnderlineOffset( 0 )
- , mnDUnderlineSize( 0 )
- , mnDUnderlineOffset1( 0 )
- , mnDUnderlineOffset2( 0 )
- , mnWUnderlineSize( 0 )
- , mnWUnderlineOffset( 0 )
- , mnAboveUnderlineSize( 0 )
- , mnAboveUnderlineOffset( 0 )
- , mnAboveBUnderlineSize( 0 )
- , mnAboveBUnderlineOffset( 0 )
- , mnAboveDUnderlineSize( 0 )
- , mnAboveDUnderlineOffset1( 0 )
- , mnAboveDUnderlineOffset2( 0 )
- , mnAboveWUnderlineSize( 0 )
- , mnAboveWUnderlineOffset( 0 )
- , mnStrikeoutSize( 0 )
- , mnStrikeoutOffset( 0 )
- , mnBStrikeoutSize( 0 )
- , mnBStrikeoutOffset( 0 )
- , mnDStrikeoutSize( 0 )
- , mnDStrikeoutOffset1( 0 )
- , mnDStrikeoutOffset2( 0 )
-{
- // intialize the used font name
- if( rFontSelData.mpFontData )
- {
- SetFamilyName( rFontSelData.mpFontData->GetFamilyName() );
- SetStyleName( rFontSelData.mpFontData->GetStyleName() );
- mbDevice = rFontSelData.mpFontData->mbDevice;
- mbKernableFont = true;
- }
- else
- {
- sal_Int32 nTokenPos = 0;
- SetFamilyName( GetNextFontToken( rFontSelData.GetFamilyName(), nTokenPos ) );
- SetStyleName( rFontSelData.GetStyleName() );
- mbDevice = false;
- mbKernableFont = false;
- }
-}
-
-void ImplFontMetricData::ImplInitTextLineSize( const OutputDevice* pDev )
-{
- long nDescent = mnDescent;
- if ( nDescent <= 0 )
- {
- nDescent = mnAscent / 10;
- if ( !nDescent )
- nDescent = 1;
- }
-
- // #i55341# for some fonts it is not a good idea to calculate
- // their text line metrics from the real font descent
- // => work around this problem just for these fonts
- if( 3*nDescent > mnAscent )
- nDescent = mnAscent / 3;
-
- long nLineHeight = ((nDescent*25)+50) / 100;
- if ( !nLineHeight )
- nLineHeight = 1;
- long nLineHeight2 = nLineHeight / 2;
- if ( !nLineHeight2 )
- nLineHeight2 = 1;
-
- long nBLineHeight = ((nDescent*50)+50) / 100;
- if ( nBLineHeight == nLineHeight )
- nBLineHeight++;
- long nBLineHeight2 = nBLineHeight/2;
- if ( !nBLineHeight2 )
- nBLineHeight2 = 1;
-
- long n2LineHeight = ((nDescent*16)+50) / 100;
- if ( !n2LineHeight )
- n2LineHeight = 1;
- long n2LineDY = n2LineHeight;
- /* #117909#
- * add some pixels to minimum double line distance on higher resolution devices
- */
- long nMin2LineDY = 1 + pDev->ImplGetDPIY()/150;
- if ( n2LineDY < nMin2LineDY )
- n2LineDY = nMin2LineDY;
- long n2LineDY2 = n2LineDY/2;
- if ( !n2LineDY2 )
- n2LineDY2 = 1;
-
- long nUnderlineOffset = mnDescent/2 + 1;
- long nStrikeoutOffset = -((mnAscent - mnIntLeading) / 3);
-
- mnUnderlineSize = nLineHeight;
- mnUnderlineOffset = nUnderlineOffset - nLineHeight2;
-
- mnBUnderlineSize = nBLineHeight;
- mnBUnderlineOffset = nUnderlineOffset - nBLineHeight2;
-
- mnDUnderlineSize = n2LineHeight;
- mnDUnderlineOffset1 = nUnderlineOffset - n2LineDY2 - n2LineHeight;
- mnDUnderlineOffset2 = mnDUnderlineOffset1 + n2LineDY + n2LineHeight;
-
- long nWCalcSize = mnDescent;
- if ( nWCalcSize < 6 )
- {
- if ( (nWCalcSize == 1) || (nWCalcSize == 2) )
- mnWUnderlineSize = nWCalcSize;
- else
- mnWUnderlineSize = 3;
- }
- else
- mnWUnderlineSize = ((nWCalcSize*50)+50) / 100;
-
- // #109280# the following line assures that wavelnes are never placed below the descent, however
- // for most fonts the waveline then is drawn into the text, so we better keep the old solution
- // pFontEntry->maMetric.mnWUnderlineOffset = pFontEntry->maMetric.mnDescent + 1 - pFontEntry->maMetric.mnWUnderlineSize;
- mnWUnderlineOffset = nUnderlineOffset;
-
- mnStrikeoutSize = nLineHeight;
- mnStrikeoutOffset = nStrikeoutOffset - nLineHeight2;
-
- mnBStrikeoutSize = nBLineHeight;
- mnBStrikeoutOffset = nStrikeoutOffset - nBLineHeight2;
-
- mnDStrikeoutSize = n2LineHeight;
- mnDStrikeoutOffset1 = nStrikeoutOffset - n2LineDY2 - n2LineHeight;
- mnDStrikeoutOffset2 = mnDStrikeoutOffset1 + n2LineDY + n2LineHeight;
-}
-
-void ImplFontMetricData::ImplInitAboveTextLineSize()
-{
- long nIntLeading = mnIntLeading;
- // TODO: assess usage of nLeading below (changed in extleading CWS)
- // if no leading is available, we assume 15% of the ascent
- if ( nIntLeading <= 0 )
- {
- nIntLeading = mnAscent*15/100;
- if ( !nIntLeading )
- nIntLeading = 1;
- }
-
- long nLineHeight = ((nIntLeading*25)+50) / 100;
- if ( !nLineHeight )
- nLineHeight = 1;
-
- long nBLineHeight = ((nIntLeading*50)+50) / 100;
- if ( nBLineHeight == nLineHeight )
- nBLineHeight++;
-
- long n2LineHeight = ((nIntLeading*16)+50) / 100;
- if ( !n2LineHeight )
- n2LineHeight = 1;
-
- long nCeiling = -mnAscent;
-
- mnAboveUnderlineSize = nLineHeight;
- mnAboveUnderlineOffset = nCeiling + (nIntLeading - nLineHeight + 1) / 2;
-
- mnAboveBUnderlineSize = nBLineHeight;
- mnAboveBUnderlineOffset = nCeiling + (nIntLeading - nBLineHeight + 1) / 2;
-
- mnAboveDUnderlineSize = n2LineHeight;
- mnAboveDUnderlineOffset1 = nCeiling + (nIntLeading - 3*n2LineHeight + 1) / 2;
- mnAboveDUnderlineOffset2 = nCeiling + (nIntLeading + n2LineHeight + 1) / 2;
-
- long nWCalcSize = nIntLeading;
- if ( nWCalcSize < 6 )
- {
- if ( (nWCalcSize == 1) || (nWCalcSize == 2) )
- mnAboveWUnderlineSize = nWCalcSize;
- else
- mnAboveWUnderlineSize = 3;
- }
- else
- mnAboveWUnderlineSize = ((nWCalcSize*50)+50) / 100;
-
- mnAboveWUnderlineOffset = nCeiling + (nIntLeading + 1) / 2;
-}
-
static void ImplDrawWavePixel( long nOriginX, long nOriginY,
long nCurX, long nCurY,
short nOrientation,
@@ -2478,284 +1012,6 @@ void OutputDevice::ImplDrawMnemonicLine( long nX, long nY, long nWidth )
ImplDrawTextLine( nX, nY, 0, nWidth, STRIKEOUT_NONE, UNDERLINE_SINGLE, UNDERLINE_NONE, false );
}
-void OutputDevice::ImplGetEmphasisMark( PolyPolygon& rPolyPoly, bool& rPolyLine,
- Rectangle& rRect1, Rectangle& rRect2,
- long& rYOff, long& rWidth,
- FontEmphasisMark eEmphasis,
- long nHeight, short /*nOrient*/ )
-{
- static const sal_uInt8 aAccentPolyFlags[24] =
- {
- 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 2, 2, 0, 0, 2, 0, 2, 2
- };
-
- static const long aAccentPos[48] =
- {
- 78, 0,
- 348, 79,
- 599, 235,
- 843, 469,
- 938, 574,
- 990, 669,
- 990, 773,
- 990, 843,
- 964, 895,
- 921, 947,
- 886, 982,
- 860, 999,
- 825, 999,
- 764, 999,
- 721, 964,
- 686, 895,
- 625, 791,
- 556, 660,
- 469, 504,
- 400, 400,
- 261, 252,
- 61, 61,
- 0, 27,
- 9, 0
- };
-
- rWidth = 0;
- rYOff = 0;
- rPolyLine = false;
-
- if ( !nHeight )
- return;
-
- FontEmphasisMark nEmphasisStyle = eEmphasis & EMPHASISMARK_STYLE;
- long nDotSize = 0;
- switch ( nEmphasisStyle )
- {
- case EMPHASISMARK_DOT:
- // Dot has 55% of the height
- nDotSize = (nHeight*550)/1000;
- if ( !nDotSize )
- nDotSize = 1;
- if ( nDotSize <= 2 )
- rRect1 = Rectangle( Point(), Size( nDotSize, nDotSize ) );
- else
- {
- long nRad = nDotSize/2;
- Polygon aPoly( Point( nRad, nRad ), nRad, nRad );
- rPolyPoly.Insert( aPoly );
- }
- rYOff = ((nHeight*250)/1000)/2; // Center to the another EmphasisMarks
- rWidth = nDotSize;
- break;
-
- case EMPHASISMARK_CIRCLE:
- // Dot has 80% of the height
- nDotSize = (nHeight*800)/1000;
- if ( !nDotSize )
- nDotSize = 1;
- if ( nDotSize <= 2 )
- rRect1 = Rectangle( Point(), Size( nDotSize, nDotSize ) );
- else
- {
- long nRad = nDotSize/2;
- Polygon aPoly( Point( nRad, nRad ), nRad, nRad );
- rPolyPoly.Insert( aPoly );
- // BorderWidth is 15%
- long nBorder = (nDotSize*150)/1000;
- if ( nBorder <= 1 )
- rPolyLine = true;
- else
- {
- Polygon aPoly2( Point( nRad, nRad ),
- nRad-nBorder, nRad-nBorder );
- rPolyPoly.Insert( aPoly2 );
- }
- }
- rWidth = nDotSize;
- break;
-
- case EMPHASISMARK_DISC:
- // Dot has 80% of the height
- nDotSize = (nHeight*800)/1000;
- if ( !nDotSize )
- nDotSize = 1;
- if ( nDotSize <= 2 )
- rRect1 = Rectangle( Point(), Size( nDotSize, nDotSize ) );
- else
- {
- long nRad = nDotSize/2;
- Polygon aPoly( Point( nRad, nRad ), nRad, nRad );
- rPolyPoly.Insert( aPoly );
- }
- rWidth = nDotSize;
- break;
-
- case EMPHASISMARK_ACCENT:
- // Dot has 80% of the height
- nDotSize = (nHeight*800)/1000;
- if ( !nDotSize )
- nDotSize = 1;
- if ( nDotSize <= 2 )
- {
- if ( nDotSize == 1 )
- {
- rRect1 = Rectangle( Point(), Size( nDotSize, nDotSize ) );
- rWidth = nDotSize;
- }
- else
- {
- rRect1 = Rectangle( Point(), Size( 1, 1 ) );
- rRect2 = Rectangle( Point( 1, 1 ), Size( 1, 1 ) );
- }
- }
- else
- {
- Polygon aPoly( sizeof( aAccentPos ) / sizeof( long ) / 2,
- (const Point*)aAccentPos,
- aAccentPolyFlags );
- double dScale = ((double)nDotSize)/1000.0;
- aPoly.Scale( dScale, dScale );
- Polygon aTemp;
- aPoly.AdaptiveSubdivide( aTemp );
- Rectangle aBoundRect = aTemp.GetBoundRect();
- rWidth = aBoundRect.GetWidth();
- nDotSize = aBoundRect.GetHeight();
- rPolyPoly.Insert( aTemp );
- }
- break;
- }
-
- // calculate position
- long nOffY = 1+(mnDPIY/300); // one visible pixel space
- long nSpaceY = nHeight-nDotSize;
- if ( nSpaceY >= nOffY*2 )
- rYOff += nOffY;
- if ( !(eEmphasis & EMPHASISMARK_POS_BELOW) )
- rYOff += nDotSize;
-}
-
-void OutputDevice::ImplDrawEmphasisMark( long nBaseX, long nX, long nY,
- const PolyPolygon& rPolyPoly, bool bPolyLine,
- const Rectangle& rRect1, const Rectangle& rRect2 )
-{
- if( IsRTLEnabled() )
- // --- RTL --- mirror at basex
- nX = nBaseX - (nX - nBaseX - 1);
-
- nX -= mnOutOffX;
- nY -= mnOutOffY;
-
- if ( rPolyPoly.Count() )
- {
- if ( bPolyLine )
- {
- Polygon aPoly = rPolyPoly.GetObject( 0 );
- aPoly.Move( nX, nY );
- DrawPolyLine( aPoly );
- }
- else
- {
- PolyPolygon aPolyPoly = rPolyPoly;
- aPolyPoly.Move( nX, nY );
- DrawPolyPolygon( aPolyPoly );
- }
- }
-
- if ( !rRect1.IsEmpty() )
- {
- Rectangle aRect( Point( nX+rRect1.Left(),
- nY+rRect1.Top() ), rRect1.GetSize() );
- DrawRect( aRect );
- }
-
- if ( !rRect2.IsEmpty() )
- {
- Rectangle aRect( Point( nX+rRect2.Left(),
- nY+rRect2.Top() ), rRect2.GetSize() );
-
- DrawRect( aRect );
- }
-}
-
-void OutputDevice::ImplDrawEmphasisMarks( SalLayout& rSalLayout )
-{
- Color aOldLineColor = GetLineColor();
- Color aOldFillColor = GetFillColor();
- bool bOldMap = mbMap;
- GDIMetaFile* pOldMetaFile = mpMetaFile;
- mpMetaFile = NULL;
- EnableMapMode( false );
-
- FontEmphasisMark nEmphasisMark = ImplGetEmphasisMarkStyle( maFont );
- PolyPolygon aPolyPoly;
- Rectangle aRect1;
- Rectangle aRect2;
- long nEmphasisYOff;
- long nEmphasisWidth;
- long nEmphasisHeight;
- bool bPolyLine;
-
- if ( nEmphasisMark & EMPHASISMARK_POS_BELOW )
- nEmphasisHeight = mnEmphasisDescent;
- else
- nEmphasisHeight = mnEmphasisAscent;
-
- ImplGetEmphasisMark( aPolyPoly, bPolyLine,
- aRect1, aRect2,
- nEmphasisYOff, nEmphasisWidth,
- nEmphasisMark,
- nEmphasisHeight, mpFontEntry->mnOrientation );
-
- if ( bPolyLine )
- {
- SetLineColor( GetTextColor() );
- SetFillColor();
- }
- else
- {
- SetLineColor();
- SetFillColor( GetTextColor() );
- }
-
- Point aOffset = Point(0,0);
-
- if ( nEmphasisMark & EMPHASISMARK_POS_BELOW )
- aOffset.Y() += mpFontEntry->maMetric.mnDescent + nEmphasisYOff;
- else
- aOffset.Y() -= mpFontEntry->maMetric.mnAscent + nEmphasisYOff;
-
- long nEmphasisWidth2 = nEmphasisWidth / 2;
- long nEmphasisHeight2 = nEmphasisHeight / 2;
- aOffset += Point( nEmphasisWidth2, nEmphasisHeight2 );
-
- Point aOutPoint;
- Rectangle aRectangle;
- for( int nStart = 0;;)
- {
- sal_GlyphId aGlyphId;
- if( !rSalLayout.GetNextGlyphs( 1, &aGlyphId, aOutPoint, nStart ) )
- break;
-
- if( !mpGraphics->GetGlyphBoundRect( aGlyphId, aRectangle ) )
- continue;
-
- if( !rSalLayout.IsSpacingGlyph( aGlyphId ) )
- {
- Point aAdjPoint = aOffset;
- aAdjPoint.X() += aRectangle.Left() + (aRectangle.GetWidth() - nEmphasisWidth) / 2;
- if ( mpFontEntry->mnOrientation )
- ImplRotatePos( 0, 0, aAdjPoint.X(), aAdjPoint.Y(), mpFontEntry->mnOrientation );
- aOutPoint += aAdjPoint;
- aOutPoint -= Point( nEmphasisWidth2, nEmphasisHeight2 );
- ImplDrawEmphasisMark( rSalLayout.DrawBase().X(),
- aOutPoint.X(), aOutPoint.Y(),
- aPolyPoly, bPolyLine, aRect1, aRect2 );
- }
- }
-
- SetLineColor( aOldLineColor );
- SetFillColor( aOldFillColor );
- EnableMapMode( bOldMap );
- mpMetaFile = pOldMetaFile;
-}
-
bool OutputDevice::ImplDrawRotateText( SalLayout& rSalLayout )
{
int nX = rSalLayout.DrawBase().X();
@@ -3248,113 +1504,6 @@ void OutputDevice::SetAntialiasing( sal_uInt16 nMode )
mpAlphaVDev->SetAntialiasing( nMode );
}
-void OutputDevice::SetFont( const Font& rNewFont )
-{
-
- Font aFont( rNewFont );
- aFont.SetLanguage(rNewFont.GetLanguage());
- if ( mnDrawMode & (DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT | DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT | DRAWMODE_SETTINGSTEXT |
- DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL | DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
- DRAWMODE_GHOSTEDFILL | DRAWMODE_SETTINGSFILL ) )
- {
- Color aTextColor( aFont.GetColor() );
-
- if ( mnDrawMode & DRAWMODE_BLACKTEXT )
- aTextColor = Color( COL_BLACK );
- else if ( mnDrawMode & DRAWMODE_WHITETEXT )
- aTextColor = Color( COL_WHITE );
- else if ( mnDrawMode & DRAWMODE_GRAYTEXT )
- {
- const sal_uInt8 cLum = aTextColor.GetLuminance();
- aTextColor = Color( cLum, cLum, cLum );
- }
- else if ( mnDrawMode & DRAWMODE_SETTINGSTEXT )
- aTextColor = GetSettings().GetStyleSettings().GetFontColor();
-
- if ( mnDrawMode & DRAWMODE_GHOSTEDTEXT )
- {
- aTextColor = Color( (aTextColor.GetRed() >> 1 ) | 0x80,
- (aTextColor.GetGreen() >> 1 ) | 0x80,
- (aTextColor.GetBlue() >> 1 ) | 0x80 );
- }
-
- aFont.SetColor( aTextColor );
-
- bool bTransFill = aFont.IsTransparent();
- if ( !bTransFill )
- {
- Color aTextFillColor( aFont.GetFillColor() );
-
- if ( mnDrawMode & DRAWMODE_BLACKFILL )
- aTextFillColor = Color( COL_BLACK );
- else if ( mnDrawMode & DRAWMODE_WHITEFILL )
- aTextFillColor = Color( COL_WHITE );
- else if ( mnDrawMode & DRAWMODE_GRAYFILL )
- {
- const sal_uInt8 cLum = aTextFillColor.GetLuminance();
- aTextFillColor = Color( cLum, cLum, cLum );
- }
- else if( mnDrawMode & DRAWMODE_SETTINGSFILL )
- aTextFillColor = GetSettings().GetStyleSettings().GetWindowColor();
- else if ( mnDrawMode & DRAWMODE_NOFILL )
- {
- aTextFillColor = Color( COL_TRANSPARENT );
- bTransFill = true;
- }
-
- if ( !bTransFill && (mnDrawMode & DRAWMODE_GHOSTEDFILL) )
- {
- aTextFillColor = Color( (aTextFillColor.GetRed() >> 1) | 0x80,
- (aTextFillColor.GetGreen() >> 1) | 0x80,
- (aTextFillColor.GetBlue() >> 1) | 0x80 );
- }
-
- aFont.SetFillColor( aTextFillColor );
- }
- }
-
- if ( mpMetaFile )
- {
- mpMetaFile->AddAction( new MetaFontAction( aFont ) );
- // the color and alignment actions don't belong here
- // TODO: get rid of them without breaking anything...
- mpMetaFile->AddAction( new MetaTextAlignAction( aFont.GetAlign() ) );
- mpMetaFile->AddAction( new MetaTextFillColorAction( aFont.GetFillColor(), !aFont.IsTransparent() ) );
- }
-
- if ( !maFont.IsSameInstance( aFont ) )
- {
- // Optimization MT/HDU: COL_TRANSPARENT means SetFont should ignore the font color,
- // because SetTextColor() is used for this.
- // #i28759# maTextColor might have been changed behind our back, commit then, too.
- if( aFont.GetColor() != COL_TRANSPARENT
- && (aFont.GetColor() != maFont.GetColor() || aFont.GetColor() != maTextColor ) )
- {
- maTextColor = aFont.GetColor();
- mbInitTextColor = true;
- if( mpMetaFile )
- mpMetaFile->AddAction( new MetaTextColorAction( aFont.GetColor() ) );
- }
- maFont = aFont;
- mbNewFont = true;
-
- if( mpAlphaVDev )
- {
- // #i30463#
- // Since SetFont might change the text color, apply that only
- // selectively to alpha vdev (which normally paints opaque text
- // with COL_BLACK)
- if( aFont.GetColor() != COL_TRANSPARENT )
- {
- mpAlphaVDev->SetTextColor( COL_BLACK );
- aFont.SetColor( COL_TRANSPARENT );
- }
-
- mpAlphaVDev->SetFont( aFont );
- }
- }
-}
-
void OutputDevice::SetLayoutMode( sal_uLong nTextLayoutMode )
{
if( mpMetaFile )
@@ -4234,105 +2383,6 @@ SalLayout* OutputDevice::ImplLayout(const OUString& rOrigStr,
return pSalLayout;
}
-SalLayout* OutputDevice::getFallbackFont(ImplFontEntry &rFallbackFont,
- FontSelectPattern &rFontSelData, int nFallbackLevel,
- ImplLayoutArgs& rLayoutArgs) const
-{
- rFallbackFont.mnSetFontFlags = mpGraphics->SetFont( &rFontSelData, nFallbackLevel );
-
- rLayoutArgs.ResetPos();
- SalLayout* pFallback = mpGraphics->GetTextLayout( rLayoutArgs, nFallbackLevel );
-
- if (!pFallback)
- return NULL;
-
- if (!pFallback->LayoutText(rLayoutArgs))
- {
- // there is no need for a font that couldn't resolve anything
- pFallback->Release();
- return NULL;
- }
-
- pFallback->AdjustLayout( rLayoutArgs );
-
- return pFallback;
-}
-
-SalLayout* OutputDevice::ImplGlyphFallbackLayout( SalLayout* pSalLayout, ImplLayoutArgs& rLayoutArgs ) const
-{
- // prepare multi level glyph fallback
- MultiSalLayout* pMultiSalLayout = NULL;
- ImplLayoutRuns aLayoutRuns = rLayoutArgs.maRuns;
- rLayoutArgs.PrepareFallback();
- rLayoutArgs.mnFlags |= SAL_LAYOUT_FOR_FALLBACK;
-
- // get list of unicodes that need glyph fallback
- int nCharPos = -1;
- bool bRTL = false;
- OUStringBuffer aMissingCodeBuf;
- while( rLayoutArgs.GetNextPos( &nCharPos, &bRTL) )
- aMissingCodeBuf.append( rLayoutArgs.mpStr[ nCharPos ] );
- rLayoutArgs.ResetPos();
- OUString aMissingCodes = aMissingCodeBuf.makeStringAndClear();
-
- FontSelectPattern aFontSelData = mpFontEntry->maFontSelData;
-
- // try if fallback fonts support the missing unicodes
- for( int nFallbackLevel = 1; nFallbackLevel < MAX_FALLBACK; ++nFallbackLevel )
- {
- // find a font family suited for glyph fallback
-#ifndef FONTFALLBACK_HOOKS_DISABLED
- // GetGlyphFallbackFont() needs a valid aFontSelData.mpFontEntry
- // if the system-specific glyph fallback is active
- aFontSelData.mpFontEntry = mpFontEntry; // reset the fontentry to base-level
-#endif
- ImplFontEntry* pFallbackFont = mpFontCache->GetGlyphFallbackFont( mpFontCollection,
- aFontSelData, nFallbackLevel, aMissingCodes );
- if( !pFallbackFont )
- break;
-
- aFontSelData.mpFontEntry = pFallbackFont;
- aFontSelData.mpFontData = pFallbackFont->maFontSelData.mpFontData;
- if( mpFontEntry && nFallbackLevel < MAX_FALLBACK-1)
- {
- // ignore fallback font if it is the same as the original font
- if( mpFontEntry->maFontSelData.mpFontData == aFontSelData.mpFontData )
- {
- mpFontCache->Release( pFallbackFont );
- continue;
- }
- }
-
- // create and add glyph fallback layout to multilayout
- SalLayout* pFallback = getFallbackFont(*pFallbackFont, aFontSelData,
- nFallbackLevel, rLayoutArgs);
- if (pFallback)
- {
- if( !pMultiSalLayout )
- pMultiSalLayout = new MultiSalLayout( *pSalLayout );
- pMultiSalLayout->AddFallback( *pFallback,
- rLayoutArgs.maRuns, aFontSelData.mpFontData );
- if (nFallbackLevel == MAX_FALLBACK-1)
- pMultiSalLayout->SetInComplete();
- }
-
- mpFontCache->Release( pFallbackFont );
-
- // break when this fallback was sufficient
- if( !rLayoutArgs.PrepareFallback() )
- break;
- }
-
- if( pMultiSalLayout && pMultiSalLayout->LayoutText( rLayoutArgs ) )
- pSalLayout = pMultiSalLayout;
-
- // restore orig font settings
- pSalLayout->InitFont();
- rLayoutArgs.maRuns = aLayoutRuns;
-
- return pSalLayout;
-}
-
bool OutputDevice::GetTextIsRTL( const OUString& rString, sal_Int32 nIndex, sal_Int32 nLen ) const
{
OUString aStr( rString );
@@ -5242,191 +3292,6 @@ OUString OutputDevice::GetNonMnemonicString( const OUString& rStr, sal_Int32& rM
return aStr;
}
-int OutputDevice::GetDevFontCount() const
-{
-
- if( !mpGetDevFontList )
- mpGetDevFontList = mpFontCollection->GetDevFontList();
- return mpGetDevFontList->Count();
-}
-
-FontInfo OutputDevice::GetDevFont( int nDevFontIndex ) const
-{
-
- FontInfo aFontInfo;
-
- ImplInitFontList();
-
- int nCount = GetDevFontCount();
- if( nDevFontIndex < nCount )
- {
- const PhysicalFontFace& rData = *mpGetDevFontList->Get( nDevFontIndex );
- aFontInfo.SetName( rData.GetFamilyName() );
- aFontInfo.SetStyleName( rData.GetStyleName() );
- aFontInfo.SetCharSet( rData.IsSymbolFont() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
- aFontInfo.SetFamily( rData.GetFamilyType() );
- aFontInfo.SetPitch( rData.GetPitch() );
- aFontInfo.SetWeight( rData.GetWeight() );
- aFontInfo.SetItalic( rData.GetSlant() );
- aFontInfo.SetWidthType( rData.GetWidthType() );
- if( rData.IsScalable() )
- aFontInfo.mpImplMetric->mnMiscFlags |= ImplFontMetric::SCALABLE_FLAG;
- if( rData.mbDevice )
- aFontInfo.mpImplMetric->mnMiscFlags |= ImplFontMetric::DEVICE_FLAG;
- }
-
- return aFontInfo;
-}
-
-bool OutputDevice::AddTempDevFont( const OUString& rFileURL, const OUString& rFontName )
-{
-
- ImplInitFontList();
-
- if( !mpGraphics && !ImplGetGraphics() )
- return false;
-
- bool bRC = mpGraphics->AddTempDevFont( mpFontCollection, rFileURL, rFontName );
- if( !bRC )
- return false;
-
- if( mpAlphaVDev )
- mpAlphaVDev->AddTempDevFont( rFileURL, rFontName );
-
- mpFontCache->Invalidate();
- return true;
-}
-
-int OutputDevice::GetDevFontSizeCount( const Font& rFont ) const
-{
-
- delete mpGetDevSizeList;
-
- ImplInitFontList();
- mpGetDevSizeList = mpFontCollection->GetDevSizeList( rFont.GetName() );
- return mpGetDevSizeList->Count();
-}
-
-Size OutputDevice::GetDevFontSize( const Font& rFont, int nSizeIndex ) const
-{
-
- // check range
- int nCount = GetDevFontSizeCount( rFont );
- if ( nSizeIndex >= nCount )
- return Size();
-
- // when mapping is enabled round to .5 points
- Size aSize( 0, mpGetDevSizeList->Get( nSizeIndex ) );
- if ( mbMap )
- {
- aSize.Height() *= 10;
- MapMode aMap( MAP_10TH_INCH, Point(), Fraction( 1, 72 ), Fraction( 1, 72 ) );
- aSize = PixelToLogic( aSize, aMap );
- aSize.Height() += 5;
- aSize.Height() /= 10;
- long nRound = aSize.Height() % 5;
- if ( nRound >= 3 )
- aSize.Height() += (5-nRound);
- else
- aSize.Height() -= nRound;
- aSize.Height() *= 10;
- aSize = LogicToPixel( aSize, aMap );
- aSize = PixelToLogic( aSize );
- aSize.Height() += 5;
- aSize.Height() /= 10;
- }
- return aSize;
-}
-
-bool OutputDevice::IsFontAvailable( const OUString& rFontName ) const
-{
-
- PhysicalFontFamily* pFound = mpFontCollection->FindFontFamily( rFontName );
- return (pFound != NULL);
-}
-
-FontMetric OutputDevice::GetFontMetric() const
-{
-
- FontMetric aMetric;
- if( mbNewFont && !ImplNewFont() )
- return aMetric;
-
- ImplFontEntry* pEntry = mpFontEntry;
- ImplFontMetricData* pMetric = &(pEntry->maMetric);
-
- // prepare metric
- aMetric.Font::operator=( maFont );
-
- // set aMetric with info from font
- aMetric.SetName( maFont.GetName() );
- aMetric.SetStyleName( pMetric->GetStyleName() );
- aMetric.SetSize( PixelToLogic( Size( pMetric->mnWidth, pMetric->mnAscent+pMetric->mnDescent-pMetric->mnIntLeading ) ) );
- aMetric.SetCharSet( pMetric->IsSymbolFont() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE );
- aMetric.SetFamily( pMetric->GetFamilyType() );
- aMetric.SetPitch( pMetric->GetPitch() );
- aMetric.SetWeight( pMetric->GetWeight() );
- aMetric.SetItalic( pMetric->GetSlant() );
- aMetric.SetWidthType( pMetric->GetWidthType() );
- if ( pEntry->mnOwnOrientation )
- aMetric.SetOrientation( pEntry->mnOwnOrientation );
- else
- aMetric.SetOrientation( pMetric->mnOrientation );
- if( !pEntry->maMetric.mbKernableFont )
- aMetric.SetKerning( maFont.GetKerning() & ~KERNING_FONTSPECIFIC );
-
- // set remaining metric fields
- aMetric.mpImplMetric->mnMiscFlags = 0;
- if( pMetric->mbDevice )
- aMetric.mpImplMetric->mnMiscFlags |= ImplFontMetric::DEVICE_FLAG;
- if( pMetric->mbScalableFont )
- aMetric.mpImplMetric->mnMiscFlags |= ImplFontMetric::SCALABLE_FLAG;
- aMetric.mpImplMetric->mnAscent = ImplDevicePixelToLogicHeight( pMetric->mnAscent+mnEmphasisAscent );
- aMetric.mpImplMetric->mnDescent = ImplDevicePixelToLogicHeight( pMetric->mnDescent+mnEmphasisDescent );
- aMetric.mpImplMetric->mnIntLeading = ImplDevicePixelToLogicHeight( pMetric->mnIntLeading+mnEmphasisAscent );
- aMetric.mpImplMetric->mnExtLeading = ImplDevicePixelToLogicHeight( pMetric->mnExtLeading );
- aMetric.mpImplMetric->mnLineHeight = ImplDevicePixelToLogicHeight( pMetric->mnAscent+pMetric->mnDescent+mnEmphasisAscent+mnEmphasisDescent );
- aMetric.mpImplMetric->mnSlant = ImplDevicePixelToLogicHeight( pMetric->mnSlant );
-
-#ifdef UNX
- // backwards compatible line metrics after fixing #i60945#
- if( (meOutDevType == OUTDEV_VIRDEV)
- && static_cast<const VirtualDevice*>(this)->ForceZeroExtleadBug() )
- aMetric.mpImplMetric->mnExtLeading = 0;
-#endif
-
- return aMetric;
-}
-
-FontMetric OutputDevice::GetFontMetric( const Font& rFont ) const
-{
- // select font, query metrics, select original font again
- Font aOldFont = GetFont();
- const_cast<OutputDevice*>(this)->SetFont( rFont );
- FontMetric aMetric( GetFontMetric() );
- const_cast<OutputDevice*>(this)->SetFont( aOldFont );
- return aMetric;
-}
-
-/** OutputDevice::GetSysFontData
- *
- * @param nFallbacklevel Fallback font level (0 = best matching font)
- *
- * Retrieve detailed font information in platform independent structure
- *
- * @return SystemFontData
- **/
-SystemFontData OutputDevice::GetSysFontData(int nFallbacklevel) const
-{
- SystemFontData aSysFontData;
- aSysFontData.nSize = sizeof(aSysFontData);
-
- if (!mpGraphics) ImplGetGraphics();
- if (mpGraphics) aSysFontData = mpGraphics->GetSysFontData(nFallbacklevel);
-
- return aSysFontData;
-}
-
/** OutputDevice::GetSysTextLayoutData
*
* @param rStartPt Start point of the text
@@ -5500,71 +3365,6 @@ SystemTextLayoutData OutputDevice::GetSysTextLayoutData(const Point& rStartPt, c
return aSysLayoutData;
}
-long OutputDevice::GetMinKashida() const
-{
- if( mbNewFont && !ImplNewFont() )
- return 0;
-
- ImplFontEntry* pEntry = mpFontEntry;
- ImplFontMetricData* pMetric = &(pEntry->maMetric);
- return ImplDevicePixelToLogicWidth( pMetric->mnMinKashida );
-}
-
-sal_Int32 OutputDevice::ValidateKashidas ( const OUString& rTxt,
- sal_Int32 nIdx, sal_Int32 nLen,
- sal_Int32 nKashCount,
- const sal_Int32* pKashidaPos,
- sal_Int32* pKashidaPosDropped ) const
-{
- // do layout
- SalLayout* pSalLayout = ImplLayout( rTxt, nIdx, nLen );
- if( !pSalLayout )
- return 0;
- sal_Int32 nDropped = 0;
- for( int i = 0; i < nKashCount; ++i )
- {
- if( !pSalLayout->IsKashidaPosValid( pKashidaPos[ i ] ))
- {
- pKashidaPosDropped[ nDropped ] = pKashidaPos [ i ];
- ++nDropped;
- }
- }
- pSalLayout->Release();
- return nDropped;
-}
-
-bool OutputDevice::GetGlyphBoundRects( const Point& rOrigin, const OUString& rStr,
- int nIndex, int nLen, int nBase, MetricVector& rVector )
-{
-
- rVector.clear();
-
- if(nLen == 0x0FFFF)
- {
- SAL_INFO("sal.rtl.xub",
- "GetGlyphBoundRects Suspicious arguments nLen:" << nLen);
- }
-
- if( nIndex >= rStr.getLength() )
- return false;
-
- if( nLen < 0 || nIndex + nLen >= rStr.getLength() )
- {
- nLen = rStr.getLength() - nIndex;
- }
-
- Rectangle aRect;
- for( int i = 0; i < nLen; i++ )
- {
- if( !GetTextBoundRect( aRect, rStr, nBase, nIndex + i, 1 ) )
- break;
- aRect.Move( rOrigin.X(), rOrigin.Y() );
- rVector.push_back( aRect );
- }
-
- return (nLen == (int)rVector.size());
-}
-
bool OutputDevice::GetTextBoundRect( Rectangle& rRect,
const OUString& rStr, sal_Int32 nBase,
sal_Int32 nIndex, sal_Int32 nLen,
@@ -6033,109 +3833,4 @@ bool OutputDevice::GetTextOutline( PolyPolygon& rPolyPoly, const OUString& rStr,
return true;
}
-bool OutputDevice::GetFontCapabilities( FontCapabilities& rFontCapabilities ) const
-{
- // we need a graphics
- if( !mpGraphics && !ImplGetGraphics() )
- return false;
-
- if( mbNewFont )
- ImplNewFont();
- if( mbInitFont )
- ImplInitFont();
- if( !mpFontEntry )
- return false;
-
- return mpGraphics->GetImplFontCapabilities(rFontCapabilities);
-}
-
-bool OutputDevice::GetFontCharMap( FontCharMap& rFontCharMap ) const
-{
- rFontCharMap.Reset();
-
- // we need a graphics
- if( !mpGraphics && !ImplGetGraphics() )
- return false;
-
- if( mbNewFont )
- ImplNewFont();
- if( mbInitFont )
- ImplInitFont();
- if( !mpFontEntry )
- return false;
-
-#ifdef ENABLE_IFC_CACHE // a little font charmap cache helps considerably
- static const int NMAXITEMS = 16;
- static int nUsedItems = 0, nCurItem = 0;
-
- struct CharMapCacheItem { const PhysicalFontFace* mpFontData; FontCharMap maCharMap; };
- static CharMapCacheItem aCache[ NMAXITEMS ];
-
- const PhysicalFontFace* pFontData = mpFontEntry->maFontSelData.mpFontData;
-
- int i;
- for( i = nUsedItems; --i >= 0; )
- if( pFontData == aCache[i].mpFontData )
- break;
- if( i >= 0 ) // found in cache
- {
- rFontCharMap.Reset( aCache[i].maCharMap.mpImpl );
- }
- else // need to cache
-#endif // ENABLE_IFC_CACHE
- {
- const ImplFontCharMap* pNewMap = mpGraphics->GetImplFontCharMap();
- rFontCharMap.Reset( pNewMap );
-
-#ifdef ENABLE_IFC_CACHE
- // manage cache round-robin and insert data
- CharMapCacheItem& rItem = aCache[ nCurItem ];
- rItem.mpFontData = pFontData;
- rItem.maCharMap.Reset( pNewMap );
-
- if( ++nCurItem >= NMAXITEMS )
- nCurItem = 0;
-
- if( ++nUsedItems >= NMAXITEMS )
- nUsedItems = NMAXITEMS;
-#endif // ENABLE_IFC_CACHE
- }
-
- if( rFontCharMap.IsDefaultMap() )
- return false;
- return true;
-}
-
-sal_Int32 OutputDevice::HasGlyphs( const Font& rTempFont, const OUString& rStr,
- sal_Int32 nIndex, sal_Int32 nLen ) const
-{
- if( nIndex >= rStr.getLength() )
- return nIndex;
- sal_Int32 nEnd;
- if( nLen == -1 )
- nEnd = rStr.getLength();
- else
- nEnd = std::min( rStr.getLength(), nIndex + nLen );
-
- DBG_ASSERT( nIndex < nEnd, "StartPos >= EndPos?" );
- DBG_ASSERT( nEnd <= rStr.getLength(), "String too short" );
-
- // to get the map temporarily set font
- const Font aOrigFont = GetFont();
- const_cast<OutputDevice&>(*this).SetFont( rTempFont );
- FontCharMap aFontCharMap;
- bool bRet = GetFontCharMap( aFontCharMap );
- const_cast<OutputDevice&>(*this).SetFont( aOrigFont );
-
- // if fontmap is unknown assume it doesn't have the glyphs
- if( !bRet )
- return nIndex;
-
- for( sal_Int32 i = nIndex; nIndex < nEnd; ++i, ++nIndex )
- if( ! aFontCharMap.HasChar( rStr[i] ) )
- return nIndex;
-
- return -1;
-}
-
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */