diff options
author | Frank Schönheit <fs@openoffice.org> | 2009-09-18 10:39:28 +0000 |
---|---|---|
committer | Frank Schönheit <fs@openoffice.org> | 2009-09-18 10:39:28 +0000 |
commit | f20d782ce054876754188345ff013ede4a216f72 (patch) | |
tree | 743f149082351a9b0d3bfe2599f0d8aff2754911 /vcl/source | |
parent | 79cad7d02a0eb7cc6e662ad424204f4599a7981a (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.cxx | 143 | ||||
-rw-r--r-- | vcl/source/gdi/pdfwriter_impl.cxx | 5 | ||||
-rwxr-xr-x | vcl/source/gdi/textlayout.cxx | 117 |
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; |