Files
libreoffice/sw/source/core/txtnode/fntcache.cxx

2652 lines
98 KiB
C++
Raw Normal View History

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2000-09-18 23:08:29 +00:00
/*************************************************************************
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
2000-09-18 23:08:29 +00:00
*
* Copyright 2000, 2010 Oracle and/or its affiliates.
2000-09-18 23:08:29 +00:00
*
* OpenOffice.org - a multi-platform office productivity suite
2000-09-18 23:08:29 +00:00
*
* This file is part of OpenOffice.org.
2000-09-18 23:08:29 +00:00
*
* OpenOffice.org is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3
* only, as published by the Free Software Foundation.
2000-09-18 23:08:29 +00:00
*
* OpenOffice.org is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License version 3 for more details
* (a copy is included in the LICENSE file that accompanied this code).
2000-09-18 23:08:29 +00:00
*
* You should have received a copy of the GNU Lesser General Public License
* version 3 along with OpenOffice.org. If not, see
* <http://www.openoffice.org/license.html>
* for a copy of the LGPLv3 License.
2000-09-18 23:08:29 +00:00
*
************************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_sw.hxx"
2000-09-18 23:08:29 +00:00
#include <vcl/outdev.hxx>
#include <vcl/print.hxx>
#include <vcl/lineinfo.hxx>
2000-09-18 23:08:29 +00:00
#include <vcl/metric.hxx>
#include <vcl/window.hxx>
#include <vcl/svapp.hxx>
#include <com/sun/star/i18n/CharacterIteratorMode.hdl>
#include <com/sun/star/i18n/WordType.hdl>
#include <breakit.hxx>
2000-09-18 23:08:29 +00:00
#include <viewsh.hxx> // Bildschirmabgleich
#include <viewopt.hxx> // Bildschirmabgleich abschalten, ViewOption
#include <fntcache.hxx>
#include <IDocumentSettingAccess.hxx>
2000-09-18 23:08:29 +00:00
#include <swfont.hxx> // CH_BLANK + CH_BULLET
#include <wrong.hxx>
#include "dbg_lay.hxx"
2001-08-31 05:22:48 +00:00
#include <txtfrm.hxx> // SwTxtFrm
#include <pagefrm.hxx>
#include <pagedesc.hxx> // SwPageDesc
#include <tgrditem.hxx>
#include <scriptinfo.hxx>
#include <editeng/brshitem.hxx>
#include <tools/shl.hxx>
#include <swmodule.hxx>
#include <accessibilityoptions.hxx>
#include <svtools/accessibilityoptions.hxx>
#include <doc.hxx>
#include <editeng/fhgtitem.hxx>
#include <docsh.hxx>
#include <poolfmt.hrc>
2000-09-18 23:08:29 +00:00
using namespace ::com::sun::star;
2000-09-18 23:08:29 +00:00
// globale Variablen, werden in FntCache.Hxx bekanntgegeben
// Der FontCache wird in TxtInit.Cxx _TXTINIT erzeugt und in _TXTEXIT geloescht
SwFntCache *pFntCache = NULL;
// Letzter Font, der durch ChgFntCache eingestellt wurde.
SwFntObj *pLastFont = NULL;
// Die "MagicNumber", die den Fonts zur Identifizierung verpasst wird
sal_uInt8* pMagicNo = NULL;
2000-09-18 23:08:29 +00:00
Color *pWaveCol = 0;
long SwFntObj::nPixWidth;
MapMode* SwFntObj::pPixMap = NULL;
OutputDevice* SwFntObj::pPixOut = NULL;
extern sal_uInt16 UnMapDirection( sal_uInt16 nDir, const sal_Bool bVertFormat );
sal_uInt16 GetDefaultFontHeight( SwDrawTextInfo &rInf )
{
SwDocShell* pDocShell = rInf.GetShell()->GetDoc()->GetDocShell();
SfxStyleSheetBasePool* pBasePool = pDocShell->GetStyleSheetPool();
String aString(SW_RES(STR_POOLCOLL_STANDARD));
SfxStyleSheetBase* pStyle = pBasePool->Find( aString, (SfxStyleFamily)SFX_STYLE_FAMILY_PARA );
SfxItemSet& aTmpSet = pStyle->GetItemSet();
SvxFontHeightItem &aDefaultFontItem = (SvxFontHeightItem&)aTmpSet.Get(RES_CHRATR_CJK_FONTSIZE);
return (sal_uInt16)aDefaultFontItem.GetHeight();
}
2000-09-18 23:08:29 +00:00
/*************************************************************************
|*
|* SwFntCache::Flush()
|*
|*************************************************************************/
void SwFntCache::Flush( )
{
if ( pLastFont )
{
pLastFont->Unlock();
pLastFont = NULL;
}
SwCache::Flush( );
}
/*************************************************************************
|*
|* SwFntObj::SwFntObj(), ~SwFntObj()
|*
|*************************************************************************/
SwFntObj::SwFntObj( const SwSubFont &rFont, const void *pOwn, ViewShell *pSh ) :
SwCacheObj( (void*)pOwn ),
2001-02-13 07:56:40 +00:00
aFont( rFont ),
2000-09-18 23:08:29 +00:00
pScrFont( NULL ),
2001-02-13 07:56:40 +00:00
pPrtFont( &aFont ),
2000-09-18 23:08:29 +00:00
pPrinter( NULL ),
2001-02-13 07:56:40 +00:00
nPropWidth( rFont.GetPropWidth() )
2000-09-18 23:08:29 +00:00
{
nZoom = pSh ? pSh->GetViewOptions()->GetZoom() : USHRT_MAX;
nGuessedLeading = USHRT_MAX;
nExtLeading = USHRT_MAX;
2000-09-18 23:08:29 +00:00
nPrtAscent = USHRT_MAX;
nPrtHeight = USHRT_MAX;
bSymbol = RTL_TEXTENCODING_SYMBOL == aFont.GetCharSet();
2000-09-18 23:08:29 +00:00
bPaintBlank = ( UNDERLINE_NONE != aFont.GetUnderline()
|| UNDERLINE_NONE != aFont.GetOverline()
|| STRIKEOUT_NONE != aFont.GetStrikeout() )
&& !aFont.IsWordLineMode();
CWS-TOOLING: integrate CWS graphite01 2009-08-06 11:09:01 +0200 hdu r274708 : #i10000# fix build breaker for SYSTEM_GRAPHITE=NO 2009-07-21 12:01:52 +0200 hdu r274174 : #i93645# fix include files for EXT_USE_STLPORT 2009-07-21 11:51:07 +0200 hdu r274173 : #i93645# convert line-endings of files to be patched 2009-07-21 10:49:01 +0200 hdu r274170 : #i93645# adjust makefile.vc8 for HH-RelEng env (thanks ause) 2009-07-20 05:21:32 +0200 kstribley r274105 : attempt to fix Windows build error caused by NULL variable in nmake file 2009-07-16 10:22:36 +0200 hdu r274032 : #i69129# also use solar minor version to find graphite lib 2009-07-16 05:36:06 +0200 kstribley r274029 : allow windows build to have Graphite disabled with SAL_DISABLE_GRAPHITE 2009-07-15 13:59:22 +0200 hdu r274011 : #i69129# default to ENABLE_GRAPHITE=TRUE 2009-07-15 13:19:54 +0200 hdu r274008 : #i93645# ignore compile warnings for graphite 2009-07-15 13:18:25 +0200 hdu r274006 : #i93645# stlport needs libmath, use solar minor version to find matching libs 2009-07-15 09:21:13 +0200 hdu r273989 : #i100000# avoid compile warning 2009-07-14 12:19:08 +0200 hdu r273963 : CWS-TOOLING: rebase CWS graphite01 to trunk@273858 (milestone: DEV300:m52) 2009-07-13 06:54:56 +0200 kstribley r273912 : change to use standard file headers 2009-07-13 05:39:14 +0200 kstribley r273911 : Remove unnecessary change to configure.in as reported by Rene 2009-07-10 16:58:44 +0200 hdu r273902 : #i100000# fix compile for precompiled-header support 2009-07-02 13:48:26 +0200 kstribley r273647 : #69129# fix a graphite bug which could crash with fonts containing obscure GDL positioning rules 2009-07-02 01:44:02 +0200 rene r273616 : #i10000# we need to link with -licuuc 2009-07-01 04:02:20 +0200 kstribley r273540 : restore missing sdf files from base 2009-07-01 04:01:40 +0200 kstribley r273539 : restore missing sdf files from base 2009-07-01 04:01:12 +0200 kstribley r273538 : restore missing sdf files from base 2009-07-01 03:59:41 +0200 kstribley r273537 : restore missing sdf files from base 2009-06-29 10:16:51 +0200 kstribley r273456 : #i69129# fixes a bug which caused occasional incorrect linebreaking when graphite is asked to render a part of a cluster not containing a base 2009-06-27 10:43:58 +0200 kstribley r273445 : #i69129# added kashida support for justified RTL text 2009-06-01 12:57:06 +0200 kstribley r272476 : CWS-TOOLING: rebase CWS graphite01 to trunk@272291 (milestone: DEV300:m49) 2009-05-26 10:50:06 +0200 kstribley r272286 : #i69129# fixes a build error when NDEBUG is not defined 2009-05-25 13:14:06 +0200 kstribley r272237 : #i69129# enable debugging by fixing compile warnings 2009-05-25 13:07:47 +0200 kstribley r272234 : #i69129# added env variable to disable GRAPHITE at run time on linux and fixed a bug with a rare attachment sequence 2009-04-20 17:39:25 +0200 kstribley r271001 : CWS-TOOLING: rebase CWS graphite01 to trunk@270723 (milestone: DEV300:m46) 2009-04-18 07:11:33 +0200 kstribley r270957 : #i101178# attempt to fix buildbot builds by reordering configure.in 2009-04-14 17:37:07 +0200 kstribley r270801 : #i93645# tweak configure to enable graphite by default on windows and linux to assist testing with tinderbox build 2009-04-14 16:33:17 +0200 kstribley r270796 : #i96925# another fix for rtl fallback and add optional debug info in MultiSalLayout 2009-04-08 13:27:55 +0200 kstribley r270641 : #i69129# fix features after a bad merge 2009-04-08 13:26:34 +0200 kstribley r270640 : #i69129# add a patch for WinFont 2009-03-24 12:37:54 +0100 kstribley r269937 : #i69129# fix build error due to locale being included in method for features 2009-03-24 12:36:10 +0100 kstribley r269936 : #i93645# change patch variable and fix configure 2009-03-20 04:18:56 +0100 kstribley r269776 : CWS-TOOLING: rebase CWS graphite01 to trunk@269297 (milestone: DEV300:m43) 2009-03-01 13:10:59 +0100 kstribley r268622 : added a patch to improve handling of a font with bad graphite language feature tables #i93645# 2009-02-12 04:50:51 +0100 kstribley r267631 : #i93645# fix windows build for graphite 2.3.1 and remove unnecessary patch 2009-02-10 04:48:50 +0100 kstribley r267535 : #i93645# fix a build error with stlport on Ubuntu 8.10 x86 2009-02-10 03:51:10 +0100 kstribley r267534 : #i69129# remove legacy config_office 2009-02-07 19:12:54 +0100 kstribley r267482 : #i93645# upgrade to using silgraphite-2.3.1 2009-02-02 18:17:57 +0100 kstribley r267290 : #i69129# backout unwanted checkin 2009-02-02 17:44:03 +0100 kstribley r267281 : #i69129# backout erroneous update to aclocal.m4 2009-02-01 10:05:03 +0100 kstribley r267236 : #i69129# fix build error due to locale being added to set font attributes 2009-02-01 06:02:52 +0100 kstribley r267235 : #i69129# fix erroneous merge 2009-01-31 16:24:56 +0100 kstribley r267234 : #i69129# update configure.in solenv.in in their new locations with enable graphite 2009-01-31 10:53:18 +0100 kstribley r267232 : CWS-TOOLING: rebase CWS graphite01 to trunk@267171 (milestone: DEV300:m41) 2008-12-17 04:17:33 +0100 kstribley r265577 : #i93645# remove superfluous autoreconf check and autoconf patch 2008-12-16 10:07:20 +0100 rene r265529 : fix aclocal.m4 breakage 2008-12-16 05:13:29 +0100 kstribley r265520 : #i93645# change to autoconf && configure 2008-12-16 04:39:48 +0100 kstribley r265519 : #i93645# modified LD_FLAGS so that system graphite isn't pulled in by accident and fixed autoconf problem 2008-12-15 14:16:25 +0100 rene r265497 : check for working STL 2008-12-15 12:53:39 +0100 rene r265473 : revert broken check 2008-12-15 11:59:21 +0100 kstribley r265472 : #i93645# added check for system STL, since this is a requirement for system graphite to work correctly and moved the position of the check further down 2008-12-15 11:55:34 +0100 kstribley r265471 : #i93645# remove references to gr3ooo to allow system graphite to be used 2008-12-12 18:48:18 +0100 rene r265437 : fix link for system-graphite 2008-12-12 18:46:45 +0100 rene r265436 : the tarball is in graphite, remove obsolete check 2008-12-12 18:22:22 +0100 rene r265433 : typo; re-autoconf 2008-12-12 17:35:26 +0100 rene r265432 : actually implement SYSTEM_GRAPHIT checks (as already checked for in makefile.mks) but remove the checks in graphit itself and move to BUILD_TYPE 2008-12-12 08:08:33 +0100 kstribley r265387 : #i69129# 2 of the patched files need windows line endings so patch works on linux as well as windows 2008-12-12 08:04:41 +0100 kstribley r265386 : #i69129# rtl fallback fix which prevents caching of segments with fallback 2008-12-08 04:28:12 +0100 kstribley r264969 : results of running autoconf with graphite config changes #i69129# 2008-12-05 08:12:47 +0100 kstribley r264886 : backout unintential change at r264884 2008-12-05 06:26:33 +0100 kstribley r264884 : #i96925# fixes for uniscribe fallback 2008-12-05 06:11:37 +0100 kstribley r264883 : #i69129# improvements to windows graphite code, including caching of sila table lookup 2008-12-02 13:28:51 +0100 kstribley r264694 : #i93645# add graphite library and append to patch 2008-11-27 06:47:10 +0100 kstribley r264445 : #69129# fix rtl loop bug and rtl caching problem 2008-11-27 06:42:20 +0100 kstribley r264444 : add caching for GraphiteFontAdaptor 2008-11-14 15:57:03 +0100 kstribley r263681 : #69129# add graphite addtional files from cvs 2008-11-14 15:54:47 +0100 kstribley r263680 : #69129# fix for modified resolution api 2008-11-13 16:24:09 +0100 kstribley r263652 : #69129# add skeleton to build graphite module library 2008-11-13 16:22:19 +0100 kstribley r263651 : #69129# add skeleton to build graphite module library 2008-11-13 16:16:10 +0100 kstribley r263650 : #69129# migrate from cvs 2008-11-13 15:26:54 +0100 kstribley r263646 : #69129# add a module for the graphite library
2009-08-17 14:12:14 +00:00
aFont.SetLanguage(rFont.GetLanguage());
2000-09-18 23:08:29 +00:00
}
SwFntObj::~SwFntObj()
{
2001-02-13 07:56:40 +00:00
if ( pScrFont != pPrtFont )
2000-09-18 23:08:29 +00:00
delete pScrFont;
2001-02-13 07:56:40 +00:00
if ( pPrtFont != &aFont )
delete pPrtFont;
}
void SwFntObj::CreatePrtFont( const OutputDevice& rPrt )
2001-02-13 07:56:40 +00:00
{
if ( nPropWidth != 100 && pPrinter != &rPrt )
2001-02-13 07:56:40 +00:00
{
if( pScrFont != pPrtFont )
delete pScrFont;
if( pPrtFont != &aFont )
delete pPrtFont;
const Font aOldFnt( rPrt.GetFont() );
((OutputDevice&)rPrt).SetFont( aFont );
const FontMetric aWinMet( rPrt.GetFontMetric() );
((OutputDevice&)rPrt).SetFont( aOldFnt );
long nWidth = ( aWinMet.GetSize().Width() * nPropWidth ) / 100;
if( !nWidth )
++nWidth;
pPrtFont = new Font( aFont );
pPrtFont->SetSize( Size( nWidth, aFont.GetSize().Height() ) );
pScrFont = NULL;
}
2000-09-18 23:08:29 +00:00
}
/*************************************************************************
*
* bool lcl_IsFontAdjustNecessary( rOutDev, rRefDev )
*
* returns whether we have to adjust the output font to resemble
* the formatting font
*
* _Not_ necessary if
*
* 1. RefDef == OutDev (text formatting, online layout...)
* 2. PDF export from online layout
* 3. Prospect/PagePreview pringing
*
*************************************************************************/
bool lcl_IsFontAdjustNecessary( const OutputDevice& rOutDev,
const OutputDevice& rRefDev )
{
return &rRefDev != &rOutDev &&
OUTDEV_WINDOW != rRefDev.GetOutDevType() &&
( OUTDEV_PRINTER != rRefDev.GetOutDevType() ||
OUTDEV_PRINTER != rOutDev.GetOutDevType() );
}
struct CalcLinePosData
{
SwDrawTextInfo& rInf;
Font& rFont;
xub_StrLen nCnt;
const sal_Bool bSwitchH2V;
const sal_Bool bSwitchL2R;
long nHalfSpace;
sal_Int32* pKernArray;
const sal_Bool bBidiPor;
CalcLinePosData( SwDrawTextInfo& _rInf, Font& _rFont,
xub_StrLen _nCnt, const sal_Bool _bSwitchH2V, const sal_Bool _bSwitchL2R,
long _nHalfSpace, sal_Int32* _pKernArray, const sal_Bool _bBidiPor) :
rInf( _rInf ),
rFont( _rFont ),
nCnt( _nCnt ),
bSwitchH2V( _bSwitchH2V ),
bSwitchL2R( _bSwitchL2R ),
nHalfSpace( _nHalfSpace ),
pKernArray( _pKernArray ),
bBidiPor( _bBidiPor )
{
}
};
/** Function: lcl_calcLinePos
Computes the start and end position of an underline. This function is called
from the DrawText-method (for underlining misspelled words or smarttag terms).
*/
void lcl_calcLinePos( const CalcLinePosData &rData,
Point &rStart, Point &rEnd, xub_StrLen nStart, xub_StrLen nWrLen )
{
long nBlank = 0;
const xub_StrLen nEnd = nStart + nWrLen;
const long nTmpSpaceAdd = rData.rInf.GetSpace() / SPACING_PRECISION_FACTOR;
if ( nEnd < rData.nCnt
&& CH_BLANK == rData.rInf.GetText().GetChar( rData.rInf.GetIdx() + nEnd ) )
{
if( nEnd + 1 == rData.nCnt )
nBlank -= nTmpSpaceAdd;
else
nBlank -= rData.nHalfSpace;
}
// determine start, end and length of wave line
sal_Int32 nKernStart = nStart ? rData.pKernArray[ sal_uInt16( nStart - 1 ) ] : 0;
sal_Int32 nKernEnd = rData.pKernArray[ sal_uInt16( nEnd - 1 ) ];
sal_uInt16 nDir = rData.bBidiPor ? 1800 :
UnMapDirection( rData.rFont.GetOrientation(), rData.bSwitchH2V );
switch ( nDir )
{
case 0 :
rStart.X() += nKernStart;
rEnd.X() = nBlank + rData.rInf.GetPos().X() + nKernEnd;
rEnd.Y() = rData.rInf.GetPos().Y();
break;
case 900 :
rStart.Y() -= nKernStart;
rEnd.X() = rData.rInf.GetPos().X();
rEnd.Y() = nBlank + rData.rInf.GetPos().Y() - nKernEnd;
break;
case 1800 :
rStart.X() -= nKernStart;
rEnd.X() = rData.rInf.GetPos().X() - nKernEnd - nBlank;
rEnd.Y() = rData.rInf.GetPos().Y();
break;
case 2700 :
rStart.Y() += nKernStart;
rEnd.X() = rData.rInf.GetPos().X();
rEnd.Y() = nBlank + rData.rInf.GetPos().Y() + nKernEnd;
break;
}
if ( rData.bSwitchL2R )
{
rData.rInf.GetFrm()->SwitchLTRtoRTL( rStart );
rData.rInf.GetFrm()->SwitchLTRtoRTL( rEnd );
}
if ( rData.bSwitchH2V )
{
rData.rInf.GetFrm()->SwitchHorizontalToVertical( rStart );
rData.rInf.GetFrm()->SwitchHorizontalToVertical( rEnd );
}
}
/*************************************************************************
*
* sal_uInt16 SwFntObj::GetFontAscent( const OutputDevice& rOut )
2000-09-18 23:08:29 +00:00
*
* Beschreibung: liefern den Ascent des Fonts auf dem
* gewuenschten Outputdevice zurueck, ggf. muss der Bildschirmfont erst
* erzeugt werden.
2000-09-18 23:08:29 +00:00
*************************************************************************/
sal_uInt16 SwFntObj::GetFontAscent( const ViewShell *pSh, const OutputDevice& rOut )
2000-09-18 23:08:29 +00:00
{
sal_uInt16 nRet = 0;
const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
{
CreateScrFont( *pSh, rOut );
OSL_ENSURE( USHRT_MAX != nScrAscent, "nScrAscent is going berzerk" );
nRet = nScrAscent;
}
else
2000-09-18 23:08:29 +00:00
{
if ( nPrtAscent == USHRT_MAX ) // DruckerAscent noch nicht bekannt?
{
CreatePrtFont( rOut );
const Font aOldFnt( rRefDev.GetFont() );
((OutputDevice&)rRefDev).SetFont( *pPrtFont );
const FontMetric aOutMet( rRefDev.GetFontMetric() );
nPrtAscent = (sal_uInt16) aOutMet.GetAscent();
( (OutputDevice&)rRefDev).SetFont( aOldFnt );
2000-09-18 23:08:29 +00:00
}
nRet = nPrtAscent;
2000-09-18 23:08:29 +00:00
}
#if !defined(MACOSX) // #i89844# extleading is below the line for Mac
// TODO: move extleading below the line for all platforms too
nRet += GetFontLeading( pSh, rRefDev );
#endif
OSL_ENSURE( USHRT_MAX != nRet, "GetFontAscent returned USHRT_MAX" );
return nRet;
2000-09-18 23:08:29 +00:00
}
/*************************************************************************
*
* sal_uInt16 SwFntObj::GetFontHeight( const OutputDevice* pOut )
*
* Beschreibung: liefern die H?he des Fonts auf dem
* gewuenschten Outputdevice zurueck, ggf. muss der Bildschirmfont erst
* erzeugt werden.
*************************************************************************/
sal_uInt16 SwFntObj::GetFontHeight( const ViewShell* pSh, const OutputDevice& rOut )
2000-09-18 23:08:29 +00:00
{
sal_uInt16 nRet = 0;
const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
{
CreateScrFont( *pSh, rOut );
OSL_ENSURE( USHRT_MAX != nScrHeight, "nScrHeight is going berzerk" );
nRet = nScrHeight + GetFontLeading( pSh, rRefDev );
}
else
2000-09-18 23:08:29 +00:00
{
if ( nPrtHeight == USHRT_MAX ) // PrinterHeight noch nicht bekannt?
{
CreatePrtFont( rOut );
const Font aOldFnt( rRefDev.GetFont() );
((OutputDevice&)rRefDev).SetFont( *pPrtFont );
nPrtHeight = static_cast<sal_uInt16>(rRefDev.GetTextHeight());
#if OSL_DEBUG_LEVEL > 1
// Check if vcl did not change the meading of GetTextHeight
const FontMetric aOutMet( rRefDev.GetFontMetric() );
long nTmpPrtHeight = (sal_uInt16)aOutMet.GetAscent() + aOutMet.GetDescent();
(void) nTmpPrtHeight;
// #i106098#: do not compare with == here due to rounding error
OSL_ENSURE( abs(nTmpPrtHeight - nPrtHeight) < 3,
"GetTextHeight != Ascent + Descent" );
#endif
((OutputDevice&)rRefDev).SetFont( aOldFnt );
2000-09-18 23:08:29 +00:00
}
nRet = nPrtHeight + GetFontLeading( pSh, rRefDev );
2000-09-18 23:08:29 +00:00
}
OSL_ENSURE( USHRT_MAX != nRet, "GetFontHeight returned USHRT_MAX" );
return nRet;
}
sal_uInt16 SwFntObj::GetFontLeading( const ViewShell *pSh, const OutputDevice& rOut )
{
sal_uInt16 nRet = 0;
if ( pSh )
2000-09-18 23:08:29 +00:00
{
if ( USHRT_MAX == nGuessedLeading || USHRT_MAX == nExtLeading )
{
const Font aOldFnt( rOut.GetFont() );
((OutputDevice&)rOut).SetFont( *pPrtFont );
const FontMetric aMet( rOut.GetFontMetric() );
((OutputDevice&)rOut).SetFont( aOldFnt );
bSymbol = RTL_TEXTENCODING_SYMBOL == aMet.GetCharSet();
GuessLeading( *pSh, aMet );
nExtLeading = static_cast<sal_uInt16>(aMet.GetExtLeading());
}
const IDocumentSettingAccess& rIDSA = *pSh->getIDocumentSettingAccess();
const bool bBrowse = ( pSh->GetWin() &&
pSh->GetViewOptions()->getBrowseMode() &&
!pSh->GetViewOptions()->IsPrtFormat() );
if ( !bBrowse && rIDSA.get(IDocumentSettingAccess::ADD_EXT_LEADING) )
nRet = nExtLeading;
else
nRet = nGuessedLeading;
2000-09-18 23:08:29 +00:00
}
OSL_ENSURE( USHRT_MAX != nRet, "GetFontLeading returned USHRT_MAX" );
return nRet;
2000-09-18 23:08:29 +00:00
}
2000-09-18 23:08:29 +00:00
/*************************************************************************
*
* SwFntObj::CreateScrFont( const ViewShell& rSh, const OutputDevice& rOut )
2000-09-18 23:08:29 +00:00
*
* pOut is the output device, not the reference device
2000-09-18 23:08:29 +00:00
*
*************************************************************************/
void SwFntObj::CreateScrFont( const ViewShell& rSh, const OutputDevice& rOut )
2000-09-18 23:08:29 +00:00
{
if ( pScrFont )
return;
// any changes to the output device are reset at the end of the function
OutputDevice* pOut = (OutputDevice*)&rOut;
// Save old font
Font aOldOutFont( pOut->GetFont() );
2000-09-18 23:08:29 +00:00
nScrHeight = USHRT_MAX;
// Condition for output font / refdev font adjustment
OutputDevice* pPrt = &rSh.GetRefDev();
if( !rSh.GetWin() ||
!rSh.GetViewOptions()->getBrowseMode() ||
rSh.GetViewOptions()->IsPrtFormat() )
2000-09-18 23:08:29 +00:00
{
// After CreatePrtFont pPrtFont is the font which is actually used
// by the reference device
CreatePrtFont( *pPrt );
2000-09-18 23:08:29 +00:00
pPrinter = pPrt;
// save old reference device font
Font aOldPrtFnt( pPrt->GetFont() );
// set the font used at the reference device at the reference device
// and the output device
2001-02-13 07:56:40 +00:00
pPrt->SetFont( *pPrtFont );
pOut->SetFont( *pPrtFont );
// This should be the default for pScrFont.
pScrFont = pPrtFont;
FontMetric aMet = pPrt->GetFontMetric( );
//Don't loose "faked" properties of the logical font that don't truly
//exist in the physical font metrics which vcl which fake up for us
aMet.SetWeight(pScrFont->GetWeight());
aMet.SetItalic(pScrFont->GetItalic());
2000-09-18 23:08:29 +00:00
bSymbol = RTL_TEXTENCODING_SYMBOL == aMet.GetCharSet();
if ( USHRT_MAX == nGuessedLeading )
GuessLeading( rSh, aMet );
if ( USHRT_MAX == nExtLeading )
nExtLeading = static_cast<sal_uInt16>(aMet.GetExtLeading());
// reset the original reference device font
pPrt->SetFont( aOldPrtFnt );
2000-09-18 23:08:29 +00:00
}
else
{
bSymbol = RTL_TEXTENCODING_SYMBOL == aFont.GetCharSet();
if ( nGuessedLeading == USHRT_MAX )
nGuessedLeading = 0;
// no external leading in browse mode
if ( nExtLeading == USHRT_MAX )
nExtLeading = 0;
pScrFont = pPrtFont;
}
2000-09-18 23:08:29 +00:00
// Zoomfaktor ueberpruefen, z.B. wg. PrtOle2 beim Speichern
{
// Sollte der Zoomfaktor des OutputDevices nicht mit dem der View-
// Options uebereinstimmen, so darf dieser Font nicht gecacht
// werden, deshalb wird der Zoomfaktor auf einen "ungueltigen" Wert
// gesetzt.
long nTmp;
if( pOut->GetMapMode().GetScaleX().IsValid() &&
pOut->GetMapMode().GetScaleY().IsValid() &&
pOut->GetMapMode().GetScaleX() == pOut->GetMapMode().GetScaleY() )
{
nTmp = ( 100 * pOut->GetMapMode().GetScaleX().GetNumerator() ) /
pOut->GetMapMode().GetScaleX().GetDenominator();
}
else
nTmp = 0;
if( nTmp != nZoom )
nZoom = USHRT_MAX - 1;
}
nScrAscent = (sal_uInt16)pOut->GetFontMetric().GetAscent();
if ( USHRT_MAX == nScrHeight )
nScrHeight = (sal_uInt16)pOut->GetTextHeight();
2000-09-18 23:08:29 +00:00
// reset original output device font
pOut->SetFont( aOldOutFont );
2000-09-18 23:08:29 +00:00
}
void SwFntObj::GuessLeading( const ViewShell&
2011-04-22 23:41:42 +02:00
#if defined(WNT)
rSh
#endif
, const FontMetric& rMet )
2000-09-18 23:08:29 +00:00
{
// If leading >= 5, this seems to be enough leading.
// Nothing has to be done.
if ( rMet.GetIntLeading() >= 5 )
{
nGuessedLeading = 0;
return;
}
2000-09-18 23:08:29 +00:00
2011-04-22 23:41:42 +02:00
#if defined(WNT)
OutputDevice *pWin = rSh.GetWin() ?
rSh.GetWin() :
2000-09-18 23:08:29 +00:00
GetpApp()->GetDefaultDevice();
if ( pWin )
{
MapMode aTmpMap( MAP_TWIP );
MapMode aOldMap = pWin->GetMapMode( );
pWin->SetMapMode( aTmpMap );
const Font aOldFnt( pWin->GetFont() );
2001-02-13 07:56:40 +00:00
pWin->SetFont( *pPrtFont );
2000-09-18 23:08:29 +00:00
const FontMetric aWinMet( pWin->GetFontMetric() );
const sal_uInt16 nWinHeight = sal_uInt16( aWinMet.GetSize().Height() );
2001-02-13 07:56:40 +00:00
if( pPrtFont->GetName().Search( aWinMet.GetName() ) < USHRT_MAX )
2000-09-18 23:08:29 +00:00
{
// Wenn das Leading auf dem Window auch 0 ist, dann
// muss es auch so bleiben (vgl. StarMath!).
long nTmpLeading = (long)aWinMet.GetIntLeading();
2000-09-18 23:08:29 +00:00
// einen Versuch haben wir noch wg. 31003:
if( nTmpLeading <= 0 )
{
pWin->SetFont( rMet );
nTmpLeading = (long)pWin->GetFontMetric().GetIntLeading();
2000-09-18 23:08:29 +00:00
if( nTmpLeading < 0 )
nGuessedLeading = 0;
2000-09-18 23:08:29 +00:00
else
nGuessedLeading = sal_uInt16(nTmpLeading);
2000-09-18 23:08:29 +00:00
}
else
{
nGuessedLeading = sal_uInt16(nTmpLeading);
2000-09-18 23:08:29 +00:00
// Manta-Hack #50153#:
// Wer beim Leading luegt, luegt moeglicherweise auch beim
// Ascent/Descent, deshalb wird hier ggf. der Font ein wenig
// tiefergelegt, ohne dabei seine Hoehe zu aendern.
long nDiff = Min( rMet.GetDescent() - aWinMet.GetDescent(),
aWinMet.GetAscent() - rMet.GetAscent() - nTmpLeading );
if( nDiff > 0 )
{
OSL_ENSURE( nPrtAscent < USHRT_MAX, "GuessLeading: PrtAscent-Fault" );
if ( nPrtAscent < USHRT_MAX )
nPrtAscent = nPrtAscent + (sal_uInt16)(( 2 * nDiff ) / 5);
2000-09-18 23:08:29 +00:00
}
}
}
else
{
// Wenn alle Stricke reissen, nehmen wir 15% der
// Hoehe, ein von CL empirisch ermittelter Wert.
nGuessedLeading = (nWinHeight * 15) / 100;
2000-09-18 23:08:29 +00:00
}
pWin->SetFont( aOldFnt );
pWin->SetMapMode( aOldMap );
}
else
#endif
nGuessedLeading = 0;
2000-09-18 23:08:29 +00:00
}
/*************************************************************************
*
* void SwFntObj::SetDeviceFont( const OutputDevice *pOut ),
*
* Beschreibung: stellt den Font am gewuenschten OutputDevice ein,
* am Bildschirm muss eventuell erst den Abgleich durchgefuehrt werden.
*
*************************************************************************/
void SwFntObj::SetDevFont( const ViewShell *pSh, OutputDevice& rOut )
2000-09-18 23:08:29 +00:00
{
const OutputDevice& rRefDev = pSh ? pSh->GetRefDev() : rOut;
if ( pSh && lcl_IsFontAdjustNecessary( rOut, rRefDev ) )
2000-09-18 23:08:29 +00:00
{
CreateScrFont( *pSh, rOut );
if( !GetScrFont()->IsSameInstance( rOut.GetFont() ) )
rOut.SetFont( *pScrFont );
2001-02-13 07:56:40 +00:00
if( pPrinter && ( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) ) )
pPrinter->SetFont( *pPrtFont );
2000-09-18 23:08:29 +00:00
}
else
{
CreatePrtFont( rOut );
if( !pPrtFont->IsSameInstance( rOut.GetFont() ) )
rOut.SetFont( *pPrtFont );
2000-09-18 23:08:29 +00:00
}
// Here, we actually do not need the leading values, but by calling
// GetFontLeading() we assure that the values are calculated for later use.
GetFontLeading( pSh, rRefDev );
2000-09-18 23:08:29 +00:00
}
#define WRONG_SHOW_MIN 5
#define WRONG_SHOW_SMALL 11
#define WRONG_SHOW_MEDIUM 15
/*************************************************************************
*
* void SwFntObj::DrawText( ... )
*
* Beschreibung: Textausgabe
* auf dem Bildschirm => DrawTextArray
* auf dem Drucker, !Kerning => DrawText
* auf dem Drucker + Kerning => DrawStretchText
*
*************************************************************************/
sal_uInt8 lcl_WhichPunctuation( xub_Unicode cChar )
{
if ( ( cChar < 0x3001 || cChar > 0x3002 ) &&
( cChar < 0x3008 || cChar > 0x3011 ) &&
( cChar < 0x3014 || cChar > 0x301F ) &&
0xFF62 != cChar && 0xFF63 != cChar )
// no punctuation
return SwScriptInfo::NONE;
else if ( 0x3001 == cChar || 0x3002 == cChar ||
0x3009 == cChar || 0x300B == cChar ||
0x300D == cChar || 0x300F == cChar ||
0x3011 == cChar || 0x3015 == cChar ||
0x3017 == cChar || 0x3019 == cChar ||
0x301B == cChar || 0x301E == cChar ||
0x301F == cChar || 0xFF63 == cChar )
// right punctuation
return SwScriptInfo::SPECIAL_RIGHT;
return SwScriptInfo::SPECIAL_LEFT;
}
static sal_Bool lcl_IsMonoSpaceFont( const OutputDevice& rOut )
{
const String aStr1( xub_Unicode( 0x3008 ) );
const String aStr2( xub_Unicode( 0x307C ) );
const long nWidth1 = rOut.GetTextWidth( aStr1 );
const long nWidth2 = rOut.GetTextWidth( aStr2 );
return nWidth1 == nWidth2;
}
2000-09-18 23:08:29 +00:00
// ER 09.07.95 20:34
// mit -Ox Optimierung stuerzt's unter win95 ab
// JP 12.07.95: unter WNT auch (i386); Alpha ??
// global optimization off
#ifdef _MSC_VER
2000-09-18 23:08:29 +00:00
#pragma optimize("g",off)
#endif
/* This helper structure (SwForbidden) contains the already marked parts of the string
to avoid double lines (e.g grammar + spell check error) */
typedef std::vector< std::pair< xub_StrLen, xub_StrLen > > SwForbidden;
static void lcl_DrawLineForWrongListData(
SwForbidden &rForbidden,
const SwDrawTextInfo &rInf,
const SwWrongList *pWList,
const CalcLinePosData &rCalcLinePosData,
const Size &rPrtFontSize )
{
if (!pWList)
return;
xub_StrLen nStart = rInf.GetIdx();
xub_StrLen nWrLen = rInf.GetLen();
// check if respective data is available in the current text range
if (pWList->Check( nStart, nWrLen ))
{
// get line color to use...
Color aLineColor;
if (pWList == rInf.GetWrong()) // ... for spell checking
aLineColor = SwViewOption::GetSpellColor();
else if (pWList == rInf.GetGrammarCheck()) // ... for grammar checking
// currently there is no specific color for grammar check errors available in the configuration
aLineColor = Color( COL_LIGHTBLUE );
else if (pWList == rInf.GetSmartTags()) // ... for smart tags
aLineColor = SwViewOption::GetSmarttagColor();
long nHght = rInf.GetOut().LogicToPixel( rPrtFontSize ).Height();
// Draw wavy lines for spell and grammar errors only if font is large enough.
// Lines for smart tags will always be drawn.
if (pWList == rInf.GetSmartTags() || WRONG_SHOW_MIN < nHght)
{
SwForbidden::iterator pIter = rForbidden.begin();
if (rInf.GetOut().GetConnectMetaFile())
rInf.GetOut().Push();
const Color aCol( rInf.GetOut().GetLineColor() );
const sal_Bool bColSave = aCol != aLineColor;
if (bColSave)
rInf.GetOut().SetLineColor( aLineColor );
// iterate over all ranges stored in the respective SwWrongList
do
{
nStart = nStart - rInf.GetIdx();
const xub_StrLen nEnd = nStart + nWrLen;
xub_StrLen nNext = nStart;
while( nNext < nEnd )
{
while( pIter != rForbidden.end() && pIter->second <= nNext )
++pIter;
xub_StrLen nNextStart = nNext;
xub_StrLen nNextEnd = nEnd;
if( pIter == rForbidden.end() || nNextEnd <= pIter->first )
{
// No overlapping mark up found
std::pair< xub_StrLen, xub_StrLen > aNew;
aNew.first = nNextStart;
aNew.second = nNextEnd;
rForbidden.insert( pIter, aNew );
pIter = rForbidden.begin();
nNext = nEnd;
}
else
{
nNext = pIter->second;
if( nNextStart < pIter->first )
{
nNextEnd = pIter->first;
pIter->first = nNextStart;
}
else
continue;
}
// determine line pos
Point aStart( rInf.GetPos() );
Point aEnd;
lcl_calcLinePos( rCalcLinePosData, aStart, aEnd, nNextStart, nNextEnd - nNextStart );
// draw line for smart tags?
if (pWList == rInf.GetSmartTags())
{
aStart.Y() +=30;
aEnd.Y() +=30;
LineInfo aLineInfo( LINE_DASH );
aLineInfo.SetDistance( 40 );
aLineInfo.SetDashLen( 1 );
aLineInfo.SetDashCount(1);
rInf.GetOut().DrawLine( aStart, aEnd, aLineInfo );
}
else // draw wavy lines for spell or grammar errors
{
// get wavy line type to use
sal_uInt16 nWave =
WRONG_SHOW_MEDIUM < nHght ? WAVE_NORMAL :
( WRONG_SHOW_SMALL < nHght ? WAVE_SMALL : WAVE_FLAT );
rInf.GetOut().DrawWaveLine( aStart, aEnd, nWave );
}
}
nStart = nEnd + rInf.GetIdx();
nWrLen = rInf.GetIdx() + rInf.GetLen() - nStart;
}
while (nWrLen && pWList->Check( nStart, nWrLen ));
if (bColSave)
rInf.GetOut().SetLineColor( aCol );
if (rInf.GetOut().GetConnectMetaFile())
rInf.GetOut().Pop();
}
}
}
2002-04-10 06:02:27 +00:00
void SwFntObj::DrawText( SwDrawTextInfo &rInf )
{
OSL_ENSURE( rInf.GetShell(), "SwFntObj::DrawText without shell" );
OutputDevice& rRefDev = rInf.GetShell()->GetRefDev();
OutputDevice* pWin = rInf.GetShell()->GetWin();
// true if pOut is the printer and the printer has been used for formatting
const sal_Bool bPrt = OUTDEV_PRINTER == rInf.GetOut().GetOutDevType() &&
OUTDEV_PRINTER == rRefDev.GetOutDevType();
const sal_Bool bBrowse = ( pWin &&
rInf.GetShell()->GetViewOptions()->getBrowseMode() &&
!rInf.GetShell()->GetViewOptions()->IsPrtFormat() &&
!rInf.GetBullet() &&
( rInf.GetSpace() || !rInf.GetKern() ) &&
!rInf.GetWrong() &&
!rInf.GetGrammarCheck() &&
!rInf.GetSmartTags() &&
!rInf.GetGreyWave() );
// bDirectPrint indicates that we can enter the branch which calls
// the DrawText functions instead of calling the DrawTextArray functions
const sal_Bool bDirectPrint = bPrt || bBrowse;
// Condition for output font / refdev font adjustment
const sal_Bool bUseScrFont =
lcl_IsFontAdjustNecessary( rInf.GetOut(), rRefDev );
Font* pTmpFont = bUseScrFont ? pScrFont : pPrtFont;
//
// bDirectPrint and bUseScrFont should have these values:
//
// Outdev / RefDef | Printer | VirtPrinter | Window
// ----------------------------------------------------
// Printer | 1 - 0 | 0 - 1 | -
// ----------------------------------------------------
// VirtPrinter/PDF | 0 - 1 | 0 - 1 | -
// ----------------------------------------------------
// Window/VirtWindow| 0 - 1 | 0 - 1 | 1 - 0
//
// Exception: During painting of a Writer OLE object, we do not have
// a window. Therefore bUseSrcFont is always 0 in this case.
//
#if OSL_DEBUG_LEVEL > 1
const sal_Bool bNoAdjust = bPrt ||
( pWin &&
rInf.GetShell()->GetViewOptions()->getBrowseMode() &&
!rInf.GetShell()->GetViewOptions()->IsPrtFormat() );
if ( OUTDEV_PRINTER == rInf.GetOut().GetOutDevType() )
{
// Printer output
if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
{
OSL_ENSURE( bNoAdjust == 1 && bUseScrFont == 0, "Outdev Check failed" );
}
else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
{
OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
}
else
{
OSL_FAIL( "Outdev Check failed" );
}
}
else if ( OUTDEV_VIRDEV == rInf.GetOut().GetOutDevType() && ! pWin )
{
// PDF export
if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
{
OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
}
else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
{
OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
}
else
{
OSL_FAIL( "Outdev Check failed" );
}
}
else if ( OUTDEV_WINDOW == rInf.GetOut().GetOutDevType() ||
( OUTDEV_VIRDEV == rInf.GetOut().GetOutDevType() && pWin ) )
{
// Window or virtual window
if ( OUTDEV_PRINTER == rRefDev.GetOutDevType() )
{
OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
}
else if ( OUTDEV_VIRDEV == rRefDev.GetOutDevType() )
{
OSL_ENSURE( bNoAdjust == 0 && bUseScrFont == 1, "Outdev Check failed" );
}
else if ( OUTDEV_WINDOW == rRefDev.GetOutDevType() )
{
OSL_ENSURE( bNoAdjust == 1 && bUseScrFont == 0, "Outdev Check failed" );
}
else
{
OSL_FAIL( "Outdev Check failed" );
}
}
else
{
OSL_FAIL( "Outdev Check failed" );
}
#endif
2002-04-10 06:02:27 +00:00
// robust: better use the printer font instead of using no font at all
OSL_ENSURE( pTmpFont, "No screen or printer font?" );
2002-04-10 06:02:27 +00:00
if ( ! pTmpFont )
pTmpFont = pPrtFont;
// HACK: UNDERLINE_WAVE darf nicht mehr missbraucht werden, daher
// wird die graue Wellenlinie des ExtendedAttributSets zunaechst
// in der Fontfarbe erscheinen.
const sal_Bool bSwitchH2V = rInf.GetFrm() && rInf.GetFrm()->IsVertical();
const sal_Bool bSwitchL2R = rInf.GetFrm() && rInf.GetFrm()->IsRightToLeft() &&
2002-06-20 11:44:41 +00:00
! rInf.IsIgnoreFrmRTL();
const sal_uLong nMode = rInf.GetOut().GetLayoutMode();
const sal_Bool bBidiPor = ( bSwitchL2R !=
( 0 != ( TEXT_LAYOUT_BIDI_RTL & nMode ) ) );
2002-04-10 06:02:27 +00:00
// be sure to have the correct layout mode at the printer
2002-04-10 06:02:27 +00:00
if ( pPrinter )
{
pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
}
2002-04-10 06:02:27 +00:00
Point aPos( rInf.GetPos() );
if( !bPrt )
{
if( rInf.GetpOut() != pPixOut || rInf.GetOut().GetMapMode() != *pPixMap )
{
*pPixMap = rInf.GetOut().GetMapMode();
pPixOut = rInf.GetpOut();
Size aTmp( 1, 1 );
nPixWidth = rInf.GetOut().PixelToLogic( aTmp ).Width();
}
aPos.X() += rInf.GetFrm()->IsRightToLeft() ? 0 : nPixWidth;
2002-04-10 06:02:27 +00:00
}
Color aOldColor( pTmpFont->GetColor() );
sal_Bool bChgColor = rInf.ApplyAutoColor( pTmpFont );
if( !pTmpFont->IsSameInstance( rInf.GetOut().GetFont() ) )
2002-04-10 06:02:27 +00:00
rInf.GetOut().SetFont( *pTmpFont );
if ( bChgColor )
pTmpFont->SetColor( aOldColor );
2002-04-10 06:02:27 +00:00
if ( STRING_LEN == rInf.GetLen() )
rInf.SetLen( rInf.GetText().Len() );
//
// ASIAN LINE AND CHARACTER GRID MODE START: snap to characters
//
2002-04-10 06:02:27 +00:00
if ( rInf.GetFrm() && rInf.SnapToGrid() && rInf.GetFont() &&
SW_CJK == rInf.GetFont()->GetActual() )
{
GETGRID( rInf.GetFrm()->FindPageFrm() )
if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars())
2002-04-10 06:02:27 +00:00
{
//for textgrid refactor
//const sal_uInt16 nGridWidth = pGrid->GetBaseHeight();
const SwDoc* pDoc = rInf.GetShell()->GetDoc();
const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
2002-04-10 06:02:27 +00:00
if ( pPrinter )
pPrinter->GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), rInf.GetLen() );
else
rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), rInf.GetLen() );
long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
const sal_uLong i = nWidthPerChar ?
2002-04-10 06:02:27 +00:00
( nWidthPerChar - 1 ) / nGridWidth + 1:
1;
nWidthPerChar = i * nGridWidth;
// position of first character, we take the printer position
long nCharWidth = pKernArray[ 0 ];
sal_uLong nHalfWidth = nWidthPerChar / 2;
2002-04-10 06:02:27 +00:00
long nNextFix;
// punctuation characters are not centered
xub_Unicode cChar = rInf.GetText().GetChar( rInf.GetIdx() );
sal_uInt8 nType = lcl_WhichPunctuation( cChar );
2002-04-10 06:02:27 +00:00
switch ( nType )
{
case SwScriptInfo::NONE :
aPos.X() += ( nWidthPerChar - nCharWidth ) / 2;
nNextFix = nCharWidth / 2;
break;
case SwScriptInfo::SPECIAL_RIGHT :
nNextFix = nHalfWidth;
break;
default:
aPos.X() += nWidthPerChar - nCharWidth;
nNextFix = nCharWidth - nHalfWidth;
}
// calculate offsets
for ( xub_StrLen j = 1; j < rInf.GetLen(); ++j )
{
long nScr = pKernArray[ j ] - pKernArray[ j - 1 ];
nNextFix += nWidthPerChar;
// punctuation characters are not centered
cChar = rInf.GetText().GetChar( rInf.GetIdx() + j );
nType = lcl_WhichPunctuation( cChar );
switch ( nType )
{
case SwScriptInfo::NONE :
pKernArray[ j - 1 ] = nNextFix - ( nScr / 2 );
break;
case SwScriptInfo::SPECIAL_RIGHT :
pKernArray[ j - 1 ] = nNextFix - nHalfWidth;
break;
default:
pKernArray[ j - 1 ] = nNextFix + nHalfWidth - nScr;
}
}
// the layout engine requires the total width of the output
pKernArray[ rInf.GetLen() - 1 ] = rInf.GetWidth() -
aPos.X() + rInf.GetPos().X() ;
2002-04-10 06:02:27 +00:00
if ( bSwitchH2V )
rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), rInf.GetLen() );
delete[] pKernArray;
return;
}
}
// For text grid refactor
// ASIAN LINE AND CHARACTER GRID MODE START: not snap to characters
//
if ( rInf.GetFrm() && rInf.SnapToGrid() && rInf.GetFont() &&
SW_CJK == rInf.GetFont()->GetActual() )
{
GETGRID( rInf.GetFrm()->FindPageFrm() )
if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
{
const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
const SwDoc* pDoc = rInf.GetShell()->GetDoc();
long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
if( SW_LATIN == rInf.GetFont()->GetActual() )
nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
else
nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
if ( pPrinter )
pPrinter->GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), rInf.GetLen() );
else
rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), rInf.GetLen() );
if ( bSwitchH2V )
rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
if ( rInf.GetSpace() || rInf.GetKanaComp())
{
long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
sal_Bool bSpecialJust = sal_False;
if ( rInf.GetFont() && rInf.GetLen() )
{
const SwScriptInfo* pSI = rInf.GetScriptInfo();
const sal_uInt8 nActual = rInf.GetFont()->GetActual();
///Kana Compression
if( SW_CJK == nActual && rInf.GetKanaComp() &&
pSI && pSI->CountCompChg() &&
lcl_IsMonoSpaceFont( *(rInf.GetpOut()) ) )
{
pSI->Compress( pKernArray,rInf.GetIdx(), rInf.GetLen(),
rInf.GetKanaComp(), (sal_uInt16)aFont.GetSize().Height(),&aPos );
bSpecialJust = sal_True;
}
///Asian Justification
if ( ( SW_CJK == nActual || SW_LATIN == nActual ) && nSpaceAdd )
{
LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang)
{
long nSpaceSum = nSpaceAdd;
for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
{
pKernArray[ nI ] += nSpaceSum;
nSpaceSum += nSpaceAdd;
}
bSpecialJust = sal_True;
nSpaceAdd = 0;
}
}
long nGridAddSum = nGridWidthAdd;
for(xub_StrLen i = 0; i < rInf.GetLen(); i++,nGridAddSum += nGridWidthAdd )
{
pKernArray[i] += nGridAddSum;
}
long nKernSum = rInf.GetKern();
if ( bSpecialJust || rInf.GetKern() )
{
for( xub_StrLen i = 0; i < rInf.GetLen(); i++, nKernSum += rInf.GetKern() )
{
if ( CH_BLANK == rInf.GetText().GetChar(rInf.GetIdx()+i) )
nKernSum += nSpaceAdd;
pKernArray[i] += nKernSum;
}
///With through/uderstr. Grouped style requires a blank at the end
///of a text edition special measures:
if( bPaintBlank && rInf.GetLen() && (CH_BLANK ==
rInf.GetText().GetChar( rInf.GetIdx() + rInf.GetLen() - 1) ) )
{
///If it concerns a singular, underlined space acts,
///we must spend two:
if( 1 == rInf.GetLen() )
{
pKernArray[0] = rInf.GetWidth() + nSpaceAdd;
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), 1 );
}
else
{
pKernArray[ rInf.GetLen() - 2] += nSpaceAdd;
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), rInf.GetLen() );
}
}
else
{
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), rInf.GetLen() );
}
}
else
{
Point aTmpPos( aPos );
xub_StrLen i;
xub_StrLen j = 0;
long nSpaceSum = 0;
for( i = 0; i < rInf.GetLen(); i++ )
{
if( CH_BLANK == rInf.GetText().GetChar( rInf.GetIdx() + i) )
{
nSpaceSum += nSpaceAdd;
if( j < i)
rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
rInf.GetIdx() + j, i - j );
j = i + 1;
pKernArray[i] = pKernArray[i] + nSpaceSum;
aTmpPos.X() = aPos.X() + pKernArray[ i ] + nKernSum;
}
}
if( j < i )
rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
rInf.GetIdx() +j , i - j );
}
}
}
else
{
//long nKernAdd = rInf.GetKern();
long nKernAdd = 0;
long nGridAddSum = nGridWidthAdd + nKernAdd;
for(xub_StrLen i = 0; i < rInf.GetLen(); i++,nGridAddSum += nGridWidthAdd + nKernAdd )
{
pKernArray[i] += nGridAddSum;
}
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), rInf.GetLen() );
}
delete[] pKernArray;
return;
}
}
//
// DIRECT PAINTING WITHOUT SCREEN ADJUSTMENT
//
if ( bDirectPrint )
2002-04-10 06:02:27 +00:00
{
const Fraction aTmp( 1, 1 );
sal_Bool bStretch = rInf.GetWidth() && ( rInf.GetLen() > 1 ) && bPrt
2002-04-10 06:02:27 +00:00
&& ( aTmp != rInf.GetOut().GetMapMode().GetScaleX() );
if ( bSwitchL2R )
rInf.GetFrm()->SwitchLTRtoRTL( aPos );
2002-04-10 06:02:27 +00:00
if ( bSwitchH2V )
rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
// In the good old days we used to have a simple DrawText if the
// output device is the printer. Now we need a DrawTextArray if
// 1. KanaCompression is enabled
// 2. Justified alignment
// Simple kerning is handled by DrawStretchText
if( rInf.GetSpace() || rInf.GetKanaComp() )
2002-04-10 06:02:27 +00:00
{
sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
2002-04-10 06:02:27 +00:00
rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), rInf.GetLen() );
2002-04-10 06:02:27 +00:00
if( bStretch )
{
xub_StrLen nZwi = rInf.GetLen() - 1;
long nDiff = rInf.GetWidth() - pKernArray[ nZwi ]
- rInf.GetLen() * rInf.GetKern();
long nRest = nDiff % nZwi;
long nAdd;
if( nRest < 0 )
{
nAdd = -1;
nRest += nZwi;
}
else
{
nAdd = +1;
nRest = nZwi - nRest;
}
nDiff /= nZwi;
long nSum = nDiff;
for( xub_StrLen i = 0; i < nZwi; )
{
pKernArray[ i ] += nSum;
if( ++i == nRest )
nDiff += nAdd;
nSum += nDiff;
}
}
//
// Modify Array for special justifications
//
long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
sal_Bool bSpecialJust = sal_False;
if ( rInf.GetFont() && rInf.GetLen() )
{
const SwScriptInfo* pSI = rInf.GetScriptInfo();
const sal_uInt8 nActual = rInf.GetFont()->GetActual();
// Kana Compression
if ( SW_CJK == nActual && rInf.GetKanaComp() &&
pSI && pSI->CountCompChg() &&
lcl_IsMonoSpaceFont( rInf.GetOut() ) )
{
pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
rInf.GetKanaComp(),
(sal_uInt16)aFont.GetSize().Height(), &aPos );
bSpecialJust = sal_True;
}
// Asian Justification
if ( SW_CJK == nActual && nSpaceAdd )
{
LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
{
long nSpaceSum = nSpaceAdd;
for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
{
pKernArray[ nI ] += nSpaceSum;
nSpaceSum += nSpaceAdd;
}
bSpecialJust = sal_True;
nSpaceAdd = 0;
}
}
// Kashida Justification
if ( SW_CTL == nActual && nSpaceAdd )
{
if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
{
if ( pSI && pSI->CountKashida() &&
pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(),
rInf.GetLen(), nSpaceAdd ) != STRING_LEN )
{
bSpecialJust = sal_True;
nSpaceAdd = 0;
}
}
}
// Thai Justification
if ( SW_CTL == nActual && nSpaceAdd )
{
LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
if ( LANGUAGE_THAI == aLang )
{
// Use rInf.GetSpace() because it has more precision than
// nSpaceAdd:
SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray, 0,
rInf.GetIdx(), rInf.GetLen(),
rInf.GetNumberOfBlanks(),
rInf.GetSpace() );
// adding space to blanks is already done
bSpecialJust = sal_True;
nSpaceAdd = 0;
}
}
}
2002-04-10 06:02:27 +00:00
long nKernSum = rInf.GetKern();
if ( bStretch || bPaintBlank || rInf.GetKern() || bSpecialJust )
2002-04-10 06:02:27 +00:00
{
for( xub_StrLen i = 0; i < rInf.GetLen(); i++,
nKernSum += rInf.GetKern() )
{
if ( CH_BLANK == rInf.GetText().GetChar(rInf.GetIdx()+i) )
nKernSum += nSpaceAdd;
2002-04-10 06:02:27 +00:00
pKernArray[i] += nKernSum;
}
// Bei durch/unterstr. Blocksatz erfordert ein Blank am Ende
// einer Textausgabe besondere Massnahmen:
if( bPaintBlank && rInf.GetLen() && ( CH_BLANK ==
rInf.GetText().GetChar( rInf.GetIdx()+rInf.GetLen()-1 ) ) )
{
// Wenn es sich um ein singulaeres, unterstrichenes Space
// handelt, muessen wir zwei ausgeben:
if( 1 == rInf.GetLen() )
{
pKernArray[0] = rInf.GetWidth() + nSpaceAdd;
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), 1 );
2002-04-10 06:02:27 +00:00
}
else
{
pKernArray[ rInf.GetLen() - 2 ] += nSpaceAdd;
2002-04-10 06:02:27 +00:00
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), rInf.GetLen() );
}
}
else
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), rInf.GetLen() );
2002-04-10 06:02:27 +00:00
}
else
{
Point aTmpPos( aPos );
xub_StrLen j = 0;
xub_StrLen i;
for( i = 0; i < rInf.GetLen(); i++ )
{
if( CH_BLANK == rInf.GetText().GetChar( rInf.GetIdx()+i ) )
{
nKernSum += nSpaceAdd;
2002-04-10 06:02:27 +00:00
if( j < i )
rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
rInf.GetIdx() + j, i - j );
2002-04-10 06:02:27 +00:00
j = i + 1;
SwTwips nAdd = pKernArray[ i ] + nKernSum;
if ( ( TEXT_LAYOUT_BIDI_STRONG | TEXT_LAYOUT_BIDI_RTL ) == nMode )
nAdd *= -1;
aTmpPos.X() = aPos.X() + nAdd;
2002-04-10 06:02:27 +00:00
}
}
if( j < i )
rInf.GetOut().DrawText( aTmpPos, rInf.GetText(),
rInf.GetIdx() + j, i - j );
}
delete[] pKernArray;
}
else if( bStretch )
{
long nTmpWidth = rInf.GetWidth();
2002-04-10 06:02:27 +00:00
if( rInf.GetKern() && rInf.GetLen() && nTmpWidth > rInf.GetKern() )
nTmpWidth -= rInf.GetKern();
rInf.GetOut().DrawStretchText( aPos, nTmpWidth,
rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
2002-04-10 06:02:27 +00:00
}
else if( rInf.GetKern() )
{
const long nTmpWidth = GetTextSize( rInf ).Width();
const Color aSaveColor( pTmpFont->GetColor() );
const sal_Bool bColorChanged = rInf.ApplyAutoColor( pTmpFont );
if( bColorChanged )
2002-04-10 06:02:27 +00:00
{
if( !pTmpFont->IsSameInstance( rInf.GetOut().GetFont() ) )
rInf.GetOut().SetFont( *pTmpFont );
pTmpFont->SetColor( aSaveColor );
2002-04-10 06:02:27 +00:00
}
rInf.GetOut().DrawStretchText( aPos, (sal_uInt16)nTmpWidth,
rInf.GetText(), rInf.GetIdx(), rInf.GetLen() );
2002-04-10 06:02:27 +00:00
}
else
rInf.GetOut().DrawText( aPos, rInf.GetText(),
rInf.GetIdx(), rInf.GetLen() );
}
//
// PAINTING WITH FORMATTING DEVICE/SCREEN ADJUSTMENT
//
2002-04-10 06:02:27 +00:00
else
{
const String* pStr = &rInf.GetText();
String aStr( aEmptyStr );
sal_Bool bBullet = rInf.GetBullet();
2002-04-10 06:02:27 +00:00
if( bSymbol )
bBullet = sal_False;
sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
CreateScrFont( *rInf.GetShell(), rInf.GetOut() );
2002-04-10 06:02:27 +00:00
long nScrPos;
// get screen array
sal_Int32* pScrArray = new sal_Int32[ rInf.GetLen() ];
2002-04-10 06:02:27 +00:00
rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray,
rInf.GetIdx(), rInf.GetLen() );
// OLE: no printer available
// OSL_ENSURE( pPrinter, "DrawText needs pPrinter" )
2002-04-10 06:02:27 +00:00
if ( pPrinter )
{
// pTmpFont has already been set as current font for rInf.GetOut()
if ( pPrinter != rInf.GetpOut() || pTmpFont != pPrtFont )
{
if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
pPrinter->SetFont( *pPrtFont );
}
2002-04-10 06:02:27 +00:00
pPrinter->GetTextArray( rInf.GetText(), pKernArray, rInf.GetIdx(),
rInf.GetLen() );
}
else
{
rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), rInf.GetLen() );
}
//
// Modify Printer and ScreenArrays for special justifications
//
long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
bool bNoHalfSpace = false;
2002-04-10 06:02:27 +00:00
if ( rInf.GetFont() && rInf.GetLen() )
{
const sal_uInt8 nActual = rInf.GetFont()->GetActual();
2002-04-10 06:02:27 +00:00
const SwScriptInfo* pSI = rInf.GetScriptInfo();
// Kana Compression
if ( SW_CJK == nActual && rInf.GetKanaComp() &&
pSI && pSI->CountCompChg() &&
lcl_IsMonoSpaceFont( rInf.GetOut() ) )
2002-04-10 06:02:27 +00:00
{
Point aTmpPos( aPos );
2002-04-10 06:02:27 +00:00
pSI->Compress( pScrArray, rInf.GetIdx(), rInf.GetLen(),
rInf.GetKanaComp(),
(sal_uInt16)aFont.GetSize().Height(), &aTmpPos );
2002-04-10 06:02:27 +00:00
pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
rInf.GetKanaComp(),
(sal_uInt16)aFont.GetSize().Height(), &aPos );
2002-04-10 06:02:27 +00:00
}
// Asian Justification
if ( SW_CJK == nActual && nSpaceAdd )
{
LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
{
long nSpaceSum = nSpaceAdd;
for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
{
pKernArray[ nI ] += nSpaceSum;
pScrArray[ nI ] += nSpaceSum;
nSpaceSum += nSpaceAdd;
}
nSpaceAdd = 0;
}
}
// Kashida Justification
if ( SW_CTL == nActual && nSpaceAdd )
{
if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
{
if ( pSI && pSI->CountKashida() &&
pSI->KashidaJustify( pKernArray, pScrArray, rInf.GetIdx(),
rInf.GetLen(), nSpaceAdd ) != STRING_LEN )
nSpaceAdd = 0;
else
bNoHalfSpace = true;
}
}
// Thai Justification
if ( SW_CTL == nActual && nSpaceAdd )
2002-04-10 06:02:27 +00:00
{
LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
if ( LANGUAGE_THAI == aLang )
{
SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray,
pScrArray, rInf.GetIdx(),
rInf.GetLen(),
rInf.GetNumberOfBlanks(),
rInf.GetSpace() );
// adding space to blanks is already done
nSpaceAdd = 0;
}
2002-04-10 06:02:27 +00:00
}
}
nScrPos = pScrArray[ 0 ];
if( bBullet )
{
// !!! HACK !!!
// The Arabic layout engine requires some context of the string
// which should be painted.
xub_StrLen nCopyStart = rInf.GetIdx();
if ( nCopyStart )
--nCopyStart;
xub_StrLen nCopyLen = rInf.GetLen();
if ( nCopyStart + nCopyLen < rInf.GetText().Len() )
++nCopyLen;
aStr = rInf.GetText().Copy( nCopyStart, nCopyLen );
pStr = &aStr;
2002-09-09 08:26:48 +00:00
2002-04-10 06:02:27 +00:00
for( xub_StrLen i = 0; i < aStr.Len(); ++i )
if( CH_BLANK == aStr.GetChar( i ) )
aStr.SetChar( i, CH_BULLET );
2002-04-10 06:02:27 +00:00
}
xub_StrLen nCnt = rInf.GetText().Len();
if ( nCnt < rInf.GetIdx() )
nCnt = 0;
else
nCnt = nCnt - rInf.GetIdx();
2002-04-10 06:02:27 +00:00
nCnt = Min( nCnt, rInf.GetLen() );
long nKernSum = rInf.GetKern();
xub_Unicode cChPrev = rInf.GetText().GetChar( rInf.GetIdx() );
// Wenn es sich um ein singulaeres, unterstrichenes Space
// im Blocksatz handelt, muessen wir zwei ausgeben:
if ( ( nCnt == 1 ) && rInf.GetSpace() && ( cChPrev == CH_BLANK ) )
{
pKernArray[0] = rInf.GetWidth() +
rInf.GetKern() +
( rInf.GetSpace() / SPACING_PRECISION_FACTOR );
2002-04-10 06:02:27 +00:00
if ( bSwitchL2R )
rInf.GetFrm()->SwitchLTRtoRTL( aPos );
2002-04-10 06:02:27 +00:00
if ( bSwitchH2V )
rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
rInf.GetOut().DrawTextArray( aPos, rInf.GetText(),
pKernArray, rInf.GetIdx(), 1 );
2002-04-10 06:02:27 +00:00
if( bBullet )
rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray,
rInf.GetIdx() ? 1 : 0, 1 );
2002-04-10 06:02:27 +00:00
}
else
{
xub_Unicode nCh;
// Bei Pairkerning waechst der Printereinfluss auf die Positionierung
sal_uInt16 nMul = 3;
2002-04-10 06:02:27 +00:00
if ( pPrtFont->GetKerning() )
nMul = 1;
const sal_uInt16 nDiv = nMul+1;
2002-04-10 06:02:27 +00:00
// In nSpaceSum wird der durch Blocksatz auf die Spaces verteilte
// Zwischenraum aufsummiert.
// Die Spaces selbst werden im Normalfall in der Mitte des
// Zwischenraums positioniert, deshalb die nSpace/2-Mimik.
// Bei wortweiser Unterstreichung muessen sie am Anfang des
// Zwischenraums stehen, damit dieser nicht unterstrichen wird.
// Ein Space am Anfang oder am Ende des Textes muss allerdings
// vor bzw. hinter den kompletten Zwischenraum gesetzt werden,
// sonst wuerde das Durch-/Unterstreichen Luecken aufweisen.
long nSpaceSum = 0;
// in word line mode and for Arabic, we disable the half space trick:
const long nHalfSpace = pPrtFont->IsWordLineMode() || bNoHalfSpace ? 0 : nSpaceAdd / 2;
const long nOtherHalf = nSpaceAdd - nHalfSpace;
2002-04-10 06:02:27 +00:00
if ( nSpaceAdd && ( cChPrev == CH_BLANK ) )
nSpaceSum = nHalfSpace;
for ( xub_StrLen i=1; i<nCnt; ++i,nKernSum += rInf.GetKern() )
{
nCh = rInf.GetText().GetChar( rInf.GetIdx() + i );
OSL_ENSURE( pScrArray, "Where is the screen array?" );
2002-04-10 06:02:27 +00:00
long nScr;
nScr = pScrArray[ i ] - pScrArray[ i - 1 ];
// Wenn vor uns ein (Ex-)SPACE ist, positionieren wir uns optimal,
// d.h. unseren rechten Rand auf die 100% Druckerposition,
// sind wir sogar selbst ein Ex-SPACE, so positionieren wir uns
// linksbuendig zur Druckerposition.
if ( nCh == CH_BLANK )
{
nScrPos = pKernArray[i-1] + nScr;
2002-04-10 06:02:27 +00:00
if ( cChPrev == CH_BLANK )
nSpaceSum += nOtherHalf;
if ( i + 1 == nCnt )
nSpaceSum += nSpaceAdd;
else
nSpaceSum += nHalfSpace;
}
else
{
if ( cChPrev == CH_BLANK )
{
nScrPos = pKernArray[i-1] + nScr;
2002-04-10 06:02:27 +00:00
// kein Pixel geht verloren:
nSpaceSum += nOtherHalf;
}
else if ( cChPrev == '-' )
nScrPos = pKernArray[i-1] + nScr;
else
{
nScrPos += nScr;
nScrPos = ( nMul * nScrPos + pKernArray[i] ) / nDiv;
}
}
cChPrev = nCh;
pKernArray[i-1] = nScrPos - nScr + nKernSum + nSpaceSum;
// In word line mode and for Arabic, we disabled the half space trick. If a portion
// ends with a blank, the full nSpaceAdd value has been added to the character in
// front of the blank. This leads to painting artifacts, therefore we remove the
// nSpaceAdd value again:
if ( (bNoHalfSpace || pPrtFont->IsWordLineMode()) && i+1 == nCnt && nCh == CH_BLANK )
pKernArray[i-1] = pKernArray[i-1] - nSpaceAdd;
2002-04-10 06:02:27 +00:00
}
// the layout engine requires the total width of the output
pKernArray[ rInf.GetLen() - 1 ] += nKernSum + nSpaceSum;
if( rInf.GetGreyWave() )
{
if( rInf.GetLen() )
{
long nHght = rInf.GetOut().LogicToPixel(
pPrtFont->GetSize() ).Height();
if( WRONG_SHOW_MIN < nHght )
{
if ( rInf.GetOut().GetConnectMetaFile() )
rInf.GetOut().Push();
sal_uInt16 nWave =
2002-04-10 06:02:27 +00:00
WRONG_SHOW_MEDIUM < nHght ? WAVE_NORMAL :
( WRONG_SHOW_SMALL < nHght ? WAVE_SMALL :
WAVE_FLAT );
Color aCol( rInf.GetOut().GetLineColor() );
sal_Bool bColSave = aCol != *pWaveCol;
2002-04-10 06:02:27 +00:00
if ( bColSave )
rInf.GetOut().SetLineColor( *pWaveCol );
2002-04-10 06:02:27 +00:00
Point aEnd;
long nKernVal = pKernArray[ sal_uInt16( rInf.GetLen() - 1 ) ];
2002-04-10 06:02:27 +00:00
sal_uInt16 nDir = bBidiPor ?
2002-04-10 06:02:27 +00:00
1800 :
UnMapDirection(
GetFont()->GetOrientation(),
bSwitchH2V );
2002-04-10 06:02:27 +00:00
switch ( nDir )
{
case 0 :
aEnd.X() = rInf.GetPos().X() + nKernVal;
aEnd.Y() = rInf.GetPos().Y();
break;
case 900 :
aEnd.X() = rInf.GetPos().X();
aEnd.Y() = rInf.GetPos().Y() - nKernVal;
break;
case 1800 :
aEnd.X() = rInf.GetPos().X() - nKernVal;
aEnd.Y() = rInf.GetPos().Y();
break;
case 2700 :
aEnd.X() = rInf.GetPos().X();
aEnd.Y() = rInf.GetPos().Y() + nKernVal;
break;
}
Point aCurrPos( rInf.GetPos() );
2002-04-10 06:02:27 +00:00
if ( bSwitchL2R )
{
rInf.GetFrm()->SwitchLTRtoRTL( aCurrPos );
2002-04-10 06:02:27 +00:00
rInf.GetFrm()->SwitchLTRtoRTL( aEnd );
}
if ( bSwitchH2V )
{
rInf.GetFrm()->SwitchHorizontalToVertical( aCurrPos );
2002-04-10 06:02:27 +00:00
rInf.GetFrm()->SwitchHorizontalToVertical( aEnd );
}
rInf.GetOut().DrawWaveLine( aCurrPos, aEnd, nWave );
2002-04-10 06:02:27 +00:00
if ( bColSave )
rInf.GetOut().SetLineColor( aCol );
2002-04-10 06:02:27 +00:00
if ( rInf.GetOut().GetConnectMetaFile() )
rInf.GetOut().Pop();
}
}
}
else if( !bSymbol && rInf.GetLen() )
2002-04-10 06:02:27 +00:00
{
// anything to do?
if (rInf.GetWrong() || rInf.GetGrammarCheck() || rInf.GetSmartTags())
{
CalcLinePosData aCalcLinePosData(rInf, *GetFont(),
nCnt, bSwitchH2V, bSwitchL2R,
nHalfSpace, pKernArray, bBidiPor);
SwForbidden aForbidden;
// draw line for smart tag data
lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetSmartTags(), aCalcLinePosData, Size() );
// draw wave line for spell check errors
// draw them BEFORE the grammar check lines to 'override' the latter in case of conflict.
// reason: some grammar errors can only be found if spelling errors are fixed,
// therefore we don't want the user to miss a spelling error.
lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetWrong(), aCalcLinePosData, pPrtFont->GetSize() );
// draw wave line for grammar check errors
lcl_DrawLineForWrongListData( aForbidden, rInf, rInf.GetGrammarCheck(), aCalcLinePosData, pPrtFont->GetSize() );
}
2002-04-10 06:02:27 +00:00
}
2002-04-10 06:02:27 +00:00
xub_StrLen nOffs = 0;
xub_StrLen nLen = rInf.GetLen();
2002-04-10 06:02:27 +00:00
if( nOffs < nLen )
{
// If we paint bullets instead of spaces, we use a copy of
// the paragraph string. For the layout engine, the copy
// of the string has to be an environment of the range which
// is painted
xub_StrLen nTmpIdx = bBullet ?
2002-04-10 06:02:27 +00:00
( rInf.GetIdx() ? 1 : 0 ) :
rInf.GetIdx();
if ( bSwitchL2R )
rInf.GetFrm()->SwitchLTRtoRTL( aPos );
if ( bSwitchH2V )
rInf.GetFrm()->SwitchHorizontalToVertical( aPos );
rInf.GetOut().DrawTextArray( aPos, *pStr, pKernArray + nOffs,
nTmpIdx + nOffs , nLen - nOffs );
2002-04-10 06:02:27 +00:00
}
}
delete[] pScrArray;
delete[] pKernArray;
}
}
// Optimierung war fuer DrawText() ausgeschaltet
#ifdef _MSC_VER
#pragma optimize("",on)
#endif
2001-08-31 05:22:48 +00:00
/*************************************************************************
*
* Size SwFntObj::GetTextSize( const OutputDevice *pOut, const String &rTxt,
* const sal_uInt16 nIdx, const sal_uInt16 nLen, const short nKern = 0 );
*
* Beschreibung: ermittelt die TextSize (des Druckers)
*
*************************************************************************/
Size SwFntObj::GetTextSize( SwDrawTextInfo& rInf )
{
Size aTxtSize;
const xub_StrLen nLn = ( STRING_LEN != rInf.GetLen() ) ? rInf.GetLen() :
rInf.GetText().Len();
2000-09-18 23:08:29 +00:00
// be sure to have the correct layout mode at the printer
if ( pPrinter )
{
pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
}
if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
SW_CJK == rInf.GetFont()->GetActual() )
{
GETGRID( rInf.GetFrm()->FindPageFrm() )
if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
{
const SwDoc* pDoc = rInf.GetShell()->GetDoc();
const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
OutputDevice* pOutDev;
if ( pPrinter )
{
if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
pPrinter->SetFont(*pPrtFont);
pOutDev = pPrinter;
}
else
pOutDev = rInf.GetpOut();
aTxtSize.Width() =
pOutDev->GetTextWidth( rInf.GetText(), rInf.GetIdx(), nLn );
OSL_ENSURE( !rInf.GetShell() ||
( USHRT_MAX != GetGuessedLeading() && USHRT_MAX != GetExtLeading() ),
"Leading values should be already calculated" );
aTxtSize.Height() = pOutDev->GetTextHeight() +
GetFontLeading( rInf.GetShell(), rInf.GetOut() );
long nWidthPerChar = aTxtSize.Width() / nLn;
const sal_uLong i = nWidthPerChar ?
( nWidthPerChar - 1 ) / nGridWidth + 1:
1;
aTxtSize.Width() = i * nGridWidth * nLn;
rInf.SetKanaDiff( 0 );
return aTxtSize;
}
}
//for textgrid refactor
if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
SW_CJK == rInf.GetFont()->GetActual() )
{
GETGRID( rInf.GetFrm()->FindPageFrm() )
if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
{
const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
const SwDoc* pDoc = rInf.GetShell()->GetDoc();
long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
if( SW_LATIN == rInf.GetFont()->GetActual() )
nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
else
nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
OutputDevice* pOutDev;
if ( pPrinter )
{
if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
pPrinter->SetFont(*pPrtFont);
pOutDev = pPrinter;
}
else
pOutDev = rInf.GetpOut();
aTxtSize.Width() = pOutDev->GetTextWidth( rInf.GetText(), rInf.GetIdx(), nLn );
aTxtSize.Height() = pOutDev->GetTextHeight() +
GetFontLeading( rInf.GetShell(), rInf.GetOut() );
aTxtSize.Width() += (nLn) * long( nGridWidthAdd );
//if ( rInf.GetKern() && nLn )
// aTxtSize.Width() += ( nLn ) * long( rInf.GetKern() );
rInf.SetKanaDiff( 0 );
return aTxtSize;
}
}
const sal_Bool bCompress = rInf.GetKanaComp() && nLn &&
rInf.GetFont() &&
SW_CJK == rInf.GetFont()->GetActual() &&
rInf.GetScriptInfo() &&
rInf.GetScriptInfo()->CountCompChg() &&
lcl_IsMonoSpaceFont( rInf.GetOut() );
OSL_ENSURE( !bCompress || ( rInf.GetScriptInfo() && rInf.GetScriptInfo()->
CountCompChg()), "Compression without info" );
// This is the part used e.g., for cursor travelling
// See condition for DrawText or DrawTextArray (bDirectPrint)
if ( pPrinter && pPrinter != rInf.GetpOut() )
{
if( !pPrtFont->IsSameInstance( pPrinter->GetFont() ) )
pPrinter->SetFont(*pPrtFont);
aTxtSize.Width() = pPrinter->GetTextWidth( rInf.GetText(),
rInf.GetIdx(), nLn );
aTxtSize.Height() = pPrinter->GetTextHeight();
sal_Int32 *pKernArray = new sal_Int32[nLn];
CreateScrFont( *rInf.GetShell(), rInf.GetOut() );
if( !GetScrFont()->IsSameInstance( rInf.GetOut().GetFont() ) )
rInf.GetOut().SetFont( *pScrFont );
long nScrPos;
2000-09-18 23:08:29 +00:00
2001-04-09 09:44:17 +00:00
pPrinter->GetTextArray( rInf.GetText(), pKernArray, rInf.GetIdx(),nLn );
if( bCompress )
rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( pKernArray,
rInf.GetIdx(), nLn, rInf.GetKanaComp(),
(sal_uInt16)aFont.GetSize().Height() ) );
2001-04-09 09:44:17 +00:00
else
rInf.SetKanaDiff( 0 );
2000-09-18 23:08:29 +00:00
2001-04-09 09:44:17 +00:00
if ( rInf.GetKanaDiff() )
nScrPos = pKernArray[ nLn - 1 ];
2000-09-18 23:08:29 +00:00
else
{
sal_Int32* pScrArray = new sal_Int32[ rInf.GetLen() ];
rInf.GetOut().GetTextArray( rInf.GetText(), pScrArray,
rInf.GetIdx(), rInf.GetLen() );
2002-03-21 09:46:39 +00:00
nScrPos = pScrArray[ 0 ];
2001-04-09 09:44:17 +00:00
xub_StrLen nCnt = rInf.GetText().Len();
if ( nCnt < rInf.GetIdx() )
nCnt=0;
2000-09-18 23:08:29 +00:00
else
nCnt = nCnt - rInf.GetIdx();
2001-04-09 09:44:17 +00:00
nCnt = Min (nCnt, nLn);
xub_Unicode nChPrev = rInf.GetText().GetChar( rInf.GetIdx() );
xub_Unicode nCh;
// Bei Pairkerning waechst der Printereinfluss auf die Positionierung
sal_uInt16 nMul = 3;
if ( pPrtFont->GetKerning() )
2001-04-09 09:44:17 +00:00
nMul = 1;
const sal_uInt16 nDiv = nMul+1;
2001-04-09 09:44:17 +00:00
for( xub_StrLen i=1; i<nCnt; i++ )
2000-09-18 23:08:29 +00:00
{
2001-04-09 09:44:17 +00:00
nCh = rInf.GetText().GetChar( rInf.GetIdx() + i );
long nScr;
2002-03-21 09:46:39 +00:00
nScr = pScrArray[ i ] - pScrArray[ i - 1 ];
2001-04-09 09:44:17 +00:00
if ( nCh == CH_BLANK )
2000-09-18 23:08:29 +00:00
nScrPos = pKernArray[i-1]+nScr;
else
{
2001-04-09 09:44:17 +00:00
if ( nChPrev == CH_BLANK || nChPrev == '-' )
nScrPos = pKernArray[i-1]+nScr;
else
{
nScrPos += nScr;
nScrPos = ( nMul * nScrPos + pKernArray[i] ) / nDiv;
}
2000-09-18 23:08:29 +00:00
}
2001-04-09 09:44:17 +00:00
nChPrev = nCh;
pKernArray[i-1] = nScrPos - nScr;
2000-09-18 23:08:29 +00:00
}
2002-03-21 09:46:39 +00:00
delete[] pScrArray;
2000-09-18 23:08:29 +00:00
}
2001-04-09 09:44:17 +00:00
2000-09-18 23:08:29 +00:00
delete[] pKernArray;
aTxtSize.Width() = nScrPos;
}
else
{
if( !pPrtFont->IsSameInstance( rInf.GetOut().GetFont() ) )
rInf.GetOut().SetFont( *pPrtFont );
2001-04-09 09:44:17 +00:00
if( bCompress )
{
sal_Int32 *pKernArray = new sal_Int32[nLn];
rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), nLn );
2001-04-09 09:44:17 +00:00
rInf.SetKanaDiff( rInf.GetScriptInfo()->Compress( pKernArray,
rInf.GetIdx(), nLn, rInf.GetKanaComp(),
(sal_uInt16) aFont.GetSize().Height() ) );
2001-04-09 09:44:17 +00:00
aTxtSize.Width() = pKernArray[ nLn - 1 ];
delete[] pKernArray;
}
else
{
aTxtSize.Width() = rInf.GetOut().GetTextWidth( rInf.GetText(),
rInf.GetIdx(), nLn );
2001-04-09 09:44:17 +00:00
rInf.SetKanaDiff( 0 );
}
aTxtSize.Height() = rInf.GetOut().GetTextHeight();
2000-09-18 23:08:29 +00:00
}
2001-04-09 09:44:17 +00:00
if ( rInf.GetKern() && nLn )
aTxtSize.Width() += ( nLn - 1 ) * long( rInf.GetKern() );
OSL_ENSURE( !rInf.GetShell() ||
( USHRT_MAX != GetGuessedLeading() && USHRT_MAX != GetExtLeading() ),
"Leading values should be already calculated" );
aTxtSize.Height() += GetFontLeading( rInf.GetShell(), rInf.GetOut() );
2000-09-18 23:08:29 +00:00
return aTxtSize;
}
2002-04-10 06:02:27 +00:00
xub_StrLen SwFntObj::GetCrsrOfst( SwDrawTextInfo &rInf )
{
long nSpaceAdd = rInf.GetSpace() / SPACING_PRECISION_FACTOR;
const long nSperren = -rInf.GetSperren() / SPACING_PRECISION_FACTOR;
long nKern = rInf.GetKern();
if( 0 != nSperren )
nKern -= nSperren;
2002-04-10 06:02:27 +00:00
sal_Int32 *pKernArray = new sal_Int32[ rInf.GetLen() ];
2002-04-10 06:02:27 +00:00
// be sure to have the correct layout mode at the printer
2002-04-10 06:02:27 +00:00
if ( pPrinter )
{
pPrinter->SetLayoutMode( rInf.GetOut().GetLayoutMode() );
pPrinter->SetDigitLanguage( rInf.GetOut().GetDigitLanguage() );
2002-04-10 06:02:27 +00:00
pPrinter->GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), rInf.GetLen() );
}
2002-04-10 06:02:27 +00:00
else
rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), rInf.GetLen() );
2002-04-10 06:02:27 +00:00
const SwScriptInfo* pSI = rInf.GetScriptInfo();
2002-04-10 06:02:27 +00:00
if ( rInf.GetFont() && rInf.GetLen() )
{
const sal_uInt8 nActual = rInf.GetFont()->GetActual();
2002-04-10 06:02:27 +00:00
// Kana Compression
if ( SW_CJK == nActual && rInf.GetKanaComp() &&
pSI && pSI->CountCompChg() &&
lcl_IsMonoSpaceFont( rInf.GetOut() ) )
2002-04-10 06:02:27 +00:00
{
pSI->Compress( pKernArray, rInf.GetIdx(), rInf.GetLen(),
rInf.GetKanaComp(),
(sal_uInt16) aFont.GetSize().Height() );
2002-04-10 06:02:27 +00:00
}
// Asian Justification
if ( SW_CJK == rInf.GetFont()->GetActual() )
{
LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CJK );
if ( LANGUAGE_KOREAN != aLang && LANGUAGE_KOREAN_JOHAB != aLang )
{
long nSpaceSum = nSpaceAdd;
for ( sal_uInt16 nI = 0; nI < rInf.GetLen(); ++nI )
{
pKernArray[ nI ] += nSpaceSum;
nSpaceSum += nSpaceAdd;
}
nSpaceAdd = 0;
}
}
// Kashida Justification
if ( SW_CTL == nActual && rInf.GetSpace() )
{
if ( SwScriptInfo::IsArabicText( rInf.GetText(), rInf.GetIdx(), rInf.GetLen() ) )
{
if ( pSI && pSI->CountKashida() &&
pSI->KashidaJustify( pKernArray, 0, rInf.GetIdx(), rInf.GetLen(),
nSpaceAdd ) != STRING_LEN )
nSpaceAdd = 0;
}
}
// Thai Justification
if ( SW_CTL == nActual && nSpaceAdd )
2002-04-10 06:02:27 +00:00
{
LanguageType aLang = rInf.GetFont()->GetLanguage( SW_CTL );
if ( LANGUAGE_THAI == aLang )
{
SwScriptInfo::ThaiJustify( rInf.GetText(), pKernArray, 0,
rInf.GetIdx(), rInf.GetLen(),
rInf.GetNumberOfBlanks(),
rInf.GetSpace() );
// adding space to blanks is already done
nSpaceAdd = 0;
}
2002-04-10 06:02:27 +00:00
}
}
long nLeft = 0;
long nRight = 0;
xub_StrLen nCnt = 0;
long nSpaceSum = 0;
2002-04-10 06:02:27 +00:00
long nKernSum = 0;
if ( rInf.GetFrm() && rInf.GetLen() && rInf.SnapToGrid() &&
rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
{
GETGRID( rInf.GetFrm()->FindPageFrm() )
if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
2002-04-10 06:02:27 +00:00
{
const SwDoc* pDoc = rInf.GetShell()->GetDoc();
const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
2002-04-10 06:02:27 +00:00
long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
sal_uLong i = nWidthPerChar ?
( nWidthPerChar - 1 ) / nGridWidth + 1:
1;
2002-04-10 06:02:27 +00:00
nWidthPerChar = i * nGridWidth;
nCnt = (sal_uInt16)(rInf.GetOfst() / nWidthPerChar);
2002-04-10 06:02:27 +00:00
if ( 2 * ( rInf.GetOfst() - nCnt * nWidthPerChar ) > nWidthPerChar )
++nCnt;
delete[] pKernArray;
return nCnt;
}
}
//for textgrid refactor
if ( rInf.GetFrm() && rInf.GetLen() && rInf.SnapToGrid() &&
rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
{
GETGRID( rInf.GetFrm()->FindPageFrm() )
if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
{
const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
const SwDoc* pDoc = rInf.GetShell()->GetDoc();
long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
if( SW_LATIN == rInf.GetFont()->GetActual() )
nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2;
else
nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
for(xub_StrLen j = 0; j < rInf.GetLen(); j++)
{
long nScr = pKernArray[ j ] + ( nSpaceAdd + nGridWidthAdd ) * ( j + 1 );
if( nScr >= rInf.GetOfst())
{
nCnt = j;
break;
}
}
delete[] pKernArray;
return nCnt;
}
}
sal_uInt16 nItrMode = i18n::CharacterIteratorMode::SKIPCELL;
sal_Int32 nDone = 0;
LanguageType aLang = LANGUAGE_NONE;
bool bSkipCharacterCells = false;
xub_StrLen nIdx = rInf.GetIdx();
xub_StrLen nLastIdx = nIdx;
const xub_StrLen nEnd = rInf.GetIdx() + rInf.GetLen();
2001-04-09 09:44:17 +00:00
// #i105901#
// skip character cells for all script types
if ( pBreakIt->GetBreakIter().is() )
2000-09-18 23:08:29 +00:00
{
aLang = rInf.GetFont()->GetLanguage();
bSkipCharacterCells = true;
2000-09-18 23:08:29 +00:00
}
while ( ( nRight < long( rInf.GetOfst() ) ) && ( nIdx < nEnd ) )
{
if ( nSpaceAdd && CH_BLANK == rInf.GetText().GetChar( nIdx ) )
nSpaceSum += nSpaceAdd;
// go to next character (cell).
nLastIdx = nIdx;
if ( bSkipCharacterCells )
{
CWS-TOOLING: integrate CWS oj18 2009-08-21 15:08:49 +0200 oj r275263 : wrong check 2009-08-21 08:56:01 +0200 oj r275215 : missing not 2009-08-20 07:27:13 +0200 oj r275164 : use new method from global 2009-08-19 10:22:35 +0200 oj r275138 : call GetLocale instead of pLocale 2009-08-18 10:39:32 +0200 oj r275082 : missing header include 2009-08-18 10:09:44 +0200 oj r275081 : new methods at global 2009-08-18 10:09:00 +0200 oj r275080 : unused var 2009-08-18 08:59:04 +0200 oj r275078 : move files from classes to xml 2009-08-17 14:58:16 +0200 oj r275056 : CWS-TOOLING: rebase CWS oj18 to trunk@275001 (milestone: DEV300:m55) 2009-08-17 13:29:44 +0200 oj r275047 : compile error 2009-08-17 13:27:47 +0200 oj r275045 : compile error 2009-08-17 11:44:54 +0200 oj r275040 : add dep 2009-07-22 14:26:05 +0200 oj r274240 : move unused services into fwl 2009-07-22 14:25:35 +0200 oj r274239 : move unused services into fwl 2009-07-22 13:47:45 +0200 oj r274233 : remove some unused code 2009-07-22 09:06:20 +0200 oj r274219 : export dbtoolsclient dbcharsethelper for sc 2009-07-22 08:48:58 +0200 oj r274218 : create NumberFormatter on demand 2009-07-22 08:39:23 +0200 oj r274217 : change char to sal_Char 2009-07-22 07:33:34 +0200 oj r274214 : export dbtoolsclient dbcharsethelper for sc 2009-07-22 07:30:04 +0200 oj r274213 : late init of numberformatter and breakiterator 2009-07-22 07:28:55 +0200 oj r274212 : export dbtoolsclient dbcharsethelper for sc 2009-07-21 13:43:28 +0200 oj r274196 : check if quick start is enbaled 2009-07-21 13:40:09 +0200 oj r274195 : check config entry for UiEventsLogger 2009-07-21 13:37:40 +0200 oj r274194 : code refactoring, remove of duplicate code and some late inits and removale of not needed files 2009-07-21 13:35:38 +0200 oj r274193 : code refactoring, remove of duplicate code and some late inits and removale of not needed files 2009-07-21 13:33:41 +0200 oj r274192 : doc meta data will now be created on demand 2009-07-21 13:13:40 +0200 oj r274187 : load ldap functions on demand 2009-07-21 13:03:17 +0200 oj r274183 : late init of TransliterationImpl 2009-07-21 12:36:10 +0200 oj r274180 : late init of charClass
2009-09-08 04:57:32 +00:00
nIdx = (xub_StrLen)pBreakIt->GetBreakIter()->nextCharacters( rInf.GetText(),
nIdx, pBreakIt->GetLocale( aLang ), nItrMode, 1, nDone );
if ( nIdx <= nLastIdx )
break;
}
else
++nIdx;
2000-09-18 23:08:29 +00:00
nLeft = nRight;
nRight = pKernArray[ nIdx - rInf.GetIdx() - 1 ] + nKernSum + nSpaceSum;
2000-09-18 23:08:29 +00:00
nKernSum += nKern;
}
// step back if position is before the middle of the character
// or if we do not want to go to the next character
if ( nIdx > rInf.GetIdx() &&
( rInf.IsPosMatchesBounds() ||
( ( nRight > long( rInf.GetOfst() ) ) &&
( nRight - rInf.GetOfst() > rInf.GetOfst() - nLeft ) ) ) )
nCnt = nLastIdx - rInf.GetIdx(); // first half
else
nCnt = nIdx - rInf.GetIdx(); // second half
if ( pSI )
rInf.SetCursorBidiLevel( pSI->DirType( nLastIdx ) );
2000-09-18 23:08:29 +00:00
delete[] pKernArray;
return nCnt;
}
2002-04-10 06:02:27 +00:00
2000-09-18 23:08:29 +00:00
/*************************************************************************
|*
|* SwFntAccess::SwFntAccess()
|*
|*************************************************************************/
SwFntAccess::SwFntAccess( const void* &rMagic,
sal_uInt16 &rIndex, const void *pOwn, ViewShell *pSh,
sal_Bool bCheck ) :
2000-09-18 23:08:29 +00:00
SwCacheAccess( *pFntCache, rMagic, rIndex ),
pShell( pSh )
{
// Der benutzte CTor von SwCacheAccess sucht anhand rMagic+rIndex im Cache
if ( IsAvail() )
{
// Der schnellste Fall: ein bekannter Font ( rMagic ),
// bei dem Drucker und Zoom nicht ueberprueft werden brauchen.
if ( !bCheck )
return;
// Hier ist zwar der Font bekannt, muss aber noch ueberprueft werden.
}
else
// Hier ist der Font nicht bekannt, muss also gesucht werden.
bCheck = sal_False;
2000-09-18 23:08:29 +00:00
2000-09-18 23:08:29 +00:00
{
OutputDevice* pOut = 0;
sal_uInt16 nZoom = USHRT_MAX;
// Get the reference device
2000-09-18 23:08:29 +00:00
if ( pSh )
{
pOut = &pSh->GetRefDev();
2000-09-18 23:08:29 +00:00
nZoom = pSh->GetViewOptions()->GetZoom();
}
SwFntObj *pFntObj;
if ( bCheck )
{
pFntObj = Get();
2000-09-18 23:08:29 +00:00
if ( ( pFntObj->GetZoom( ) == nZoom ) &&
2001-02-13 07:56:40 +00:00
( pFntObj->pPrinter == pOut ) &&
pFntObj->GetPropWidth() ==
((SwSubFont*)pOwn)->GetPropWidth() )
2000-09-18 23:08:29 +00:00
return; // Die Ueberpruefung ergab: Drucker+Zoom okay.
pFntObj->Unlock( ); // Vergiss dies Objekt, es wurde leider
pObj = NULL; // eine Drucker/Zoomaenderung festgestellt.
}
// Search by font comparison, quite expensive!
// Look for same font and same printer
2000-09-18 23:08:29 +00:00
pFntObj = pFntCache->First();
while ( pFntObj && !( pFntObj->aFont == *(Font *)pOwn &&
pFntObj->GetZoom() == nZoom &&
pFntObj->GetPropWidth() ==
((SwSubFont*)pOwn)->GetPropWidth() &&
( !pFntObj->pPrinter || pFntObj->pPrinter == pOut ) ) )
2000-09-18 23:08:29 +00:00
pFntObj = pFntCache->Next( pFntObj );
2000-09-18 23:08:29 +00:00
if( pFntObj && pFntObj->pPrinter != pOut )
{
// Wir haben zwar einen ohne Drucker gefunden, mal sehen, ob es
// auch noch einen mit identischem Drucker gibt.
SwFntObj *pTmpObj = pFntObj;
while( pTmpObj && !( pTmpObj->aFont == *(Font *)pOwn &&
2001-02-13 07:56:40 +00:00
pTmpObj->GetZoom()==nZoom && pTmpObj->pPrinter==pOut &&
pTmpObj->GetPropWidth() ==
((SwSubFont*)pOwn)->GetPropWidth() ) )
2000-09-18 23:08:29 +00:00
pTmpObj = pFntCache->Next( pTmpObj );
if( pTmpObj )
pFntObj = pTmpObj;
}
if ( !pFntObj ) // Font has not been found, create one
2000-09-18 23:08:29 +00:00
{
// Das Objekt muss neu angelegt werden, deshalb muss der Owner ein
// SwFont sein, spaeter wird als Owner die "MagicNumber" gehalten.
SwCacheAccess::pOwner = pOwn;
pFntObj = Get(); // hier wird via NewObj() angelegt und gelockt.
OSL_ENSURE(pFntObj, "No Font, no Fun.");
2000-09-18 23:08:29 +00:00
}
else // Font has been found, so we lock it.
2000-09-18 23:08:29 +00:00
{
pFntObj->Lock();
if( pFntObj->pPrinter != pOut ) // Falls bis dato kein Drucker bekannt
{
OSL_ENSURE( !pFntObj->pPrinter, "SwFntAccess: Printer Changed" );
pFntObj->CreatePrtFont( *pOut );
2000-09-18 23:08:29 +00:00
pFntObj->pPrinter = pOut;
pFntObj->pScrFont = NULL;
pFntObj->nGuessedLeading = USHRT_MAX;
pFntObj->nExtLeading = USHRT_MAX;
2001-04-03 11:52:45 +00:00
pFntObj->nPrtAscent = USHRT_MAX;
pFntObj->nPrtHeight = USHRT_MAX;
2000-09-18 23:08:29 +00:00
}
pObj = pFntObj;
}
2000-09-18 23:08:29 +00:00
// egal, ob neu oder gefunden, ab jetzt ist der Owner vom Objekt eine
// MagicNumber und wird auch dem aufrufenden SwFont bekanntgegeben,
// ebenso der Index fuer spaetere direkte Zugriffe
rMagic = pFntObj->GetOwner();
SwCacheAccess::pOwner = rMagic;
rIndex = pFntObj->GetCachePos();
}
}
SwCacheObj *SwFntAccess::NewObj( )
{
// Ein neuer Font, eine neue "MagicNumber".
2001-02-13 07:56:40 +00:00
return new SwFntObj( *(SwSubFont *)pOwner, ++pMagicNo, pShell );
2000-09-18 23:08:29 +00:00
}
extern xub_StrLen lcl_CalcCaseMap( const SwFont& rFnt,
const XubString& rOrigString,
xub_StrLen nOfst,
xub_StrLen nLen,
xub_StrLen nIdx );
2001-04-09 09:44:17 +00:00
xub_StrLen SwFont::GetTxtBreak( SwDrawTextInfo& rInf, long nTextWidth )
{
ChgFnt( rInf.GetShell(), rInf.GetOut() );
const sal_Bool bCompress = rInf.GetKanaComp() && rInf.GetLen() &&
SW_CJK == GetActual() &&
rInf.GetScriptInfo() &&
rInf.GetScriptInfo()->CountCompChg() &&
lcl_IsMonoSpaceFont( rInf.GetOut() );
OSL_ENSURE( !bCompress || ( rInf.GetScriptInfo() && rInf.GetScriptInfo()->
2001-04-09 09:44:17 +00:00
CountCompChg()), "Compression without info" );
sal_uInt16 nTxtBreak = 0;
2001-04-09 09:44:17 +00:00
long nKern = 0;
sal_uInt16 nLn = ( rInf.GetLen() == STRING_LEN ? rInf.GetText().Len()
2001-04-09 09:44:17 +00:00
: rInf.GetLen() );
if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() &&
rInf.GetFont() && SW_CJK == rInf.GetFont()->GetActual() )
{
GETGRID( rInf.GetFrm()->FindPageFrm() )
if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && pGrid->IsSnapToChars() )
{
const SwDoc* pDoc = rInf.GetShell()->GetDoc();
const sal_uInt16 nGridWidth = GETGRIDWIDTH(pGrid, pDoc);
sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), rInf.GetLen() );
long nWidthPerChar = pKernArray[ rInf.GetLen() - 1 ] / rInf.GetLen();
const sal_uLong i = nWidthPerChar ?
( nWidthPerChar - 1 ) / nGridWidth + 1:
1;
nWidthPerChar = i * nGridWidth;
long nCurrPos = nWidthPerChar;
while( nTxtBreak < rInf.GetLen() && nTextWidth >= nCurrPos )
{
nCurrPos += nWidthPerChar;
++nTxtBreak;
}
delete[] pKernArray;
return nTxtBreak + rInf.GetIdx();
}
}
//for text grid enhancement
if ( rInf.GetFrm() && nLn && rInf.SnapToGrid() && rInf.GetFont() &&
SW_CJK == rInf.GetFont()->GetActual() )
{
GETGRID( rInf.GetFrm()->FindPageFrm() )
if ( pGrid && GRID_LINES_CHARS == pGrid->GetGridType() && !pGrid->IsSnapToChars() )
{
const sal_uInt16 nDefaultFontHeight = GetDefaultFontHeight( rInf );
const SwDoc* pDoc = rInf.GetShell()->GetDoc();
long nGridWidthAdd = GETGRIDWIDTH(pGrid, pDoc);
if( SW_LATIN == rInf.GetFont()->GetActual() )
nGridWidthAdd = ( nGridWidthAdd - nDefaultFontHeight ) / 2 ;
else
nGridWidthAdd = nGridWidthAdd - nDefaultFontHeight;
sal_Int32* pKernArray = new sal_Int32[rInf.GetLen()];
rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), rInf.GetLen() );
long nCurrPos = pKernArray[nTxtBreak] + nGridWidthAdd;
while( nTxtBreak < rInf.GetLen() && nTextWidth >= nCurrPos)
{
nTxtBreak++;
nCurrPos = pKernArray[nTxtBreak] + nGridWidthAdd * ( nTxtBreak + 1 );
}
delete[] pKernArray;
return nTxtBreak + rInf.GetIdx();
}
}
2001-04-09 09:44:17 +00:00
if( aSub[nActual].IsCapital() && nLn )
nTxtBreak = GetCapitalBreak( rInf.GetShell(), rInf.GetpOut(),
rInf.GetScriptInfo(), rInf.GetText(), nTextWidth,0, rInf.GetIdx(),nLn );
else
{
nKern = CheckKerning();
const XubString* pTmpText;
XubString aTmpText;
xub_StrLen nTmpIdx;
xub_StrLen nTmpLen;
bool bTextReplaced = false;
if ( !aSub[nActual].IsCaseMap() )
2001-04-09 09:44:17 +00:00
{
pTmpText = &rInf.GetText();
nTmpIdx = rInf.GetIdx();
nTmpLen = nLn;
}
else
{
const XubString aSnippet( rInf.GetText(), rInf.GetIdx(), nLn );
aTmpText = aSub[nActual].CalcCaseMap( aSnippet );
const bool bTitle = SVX_CASEMAP_TITEL == aSub[nActual].GetCaseMap() &&
CWS-TOOLING: integrate CWS oj18 2009-08-21 15:08:49 +0200 oj r275263 : wrong check 2009-08-21 08:56:01 +0200 oj r275215 : missing not 2009-08-20 07:27:13 +0200 oj r275164 : use new method from global 2009-08-19 10:22:35 +0200 oj r275138 : call GetLocale instead of pLocale 2009-08-18 10:39:32 +0200 oj r275082 : missing header include 2009-08-18 10:09:44 +0200 oj r275081 : new methods at global 2009-08-18 10:09:00 +0200 oj r275080 : unused var 2009-08-18 08:59:04 +0200 oj r275078 : move files from classes to xml 2009-08-17 14:58:16 +0200 oj r275056 : CWS-TOOLING: rebase CWS oj18 to trunk@275001 (milestone: DEV300:m55) 2009-08-17 13:29:44 +0200 oj r275047 : compile error 2009-08-17 13:27:47 +0200 oj r275045 : compile error 2009-08-17 11:44:54 +0200 oj r275040 : add dep 2009-07-22 14:26:05 +0200 oj r274240 : move unused services into fwl 2009-07-22 14:25:35 +0200 oj r274239 : move unused services into fwl 2009-07-22 13:47:45 +0200 oj r274233 : remove some unused code 2009-07-22 09:06:20 +0200 oj r274219 : export dbtoolsclient dbcharsethelper for sc 2009-07-22 08:48:58 +0200 oj r274218 : create NumberFormatter on demand 2009-07-22 08:39:23 +0200 oj r274217 : change char to sal_Char 2009-07-22 07:33:34 +0200 oj r274214 : export dbtoolsclient dbcharsethelper for sc 2009-07-22 07:30:04 +0200 oj r274213 : late init of numberformatter and breakiterator 2009-07-22 07:28:55 +0200 oj r274212 : export dbtoolsclient dbcharsethelper for sc 2009-07-21 13:43:28 +0200 oj r274196 : check if quick start is enbaled 2009-07-21 13:40:09 +0200 oj r274195 : check config entry for UiEventsLogger 2009-07-21 13:37:40 +0200 oj r274194 : code refactoring, remove of duplicate code and some late inits and removale of not needed files 2009-07-21 13:35:38 +0200 oj r274193 : code refactoring, remove of duplicate code and some late inits and removale of not needed files 2009-07-21 13:33:41 +0200 oj r274192 : doc meta data will now be created on demand 2009-07-21 13:13:40 +0200 oj r274187 : load ldap functions on demand 2009-07-21 13:03:17 +0200 oj r274183 : late init of TransliterationImpl 2009-07-21 12:36:10 +0200 oj r274180 : late init of charClass
2009-09-08 04:57:32 +00:00
pBreakIt->GetBreakIter().is();
// Uaaaaahhhh!!! In title case mode, we would get wrong results
if ( bTitle && nLn )
{
// check if rInf.GetIdx() is begin of word
CWS-TOOLING: integrate CWS oj18 2009-08-21 15:08:49 +0200 oj r275263 : wrong check 2009-08-21 08:56:01 +0200 oj r275215 : missing not 2009-08-20 07:27:13 +0200 oj r275164 : use new method from global 2009-08-19 10:22:35 +0200 oj r275138 : call GetLocale instead of pLocale 2009-08-18 10:39:32 +0200 oj r275082 : missing header include 2009-08-18 10:09:44 +0200 oj r275081 : new methods at global 2009-08-18 10:09:00 +0200 oj r275080 : unused var 2009-08-18 08:59:04 +0200 oj r275078 : move files from classes to xml 2009-08-17 14:58:16 +0200 oj r275056 : CWS-TOOLING: rebase CWS oj18 to trunk@275001 (milestone: DEV300:m55) 2009-08-17 13:29:44 +0200 oj r275047 : compile error 2009-08-17 13:27:47 +0200 oj r275045 : compile error 2009-08-17 11:44:54 +0200 oj r275040 : add dep 2009-07-22 14:26:05 +0200 oj r274240 : move unused services into fwl 2009-07-22 14:25:35 +0200 oj r274239 : move unused services into fwl 2009-07-22 13:47:45 +0200 oj r274233 : remove some unused code 2009-07-22 09:06:20 +0200 oj r274219 : export dbtoolsclient dbcharsethelper for sc 2009-07-22 08:48:58 +0200 oj r274218 : create NumberFormatter on demand 2009-07-22 08:39:23 +0200 oj r274217 : change char to sal_Char 2009-07-22 07:33:34 +0200 oj r274214 : export dbtoolsclient dbcharsethelper for sc 2009-07-22 07:30:04 +0200 oj r274213 : late init of numberformatter and breakiterator 2009-07-22 07:28:55 +0200 oj r274212 : export dbtoolsclient dbcharsethelper for sc 2009-07-21 13:43:28 +0200 oj r274196 : check if quick start is enbaled 2009-07-21 13:40:09 +0200 oj r274195 : check config entry for UiEventsLogger 2009-07-21 13:37:40 +0200 oj r274194 : code refactoring, remove of duplicate code and some late inits and removale of not needed files 2009-07-21 13:35:38 +0200 oj r274193 : code refactoring, remove of duplicate code and some late inits and removale of not needed files 2009-07-21 13:33:41 +0200 oj r274192 : doc meta data will now be created on demand 2009-07-21 13:13:40 +0200 oj r274187 : load ldap functions on demand 2009-07-21 13:03:17 +0200 oj r274183 : late init of TransliterationImpl 2009-07-21 12:36:10 +0200 oj r274180 : late init of charClass
2009-09-08 04:57:32 +00:00
if ( !pBreakIt->GetBreakIter()->isBeginWord(
rInf.GetText(), rInf.GetIdx(),
pBreakIt->GetLocale( aSub[nActual].GetLanguage() ),
i18n::WordType::ANYWORD_IGNOREWHITESPACES ) )
{
// In this case, the beginning of aTmpText is wrong.
XubString aSnippetTmp( aSnippet, 0, 1 );
aSnippetTmp = aSub[nActual].CalcCaseMap( aSnippetTmp );
aTmpText.Erase( 0, aSnippetTmp.Len() );
aTmpText.Insert( aSnippet.GetChar( 0 ), 0 );
}
}
pTmpText = &aTmpText;
nTmpIdx = 0;
nTmpLen = aTmpText.Len();
bTextReplaced = true;
2001-04-09 09:44:17 +00:00
}
if( rInf.GetHyphPos() )
nTxtBreak = rInf.GetOut().GetTextBreak( *pTmpText, nTextWidth,
'-', *rInf.GetHyphPos(),
nTmpIdx, nTmpLen, nKern );
2001-04-09 09:44:17 +00:00
else
nTxtBreak = rInf.GetOut().GetTextBreak( *pTmpText, nTextWidth,
nTmpIdx, nTmpLen, nKern );
if ( bTextReplaced && STRING_LEN != nTxtBreak )
2001-04-09 09:44:17 +00:00
{
if ( nTmpLen != nLn )
nTxtBreak = lcl_CalcCaseMap( *this, rInf.GetText(),
rInf.GetIdx(), nLn, nTxtBreak );
2001-04-09 09:44:17 +00:00
else
nTxtBreak = nTxtBreak + rInf.GetIdx();
2001-04-09 09:44:17 +00:00
}
}
if ( ! bCompress )
return nTxtBreak;
nTxtBreak = nTxtBreak - rInf.GetIdx();
2001-04-09 09:44:17 +00:00
if( nTxtBreak < nLn )
{
if( !nTxtBreak && nLn )
nLn = 1;
else if( nLn > 2 * nTxtBreak )
nLn = 2 * nTxtBreak;
sal_Int32 *pKernArray = new sal_Int32[ nLn ];
2001-04-09 09:44:17 +00:00
rInf.GetOut().GetTextArray( rInf.GetText(), pKernArray,
rInf.GetIdx(), nLn );
if( rInf.GetScriptInfo()->Compress( pKernArray, rInf.GetIdx(), nLn,
rInf.GetKanaComp(), (sal_uInt16)GetHeight( nActual ) ) )
2001-04-09 09:44:17 +00:00
{
long nKernAdd = nKern;
xub_StrLen nTmpBreak = nTxtBreak;
if( nKern && nTxtBreak )
nKern *= nTxtBreak - 1;
while( nTxtBreak<nLn && nTextWidth >= pKernArray[nTxtBreak] +nKern )
{
nKern += nKernAdd;
++nTxtBreak;
}
if( rInf.GetHyphPos() )
*rInf.GetHyphPos() += nTxtBreak - nTmpBreak; // It's not perfect
}
delete[] pKernArray;
}
nTxtBreak = nTxtBreak + rInf.GetIdx();
2001-04-09 09:44:17 +00:00
return nTxtBreak;
}
extern Color aGlobalRetoucheColor;
sal_Bool SwDrawTextInfo::ApplyAutoColor( Font* pFont )
{
const Font& rFnt = pFont ? *pFont : GetOut().GetFont();
sal_Bool bPrt = GetShell() && ! GetShell()->GetWin();
ColorData nNewColor = COL_BLACK;
sal_Bool bChgFntColor = sal_False;
sal_Bool bChgLineColor = sal_False;
if( bPrt && GetShell() && GetShell()->GetViewOptions()->IsBlackFont() )
{
if ( COL_BLACK != rFnt.GetColor().GetColor() )
bChgFntColor = sal_True;
if ( (COL_BLACK != GetOut().GetLineColor().GetColor()) ||
(COL_BLACK != GetOut().GetOverlineColor().GetColor()) )
bChgLineColor = sal_True;
}
else
{
// FontColor has to be changed if:
// 1. FontColor = AUTO or 2. IsAlwaysAutoColor is set
// LineColor has to be changed if:
// 1. IsAlwaysAutoColor is set
bChgLineColor = ! bPrt && GetShell() &&
GetShell()->GetAccessibilityOptions()->IsAlwaysAutoColor();
bChgFntColor = COL_AUTO == rFnt.GetColor().GetColor() || bChgLineColor;
if ( bChgFntColor )
{
// check if current background has a user defined setting
const Color* pCol = GetFont() ? GetFont()->GetBackColor() : NULL;
if( ! pCol || COL_TRANSPARENT == pCol->GetColor() )
{
const SvxBrushItem* pItem;
SwRect aOrigBackRect;
/// OD 21.08.2002
/// consider, that [GetBackgroundBrush(...)] can set <pCol>
/// - see implementation in /core/layout/paintfrm.cxx
/// OD 21.08.2002 #99657#
/// There is a user defined setting for the background, if there
/// is a background brush and its color is *not* "no fill"/"auto fill".
if( GetFrm()->GetBackgroundBrush( pItem, pCol, aOrigBackRect, sal_False ) )
{
if ( !pCol )
{
pCol = &pItem->GetColor();
}
/// OD 30.08.2002 #99657#
/// determined color <pCol> can be <COL_TRANSPARENT>. Thus, check it.
if ( pCol->GetColor() == COL_TRANSPARENT)
pCol = NULL;
}
else
pCol = NULL;
}
// no user defined color at paragraph or font background
if ( ! pCol )
pCol = &aGlobalRetoucheColor;
if( GetShell() && GetShell()->GetWin() )
{
// here we determine the prefered window text color for painting
const SwViewOption* pViewOption = GetShell()->GetViewOptions();
if(pViewOption->IsPagePreview() &&
!SW_MOD()->GetAccessibilityOptions().GetIsForPagePreviews())
nNewColor = COL_BLACK;
else
// we take the font color from the appearence page
nNewColor = SwViewOption::GetFontColor().GetColor();
}
// change painting color depending of dark/bright background
Color aTmpColor( nNewColor );
if ( pCol->IsDark() && aTmpColor.IsDark() )
nNewColor = COL_WHITE;
else if ( pCol->IsBright() && aTmpColor.IsBright() )
nNewColor = COL_BLACK;
}
}
if ( bChgFntColor || bChgLineColor )
{
Color aNewColor( nNewColor );
if ( bChgFntColor )
{
if ( pFont && aNewColor != pFont->GetColor() )
{
// only set the new color at the font passed as argument
pFont->SetColor( aNewColor );
}
else if ( aNewColor != GetOut().GetFont().GetColor() )
{
// set new font with new color at output device
Font aFont( rFnt );
aFont.SetColor( aNewColor );
GetOut().SetFont( aFont );
}
}
// the underline and overline colors have to be set separately
if ( bChgLineColor )
{
// get current font color or color set at output device
aNewColor = pFont ? pFont->GetColor() : GetOut().GetFont().GetColor();
if ( aNewColor != GetOut().GetLineColor() )
GetOut().SetLineColor( aNewColor );
if ( aNewColor != GetOut().GetOverlineColor() )
GetOut().SetOverlineColor( aNewColor );
}
return sal_True;
}
return sal_False;
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */