diff options
author | Armin Le Grand <Armin.Le.Grand@cib.de> | 2017-07-04 16:28:58 +0200 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@cib.de> | 2017-07-12 21:01:20 +0200 |
commit | f65cbae8947c0462b35c8d3c3d5124e431b100b6 (patch) | |
tree | e8248f034f7a97e1716f9477937b55ae31038a76 /svx/source/dialog | |
parent | fc55711f01af172eb3a034454405fa941454c781 (diff) |
borderline: correct problems with border display
Borderline display with direct paint and with primitive direct
paint has quite some errors in the current state. Started to
unify usages, check deeper with creation/usage.
borderline: deep changes to BorderLine
Found basic error in determining the offset values
for BorderLinePrimitive creation, these were not
centered on the lines. Corrected that. This makes
it possible to remove the formally used clipping
which seems to have been used to correct that. Also
allows to go back to a 'normal' decomposition that
creates line primitives as expected. That again can
then be painted quite normally.
Also added view-dependent case to the decomposition
to guarantee a gap of one discrete unit (pixel).
Removed the direct painter, too. Checked and corrected
stroking.
borderline: Adapted previews to primitives
Added code to use the primitive representation in
all dialogs and apps using tables. The edit views
use these mostly, so the preview should do that,
too. Currently missing is a good visualization of
diagonals, but this is also true for edit views.
Checked all apps and table usages to not get worse
borderline: correct line dash visualization
When a dashed line is used, a factor of 10.0 was applied in the
original coded, added that. Also the orientation of vertical
borders was inverted since it was simpler to exchange Start/End,
but this also mirrors the line dash visualisation, corrected that
Change-Id: I4c1b380a76cb37389fab1259a53fb7cc9da982d1
e95e246d5563360617a2a2213e4d5ec7d0e736b9
62369b4de58fb0264aeb710ec6983ceddca5701d
77418cc6c84ebb0632f8c3448976e82ce612d6b6
b4eb28dc86ce05eb89b26517167305b994158ef8
borderline: adapt cppunittest and clang
Diffstat (limited to 'svx/source/dialog')
-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 |
3 files changed, 217 insertions, 83 deletions
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() |