diff options
-rw-r--r-- | compilerplugins/clang/fpcomparison.cxx | 1 | ||||
-rw-r--r-- | drawinglayer/Library_drawinglayer.mk | 1 | ||||
-rw-r--r-- | drawinglayer/qa/unit/border.cxx | 47 | ||||
-rw-r--r-- | drawinglayer/source/primitive2d/borderlineprimitive2d.cxx | 389 | ||||
-rw-r--r-- | drawinglayer/source/primitive2d/clippedborderlineprimitive2d.cxx | 64 | ||||
-rw-r--r-- | drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 395 | ||||
-rw-r--r-- | drawinglayer/source/processor2d/vclpixelprocessor2d.hxx | 1 | ||||
-rw-r--r-- | include/drawinglayer/primitive2d/borderlineprimitive2d.hxx | 26 | ||||
-rw-r--r-- | include/drawinglayer/primitive2d/clippedborderlineprimitive2d.hxx | 65 | ||||
-rw-r--r-- | include/svx/framelink.hxx | 8 | ||||
-rw-r--r-- | include/svx/framelinkarray.hxx | 7 | ||||
-rw-r--r-- | sc/source/ui/view/output.cxx | 86 | ||||
-rw-r--r-- | svx/source/dialog/framelink.cxx | 103 | ||||
-rw-r--r-- | svx/source/dialog/framelinkarray.cxx | 165 | ||||
-rw-r--r-- | svx/source/dialog/frmsel.cxx | 32 | ||||
-rw-r--r-- | sw/source/core/layout/paintfrm.cxx | 52 |
16 files changed, 497 insertions, 945 deletions
diff --git a/compilerplugins/clang/fpcomparison.cxx b/compilerplugins/clang/fpcomparison.cxx index 1cc7616c887b..f85dba05cd1e 100644 --- a/compilerplugins/clang/fpcomparison.cxx +++ b/compilerplugins/clang/fpcomparison.cxx @@ -179,7 +179,6 @@ bool FpComparison::ignore(FunctionDecl* function) || dc.Function("create2DDecomposition").Class("ScenePrimitive2D").Namespace("primitive2d").Namespace("drawinglayer").GlobalNamespace() || dc.Function("createAtom").Class("SvgLinearGradientPrimitive2D").Namespace("primitive2d").Namespace("drawinglayer").GlobalNamespace() || dc.Function("createAtom").Class("SvgRadialGradientPrimitive2D").Namespace("primitive2d").Namespace("drawinglayer").GlobalNamespace() - || dc.Function("tryDrawBorderLinePrimitive2DDirect").Class("VclPixelProcessor2D").Namespace("processor2d").Namespace("drawinglayer").GlobalNamespace() || dc.Function("FoldConstantsBinaryNode").Class("SbiExprNode").GlobalNamespace() || dc.Function("Format").Class("SbxValue").GlobalNamespace() || dc.Function("Compare").Class("SbxValue").GlobalNamespace() diff --git a/drawinglayer/Library_drawinglayer.mk b/drawinglayer/Library_drawinglayer.mk index 8c431c8ec08f..32daccd9d43e 100644 --- a/drawinglayer/Library_drawinglayer.mk +++ b/drawinglayer/Library_drawinglayer.mk @@ -67,7 +67,6 @@ $(eval $(call gb_Library_add_exception_objects,drawinglayer,\ drawinglayer/source/primitive2d/baseprimitive2d \ drawinglayer/source/primitive2d/bitmapprimitive2d \ drawinglayer/source/primitive2d/borderlineprimitive2d \ - drawinglayer/source/primitive2d/clippedborderlineprimitive2d \ drawinglayer/source/primitive2d/controlprimitive2d \ drawinglayer/source/primitive2d/cropprimitive2d \ drawinglayer/source/primitive2d/discretebitmapprimitive2d \ diff --git a/drawinglayer/qa/unit/border.cxx b/drawinglayer/qa/unit/border.cxx index 25264c46ee51..ce99965b13f9 100644 --- a/drawinglayer/qa/unit/border.cxx +++ b/drawinglayer/qa/unit/border.cxx @@ -17,6 +17,7 @@ #include <drawinglayer/geometry/viewinformation2d.hxx> #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx> #include <drawinglayer/primitive2d/polypolygonprimitive2d.hxx> +#include <drawinglayer/primitive2d/polygonprimitive2d.hxx> #include <drawinglayer/processor2d/baseprocessor2d.hxx> #include <drawinglayer/processor2d/processorfromoutputdevice.hxx> #include <rtl/ref.hxx> @@ -70,17 +71,15 @@ void DrawinglayerBorderTest::testDoubleDecompositionSolid() // Make sure it results in two borders as it's a double one. CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(2), aContainer.size()); - // Get the inside line. - auto pInside = dynamic_cast<const drawinglayer::primitive2d::PolyPolygonColorPrimitive2D*>(aContainer[0].get()); + // Get the inside line, now a PolygonStrokePrimitive2D + auto pInside = dynamic_cast<const drawinglayer::primitive2d::PolygonStrokePrimitive2D*>(aContainer[0].get()); CPPUNIT_ASSERT(pInside); // Make sure the inside line's height is fLeftWidth. - const basegfx::B2DPolyPolygon& rPolyPolygon = pInside->getB2DPolyPolygon(); - CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(1), rPolyPolygon.count()); - const basegfx::B2DPolygon& rPolygon = rPolyPolygon.getB2DPolygon(0); - const basegfx::B2DRange& rRange = rPolygon.getB2DRange(); + const double fLineWidthFromDecompose = pInside->getLineAttribute().getWidth(); + // This was 2.47, i.e. the width of the inner line was 1 unit (in the bugdoc's case: 1 pixel) wider than expected. - CPPUNIT_ASSERT_DOUBLES_EQUAL(fLeftWidth, rRange.getHeight(), basegfx::fTools::getSmallValue()); + CPPUNIT_ASSERT_DOUBLES_EQUAL(fLeftWidth, fLineWidthFromDecompose, basegfx::fTools::getSmallValue()); } void DrawinglayerBorderTest::testDoublePixelProcessing() @@ -100,7 +99,7 @@ void DrawinglayerBorderTest::testDoublePixelProcessing() basegfx::B2DPoint aEnd(100, 20); double const fLeftWidth = 1.47; double const fDistance = 1.47; - double fRightWidth = 1.47; + double const fRightWidth = 1.47; double const fExtendLeftStart = 0; double const fExtendLeftEnd = 0; double const fExtendRightStart = 0; @@ -117,31 +116,33 @@ void DrawinglayerBorderTest::testDoublePixelProcessing() // Process the primitives. pProcessor->process(aPrimitives); - // Now assert the height of the outer (second) border polygon. + // Double line now gets decomposed in Metafile to painting four lines + // with width == 0 in a cross pattern due to real line width being between + // 1.0 and 2.0. Count created lines aMetaFile.Stop(); aMetaFile.WindStart(); - bool bFirst = true; - sal_Int32 nHeight = 0; + sal_uInt32 nPolyLineActionCount = 0; + for (std::size_t nAction = 0; nAction < aMetaFile.GetActionSize(); ++nAction) { MetaAction* pAction = aMetaFile.GetAction(nAction); - if (pAction->GetType() == MetaActionType::POLYPOLYGON) + + if (MetaActionType::POLYLINE == pAction->GetType()) { - if (bFirst) + auto pMPLAction = static_cast<MetaPolyLineAction*>(pAction); + + if (0 == pMPLAction->GetLineInfo().GetWidth() && LineStyle::Solid == pMPLAction->GetLineInfo().GetStyle()) { - bFirst = false; - continue; + nPolyLineActionCount++; } - - auto pMPPAction = static_cast<MetaPolyPolygonAction*>(pAction); - const tools::PolyPolygon& rPolyPolygon = pMPPAction->GetPolyPolygon(); - nHeight = rPolyPolygon.GetBoundRect().getHeight(); } } - sal_Int32 nExpectedHeight = std::round(fRightWidth); - // This was 2, and should be 1: if the logical requested width is 1.47, - // then that must be 1 px on the screen, not 2. - CPPUNIT_ASSERT_EQUAL(nExpectedHeight, nHeight); + + // Check if all eight (2x four) simple lines with width == 0 and + // solid were created + const sal_uInt32 nExpectedNumPolyLineActions = 8; + + CPPUNIT_ASSERT_EQUAL(nExpectedNumPolyLineActions, nPolyLineActionCount); } CPPUNIT_TEST_SUITE_REGISTRATION(DrawinglayerBorderTest); diff --git a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx index c6ea4a5c41f7..9735cc1aa44d 100644 --- a/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/borderlineprimitive2d.cxx @@ -42,282 +42,138 @@ T round(T x) } #endif -namespace drawinglayer { - -namespace { - -void moveLine(basegfx::B2DPolygon& rPoly, double fGap, const basegfx::B2DVector& rVector) -{ - if (basegfx::fTools::equalZero(rVector.getX())) - { - basegfx::B2DHomMatrix aMat(1, 0, fGap, 0, 1, 0); - rPoly.transform(aMat); - } - else if (basegfx::fTools::equalZero(rVector.getY())) - { - basegfx::B2DHomMatrix aMat(1, 0, 0, 0, 1, fGap); - rPoly.transform(aMat); - } -} - -primitive2d::Primitive2DReference makeHairLinePrimitive( - const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd, const basegfx::B2DVector& rVector, - const basegfx::BColor& rColor, double fGap) -{ - basegfx::B2DPolygon aPolygon; - aPolygon.append(rStart); - aPolygon.append(rEnd); - moveLine(aPolygon, fGap, rVector); - - return primitive2d::Primitive2DReference(new primitive2d::PolygonHairlinePrimitive2D(aPolygon, rColor)); -} - -primitive2d::Primitive2DReference makeSolidLinePrimitive( - const basegfx::B2DPolyPolygon& rClipRegion, const basegfx::B2DPoint& rStart, const basegfx::B2DPoint& rEnd, - const basegfx::B2DVector& rVector, const basegfx::BColor& rColor, double fLineWidth, double fGap) +namespace drawinglayer { - const basegfx::B2DVector aPerpendicular = basegfx::getPerpendicular(rVector); - const basegfx::B2DVector aLineWidthOffset = (fLineWidth * 0.5) * aPerpendicular; - - basegfx::B2DPolygon aPolygon; - aPolygon.append(rStart + aLineWidthOffset); - aPolygon.append(rEnd + aLineWidthOffset); - aPolygon.append(rEnd - aLineWidthOffset); - aPolygon.append(rStart - aLineWidthOffset); - aPolygon.setClosed(true); - - moveLine(aPolygon, fGap, rVector); - - basegfx::B2DPolyPolygon aClipped = - basegfx::tools::clipPolygonOnPolyPolygon(aPolygon, rClipRegion, true, false); - - if (aClipped.count()) - aPolygon = aClipped.getB2DPolygon(0); - - return primitive2d::Primitive2DReference( - new primitive2d::PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aPolygon), rColor)); -} - -} - - // fdo#49438: heuristic pseudo hack - static bool lcl_UseHairline(double const fW, - basegfx::B2DPoint const& rStart, basegfx::B2DPoint const& rEnd, - geometry::ViewInformation2D const& rViewInformation) - { - basegfx::B2DTuple scale; - basegfx::B2DTuple translation; - double fRotation; - double fShear; - rViewInformation.getObjectToViewTransformation().decompose( - scale, translation, fRotation, fShear); - double const fScale( - (rEnd.getX() - rStart.getX() > rEnd.getY() - rStart.getY()) - ? scale.getY() : scale.getX()); - return (fW * fScale < 0.51); - } - - static double lcl_GetCorrectedWidth(double const fW, - basegfx::B2DPoint const& rStart, basegfx::B2DPoint const& rEnd, - geometry::ViewInformation2D const& rViewInformation) - { - return (lcl_UseHairline(fW, rStart, rEnd, rViewInformation)) ? 0.0 : fW; - } - namespace primitive2d { - double BorderLinePrimitive2D::getWidth( - geometry::ViewInformation2D const& rViewInformation) const - { - return lcl_GetCorrectedWidth(mfLeftWidth, getStart(), getEnd(), - rViewInformation) - + lcl_GetCorrectedWidth(mfDistance, getStart(), getEnd(), - rViewInformation) - + lcl_GetCorrectedWidth(mfRightWidth, getStart(), getEnd(), - rViewInformation); - } - - basegfx::B2DPolyPolygon BorderLinePrimitive2D::getClipPolygon( - geometry::ViewInformation2D const& rViewInformation) const + // helper to add a centered, maybe stroked line primitive to rContainer + void addPolygonStrokePrimitive2D( + Primitive2DContainer& rContainer, + const basegfx::B2DPoint& rStart, + const basegfx::B2DPoint& rEnd, + const basegfx::BColor& rColor, + double fWidth, + SvxBorderLineStyle aStyle, + double fPatternScale) { - basegfx::B2DPolygon clipPolygon; - - // Get the vectors - basegfx::B2DVector aVector( getEnd() - getStart() ); - aVector.normalize(); - const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector)); - - // Get the points - const double fWidth(getWidth(rViewInformation)); - const basegfx::B2DVector aLeftOff( - aPerpendicular * (-0.5 * std::max(fWidth, 1.0))); - const basegfx::B2DVector aRightOff( - aPerpendicular * (0.5 * std::max(fWidth, 1.0))); + basegfx::B2DPolygon aPolygon; - const basegfx::B2DVector aSLVector( aLeftOff - ( getExtendLeftStart() * aVector ) ); - clipPolygon.append( basegfx::B2DPoint( getStart() + aSLVector * 2.0 ) ); + aPolygon.append(rStart); + aPolygon.append(rEnd); - clipPolygon.append( getStart( ) ); + const attribute::LineAttribute aLineAttribute(rColor, fWidth); + static double fPatScFact(10.0); // 10.0 multiply, see old code + const std::vector<double> aDashing(svtools::GetLineDashing(aStyle, fPatternScale * fPatScFact)); - const basegfx::B2DVector aSRVector( aRightOff - ( getExtendRightStart() * aVector ) ); - clipPolygon.append( basegfx::B2DPoint( getStart() + aSRVector * 2.0 ) ); - - const basegfx::B2DVector aERVector( aRightOff + ( getExtendRightEnd() * aVector ) ); - clipPolygon.append( basegfx::B2DPoint( getEnd() + aERVector * 2.0 ) ); - - clipPolygon.append( getEnd( ) ); - - const basegfx::B2DVector aELVector( aLeftOff + ( getExtendLeftEnd() * aVector ) ); - clipPolygon.append( basegfx::B2DPoint( getEnd() + aELVector * 2.0 ) ); - - clipPolygon.setClosed( true ); - - return basegfx::B2DPolyPolygon( clipPolygon ); - } + if (aDashing.empty()) + { + rContainer.push_back( + new PolygonStrokePrimitive2D( + aPolygon, + aLineAttribute)); + } + else + { + const attribute::StrokeAttribute aStrokeAttribute(aDashing); - void BorderLinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const - { - createDecomposition(rContainer, rViewInformation, false); + rContainer.push_back( + new PolygonStrokePrimitive2D( + aPolygon, + aLineAttribute, + aStrokeAttribute)); + } } - void BorderLinePrimitive2D::createDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation, bool bPixelCorrection) const + void BorderLinePrimitive2D::create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& /*rViewInformation*/) const { - if(!getStart().equal(getEnd()) && ( isInsideUsed() || isOutsideUsed() ) ) + if (!getStart().equal(getEnd()) && (isInsideUsed() || isOutsideUsed())) { // get data and vectors basegfx::B2DVector aVector(getEnd() - getStart()); aVector.normalize(); const basegfx::B2DVector aPerpendicular(basegfx::getPerpendicular(aVector)); - const basegfx::B2DPolyPolygon& aClipRegion = - getClipPolygon(rViewInformation); - - if(isOutsideUsed() && isInsideUsed()) + if (isOutsideUsed() && isInsideUsed()) { - const double fExt = getWidth(rViewInformation); // Extend a lot: it'll be clipped later. - const basegfx::B2DPoint aTmpStart(getStart() - (fExt * aVector)); - const basegfx::B2DPoint aTmpEnd(getEnd() + (fExt * aVector)); - - double fLeftWidth = getLeftWidth(); - bool bLeftHairline = lcl_UseHairline(fLeftWidth, getStart(), getEnd(), rViewInformation); - if (bLeftHairline) - fLeftWidth = 0.0; - - double fRightWidth = getRightWidth(); - bool bRightHairline = lcl_UseHairline(fRightWidth, getStart(), getEnd(), rViewInformation); - if (bRightHairline) - fRightWidth = 0.0; - - // "inside" line - - if (bLeftHairline) - rContainer.push_back(makeHairLinePrimitive( - getStart(), getEnd(), aVector, getRGBColorLeft(), 0.0)); - else + // double line with gap. Use mfDiscreteDistance (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 + if (isInsideUsed()) { - double fWidth = bPixelCorrection ? std::round(fLeftWidth) : fLeftWidth; - rContainer.push_back(makeSolidLinePrimitive( - aClipRegion, aTmpStart, aTmpEnd, aVector, getRGBColorLeft(), fWidth, -fLeftWidth/2.0)); + // inside line (left). Create stroke primitive centered on line width + const double fDeltaY((mfDiscreteDistance + getLeftWidth()) * 0.5); + const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY); + const basegfx::B2DPoint aStart(getStart() - (aVector * getExtendLeftStart()) - aDeltaY); + const basegfx::B2DPoint aEnd(getEnd() + (aVector * getExtendLeftEnd()) - aDeltaY); + + addPolygonStrokePrimitive2D( + rContainer, + aStart, + aEnd, + getRGBColorLeft(), + getLeftWidth(), + getStyle(), + getPatternScale()); } - // "outside" line - - if (bRightHairline) - rContainer.push_back(makeHairLinePrimitive( - getStart(), getEnd(), aVector, getRGBColorRight(), fLeftWidth+mfDistance)); - else + if (hasGapColor() && isDistanceUsed()) { - double fWidth = bPixelCorrection ? std::round(fRightWidth) : fRightWidth; - rContainer.push_back(makeSolidLinePrimitive( - aClipRegion, aTmpStart, aTmpEnd, aVector, getRGBColorRight(), fWidth, mfDistance+fRightWidth/2.0)); + // gap (if visible, found no practicval usage). + // Create stroke primitive on vector with given color + addPolygonStrokePrimitive2D( + rContainer, + getStart(), + getEnd(), + getRGBColorGap(), + mfDiscreteDistance, + getStyle(), + getPatternScale()); } - } - else - { - // single line, create geometry - basegfx::B2DPolygon aPolygon; - const double fExt = getWidth(rViewInformation); // Extend a lot: it'll be clipped after - const basegfx::B2DPoint aTmpStart(getStart() - (fExt * aVector)); - const basegfx::B2DPoint aTmpEnd(getEnd() + (fExt * aVector)); - // Get which is the line to show - bool bIsSolidline = mnStyle == SvxBorderLineStyle::SOLID; - double nWidth = getLeftWidth(); - basegfx::BColor aColor = getRGBColorLeft(); - if ( basegfx::fTools::equal( 0.0, mfLeftWidth ) ) + if (isOutsideUsed()) { - nWidth = getRightWidth(); - aColor = getRGBColorRight(); + // outside line (right). Create stroke primitive centered on line width + const double fDeltaY((mfDiscreteDistance + getRightWidth()) * 0.5); + const basegfx::B2DVector aDeltaY(aPerpendicular * fDeltaY); + const basegfx::B2DPoint aStart(getStart() - (aVector * getExtendRightStart()) + aDeltaY); + const basegfx::B2DPoint aEnd(getEnd() + (aVector * getExtendRightEnd()) + aDeltaY); + + addPolygonStrokePrimitive2D( + rContainer, + aStart, + aEnd, + getRGBColorRight(), + getRightWidth(), + getStyle(), + getPatternScale()); } - bool const bIsHairline = lcl_UseHairline( - nWidth, getStart(), getEnd(), rViewInformation); - nWidth = lcl_GetCorrectedWidth(nWidth, - getStart(), getEnd(), rViewInformation); - - if(bIsHairline && bIsSolidline) - { - // create hairline primitive - aPolygon.append( getStart() ); - aPolygon.append( getEnd() ); - - rContainer.push_back(new PolygonHairlinePrimitive2D( - aPolygon, - aColor)); - } - else - { - // create filled polygon primitive - const basegfx::B2DVector aLineWidthOffset(((nWidth + 1) * 0.5) * aPerpendicular); - - aPolygon.append( aTmpStart ); - aPolygon.append( aTmpEnd ); - - basegfx::B2DPolyPolygon aDashed = - svtools::ApplyLineDashing(aPolygon, getStyle(), mfPatternScale*10.0); - - for (sal_uInt32 i = 0; i < aDashed.count(); i++ ) - { - basegfx::B2DPolygon aDash = aDashed.getB2DPolygon( i ); - basegfx::B2DPoint aDashStart = aDash.getB2DPoint( 0 ); - basegfx::B2DPoint aDashEnd = aDash.getB2DPoint( aDash.count() - 1 ); - - basegfx::B2DPolygon aDashPolygon; - aDashPolygon.append( aDashStart + aLineWidthOffset ); - aDashPolygon.append( aDashEnd + aLineWidthOffset ); - aDashPolygon.append( aDashEnd - aLineWidthOffset ); - aDashPolygon.append( aDashStart - aLineWidthOffset ); - aDashPolygon.setClosed( true ); - - basegfx::B2DPolyPolygon aClipped = basegfx::tools::clipPolygonOnPolyPolygon( - aDashPolygon, aClipRegion, true, false ); + } + else if(isInsideUsed()) + { + // single line, only inside values used, no vertical offsets + addPolygonStrokePrimitive2D( + rContainer, + getStart(), + getEnd(), + getRGBColorLeft(), + getLeftWidth(), + getStyle(), + getPatternScale()); + } + } + } - if ( aClipped.count() ) - aDashed.setB2DPolygon( i, aClipped.getB2DPolygon( 0 ) ); - } + bool BorderLinePrimitive2D::isHorizontalOrVertical(const geometry::ViewInformation2D& rViewInformation) const + { + if (!getStart().equal(getEnd())) + { + const basegfx::B2DHomMatrix& rOTVT = rViewInformation.getObjectToViewTransformation(); + const basegfx::B2DVector aVector(rOTVT * getEnd() - rOTVT * getStart()); - sal_uInt32 n = aDashed.count(); - for (sal_uInt32 i = 0; i < n; ++i) - { - basegfx::B2DPolygon aDash = aDashed.getB2DPolygon(i); - if (bIsHairline) - { - // Convert a rectangular polygon into a line. - basegfx::B2DPolygon aDash2; - basegfx::B2DRange aRange = aDash.getB2DRange(); - aDash2.append(basegfx::B2DPoint(aRange.getMinX(), aRange.getMinY())); - aDash2.append(basegfx::B2DPoint(aRange.getMaxX(), aRange.getMinY())); - rContainer.push_back( - new PolygonHairlinePrimitive2D(aDash2, aColor)); - } - else - { - rContainer.push_back( - new PolyPolygonColorPrimitive2D(basegfx::B2DPolyPolygon(aDash), aColor)); - } - } - } - } + return basegfx::fTools::equalZero(aVector.getX()) || basegfx::fTools::equalZero(aVector.getY()); } + + return false; } BorderLinePrimitive2D::BorderLinePrimitive2D( @@ -351,7 +207,8 @@ primitive2d::Primitive2DReference makeSolidLinePrimitive( maRGBColorGap(rRGBColorGap), mbHasGapColor(bHasGapColor), mnStyle(nStyle), - mfPatternScale(fPatternScale) + mfPatternScale(fPatternScale), + mfDiscreteDistance(0.0) { } @@ -381,6 +238,42 @@ primitive2d::Primitive2DReference makeSolidLinePrimitive( return false; } + void BorderLinePrimitive2D::get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const + { + ::osl::MutexGuard aGuard(m_aMutex); + + if (!getStart().equal(getEnd()) && isOutsideUsed() && isInsideUsed()) + { + // Double line with gap. In this case, we want to be view-dependent. + // Get the current DiscreteUnit, look at X and Y and use the maximum + const basegfx::B2DVector aDiscreteVector(rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(1.0, 1.0)); + const double fDiscreteUnit(std::min(fabs(aDiscreteVector.getX()), fabs(aDiscreteVector.getY()))); + + // When discrete unit is bigger than distance (distance is less than one pixel), + // force distance to one pixel. Or expressed different, do not let the distance + // get smaller than one pixel. This is done for screen rendering and compatibility. + // This can also be done using DiscreteMetricDependentPrimitive2D as base class + // for this class, but specialization is better here for later buffering (only + // do this when 'double line with gap') + const double fNewDiscreteDistance(std::max(fDiscreteUnit, getDistance())); + + if (!rtl::math::approxEqual(fNewDiscreteDistance, mfDiscreteDistance)) + { + if (!getBuffered2DDecomposition().empty()) + { + // conditions of last local decomposition have changed, delete + const_cast< BorderLinePrimitive2D* >(this)->setBuffered2DDecomposition(Primitive2DContainer()); + } + + // remember value for usage in create2DDecomposition + const_cast< BorderLinePrimitive2D* >(this)->mfDiscreteDistance = fNewDiscreteDistance; + } + } + + // call base implementation + BufferedDecompositionPrimitive2D::get2DDecomposition(rVisitor, rViewInformation); + } + // provide unique ID ImplPrimitive2DIDBlock(BorderLinePrimitive2D, PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D) diff --git a/drawinglayer/source/primitive2d/clippedborderlineprimitive2d.cxx b/drawinglayer/source/primitive2d/clippedborderlineprimitive2d.cxx deleted file mode 100644 index ca44a2838909..000000000000 --- a/drawinglayer/source/primitive2d/clippedborderlineprimitive2d.cxx +++ /dev/null @@ -1,64 +0,0 @@ -/* -*- 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 <drawinglayer/primitive2d/clippedborderlineprimitive2d.hxx> -#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx> - -namespace drawinglayer -{ - namespace primitive2d - { - basegfx::B2DPolyPolygon ClippedBorderLinePrimitive2D::getClipPolygon( - SAL_UNUSED_PARAMETER geometry::ViewInformation2D const&) const - { - basegfx::B2DPolyPolygon aPolyPolygon; - aPolyPolygon.append( maIntersection ); - return aPolyPolygon; - } - - ClippedBorderLinePrimitive2D::ClippedBorderLinePrimitive2D( - const basegfx::B2DPoint& rStart, - const basegfx::B2DPoint& rEnd, - double fLeftWidth, - double fDistance, - double fRightWidth, - const basegfx::B2DPolygon& rIntersection, - const basegfx::BColor& rRGBColorRight, - const basegfx::BColor& rRGBColorLeft, - const basegfx::BColor& rRGBColorGap, - bool bHasGapColor, - SvxBorderLineStyle nStyle, - double fPatternScale) - : BorderLinePrimitive2D( rStart, rEnd, fLeftWidth,fDistance, fRightWidth, - 0.0, 0.0, 0.0, 0.0, rRGBColorRight, rRGBColorLeft, - rRGBColorGap, bHasGapColor, nStyle, fPatternScale), - maIntersection( rIntersection ) - { - } - - bool ClippedBorderLinePrimitive2D::operator==(const BasePrimitive2D& rPrimitive) const - { - if(BorderLinePrimitive2D::operator==(rPrimitive)) - { - const ClippedBorderLinePrimitive2D& rCompare = static_cast<const ClippedBorderLinePrimitive2D&>(rPrimitive); - - return maIntersection == rCompare.maIntersection; - } - - return false; - } - - // provide unique ID - ImplPrimitive2DIDBlock(ClippedBorderLinePrimitive2D, PRIMITIVE2D_ID_CLIPPEDBORDERLINEPRIMITIVE2D) - - - } // namespace primitive2d -} // namespace drawinglayer - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index 4b5e45c7ef04..a93f85df4595 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -70,34 +70,6 @@ T round(T x) using namespace com::sun::star; -namespace { - -basegfx::B2DPolygon makeRectPolygon( double fX, double fY, double fW, double fH ) -{ - basegfx::B2DPolygon aPoly; - aPoly.append(basegfx::B2DPoint(fX, fY)); - aPoly.append(basegfx::B2DPoint(fX+fW, fY)); - aPoly.append(basegfx::B2DPoint(fX+fW, fY+fH)); - aPoly.append(basegfx::B2DPoint(fX, fY+fH)); - aPoly.setClosed(true); - return aPoly; -} - -void drawHairLine( - OutputDevice* pOutDev, double fX1, double fY1, double fX2, double fY2, - const basegfx::BColor& rColor ) -{ - basegfx::B2DPolygon aTarget; - aTarget.append(basegfx::B2DPoint(fX1, fY1)); - aTarget.append(basegfx::B2DPoint(fX2, fY2)); - - pOutDev->SetFillColor(); - pOutDev->SetLineColor(Color(rColor)); - pOutDev->DrawPolyLine(aTarget); -} - -} - namespace drawinglayer { namespace processor2d @@ -306,341 +278,6 @@ namespace drawinglayer return bTryWorked; } - bool VclPixelProcessor2D::tryDrawBorderLinePrimitive2DDirect( - const drawinglayer::primitive2d::BorderLinePrimitive2D& rSource) - { - const basegfx::B2DPoint& rS = rSource.getStart(); - const basegfx::B2DPoint& rE = rSource.getEnd(); - - double fX1 = rS.getX(); - double fY1 = rS.getY(); - double fX2 = rE.getX(); - double fY2 = rE.getY(); - - bool bHorizontal = false; - if (fX1 == fX2) - { - // Vertical line. - } - else if (fY1 == fY2) - { - // Horizontal line. - bHorizontal = true; - } - else - // Neither. Bail out. - return false; - - switch (rSource.getStyle()) - { - case SvxBorderLineStyle::SOLID: - case SvxBorderLineStyle::DOUBLE_THIN: - { - const basegfx::BColor aLineColor = - maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft()); - double nThick = rtl::math::round(rSource.getLeftWidth()); - - bool bDouble = rSource.getStyle() == SvxBorderLineStyle::DOUBLE_THIN; - - basegfx::B2DPolygon aTarget; - - if (bHorizontal) - { - // Horizontal line. Draw it as a rectangle. - - aTarget = makeRectPolygon(fX1, fY1, fX2-fX1, nThick); - aTarget.transform(maCurrentTransformation); - - basegfx::B2DRange aRange = aTarget.getB2DRange(); - double fH = aRange.getHeight(); - - if (bDouble) - { - // Double line - drawHairLine( - mpOutputDevice, aRange.getMinX(), aRange.getMinY()-1.0, aRange.getMaxX(), aRange.getMinY()-1.0, - aLineColor); - - drawHairLine( - mpOutputDevice, aRange.getMinX(), aRange.getMinY()+1.0, aRange.getMaxX(), aRange.getMinY()+1.0, - aLineColor); - - return true; - } - - if (fH <= 1.0) - { - // Draw it as a line. - drawHairLine( - mpOutputDevice, aRange.getMinX(), aRange.getMinY(), aRange.getMaxX(), aRange.getMinY(), - aLineColor); - - return true; - } - - double fOffset = rtl::math::round(fH/2.0, 0, rtl_math_RoundingMode_Down); - if (fOffset != 0.0) - { - // Move it up a bit to align it vertically centered. - basegfx::B2DHomMatrix aMat; - aMat.set(1, 2, -fOffset); - aTarget.transform(aMat); - } - } - else - { - // Vertical line. Draw it as a rectangle. - - aTarget = makeRectPolygon(fX1, fY1, nThick, fY2-fY1); - aTarget.transform(maCurrentTransformation); - - basegfx::B2DRange aRange = aTarget.getB2DRange(); - double fW = aRange.getWidth(); - - if (bDouble) - { - // Draw it as a line. - drawHairLine( - mpOutputDevice, aRange.getMinX()-1.0, aRange.getMinY(), aRange.getMinX()-1.0, aRange.getMaxY(), - aLineColor); - - drawHairLine( - mpOutputDevice, aRange.getMinX()+1.0, aRange.getMinY(), aRange.getMinX()+1.0, aRange.getMaxY(), - aLineColor); - - return true; - } - - if (fW <= 1.0) - { - // Draw it as a line. - drawHairLine( - mpOutputDevice, aRange.getMinX(), aRange.getMinY(), aRange.getMinX(), aRange.getMaxY(), - aLineColor); - - return true; - } - - double fOffset = rtl::math::round(fW/2.0, 0, rtl_math_RoundingMode_Down); - if (fOffset != 0.0) - { - // Move it to the left a bit to center it horizontally. - basegfx::B2DHomMatrix aMat; - aMat.set(0, 2, -fOffset); - aTarget.transform(aMat); - } - } - - mpOutputDevice->SetFillColor(Color(aLineColor)); - mpOutputDevice->SetLineColor(); - mpOutputDevice->DrawPolygon(aTarget); - return true; - } - break; - case SvxBorderLineStyle::DOTTED: - case SvxBorderLineStyle::DASHED: - case SvxBorderLineStyle::DASH_DOT: - case SvxBorderLineStyle::DASH_DOT_DOT: - case SvxBorderLineStyle::FINE_DASHED: - { - std::vector<double> aPattern = - svtools::GetLineDashing(rSource.getStyle(), rSource.getPatternScale()*10.0); - - if (aPattern.empty()) - // Failed to get pattern values. - return false; - - double nThick = rtl::math::round(rSource.getLeftWidth()); - - const basegfx::BColor aLineColor = - maBColorModifierStack.getModifiedColor(rSource.getRGBColorLeft()); - - // Transform the current line range before using it for rendering. - basegfx::B2DRange aRange(fX1, fY1, fX2, fY2); - aRange.transform(maCurrentTransformation); - fX1 = aRange.getMinX(); - fX2 = aRange.getMaxX(); - fY1 = aRange.getMinY(); - fY2 = aRange.getMaxY(); - - basegfx::B2DPolyPolygon aTarget; - - if (bHorizontal) - { - // Horizontal line. - - if (basegfx::fTools::equalZero(nThick)) - { - // Dash line segment too small to draw. Substitute it with a solid line. - drawHairLine(mpOutputDevice, fX1, fY1, fX2, fY1, aLineColor); - return true; - } - - // Create a dash unit polygon set. - basegfx::B2DPolyPolygon aDashes; - std::vector<double>::const_iterator it = aPattern.begin(), itEnd = aPattern.end(); - for (; it != itEnd; ++it) - aDashes.append(makeRectPolygon(0, 0, *it, nThick)); - - aDashes.transform(maCurrentTransformation); - rtl::math::setNan(&nThick); - - // Pixelize the dash unit. We use the same height for - // all dash polygons. - basegfx::B2DPolyPolygon aDashesPix; - - for (sal_uInt32 i = 0, n = aDashes.count(); i < n; ++i) - { - basegfx::B2DPolygon aPoly = aDashes.getB2DPolygon(i); - aRange = aPoly.getB2DRange(); - double fW = rtl::math::round(aRange.getWidth()); - if (basegfx::fTools::equalZero(fW)) - { - // Dash line segment too small to draw. Substitute it with a solid line. - drawHairLine(mpOutputDevice, fX1, fY1, fX2, fY1, aLineColor); - return true; - } - - if (rtl::math::isNan(nThick)) - nThick = rtl::math::round(aRange.getHeight()); - - aDashesPix.append(makeRectPolygon(0, 0, fW, nThick)); - } - - // Make all dash polygons and render them. - double fX = fX1; - bool bLine = true; - sal_uInt32 i = 0, n = aDashesPix.count(); - while (fX <= fX2) - { - basegfx::B2DPolygon aPoly = aDashesPix.getB2DPolygon(i); - aRange = aPoly.getB2DRange(); - if (bLine) - { - double fBlockW = aRange.getWidth(); - if (fX + fBlockW > fX2) - // Clip the right end in case it spills over the range. - fBlockW = fX2 - fX + 1; - - double fH = aRange.getHeight(); - if (basegfx::fTools::equalZero(fH)) - fH = 1.0; - - aTarget.append(makeRectPolygon(fX, fY1, fBlockW, fH)); - } - - bLine = !bLine; // line and blank alternate. - fX += aRange.getWidth(); - - ++i; - if (i >= n) - i = 0; - } - - double fOffset = rtl::math::round(nThick/2.0, 0, rtl_math_RoundingMode_Down); - if (fOffset != 0.0) - { - // Move it up a bit to align it vertically centered. - basegfx::B2DHomMatrix aMat; - aMat.set(1, 2, -fOffset); - aTarget.transform(aMat); - } - } - else - { - // Vertical line. - - if (basegfx::fTools::equalZero(nThick)) - { - // Dash line segment too small to draw. Substitute it with a solid line. - drawHairLine(mpOutputDevice, fX1, fY1, fX1, fY2, aLineColor); - return true; - } - - // Create a dash unit polygon set. - basegfx::B2DPolyPolygon aDashes; - std::vector<double>::const_iterator it = aPattern.begin(), itEnd = aPattern.end(); - for (; it != itEnd; ++it) - aDashes.append(makeRectPolygon(0, 0, nThick, *it)); - - aDashes.transform(maCurrentTransformation); - rtl::math::setNan(&nThick); - - // Pixelize the dash unit. We use the same width for - // all dash polygons. - basegfx::B2DPolyPolygon aDashesPix; - - for (sal_uInt32 i = 0, n = aDashes.count(); i < n; ++i) - { - basegfx::B2DPolygon aPoly = aDashes.getB2DPolygon(i); - aRange = aPoly.getB2DRange(); - double fH = rtl::math::round(aRange.getHeight()); - if (basegfx::fTools::equalZero(fH)) - { - // Dash line segment too small to draw. Substitute it with a solid line. - drawHairLine(mpOutputDevice, fX1, fY1, fX1, fY2, aLineColor); - return true; - } - - if (rtl::math::isNan(nThick)) - nThick = rtl::math::round(aRange.getWidth()); - - aDashesPix.append(makeRectPolygon(0, 0, nThick, fH)); - } - - // Make all dash polygons and render them. - double fY = fY1; - bool bLine = true; - sal_uInt32 i = 0, n = aDashesPix.count(); - while (fY <= fY2) - { - basegfx::B2DPolygon aPoly = aDashesPix.getB2DPolygon(i); - aRange = aPoly.getB2DRange(); - if (bLine) - { - double fBlockH = aRange.getHeight(); - if (fY + fBlockH > fY2) - // Clip the bottom end in case it spills over the range. - fBlockH = fY2 - fY + 1; - - double fW = aRange.getWidth(); - if (basegfx::fTools::equalZero(fW)) - fW = 1.0; - - aTarget.append(makeRectPolygon(fX1, fY, fW, fBlockH)); - } - - bLine = !bLine; // line and blank alternate. - fY += aRange.getHeight(); - - ++i; - if (i >= n) - i = 0; - } - - double fOffset = rtl::math::round(nThick/2.0, 0, rtl_math_RoundingMode_Down); - if (fOffset != 0.0) - { - // Move it to the left a bit to center it horizontally. - basegfx::B2DHomMatrix aMat; - aMat.set(0, 2, -fOffset); - aTarget.transform(aMat); - } - } - - mpOutputDevice->SetFillColor(Color(aLineColor)); - mpOutputDevice->SetLineColor(); - mpOutputDevice->DrawPolyPolygon(aTarget); - - return true; - } - break; - default: - ; - } - return false; - } - void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { switch(rCandidate.getPrimitive2DID()) @@ -1253,28 +890,26 @@ namespace drawinglayer } case PRIMITIVE2D_ID_BORDERLINEPRIMITIVE2D: { - // process recursively, but turn off anti-aliasing. Border - // lines are always rectangular, and look horrible when - // the anti-aliasing is enabled. - AntialiasingFlags nAntiAliasing = mpOutputDevice->GetAntialiasing(); - mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::EnableB2dDraw); - + // process recursively, but switch off AntiAliasing for + // horizontal/vertical lines (*not* diagonal lines). + // Checked using AntialiasingFlags::PixelSnapHairline instead, + // but with AntiAliasing on the display really is too 'ghosty' when + // using fine stroking. Correct, but 'ghosty'. const drawinglayer::primitive2d::BorderLinePrimitive2D& rBorder = static_cast<const drawinglayer::primitive2d::BorderLinePrimitive2D&>(rCandidate); - if (!tryDrawBorderLinePrimitive2DDirect(rBorder)) + if (rBorder.isHorizontalOrVertical(getViewInformation2D())) { - if (rBorder.getStyle() == SvxBorderLineStyle::DOUBLE) - { - primitive2d::Primitive2DContainer aContainer; - rBorder.createDecomposition(aContainer, getViewInformation2D(), true); - process(aContainer); - } - else - process(rCandidate); - } + AntialiasingFlags nAntiAliasing = mpOutputDevice->GetAntialiasing(); + mpOutputDevice->SetAntialiasing(nAntiAliasing & ~AntialiasingFlags::EnableB2dDraw); - mpOutputDevice->SetAntialiasing(nAntiAliasing); + process(rCandidate); + mpOutputDevice->SetAntialiasing(nAntiAliasing); + } + else + { + process(rCandidate); + } break; } default : diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx index 0a8e97d748b8..19c0282ffc5a 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.hxx @@ -64,7 +64,6 @@ namespace drawinglayer bool tryDrawPolyPolygonColorPrimitive2DDirect(const drawinglayer::primitive2d::PolyPolygonColorPrimitive2D& rSource, double fTransparency); bool tryDrawPolygonHairlinePrimitive2DDirect(const drawinglayer::primitive2d::PolygonHairlinePrimitive2D& rSource, double fTransparency); bool tryDrawPolygonStrokePrimitive2DDirect(const drawinglayer::primitive2d::PolygonStrokePrimitive2D& rSource, double fTransparency); - bool tryDrawBorderLinePrimitive2DDirect(const drawinglayer::primitive2d::BorderLinePrimitive2D& rSource); public: /// constructor/destructor diff --git a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx index 4ac0a1045585..4645bde2a2c5 100644 --- a/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/borderlineprimitive2d.hxx @@ -66,27 +66,29 @@ namespace drawinglayer bool mbHasGapColor; SvxBorderLineStyle mnStyle; - double mfPatternScale; - /// local helpers - double getWidth( - const geometry::ViewInformation2D& rViewInformation) const; + // for view dependent decomposition in the case with distance (gap), + // remember the last used concrete mfDistance, see get2DDecomposition + // implementation + double mfDiscreteDistance; + /// local helpers bool isInsideUsed() const { return !basegfx::fTools::equalZero(mfLeftWidth); } + bool isDistanceUsed() const + { + return !basegfx::fTools::equalZero(mfDistance); + } + bool isOutsideUsed() const { return !basegfx::fTools::equalZero(mfRightWidth); } - protected: - virtual basegfx::B2DPolyPolygon getClipPolygon( - const geometry::ViewInformation2D& rViewInformation) const; - /// create local decomposition virtual void create2DDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation) const override; @@ -125,12 +127,16 @@ namespace drawinglayer bool hasGapColor( ) const { return mbHasGapColor; } SvxBorderLineStyle getStyle () const { return mnStyle; } double getPatternScale() const { return mfPatternScale; } - /// Same as create2DDecomposition(), but can do pixel correction if requested. - void createDecomposition(Primitive2DContainer& rContainer, const geometry::ViewInformation2D& rViewInformation, bool bPixelCorrection) const; + + /// helper to decide if AntiAliasing should be used + bool isHorizontalOrVertical(const geometry::ViewInformation2D& rViewInformation) const; /// compare operator virtual bool operator==(const BasePrimitive2D& rPrimitive) const override; + /// Override standard getDecomposition to be view-dependent here + virtual void get2DDecomposition(Primitive2DDecompositionVisitor& rVisitor, const geometry::ViewInformation2D& rViewInformation) const override; + /// provide unique ID DeclPrimitive2DIDBlock() }; diff --git a/include/drawinglayer/primitive2d/clippedborderlineprimitive2d.hxx b/include/drawinglayer/primitive2d/clippedborderlineprimitive2d.hxx deleted file mode 100644 index 3fe2813be9a9..000000000000 --- a/include/drawinglayer/primitive2d/clippedborderlineprimitive2d.hxx +++ /dev/null @@ -1,65 +0,0 @@ -/* -*- 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_DRAWINGLAYER_PRIMITIVE2D_CLIPPEDBORDERLINEPRIMITIVE2D_HXX -#define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_CLIPPEDBORDERLINEPRIMITIVE2D_HXX - -#include <drawinglayer/drawinglayerdllapi.h> - -#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx> -#include <basegfx/polygon/b2dpolypolygon.hxx> -#include <basegfx/polygon/b2dpolygon.hxx> - - -namespace drawinglayer -{ - namespace primitive2d - { - /** BorderLinePrimitive2D clipped by the intersection with a provided - polygon. - */ - class DRAWINGLAYER_DLLPUBLIC ClippedBorderLinePrimitive2D : public BorderLinePrimitive2D - { - private: - const basegfx::B2DPolygon maIntersection; - - protected: - virtual basegfx::B2DPolyPolygon getClipPolygon( - const geometry::ViewInformation2D& rViewInformation) const override; - - public: - /// constructor - ClippedBorderLinePrimitive2D( - const basegfx::B2DPoint& rStart, - const basegfx::B2DPoint& rEnd, - double fLeftWidth, - double fDistance, - double fRightWidth, - const basegfx::B2DPolygon& rIntersection, - const basegfx::BColor& rRGBColorRight, - const basegfx::BColor& rRGBColorLeft, - const basegfx::BColor& rRGBColorGap, - bool bHasGapColor, - SvxBorderLineStyle nStyle, - double fPatternScale ); - - /// compare operator - virtual bool operator==(const BasePrimitive2D& rPrimitive) const override; - - /// provide unique ID - DeclPrimitive2DIDBlock() - }; - } // end of namespace primitive2d -} // end of namespace drawinglayer - - -#endif //INCLUDED_DRAWINGLAYER_PRIMITIVE2D_CLIPPEDBORDERLINEPRIMITIVE2D_HXX - - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/include/svx/framelink.hxx b/include/svx/framelink.hxx index 20ef1dbc6dcc..d5a962acdb1d 100644 --- a/include/svx/framelink.hxx +++ b/include/svx/framelink.hxx @@ -429,7 +429,7 @@ SVX_DLLPUBLIC bool CheckFrameBorderConnectable( | \ / | rLFromB \ / rRFromB */ -SVX_DLLPUBLIC drawinglayer::primitive2d::Primitive2DContainer CreateBorderPrimitives( +SVX_DLLPUBLIC drawinglayer::primitive2d::Primitive2DReference CreateBorderPrimitives( const Point& rLPos, /// Reference point for left end of the processed frame border. const Point& rRPos, /// Reference point for right end of the processed frame border. const Style& rBorder, /// Style of the processed frame border. @@ -451,7 +451,7 @@ SVX_DLLPUBLIC drawinglayer::primitive2d::Primitive2DContainer CreateBorderPrimit const long rRotationB = 9000 /// Angle of the bottom slanted frames in 100th of degree ); -SVX_DLLPUBLIC drawinglayer::primitive2d::Primitive2DContainer CreateBorderPrimitives( +SVX_DLLPUBLIC drawinglayer::primitive2d::Primitive2DReference CreateBorderPrimitives( const Point& rLPos, /// Reference point for left end of the processed frame border. const Point& rRPos, /// Reference point for right end of the processed frame border. const Style& rBorder, /// Style of the processed frame border. @@ -469,10 +469,6 @@ SVX_DLLPUBLIC drawinglayer::primitive2d::Primitive2DContainer CreateBorderPrimit const long rRotationB = 9000 /// Angle of the bottom slanted frame in 100th of degrees ); -SVX_DLLPUBLIC drawinglayer::primitive2d::Primitive2DContainer CreateClippedBorderPrimitives ( - const Point& rStart, const Point& rEnd, const Style& rBorder, - const tools::Rectangle& rClipRect ); - /** Draws a horizontal frame border, regards all connected frame styles. The frame style to draw is passed as parameter rBorder. The function diff --git a/include/svx/framelinkarray.hxx b/include/svx/framelinkarray.hxx index a899caa7ee40..9208f67b46ae 100644 --- a/include/svx/framelinkarray.hxx +++ b/include/svx/framelinkarray.hxx @@ -331,7 +331,7 @@ public: /** Draws the part of the specified range, that is inside the clipping range. @param pForceColor If not NULL, only this color will be used to draw all frame borders. */ - void DrawRange( drawinglayer::processor2d::BaseProcessor2D* rDev, + void DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor, size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow, const Color* pForceColor ) const; @@ -344,7 +344,10 @@ public: size_t nLastCol, size_t nLastRow ) const; /** Draws the part of the array, that is inside the clipping range. */ - void DrawArray( OutputDevice& rDev ) const; + void DrawArray(OutputDevice& rDev) const; + + /** Draws the part of the array, that is inside the clipping range. */ + void DrawArray(drawinglayer::processor2d::BaseProcessor2D& rProcessor) const; private: diff --git a/sc/source/ui/view/output.cxx b/sc/source/ui/view/output.cxx index a1d4db5e12e5..8c656ca45bb7 100644 --- a/sc/source/ui/view/output.cxx +++ b/sc/source/ui/view/output.cxx @@ -1458,7 +1458,7 @@ void ScOutputData::DrawFrame(vcl::RenderContext& rRenderContext) { size_t nRow2 = nRow1; while( (nRow2 + 1 <= nLastRow) && pRowInfo[ nRow2 + 1 ].bChanged ) ++nRow2; - rArray.DrawRange( pProcessor.get(), nFirstCol, nRow1, nLastCol, nRow2, pForceColor ); + rArray.DrawRange( *pProcessor.get(), nFirstCol, nRow1, nLastCol, nRow2, pForceColor ); nRow1 = nRow2 + 1; } } @@ -1759,58 +1759,70 @@ void ScOutputData::DrawRotatedFrame(vcl::RenderContext& rRenderContext, const Co if (aTopLine.Prim() || aTopLine.Secn()) { long nUpperRotate = lcl_getRotate( mpDoc, nTab, nX, nY - 1 ); - pProcessor->process( svx::frame::CreateBorderPrimitives( - aPoints[bLayoutRTL?1:0], aPoints[bLayoutRTL?0:1], aTopLine, - svx::frame::Style(), - svx::frame::Style(), - aLeftLine, - svx::frame::Style(), - svx::frame::Style(), - aRightLine, - pForceColor, nUpperRotate, nAttrRotate ) ); + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + svx::frame::CreateBorderPrimitives( + aPoints[bLayoutRTL?1:0], aPoints[bLayoutRTL?0:1], aTopLine, + svx::frame::Style(), + svx::frame::Style(), + aLeftLine, + svx::frame::Style(), + svx::frame::Style(), + aRightLine, + pForceColor, nUpperRotate, nAttrRotate ) ); + pProcessor->process(aSequence); } if (aBottomLine.Prim() || aBottomLine.Secn()) { long nLowerRotate = lcl_getRotate( mpDoc, nTab, nX, nY + 1 ); - pProcessor->process( svx::frame::CreateBorderPrimitives( - aPoints[bLayoutRTL?2:3], aPoints[bLayoutRTL?3:2], aBottomLine, - aLeftLine, - svx::frame::Style(), - svx::frame::Style(), - aRightLine, - svx::frame::Style(), - svx::frame::Style(), - pForceColor, 18000 - nAttrRotate, 18000 - nLowerRotate ) ); + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + svx::frame::CreateBorderPrimitives( + aPoints[bLayoutRTL?2:3], aPoints[bLayoutRTL?3:2], aBottomLine, + aLeftLine, + svx::frame::Style(), + svx::frame::Style(), + aRightLine, + svx::frame::Style(), + svx::frame::Style(), + pForceColor, 18000 - nAttrRotate, 18000 - nLowerRotate ) ); + pProcessor->process(aSequence); } // Vertical slanted lines if (aLeftLine.Prim() || aLeftLine.Secn()) { long nLeftRotate = lcl_getRotate( mpDoc, nTab, nX - 1, nY ); - pProcessor->process( svx::frame::CreateBorderPrimitives( - aPoints[0], aPoints[3], aLeftLine, - aTopLine, - svx::frame::Style(), - svx::frame::Style(), - aBottomLine, - svx::frame::Style(), - svx::frame::Style(), - pForceColor, nAttrRotate, nLeftRotate ) ); + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + svx::frame::CreateBorderPrimitives( + aPoints[0], aPoints[3], aLeftLine, + aTopLine, + svx::frame::Style(), + svx::frame::Style(), + aBottomLine, + svx::frame::Style(), + svx::frame::Style(), + pForceColor, nAttrRotate, nLeftRotate ) ); + pProcessor->process(aSequence); } if (aRightLine.Prim() || aRightLine.Secn()) { long nRightRotate = lcl_getRotate( mpDoc, nTab, nX + 1, nY ); - pProcessor->process( svx::frame::CreateBorderPrimitives( - aPoints[1], aPoints[2], aRightLine, - svx::frame::Style(), - svx::frame::Style(), - aTopLine, - svx::frame::Style(), - svx::frame::Style(), - aBottomLine, - pForceColor, 18000 - nRightRotate, 18000 - nAttrRotate ) ); + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + svx::frame::CreateBorderPrimitives( + aPoints[1], aPoints[2], aRightLine, + svx::frame::Style(), + svx::frame::Style(), + aTopLine, + svx::frame::Style(), + svx::frame::Style(), + aBottomLine, + pForceColor, 18000 - nRightRotate, 18000 - nAttrRotate ) ); + pProcessor->process(aSequence); } } } diff --git a/svx/source/dialog/framelink.cxx b/svx/source/dialog/framelink.cxx index 2de6d3dae281..d2a1e1ffd06e 100644 --- a/svx/source/dialog/framelink.cxx +++ b/svx/source/dialog/framelink.cxx @@ -33,7 +33,6 @@ #include <basegfx/polygon/b2dpolygontools.hxx> #include <drawinglayer/primitive2d/borderlineprimitive2d.hxx> -#include <drawinglayer/primitive2d/clippedborderlineprimitive2d.hxx> using namespace ::com::sun::star; @@ -1349,9 +1348,34 @@ bool CheckFrameBorderConnectable( const Style& rLBorder, const Style& rRBorder, // Drawing functions +// get offset to center of line in question +double lcl_getCenterOfLineOffset(const Style& rBorder, bool bLeftEdge) +{ + const bool bPrimUsed(!basegfx::fTools::equalZero(rBorder.Prim())); // left + const bool bDistUsed(!basegfx::fTools::equalZero(rBorder.Dist())); // distance + const bool bSecnUsed(!basegfx::fTools::equalZero(rBorder.Secn())); // right + + if (bDistUsed || bSecnUsed) + { + // double line, get center by adding half ditance and half line width. + // bLeftEdge defines which line to use + return (rBorder.Dist() + (bLeftEdge ? rBorder.Prim() : rBorder.Secn())) * 0.5; + } + else if (bPrimUsed) + { + // single line, get center + return rBorder.Prim() * 0.5; + } + + // no line width at all, stay on unit vector + return 0.0; +} -double lcl_GetExtent( const Style& rBorder, const Style& rSide, const Style& rOpposite, - long nAngleSide, long nAngleOpposite ) +double lcl_GetExtent( + const Style& rBorder, const Style& rSide, const Style& rOpposite, + long nAngleSide, long nAngleOpposite, + bool bLeftEdge, // left or right of rBorder + bool bOtherLeft ) // left or right of rSide/rOpposite { Style aOtherBorder = rSide; long nOtherAngle = nAngleSide; @@ -1370,7 +1394,8 @@ double lcl_GetExtent( const Style& rBorder, const Style& rSide, const Style& rOp // Let's assume the border we are drawing is horizontal and compute all the angles / distances from this basegfx::B2DVector aBaseVector( 1.0, 0.0 ); - basegfx::B2DPoint aBasePoint( 0.0, static_cast<double>( rBorder.GetWidth() / 2 ) ); + // added support to get the distances to the centers of the line, *not* the outre edge + basegfx::B2DPoint aBasePoint(0.0, lcl_getCenterOfLineOffset(rBorder, bLeftEdge)); basegfx::B2DHomMatrix aRotation; aRotation.rotate( double( nOtherAngle ) * M_PI / 18000.0 ); @@ -1378,7 +1403,8 @@ double lcl_GetExtent( const Style& rBorder, const Style& rSide, const Style& rOp basegfx::B2DVector aOtherVector = aRotation * aBaseVector; // Compute a line shifted by half the width of the other border basegfx::B2DVector aPerpendicular = basegfx::getNormalizedPerpendicular( aOtherVector ); - basegfx::B2DPoint aOtherPoint = basegfx::B2DPoint() + aPerpendicular * aOtherBorder.GetWidth() / 2; + // added support to get the distances to the centers of the line, *not* the outre edge + basegfx::B2DPoint aOtherPoint = basegfx::B2DPoint() + aPerpendicular * lcl_getCenterOfLineOffset(aOtherBorder, bOtherLeft); // Find the cut between the two lines double nCut = 0.0; @@ -1389,67 +1415,32 @@ double lcl_GetExtent( const Style& rBorder, const Style& rSide, const Style& rOp return nCut; } -basegfx::B2DPoint lcl_PointToB2DPoint( const Point& rPoint ) -{ - return basegfx::B2DPoint(rPoint.getX(), rPoint.getY()); -} - -drawinglayer::primitive2d::Primitive2DContainer CreateClippedBorderPrimitives ( - const Point& rStart, const Point& rEnd, const Style& rBorder, - const tools::Rectangle& rClipRect ) -{ - drawinglayer::primitive2d::Primitive2DContainer aSequence( 1 ); - basegfx::B2DPolygon aPolygon; - aPolygon.append( lcl_PointToB2DPoint( rClipRect.TopLeft( ) ) ); - aPolygon.append( lcl_PointToB2DPoint( rClipRect.TopRight( ) ) ); - aPolygon.append( lcl_PointToB2DPoint( rClipRect.BottomRight( ) ) ); - aPolygon.append( lcl_PointToB2DPoint( rClipRect.BottomLeft( ) ) ); - aPolygon.setClosed( true ); - - aSequence[0] = new drawinglayer::primitive2d::ClippedBorderLinePrimitive2D( - lcl_PointToB2DPoint( rStart ), - lcl_PointToB2DPoint( rEnd ), - rBorder.Prim(), - rBorder.Dist(), - rBorder.Secn(), - aPolygon, - rBorder.GetColorSecn().getBColor(), - rBorder.GetColorPrim().getBColor(), - rBorder.GetColorGap().getBColor(), - rBorder.UseGapColor(), rBorder.Type(), rBorder.PatternScale() ); - - return aSequence; -} - -drawinglayer::primitive2d::Primitive2DContainer CreateBorderPrimitives( +drawinglayer::primitive2d::Primitive2DReference CreateBorderPrimitives( const Point& rLPos, const Point& rRPos, const Style& rBorder, const DiagStyle& /*rLFromTR*/, const Style& rLFromT, const Style& /*rLFromL*/, const Style& rLFromB, const DiagStyle& /*rLFromBR*/, const DiagStyle& /*rRFromTL*/, const Style& rRFromT, const Style& /*rRFromR*/, const Style& rRFromB, const DiagStyle& /*rRFromBL*/, const Color* /*pForceColor*/, long nRotateT, long nRotateB ) { - drawinglayer::primitive2d::Primitive2DContainer aSequence( 1 ); - basegfx::B2DPoint aStart( rLPos.getX(), rLPos.getY() ); basegfx::B2DPoint aEnd( rRPos.getX(), rRPos.getY() ); - aSequence[0] = new drawinglayer::primitive2d::BorderLinePrimitive2D( - aStart, aEnd, - rBorder.Prim(), - rBorder.Dist(), - rBorder.Secn(), - lcl_GetExtent( rBorder, rLFromT, rLFromB, nRotateT, - nRotateB ), - lcl_GetExtent( rBorder, rRFromT, rRFromB, 18000 - nRotateT, nRotateB - 18000 ), - lcl_GetExtent( rBorder, rLFromB, rLFromT, nRotateB, - nRotateT ), - lcl_GetExtent( rBorder, rRFromB, rRFromT, 18000 - nRotateB, nRotateT - 18000 ), - rBorder.GetColorSecn().getBColor(), - rBorder.GetColorPrim().getBColor(), - rBorder.GetColorGap().getBColor(), - rBorder.UseGapColor(), rBorder.Type(), rBorder.PatternScale() ); - - return aSequence; + return drawinglayer::primitive2d::Primitive2DReference( + new drawinglayer::primitive2d::BorderLinePrimitive2D( + aStart, aEnd, + rBorder.Prim(), + rBorder.Dist(), + rBorder.Secn(), + lcl_GetExtent( rBorder, rLFromT, rLFromB, nRotateT, - nRotateB, true, false ), // top-left, so left for rBorder and right for left outer + lcl_GetExtent( rBorder, rRFromT, rRFromB, 18000 - nRotateT, nRotateB - 18000, true, true ), // top-right + lcl_GetExtent( rBorder, rLFromB, rLFromT, nRotateB, - nRotateT, false, false ), // bottom-left + lcl_GetExtent( rBorder, rRFromB, rRFromT, 18000 - nRotateB, nRotateT - 18000, false, true ), // bottom-right + rBorder.GetColorSecn().getBColor(), + rBorder.GetColorPrim().getBColor(), + rBorder.GetColorGap().getBColor(), + rBorder.UseGapColor(), rBorder.Type(), rBorder.PatternScale())); } -drawinglayer::primitive2d::Primitive2DContainer CreateBorderPrimitives( +drawinglayer::primitive2d::Primitive2DReference CreateBorderPrimitives( const Point& rLPos, const Point& rRPos, const Style& rBorder, const Style& rLFromT, const Style& rLFromL, const Style& rLFromB, const Style& rRFromT, const Style& rRFromR, const Style& rRFromB, diff --git a/svx/source/dialog/framelinkarray.cxx b/svx/source/dialog/framelinkarray.cxx index 079a12b9acb3..24f432e3b97d 100644 --- a/svx/source/dialog/framelinkarray.cxx +++ b/svx/source/dialog/framelinkarray.cxx @@ -23,6 +23,7 @@ #include <vector> #include <algorithm> #include <vcl/outdev.hxx> +#include <drawinglayer/primitive2d/borderlineprimitive2d.hxx> namespace svx { namespace frame { @@ -878,7 +879,7 @@ void Array::MirrorSelfX() } // drawing -void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D* pProcessor, +void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D& rProcessor, size_t nFirstCol, size_t nFirstRow, size_t nLastCol, size_t nLastRow, const Color* pForceColor ) const { @@ -907,23 +908,52 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D* pProcessor, size_t _nFirstRow = mxImpl->GetMergedFirstRow( nCol, nRow ); const Style aTlbrStyle = GetCellStyleTLBR( _nFirstCol, _nFirstRow ); - if ( aTlbrStyle.GetWidth( ) ) - pProcessor->process( CreateClippedBorderPrimitives( - aRect.TopLeft(), aRect.BottomRight(), - aTlbrStyle, aRect ) ); + if (aTlbrStyle.GetWidth()) + { + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + new drawinglayer::primitive2d::BorderLinePrimitive2D( + basegfx::B2DPoint(aRect.Left(), aRect.Top()), + basegfx::B2DPoint(aRect.Right(), aRect.Bottom()), + aTlbrStyle.Prim(), + aTlbrStyle.Dist(), + aTlbrStyle.Secn(), + 0.0, 0.0, 0.0, 0.0, + aTlbrStyle.GetColorSecn().getBColor(), + aTlbrStyle.GetColorPrim().getBColor(), + aTlbrStyle.GetColorGap().getBColor(), + aTlbrStyle.UseGapColor(), + aTlbrStyle.Type(), + aTlbrStyle.PatternScale())); + rProcessor.process(aSequence); + } const Style aBltrStyle = GetCellStyleBLTR( _nFirstCol, _nFirstRow ); - if ( aBltrStyle.GetWidth( ) ) - pProcessor->process( CreateClippedBorderPrimitives( - aRect.BottomLeft(), aRect.TopRight(), - aBltrStyle, aRect ) ); + if (aBltrStyle.GetWidth()) + { + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + new drawinglayer::primitive2d::BorderLinePrimitive2D( + basegfx::B2DPoint(aRect.Left(), aRect.Bottom()), + basegfx::B2DPoint(aRect.Right(), aRect.Top()), + aBltrStyle.Prim(), + aBltrStyle.Dist(), + aBltrStyle.Secn(), + 0.0, 0.0, 0.0, 0.0, + aBltrStyle.GetColorSecn().getBColor(), + aBltrStyle.GetColorPrim().getBColor(), + aBltrStyle.GetColorGap().getBColor(), + aBltrStyle.UseGapColor(), + aBltrStyle.Type(), + aBltrStyle.PatternScale())); + rProcessor.process(aSequence); + } } } } } // *** horizontal frame borders *** - for( nRow = nFirstRow; nRow <= nLastRow + 1; ++nRow ) { double fAngle = mxImpl->GetHorDiagAngle( nFirstCol, nRow ); @@ -970,10 +1000,27 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D* pProcessor, { // draw previous frame border Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() ); - if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) ) - pProcessor->process( CreateBorderPrimitives( aStartPos, aEndPos, *pStart, - aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR, - aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor ) ); + if (pStart->Prim() && (aStartPos.X() <= aEndPos.X())) + { + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + CreateBorderPrimitives( + aStartPos, + aEndPos, + *pStart, + aStartLFromTR, + *pStartLFromT, + *pStartLFromL, + *pStartLFromB, + aStartLFromBR, + aEndRFromTL, + *pEndRFromT, + *pEndRFromR, + *pEndRFromB, + aEndRFromBL, + pForceColor)); + rProcessor.process(aSequence); + } // re-init "*Start***" variables aStartPos = aEndPos; @@ -995,10 +1042,27 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D* pProcessor, // draw last frame border Point aEndPos( mxImpl->GetColPosition( nCol ), aStartPos.Y() ); - if( pStart->Prim() && (aStartPos.X() <= aEndPos.X()) ) - pProcessor->process( CreateBorderPrimitives( aStartPos, aEndPos, *pStart, - aStartLFromTR, *pStartLFromT, *pStartLFromL, *pStartLFromB, aStartLFromBR, - aEndRFromTL, *pEndRFromT, *pEndRFromR, *pEndRFromB, aEndRFromBL, pForceColor ) ); + if (pStart->Prim() && (aStartPos.X() <= aEndPos.X())) + { + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + CreateBorderPrimitives( + aStartPos, + aEndPos, + *pStart, + aStartLFromTR, + *pStartLFromT, + *pStartLFromL, + *pStartLFromB, + aStartLFromBR, + aEndRFromTL, + *pEndRFromT, + *pEndRFromR, + *pEndRFromB, + aEndRFromBL, + pForceColor)); + rProcessor.process(aSequence); + } } // *** vertical frame borders *** @@ -1048,10 +1112,35 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D* pProcessor, { // draw previous frame border Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) ); - if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) ) - pProcessor->process( CreateBorderPrimitives( aEndPos, aStartPos, *pStart, - aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR, - aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR, pForceColor ) ); + if (pStart->Prim() && (aStartPos.Y() <= aEndPos.Y())) + { + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + CreateBorderPrimitives( + // This replaces DrawVerFrameBorder which went from top to bottom. To be able to use + // the same method as for horizontal (CreateBorderPrimitives), the given borders + // have to be rearranged. Best is to look at the explanations of parameters in + // framelink.hxx and the former calls to DrawVerFrameBorder and it's parameters. + // In principle, the order of the five TFrom and BFrom has to be + // inverted to get the same orientation. Before, EndPos and StartPos were changed + // which avoids the reordering, but also leads to inverted line patters for vertical + // lines + aStartPos, + aEndPos, + *pStart, + aStartTFromBR, + *pStartTFromR, + *pStartTFromT, + *pStartTFromL, + aStartTFromBL, + aEndBFromTR, + *pEndBFromR, + *pEndBFromB, + *pEndBFromL, + aEndBFromTL, + pForceColor)); + rProcessor.process(aSequence); + } // re-init "*Start***" variables aStartPos = aEndPos; @@ -1073,10 +1162,28 @@ void Array::DrawRange( drawinglayer::processor2d::BaseProcessor2D* pProcessor, // draw last frame border Point aEndPos( aStartPos.X(), mxImpl->GetRowPosition( nRow ) ); - if( pStart->Prim() && (aStartPos.Y() <= aEndPos.Y()) ) - pProcessor->process( CreateBorderPrimitives( aEndPos, aStartPos, *pStart, - aEndBFromTL, *pEndBFromL, *pEndBFromB, *pEndBFromR, aEndBFromTR, - aStartTFromBL, *pStartTFromL, *pStartTFromT, *pStartTFromR, aStartTFromBR, pForceColor ) ); + if (pStart->Prim() && (aStartPos.Y() <= aEndPos.Y())) + { + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + CreateBorderPrimitives( + // also reordered, see call to CreateBorderPrimitives above + aStartPos, + aEndPos, + *pStart, + aStartTFromBR, + *pStartTFromR, + *pStartTFromT, + *pStartTFromL, + aStartTFromBL, + aEndBFromTR, + *pEndBFromR, + *pEndBFromB, + *pEndBFromL, + aEndBFromTL, + pForceColor)); + rProcessor.process(aSequence); + } } } @@ -1291,6 +1398,12 @@ void Array::DrawArray( OutputDevice& rDev ) const DrawRange( rDev, 0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1 ); } +void Array::DrawArray(drawinglayer::processor2d::BaseProcessor2D& rProcessor) const +{ + if (mxImpl->mnWidth && mxImpl->mnHeight) + DrawRange(rProcessor, 0, 0, mxImpl->mnWidth - 1, mxImpl->mnHeight - 1, nullptr); +} + #undef ORIGCELL #undef CELLACC diff --git a/svx/source/dialog/frmsel.cxx b/svx/source/dialog/frmsel.cxx index 7886c117ddf8..02c9493b9d86 100644 --- a/svx/source/dialog/frmsel.cxx +++ b/svx/source/dialog/frmsel.cxx @@ -28,6 +28,7 @@ #include <com/sun/star/accessibility/AccessibleEventId.hpp> #include <com/sun/star/accessibility/AccessibleStateType.hpp> #include <vcl/settings.hxx> +#include <drawinglayer/processor2d/processor2dtools.hxx> #include <svx/dialogs.hrc> #include "bitmaps.hlst" @@ -671,7 +672,36 @@ void FrameSelectorImpl::DrawAllFrameBorders() maArray.SetCellStyleDiag( nCol, nRow, maTLBR.GetUIStyle(), maBLTR.GetUIStyle() ); // Let the helper array draw itself - maArray.DrawArray( *mpVirDev.get() ); + static bool bUsePrimitives(true); + + if (bUsePrimitives) + { + // This is used in the dialog/control for 'Border' attributes. When using + // the original paint below instead of primitives, the advantage currently + // is the correct visualization of diagonal line(s) including overlaying, + // but the rest is bad. Since the edit views use primitives and the preview + // should be 'real' I opt for also changing this to primitives. I will + // keep the old solution and add a switch (above) based on a static bool so + // that interested people may test this out in the debugger. + // This is one more hint to enhance the primitive visualization further to + // support diagonals better - that's the way to go. + const drawinglayer::geometry::ViewInformation2D aNewViewInformation2D; + std::unique_ptr<drawinglayer::processor2d::BaseProcessor2D> pProcessor2D( + drawinglayer::processor2d::createPixelProcessor2DFromOutputDevice( + *mpVirDev.get(), + aNewViewInformation2D)); + + if (pProcessor2D) + { + maArray.DrawArray(*pProcessor2D.get()); + pProcessor2D.reset(); + } + } + else + { + // original paint + maArray.DrawArray(*mpVirDev.get()); + } } void FrameSelectorImpl::DrawVirtualDevice() diff --git a/sw/source/core/layout/paintfrm.cxx b/sw/source/core/layout/paintfrm.cxx index c0ddb50d4ad1..2b45cba8fb22 100644 --- a/sw/source/core/layout/paintfrm.cxx +++ b/sw/source/core/layout/paintfrm.cxx @@ -2747,33 +2747,37 @@ void SwTabFramePainter::PaintLines(OutputDevice& rDev, const SwRect& rRect) cons if (bHori) { - mrTabFrame.ProcessPrimitives( svx::frame::CreateBorderPrimitives( - aPaintStart, - aPaintEnd, - aStyles[ 0 ], // current style - aStyles[ 1 ], // aLFromT - aStyles[ 2 ], // aLFromL - aStyles[ 3 ], // aLFromB - aStyles[ 4 ], // aRFromT - aStyles[ 5 ], // aRFromR - aStyles[ 6 ], // aRFromB - pTmpColor) - ); + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + svx::frame::CreateBorderPrimitives( + aPaintStart, + aPaintEnd, + aStyles[ 0 ], // current style + aStyles[ 1 ], // aLFromT + aStyles[ 2 ], // aLFromL + aStyles[ 3 ], // aLFromB + aStyles[ 4 ], // aRFromT + aStyles[ 5 ], // aRFromR + aStyles[ 6 ], // aRFromB + pTmpColor)); + mrTabFrame.ProcessPrimitives(aSequence); } else { - mrTabFrame.ProcessPrimitives( svx::frame::CreateBorderPrimitives( - aPaintEnd, - aPaintStart, - aStyles[ 0 ], // current style - aStyles[ 4 ], // aBFromL - aStyles[ 5 ], // aBFromB - aStyles[ 6 ], // aBFromR - aStyles[ 1 ], // aTFromL - aStyles[ 2 ], // aTFromT - aStyles[ 3 ], // aTFromR - pTmpColor) - ); + drawinglayer::primitive2d::Primitive2DContainer aSequence(1); + aSequence.append( + svx::frame::CreateBorderPrimitives( + aPaintEnd, + aPaintStart, + aStyles[ 0 ], // current style + aStyles[ 4 ], // aBFromL + aStyles[ 5 ], // aBFromB + aStyles[ 6 ], // aBFromR + aStyles[ 1 ], // aTFromL + aStyles[ 2 ], // aTFromT + aStyles[ 3 ], // aTFromR + pTmpColor)); + mrTabFrame.ProcessPrimitives(aSequence); } } |