drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx  |  102 +++++++++----
 include/basegfx/curve/b2dcubicbezier.hxx                   |    2 
 include/drawinglayer/primitive2d/wrongspellprimitive2d.hxx |    4 
 3 files changed, 81 insertions(+), 27 deletions(-)

New commits:
commit 8bdddee0897034976bbbea57eedf4c7611228d5d
Author:     Armin Le Grand (Collabora) <armin.le.gr...@me.com>
AuthorDate: Fri Aug 23 14:39:34 2024 +0200
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Fri Aug 23 16:36:59 2024 +0200

    CairoSDPR: Adapt WrongSpell Primitive to View-Independent
    
    Change-Id: If739dd9f28f56874978c7b3a76e1234e5f430c9f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/172319
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx 
b/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx
index 6084814ae71f..b583dd9901a1 100644
--- a/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/wrongspellprimitive2d.cxx
@@ -19,9 +19,10 @@
 
 #include <drawinglayer/primitive2d/wrongspellprimitive2d.hxx>
 #include <basegfx/polygon/b2dpolygon.hxx>
-#include <drawinglayer/primitive2d/PolygonWavePrimitive2D.hxx>
+#include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/curve/b2dcubicbezier.hxx>
+#include <drawinglayer/primitive2d/PolygonHairlinePrimitive2D.hxx>
 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
-#include <drawinglayer/geometry/viewinformation2d.hxx>
 #include <utility>
 
 
@@ -29,43 +30,95 @@ namespace drawinglayer::primitive2d
 {
         Primitive2DReference 
WrongSpellPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& 
/*rViewInformation*/) const
         {
-            // ATM this decompose is view-independent, what the original 
VCL-Display is not. To mimic
-            // the old behaviour here if wanted it is necessary to add 
get2DDecomposition and implement
-            // it similar to the usage in e.g. HelplinePrimitive2D. 
Remembering the ViewTransformation
-            // should be enough then.
-            // The view-independent wavelines work well (if You ask me). Maybe 
the old VCL-Behaviour is only
-            // in place because it was not possible/too expensive at that time 
to scale the wavelines with the
-            // view...
-            // With the VCL-PixelRenderer this will not even be used since it 
implements WrongSpellPrimitive2D
-            // directly and mimics the old VCL-Display there. If You 
implemented a new renderer without
-            // direct WrongSpellPrimitive2D support, You may want to do the 
described change here.
+            // This *was* a view-independent primitive before (see before this 
commit),
+            // but was never really used, but handled in various processors 
anyways.
+            // Since the current VCL primitve renderer and it's functions used 
in
+            // VCL do render this always in one discrete pixel size I decided 
to
+            // adapt this primitive to do that, too, but - due to being a 
primitive -
+            // with the correct invalidate/hit-ranges etc.
+            // I use here DiscreteMetricDependentPrimitive2D which already 
implements
+            // buffering and providing the discrete size using 
'getDiscreteUnit()' plus
+            // the needed updates to buffering, what makes the rest simple.
+            // NOTE: If one day the (in my opinion) also good looking 
view-independent
+            // version should be needed again, just revert this change
+            if (basegfx::fTools::lessOrEqual(getStop(), getStart()))
+            {
+                // stop smaller or equal to start, done
+                return nullptr;
+            }
 
             // get the font height (part of scale), so decompose the matrix
             basegfx::B2DVector aScale, aTranslate;
             double fRotate, fShearX;
             getTransformation().decompose(aScale, aTranslate, fRotate, 
fShearX);
 
+            constexpr double constMinimumFontHeight(5.0);
+            if (aScale.getY() / getDiscreteUnit() < constMinimumFontHeight)
+            {
+                // font height smaller constMinimumFontHeight pixels -> 
decompose to empty
+                return nullptr;
+            }
+
             // calculate distances based on a static default (to allow testing 
in debugger)
             static const double fDefaultDistance(0.03);
             const double fFontHeight(aScale.getY());
             const double fUnderlineDistance(fFontHeight * fDefaultDistance);
-            const double fWaveWidth(2.0 * fUnderlineDistance);
 
             // the Y-distance needs to be relative to FontHeight since the 
points get
             // transformed with the transformation containing that scale 
already.
             const double 
fRelativeUnderlineDistance(basegfx::fTools::equalZero(aScale.getY()) ? 0.0 : 
fUnderlineDistance / aScale.getY());
-            basegfx::B2DPoint aStart(getStart(), fRelativeUnderlineDistance);
-            basegfx::B2DPoint aStop(getStop(), fRelativeUnderlineDistance);
-            basegfx::B2DPolygon aPolygon;
 
