19f62ea84SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 39f62ea84SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 49f62ea84SAndrew Rist * or more contributor license agreements. See the NOTICE file 59f62ea84SAndrew Rist * distributed with this work for additional information 69f62ea84SAndrew Rist * regarding copyright ownership. The ASF licenses this file 79f62ea84SAndrew Rist * to you under the Apache License, Version 2.0 (the 89f62ea84SAndrew Rist * "License"); you may not use this file except in compliance 99f62ea84SAndrew Rist * with the License. You may obtain a copy of the License at 109f62ea84SAndrew Rist * 119f62ea84SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 129f62ea84SAndrew Rist * 139f62ea84SAndrew Rist * Unless required by applicable law or agreed to in writing, 149f62ea84SAndrew Rist * software distributed under the License is distributed on an 159f62ea84SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 169f62ea84SAndrew Rist * KIND, either express or implied. See the License for the 179f62ea84SAndrew Rist * specific language governing permissions and limitations 189f62ea84SAndrew Rist * under the License. 199f62ea84SAndrew Rist * 209f62ea84SAndrew Rist *************************************************************/ 219f62ea84SAndrew Rist 229f62ea84SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove 25cdf0e10cSrcweir #include "precompiled_vcl.hxx" 26cdf0e10cSrcweir 27cdf0e10cSrcweir #include "vcl/ctrl.hxx" 28cdf0e10cSrcweir #include "vcl/outdev.hxx" 29cdf0e10cSrcweir 30cdf0e10cSrcweir #include "outfont.hxx" 31cdf0e10cSrcweir #include "textlayout.hxx" 32cdf0e10cSrcweir 33cdf0e10cSrcweir #include <com/sun/star/i18n/ScriptDirection.hpp> 34cdf0e10cSrcweir 35cdf0e10cSrcweir #include <tools/diagnose_ex.h> 36cdf0e10cSrcweir 37cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 38cdf0e10cSrcweir #include <rtl/strbuf.hxx> 39cdf0e10cSrcweir #endif 40cdf0e10cSrcweir 41cdf0e10cSrcweir //........................................................................ 42cdf0e10cSrcweir namespace vcl 43cdf0e10cSrcweir { 44cdf0e10cSrcweir //........................................................................ 45cdf0e10cSrcweir 46cdf0e10cSrcweir using ::com::sun::star::uno::Reference; 47cdf0e10cSrcweir using ::com::sun::star::uno::Exception; 48cdf0e10cSrcweir namespace ScriptDirection = ::com::sun::star::i18n::ScriptDirection; 49cdf0e10cSrcweir 50cdf0e10cSrcweir //==================================================================== 51cdf0e10cSrcweir //= DefaultTextLayout 52cdf0e10cSrcweir //==================================================================== 53cdf0e10cSrcweir //-------------------------------------------------------------------- ~DefaultTextLayout()54cdf0e10cSrcweir DefaultTextLayout::~DefaultTextLayout() 55cdf0e10cSrcweir { 56cdf0e10cSrcweir } 57cdf0e10cSrcweir 58cdf0e10cSrcweir //-------------------------------------------------------------------- GetTextWidth(const XubString & _rText,xub_StrLen _nStartIndex,xub_StrLen _nLength) const59cdf0e10cSrcweir long DefaultTextLayout::GetTextWidth( const XubString& _rText, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const 60cdf0e10cSrcweir { 61cdf0e10cSrcweir return m_rTargetDevice.GetTextWidth( _rText, _nStartIndex, _nLength ); 62cdf0e10cSrcweir } 63cdf0e10cSrcweir 64cdf0e10cSrcweir //-------------------------------------------------------------------- DrawText(const Point & _rStartPoint,const XubString & _rText,xub_StrLen _nStartIndex,xub_StrLen _nLength,MetricVector * _pVector,String * _pDisplayText)65cdf0e10cSrcweir void DefaultTextLayout::DrawText( const Point& _rStartPoint, const XubString& _rText, xub_StrLen _nStartIndex, 66cdf0e10cSrcweir xub_StrLen _nLength, MetricVector* _pVector, String* _pDisplayText ) 67cdf0e10cSrcweir { 68cdf0e10cSrcweir m_rTargetDevice.DrawText( _rStartPoint, _rText, _nStartIndex, _nLength, _pVector, _pDisplayText ); 69cdf0e10cSrcweir } 70cdf0e10cSrcweir 71cdf0e10cSrcweir //-------------------------------------------------------------------- GetCaretPositions(const XubString & _rText,sal_Int32 * _pCaretXArray,xub_StrLen _nStartIndex,xub_StrLen _nLength) const72cdf0e10cSrcweir bool DefaultTextLayout::GetCaretPositions( const XubString& _rText, sal_Int32* _pCaretXArray, 73cdf0e10cSrcweir xub_StrLen _nStartIndex, xub_StrLen _nLength ) const 74cdf0e10cSrcweir { 75cdf0e10cSrcweir return m_rTargetDevice.GetCaretPositions( _rText, _pCaretXArray, _nStartIndex, _nLength ); 76cdf0e10cSrcweir } 77cdf0e10cSrcweir 78cdf0e10cSrcweir //-------------------------------------------------------------------- GetTextBreak(const XubString & _rText,long _nMaxTextWidth,xub_StrLen _nStartIndex,xub_StrLen _nLength) const79cdf0e10cSrcweir xub_StrLen DefaultTextLayout::GetTextBreak( const XubString& _rText, long _nMaxTextWidth, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const 80cdf0e10cSrcweir { 81cdf0e10cSrcweir return m_rTargetDevice.GetTextBreak( _rText, _nMaxTextWidth, _nStartIndex, _nLength ); 82cdf0e10cSrcweir } 83cdf0e10cSrcweir 84cdf0e10cSrcweir //-------------------------------------------------------------------- DecomposeTextRectAction() const85cdf0e10cSrcweir bool DefaultTextLayout::DecomposeTextRectAction() const 86cdf0e10cSrcweir { 87cdf0e10cSrcweir return false; 88cdf0e10cSrcweir } 89cdf0e10cSrcweir 90cdf0e10cSrcweir //==================================================================== 91cdf0e10cSrcweir //= ReferenceDeviceTextLayout 92cdf0e10cSrcweir //==================================================================== 93cdf0e10cSrcweir class ReferenceDeviceTextLayout : public ITextLayout 94cdf0e10cSrcweir { 95cdf0e10cSrcweir public: 96cdf0e10cSrcweir ReferenceDeviceTextLayout( const Control& _rControl, OutputDevice& _rTargetDevice, OutputDevice& _rReferenceDevice ); 97cdf0e10cSrcweir virtual ~ReferenceDeviceTextLayout(); 98cdf0e10cSrcweir 99cdf0e10cSrcweir // ITextLayout 100cdf0e10cSrcweir virtual long GetTextWidth( const XubString& rStr, xub_StrLen nIndex, xub_StrLen nLen ) const; 101cdf0e10cSrcweir virtual void DrawText( const Point& _rStartPoint, const XubString& _rText, xub_StrLen _nStartIndex, xub_StrLen _nLength, MetricVector* _pVector, String* _pDisplayText ); 102cdf0e10cSrcweir virtual bool GetCaretPositions( const XubString& _rText, sal_Int32* _pCaretXArray, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const; 103cdf0e10cSrcweir virtual xub_StrLen GetTextBreak( const XubString& _rText, long _nMaxTextWidth, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const; 104cdf0e10cSrcweir virtual bool DecomposeTextRectAction() const; 105cdf0e10cSrcweir 106cdf0e10cSrcweir public: 107cdf0e10cSrcweir // equivalents to the respective OutputDevice methods, which take the reference device into account 108cdf0e10cSrcweir long GetTextArray( const XubString& _rText, sal_Int32* _pDXAry, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const; 109cdf0e10cSrcweir Rectangle DrawText( const Rectangle& _rRect, const XubString& _rText, sal_uInt16 _nStyle, MetricVector* _pVector, String* _pDisplayText ); 110cdf0e10cSrcweir 111cdf0e10cSrcweir protected: onBeginDrawText()112cdf0e10cSrcweir void onBeginDrawText() 113cdf0e10cSrcweir { 114cdf0e10cSrcweir m_aCompleteTextRect.SetEmpty(); 115cdf0e10cSrcweir } onEndDrawText()116cdf0e10cSrcweir Rectangle onEndDrawText() 117cdf0e10cSrcweir { 118cdf0e10cSrcweir return m_aCompleteTextRect; 119cdf0e10cSrcweir } 120cdf0e10cSrcweir 121cdf0e10cSrcweir private: 122cdf0e10cSrcweir OutputDevice& m_rTargetDevice; 123cdf0e10cSrcweir OutputDevice& m_rReferenceDevice; 124cdf0e10cSrcweir Font m_aUnzoomedPointFont; 125cdf0e10cSrcweir const Fraction m_aZoom; 126cdf0e10cSrcweir const bool m_bRTLEnabled; 127cdf0e10cSrcweir 128cdf0e10cSrcweir Rectangle m_aCompleteTextRect; 129cdf0e10cSrcweir }; 130cdf0e10cSrcweir 131cdf0e10cSrcweir //==================================================================== 132cdf0e10cSrcweir //= ControlTextRenderer 133cdf0e10cSrcweir //==================================================================== ReferenceDeviceTextLayout(const Control & _rControl,OutputDevice & _rTargetDevice,OutputDevice & _rReferenceDevice)134cdf0e10cSrcweir ReferenceDeviceTextLayout::ReferenceDeviceTextLayout( const Control& _rControl, OutputDevice& _rTargetDevice, 135cdf0e10cSrcweir OutputDevice& _rReferenceDevice ) 136cdf0e10cSrcweir :m_rTargetDevice( _rTargetDevice ) 137cdf0e10cSrcweir ,m_rReferenceDevice( _rReferenceDevice ) 138cdf0e10cSrcweir ,m_aUnzoomedPointFont( _rControl.GetUnzoomedControlPointFont() ) 139cdf0e10cSrcweir ,m_aZoom( _rControl.GetZoom() ) 140cdf0e10cSrcweir ,m_bRTLEnabled( _rControl.IsRTLEnabled() ) 141cdf0e10cSrcweir { 142cdf0e10cSrcweir m_rTargetDevice.Push( PUSH_MAPMODE | PUSH_FONT | PUSH_TEXTLAYOUTMODE ); 143cdf0e10cSrcweir 144cdf0e10cSrcweir MapMode aTargetMapMode( m_rTargetDevice.GetMapMode() ); 145cdf0e10cSrcweir OSL_ENSURE( aTargetMapMode.GetOrigin() == Point(), "ReferenceDeviceTextLayout::ReferenceDeviceTextLayout: uhm, the code below won't work here ..." ); 146cdf0e10cSrcweir 147cdf0e10cSrcweir // normally, controls simulate "zoom" by "zooming" the font. This is responsible for (part of) the discrepancies 148cdf0e10cSrcweir // between text in Writer and text in controls in Writer, though both have the same font. 149cdf0e10cSrcweir // So, if we have a zoom set at the control, then we do not scale the font, but instead modify the map mode 150*86e1cf34SPedro Giffuni // to accommodate for the zoom. 151cdf0e10cSrcweir aTargetMapMode.SetScaleX( m_aZoom ); // TODO: shouldn't this be "current_scale * zoom"? 152cdf0e10cSrcweir aTargetMapMode.SetScaleY( m_aZoom ); 153cdf0e10cSrcweir 154cdf0e10cSrcweir // also, use a higher-resolution map unit than "pixels", which should save us some rounding errors when 155cdf0e10cSrcweir // translating coordinates between the reference device and the target device. 156cdf0e10cSrcweir OSL_ENSURE( aTargetMapMode.GetMapUnit() == MAP_PIXEL, 157cdf0e10cSrcweir "ReferenceDeviceTextLayout::ReferenceDeviceTextLayout: this class is not expected to work with such target devices!" ); 158cdf0e10cSrcweir // we *could* adjust all the code in this class to handle this case, but at the moment, it's not necessary 159cdf0e10cSrcweir const MapUnit eTargetMapUnit = m_rReferenceDevice.GetMapMode().GetMapUnit(); 160cdf0e10cSrcweir aTargetMapMode.SetMapUnit( eTargetMapUnit ); 161cdf0e10cSrcweir OSL_ENSURE( aTargetMapMode.GetMapUnit() != MAP_PIXEL, 162cdf0e10cSrcweir "ReferenceDeviceTextLayout::ReferenceDeviceTextLayout: a reference device which has map mode PIXEL?!" ); 163cdf0e10cSrcweir 164cdf0e10cSrcweir m_rTargetDevice.SetMapMode( aTargetMapMode ); 165cdf0e10cSrcweir 166cdf0e10cSrcweir // now that the Zoom is part of the map mode, reset the target device's font to the "unzoomed" version 167cdf0e10cSrcweir Font aDrawFont( m_aUnzoomedPointFont ); 168cdf0e10cSrcweir aDrawFont.SetSize( m_rTargetDevice.LogicToLogic( aDrawFont.GetSize(), MAP_POINT, eTargetMapUnit ) ); 169cdf0e10cSrcweir _rTargetDevice.SetFont( aDrawFont ); 170cdf0e10cSrcweir 171cdf0e10cSrcweir // transfer font to the reference device 172cdf0e10cSrcweir m_rReferenceDevice.Push( PUSH_FONT | PUSH_TEXTLAYOUTMODE ); 173cdf0e10cSrcweir Font aRefFont( m_aUnzoomedPointFont ); 174cdf0e10cSrcweir aRefFont.SetSize( OutputDevice::LogicToLogic( 175cdf0e10cSrcweir aRefFont.GetSize(), MAP_POINT, m_rReferenceDevice.GetMapMode().GetMapUnit() ) ); 176cdf0e10cSrcweir m_rReferenceDevice.SetFont( aRefFont ); 177cdf0e10cSrcweir } 178cdf0e10cSrcweir 179cdf0e10cSrcweir //-------------------------------------------------------------------- ~ReferenceDeviceTextLayout()180cdf0e10cSrcweir ReferenceDeviceTextLayout::~ReferenceDeviceTextLayout() 181cdf0e10cSrcweir { 182cdf0e10cSrcweir m_rReferenceDevice.Pop(); 183cdf0e10cSrcweir m_rTargetDevice.Pop(); 184cdf0e10cSrcweir } 185cdf0e10cSrcweir 186cdf0e10cSrcweir //-------------------------------------------------------------------- 187cdf0e10cSrcweir namespace 188cdf0e10cSrcweir { 189cdf0e10cSrcweir //................................................................ lcl_normalizeLength(const XubString & _rText,const xub_StrLen _nStartIndex,xub_StrLen & _io_nLength)190cdf0e10cSrcweir bool lcl_normalizeLength( const XubString& _rText, const xub_StrLen _nStartIndex, xub_StrLen& _io_nLength ) 191cdf0e10cSrcweir { 192cdf0e10cSrcweir xub_StrLen nTextLength = _rText.Len(); 193cdf0e10cSrcweir if ( _nStartIndex > nTextLength ) 194cdf0e10cSrcweir return false; 195cdf0e10cSrcweir if ( _nStartIndex + _io_nLength > nTextLength ) 196cdf0e10cSrcweir _io_nLength = nTextLength - _nStartIndex; 197cdf0e10cSrcweir return true; 198cdf0e10cSrcweir } 199cdf0e10cSrcweir } 200cdf0e10cSrcweir 201cdf0e10cSrcweir //-------------------------------------------------------------------- GetTextArray(const XubString & _rText,sal_Int32 * _pDXAry,xub_StrLen _nStartIndex,xub_StrLen _nLength) const202cdf0e10cSrcweir long ReferenceDeviceTextLayout::GetTextArray( const XubString& _rText, sal_Int32* _pDXAry, xub_StrLen _nStartIndex, 203cdf0e10cSrcweir xub_StrLen _nLength ) const 204cdf0e10cSrcweir { 205cdf0e10cSrcweir if ( !lcl_normalizeLength( _rText, _nStartIndex, _nLength ) ) 206cdf0e10cSrcweir return 0; 207cdf0e10cSrcweir 208cdf0e10cSrcweir // retrieve the character widths from the reference device 209cdf0e10cSrcweir long nTextWidth = m_rReferenceDevice.GetTextArray( _rText, _pDXAry, _nStartIndex, _nLength ); 210cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1 211cdf0e10cSrcweir if ( _pDXAry ) 212cdf0e10cSrcweir { 213cdf0e10cSrcweir ::rtl::OStringBuffer aTrace; 214cdf0e10cSrcweir aTrace.append( "ReferenceDeviceTextLayout::GetTextArray( " ); 215cdf0e10cSrcweir aTrace.append( ::rtl::OUStringToOString( _rText, RTL_TEXTENCODING_UTF8 ) ); 216cdf0e10cSrcweir aTrace.append( " ): " ); 217cdf0e10cSrcweir aTrace.append( nTextWidth ); 218cdf0e10cSrcweir aTrace.append( " = ( " ); 219cdf0e10cSrcweir for ( size_t i=0; i<_nLength; ) 220cdf0e10cSrcweir { 221cdf0e10cSrcweir aTrace.append( _pDXAry[i] ); 222cdf0e10cSrcweir if ( ++i < _nLength ) 223cdf0e10cSrcweir aTrace.append( ", " ); 224cdf0e10cSrcweir } 225cdf0e10cSrcweir aTrace.append( ")" ); 226cdf0e10cSrcweir OSL_TRACE( aTrace.makeStringAndClear().getStr() ); 227cdf0e10cSrcweir } 228cdf0e10cSrcweir #endif 229cdf0e10cSrcweir return nTextWidth; 230cdf0e10cSrcweir } 231cdf0e10cSrcweir 232cdf0e10cSrcweir //-------------------------------------------------------------------- GetTextWidth(const XubString & _rText,xub_StrLen _nStartIndex,xub_StrLen _nLength) const233cdf0e10cSrcweir long ReferenceDeviceTextLayout::GetTextWidth( const XubString& _rText, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const 234cdf0e10cSrcweir { 235cdf0e10cSrcweir return GetTextArray( _rText, NULL, _nStartIndex, _nLength ); 236cdf0e10cSrcweir } 237cdf0e10cSrcweir 238cdf0e10cSrcweir //-------------------------------------------------------------------- DrawText(const Point & _rStartPoint,const XubString & _rText,xub_StrLen _nStartIndex,xub_StrLen _nLength,MetricVector * _pVector,String * _pDisplayText)239cdf0e10cSrcweir void ReferenceDeviceTextLayout::DrawText( const Point& _rStartPoint, const XubString& _rText, xub_StrLen _nStartIndex, xub_StrLen _nLength, MetricVector* _pVector, String* _pDisplayText ) 240cdf0e10cSrcweir { 241cdf0e10cSrcweir if ( !lcl_normalizeLength( _rText, _nStartIndex, _nLength ) ) 242cdf0e10cSrcweir return; 243cdf0e10cSrcweir 244cdf0e10cSrcweir if ( _pVector && _pDisplayText ) 245cdf0e10cSrcweir { 246cdf0e10cSrcweir MetricVector aGlyphBounds; 247cdf0e10cSrcweir m_rReferenceDevice.GetGlyphBoundRects( _rStartPoint, _rText, _nStartIndex, _nLength, _nStartIndex, aGlyphBounds ); 248cdf0e10cSrcweir ::std::copy( 249cdf0e10cSrcweir aGlyphBounds.begin(), aGlyphBounds.end(), 250cdf0e10cSrcweir ::std::insert_iterator< MetricVector > ( *_pVector, _pVector->end() ) ); 251cdf0e10cSrcweir _pDisplayText->Append( _rText.Copy( _nStartIndex, _nLength ) ); 252cdf0e10cSrcweir return; 253cdf0e10cSrcweir } 254cdf0e10cSrcweir 255cdf0e10cSrcweir sal_Int32* pCharWidths = new sal_Int32[ _nLength ]; 256cdf0e10cSrcweir long nTextWidth = GetTextArray( _rText, pCharWidths, _nStartIndex, _nLength ); 257cdf0e10cSrcweir m_rTargetDevice.DrawTextArray( _rStartPoint, _rText, pCharWidths, _nStartIndex, _nLength ); 258cdf0e10cSrcweir delete[] pCharWidths; 259cdf0e10cSrcweir 260cdf0e10cSrcweir m_aCompleteTextRect.Union( Rectangle( _rStartPoint, Size( nTextWidth, m_rTargetDevice.GetTextHeight() ) ) ); 261cdf0e10cSrcweir } 262cdf0e10cSrcweir 263cdf0e10cSrcweir //-------------------------------------------------------------------- GetCaretPositions(const XubString & _rText,sal_Int32 * _pCaretXArray,xub_StrLen _nStartIndex,xub_StrLen _nLength) const264cdf0e10cSrcweir bool ReferenceDeviceTextLayout::GetCaretPositions( const XubString& _rText, sal_Int32* _pCaretXArray, 265cdf0e10cSrcweir xub_StrLen _nStartIndex, xub_StrLen _nLength ) const 266cdf0e10cSrcweir { 267cdf0e10cSrcweir if ( !lcl_normalizeLength( _rText, _nStartIndex, _nLength ) ) 268cdf0e10cSrcweir return false; 269cdf0e10cSrcweir 270cdf0e10cSrcweir // retrieve the caret positions from the reference device 271cdf0e10cSrcweir if ( !m_rReferenceDevice.GetCaretPositions( _rText, _pCaretXArray, _nStartIndex, _nLength ) ) 272cdf0e10cSrcweir return false; 273cdf0e10cSrcweir 274cdf0e10cSrcweir return true; 275cdf0e10cSrcweir } 276cdf0e10cSrcweir 277cdf0e10cSrcweir //-------------------------------------------------------------------- GetTextBreak(const XubString & _rText,long _nMaxTextWidth,xub_StrLen _nStartIndex,xub_StrLen _nLength) const278cdf0e10cSrcweir xub_StrLen ReferenceDeviceTextLayout::GetTextBreak( const XubString& _rText, long _nMaxTextWidth, xub_StrLen _nStartIndex, xub_StrLen _nLength ) const 279cdf0e10cSrcweir { 280cdf0e10cSrcweir if ( !lcl_normalizeLength( _rText, _nStartIndex, _nLength ) ) 281cdf0e10cSrcweir return 0; 282cdf0e10cSrcweir 283cdf0e10cSrcweir return m_rReferenceDevice.GetTextBreak( _rText, _nMaxTextWidth, _nStartIndex, _nLength ); 284cdf0e10cSrcweir } 285cdf0e10cSrcweir 286cdf0e10cSrcweir //-------------------------------------------------------------------- DecomposeTextRectAction() const287cdf0e10cSrcweir bool ReferenceDeviceTextLayout::DecomposeTextRectAction() const 288cdf0e10cSrcweir { 289cdf0e10cSrcweir return true; 290cdf0e10cSrcweir } 291cdf0e10cSrcweir 292cdf0e10cSrcweir //-------------------------------------------------------------------- 293cdf0e10cSrcweir namespace 294cdf0e10cSrcweir { zoomBy(long _value,const Fraction & _zoom)295cdf0e10cSrcweir long zoomBy( long _value, const Fraction& _zoom ) 296cdf0e10cSrcweir { 297cdf0e10cSrcweir double n = (double)_value; 298cdf0e10cSrcweir n *= (double)_zoom.GetNumerator(); 299cdf0e10cSrcweir n /= (double)_zoom.GetDenominator(); 300cdf0e10cSrcweir return (long)::rtl::math::round( n ); 301cdf0e10cSrcweir } unzoomBy(long _value,const Fraction & _zoom)302cdf0e10cSrcweir long unzoomBy( long _value, const Fraction& _zoom ) 303cdf0e10cSrcweir { 304cdf0e10cSrcweir return zoomBy( _value, Fraction( _zoom.GetDenominator(), _zoom.GetNumerator() ) ); 305cdf0e10cSrcweir } 306cdf0e10cSrcweir } 307cdf0e10cSrcweir 308cdf0e10cSrcweir //-------------------------------------------------------------------- DrawText(const Rectangle & _rRect,const XubString & _rText,sal_uInt16 _nStyle,MetricVector * _pVector,String * _pDisplayText)309cdf0e10cSrcweir Rectangle ReferenceDeviceTextLayout::DrawText( const Rectangle& _rRect, const XubString& _rText, sal_uInt16 _nStyle, MetricVector* _pVector, String* _pDisplayText ) 310cdf0e10cSrcweir { 311cdf0e10cSrcweir if ( !_rText.Len() ) 312cdf0e10cSrcweir return Rectangle(); 313cdf0e10cSrcweir 314cdf0e10cSrcweir // determine text layout mode from the RTL-ness of the control whose text we render 315cdf0e10cSrcweir sal_uLong nTextLayoutMode = m_bRTLEnabled ? TEXT_LAYOUT_BIDI_RTL : TEXT_LAYOUT_BIDI_LTR; 316cdf0e10cSrcweir m_rReferenceDevice.SetLayoutMode( nTextLayoutMode ); 317cdf0e10cSrcweir m_rTargetDevice.SetLayoutMode( nTextLayoutMode | TEXT_LAYOUT_TEXTORIGIN_LEFT ); 318cdf0e10cSrcweir // TEXT_LAYOUT_TEXTORIGIN_LEFT is because when we do actually draw the text (in DrawText( Point, ... )), then 319cdf0e10cSrcweir // our caller gives us the left border of the draw position, regardless of script type, text layout, 320cdf0e10cSrcweir // and the like 321cdf0e10cSrcweir 322cdf0e10cSrcweir // in our ctor, we set the map mode of the target device from pixel to twip, but our caller doesn't know this, 323cdf0e10cSrcweir // but passed pixel coordinates. So, adjust the rect. 324cdf0e10cSrcweir Rectangle aRect( m_rTargetDevice.PixelToLogic( _rRect ) ); 325cdf0e10cSrcweir 326cdf0e10cSrcweir onBeginDrawText(); 327cdf0e10cSrcweir m_rTargetDevice.DrawText( aRect, _rText, _nStyle, _pVector, _pDisplayText, this ); 328cdf0e10cSrcweir Rectangle aTextRect = onEndDrawText(); 329cdf0e10cSrcweir 330cdf0e10cSrcweir if ( aTextRect.IsEmpty() && !aRect.IsEmpty() ) 331cdf0e10cSrcweir { 332cdf0e10cSrcweir // this happens for instance if we're in a PaintToDevice call, where only a MetaFile is recorded, 333cdf0e10cSrcweir // but no actual painting happens, so our "DrawText( Point, ... )" is never called 334cdf0e10cSrcweir // In this case, calculate the rect from what OutputDevice::GetTextRect would give us. This has 335cdf0e10cSrcweir // the disadvantage of less accuracy, compared with the approach to calculate the rect from the 336cdf0e10cSrcweir // single "DrawText( Point, ... )" calls, since more intermediate arithmetics will translate 337cdf0e10cSrcweir // from ref- to target-units. 338cdf0e10cSrcweir aTextRect = m_rTargetDevice.GetTextRect( aRect, _rText, _nStyle, NULL, this ); 339cdf0e10cSrcweir } 340cdf0e10cSrcweir 341cdf0e10cSrcweir // similar to above, the text rect now contains TWIPs (or whatever unit the ref device has), but the caller 342cdf0e10cSrcweir // expects pixel coordinates 343cdf0e10cSrcweir aTextRect = m_rTargetDevice.LogicToPixel( aTextRect ); 344cdf0e10cSrcweir 345cdf0e10cSrcweir // convert the metric vector 346cdf0e10cSrcweir if ( _pVector ) 347cdf0e10cSrcweir { 348cdf0e10cSrcweir for ( MetricVector::iterator charRect = _pVector->begin(); 349cdf0e10cSrcweir charRect != _pVector->end(); 350cdf0e10cSrcweir ++charRect 351cdf0e10cSrcweir ) 352cdf0e10cSrcweir { 353cdf0e10cSrcweir *charRect = m_rTargetDevice.LogicToPixel( *charRect ); 354cdf0e10cSrcweir } 355cdf0e10cSrcweir } 356cdf0e10cSrcweir 357cdf0e10cSrcweir return aTextRect; 358cdf0e10cSrcweir } 359cdf0e10cSrcweir 360cdf0e10cSrcweir //==================================================================== 361cdf0e10cSrcweir //= ControlTextRenderer 362cdf0e10cSrcweir //==================================================================== 363cdf0e10cSrcweir //-------------------------------------------------------------------- ControlTextRenderer(const Control & _rControl,OutputDevice & _rTargetDevice,OutputDevice & _rReferenceDevice)364cdf0e10cSrcweir ControlTextRenderer::ControlTextRenderer( const Control& _rControl, OutputDevice& _rTargetDevice, OutputDevice& _rReferenceDevice ) 365cdf0e10cSrcweir :m_pImpl( new ReferenceDeviceTextLayout( _rControl, _rTargetDevice, _rReferenceDevice ) ) 366cdf0e10cSrcweir { 367cdf0e10cSrcweir } 368cdf0e10cSrcweir 369cdf0e10cSrcweir //-------------------------------------------------------------------- ~ControlTextRenderer()370cdf0e10cSrcweir ControlTextRenderer::~ControlTextRenderer() 371cdf0e10cSrcweir { 372cdf0e10cSrcweir } 373cdf0e10cSrcweir 374cdf0e10cSrcweir //-------------------------------------------------------------------- DrawText(const Rectangle & _rRect,const XubString & _rText,sal_uInt16 _nStyle,MetricVector * _pVector,String * _pDisplayText)375cdf0e10cSrcweir Rectangle ControlTextRenderer::DrawText( const Rectangle& _rRect, const XubString& _rText, sal_uInt16 _nStyle, 376cdf0e10cSrcweir MetricVector* _pVector, String* _pDisplayText ) 377cdf0e10cSrcweir { 378cdf0e10cSrcweir return m_pImpl->DrawText( _rRect, _rText, _nStyle, _pVector, _pDisplayText ); 379cdf0e10cSrcweir } 380cdf0e10cSrcweir 381cdf0e10cSrcweir //........................................................................ 382cdf0e10cSrcweir } // namespace vcl 383cdf0e10cSrcweir //........................................................................ 384