summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vcl/inc/vcl/ctrl.hxx13
-rw-r--r--vcl/inc/vcl/outdev.hxx20
-rwxr-xr-xvcl/inc/vcl/textlayout.hxx92
-rw-r--r--vcl/source/control/button.cxx6
-rw-r--r--vcl/source/control/ctrl.cxx78
-rw-r--r--vcl/source/control/fixed.cxx4
-rw-r--r--vcl/source/gdi/makefile.mk3
-rw-r--r--vcl/source/gdi/outdev3.cxx74
-rw-r--r--vcl/source/gdi/pdfwriter_impl.cxx2
-rwxr-xr-xvcl/source/gdi/textlayout.cxx269
10 files changed, 460 insertions, 101 deletions
diff --git a/vcl/inc/vcl/ctrl.hxx b/vcl/inc/vcl/ctrl.hxx
index 2508a58c005e..535f75549991 100644
--- a/vcl/inc/vcl/ctrl.hxx
+++ b/vcl/inc/vcl/ctrl.hxx
@@ -97,8 +97,11 @@ protected:
If no reference device is set, the draw request will simply be forwarded to OutputDevice::DrawText. Otherwise,
the text will be rendered according to the metrics at the reference device.
+
+ Note that the given rectangle might be modified, it will contain the result of a GetTextRect call (either
+ directly at the target device, or taking the reference device into account) when returning.
*/
- void DrawControlText( OutputDevice& _rTargetDevice, const Rectangle& _rRect,
+ void DrawControlText( OutputDevice& _rTargetDevice, Rectangle& _io_rRect,
const XubString& _rStr, USHORT _nStyle,
MetricVector* _pVector, String* _pDisplayText ) const;
@@ -188,6 +191,14 @@ public:
*/
void SetReferenceDevice( OutputDevice* _referenceDevice );
OutputDevice* GetReferenceDevice() const;
+
+ Font GetUnzoomedControlPointFont() const
+ {
+ Font aFont( GetCanonicalFont( GetSettings().GetStyleSettings() ) );
+ if ( IsControlFont() )
+ aFont.Merge( GetControlFont() );
+ return aFont;
+ }
};
#endif // _SV_CTRL_HXX
diff --git a/vcl/inc/vcl/outdev.hxx b/vcl/inc/vcl/outdev.hxx
index f4e42846dd5e..d056a26c0127 100644
--- a/vcl/inc/vcl/outdev.hxx
+++ b/vcl/inc/vcl/outdev.hxx
@@ -103,8 +103,12 @@ namespace awt {
typedef std::vector< Rectangle > MetricVector;
-namespace vcl { class PDFWriterImpl; }
-namespace vcl { class ExtOutDevData; }
+namespace vcl
+{
+ class PDFWriterImpl;
+ class ExtOutDevData;
+ class ITextLayout;
+}
#define OUTDEV_BUFFER_SIZE 128
@@ -433,7 +437,7 @@ public:
SAL_DLLPRIVATE long ImplGetTextWidth( const SalLayout& ) const;
SAL_DLLPRIVATE void ImplDrawText( const Rectangle& rRect,
const String& rOrigStr, USHORT nStyle,
- MetricVector* pVector, String* pDisplayText );
+ MetricVector* pVector, String* pDisplayText, ::vcl::ITextLayout* _pLayout );
SAL_DLLPRIVATE void ImplDrawTextBackground( const SalLayout& );
SAL_DLLPRIVATE void ImplDrawTextLines( SalLayout&, FontStrikeout eStrikeout, FontUnderline eUnderline, FontUnderline eOverline, BOOL bWordLine, BOOL bUnderlineAbove );
SAL_DLLPRIVATE bool ImplDrawRotateText( SalLayout& );
@@ -456,7 +460,7 @@ public:
SAL_DLLPRIVATE void ImplDrawMnemonicLine( long nX, long nY, long nWidth );
SAL_DLLPRIVATE void ImplGetEmphasisMark( PolyPolygon& rPolyPoly, BOOL& rPolyLine, Rectangle& rRect1, Rectangle& rRect2, long& rYOff, long& rWidth, FontEmphasisMark eEmphasis, long nHeight, short nOrient );
SAL_DLLPRIVATE void ImplDrawEmphasisMark( long nBaseX, long nX, long nY, const PolyPolygon& rPolyPoly, BOOL bPolyLine, const Rectangle& rRect1, const Rectangle& rRect2 );
- SAL_DLLPRIVATE long ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo, long nWidth, const XubString& rStr, USHORT nStyle ) const;
+ SAL_DLLPRIVATE long ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo, long nWidth, const XubString& rStr, USHORT nStyle, const ::vcl::ITextLayout* _pLayout ) const;
SAL_DLLPRIVATE void ImplInitFontList() const;
SAL_DLLPRIVATE void ImplUpdateFontData( bool bNewFontLists );
SAL_DLLPRIVATE static void ImplUpdateAllFontData( bool bNewFontLists );
@@ -650,9 +654,17 @@ public:
void DrawText( const Rectangle& rRect,
const XubString& rStr, USHORT nStyle = 0,
MetricVector* pVector = NULL, String* pDisplayText = NULL );
+ void DrawText( const Rectangle& rRect,
+ const XubString& rStr, USHORT nStyle,
+ MetricVector* pVector, String* pDisplayText,
+ ::vcl::ITextLayout* _pTextLayout );
Rectangle GetTextRect( const Rectangle& rRect,
const XubString& rStr, USHORT nStyle = TEXT_DRAW_WORDBREAK,
TextRectInfo* pInfo = NULL ) const;
+ Rectangle GetTextRect( const Rectangle& rRect,
+ const XubString& rStr, USHORT nStyle,
+ TextRectInfo* pInfo,
+ const ::vcl::ITextLayout* _pTextLayout ) const;
XubString GetEllipsisString( const XubString& rStr, long nMaxWidth,
USHORT nStyle = TEXT_DRAW_ENDELLIPSIS ) const;
void DrawCtrlText( const Point& rPos, const XubString& rStr,
diff --git a/vcl/inc/vcl/textlayout.hxx b/vcl/inc/vcl/textlayout.hxx
new file mode 100755
index 000000000000..dbb7b2d17d77
--- /dev/null
+++ b/vcl/inc/vcl/textlayout.hxx
@@ -0,0 +1,92 @@
+/*************************************************************************
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2009 by Sun Microsystems, Inc.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* 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.
+*
+* 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).
+*
+* 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.
+************************************************************************/
+
+#ifndef VCL_TEXTLAYOUT_HXX
+#define VCL_TEXTLAYOUT_HXX
+
+#include "vcl/outdev.hxx"
+
+#include <tools/solar.h>
+#include <tools/string.hxx>
+
+#include <memory>
+
+class Control;
+
+//........................................................................
+namespace vcl
+{
+//........................................................................
+
+ //====================================================================
+ //= ITextLayout
+ //====================================================================
+ class SAL_NO_VTABLE ITextLayout
+ {
+ public:
+ virtual long GetTextWidth( const XubString& _rText, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const = 0;
+ virtual void DrawText(
+ const Point& _rStartPoint,
+ const XubString& _rText,
+ xub_StrLen _nStartIndex,
+ xub_StrLen _nLength,
+ MetricVector* _pVector,
+ String* _pDisplayText
+ ) = 0;
+ };
+
+ //====================================================================
+ //= ControlTextRenderer
+ //====================================================================
+ class ReferenceDeviceTextLayout;
+ /** a class which allows rendering text onto a device, but calculating the metrics according to a reference device
+
+ The class provides a number of methods which are equivalent to the same methods of the OutputDevice, except
+ that OutputDevice does not know about reference devices.
+ */
+ class ControlTextRenderer
+ {
+ public:
+ ControlTextRenderer( const Control& _rControl, OutputDevice& _rTargetDevice, OutputDevice& _rReferenceDevice );
+ virtual ~ControlTextRenderer();
+
+ Rectangle DrawText( const Rectangle& _rRect,
+ const XubString& _rText, USHORT _nStyle = 0,
+ MetricVector* _pVector = NULL, String* _pDisplayText = NULL );
+
+ private:
+ ControlTextRenderer(); // never implemented
+ ControlTextRenderer( const ControlTextRenderer& ); // never implemented
+ ControlTextRenderer& operator=( const ControlTextRenderer& ); // never implemented
+
+ private:
+ ::std::auto_ptr< ReferenceDeviceTextLayout > m_pImpl;
+ };
+
+//........................................................................
+} // namespace vcl
+//........................................................................
+
+#endif // VCL_TEXTLAYOUT_HXX
diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx
index 0f9a09cb17e7..6d6c7aae923a 100644
--- a/vcl/source/control/button.cxx
+++ b/vcl/source/control/button.cxx
@@ -406,12 +406,12 @@ void Button::ImplDrawAlignedImage( OutputDevice* pDev, Point& rPos,
}
else if ( bDrawText && !bDrawImage && !bHasSymbol )
{
- aOutRect = pDev->GetTextRect( aOutRect, aText, nTextStyle );
+ DrawControlText( *pDev, aOutRect, aText, nTextStyle, pVector, pDisplayText );
+
+ ImplSetFocusRect( aOutRect );
rSize = aOutRect.GetSize();
rPos = aOutRect.TopLeft();
- ImplSetFocusRect( aOutRect );
- DrawControlText( *pDev, aOutRect, aText, nTextStyle, pVector, pDisplayText );
return;
}
diff --git a/vcl/source/control/ctrl.cxx b/vcl/source/control/ctrl.cxx
index 7ca2ff5ff8e5..cfffbe136204 100644
--- a/vcl/source/control/ctrl.cxx
+++ b/vcl/source/control/ctrl.cxx
@@ -41,6 +41,7 @@
#include <vcl/decoview.hxx>
#include <vcl/controldata.hxx>
#include <vcl/salnativewidgets.hxx>
+#include <vcl/textlayout.hxx>
namespace vcl
@@ -549,82 +550,17 @@ void Control::ImplInitSettings( const BOOL _bFont, const BOOL _bForeground )
// -----------------------------------------------------------------
-void Control::DrawControlText( OutputDevice& _rTargetDevice, const Rectangle& _rRect, const XubString& _rStr,
+void Control::DrawControlText( OutputDevice& _rTargetDevice, Rectangle& _io_rRect, const XubString& _rStr,
USHORT _nStyle, MetricVector* _pVector, String* _pDisplayText ) const
{
+
if ( !mpControlData->mpReferenceDevice )
{
- _rTargetDevice.DrawText( _rRect, _rStr, _nStyle, _pVector, _pDisplayText );
+ _io_rRect = _rTargetDevice.GetTextRect( _io_rRect, _rStr, _nStyle );
+ _rTargetDevice.DrawText( _io_rRect, _rStr, _nStyle, _pVector, _pDisplayText );
return;
}
- // TODO:
- // - respect the style (word break, vert./horz. align, etc.)
- // - respect _pVector and _pDisplayText, i.e. fill metric data if they're given
-
- sal_Int32* pCharWidths = new sal_Int32[ _rStr.Len() ];
- // retrieve unzoomed point font of the target device
- Font aFont( GetCanonicalFont( GetSettings().GetStyleSettings() ) );
- if ( IsControlFont() )
- aFont.Merge( GetControlFont() );
-
- // transfer font to the reference device
- mpControlData->mpReferenceDevice->Push( PUSH_FONT );
- Font aRefFont( aFont );
- aRefFont.SetSize( LogicToLogic(
- aRefFont.GetSize(), MAP_POINT, mpControlData->mpReferenceDevice->GetMapMode().GetMapUnit() ) );
- mpControlData->mpReferenceDevice->SetFont( aRefFont );
-
- // retrieve the character widths from the reference device
- mpControlData->mpReferenceDevice->GetTextArray( _rStr, pCharWidths );
- mpControlData->mpReferenceDevice->Pop();
-
- // adjust the widths, which are in ref-device units, to the target device
- const MapUnit eRefMapUnit( mpControlData->mpReferenceDevice->GetMapMode().GetMapUnit() );
- OSL_ENSURE( eRefMapUnit != MAP_PIXEL, "a reference device with MAP_PIXEL?" );
-
- const MapMode& aTargetMapMode( _rTargetDevice.GetMapMode() );
- const MapUnit eTargetMapUnit( aTargetMapMode.GetMapUnit() );
- const bool bTargetIsPixel = ( eTargetMapUnit == MAP_PIXEL );
- {
- for ( size_t i=0; i<_rStr.Len(); ++i )
- {
- pCharWidths[i] =
- bTargetIsPixel
- ? _rTargetDevice.LogicToPixel( Size( pCharWidths[i], 0 ), eRefMapUnit ).Width()
- : _rTargetDevice.LogicToLogic( Size( pCharWidths[i], 0 ), eRefMapUnit, eTargetMapUnit ).Width();
- }
- }
-
- Point aDrawTextPosition( _rRect.TopLeft() );
- // translate our zoom into a map mode / font / origin at the target device
- if ( IsZoom() )
- {
- _rTargetDevice.Push( PUSH_MAPMODE | PUSH_FONT );
-
- const Fraction& rZoom( GetZoom() );
-
- MapMode aDrawMapMode( aTargetMapMode );
- aDrawMapMode.SetScaleX( rZoom );
- aDrawMapMode.SetScaleY( rZoom );
- _rTargetDevice.SetMapMode( aDrawMapMode );
-
- Font aDrawFont( aFont );
- if ( bTargetIsPixel )
- aDrawFont.SetSize( _rTargetDevice.LogicToPixel( aDrawFont.GetSize(), MAP_POINT ) );
- else
- aDrawFont.SetSize( _rTargetDevice.LogicToLogic( aDrawFont.GetSize(), MAP_POINT, eTargetMapUnit ) );
- _rTargetDevice.SetFont( aDrawFont );
-
- aDrawTextPosition.X() = long(aDrawTextPosition.X() / (double)rZoom);
- aDrawTextPosition.Y() = long(aDrawTextPosition.Y() / (double)rZoom);
- }
-
- // draw the text
- _rTargetDevice.DrawTextArray( aDrawTextPosition, _rStr, pCharWidths );
-
- if ( IsZoom() )
- _rTargetDevice.Pop();
-
- delete[] pCharWidths;
+ ControlTextRenderer aRenderer( *this, _rTargetDevice, *mpControlData->mpReferenceDevice );
+ _io_rRect = aRenderer.DrawText( _io_rRect, _rStr, _nStyle, _pVector, _pDisplayText );
}
diff --git a/vcl/source/control/fixed.cxx b/vcl/source/control/fixed.cxx
index 4b081c57e188..53029c8e3573 100644
--- a/vcl/source/control/fixed.cxx
+++ b/vcl/source/control/fixed.cxx
@@ -265,7 +265,8 @@ void FixedText::ImplDraw( OutputDevice* pDev, ULONG nDrawFlags,
if( bFillLayout )
mpControlData->mpLayoutData->m_aDisplayText = String();
- DrawControlText( *pDev, Rectangle( aPos, rSize ), aText, nTextStyle,
+ Rectangle aRect( Rectangle( aPos, rSize ) );
+ DrawControlText( *pDev, aRect, aText, nTextStyle,
bFillLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : NULL,
bFillLayout ? &mpControlData->mpLayoutData->m_aDisplayText : NULL
);
@@ -548,7 +549,6 @@ void FixedLine::ImplDraw( bool bLayout )
if ( rStyleSettings.GetOptions() & STYLE_OPTION_MONO )
nStyle |= TEXT_DRAW_MONO;
- aRect = GetTextRect( aRect, aText, nStyle );
DrawControlText( *this, aRect, aText, nStyle, pVector, pDisplayText );
if( !pVector )
diff --git a/vcl/source/gdi/makefile.mk b/vcl/source/gdi/makefile.mk
index a09ae92dcb5e..b708346e45e4 100644
--- a/vcl/source/gdi/makefile.mk
+++ b/vcl/source/gdi/makefile.mk
@@ -115,7 +115,8 @@ SLOFILES= $(SLO)$/salmisc.obj \
$(SLO)$/bmpconv.obj \
$(SLO)$/pngread.obj \
$(SLO)$/pngwrite.obj \
- $(SLO)$/graphictools.obj
+ $(SLO)$/graphictools.obj \
+ $(SLO)$/textlayout.obj
EXCEPTIONSFILES= $(SLO)$/salmisc.obj \
$(SLO)$/outdev.obj \
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
index 0a6b778681e1..87a6659de51e 100644
--- a/vcl/source/gdi/outdev3.cxx
+++ b/vcl/source/gdi/outdev3.cxx
@@ -61,6 +61,7 @@
#include <vcl/edit.hxx>
#include <vcl/fontcfg.hxx>
#include <vcl/sysdata.hxx>
+#include <vcl/textlayout.hxx>
#ifndef _OSL_FILE_H
#include <osl/file.h>
#endif
@@ -5257,7 +5258,7 @@ void OutputDevice::ImplDrawText( SalLayout& rSalLayout )
long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
long nWidth, const XubString& rStr,
- USHORT nStyle ) const
+ USHORT nStyle, const ::vcl::ITextLayout* _pLayout ) const
{
DBG_ASSERTWARNING( nWidth >= 0, "ImplGetTextLines: nWidth <= 0!" );
@@ -5295,7 +5296,8 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
while ( ( nBreakPos < nLen ) && ( rStr.GetChar( nBreakPos ) != _CR ) && ( rStr.GetChar( nBreakPos ) != _LF ) )
nBreakPos++;
- long nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ long nLineWidth = ( _pLayout != NULL ) ? _pLayout->GetTextWidth( rStr, nPos, nBreakPos-nPos )
+ : GetTextWidth( rStr, nPos, nBreakPos-nPos );
if ( ( nLineWidth > nWidth ) && ( nStyle & TEXT_DRAW_WORDBREAK ) )
{
if ( !xBI.is() )
@@ -5408,7 +5410,8 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
} // if ( xHyph.is() )
} // if ( (nStyle & TEXT_DRAW_WORDBREAK_HYPHENATION) == TEXT_DRAW_WORDBREAK_HYPHENATION )
}
- nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ nLineWidth = ( _pLayout != NULL ) ? _pLayout->GetTextWidth( rStr, nPos, nBreakPos-nPos )
+ : GetTextWidth( rStr, nPos, nBreakPos-nPos );
}
else
{
@@ -5422,14 +5425,16 @@ long OutputDevice::ImplGetTextLines( ImplMultiTextLineInfo& rLineInfo,
{
if( nSpacePos > nPos )
nSpacePos--;
- nW = GetTextWidth( rStr, nPos, nSpacePos-nPos );
+ nW = ( _pLayout != NULL ) ? _pLayout->GetTextWidth( rStr, nPos, nSpacePos-nPos )
+ : GetTextWidth( rStr, nPos, nSpacePos-nPos );
}
} while( nW > nWidth );
if( nSpacePos != STRING_NOTFOUND )
{
nBreakPos = nSpacePos;
- nLineWidth = GetTextWidth( rStr, nPos, nBreakPos-nPos );
+ nLineWidth = ( _pLayout != NULL ) ? _pLayout->GetTextWidth( rStr, nPos, nBreakPos-nPos )
+ : GetTextWidth( rStr, nPos, nBreakPos-nPos );
if( nBreakPos < rStr.Len()-1 )
nBreakPos++;
}
@@ -6773,7 +6778,8 @@ xub_StrLen OutputDevice::GetTextBreak( const String& rStr, long nTextWidth,
void OutputDevice::ImplDrawText( const Rectangle& rRect,
const String& rOrigStr, USHORT nStyle,
- MetricVector* pVector, String* pDisplayText )
+ MetricVector* pVector, String* pDisplayText,
+ ::vcl::ITextLayout* _pLayout )
{
Color aOldTextColor;
Color aOldTextFillColor;
@@ -6850,7 +6856,7 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
if ( nTextHeight )
{
- nMaxTextWidth = ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle );
+ nMaxTextWidth = ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle, _pLayout );
nLines = (xub_StrLen)(nHeight/nTextHeight);
nFormatLines = aMultiLineInfo.Count();
if ( !nLines )
@@ -6916,7 +6922,10 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
aPos.X() += (nWidth-pLineInfo->GetWidth())/2;
xub_StrLen nIndex = pLineInfo->GetIndex();
xub_StrLen nLineLen = pLineInfo->GetLen();
- DrawText( aPos, aStr, nIndex, nLineLen, pVector, pDisplayText );
+ 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 )
{
if ( (nMnemonicPos >= nIndex) && (nMnemonicPos < nIndex+nLineLen) )
@@ -6946,7 +6955,10 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
// Gibt es noch eine letzte Zeile, dann diese linksbuendig ausgeben,
// da die Zeile gekuerzt wurde
if ( aLastLine.Len() )
- DrawText( aPos, aLastLine, 0, STRING_LEN, pVector, pDisplayText );
+ if ( _pLayout )
+ _pLayout->DrawText( aPos, aLastLine, 0, STRING_LEN, pVector, pDisplayText );
+ else
+ DrawText( aPos, aLastLine, 0, STRING_LEN, pVector, pDisplayText );
// Clipping zuruecksetzen
if ( nStyle & TEXT_DRAW_CLIP )
@@ -6955,7 +6967,9 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
}
else
{
- long nTextWidth = GetTextWidth( aStr );
+ long nTextWidth = _pLayout
+ ? _pLayout->GetTextWidth( aStr, 0, STRING_LEN )
+ : GetTextWidth( aStr );
// Evt. Text kuerzen
if ( nTextWidth > nWidth )
@@ -7011,7 +7025,10 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
{
Push( PUSH_CLIPREGION );
IntersectClipRegion( rRect );
- DrawText( aPos, aStr, 0, STRING_LEN, pVector, pDisplayText );
+ 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 )
{
if ( nMnemonicPos != STRING_NOTFOUND )
@@ -7021,7 +7038,10 @@ void OutputDevice::ImplDrawText( const Rectangle& rRect,
}
else
{
- DrawText( aPos, aStr, 0, STRING_LEN, pVector, pDisplayText );
+ 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 )
{
if ( nMnemonicPos != STRING_NOTFOUND )
@@ -7067,7 +7087,7 @@ void OutputDevice::AddTextRectActions( const Rectangle& rRect,
// #i47157# Factored out to ImplDrawTextRect(), to be shared
// between us and DrawText()
- ImplDrawText( rRect, rOrigStr, nStyle, NULL, NULL );
+ ImplDrawText( rRect, rOrigStr, nStyle, NULL, NULL, NULL );
// and restore again
EnableOutput( bOutputEnabled );
@@ -7079,7 +7099,15 @@ void OutputDevice::AddTextRectActions( const Rectangle& rRect,
void OutputDevice::DrawText( const Rectangle& rRect,
const String& rOrigStr, USHORT nStyle,
MetricVector* pVector, String* pDisplayText )
+{
+ DrawText( rRect, rOrigStr, nStyle, pVector, pDisplayText, NULL );
+}
+
+// -----------------------------------------------------------------------
+void OutputDevice::DrawText( const Rectangle& rRect, const String& rOrigStr, USHORT nStyle,
+ MetricVector* pVector, String* pDisplayText,
+ ::vcl::ITextLayout* _pTextLayout )
{
if( mpOutDevData && mpOutDevData->mpRecordLayout )
{
@@ -7109,9 +7137,9 @@ void OutputDevice::DrawText( const Rectangle& rRect,
GDIMetaFile* pMtf = mpMetaFile;
mpMetaFile = NULL;
- // #i47157# Factored out to ImplDrawTextRect(), to be used also
+ // #i47157# Factored out to ImplDrawText(), to be used also
// from AddTextRectActions()
- ImplDrawText( rRect, rOrigStr, nStyle, pVector, pDisplayText );
+ ImplDrawText( rRect, rOrigStr, nStyle, pVector, pDisplayText, _pTextLayout );
// and enable again
mpMetaFile = pMtf;
@@ -7126,6 +7154,16 @@ Rectangle OutputDevice::GetTextRect( const Rectangle& rRect,
const String& rOrigStr, USHORT nStyle,
TextRectInfo* pInfo ) const
{
+ return GetTextRect( rRect, rOrigStr, nStyle, pInfo, NULL );
+}
+
+// -----------------------------------------------------------------------
+
+Rectangle OutputDevice::GetTextRect( const Rectangle& rRect,
+ const XubString& rStr, USHORT nStyle,
+ TextRectInfo* pInfo,
+ const ::vcl::ITextLayout* _pTextLayout ) const
+{
DBG_TRACE( "OutputDevice::GetTextRect()" );
DBG_CHKTHIS( OutputDevice, ImplDbgCheckOutputDevice );
@@ -7135,7 +7173,7 @@ Rectangle OutputDevice::GetTextRect( const Rectangle& rRect,
long nMaxWidth;
long nTextHeight = GetTextHeight();
- String aStr = rOrigStr;
+ String aStr = rStr;
if ( nStyle & TEXT_DRAW_MNEMONIC )
aStr = GetNonMnemonicString( aStr );
@@ -7147,7 +7185,7 @@ Rectangle OutputDevice::GetTextRect( const Rectangle& rRect,
xub_StrLen i;
nMaxWidth = 0;
- ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle );
+ ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle, _pTextLayout );
nFormatLines = aMultiLineInfo.Count();
if ( !nTextHeight )
nTextHeight = 1;
@@ -7195,7 +7233,7 @@ Rectangle OutputDevice::GetTextRect( const Rectangle& rRect,
else
{
nLines = 1;
- nMaxWidth = GetTextWidth( aStr );
+ nMaxWidth = _pTextLayout ? _pTextLayout->GetTextWidth( aStr, 0, aStr.Len() ) : GetTextWidth( aStr );
if ( pInfo )
{
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index e7ee18ec7705..3eda6b5c929c 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -7307,7 +7307,7 @@ void PDFWriterImpl::drawText( const Rectangle& rRect, const String& rOrigStr, US
if ( nTextHeight )
{
- nMaxTextWidth = m_pReferenceDevice->ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle );
+ nMaxTextWidth = m_pReferenceDevice->ImplGetTextLines( aMultiLineInfo, nWidth, aStr, nStyle, NULL );
nLines = (xub_StrLen)(nHeight/nTextHeight);
nFormatLines = aMultiLineInfo.Count();
if ( !nLines )
diff --git a/vcl/source/gdi/textlayout.cxx b/vcl/source/gdi/textlayout.cxx
new file mode 100755
index 000000000000..7ea72e8e12ea
--- /dev/null
+++ b/vcl/source/gdi/textlayout.cxx
@@ -0,0 +1,269 @@
+/*************************************************************************
+* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+*
+* Copyright 2009 by Sun Microsystems, Inc.
+*
+* OpenOffice.org - a multi-platform office productivity suite
+*
+* This file is part of OpenOffice.org.
+*
+* 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.
+*
+* 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).
+*
+* 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.
+************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_vcl.hxx"
+
+#include "vcl/ctrl.hxx"
+#include "vcl/outdev.hxx"
+#include "vcl/outfont.hxx"
+#include "vcl/textlayout.hxx"
+
+//........................................................................
+namespace vcl
+{
+//........................................................................
+
+ //====================================================================
+ //= ReferenceDeviceTextLayout
+ //====================================================================
+ class ReferenceDeviceTextLayout : public ITextLayout
+ {
+ public:
+ ReferenceDeviceTextLayout( const Control& _rControl, OutputDevice& _rTargetDevice, OutputDevice& _rReferenceDevice );
+ virtual ~ReferenceDeviceTextLayout();
+
+ // 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 );
+
+ public:
+ // equivalents to the respective OutputDevice methods, which take the reference device into account
+ long GetTextArray( const XubString& _rText, sal_Int32* _pDXAry, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const;
+ Rectangle DrawText( const Rectangle& _rRect, const XubString& _rText, USHORT _nStyle, MetricVector* _pVector, String* _pDisplayText);
+
+
+ bool IsZoom() const;
+
+ protected:
+ void onBeginDrawText()
+ {
+ m_aCompleteTextRect.SetEmpty();
+ }
+ Rectangle onEndDrawText()
+ {
+ return m_aCompleteTextRect;
+ }
+
+ private:
+ OutputDevice& m_rTargetDevice;
+ OutputDevice& m_rReferenceDevice;
+ Font m_aUnzoomedPointFont;
+ const Fraction m_aZoom;
+
+ Rectangle m_aCompleteTextRect;
+ };
+
+ //====================================================================
+ //= ControlTextRenderer
+ //====================================================================
+ ReferenceDeviceTextLayout::ReferenceDeviceTextLayout( const Control& _rControl, OutputDevice& _rTargetDevice, OutputDevice& _rReferenceDevice )
+ :m_rTargetDevice( _rTargetDevice )
+ ,m_rReferenceDevice( _rReferenceDevice )
+ ,m_aUnzoomedPointFont( _rControl.GetUnzoomedControlPointFont() )
+ ,m_aZoom( _rControl.GetZoom() )
+ {
+ if ( IsZoom() )
+ {
+ m_rTargetDevice.Push( PUSH_MAPMODE | PUSH_FONT );
+
+ MapMode aDrawMapMode( m_rTargetDevice.GetMapMode() );
+ aDrawMapMode.SetScaleX( m_aZoom ); // TODO: shouldn't this be "current_scale * zoom"?
+ aDrawMapMode.SetScaleY( m_aZoom );
+ m_rTargetDevice.SetMapMode( aDrawMapMode );
+
+ MapUnit eTargetMapUnit = m_rTargetDevice.GetMapMode().GetMapUnit();
+ Font aDrawFont( m_aUnzoomedPointFont );
+ if ( eTargetMapUnit == MAP_PIXEL )
+ aDrawFont.SetSize( m_rTargetDevice.LogicToPixel( aDrawFont.GetSize(), MAP_POINT ) );
+ else
+ aDrawFont.SetSize( m_rTargetDevice.LogicToLogic( aDrawFont.GetSize(), MAP_POINT, eTargetMapUnit ) );
+ _rTargetDevice.SetFont( aDrawFont );
+ }
+ }
+
+ //--------------------------------------------------------------------
+ namespace
+ {
+ //................................................................
+ bool lcl_normalizeLength( const XubString& _rText, const xub_StrLen _nStartIndex, xub_StrLen& _io_nLength )
+ {
+ xub_StrLen nTextLength = _rText.Len();
+ if ( _nStartIndex > nTextLength )
+ return false;
+ if ( _nStartIndex + _io_nLength > nTextLength )
+ _io_nLength = nTextLength - _nStartIndex;
+ return true;
+ }
+
+ //................................................................
+ class DeviceUnitMapping
+ {
+ public:
+ DeviceUnitMapping( const OutputDevice& _rTargetDevice, const OutputDevice& _rReferenceDevice )
+ :m_rTargetDevice( _rTargetDevice )
+ ,m_eTargetMapUnit( _rTargetDevice.GetMapMode().GetMapUnit() )
+ ,m_bTargetIsPixel( _rTargetDevice.GetMapMode().GetMapUnit() == MAP_PIXEL )
+ ,m_eRefMapUnit( _rReferenceDevice.GetMapMode().GetMapUnit() )
+ {
+ OSL_ENSURE( m_eRefMapUnit != MAP_PIXEL, "a reference device with MAP_PIXEL?" );
+ }
+
+ long mapToTarget( long _nWidth )
+ {
+ return m_bTargetIsPixel
+ ? m_rTargetDevice.LogicToPixel( Size( _nWidth, 0 ), m_eRefMapUnit ).Width()
+ : m_rTargetDevice.LogicToLogic( Size( _nWidth, 0 ), m_eRefMapUnit, m_eTargetMapUnit ).Width();
+ }
+
+ private:
+ const OutputDevice& m_rTargetDevice;
+ const MapUnit m_eTargetMapUnit;
+ const bool m_bTargetIsPixel;
+ const MapUnit m_eRefMapUnit;
+ };
+ }
+
+ //--------------------------------------------------------------------
+ ReferenceDeviceTextLayout::~ReferenceDeviceTextLayout()
+ {
+ if ( IsZoom() )
+ m_rTargetDevice.Pop();
+ }
+
+ //--------------------------------------------------------------------
+ bool ReferenceDeviceTextLayout::IsZoom() const
+ {
+ return m_aZoom.GetNumerator() != m_aZoom.GetDenominator();
+ }
+
+ //--------------------------------------------------------------------
+ long ReferenceDeviceTextLayout::GetTextArray( const XubString& _rText, sal_Int32* _pDXAry, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const
+ {
+ 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 );
+ if ( _pDXAry )
+ {
+ for ( size_t i=0; i<_nLength; ++i )
+ _pDXAry[i] = aMapping.mapToTarget( _pDXAry[i] );
+ }
+ nTextWidth = aMapping.mapToTarget( nTextWidth );
+
+ return nTextWidth;
+ }
+
+ //--------------------------------------------------------------------
+ long ReferenceDeviceTextLayout::GetTextWidth( const XubString& _rText, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const
+ {
+ return GetTextArray( _rText, NULL, _nStartIndex, _nLength );
+ }
+
+ //--------------------------------------------------------------------
+ void ReferenceDeviceTextLayout::DrawText( const Point& _rStartPoint, const XubString& _rText, xub_StrLen _nStartIndex, xub_StrLen _nLength, MetricVector* _pVector, String* _pDisplayText )
+ {
+ if ( !lcl_normalizeLength( _rText, _nStartIndex, _nLength ) )
+ return;
+
+ sal_Int32* pCharWidths = new sal_Int32[ _nLength ];
+ long nTextWidth = GetTextArray( _rText, pCharWidths, _nStartIndex, _nLength );
+ m_rTargetDevice.DrawTextArray( _rStartPoint, _rText, pCharWidths, _nStartIndex, _nLength );
+ delete[] pCharWidths;
+
+ m_aCompleteTextRect.Union( Rectangle( _rStartPoint, Size( nTextWidth, m_rTargetDevice.GetTextHeight() ) ) );
+
+ // TODO: use/fill those:
+ (void)_pVector;
+ (void)_pDisplayText;
+ }
+
+ //--------------------------------------------------------------------
+ Rectangle ReferenceDeviceTextLayout::DrawText( const Rectangle& _rRect, const XubString& _rText, USHORT _nStyle, MetricVector* _pVector, String* _pDisplayText)
+ {
+ Rectangle aRect( _rRect );
+ if ( IsZoom() )
+ {
+ // 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 );
+ }
+
+ onBeginDrawText();
+ m_rTargetDevice.DrawText( aRect, _rText, _nStyle, _pVector, _pDisplayText, this );
+ Rectangle aTextRect = onEndDrawText();
+
+ if ( IsZoom() )
+ {
+ // 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 );
+ }
+
+ return aTextRect;
+ }
+
+ //====================================================================
+ //= ControlTextRenderer
+ //====================================================================
+ //--------------------------------------------------------------------
+ ControlTextRenderer::ControlTextRenderer( const Control& _rControl, OutputDevice& _rTargetDevice, OutputDevice& _rReferenceDevice )
+ :m_pImpl( new ReferenceDeviceTextLayout( _rControl, _rTargetDevice, _rReferenceDevice ) )
+ {
+ }
+
+ //--------------------------------------------------------------------
+ ControlTextRenderer::~ControlTextRenderer()
+ {
+ }
+
+ //--------------------------------------------------------------------
+ Rectangle ControlTextRenderer::DrawText( const Rectangle& _rRect, const XubString& _rText, USHORT _nStyle,
+ MetricVector* _pVector, String* _pDisplayText )
+ {
+ return m_pImpl->DrawText( _rRect, _rText, _nStyle, _pVector, _pDisplayText );
+ }
+
+//........................................................................
+} // namespace vcl
+//........................................................................