-            aPolygon.append(getTransformation() * aStart);
-            aPolygon.append(getTransformation() * aStop);
+            // get start/stop positions and WaveLength, base all calculations 
for discrete
+            // waveline on these initial values
+            basegfx::B2DPoint aStart(getTransformation() * 
basegfx::B2DPoint(getStart(), fRelativeUnderlineDistance));
+            const basegfx::B2DPoint aStop(getTransformation() * 
basegfx::B2DPoint(getStop(), fRelativeUnderlineDistance));
+            const double fWaveLength(getDiscreteUnit() * 8);
+
+            // get pre-calculated vector and controlPoint for one wave segment
+            basegfx::B2DVector aVector(aStop - aStart);
+            double fLength(aVector.getLength());
+            aVector.normalize();
+            basegfx::B2DVector aControl(basegfx::getPerpendicular(aVector));
+            aVector *= fWaveLength;
+            aControl = aControl * (fWaveLength * 0.5) + aVector * 0.5;
+
+            // create geometry
+            basegfx::B2DPolygon aWave;
+            aWave.append(aStart);
+
+            while (fLength > fWaveLength)
+            {
+                // one WaveSegment per WaveLength
+                basegfx::B2DPoint aNew(aStart + aVector);
+                aWave.appendBezierSegment(
+                    aStart + aControl,
+                    aNew - aControl,
+                    aNew);
+                aStart = aNew;
+                fLength -= fWaveLength;
+            }
 
-            // prepare line attribute
-            const attribute::LineAttribute aLineAttribute(getColor());
+            if (fLength > fWaveLength * 0.2)
+            {
+                // if rest is more than 20% of WaveLength, create
+                // remaining snippet and add it
+                basegfx::B2DPoint aNew(aStart + aVector);
+                basegfx::B2DCubicBezier aRest(
+                    aStart,
+                    aStart + aControl,
+                    aNew - aControl,
+                    aNew);
+                aRest = aRest.snippet(0.0, fLength/fWaveLength);
+                aWave.appendBezierSegment(
+                    aRest.getControlPointA(),
+                    aRest.getControlPointB(),
+                    aRest.getEndPoint());
+            }
 
-            // create the waveline primitive
-            return new PolygonWavePrimitive2D(aPolygon, aLineAttribute, 
fWaveWidth, 0.5 * fWaveWidth);
+            // create & return primitive
+            return new PolygonHairlinePrimitive2D(
+                aWave,
+                getColor());
         }
 
         WrongSpellPrimitive2D::WrongSpellPrimitive2D(
@@ -73,7 +126,8 @@ namespace drawinglayer::primitive2d
             double fStart,
             double fStop,
             const basegfx::BColor& rColor)
-        :   maTransformation(std::move(aTransformation)),
+        :   DiscreteMetricDependentPrimitive2D(),
+            maTransformation(std::move(aTransformation)),
             mfStart(fStart),
             mfStop(fStop),
             maColor(rColor)
@@ -82,7 +136,7 @@ namespace drawinglayer::primitive2d
 
         bool WrongSpellPrimitive2D::operator==(const BasePrimitive2D& 
rPrimitive) const
         {
-            if(BufferedDecompositionPrimitive2D::operator==(rPrimitive))
+            if(DiscreteMetricDependentPrimitive2D::operator==(rPrimitive))
             {
                 const WrongSpellPrimitive2D& rCompare = static_cast<const 
WrongSpellPrimitive2D&>(rPrimitive);
 
diff --git a/include/basegfx/curve/b2dcubicbezier.hxx 
b/include/basegfx/curve/b2dcubicbezier.hxx
index 9d79fbeb5f9d..00a46b6333f2 100644
--- a/include/basegfx/curve/b2dcubicbezier.hxx
+++ b/include/basegfx/curve/b2dcubicbezier.hxx
@@ -159,7 +159,7 @@ namespace basegfx
         void split(double t, B2DCubicBezier* pBezierA, B2DCubicBezier* 
pBezierB) const;
 
         // extract snippet from fStart to fEnd from this bezier
-        SAL_DLLPRIVATE B2DCubicBezier snippet(double fStart, double fEnd) 
const;
+        B2DCubicBezier snippet(double fStart, double fEnd) const;
 
         // get range including control points
         B2DRange getRange() const;
diff --git a/include/drawinglayer/primitive2d/wrongspellprimitive2d.hxx 
b/include/drawinglayer/primitive2d/wrongspellprimitive2d.hxx
index 9a903f9f3db1..e3b743c8d6fe 100644
--- a/include/drawinglayer/primitive2d/wrongspellprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/wrongspellprimitive2d.hxx
@@ -21,7 +21,7 @@
 
 #include <drawinglayer/drawinglayerdllapi.h>
 
-#include <drawinglayer/primitive2d/BufferedDecompositionPrimitive2D.hxx>
+#include <drawinglayer/primitive2d/primitivetools2d.hxx>
 #include <basegfx/color/bcolor.hxx>
 #include <basegfx/matrix/b2dhommatrix.hxx>
 
@@ -44,7 +44,7 @@ namespace drawinglayer::primitive2d
             The geometric definition defines a line on the X-Axis (no 
Y-coordinates)
             which will when transformed by Transformation, create the 
coordinate data.
          */
-        class DRAWINGLAYER_DLLPUBLIC WrongSpellPrimitive2D final : public 
BufferedDecompositionPrimitive2D
+        class DRAWINGLAYER_DLLPUBLIC WrongSpellPrimitive2D final : public 
DiscreteMetricDependentPrimitive2D
         {
         private:
             /// geometry definition

Reply via email to