diff options
-rw-r--r-- | include/vcl/ctrl.hxx | 16 | ||||
-rw-r--r-- | vcl/inc/textlayout.hxx | 7 | ||||
-rw-r--r-- | vcl/source/control/button.cxx | 11 | ||||
-rw-r--r-- | vcl/source/control/ctrl.cxx | 42 | ||||
-rw-r--r-- | vcl/source/control/fixed.cxx | 4 | ||||
-rw-r--r-- | vcl/source/control/tabctrl.cxx | 4 | ||||
-rw-r--r-- | vcl/source/gdi/textlayout.cxx | 56 |
7 files changed, 112 insertions, 28 deletions
diff --git a/include/vcl/ctrl.hxx b/include/vcl/ctrl.hxx index dede22f9d680..605f52cf4b19 100644 --- a/include/vcl/ctrl.hxx +++ b/include/vcl/ctrl.hxx @@ -80,12 +80,18 @@ 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. + return 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, Rectangle& _io_rRect, - const OUString& _rStr, DrawTextFlags _nStyle, - MetricVector* _pVector, OUString* _pDisplayText ) const; + Rectangle DrawControlText( OutputDevice& _rTargetDevice, const Rectangle& _rRect, + const OUString& _rStr, DrawTextFlags _nStyle, + MetricVector* _pVector, OUString* _pDisplayText, + const Size* i_pDeviceSize = nullptr ) const; + + Rectangle GetControlTextRect( OutputDevice& _rTargetDevice, const Rectangle & rRect, + const OUString& _rStr, DrawTextFlags _nStyle, + Size* o_pDeviceSize = nullptr ) const; virtual const vcl::Font& GetCanonicalFont( const StyleSettings& _rStyle ) const; diff --git a/vcl/inc/textlayout.hxx b/vcl/inc/textlayout.hxx index f057c5c3dd1d..b858a67fdbe6 100644 --- a/vcl/inc/textlayout.hxx +++ b/vcl/inc/textlayout.hxx @@ -91,8 +91,11 @@ namespace vcl virtual ~ControlTextRenderer(); Rectangle DrawText( const Rectangle& _rRect, - const OUString& _rText, DrawTextFlags _nStyle = DrawTextFlags::NONE, - MetricVector* _pVector = nullptr, OUString* _pDisplayText = nullptr ); + const OUString& _rText, DrawTextFlags _nStyle, + MetricVector* _pVector, OUString* _pDisplayText, const Size* i_pDeviceSize ); + + Rectangle GetTextRect( const Rectangle& _rRect, + const OUString& _rText, DrawTextFlags _nStyle, Size* o_pDeviceSize ); private: ControlTextRenderer( const ControlTextRenderer& ) = delete; diff --git a/vcl/source/control/button.cxx b/vcl/source/control/button.cxx index 570354afd892..8c95f2de8ea9 100644 --- a/vcl/source/control/button.cxx +++ b/vcl/source/control/button.cxx @@ -285,7 +285,7 @@ void Button::ImplDrawAlignedImage(OutputDevice* pDev, Point& rPos, } else if (bDrawText && !bDrawImage && !bHasSymbol) { - DrawControlText(*pDev, aOutRect, aText, nTextStyle, nullptr, nullptr); + aOutRect = DrawControlText(*pDev, aOutRect, aText, nTextStyle, nullptr, nullptr); ImplSetFocusRect(aOutRect); rSize = aOutRect.GetSize(); @@ -299,6 +299,7 @@ void Button::ImplDrawAlignedImage(OutputDevice* pDev, Point& rPos, Size aTextSize; Size aSymbolSize; + Size aDeviceTextSize; Size aMax; Point aImagePos = rPos; Point aTextPos = rPos; @@ -358,7 +359,7 @@ void Button::ImplDrawAlignedImage(OutputDevice* pDev, Point& rPos, aRect.Bottom() -= (aImageSize.Height() + nImageSep); } - aRect = pDev->GetTextRect(aRect, aText, nTextStyle); + aRect = GetControlTextRect(*pDev, aRect, aText, nTextStyle, &aDeviceTextSize); aTextSize = aRect.GetSize(); aTSSize.Width() += aTextSize.Width(); @@ -510,9 +511,9 @@ void Button::ImplDrawAlignedImage(OutputDevice* pDev, Point& rPos, if (bDrawText) { - Rectangle aTOutRect( aTextPos, aTextSize ); - ImplSetFocusRect( aTOutRect ); - DrawControlText( *pDev, aTOutRect, aText, nTextStyle, nullptr, nullptr ); + const Rectangle aTOutRect(aTextPos, aTextSize); + ImplSetFocusRect(aTOutRect); + DrawControlText(*pDev, aTOutRect, aText, nTextStyle, nullptr, nullptr, &aDeviceTextSize); } else { diff --git a/vcl/source/control/ctrl.cxx b/vcl/source/control/ctrl.cxx index 72ee5948a50e..92e16e66c86e 100644 --- a/vcl/source/control/ctrl.cxx +++ b/vcl/source/control/ctrl.cxx @@ -439,8 +439,8 @@ void Control::ImplInitSettings(const bool, const bool) ApplySettings(*this); } -void Control::DrawControlText( OutputDevice& _rTargetDevice, Rectangle& _io_rRect, const OUString& _rStr, - DrawTextFlags _nStyle, MetricVector* _pVector, OUString* _pDisplayText ) const +Rectangle Control::DrawControlText( OutputDevice& _rTargetDevice, const Rectangle& rRect, const OUString& _rStr, + DrawTextFlags _nStyle, MetricVector* _pVector, OUString* _pDisplayText, const Size* i_pDeviceSize ) const { OUString rPStr = _rStr; DrawTextFlags nPStyle = _nStyle; @@ -456,14 +456,42 @@ void Control::DrawControlText( OutputDevice& _rTargetDevice, Rectangle& _io_rRec if ( !mpControlData->mpReferenceDevice || ( mpControlData->mpReferenceDevice == &_rTargetDevice ) ) { - _io_rRect = _rTargetDevice.GetTextRect( _io_rRect, rPStr, nPStyle ); - _rTargetDevice.DrawText( _io_rRect, rPStr, nPStyle, _pVector, _pDisplayText ); + const Rectangle aRet = _rTargetDevice.GetTextRect(rRect, rPStr, nPStyle); + _rTargetDevice.DrawText(aRet, rPStr, nPStyle, _pVector, _pDisplayText); + return aRet; } - else + + ControlTextRenderer aRenderer( *this, _rTargetDevice, *mpControlData->mpReferenceDevice ); + return aRenderer.DrawText(rRect, rPStr, nPStyle, _pVector, _pDisplayText, i_pDeviceSize); +} + +Rectangle Control::GetControlTextRect( OutputDevice& _rTargetDevice, const Rectangle & rRect, + const OUString& _rStr, DrawTextFlags _nStyle, Size* o_pDeviceSize ) const +{ + OUString rPStr = _rStr; + DrawTextFlags nPStyle = _nStyle; + + bool accel = ImplGetSVData()->maNWFData.mbEnableAccel; + bool autoacc = ImplGetSVData()->maNWFData.mbAutoAccel; + + if (!accel || (autoacc && !mbShowAccelerator)) + { + rPStr = GetNonMnemonicString( _rStr ); + nPStyle &= ~DrawTextFlags::HideMnemonic; + } + + if ( !mpControlData->mpReferenceDevice || ( mpControlData->mpReferenceDevice == &_rTargetDevice ) ) { - ControlTextRenderer aRenderer( *this, _rTargetDevice, *mpControlData->mpReferenceDevice ); - _io_rRect = aRenderer.DrawText( _io_rRect, rPStr, nPStyle, _pVector, _pDisplayText ); + Rectangle aRet = _rTargetDevice.GetTextRect( rRect, rPStr, nPStyle ); + if (o_pDeviceSize) + { + *o_pDeviceSize = aRet.GetSize(); + } + return aRet; } + + ControlTextRenderer aRenderer( *this, _rTargetDevice, *mpControlData->mpReferenceDevice ); + return aRenderer.GetTextRect(rRect, rPStr, nPStyle, o_pDeviceSize); } Font diff --git a/vcl/source/control/fixed.cxx b/vcl/source/control/fixed.cxx index 98532d8c4771..f90ee89c32d2 100644 --- a/vcl/source/control/fixed.cxx +++ b/vcl/source/control/fixed.cxx @@ -197,7 +197,7 @@ void FixedText::ImplDraw(OutputDevice* pDev, DrawFlags nDrawFlags, if( bFillLayout ) (mpControlData->mpLayoutData->m_aDisplayText).clear(); - Rectangle aRect( Rectangle( aPos, rSize ) ); + const Rectangle aRect(aPos, rSize); DrawControlText(*pDev, aRect, aText, nTextStyle, bFillLayout ? &mpControlData->mpLayoutData->m_aUnicodeBoundRects : nullptr, bFillLayout ? &mpControlData->mpLayoutData->m_aDisplayText : nullptr); @@ -572,7 +572,7 @@ void FixedLine::ImplDraw(vcl::RenderContext& rRenderContext) if (rStyleSettings.GetOptions() & StyleSettingsOptions::Mono) nStyle |= DrawTextFlags::Mono; - DrawControlText(*this, aRect, aText, nStyle, nullptr, nullptr); + aRect = DrawControlText(*this, aRect, aText, nStyle, nullptr, nullptr); long nTop = aRect.Top() + ((aRect.GetHeight() - 1) / 2); aDecoView.DrawSeparator(Point(aRect.Right() + FIXEDLINE_TEXT_BORDER, nTop), Point(aOutSize.Width() - 1, nTop), false); diff --git a/vcl/source/control/tabctrl.cxx b/vcl/source/control/tabctrl.cxx index fd5d14f5e929..10253bca96f8 100644 --- a/vcl/source/control/tabctrl.cxx +++ b/vcl/source/control/tabctrl.cxx @@ -938,8 +938,8 @@ void TabControl::ImplDrawItem(vcl::RenderContext& rRenderContext, ImplTabItem* p Color aOldColor(rRenderContext.GetTextColor()); rRenderContext.SetTextColor(aColor); - Rectangle aOutRect(nXPos + aImageSize.Width(), nYPos, - nXPos + aImageSize.Width() + nTextWidth, nYPos + nTextHeight); + const Rectangle aOutRect(nXPos + aImageSize.Width(), nYPos, + nXPos + aImageSize.Width() + nTextWidth, nYPos + nTextHeight); DrawControlText(rRenderContext, aOutRect, pItem->maFormatText, nStyle, nullptr, nullptr); diff --git a/vcl/source/gdi/textlayout.cxx b/vcl/source/gdi/textlayout.cxx index a28eaf752e5c..4f459b6d33c9 100644 --- a/vcl/source/gdi/textlayout.cxx +++ b/vcl/source/gdi/textlayout.cxx @@ -84,8 +84,8 @@ namespace vcl public: // equivalents to the respective OutputDevice methods, which take the reference device into account - long GetTextArray( const OUString& _rText, long* _pDXAry, sal_Int32 _nStartIndex, sal_Int32 _nLength ) const; - Rectangle DrawText( const Rectangle& _rRect, const OUString& _rText, DrawTextFlags _nStyle, MetricVector* _pVector, OUString* _pDisplayText ); + Rectangle DrawText( const Rectangle& _rRect, const OUString& _rText, DrawTextFlags _nStyle, MetricVector* _pVector, OUString* _pDisplayText, const Size* i_pDeviceSize ); + Rectangle GetTextRect( const Rectangle& _rRect, const OUString& _rText, DrawTextFlags _nStyle, Size* o_pDeviceSize ); protected: void onBeginDrawText() @@ -98,6 +98,8 @@ namespace vcl } private: + long GetTextArray( const OUString& _rText, long* _pDXAry, sal_Int32 _nStartIndex, sal_Int32 _nLength ) const; + OutputDevice& m_rTargetDevice; OutputDevice& m_rReferenceDevice; Font m_aUnzoomedPointFont; @@ -252,7 +254,8 @@ namespace vcl return true; } - Rectangle ReferenceDeviceTextLayout::DrawText( const Rectangle& _rRect, const OUString& _rText, DrawTextFlags _nStyle, MetricVector* _pVector, OUString* _pDisplayText ) + Rectangle ReferenceDeviceTextLayout::DrawText( const Rectangle& _rRect, const OUString& _rText, DrawTextFlags _nStyle, + MetricVector* _pVector, OUString* _pDisplayText, const Size* i_pDeviceSize ) { if ( _rText.isEmpty() ) return Rectangle(); @@ -267,6 +270,13 @@ namespace vcl // and the like in our ctor, we set the map mode of the target device from pixel to twip, but our caller doesn't know this, // but passed pixel coordinates. So, adjust the rect. Rectangle aRect( m_rTargetDevice.PixelToLogic( _rRect ) ); + if (i_pDeviceSize) + { + //if i_pDeviceSize is passed in here, it was the original pre logic-to-pixel size of _rRect + SAL_WARN_IF(std::abs(_rRect.GetSize().Width() - m_rTargetDevice.LogicToPixel(*i_pDeviceSize).Width()) > 1, "vcl", "DeviceSize width was expected to match Pixel width"); + SAL_WARN_IF(std::abs(_rRect.GetSize().Height() - m_rTargetDevice.LogicToPixel(*i_pDeviceSize).Height()) > 1, "vcl", "DeviceSize height was expected to match Pixel height"); + aRect.SetSize(*i_pDeviceSize); + } onBeginDrawText(); m_rTargetDevice.DrawText( aRect, _rText, _nStyle, _pVector, _pDisplayText, this ); @@ -302,6 +312,37 @@ namespace vcl return aTextRect; } + Rectangle ReferenceDeviceTextLayout::GetTextRect( const Rectangle& _rRect, const OUString& _rText, DrawTextFlags _nStyle, Size* o_pDeviceSize ) + { + if ( _rText.isEmpty() ) + return Rectangle(); + + // determine text layout mode from the RTL-ness of the control whose text we render + ComplexTextLayoutMode nTextLayoutMode = m_bRTLEnabled ? TEXT_LAYOUT_BIDI_RTL : TEXT_LAYOUT_DEFAULT; + m_rReferenceDevice.SetLayoutMode( nTextLayoutMode ); + m_rTargetDevice.SetLayoutMode( nTextLayoutMode | TEXT_LAYOUT_TEXTORIGIN_LEFT ); + + // TEXT_LAYOUT_TEXTORIGIN_LEFT is because when we do actually draw the text (in DrawText( Point, ... )), then + // our caller gives us the left border of the draw position, regardless of script type, text layout, + // and the like in our ctor, we set the map mode of the target device from pixel to twip, but our caller doesn't know this, + // but passed pixel coordinates. So, adjust the rect. + Rectangle aRect( m_rTargetDevice.PixelToLogic( _rRect ) ); + + Rectangle aTextRect = m_rTargetDevice.GetTextRect( aRect, _rText, _nStyle, nullptr, this ); + + //if o_pDeviceSize is available, stash the pre logic-to-pixel size in it + if (o_pDeviceSize) + { + *o_pDeviceSize = aTextRect.GetSize(); + } + + // similar to above, the text rect now contains TWIPs (or whatever unit the ref device has), but the caller + // expects pixel coordinates + aTextRect = m_rTargetDevice.LogicToPixel( aTextRect ); + + return aTextRect; + } + ControlTextRenderer::ControlTextRenderer( const Control& _rControl, OutputDevice& _rTargetDevice, OutputDevice& _rReferenceDevice ) :m_pImpl( new ReferenceDeviceTextLayout( _rControl, _rTargetDevice, _rReferenceDevice ) ) { @@ -312,9 +353,14 @@ namespace vcl } Rectangle ControlTextRenderer::DrawText( const Rectangle& _rRect, const OUString& _rText, DrawTextFlags _nStyle, - MetricVector* _pVector, OUString* _pDisplayText ) + MetricVector* _pVector, OUString* _pDisplayText, const Size* i_pDeviceSize ) + { + return m_pImpl->DrawText( _rRect, _rText, _nStyle, _pVector, _pDisplayText, i_pDeviceSize ); + } + + Rectangle ControlTextRenderer::GetTextRect( const Rectangle& _rRect, const OUString& _rText, DrawTextFlags _nStyle, Size* o_pDeviceSize = nullptr ) { - return m_pImpl->DrawText( _rRect, _rText, _nStyle, _pVector, _pDisplayText ); + return m_pImpl->GetTextRect( _rRect, _rText, _nStyle, o_pDeviceSize ); } } // namespace vcl |