[Libreoffice-commits] core.git: include/vcl vcl/inc vcl/source

Caolán McNamara caolanm at redhat.com
Wed Jan 18 20:43:43 UTC 2017


 include/vcl/ctrl.hxx          |    9 +++++--
 vcl/inc/textlayout.hxx        |    5 +++
 vcl/source/control/button.cxx |    5 ++-
 vcl/source/control/ctrl.cxx   |   33 ++++++++++++++++++++++++--
 vcl/source/gdi/textlayout.cxx |   53 ++++++++++++++++++++++++++++++++++++++----
 5 files changed, 94 insertions(+), 11 deletions(-)

New commits:
commit db9ef688edd86b31606e0dd6df6a77732faca49b
Author: Caolán McNamara <caolanm at redhat.com>
Date:   Wed Jan 18 17:17:09 2017 +0000

    Resolves: tdf#98593 buttons in writer show different text at different zooms
    
    The DrawControlText always renders with a reference device positions but
    we pass in a rectangle which is derived a different way.
    
    So, add a GetControlTextRect which operates on the same reference
    device as DrawControlText so the rectangles match
    
    The rectangle is mapped from pixels to logic and back from logic
    to pixel, so add an argument to store the logic size from
    GetControlTextRect and re-use it without conversion on the cases
    where we pass back the original rectangle
    
    zooming in/out on the button in writer is now stable wrt text shown at all zoom
    levels
    
    Change-Id: Ic581eca67d0ff265e2753ab8b6c40e8fca7e6ae4
    Reviewed-on: https://gerrit.libreoffice.org/33277
    Tested-by: Jenkins <ci at libreoffice.org>
    Reviewed-by: Caolán McNamara <caolanm at redhat.com>
    Tested-by: Caolán McNamara <caolanm at redhat.com>

diff --git a/include/vcl/ctrl.hxx b/include/vcl/ctrl.hxx
index 2f93f64..c6b60ef 100644
--- a/include/vcl/ctrl.hxx
+++ b/include/vcl/ctrl.hxx
@@ -85,8 +85,13 @@ protected:
         returning.
     */
     Rectangle DrawControlText( OutputDevice& _rTargetDevice, const Rectangle& _rRect,
-                                 const OUString& _rStr, DrawTextFlags _nStyle,
-                                 MetricVector* _pVector, OUString* _pDisplayText ) const;
+                               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 97350c0..a8a4124 100644
--- a/vcl/inc/textlayout.hxx
+++ b/vcl/inc/textlayout.hxx
@@ -92,7 +92,10 @@ namespace vcl
 
         Rectangle   DrawText( const Rectangle& _rRect,
                               const OUString& _rText, DrawTextFlags _nStyle,
-                              MetricVector* _pVector, OUString* _pDisplayText );
+                              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 91cc0dd..c928010 100644
--- a/vcl/source/control/button.cxx
+++ b/vcl/source/control/button.cxx
@@ -300,6 +300,7 @@ void Button::ImplDrawAlignedImage(OutputDevice* pDev, Point& rPos,
 
     Size aTextSize;
     Size aSymbolSize;
+    Size aDeviceTextSize;
     Size aMax;
     Point aImagePos = rPos;
     Point aTextPos = rPos;
@@ -359,7 +360,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();
@@ -513,7 +514,7 @@ void Button::ImplDrawAlignedImage(OutputDevice* pDev, Point& rPos,
     {
         const Rectangle aTOutRect(aTextPos, aTextSize);
         ImplSetFocusRect(aTOutRect);
-        DrawControlText(*pDev, aTOutRect, aText, nTextStyle, nullptr, nullptr);
+        DrawControlText(*pDev, aTOutRect, aText, nTextStyle, nullptr, nullptr, &aDeviceTextSize);
     }
     else
     {
diff --git a/vcl/source/control/ctrl.cxx b/vcl/source/control/ctrl.cxx
index f75e54f..78b9295 100644
--- a/vcl/source/control/ctrl.cxx
+++ b/vcl/source/control/ctrl.cxx
@@ -413,7 +413,7 @@ void Control::ImplInitSettings(const bool, const bool)
 }
 
 Rectangle Control::DrawControlText( OutputDevice& _rTargetDevice, const Rectangle& rRect, const OUString& _rStr,
-    DrawTextFlags _nStyle, MetricVector* _pVector, OUString* _pDisplayText ) const
+    DrawTextFlags _nStyle, MetricVector* _pVector, OUString* _pDisplayText, const Size* i_pDeviceSize ) const
 {
     OUString rPStr = _rStr;
     DrawTextFlags nPStyle = _nStyle;
@@ -435,7 +435,36 @@ Rectangle Control::DrawControlText( OutputDevice& _rTargetDevice, const Rectangl
     }
 
     ControlTextRenderer aRenderer( *this, _rTargetDevice, *mpControlData->mpReferenceDevice );
-    return aRenderer.DrawText(rRect, rPStr, nPStyle, _pVector, _pDisplayText);
+    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 ) )
+    {
+        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/gdi/textlayout.cxx b/vcl/source/gdi/textlayout.cxx
index 7c9686e..0d0b600 100644
--- a/vcl/source/gdi/textlayout.cxx
+++ b/vcl/source/gdi/textlayout.cxx
@@ -84,7 +84,8 @@ namespace vcl
 
     public:
         // equivalents to the respective OutputDevice methods, which take the reference device into account
-        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 );
 
     private:
         long        GetTextArray( const OUString& _rText, long* _pDXAry, sal_Int32 _nStartIndex, sal_Int32 _nLength ) const;
@@ -243,7 +244,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();
@@ -258,6 +260,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);
+        }
 
         m_aCompleteTextRect.SetEmpty();
         m_rTargetDevice.DrawText( aRect, _rText, _nStyle, _pVector, _pDisplayText, this );
@@ -293,6 +302,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
+        ComplexTextLayoutFlags nTextLayoutMode = m_bRTLEnabled ? ComplexTextLayoutFlags::BiDiRtl : ComplexTextLayoutFlags::Default;
+        m_rReferenceDevice.SetLayoutMode( nTextLayoutMode );
+        m_rTargetDevice.SetLayoutMode( nTextLayoutMode | ComplexTextLayoutFlags::TextOriginLeft );
+
+        // ComplexTextLayoutFlags::TextOriginLeft 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 ) )
     {
@@ -303,9 +343,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


More information about the Libreoffice-commits mailing list