summaryrefslogtreecommitdiff
path: root/vcl/source
diff options
context:
space:
mode:
authorFrank Schönheit <fs@openoffice.org>2009-09-18 10:39:28 +0000
committerFrank Schönheit <fs@openoffice.org>2009-09-18 10:39:28 +0000
commitf20d782ce054876754188345ff013ede4a216f72 (patch)
tree743f149082351a9b0d3bfe2599f0d8aff2754911 /vcl/source
parent79cad7d02a0eb7cc6e662ad424204f4599a7981a (diff)
#b6875455#
- made ImplDrawText and ImplGetTextLines static This way, we find all places where both methods access the target device (which is now explicit instead of implicit), and can make sure that everything is routed through the ITextLayout interface, if necessary. - also, made both methods take ITextLayout& instead of a ITextLayout* - added a default implementation for ITextLayout, which simply delegates all calls to a target device, without any magic - added GetCaretPositions to the ITextLayout interface, since this clearly is controlled by the text layout. Implement the new method for both DefaultTextLayout and ReferenceDeviceTextLayout - let the ReferenceDeviceTextLayout calculate more precise, when zooming/unzooming geometry data - let the ReferenceDeviceTextLayout do less actions on the reference device - pushing and popping the Font is necessary only once, not for every DrawText(Point) action
Diffstat (limited to 'vcl/source')
-rw-r--r--vcl/source/gdi/outdev3.cxx143
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx5
-rwxr-xr-xvcl/source/gdi/textlayout.cxx117
3 files changed, 162 insertions, 103 deletions
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
index 7865ca507418..6d5817f0dffd 100644
--- a/vcl/source/gdi/outdev3.cxx
+++ b/vcl/source/gdi/outdev3.cxx
@@ -5256,9 +5256,9 @@ void OutputDevice::ImplDrawText( SalLayout& rSalLayout )
// -----------------------------------------------------------------------
-long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
+long OutputDevice::ImplGetTextLines( OutputDevice& rTargetDevice, ImplMultiTextLineInfo& rLineInfo,
long nWidth, const XubString& rStr,
- USHORT nStyle, const ::vcl::ITextLayout* _pLayout ) const
+ USHORT nStyle, const ::vcl::ITextLayout& _rLayout )
{
DBG_ASSERTWARNING( nWidth >= 0, "ImplGetTextLines: nWidth <= 0!" );
@@ -5296,8 +5296,7 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
while ( ( nBreakPos < nLen ) && ( rStr.GetChar( nBreakPos ) != _CR ) && ( rStr.GetChar( nBreakPos ) != _LF ) )
nBreakPos++;
- long nLineWidth = ( _pLayout != NULL ) ? _pLayout->GetTextWidth( rStr, nPos, nBreakPos-nPos )
- : GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ long nLineWidth = _rLayout.GetTextWidth( rStr, nPos, nBreakPos-nPos );
if ( ( nLineWidth > nWidth ) && ( nStyle & TEXT_DRAW_WORDBREAK ) )
{
if ( !xBI.is() )
@@ -5306,7 +5305,7 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
if ( xBI.is() )
{
const com::sun::star::lang::Locale& rDefLocale(Application::GetSettings().GetUILocale());
- xub_StrLen nSoftBreak = GetTextBreak( rStr, nWidth, nPos, nBreakPos - nPos );
+ xub_StrLen nSoftBreak = rTargetDevice.GetTextBreak( rStr, nWidth, nPos, nBreakPos - nPos );
DBG_ASSERT( nSoftBreak < nBreakPos, "Break?!" );
//aHyphOptions.hyphenIndex = nSoftBreak;
i18n::LineBreakResults aLBR = xBI->getLineBreak( aText, nSoftBreak, rDefLocale, nPos, aHyphOptions, aUserOptions );
@@ -5410,8 +5409,7 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
} // if ( xHyph.is() )
} // if ( (nStyle & TEXT_DRAW_WORDBREAK_HYPHENATION) == TEXT_DRAW_WORDBREAK_HYPHENATION )
}
- nLineWidth = ( _pLayout != NULL ) ? _pLayout->GetTextWidth( rStr, nPos, nBreakPos-nPos )
- : GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ nLineWidth = _rLayout.GetTextWidth( rStr, nPos, nBreakPos-nPos );
}
else
{
@@ -5425,16 +5423,14 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
{
if( nSpacePos > nPos )
nSpacePos--;
- nW = ( _pLayout != NULL ) ? _pLayout->GetTextWidth( rStr, nPos, nSpacePos-nPos )
- : GetTextWidth( rStr, nPos, nSpacePos-nPos );
+ nW = _rLayout.GetTextWidth( rStr, nPos, nSpacePos-nPos );
}
} while( nW > nWidth );
if( nSpacePos != STRING_NOTFOUND )
{
nBreakPos = nSpacePos;
- nLineWidth = ( _pLayout != NULL ) ? _pLayout->GetTextWidth( rStr, nPos, nBreakPos-nPos )
- : GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ nLineWidth = _rLayout.GetTextWidth( rStr, nPos, nBreakPos-nPos );
if( nBreakPos < rStr.Len()-1 )
nBreakPos++;
}
@@ -6776,10 +6772,10 @@ xub_StrLen OutputDevice::GetTextBreak( const String& rStr, long nTextWidth,
// -----------------------------------------------------------------------
-void OutputDevice::ImplDrawText( const Rectangle& rRect,
+void OutputDevice::ImplDrawText( OutputDevice& rTargetDevice, const Rectangle& rRect,
const String& rOrigStr, USHORT nStyle,
MetricVector* pVector, String* pDisplayText,
- ::vcl::ITextLayout* _pLayout )
+ ::vcl::ITextLayout& _rLayout )
{
Color aOldTextColor;
Color aOldTextFillColor;
@@ -6789,29 +6785,29 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
BOOL bHighContrastBlack = FALSE;
BOOL bHighContrastWhite = FALSE;
Color aCol;
- if( IsBackground() )
- aCol = GetBackground().GetColor();
+ if( rTargetDevice.IsBackground() )
+ aCol = rTargetDevice.GetBackground().GetColor();
else
// best guess is the face color here
// but it may be totally wrong. the background color
// was typically already reset
- aCol = GetSettings().GetStyleSettings().GetFaceColor();
+ aCol = rTargetDevice.GetSettings().GetStyleSettings().GetFaceColor();
bHighContrastBlack = aCol.IsDark();
- bHighContrastWhite = aCol.IsBright() && GetSettings().GetStyleSettings().GetHighContrastMode();
+ bHighContrastWhite = aCol.IsBright() && rTargetDevice.GetSettings().GetStyleSettings().GetHighContrastMode();
- aOldTextColor = GetTextColor();
- if ( IsTextFillColor() )
+ aOldTextColor = rTargetDevice.GetTextColor();
+ if ( rTargetDevice.IsTextFillColor() )
{
bRestoreFillColor = TRUE;
- aOldTextFillColor = GetTextFillColor();
+ aOldTextFillColor = rTargetDevice.GetTextFillColor();
}
else
bRestoreFillColor = FALSE;
if( bHighContrastBlack )
- SetTextColor( COL_GREEN );
+ rTargetDevice.SetTextColor( COL_GREEN );
else if( bHighContrastWhite )
- SetTextColor( COL_LIGHTGREEN );
+ rTargetDevice.SetTextColor( COL_LIGHTGREEN );
else
{
// draw disabled text always without shadow
@@ -6822,7 +6818,7 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
aRect.Move( 1, 1 );
DrawText( aRect, rOrigStr, nStyle & ~TEXT_DRAW_DISABLE );
*/
- SetTextColor( GetSettings().GetStyleSettings().GetShadowColor() );
+ rTargetDevice.SetTextColor( rTargetDevice.GetSettings().GetStyleSettings().GetShadowColor() );
}
}
@@ -6834,14 +6830,16 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
Point aPos = rRect.TopLeft();
- long nTextHeight = GetTextHeight();
- TextAlign eAlign = GetTextAlign();
+ long nTextHeight = rTargetDevice.GetTextHeight();
+ TextAlign eAlign = rTargetDevice.GetTextAlign();
xub_StrLen nMnemonicPos = STRING_NOTFOUND;
String aStr = rOrigStr;
if ( nStyle & TEXT_DRAW_MNEMONIC )
aStr = GetNonMnemonicString( aStr, nMnemonicPos );
+ const bool bDrawMnemonics = !(rTargetDevice.GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) && !pVector;
+
// Mehrzeiligen Text behandeln wir anders
if ( nStyle & TEXT_DRAW_MULTILINE )
{
@@ -6856,7 +6854,7 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
if ( nTextHeight )
{
- nMaxTextWidth = ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle, _pLayout );
+ nMaxTextWidth = ImplGetTextLines( rTargetDevice, aMultiLineInfo, nWidth, aStr, nStyle, _rLayout );
nLines = (xub_StrLen)(nHeight/nTextHeight);
nFormatLines = aMultiLineInfo.Count();
if ( !nLines )
@@ -6878,7 +6876,7 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
if ( aLastLine.GetChar( i ) == _LF )
aLastLine.SetChar( i, ' ' );
}
- aLastLine = GetEllipsisString( aLastLine, nWidth, nStyle );
+ aLastLine = rTargetDevice.GetEllipsisString( aLastLine, nWidth, nStyle );
nStyle &= ~(TEXT_DRAW_VCENTER | TEXT_DRAW_BOTTOM);
nStyle |= TEXT_DRAW_TOP;
}
@@ -6896,8 +6894,8 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
// Clipping setzen
if ( nStyle & TEXT_DRAW_CLIP )
{
- Push( PUSH_CLIPREGION );
- IntersectClipRegion( rRect );
+ rTargetDevice.Push( PUSH_CLIPREGION );
+ rTargetDevice.IntersectClipRegion( rRect );
}
// Vertikales Alignment
@@ -6910,7 +6908,7 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
if ( eAlign == ALIGN_BOTTOM )
aPos.Y() += nTextHeight;
else if ( eAlign == ALIGN_BASELINE )
- aPos.Y() += GetFontMetric().GetAscent();
+ aPos.Y() += rTargetDevice.GetFontMetric().GetAscent();
// Alle Zeilen ausgeben, bis auf die letzte
for ( i = 0; i < nFormatLines; i++ )
@@ -6922,11 +6920,8 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
aPos.X() += (nWidth-pLineInfo->GetWidth())/2;
xub_StrLen nIndex = pLineInfo->GetIndex();
xub_StrLen nLineLen = pLineInfo->GetLen();
- if ( _pLayout )
- _pLayout->DrawText( aPos, aStr, nIndex, nLineLen, pVector, pDisplayText );
- else
- DrawText( aPos, aStr, nIndex, nLineLen, pVector, pDisplayText );
- if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) && !pVector )
+ _rLayout.DrawText( aPos, aStr, nIndex, nLineLen, pVector, pDisplayText );
+ if ( bDrawMnemonics )
{
if ( (nMnemonicPos >= nIndex) && (nMnemonicPos < nIndex+nLineLen) )
{
@@ -6935,16 +6930,16 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
long nMnemonicWidth;
sal_Int32* pCaretXArray = (sal_Int32*) alloca( 2 * sizeof(sal_Int32) * nLineLen );
- /*BOOL bRet =*/ GetCaretPositions( aStr, pCaretXArray,
- nIndex, nLineLen);
+ /*BOOL bRet =*/ _rLayout.GetCaretPositions( aStr, pCaretXArray,
+ nIndex, nLineLen );
long lc_x1 = pCaretXArray[2*(nMnemonicPos - nIndex)];
long lc_x2 = pCaretXArray[2*(nMnemonicPos - nIndex)+1];
- nMnemonicWidth = ::abs((int)(lc_x1 - lc_x2));
+ nMnemonicWidth = rTargetDevice.ImplLogicWidthToDevicePixel( ::abs((int)(lc_x1 - lc_x2)) );
- Point aTempPos = LogicToPixel( aPos );
- nMnemonicX = mnOutOffX + aTempPos.X() + ImplLogicWidthToDevicePixel( Min( lc_x1, lc_x2 ) );
- nMnemonicY = mnOutOffY + aTempPos.Y() + ImplLogicWidthToDevicePixel( GetFontMetric().GetAscent() );
- ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, nMnemonicWidth );
+ Point aTempPos = rTargetDevice.LogicToPixel( aPos );
+ nMnemonicX = rTargetDevice.GetOutOffXPixel() + aTempPos.X() + rTargetDevice.ImplLogicWidthToDevicePixel( Min( lc_x1, lc_x2 ) );
+ nMnemonicY = rTargetDevice.GetOutOffYPixel() + aTempPos.Y() + rTargetDevice.ImplLogicWidthToDevicePixel( rTargetDevice.GetFontMetric().GetAscent() );
+ rTargetDevice.ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, nMnemonicWidth );
}
}
aPos.Y() += nTextHeight;
@@ -6955,31 +6950,26 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
// Gibt es noch eine letzte Zeile, dann diese linksbuendig ausgeben,
// da die Zeile gekuerzt wurde
if ( aLastLine.Len() )
- if ( _pLayout )
- _pLayout->DrawText( aPos, aLastLine, 0, STRING_LEN, pVector, pDisplayText );
- else
- DrawText( aPos, aLastLine, 0, STRING_LEN, pVector, pDisplayText );
+ _rLayout.DrawText( aPos, aLastLine, 0, STRING_LEN, pVector, pDisplayText );
// Clipping zuruecksetzen
if ( nStyle & TEXT_DRAW_CLIP )
- Pop();
+ rTargetDevice.Pop();
}
}
else
{
- long nTextWidth = _pLayout
- ? _pLayout->GetTextWidth( aStr, 0, STRING_LEN )
- : GetTextWidth( aStr );
+ long nTextWidth = _rLayout.GetTextWidth( aStr, 0, STRING_LEN );
// Evt. Text kuerzen
if ( nTextWidth > nWidth )
{
if ( nStyle & TEXT_DRAW_ELLIPSIS )
{
- aStr = GetEllipsisString( aStr, nWidth, nStyle );
+ aStr = rTargetDevice.GetEllipsisString( aStr, nWidth, nStyle );
nStyle &= ~(TEXT_DRAW_CENTER | TEXT_DRAW_RIGHT);
nStyle |= TEXT_DRAW_LEFT;
- nTextWidth = GetTextWidth( aStr );
+ nTextWidth = _rLayout.GetTextWidth( aStr, 0, aStr.Len() );
}
}
else
@@ -6998,7 +6988,7 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
if ( eAlign == ALIGN_BOTTOM )
aPos.Y() += nTextHeight;
else if ( eAlign == ALIGN_BASELINE )
- aPos.Y() += GetFontMetric().GetAscent();
+ aPos.Y() += rTargetDevice.GetFontMetric().GetAscent();
if ( nStyle & TEXT_DRAW_BOTTOM )
aPos.Y() += nHeight-nTextHeight;
@@ -7011,50 +7001,44 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
if ( nMnemonicPos != STRING_NOTFOUND )
{
sal_Int32* pCaretXArray = (sal_Int32*) alloca( 2 * sizeof(sal_Int32) * aStr.Len() );
- /*BOOL bRet =*/ GetCaretPositions( aStr, pCaretXArray, 0, aStr.Len() );
+ /*BOOL bRet =*/ _rLayout.GetCaretPositions( aStr, pCaretXArray, 0, aStr.Len() );
long lc_x1 = pCaretXArray[2*(nMnemonicPos)];
long lc_x2 = pCaretXArray[2*(nMnemonicPos)+1];
- nMnemonicWidth = ::abs((int)(lc_x1 - lc_x2));
+ nMnemonicWidth = rTargetDevice.ImplLogicWidthToDevicePixel( ::abs((int)(lc_x1 - lc_x2)) );
- Point aTempPos = LogicToPixel( aPos );
- nMnemonicX = mnOutOffX + aTempPos.X() + ImplLogicWidthToDevicePixel( Min(lc_x1, lc_x2) );
- nMnemonicY = mnOutOffY + aTempPos.Y() + ImplLogicWidthToDevicePixel( GetFontMetric().GetAscent() );
+ Point aTempPos = rTargetDevice.LogicToPixel( aPos );
+ nMnemonicX = rTargetDevice.GetOutOffXPixel() + aTempPos.X() + rTargetDevice.ImplLogicWidthToDevicePixel( Min(lc_x1, lc_x2) );
+ nMnemonicY = rTargetDevice.GetOutOffYPixel() + aTempPos.Y() + rTargetDevice.ImplLogicWidthToDevicePixel( rTargetDevice.GetFontMetric().GetAscent() );
}
if ( nStyle & TEXT_DRAW_CLIP )
{
- Push( PUSH_CLIPREGION );
- IntersectClipRegion( rRect );
- if ( _pLayout )
- _pLayout->DrawText( aPos, aStr, 0, STRING_LEN, pVector, pDisplayText );
- else
- DrawText( aPos, aStr, 0, STRING_LEN, pVector, pDisplayText );
- if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) && !pVector )
+ rTargetDevice.Push( PUSH_CLIPREGION );
+ rTargetDevice.IntersectClipRegion( rRect );
+ _rLayout.DrawText( aPos, aStr, 0, STRING_LEN, pVector, pDisplayText );
+ if ( bDrawMnemonics )
{
if ( nMnemonicPos != STRING_NOTFOUND )
- ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, nMnemonicWidth );
+ rTargetDevice.ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, nMnemonicWidth );
}
- Pop();
+ rTargetDevice.Pop();
}
else
{
- if ( _pLayout )
- _pLayout->DrawText( aPos, aStr, 0, STRING_LEN, pVector, pDisplayText );
- else
- DrawText( aPos, aStr, 0, STRING_LEN, pVector, pDisplayText );
- if ( !(GetSettings().GetStyleSettings().GetOptions() & STYLE_OPTION_NOMNEMONICS) && !pVector )
+ _rLayout.DrawText( aPos, aStr, 0, STRING_LEN, pVector, pDisplayText );
+ if ( bDrawMnemonics )
{
if ( nMnemonicPos != STRING_NOTFOUND )
- ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, nMnemonicWidth );
+ rTargetDevice.ImplDrawMnemonicLine( nMnemonicX, nMnemonicY, nMnemonicWidth );
}
}
}
if ( nStyle & TEXT_DRAW_DISABLE && !pVector )
{
- SetTextColor( aOldTextColor );
+ rTargetDevice.SetTextColor( aOldTextColor );
if ( bRestoreFillColor )
- SetTextFillColor( aOldTextFillColor );
+ rTargetDevice.SetTextFillColor( aOldTextFillColor );
}
}
@@ -7087,7 +7071,8 @@ void OutputDevice::AddTextRectActions( const Rectangle& rRect,
// #i47157# Factored out to ImplDrawTextRect(), to be shared
// between us and DrawText()
- ImplDrawText( rRect, rOrigStr, nStyle, NULL, NULL, NULL );
+ DefaultTextLayout aLayout( *this );
+ ImplDrawText( *this, rRect, rOrigStr, nStyle, NULL, NULL, aLayout );
// and restore again
EnableOutput( bOutputEnabled );
@@ -7130,7 +7115,8 @@ void OutputDevice::DrawText( const Rectangle& rRect, const String& rOrigStr, USH
// #i47157# Factored out to ImplDrawText(), to be used also
// from AddTextRectActions()
- ImplDrawText( rRect, rOrigStr, nStyle, pVector, pDisplayText, _pTextLayout );
+ DefaultTextLayout aDefaultLayout( *this );
+ ImplDrawText( *this, rRect, rOrigStr, nStyle, pVector, pDisplayText, _pTextLayout ? *_pTextLayout : aDefaultLayout );
// and enable again
mpMetaFile = pMtf;
@@ -7167,7 +7153,8 @@ Rectangle OutputDevice::GetTextRect( const Rectangle& rRect,
xub_StrLen i;
nMaxWidth = 0;
- ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle, _pTextLayout );
+ DefaultTextLayout aDefaultLayout( *const_cast< OutputDevice* >( this ) );
+ ImplGetTextLines( *const_cast< OutputDevice* >( this ), aMultiLineInfo, nWidth, aStr, nStyle, _pTextLayout ? *_pTextLayout : aDefaultLayout );
nFormatLines = aMultiLineInfo.Count();
if ( !nTextHeight )
nTextHeight = 1;
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index 3eda6b5c929c..0ce6df6bc85f 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -41,7 +41,6 @@
#include <tools/debug.hxx>
#include <tools/zcodec.hxx>
#include <tools/stream.hxx>
-#include <tools/urlobj.hxx> //for relative url
#include <i18npool/mslangid.hxx>
#include <vcl/virdev.hxx>
#include <vcl/bmpacc.hxx>
@@ -51,6 +50,7 @@
#include <vcl/sallayout.hxx>
#include <vcl/metric.hxx>
#include <vcl/fontsubset.hxx>
+#include <vcl/textlayout.hxx>
#include <svsys.h>
#include <vcl/salgdi.hxx>
#include <vcl/svapp.hxx>
@@ -7307,7 +7307,8 @@ void PDFWriterImpl::drawText( const Rectangle& rRect, const String& rOrigStr, US
if ( nTextHeight )
{
- nMaxTextWidth = m_pReferenceDevice->ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle, NULL );
+ ::vcl::DefaultTextLayout aLayout( *m_pReferenceDevice );
+ nMaxTextWidth = OutputDevice::ImplGetTextLines( *m_pReferenceDevice, aMultiLineInfo, nWidth, aStr, nStyle, aLayout );
nLines = (xub_StrLen)(nHeight/nTextHeight);
nFormatLines = aMultiLineInfo.Count();
if ( !nLines )
diff --git a/vcl/source/gdi/textlayout.cxx b/vcl/source/gdi/textlayout.cxx
index ddb8979a1a73..dd00414837d1 100755
--- a/vcl/source/gdi/textlayout.cxx
+++ b/vcl/source/gdi/textlayout.cxx
@@ -37,6 +37,34 @@ namespace vcl
//........................................................................
//====================================================================
+ //= DefaultTextLayout
+ //====================================================================
+ //--------------------------------------------------------------------
+ DefaultTextLayout::~DefaultTextLayout()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ long DefaultTextLayout::GetTextWidth( const XubString& _rText, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const
+ {
+ return m_rTargetDevice.GetTextWidth( _rText, _nStartIndex, _nLength );
+ }
+
+ //--------------------------------------------------------------------
+ void DefaultTextLayout::DrawText( const Point& _rStartPoint, const XubString& _rText, xub_StrLen _nStartIndex,
+ xub_StrLen _nLength, MetricVector* _pVector, String* _pDisplayText )
+ {
+ m_rTargetDevice.DrawText( _rStartPoint, _rText, _nStartIndex, _nLength, _pVector, _pDisplayText );
+ }
+
+ //--------------------------------------------------------------------
+ bool DefaultTextLayout::GetCaretPositions( const XubString& _rText, sal_Int32* _pCaretXArray,
+ xub_StrLen _nStartIndex, xub_StrLen _nLength ) const
+ {
+ return m_rTargetDevice.GetCaretPositions( _rText, _pCaretXArray, _nStartIndex, _nLength );
+ }
+
+ //====================================================================
//= ReferenceDeviceTextLayout
//====================================================================
class ReferenceDeviceTextLayout : public ITextLayout
@@ -48,6 +76,7 @@ namespace vcl
// ITextLayout
virtual long GetTextWidth( const XubString& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const;
virtual void DrawText( const Point& _rStartPoint, const XubString& _rText, xub_StrLen _nStartIndex, xub_StrLen _nLength, MetricVector* _pVector, String* _pDisplayText );
+ virtual bool GetCaretPositions( const XubString& _rText, sal_Int32* _pCaretXArray, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const;
public:
// equivalents to the respective OutputDevice methods, which take the reference device into account
@@ -84,11 +113,17 @@ namespace vcl
,m_aUnzoomedPointFont( _rControl.GetUnzoomedControlPointFont() )
,m_aZoom( _rControl.GetZoom() )
{
+ // normally, controls simulate "zoom" by "zooming" the font. This is responsible for (part of) the discrepancies
+ // between text in Writer and text in controls in Writer, though both have the same font.
+ // So, if we have a zoom set at the control, then we do not scale the font, but instead modify the map mode
+ // to accomodate for the zoom.
if ( IsZoom() )
{
m_rTargetDevice.Push( PUSH_MAPMODE | PUSH_FONT );
MapMode aDrawMapMode( m_rTargetDevice.GetMapMode() );
+ OSL_ENSURE( aDrawMapMode.GetOrigin() == Point(), "ReferenceDeviceTextLayout::ReferenceDeviceTextLayout: uhm, the code below won't work here ..." );
+
aDrawMapMode.SetScaleX( m_aZoom ); // TODO: shouldn't this be "current_scale * zoom"?
aDrawMapMode.SetScaleY( m_aZoom );
m_rTargetDevice.SetMapMode( aDrawMapMode );
@@ -101,6 +136,22 @@ namespace vcl
aDrawFont.SetSize( m_rTargetDevice.LogicToLogic( aDrawFont.GetSize(), MAP_POINT, eTargetMapUnit ) );
_rTargetDevice.SetFont( aDrawFont );
}
+
+ // transfer font to the reference device
+ m_rReferenceDevice.Push( PUSH_FONT );
+ Font aRefFont( m_aUnzoomedPointFont );
+ aRefFont.SetSize( OutputDevice::LogicToLogic(
+ aRefFont.GetSize(), MAP_POINT, m_rReferenceDevice.GetMapMode().GetMapUnit() ) );
+ m_rReferenceDevice.SetFont( aRefFont );
+
+ }
+
+ //--------------------------------------------------------------------
+ ReferenceDeviceTextLayout::~ReferenceDeviceTextLayout()
+ {
+ if ( IsZoom() )
+ m_rTargetDevice.Pop();
+ m_rReferenceDevice.Pop();
}
//--------------------------------------------------------------------
@@ -146,13 +197,6 @@ namespace vcl
}
//--------------------------------------------------------------------
- ReferenceDeviceTextLayout::~ReferenceDeviceTextLayout()
- {
- if ( IsZoom() )
- m_rTargetDevice.Pop();
- }
-
- //--------------------------------------------------------------------
bool ReferenceDeviceTextLayout::IsZoom() const
{
return m_aZoom.GetNumerator() != m_aZoom.GetDenominator();
@@ -164,16 +208,8 @@ namespace vcl
if ( !lcl_normalizeLength( _rText, _nStartIndex, _nLength ) )
return 0;
- // transfer font to the reference device
- m_rReferenceDevice.Push( PUSH_FONT );
- Font aRefFont( m_aUnzoomedPointFont );
- aRefFont.SetSize( OutputDevice::LogicToLogic(
- aRefFont.GetSize(), MAP_POINT, m_rReferenceDevice.GetMapMode().GetMapUnit() ) );
- m_rReferenceDevice.SetFont( aRefFont );
-
// retrieve the character widths from the reference device
long nTextWidth = m_rReferenceDevice.GetTextArray( _rText, _pDXAry, _nStartIndex, _nLength );
- m_rReferenceDevice.Pop();
// adjust the widths, which are in ref-device units, to the target device
DeviceUnitMapping aMapping( m_rTargetDevice, m_rReferenceDevice );
@@ -212,6 +248,41 @@ namespace vcl
}
//--------------------------------------------------------------------
+ bool ReferenceDeviceTextLayout::GetCaretPositions( const XubString& _rText, sal_Int32* _pCaretXArray,
+ xub_StrLen _nStartIndex, xub_StrLen _nLength ) const
+ {
+ if ( !lcl_normalizeLength( _rText, _nStartIndex, _nLength ) )
+ return false;
+
+ // retrieve the caret positions from the reference device
+ if ( !m_rReferenceDevice.GetCaretPositions( _rText, _pCaretXArray, _nStartIndex, _nLength ) )
+ return false;
+
+ // adjust the positions, which are in ref-device units, to the target device
+ DeviceUnitMapping aMapping( m_rTargetDevice, m_rReferenceDevice );
+ for ( size_t i=0; i<2*size_t(_nLength); ++i )
+ _pCaretXArray[i] = aMapping.mapToTarget( _pCaretXArray[i] );
+
+ return true;
+ }
+
+ //--------------------------------------------------------------------
+ namespace
+ {
+ long zoomBy( long _value, const Fraction& _zoom )
+ {
+ double n = (double)_value;
+ n *= (double)_zoom.GetNumerator();
+ n /= (double)_zoom.GetDenominator();
+ return (long)::rtl::math::round( n );
+ }
+ long unzoomBy( long _value, const Fraction& _zoom )
+ {
+ return zoomBy( _value, Fraction( _zoom.GetDenominator(), _zoom.GetNumerator() ) );
+ }
+ }
+
+ //--------------------------------------------------------------------
Rectangle ReferenceDeviceTextLayout::DrawText( const Rectangle& _rRect, const XubString& _rText, USHORT _nStyle, MetricVector* _pVector, String* _pDisplayText)
{
Rectangle aRect( _rRect );
@@ -219,10 +290,10 @@ namespace vcl
{
// if there's a zoom factor involved, then we tampered with the target device's map mode in the ctor.
// Need to adjust the rectangle to this
- aRect.Left() = long( aRect.Left() / (double)m_aZoom );
- aRect.Right() = long( aRect.Right() / (double)m_aZoom );
- aRect.Top() = long( aRect.Top() / (double)m_aZoom );
- aRect.Bottom() = long( aRect.Bottom() / (double)m_aZoom );
+ aRect.Left() = unzoomBy( aRect.Left(), m_aZoom );
+ aRect.Right() = unzoomBy( aRect.Right(), m_aZoom );
+ aRect.Top() = unzoomBy( aRect.Top(), m_aZoom );
+ aRect.Bottom() = unzoomBy( aRect.Bottom(), m_aZoom );
}
#ifdef FS_DEBUG
@@ -240,10 +311,10 @@ namespace vcl
{
// similar to above, transform the to-be-returned rectanle to coordinates which are meaningful
// with the original map mode of the target device
- aTextRect.Left() = long( aTextRect.Left() * (double)m_aZoom );
- aTextRect.Right() = long( aTextRect.Right() * (double)m_aZoom );
- aTextRect.Top() = long( aTextRect.Top() * (double)m_aZoom );
- aTextRect.Bottom() = long( aTextRect.Bottom() * (double)m_aZoom );
+ aTextRect.Left() = zoomBy( aTextRect.Left(), m_aZoom );
+ aTextRect.Right() = zoomBy( aTextRect.Right(), m_aZoom );
+ aTextRect.Top() = zoomBy( aTextRect.Top(), m_aZoom );
+ aTextRect.Bottom() = zoomBy( aTextRect.Bottom(), m_aZoom );
}
return aTextRect;