[Libreoffice-commits] core.git: Branch 'feature/borderline3' - drawinglayer/source svx/source

Armin Le Grand Armin.Le.Grand at cib.de
Wed Sep 13 16:39:14 UTC 2017


 drawinglayer/source/primitive2d/borderlineprimitive2d.cxx |   83 -----
 svx/source/dialog/framelink.cxx                           |  225 ++++++++++++--
 svx/source/dialog/framelinkarray.cxx                      |    8 
 3 files changed, 203 insertions(+), 113 deletions(-)

New commits:
commit 3aa80a7fda57a8e2c1caf25cc9c26d780dbadf70
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date:   Wed Sep 13 18:37:02 2017 +0200

    borderline: extended the expand logic
    
    Extended and checked the expand logic for creating
    the line extends. Now creating quite the right lines,
    will need to check some speccial cases. Also some
    cleanups.
    
    Change-Id: I3a3bd4d23c7017ecd873147df2d93af61de39fa6

diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
index eba1f7f0d996..6295d4673c36 100644
--- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx
@@ -165,89 +165,6 @@ namespace drawinglayer
             }
         }
 
-
-
-
-        //         static double fPatScFact(10.0); // 10.0 multiply, see old code
-        //         const std::vector<double> aDashing(svtools::GetLineDashing(getStyle(), getPatternScale() * fPatScFact));
-        //         const attribute::StrokeAttribute aStrokeAttribute(aDashing);
-
-        //         if (3 == getBorderLines().size())
-        //         {
-        //             // double line with gap. Use mfSmallestAllowedDiscreteGapDistance (see get2DDecomposition) as distance.
-        //             // That value is prepared to be at least one pixel (discrete unit) so that the
-        //             // decomposition is view-dependent in this cases
-        //             const BorderLine& rLeft(getBorderLines()[0]);
-        //             const BorderLine& rGap(getBorderLines()[1]);
-        //             const BorderLine& rRight(getBorderLines()[2]);
-        //             const double fFullWidth(rLeft.getWidth() + mfSmallestAllowedDiscreteGapDistance + rRight.getWidth());
-
-        //             {
-        //                 // inside line (left of vector). Create stroke primitive centered on left line width
-        //                 const double fDeltaY((rLeft.getWidth() - fFullWidth) * 0.5);
-        //                 const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY);
-        //                 const basegfx::B2DPoint aStart(getStart() - (aVector * rLeft.getBorderLineExtend().getStartAverage()) + aDeltaY);
-        //                 const basegfx::B2DPoint aEnd(getEnd() + (aVector * rLeft.getBorderLineExtend().getEndAverage()) + aDeltaY);
-        //                 const attribute::LineAttribute aLineAttribute(rLeft.getRGBColor(), rLeft.getWidth());
-
-        //                 addPolygonStrokePrimitive2D(
-        //                     rContainer,
-        //                     aStart,
-        //                     aEnd,
-        //                     aLineAttribute,
-        //                     aStrokeAttribute);
-        //             }
-
-        //             if (hasGapColor())
-        //             {
-        //                 // gap (if visible, found practical usage in Writer MultiColorBorderLines).
-        //                 // Create stroke primitive on vector with given color centered on gap position
-        //                 const double fDeltaY(((fFullWidth - mfSmallestAllowedDiscreteGapDistance) * 0.5) - rRight.getWidth());
-        //                 const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY);
-        //                 const basegfx::B2DPoint aStart(getStart() - (aVector * rGap.getBorderLineExtend().getStartAverage()) + aDeltaY);
-        //                 const basegfx::B2DPoint aEnd(getEnd() + (aVector * rGap.getBorderLineExtend().getEndAverage()) + aDeltaY);
-        //                 const attribute::LineAttribute aLineAttribute(rGap.getRGBColor(), mfSmallestAllowedDiscreteGapDistance);
-
-        //                 addPolygonStrokePrimitive2D(
-        //                     rContainer,
-        //                     aStart,
-        //                     aEnd,
-        //                     aLineAttribute,
-        //                     aStrokeAttribute);
-        //             }
-
-        //             {
-        //                 // outside line (right of vector). Create stroke primitive centered on right line width
-        //                 const double fDeltaY((fFullWidth - rRight.getWidth()) * 0.5);
-        //                 const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY);
-        //                 const basegfx::B2DPoint aStart(getStart() - (aVector * rRight.getBorderLineExtend().getStartAverage()) + aDeltaY);
-        //                 const basegfx::B2DPoint aEnd(getEnd() + (aVector * rRight.getBorderLineExtend().getEndAverage()) + aDeltaY);
-        //                 const attribute::LineAttribute aLineAttribute(rRight.getRGBColor(), rRight.getWidth());
-
-        //                 addPolygonStrokePrimitive2D(
-        //                     rContainer,
-        //                     aStart,
-        //                     aEnd,
-        //                     aLineAttribute,
-        //                     aStrokeAttribute);
-        //             }
-        //         }
-        //         else
-        //         {
-        //             // single line, only inside values used, no vertical offsets
-        //             const BorderLine& rBorderLine(getBorderLines()[0]);
-        //             const attribute::LineAttribute aLineAttribute(rBorderLine.getRGBColor(), rBorderLine.getWidth());
-
-        //             addPolygonStrokePrimitive2D(
-        //                 rContainer,
-        //                 getStart() - (aVector * rBorderLine.getBorderLineExtend().getStartAverage()),
-        //                 getEnd() + (aVector * rBorderLine.getBorderLineExtend().getEndAverage()),
-        //                 aLineAttribute,
-        //                 aStrokeAttribute);
-        //         }
-        //     }
-        // }
-
         bool BorderLinePrimitive2D::isHorizontalOrVertical(const geometry::ViewInformation2D& rViewInformation) const
         {
             if (!getStart().equal(getEnd()))
diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx
index c7a6377ab3e8..b7554436bf48 100644
--- a/svx/source/dialog/framelink.cxx
+++ b/svx/source/dialog/framelink.cxx
@@ -380,6 +380,7 @@ double getOffsetAndHalfWidthAndColorFromStyle(
         Color aSecn(rStyle.GetColorSecn());
         double fPrim(rStyle.Prim());
         double fSecn(rStyle.Secn());
+        const bool bSecnUsed(0.0 != fSecn);
 
         if(bMirrored)
         {
@@ -389,8 +390,12 @@ double getOffsetAndHalfWidthAndColorFromStyle(
                 case RefMode::End: aRefMode = RefMode::Begin; break;
                 default: break;
             }
-            std::swap(aPrim, aSecn);
-            std::swap(fPrim, fSecn);
+
+            if(bSecnUsed)
+            {
+                std::swap(aPrim, aSecn);
+                std::swap(fPrim, fSecn);
+            }
         }
 
         if (RefMode::Centered != aRefMode)
@@ -409,7 +414,7 @@ double getOffsetAndHalfWidthAndColorFromStyle(
             }
         }
 
-        if (rStyle.Dist() && fSecn)
+        if (bSecnUsed)
         {
             // both or all three lines used
             const bool bPrimTransparent(0xff == rStyle.GetColorPrim().GetTransparency());
@@ -503,6 +508,103 @@ void getCutSet(
         &rCutSet.mfORMR);
 }
 
+void getAllCutSets(
+    std::vector< CutSet >& rCutSets,
+    const basegfx::B2DPoint& rOrigin,
+    const basegfx::B2DPoint& rLeft,
+    const basegfx::B2DPoint& rRight,
+    const basegfx::B2DVector& rX,
+    const StyleVectorTable& rStyleVectorTable,
+    bool bUpper,
+    bool bLower)
+{
+    for(const auto& rStyleVectorCombination : rStyleVectorTable)
+    {
+        if(bUpper || bLower)
+        {
+            // use only upper or lower vectors compared to rX
+            const double fCross(rX.cross(rStyleVectorCombination.getB2DVector()));
+
+            if(bUpper && fCross > 0.0)
+            {
+                // upper vectors wanted, but is lower
+                continue;
+            }
+
+            if(bLower && fCross < 0.0)
+            {
+                // lower vectors wanted, but is upper
+                continue;
+            }
+        }
+
+        std::vector< OffsetAndHalfWidthAndColor > otherOffsets;
+        getOffsetAndHalfWidthAndColorFromStyle(rStyleVectorCombination.getStyle(), nullptr, rStyleVectorCombination.isMirrored(), otherOffsets);
+
+        if(!otherOffsets.empty())
+        {
+            const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleVectorCombination.getB2DVector()));
+
+            for(const auto& rOtherOffset : otherOffsets)
+            {
+                const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset - rOtherOffset.mfHalfWidth)));
+                const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset + rOtherOffset.mfHalfWidth)));
+                CutSet aCutSet;
+
+                getCutSet(aCutSet, rLeft, rRight, rX, aOtherLeft, aOtherRight, rStyleVectorCombination.getB2DVector());
+                rCutSets.push_back(aCutSet);
+            }
+        }
+    }
+}
+
+CutSet getMinMaxCutSet(
+    bool bMin,
+    const std::vector< CutSet >& rCutSets)
+{
+    if(rCutSets.empty())
+    {
+        CutSet aRetval;
+        aRetval.mfOLML = aRetval.mfORML = aRetval.mfOLMR = aRetval.mfORMR = 0.0;
+        return aRetval;
+    }
+
+    const size_t aSize(rCutSets.size());
+
+    if(1 == aSize)
+    {
+        return rCutSets[0];
+    }
+
+    CutSet aRetval(rCutSets[0]);
+    double fRetval(aRetval.mfOLML + aRetval.mfORML + aRetval.mfOLMR + aRetval.mfORMR);
+
+    for(size_t a(1); a < aSize; a++)
+    {
+        const CutSet& rCandidate(rCutSets[a]);
+        const double fCandidate(rCandidate.mfOLML + rCandidate.mfORML + rCandidate.mfOLMR + rCandidate.mfORMR);
+
+        if(bMin)
+        {
+            if(fCandidate < fRetval)
+            {
+                fRetval = fCandidate;
+                aRetval = rCandidate;
+            }
+        }
+        else
+        {
+            if(fCandidate > fRetval)
+            {
+                fRetval = fCandidate;
+                aRetval = rCandidate;
+            }
+        }
+    }
+
+    return aRetval;
+}
+
 void getExtends(
     std::vector<ExtendSet>& rExtendSet,                     // target Left/Right values to fill
     const basegfx::B2DPoint& rOrigin,                       // own vector start
@@ -518,41 +620,99 @@ void getExtends(
         for(size_t a(0); a < nOffsets; a++)
         {
             const OffsetAndHalfWidthAndColor& rOffset(rOffsets[a]);
-            ExtendSet& rExt(rExtendSet[a]);
-            bool bExtSet(false);
-            const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (rOffset.mfOffset - rOffset.mfHalfWidth)));
-            const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (rOffset.mfOffset + rOffset.mfHalfWidth)));
 
-            for(const auto& rStyleVectorCombination : rStyleVectorTable)
+            if(0xff != rOffset.maColor.GetTransparency())
             {
-                std::vector< OffsetAndHalfWidthAndColor > otherOffsets;
-                getOffsetAndHalfWidthAndColorFromStyle(rStyleVectorCombination.getStyle(), nullptr, rStyleVectorCombination.isMirrored(), otherOffsets);
+                const basegfx::B2DPoint aLeft(rOrigin + (rPerpendX * (rOffset.mfOffset - rOffset.mfHalfWidth)));
+                const basegfx::B2DPoint aRight(rOrigin + (rPerpendX * (rOffset.mfOffset + rOffset.mfHalfWidth)));
+                std::vector< CutSet > aCutSets;
+                CutSet aResult;
+                bool bResultSet(false);
+
+                if(1 == nOffsets)
+                {
+                    // single line:
+                    // - get all CutSets
+                    // - get minimum values as extension (biggest possible overlap)
+                    getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, false, false);
 
-                if(!otherOffsets.empty())
+                    if(!aCutSets.empty())
+                    {
+                        aResult = getMinMaxCutSet(true, aCutSets);
+                        bResultSet = true;
+                    }
+                }
+                else
                 {
-                    const basegfx::B2DVector aOtherPerpend(basegfx::getNormalizedPerpendicular(rStyleVectorCombination.getB2DVector()));
+                    // multiple lines
+                    const bool bUpper(a < (nOffsets >> 1));
+                    const bool bLower(a > (nOffsets >> 1));
 
-                    for(const auto& rOtherOffset : otherOffsets)
+                    if(bUpper)
                     {
-                        const basegfx::B2DPoint aOtherLeft(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset - rOtherOffset.mfHalfWidth)));
-                        const basegfx::B2DPoint aOtherRight(rOrigin + (aOtherPerpend * (rOtherOffset.mfOffset + rOtherOffset.mfHalfWidth)));
-                        CutSet aCutSet;
+                        getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, true, false);
+
+                        if(!aCutSets.empty())
+                        {
+                            aResult = getMinMaxCutSet(false, aCutSets);
+                            bResultSet = true;
+                        }
+                        else
+                        {
+                            getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, false, true);
 
