From 26bfc77430c40530113d3ce739896139522565f4 Mon Sep 17 00:00:00 2001 From: Jan Holesovsky Date: Wed, 27 Nov 2013 11:51:32 +0100 Subject: [PATCH 006/109] EMF+: Line thickness has to be considered when drawing the caps. Change-Id: I6043ee3c214f453afaef06125993c73be624c07e Reviewed-on: https://gerrit.libreoffice.org/6832 Reviewed-by: Andras Timar Tested-by: Andras Timar --- basegfx/source/polygon/b2dlinegeometry.cxx | 7 +-- cppcanvas/source/inc/implrenderer.hxx | 3 +- cppcanvas/source/mtfrenderer/emfplus.cxx | 75 +++++++++++++++++------------ include/basegfx/polygon/b2dlinegeometry.hxx | 7 ++- 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/basegfx/source/polygon/b2dlinegeometry.cxx b/basegfx/source/polygon/b2dlinegeometry.cxx index 5c016bb..417944d 100644 --- a/basegfx/source/polygon/b2dlinegeometry.cxx +++ b/basegfx/source/polygon/b2dlinegeometry.cxx @@ -44,7 +44,8 @@ namespace basegfx double fWidth, double fCandidateLength, double fDockingPosition, // 0->top, 1->bottom - double* pConsumedLength) + double* pConsumedLength, + double fShift) { B2DPolyPolygon aRetval; OSL_ENSURE(rCandidate.count() > 1L, "createAreaGeometryForLineStartEnd: Line polygon has too less points (!)"); @@ -89,7 +90,7 @@ namespace basegfx const double fArrowYLength(B2DVector(aUpperCenter).getLength()); // move arrow to have docking position centered - aArrowTransform.translate(0.0, -fArrowYLength * fDockingPosition); + aArrowTransform.translate(0.0, -fArrowYLength * fDockingPosition + fShift); // prepare polygon length if(fTools::equalZero(fCandidateLength)) @@ -98,7 +99,7 @@ namespace basegfx } // get the polygon vector we want to plant this arrow on - const double fConsumedLength(fArrowYLength * (1.0 - fDockingPosition)); + const double fConsumedLength(fArrowYLength * (1.0 - fDockingPosition) - fShift); const B2DVector aHead(rCandidate.getB2DPoint((bStart) ? 0L : rCandidate.count() - 1L)); const B2DVector aTail(getPositionAbsolute(rCandidate, (bStart) ? fConsumedLength : fCandidateLength - fConsumedLength, fCandidateLength)); diff --git a/cppcanvas/source/inc/implrenderer.hxx b/cppcanvas/source/inc/implrenderer.hxx index 270c0de..d602945 100644 --- a/cppcanvas/source/inc/implrenderer.hxx +++ b/cppcanvas/source/inc/implrenderer.hxx @@ -282,7 +282,8 @@ static float GetSwapFloat( SvStream& rSt ) double setFont( sal_uInt8 objectId, const ActionFactoryParameters& rParms, OutDevState& rState ); /// Render LineCap, like the start or end arrow of a polygon. - void EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength, + /// @return how much we should shorten the original polygon. + double EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength, const ::basegfx::B2DPolyPolygon& rLineCap, bool bStart, const com::sun::star::rendering::StrokeAttributes& rAttributes, const ActionFactoryParameters& rParms, OutDevState& rState); diff --git a/cppcanvas/source/mtfrenderer/emfplus.cxx b/cppcanvas/source/mtfrenderer/emfplus.cxx index 1d752e7..bf9720b 100644 --- a/cppcanvas/source/mtfrenderer/emfplus.cxx +++ b/cppcanvas/source/mtfrenderer/emfplus.cxx @@ -1320,13 +1320,12 @@ namespace cppcanvas } } - - void ImplRenderer::EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength, + double ImplRenderer::EMFPPlusDrawLineCap(const ::basegfx::B2DPolygon& rPolygon, double fPolyLength, const ::basegfx::B2DPolyPolygon& rLineCap, bool bStart, const rendering::StrokeAttributes& rAttributes, const ActionFactoryParameters& rParms, OutDevState& rState) { if (!rLineCap.count()) - return; + return 0.0; // it seems the line caps in EMF+ are 4*larger than what // LibreOffice expects, and the mapping in @@ -1338,7 +1337,7 @@ namespace cppcanvas basegfx::B2DPolyPolygon aArrow(basegfx::tools::createAreaGeometryForLineStartEnd( rPolygon, rLineCap, bStart, - fWidth, fPolyLength, 0.0, NULL)); + fWidth, fPolyLength, 0, NULL, rAttributes.StrokeWidth)); // createAreaGeometryForLineStartEnd from some reason always sets // the path as closed, correct it @@ -1350,6 +1349,8 @@ namespace cppcanvas maActions.push_back(MtfAction(pAction, rParms.mrCurrActionIndex)); rParms.mrCurrActionIndex += pAction->getActionCount()-1; } + + return rAttributes.StrokeWidth; } void ImplRenderer::EMFPPlusDrawPolygon (const ::basegfx::B2DPolyPolygon& polygon, const ActionFactoryParameters& rParms, @@ -1379,49 +1380,59 @@ namespace cppcanvas rendering::StrokeAttributes aPolygonAttributes(aCommonAttributes); pen->SetStrokeDashing(aPolygonAttributes); - // render the polygon - ActionSharedPtr pPolyAction(internal::PolyPolyActionFactory::createPolyPolyAction(aPolyPolygon, rParms.mrCanvas, rState, aPolygonAttributes)); - if( pPolyAction ) - { - maActions.push_back(MtfAction(pPolyAction, rParms.mrCurrActionIndex)); - rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1; - } + basegfx::B2DPolyPolygon aFinalPolyPolygon; - // render line starts & ends - if (pen->customStartCap || pen->customEndCap) + // render line starts & ends if present + if (!pen->customStartCap && !pen->customEndCap) + aFinalPolyPolygon = aPolyPolygon; + else { for (sal_uInt32 i = 0; i < aPolyPolygon.count(); ++i) { - // break the polypolygon into polygons basegfx::B2DPolygon aPolygon(aPolyPolygon.getB2DPolygon(i)); - if (aPolygon.isClosed()) - continue; + if (!aPolygon.isClosed()) + { + double fStart = 0.0; + double fEnd = 0.0; + double fPolyLength = basegfx::tools::getLength(aPolygon); - double fPolyLength = basegfx::tools::getLength(aPolygon); + // line start + if (pen->customStartCap) + { + rendering::StrokeAttributes aAttributes(aCommonAttributes); + pen->customStartCap->SetAttributes(aAttributes); - // line start - if (pen->customStartCap) - { - rendering::StrokeAttributes aAttributes(aCommonAttributes); - pen->customStartCap->SetAttributes(aAttributes); + fStart = EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customStartCap->polygon, + true, aAttributes, rParms, rState); + } - EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customStartCap->polygon, - true, aAttributes, rParms, rState); - } + // line end + if (pen->customEndCap) + { + rendering::StrokeAttributes aAttributes(aCommonAttributes); + pen->customEndCap->SetAttributes(aAttributes); - // line end - if (pen->customEndCap) - { - rendering::StrokeAttributes aAttributes(aCommonAttributes); - pen->customEndCap->SetAttributes(aAttributes); + fEnd = EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customEndCap->polygon, + false, aAttributes, rParms, rState); + } - EMFPPlusDrawLineCap(aPolygon, fPolyLength, pen->customEndCap->polygon, - false, aAttributes, rParms, rState); + // build new poly, consume something from the old poly + if (fStart != 0.0 || fEnd != 0.0) + aPolygon = basegfx::tools::getSnippetAbsolute(aPolygon, fStart, fPolyLength - fEnd, fPolyLength); } + + aFinalPolyPolygon.append(aPolygon); } } + // finally render the polygon + ActionSharedPtr pPolyAction(internal::PolyPolyActionFactory::createPolyPolyAction(aFinalPolyPolygon, rParms.mrCanvas, rState, aPolygonAttributes)); + if( pPolyAction ) + { + maActions.push_back(MtfAction(pPolyAction, rParms.mrCurrActionIndex)); + rParms.mrCurrActionIndex += pPolyAction->getActionCount()-1; + } } } diff --git a/include/basegfx/polygon/b2dlinegeometry.hxx b/include/basegfx/polygon/b2dlinegeometry.hxx index 934158f..62e230f 100644 --- a/include/basegfx/polygon/b2dlinegeometry.hxx +++ b/include/basegfx/polygon/b2dlinegeometry.hxx @@ -63,6 +63,10 @@ namespace basegfx again calculating the length (which may be expensive with beziers). If 0.0 is given, the length is calculated on demand. + @param fShift + When it is necessary to count with the thickness of the line, it + makes sense to move the start position slightly - so define the shift. + @return The Line start and end polygon, correctly rotated and scaled */ @@ -73,7 +77,8 @@ namespace basegfx double fWidth, double fCandidateLength = 0.0, // 0.0 -> calculate self double fDockingPosition = 0.5, // 0->top, 1->bottom - double* pConsumedLength = 0L); + double* pConsumedLength = 0L, + double fShift = 0.0); /** create filled polygon geometry for lines with a line width -- 1.8.4.2