basegfx/Library_basegfx.mk                                   |    3 
 basegfx/source/polygon/WaveLine.cxx                          |   52 ++++++++++
 drawinglayer/source/processor2d/helperwrongspellrenderer.cxx |    6 -
 editeng/source/editeng/impedit3.cxx                          |    7 +
 include/basegfx/polygon/WaveLine.hxx                         |   41 ++++++++
 include/vcl/outdev/ScopedStates.hxx                          |   41 ++++++++
 sw/source/core/txtnode/fntcache.cxx                          |   11 +-
 vcl/source/outdev/textline.cxx                               |   56 ++++++-----
 8 files changed, 186 insertions(+), 31 deletions(-)

New commits:
commit bfc19d77cb8db445f1c6123347c19a4c0c6a6cf8
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Fri Jun 28 00:03:19 2019 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Mon Jul 1 04:49:07 2019 +0200

    Improve the looks of a wave line by draw it with bezier curves
    
    This adds drawing the wave line (typically used to underline the
    wrongly spelled words) with bezier curves. Previously the wave
    lines were drawn with drawing pixels, which didn't look that good,
    especially on HiDPI display, so the looks of wave lines now is
    therefor much better.
    
    The creation of the wave line as a polygon has been added to the
    basegfx module, so it can be reused if needed.
    
    In addition, everytime we draw the waveline, we have to enable
    antialiasing, to have a much better quality of the curves. By
    default the antialiasing is disabled for some reason.
    
    This also adds ScopedStates.hxx file which currently includes
    ScopedAntialiasing, which sets the antialiasing to a certain state
    for the time the object is in scope, and then sets it back to the
    original state.
    
    Change-Id: I4b866fc5d69725eb7f6f78a1acf4176b1205aa73
    Reviewed-on: https://gerrit.libreoffice.org/74810
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/basegfx/Library_basegfx.mk b/basegfx/Library_basegfx.mk
index 4a89d4995583..8ba2fb7cb32c 100644
--- a/basegfx/Library_basegfx.mk
+++ b/basegfx/Library_basegfx.mk
@@ -39,7 +39,7 @@ $(eval $(call gb_Library_add_exception_objects,basegfx,\
     basegfx/source/matrix/b2dhommatrixtools \
     basegfx/source/matrix/b3dhommatrix \
     basegfx/source/matrix/b3dhommatrixtools \
-       basegfx/source/numeric/ftools \
+    basegfx/source/numeric/ftools \
     basegfx/source/point/b2dpoint \
     basegfx/source/point/b2ipoint \
     basegfx/source/point/b3dpoint \
@@ -58,6 +58,7 @@ $(eval $(call gb_Library_add_exception_objects,basegfx,\
     basegfx/source/polygon/b3dpolygontools \
     basegfx/source/polygon/b3dpolypolygon \
     basegfx/source/polygon/b3dpolypolygontools \
+    basegfx/source/polygon/WaveLine \
     basegfx/source/range/b2dpolyrange \
     basegfx/source/range/b2drange \
     basegfx/source/range/b2drangeclipper \
diff --git a/basegfx/source/polygon/WaveLine.cxx 
b/basegfx/source/polygon/WaveLine.cxx
new file mode 100644
index 000000000000..8385cef7be1b
--- /dev/null
+++ b/basegfx/source/polygon/WaveLine.cxx
@@ -0,0 +1,52 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#include <basegfx/polygon/WaveLine.hxx>
+#include <basegfx/point/b2dpoint.hxx>
+
+namespace basegfx
+{
+BASEGFX_DLLPUBLIC B2DPolygon createWaveLinePolygon(basegfx::B2DRectangle 
const& rRectangle)
+{
+    basegfx::B2DPolygon aPolygon;
+
+    double fWaveHeight = rRectangle.getHeight();
+    // Wavelength depends on the wave height so it looks nice
+    double fHalfWaveLength = fWaveHeight + 1.0;
+    double fWaveAmplitude = fWaveHeight / 2.0;
+
+    double fLastX = rRectangle.getMinX();
+    double fBaseY = rRectangle.getMinY() + fWaveAmplitude;
+    double fDirection = 1.0;
+
+    // In quadratic bezier the curve is 1/2 of the control height
+    // so we need to compensate for that.
+    double fHeightCompensation = 2.0;
+
+    aPolygon.append(basegfx::B2DPoint(fLastX, fBaseY));
+
+    for (double fI = fHalfWaveLength; fI <= rRectangle.getWidth(); fI += 
fHalfWaveLength)
+    {
+        basegfx::B2DPoint aPoint(fLastX + fHalfWaveLength, fBaseY);
+        basegfx::B2DPoint aControl(fLastX + (fHalfWaveLength / 2.0),
+                                   fBaseY + fDirection * fWaveAmplitude * 
fHeightCompensation);
+
+        aPolygon.appendQuadraticBezierSegment(aControl, aPoint);
+
+        fLastX = aPoint.getX(); // next iteration
+        fDirection *= -1.0; // fDirection iterates between 1 and -1
+    }
+
+    return aPolygon;
+}
+
+} // end of namespace basegfx
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx 
b/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx
index d690a77b6728..c359b3485bc6 100644
--- a/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx
+++ b/drawinglayer/source/processor2d/helperwrongspellrenderer.cxx
@@ -22,10 +22,9 @@
 #include <tools/gen.hxx>
 #include <vcl/outdev.hxx>
 #include <basegfx/color/bcolormodifier.hxx>
+#include <vcl/outdev/ScopedStates.hxx>
 
-
-using namespace com::sun::star;
-
+using namespace css;
 
 namespace drawinglayer
 {
@@ -55,6 +54,7 @@ namespace drawinglayer
             const basegfx::BColor 
aProcessedColor(rBColorModifierStack.getModifiedColor(rWrongSpellCandidate.getColor()));
             const bool bMapModeEnabledState(rOutputDevice.IsMapModeEnabled());
 
+            vcl::ScopedAntialiasing a(rOutputDevice, true);
             rOutputDevice.EnableMapMode(false);
             rOutputDevice.SetLineColor(Color(aProcessedColor));
             rOutputDevice.SetFillColor();
diff --git a/editeng/source/editeng/impedit3.cxx 
b/editeng/source/editeng/impedit3.cxx
index 1e0b4e51feb5..976a94ea2f1a 100644
--- a/editeng/source/editeng/impedit3.cxx
+++ b/editeng/source/editeng/impedit3.cxx
@@ -77,6 +77,8 @@
 #include <comphelper/lok.hxx>
 #include <memory>
 
+#include <vcl/outdev/ScopedStates.hxx>
+
 using namespace ::com::sun::star;
 using namespace ::com::sun::star::uno;
 using namespace ::com::sun::star::beans;
@@ -223,7 +225,10 @@ static void lcl_DrawRedLines( OutputDevice* pOutDev,
             aPoint2 = Rotate(aPoint2, nOrientation, rOrigin);
         }
 
-        pOutDev->DrawWaveLine(aPoint1, aPoint2);
+        {
+            vcl::ScopedAntialiasing a(*pOutDev, true);
+            pOutDev->DrawWaveLine(aPoint1, aPoint2);
+        }
 
         nStart = nEnd + 1;
         if (nEnd < nMaxEnd)
diff --git a/include/basegfx/polygon/WaveLine.hxx 
b/include/basegfx/polygon/WaveLine.hxx
new file mode 100644
index 000000000000..9d703165b212
--- /dev/null
+++ b/include/basegfx/polygon/WaveLine.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#ifndef INCLUDED_BASEGFX_POLYGON_WAVELINE_HXX
+#define INCLUDED_BASEGFX_POLYGON_WAVELINE_HXX
+
+#include <basegfx/basegfxdllapi.h>
+#include <basegfx/polygon/b2dpolygon.hxx>
+#include <basegfx/range/b2drectangle.hxx>
+
+namespace basegfx
+{
+// Creates a polygon of a wave line in the input rectangle.
+//
+// The polygon is created with points at the center of the rectangle,
+// and the quadratic control points at the upper and lower side. See
+// the diagram below.
+//
+// *----Q---------------Q------------*
+// |                                 |
+// |P-------P-------P-------P-------P|
+// |                                 |
+// *------------Q---------------Q----*
+//
+// P is the point
+// Q is the quadratic bezier control point
+//
+BASEGFX_DLLPUBLIC B2DPolygon createWaveLinePolygon(basegfx::B2DRectangle 
const& rRectangle);
+
+} // end of namespace basegfx
+
+#endif // INCLUDED_BASEGFX_POLYGON_WAVELINE_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/vcl/outdev/ScopedStates.hxx 
b/include/vcl/outdev/ScopedStates.hxx
new file mode 100644
index 000000000000..b64167587885
--- /dev/null
+++ b/include/vcl/outdev/ScopedStates.hxx
@@ -0,0 +1,41 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ */
+
+#ifndef INCLUDED_VCL_SCOPEDSTATES_HXX
+#define INCLUDED_VCL_SCOPEDSTATES_HXX
+
+#include <vcl/outdev.hxx>
+
+namespace vcl
+{
+class ScopedAntialiasing
+{
+private:
+    OutputDevice& m_rOutputDevice;
+    AntialiasingFlags m_nPreviousAAState;
+
+public:
+    ScopedAntialiasing(OutputDevice& rOutputDevice, bool bAAState)
+        : m_rOutputDevice(rOutputDevice)
+        , m_nPreviousAAState(m_rOutputDevice.GetAntialiasing())
+    {
+        if (bAAState)
+            rOutputDevice.SetAntialiasing(m_nPreviousAAState | 
AntialiasingFlags::EnableB2dDraw);
+        else
+            rOutputDevice.SetAntialiasing(m_nPreviousAAState & 
~AntialiasingFlags::EnableB2dDraw);
+    }
+
+    ~ScopedAntialiasing() { 
m_rOutputDevice.SetAntialiasing(m_nPreviousAAState); }
+};
+}
+
+#endif // INCLUDED_VCL_SCOPEDSTATES_HXX
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/txtnode/fntcache.cxx 
b/sw/source/core/txtnode/fntcache.cxx
index 871f9ce655ca..a73ebe3ce9ec 100644
--- a/sw/source/core/txtnode/fntcache.cxx
+++ b/sw/source/core/txtnode/fntcache.cxx
@@ -58,6 +58,7 @@
 #include <docsh.hxx>
 #include <strings.hrc>
 #include <fntcap.hxx>
+#include <vcl/outdev/ScopedStates.hxx>
 
 using namespace ::com::sun::star;
 
@@ -786,14 +787,14 @@ static void lcl_DrawLineForWrongListData(
             {
                 if (WRONGAREA_WAVE == wrongArea->mLineType)
                 {
+                    vcl::ScopedAntialiasing a(rInf.GetOut(), true);
                     rInf.GetOut().SetLineColor( wrongArea->mColor );
-
                     rInf.GetOut().DrawWaveLine( aStart, aEnd, 1 );
                 }
                 else if (WRONGAREA_BOLDWAVE == wrongArea->mLineType)
                 {
+                    vcl::ScopedAntialiasing a(rInf.GetOut(), true);
                     rInf.GetOut().SetLineColor( wrongArea->mColor );
-
                     rInf.GetOut().DrawWaveLine( aStart, aEnd, 2 );
                 }
                 else if (WRONGAREA_BOLD == wrongArea->mLineType)
@@ -1781,8 +1782,10 @@ void SwFntObj::DrawText( SwDrawTextInfo &rInf )
                             rInf.GetFrame()->SwitchHorizontalToVertical( 
aCurrPos );
                             rInf.GetFrame()->SwitchHorizontalToVertical( aEnd 
);
                         }
-                        rInf.GetOut().DrawWaveLine( aCurrPos, aEnd );
-
+                        {
+                            vcl::ScopedAntialiasing a(rInf.GetOut(), true);
+                            rInf.GetOut().DrawWaveLine( aCurrPos, aEnd );
+                        }
                         if ( bColSave )
                             rInf.GetOut().SetLineColor( aCol );
 
diff --git a/vcl/source/outdev/textline.cxx b/vcl/source/outdev/textline.cxx
index 67feda6c4030..4290044edeb1 100644
--- a/vcl/source/outdev/textline.cxx
+++ b/vcl/source/outdev/textline.cxx
@@ -34,6 +34,10 @@
 #include <outdata.hxx>
 #include <impglyphitem.hxx>
 
+#include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <basegfx/polygon/WaveLine.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+
 #define UNDERLINE_LAST      LINESTYLE_BOLDWAVE
 #define STRIKEOUT_LAST      STRIKEOUT_X
 
@@ -936,7 +940,7 @@ void OutputDevice::DrawTextLine( const Point& rPos, long 
nWidth,
         mpAlphaVDev->DrawTextLine( rPos, nWidth, eStrikeout, eUnderline, 
eOverline, bUnderlineAbove );
 }
 
-void OutputDevice::DrawWaveLine( const Point& rStartPos, const Point& rEndPos, 
long nLineWidth )
+void OutputDevice::DrawWaveLine(const Point& rStartPos, const Point& rEndPos, 
long nLineWidth)
 {
     assert(!is_double_buffered_window());
 
@@ -956,30 +960,29 @@ void OutputDevice::DrawWaveLine( const Point& rStartPos, 
const Point& rEndPos, l
     if (!InitFont())
         return;
 
-    Point   aStartPt = ImplLogicToDevicePixel( rStartPos );
-    Point   aEndPt = ImplLogicToDevicePixel( rEndPos );
-    long    nStartX = aStartPt.X();
-    long    nStartY = aStartPt.Y();
-    long    nEndX = aEndPt.X();
-    long    nEndY = aEndPt.Y();
-    short   nOrientation = 0;
+    Point aStartPt = ImplLogicToDevicePixel(rStartPos);
+    Point aEndPt = ImplLogicToDevicePixel(rEndPos);
+
+    long nStartX = aStartPt.X();
+    long nStartY = aStartPt.Y();
+    long nEndX = aEndPt.X();
+    long nEndY = aEndPt.Y();
+    double fOrientation = 0.0;
 
-    // when rotated
-    if ( (nStartY != nEndY) || (nStartX > nEndX) )
+    // handle rotation
+    if (nStartY != nEndY || nStartX > nEndX)
     {
-        long nDX = nEndX - nStartX;
-        double nO = atan2( -nEndY + nStartY, ((nDX == 0) ? 0.000000001 : nDX) 
);
-        nO /= F_PI1800;
-        nOrientation = static_cast<short>(nO);
-        aStartPt.RotateAround( nEndX, nEndY, -nOrientation );
+        long nLengthX = nEndX - nStartX;
+        fOrientation = std::atan2(nStartY - nEndY, (nLengthX == 0 ? 
0.000000001 : nLengthX));
+        fOrientation /= F_PI180;
+        // un-rotate the end point
+        aStartPt.RotateAround(nEndX, nEndY, -fOrientation * 10.0);
     }
 
     long nWaveHeight = 3;
-    nStartY++;
-    nEndY++;
 
+    // Handle HiDPI
     float fScaleFactor = GetDPIScaleFactor();
-
     if (fScaleFactor > 1.0f)
     {
         nWaveHeight *= fScaleFactor;
@@ -995,14 +998,23 @@ void OutputDevice::DrawWaveLine( const Point& rStartPos, 
const Point& rEndPos, l
 
     // #109280# make sure the waveline does not exceed the descent to avoid 
paint problems
     LogicalFontInstance* pFontInstance = mpFontInstance.get();
-    if( nWaveHeight > pFontInstance->mxFontMetric->GetWavelineUnderlineSize() )
+    if (nWaveHeight > pFontInstance->mxFontMetric->GetWavelineUnderlineSize())
     {
         nWaveHeight = pFontInstance->mxFontMetric->GetWavelineUnderlineSize();
         nLineWidth = 1;
     }
-    ImplDrawWaveLine(nStartX, nStartY, 0, 0,
-                     nEndX-nStartX, nWaveHeight,
-                     nLineWidth, nOrientation, GetLineColor());
+
+    const basegfx::B2DRectangle aWaveLineRectangle(nStartX, nStartY, nEndX, 
nEndY + nWaveHeight);
+    const basegfx::B2DPolygon aWaveLinePolygon = 
basegfx::createWaveLinePolygon(aWaveLineRectangle);
+    const basegfx::B2DHomMatrix aRotationMatrix = 
basegfx::utils::createRotateAroundPoint(nStartX, nStartY, 
basegfx::deg2rad(-fOrientation));
+    const basegfx::B2DVector aLineWidth(nLineWidth, nLineWidth);
+    const bool bPixelSnapHairline(mnAntialiasing & 
AntialiasingFlags::PixelSnapHairline);
+
+    mpGraphics->SetLineColor(GetLineColor());
+    mpGraphics->DrawPolyLine(
+            aRotationMatrix, aWaveLinePolygon, 0.0, aLineWidth,
+            basegfx::B2DLineJoin::NONE, css::drawing::LineCap_BUTT,
+            basegfx::deg2rad(15.0), bPixelSnapHairline, this);
 
     if( mpAlphaVDev )
         mpAlphaVDev->DrawWaveLine( rStartPos, rEndPos, nLineWidth );
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to