-                        getCutSet(aCutSet, aLeft, aRight, rX, aOtherLeft, aOtherRight, rStyleVectorCombination.getB2DVector());
+                            if(!aCutSets.empty())
+                            {
+                                aResult = getMinMaxCutSet(true, aCutSets);
+                                bResultSet = true;
+                            }
+                        }
+                    }
+                    else if(bLower)
+                    {
+                        getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, false, true);
 
-                        if(!bExtSet)
+                        if(!aCutSets.empty())
                         {
-                            rExt.mfExtLeft = std::min(aCutSet.mfOLML, aCutSet.mfORML);
-                            rExt.mfExtRight = std::min(aCutSet.mfOLMR, aCutSet.mfORMR);
-                            bExtSet = true;
+                            aResult = getMinMaxCutSet(false, aCutSets);
+                            bResultSet = true;
                         }
                         else
                         {
-                            rExt.mfExtLeft = std::min(rExt.mfExtLeft , std::min(aCutSet.mfOLML, aCutSet.mfORML));
-                            rExt.mfExtRight = std::min(rExt.mfExtRight , std::min(aCutSet.mfOLMR, aCutSet.mfORMR));
+                            getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, true, false);
+
+                            if(!aCutSets.empty())
+                            {
+                                aResult = getMinMaxCutSet(true, aCutSets);
+                                bResultSet = true;
+                            }
+                        }
+                    }
+                    else // middle line
+                    {
+                        getAllCutSets(aCutSets, rOrigin, aLeft, aRight, rX, rStyleVectorTable, false, false);
+
+                        if(!aCutSets.empty())
+                        {
+                            const CutSet aResultMin(getMinMaxCutSet(true, aCutSets));
+                            const CutSet aResultMax(getMinMaxCutSet(false, aCutSets));
+
+                            aResult.mfOLML = (aResultMin.mfOLML + aResultMax.mfOLML) * 0.5;
+                            aResult.mfORML = (aResultMin.mfORML + aResultMax.mfORML) * 0.5;
+                            aResult.mfOLMR = (aResultMin.mfOLMR + aResultMax.mfOLMR) * 0.5;
+                            aResult.mfORMR = (aResultMin.mfORMR + aResultMax.mfORMR) * 0.5;
+                            bResultSet = true;
                         }
                     }
                 }
+
+                if(bResultSet)
+                {
+                    ExtendSet& rExt(rExtendSet[a]);
+
+                    rExt.mfExtLeft = std::min(aResult.mfOLML, aResult.mfORML);
+                    rExt.mfExtRight = std::min(aResult.mfOLMR, aResult.mfORMR);
+                }
             }
         }
     }
@@ -588,9 +748,22 @@ void CreateBorderPrimitives(
 
         if(bHasEndStyles)
         {
-            // create extends for line ends, use inverse point/vector and inverse offsets
-            std::reverse(myOffsets.begin(), myOffsets.end());
-            getExtends(aExtendSetEnd, rOrigin + rX, -rX, -aPerpendX, myOffsets, rEndStyleVectorTable);
+            // Create extends for line ends, use inverse point/vector and inverse offsets.
+            // Offsets need to be inverted for different width of lines. To invert, change
+            // order, but also sign of offset. Do this on a copy since myOffsets will be
+            // used below to create the primitives
+            std::vector< OffsetAndHalfWidthAndColor > myInverseOffsets(myOffsets);
+            std::reverse(myInverseOffsets.begin(), myInverseOffsets.end());
+
+            for(auto& offset : myInverseOffsets)
+            {
+                offset.mfOffset *= -1;
+            }
+
+            getExtends(aExtendSetEnd, rOrigin + rX, -rX, -aPerpendX, myInverseOffsets, rEndStyleVectorTable);
+
+            // also need to reverse the result to apply to the correct lines
+            std::reverse(aExtendSetEnd.begin(), aExtendSetEnd.end());
         }
 
         std::vector< drawinglayer::primitive2d::BorderLine > aBorderlines;
diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx
index db54294640c5..5a526145cd54 100644
--- a/svx/source/dialog/framelinkarray.cxx
+++ b/svx/source/dialog/framelinkarray.cxx
@@ -988,7 +988,7 @@ void HelperCreateVerticalEntry(
 
     if(rStartFromBR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBR, rX + rY, false));
     if(rStartTFromR.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromR, rX, false));
-    if(rStartTFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromT, rY, true));
+    if(rStartTFromT.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromT, -rY, true));
     if(rStartTFromL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartTFromL, -rX, true));
     if(rStartFromBL.IsUsed()) aStart.push_back(StyleVectorCombination(rStartFromBL, rY - rX, true));
 
@@ -1002,9 +1002,9 @@ void HelperCreateVerticalEntry(
 
     if(rEndFromTR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTR, rX - rY, false));
     if(rEndBFromR.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromR, rX, false));
-    if(rEndBFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromB, -rY, false));
-    if(rEndBFromL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromL, rX, true));
-    if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, rX + rY, true));
+    if(rEndBFromB.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromB, rY, false));
+    if(rEndBFromL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndBFromL, -rX, true));
+    if(rEndFromTL.IsUsed()) aEnd.push_back(StyleVectorCombination(rEndFromTL, -rX - rY, true));
 
     CreateBorderPrimitives(
         rSequence,


More information about the Libreoffice-commits mailing list