You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by al...@apache.org on 2012/01/10 12:00:49 UTC
svn commit: r1229503 - in /incubator/ooo/branches/alg/linecap/main:
basegfx/inc/basegfx/polygon/ basegfx/source/polygon/
drawinglayer/inc/drawinglayer/primitive3d/ drawinglayer/source/primitive3d/
Author: alg
Date: Tue Jan 10 11:00:48 2012
New Revision: 1229503
URL: http://svn.apache.org/viewvc?rev=1229503&view=rev
Log:
linecaps: Adapted and partially overhauled 2D line geometry creation; Adapted 3D line geometry creation (tubes) to support LineCap styles
Modified:
incubator/ooo/branches/alg/linecap/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx
incubator/ooo/branches/alg/linecap/main/basegfx/source/polygon/b2dlinegeometry.cxx
incubator/ooo/branches/alg/linecap/main/basegfx/source/polygon/b2dpolygontools.cxx
incubator/ooo/branches/alg/linecap/main/drawinglayer/inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx
incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx
incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
Modified: incubator/ooo/branches/alg/linecap/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/linecap/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx?rev=1229503&r1=1229502&r2=1229503&view=diff
==============================================================================
--- incubator/ooo/branches/alg/linecap/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx (original)
+++ incubator/ooo/branches/alg/linecap/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx Tue Jan 10 11:00:48 2012
@@ -285,6 +285,9 @@ namespace basegfx
*/
B2DPolygon createPolygonFromCircle( const B2DPoint& rCenter, double fRadius );
+ /// create half circle centered on (0,0) from [0 .. F_PI]
+ B2DPolygon createHalfUnitCircle();
+
/** create a polygon which describes the unit circle and close it
@param nStartQuadrant
Modified: incubator/ooo/branches/alg/linecap/main/basegfx/source/polygon/b2dlinegeometry.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/linecap/main/basegfx/source/polygon/b2dlinegeometry.cxx?rev=1229503&r1=1229502&r2=1229503&view=diff
==============================================================================
--- incubator/ooo/branches/alg/linecap/main/basegfx/source/polygon/b2dlinegeometry.cxx (original)
+++ incubator/ooo/branches/alg/linecap/main/basegfx/source/polygon/b2dlinegeometry.cxx Tue Jan 10 11:00:48 2012
@@ -339,7 +339,13 @@ namespace basegfx
}
}
- B2DPolygon createAreaGeometryForEdge(const B2DCubicBezier& rEdge, double fHalfLineWidth)
+ B2DPolyPolygon createAreaGeometryForEdge(
+ const B2DCubicBezier& rEdge,
+ double fHalfLineWidth,
+ bool bStartRound,
+ bool bEndRound,
+ bool bStartSquare,
+ bool bEndSquare)
{
// create polygon for edge
// Unfortunately, while it would be geometrically correct to not add
@@ -348,35 +354,102 @@ namespace basegfx
if(rEdge.isBezier())
{
// prepare target and data common for upper and lower
+ B2DPolyPolygon aRetval;
B2DPolygon aBezierPolygon;
- const B2DVector aPureEdgeVector(rEdge.getEndPoint() - rEdge.getStartPoint());
+ const B2DVector aPureEdgeVector(rEdge.getEndPoint() - rEdge.getStartPoint());
const double fEdgeLength(aPureEdgeVector.getLength());
const bool bIsEdgeLengthZero(fTools::equalZero(fEdgeLength));
- const B2DVector aTangentA(rEdge.getTangent(0.0));
- const B2DVector aTangentB(rEdge.getTangent(1.0));
+ B2DVector aTangentA(rEdge.getTangent(0.0)); aTangentA.normalize();
+ B2DVector aTangentB(rEdge.getTangent(1.0)); aTangentB.normalize();
+ const B2DVector aNormalizedPerpendicularA(getPerpendicular(aTangentA));
+ const B2DVector aNormalizedPerpendicularB(getPerpendicular(aTangentB));
+
+ // create upper displacement vectors and check if they cut
+ const B2DVector aPerpendStartA(aNormalizedPerpendicularA * -fHalfLineWidth);
+ const B2DVector aPerpendEndA(aNormalizedPerpendicularB * -fHalfLineWidth);
+ double fCutA(0.0);
+ const tools::CutFlagValue aCutA(tools::findCut(
+ rEdge.getStartPoint(), aPerpendStartA,
+ rEdge.getEndPoint(), aPerpendEndA,
+ CUTFLAG_ALL, &fCutA));
+ const bool bCutA(CUTFLAG_NONE != aCutA);
+
+ // create lower displacement vectors and check if they cut
+ const B2DVector aPerpendStartB(aNormalizedPerpendicularA * fHalfLineWidth);
+ const B2DVector aPerpendEndB(aNormalizedPerpendicularB * fHalfLineWidth);
+ double fCutB(0.0);
+ const tools::CutFlagValue aCutB(tools::findCut(
+ rEdge.getEndPoint(), aPerpendEndB,
+ rEdge.getStartPoint(), aPerpendStartB,
+ CUTFLAG_ALL, &fCutB));
+ const bool bCutB(CUTFLAG_NONE != aCutB);
- // create upper edge.
+ // check if cut happens
+ const bool bCut(bCutA || bCutB);
+
+ // create left edge
+ if(bStartRound || bStartSquare)
{
- // create displacement vectors and check if they cut
- const B2DVector aPerpendStart(getNormalizedPerpendicular(aTangentA) * -fHalfLineWidth);
- const B2DVector aPerpendEnd(getNormalizedPerpendicular(aTangentB) * -fHalfLineWidth);
- double fCut(0.0);
- const tools::CutFlagValue aCut(tools::findCut(
- rEdge.getStartPoint(), aPerpendStart,
- rEdge.getEndPoint(), aPerpendEnd,
- CUTFLAG_ALL, &fCut));
+ basegfx::B2DPolygon aStartPolygon;
- if(CUTFLAG_NONE != aCut)
+ if(bStartRound)
+ {
+ aStartPolygon = tools::createHalfUnitCircle();
+ aStartPolygon.transform(
+ tools::createScaleShearXRotateTranslateB2DHomMatrix(
+ fHalfLineWidth, fHalfLineWidth,
+ 0.0,
+ atan2(aTangentA.getY(), aTangentA.getX()) + F_PI2,
+ rEdge.getStartPoint().getX(), rEdge.getStartPoint().getY()));
+ }
+ else // bStartSquare
+ {
+ const basegfx::B2DPoint aStart(rEdge.getStartPoint() - (aTangentA * fHalfLineWidth));
+
+ if(bCut)
+ {
+ aStartPolygon.append(rEdge.getStartPoint() + aPerpendStartB);
+ }
+
+ aStartPolygon.append(aStart + aPerpendStartB);
+ aStartPolygon.append(aStart + aPerpendStartA);
+
+ if(bCut)
+ {
+ aStartPolygon.append(rEdge.getStartPoint() + aPerpendStartA);
+ }
+ }
+
+ if(bCut)
+ {
+ aStartPolygon.append(rEdge.getStartPoint());
+ aStartPolygon.setClosed(true);
+ aRetval.append(aStartPolygon);
+ }
+ else
+ {
+ aBezierPolygon.append(aStartPolygon);
+ }
+ }
+ else
+ {
+ // append original in-between point
+ aBezierPolygon.append(rEdge.getStartPoint());
+ }
+
+ // create upper edge.
+ {
+ if(bCutA)
{
// calculate cut point and add
- const B2DPoint aCutPoint(rEdge.getStartPoint() + (aPerpendStart * fCut));
+ const B2DPoint aCutPoint(rEdge.getStartPoint() + (aPerpendStartA * fCutA));
aBezierPolygon.append(aCutPoint);
}
else
{
// create scaled bezier segment
- const B2DPoint aStart(rEdge.getStartPoint() + aPerpendStart);
- const B2DPoint aEnd(rEdge.getEndPoint() + aPerpendEnd);
+ const B2DPoint aStart(rEdge.getStartPoint() + aPerpendStartA);
+ const B2DPoint aEnd(rEdge.getEndPoint() + aPerpendEndA);
const B2DVector aEdge(aEnd - aStart);
const double fLength(aEdge.getLength());
const double fScale(bIsEdgeLengthZero ? 1.0 : fLength / fEdgeLength);
@@ -388,31 +461,69 @@ namespace basegfx
}
}
- // append original in-between point
- aBezierPolygon.append(rEdge.getEndPoint());
+ // create right edge
+ if(bEndRound || bEndSquare)
+ {
+ basegfx::B2DPolygon aEndPolygon;
- // create lower edge.
+ if(bEndRound)
+ {
+ aEndPolygon = tools::createHalfUnitCircle();
+ aEndPolygon.transform(
+ tools::createScaleShearXRotateTranslateB2DHomMatrix(
+ fHalfLineWidth, fHalfLineWidth,
+ 0.0,
+ atan2(aTangentB.getY(), aTangentB.getX()) - F_PI2,
+ rEdge.getEndPoint().getX(), rEdge.getEndPoint().getY()));
+ }
+ else // bEndSquare
+ {
+ const basegfx::B2DPoint aEnd(rEdge.getEndPoint() + (aTangentB * fHalfLineWidth));
+
+ if(bCut)
+ {
+ aEndPolygon.append(rEdge.getEndPoint() + aPerpendEndA);
+ }
+
+ aEndPolygon.append(aEnd + aPerpendEndA);
+ aEndPolygon.append(aEnd + aPerpendEndB);
+
+ if(bCut)
+ {
+ aEndPolygon.append(rEdge.getEndPoint() + aPerpendEndB);
+ }
+ }
+
+ if(bCut)
+ {
+ aEndPolygon.append(rEdge.getEndPoint());
+ aEndPolygon.setClosed(true);
+ aRetval.append(aEndPolygon);
+ }
+ else
+ {
+ aBezierPolygon.append(aEndPolygon);
+ }
+ }
+ else
{
- // create displacement vectors and check if they cut
- const B2DVector aPerpendStart(getNormalizedPerpendicular(aTangentA) * fHalfLineWidth);
- const B2DVector aPerpendEnd(getNormalizedPerpendicular(aTangentB) * fHalfLineWidth);
- double fCut(0.0);
- const tools::CutFlagValue aCut(tools::findCut(
- rEdge.getEndPoint(), aPerpendEnd,
- rEdge.getStartPoint(), aPerpendStart,
- CUTFLAG_ALL, &fCut));
+ // append original in-between point
+ aBezierPolygon.append(rEdge.getEndPoint());
+ }
- if(CUTFLAG_NONE != aCut)
+ // create lower edge.
+ {
+ if(bCutB)
{
// calculate cut point and add
- const B2DPoint aCutPoint(rEdge.getEndPoint() + (aPerpendEnd * fCut));
+ const B2DPoint aCutPoint(rEdge.getEndPoint() + (aPerpendEndB * fCutB));
aBezierPolygon.append(aCutPoint);
}
else
{
// create scaled bezier segment
- const B2DPoint aStart(rEdge.getEndPoint() + aPerpendEnd);
- const B2DPoint aEnd(rEdge.getStartPoint() + aPerpendStart);
+ const B2DPoint aStart(rEdge.getEndPoint() + aPerpendEndB);
+ const B2DPoint aEnd(rEdge.getStartPoint() + aPerpendStartB);
const B2DVector aEdge(aEnd - aStart);
const double fLength(aEdge.getLength());
const double fScale(bIsEdgeLengthZero ? 1.0 : fLength / fEdgeLength);
@@ -424,39 +535,108 @@ namespace basegfx
}
}
- // append original in-between point
- aBezierPolygon.append(rEdge.getStartPoint());
-
// close and return
aBezierPolygon.setClosed(true);
- return aBezierPolygon;
+ aRetval.append(aBezierPolygon);
+
+ return aRetval;
}
else
{
- // #i101491# emulate rEdge.getTangent call which applies a factor of 0.3 to the
- // full-length edge vector to have numerically exactly the same results as in the
- // createAreaGeometryForJoin implementation
- const B2DVector aEdgeTangent((rEdge.getEndPoint() - rEdge.getStartPoint()) * 0.3);
- const B2DVector aPerpendEdgeVector(getNormalizedPerpendicular(aEdgeTangent) * fHalfLineWidth);
- B2DPolygon aEdgePolygon;
+ // Get start and end point, create tangent and set to needed length
+ B2DVector aTangent(rEdge.getEndPoint() - rEdge.getStartPoint());
+ aTangent.setLength(fHalfLineWidth);
- // create upper edge
- aEdgePolygon.append(rEdge.getStartPoint() - aPerpendEdgeVector);
- aEdgePolygon.append(rEdge.getEndPoint() - aPerpendEdgeVector);
-
- // append original in-between point
- aEdgePolygon.append(rEdge.getEndPoint());
+ // prepare return value
+ B2DPolygon aEdgePolygon;
+
+ // buffered angle
+ double fAngle(0.0);
+ bool bAngle(false);
+
+ // buffered perpendicular
+ B2DVector aPerpend;
+ bool bPerpend(false);
+
+ // create left vertical
+ if(bStartRound)
+ {
+ aEdgePolygon = tools::createHalfUnitCircle();
+ fAngle = atan2(aTangent.getY(), aTangent.getX());
+ bAngle = true;
+ aEdgePolygon.transform(
+ tools::createScaleShearXRotateTranslateB2DHomMatrix(
+ fHalfLineWidth, fHalfLineWidth,
+ 0.0,
+ fAngle + F_PI2,
+ rEdge.getStartPoint().getX(), rEdge.getStartPoint().getY()));
+ }
+ else
+ {
+ aPerpend.setX(-aTangent.getY());
+ aPerpend.setY(aTangent.getX());
+ bPerpend = true;
+
+ if(bStartSquare)
+ {
+ const basegfx::B2DPoint aStart(rEdge.getStartPoint() - aTangent);
+
+ aEdgePolygon.append(aStart + aPerpend);
+ aEdgePolygon.append(aStart - aPerpend);
+ }
+ else
+ {
+ aEdgePolygon.append(rEdge.getStartPoint() + aPerpend);
+ aEdgePolygon.append(rEdge.getStartPoint()); // keep the in-between point for numerical reasons
+ aEdgePolygon.append(rEdge.getStartPoint() - aPerpend);
+ }
+ }
- // create lower edge
- aEdgePolygon.append(rEdge.getEndPoint() + aPerpendEdgeVector);
- aEdgePolygon.append(rEdge.getStartPoint() + aPerpendEdgeVector);
+ // create right vertical
+ if(bEndRound)
+ {
+ basegfx::B2DPolygon aEndPolygon(tools::createHalfUnitCircle());
- // append original in-between point
- aEdgePolygon.append(rEdge.getStartPoint());
+ if(!bAngle)
+ {
+ fAngle = atan2(aTangent.getY(), aTangent.getX());
+ }
+
+ aEndPolygon.transform(
+ tools::createScaleShearXRotateTranslateB2DHomMatrix(
+ fHalfLineWidth, fHalfLineWidth,
+ 0.0,
+ fAngle - F_PI2,
+ rEdge.getEndPoint().getX(), rEdge.getEndPoint().getY()));
+ aEdgePolygon.append(aEndPolygon);
+ }
+ else
+ {
+ if(!bPerpend)
+ {
+ aPerpend.setX(-aTangent.getY());
+ aPerpend.setY(aTangent.getX());
+ }
+
+ if(bEndSquare)
+ {
+ const basegfx::B2DPoint aEnd(rEdge.getEndPoint() + aTangent);
+
+ aEdgePolygon.append(aEnd - aPerpend);
+ aEdgePolygon.append(aEnd + aPerpend);
+ }
+ else
+ {
+ aEdgePolygon.append(rEdge.getEndPoint() - aPerpend);
+ aEdgePolygon.append(rEdge.getEndPoint()); // keep the in-between point for numerical reasons
+ aEdgePolygon.append(rEdge.getEndPoint() + aPerpend);
+ }
+ }
// close and return
aEdgePolygon.setClosed(true);
- return aEdgePolygon;
+
+ return B2DPolyPolygon(aEdgePolygon);
}
}
@@ -567,82 +747,6 @@ namespace basegfx
return aEdgePolygon;
}
-
- B2DPolygon createAreaGeometryForCap(
- const B2DVector& rTangent,
- const B2DPoint& rPoint,
- double fHalfLineWidth,
- com::sun::star::drawing::LineCap eCap,
- bool bIsStart)
- {
- OSL_ENSURE(fHalfLineWidth > 0.0, "createAreaGeometryForJoin: LineWidth too small (!)");
-
- const B2DVector aScaledPerpend(getNormalizedPerpendicular(rTangent)
- * (bIsStart ? fHalfLineWidth : -fHalfLineWidth));
- // Vector from rPoint towards cap
- B2DVector aScaledTangent(rTangent);
- aScaledTangent.normalize();
- aScaledTangent *= (bIsStart ? -fHalfLineWidth : fHalfLineWidth);
-
- B2DPolygon aCapPolygon;
- const B2DPoint aStartPoint(rPoint + aScaledPerpend);
- const B2DPoint aEndPoint(rPoint - aScaledPerpend);
-
- switch(eCap)
- {
- case com::sun::star::drawing::LineCap_ROUND :
- {
- // use tooling to add needed EllipseSegment
- double fAngleStart(atan2(aScaledPerpend.getY(), aScaledPerpend.getX()));
-
- // atan2 results are [-PI .. PI], consolidate to [0.0 .. 2PI]
- if(fAngleStart < 0.0)
- {
- fAngleStart += F_2PI;
- }
-
- double fAngleEnd = fAngleStart + F_PI;
- if(fAngleEnd > F_2PI)
- {
- fAngleEnd -= F_2PI;
- }
-
- const B2DPolygon aBow(tools::createPolygonFromEllipseSegment(rPoint, fHalfLineWidth, fHalfLineWidth, fAngleStart, fAngleEnd));
- // #i101491#
- // use the original start/end positions; the ones from bow creation may be numerically
- // different due to their different creation. To guarantee good merging quality with edges
- // and edge roundings (and to reduce point count)
-
- // ToDo Are there at least two points in aBow ?
- aCapPolygon = aBow;
- aCapPolygon.setB2DPoint(0, aStartPoint);
- aCapPolygon.setB2DPoint(aBow.count() - 1, aEndPoint);
- aCapPolygon.append(rPoint);
- break;
- }
- case com::sun::star::drawing::LineCap_SQUARE :
- {
- aCapPolygon.append(aStartPoint);
- aCapPolygon.append(aStartPoint + aScaledTangent);
- aCapPolygon.append(aEndPoint + aScaledTangent);
- aCapPolygon.append(aEndPoint);
- aCapPolygon.append(rPoint);
- break;
- }
- default: // com::sun::star::drawing::LineCap_BUTT
- {
- // No cap.
- // ToDo. Is actually not called with BUTT. What setting is
- // useful to prevend errors, if called with BUTT anyway?
- break;
- }
- }
-
- // create last polygon part for cap
- aCapPolygon.setClosed(true);
-
- return aCapPolygon;
- }
} // end of anonymus namespace
namespace tools
@@ -697,7 +801,7 @@ namespace basegfx
const bool bEventuallyCreateLineJoin(B2DLINEJOIN_NONE != eJoin);
const bool bIsClosed(aCandidate.isClosed());
const sal_uInt32 nEdgeCount(bIsClosed ? nPointCount : nPointCount - 1);
- const bool bCreateLineCap(com::sun::star::drawing::LineCap_BUTT != eCap);
+ const bool bLineCap(!bIsClosed && com::sun::star::drawing::LineCap_BUTT != eCap);
if(nEdgeCount)
{
@@ -707,18 +811,6 @@ namespace basegfx
// prepare edge
aEdge.setStartPoint(aCandidate.getB2DPoint(0));
- // eventually create start line cap
- if (!bIsClosed && bCreateLineCap)
- {
- aEdge.setControlPointA(aCandidate.getNextControlPoint(0));
- aEdge.setControlPointB(aCandidate.getPrevControlPoint(1 % nPointCount));
- aEdge.setEndPoint(aCandidate.getB2DPoint(1 % nPointCount ));
- const B2DVector aTangentStart(aEdge.getTangent(0.0));
- aRetval.append(createAreaGeometryForCap(
- aTangentStart, aEdge.getStartPoint(),
- fHalfLineWidth, eCap, true /*IsStart*/));
- }
-
if(bIsClosed && bEventuallyCreateLineJoin)
{
// prepare previous edge
@@ -740,85 +832,110 @@ namespace basegfx
// check and create linejoin
if(bEventuallyCreateLineJoin && (bIsClosed || 0 != a))
{
- const B2DVector aTangentPrev(aPrev.getTangent(1.0));
- const B2DVector aTangentEdge(aEdge.getTangent(0.0));
+ B2DVector aTangentPrev(aPrev.getTangent(1.0)); aTangentPrev.normalize();
+ B2DVector aTangentEdge(aEdge.getTangent(0.0)); aTangentEdge.normalize();
B2VectorOrientation aOrientation(getOrientation(aTangentPrev, aTangentEdge));
- if(ORIENTATION_NEUTRAL == aOrientation)
- {
- // they are parallell or empty; if they are both not zero and point
- // in opposite direction, a half-circle is needed
- if(!aTangentPrev.equalZero() && !aTangentEdge.equalZero())
- {
- const double fAngle(fabs(aTangentPrev.angle(aTangentEdge)));
-
- if(fTools::equal(fAngle, F_PI))
- {
+ if(ORIENTATION_NEUTRAL == aOrientation)
+ {
+ // they are parallell or empty; if they are both not zero and point
+ // in opposite direction, a half-circle is needed
+ if(!aTangentPrev.equalZero() && !aTangentEdge.equalZero())
+ {
+ const double fAngle(fabs(aTangentPrev.angle(aTangentEdge)));
+
+ if(fTools::equal(fAngle, F_PI))
+ {
// for half-circle production, fallback to positive
// orientation
- aOrientation = ORIENTATION_POSITIVE;
- }
- }
- }
+ aOrientation = ORIENTATION_POSITIVE;
+ }
+ }
+ }
if(ORIENTATION_POSITIVE == aOrientation)
{
- const B2DVector aPerpendPrev(getNormalizedPerpendicular(aTangentPrev) * -fHalfLineWidth);
- const B2DVector aPerpendEdge(getNormalizedPerpendicular(aTangentEdge) * -fHalfLineWidth);
+ const B2DVector aPerpendPrev(getPerpendicular(aTangentPrev) * -fHalfLineWidth);
+ const B2DVector aPerpendEdge(getPerpendicular(aTangentEdge) * -fHalfLineWidth);
- aRetval.append(createAreaGeometryForJoin(
- aTangentPrev, aTangentEdge,
- aPerpendPrev, aPerpendEdge,
- aEdge.getStartPoint(), fHalfLineWidth,
- eJoin, fMiterMinimumAngle));
+ aRetval.append(
+ createAreaGeometryForJoin(
+ aTangentPrev,
+ aTangentEdge,
+ aPerpendPrev,
+ aPerpendEdge,
+ aEdge.getStartPoint(),
+ fHalfLineWidth,
+ eJoin,
+ fMiterMinimumAngle));
}
else if(ORIENTATION_NEGATIVE == aOrientation)
{
- const B2DVector aPerpendPrev(getNormalizedPerpendicular(aTangentPrev) * fHalfLineWidth);
- const B2DVector aPerpendEdge(getNormalizedPerpendicular(aTangentEdge) * fHalfLineWidth);
+ const B2DVector aPerpendPrev(getPerpendicular(aTangentPrev) * fHalfLineWidth);
+ const B2DVector aPerpendEdge(getPerpendicular(aTangentEdge) * fHalfLineWidth);
- aRetval.append(createAreaGeometryForJoin(
- aTangentEdge, aTangentPrev,
- aPerpendEdge, aPerpendPrev,
- aEdge.getStartPoint(), fHalfLineWidth,
- eJoin, fMiterMinimumAngle));
+ aRetval.append(
+ createAreaGeometryForJoin(
+ aTangentEdge,
+ aTangentPrev,
+ aPerpendEdge,
+ aPerpendPrev,
+ aEdge.getStartPoint(),
+ fHalfLineWidth,
+ eJoin,
+ fMiterMinimumAngle));
}
}
// create geometry for edge
- aRetval.append(createAreaGeometryForEdge(aEdge, fHalfLineWidth));
+ const bool bLast(a + 1 == nEdgeCount);
- // prepare next step
- if(bEventuallyCreateLineJoin)
+ if(bLineCap)
+ {
+ const bool bFirst(!a);
+
+ aRetval.append(
+ createAreaGeometryForEdge(
+ aEdge,
+ fHalfLineWidth,
+ bFirst && com::sun::star::drawing::LineCap_ROUND == eCap,
+ bLast && com::sun::star::drawing::LineCap_ROUND == eCap,
+ bFirst && com::sun::star::drawing::LineCap_SQUARE == eCap,
+ bLast && com::sun::star::drawing::LineCap_SQUARE == eCap));
+ }
+ else
{
- aPrev = aEdge;
+ aRetval.append(
+ createAreaGeometryForEdge(
+ aEdge,
+ fHalfLineWidth,
+ false,
+ false,
+ false,
+ false));
}
- aEdge.setStartPoint(aEdge.getEndPoint());
- }
+ // prepare next step
+ if(!bLast)
+ {
+ if(bEventuallyCreateLineJoin)
+ {
+ aPrev = aEdge;
+ }
- // eventually create end line cap
- if (!bIsClosed && bCreateLineCap)
- {
- aEdge.setStartPoint(aCandidate.getB2DPoint(nEdgeCount -1));
- aEdge.setControlPointA(aCandidate.getNextControlPoint(nEdgeCount -1));
- aEdge.setControlPointB(aCandidate.getPrevControlPoint(nEdgeCount % nPointCount));
- aEdge.setEndPoint(aCandidate.getB2DPoint(nEdgeCount % nPointCount ));
- const B2DVector aTangentEnd(aEdge.getTangent(1.0));
- aRetval.append(createAreaGeometryForCap(
- aTangentEnd, aEdge.getEndPoint(),
- fHalfLineWidth, eCap, false /*IsStart*/));
+ aEdge.setStartPoint(aEdge.getEndPoint());
+ }
}
}
- // ToDo Returns empty PolyPolygon if rCandidate is a single point?
+
return aRetval;
- }
+ }
else
{
return B2DPolyPolygon(rCandidate);
}
- }
- } // end of namespace tools
+ }
+ } // end of namespace tools
} // end of namespace basegfx
//////////////////////////////////////////////////////////////////////////////
Modified: incubator/ooo/branches/alg/linecap/main/basegfx/source/polygon/b2dpolygontools.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/linecap/main/basegfx/source/polygon/b2dpolygontools.cxx?rev=1229503&r1=1229502&r2=1229503&view=diff
==============================================================================
--- incubator/ooo/branches/alg/linecap/main/basegfx/source/polygon/b2dpolygontools.cxx (original)
+++ incubator/ooo/branches/alg/linecap/main/basegfx/source/polygon/b2dpolygontools.cxx Tue Jan 10 11:00:48 2012
@@ -1889,6 +1889,33 @@ namespace basegfx
return aUnitCircle;
}
+ B2DPolygon createHalfUnitCircle()
+ {
+ static B2DPolygon aUnitHalfCircle;
+
+ if(!aUnitHalfCircle.count())
+ {
+ const double fKappa((M_SQRT2 - 1.0) * 4.0 / 3.0);
+ const double fScaledKappa(fKappa * (1.0 / STEPSPERQUARTER));
+ const B2DHomMatrix aRotateMatrix(createRotateB2DHomMatrix(F_PI2 / STEPSPERQUARTER));
+ B2DPoint aPoint(1.0, 0.0);
+ B2DPoint aForward(1.0, fScaledKappa);
+ B2DPoint aBackward(1.0, -fScaledKappa);
+
+ aUnitHalfCircle.append(aPoint);
+
+ for(sal_uInt32 a(0); a < STEPSPERQUARTER * 2; a++)
+ {
+ aPoint *= aRotateMatrix;
+ aBackward *= aRotateMatrix;
+ aUnitHalfCircle.appendBezierSegment(aForward, aBackward, aPoint);
+ aForward *= aRotateMatrix;
+ }
+ }
+
+ return aUnitHalfCircle;
+ }
+
B2DPolygon createPolygonFromUnitCircle(sal_uInt32 nStartQuadrant)
{
switch(nStartQuadrant % 4)
Modified: incubator/ooo/branches/alg/linecap/main/drawinglayer/inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/linecap/main/drawinglayer/inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx?rev=1229503&r1=1229502&r2=1229503&view=diff
==============================================================================
--- incubator/ooo/branches/alg/linecap/main/drawinglayer/inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx (original)
+++ incubator/ooo/branches/alg/linecap/main/drawinglayer/inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx Tue Jan 10 11:00:48 2012
@@ -59,6 +59,7 @@ namespace drawinglayer
double mfDegreeStepWidth;
double mfMiterMinimumAngle;
basegfx::B2DLineJoin maLineJoin;
+ com::sun::star::drawing::LineCap maLineCap;
protected:
/** access methods to maLast3DDecomposition. The usage of this methods may allow
@@ -76,7 +77,9 @@ namespace drawinglayer
PolygonTubePrimitive3D(
const basegfx::B3DPolygon& rPolygon,
const basegfx::BColor& rBColor,
- double fRadius, basegfx::B2DLineJoin aLineJoin,
+ double fRadius,
+ basegfx::B2DLineJoin aLineJoin,
+ com::sun::star::drawing::LineCap aLineCap,
double fDegreeStepWidth = 10.0 * F_PI180,
double fMiterMinimumAngle = 15.0 * F_PI180);
@@ -85,6 +88,7 @@ namespace drawinglayer
double getDegreeStepWidth() const { return mfDegreeStepWidth; }
double getMiterMinimumAngle() const { return mfMiterMinimumAngle; }
basegfx::B2DLineJoin getLineJoin() const { return maLineJoin; }
+ com::sun::star::drawing::LineCap getLineCap() const { return maLineCap; }
/// compare operator
virtual bool operator==(const BasePrimitive3D& rPrimitive) const;
Modified: incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/polygonprimitive3d.cxx?rev=1229503&r1=1229502&r2=1229503&view=diff
==============================================================================
--- incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/polygonprimitive3d.cxx (original)
+++ incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/polygonprimitive3d.cxx Tue Jan 10 11:00:48 2012
@@ -106,11 +106,18 @@ namespace drawinglayer
// create fat line data
const double fRadius(getLineAttribute().getWidth() / 2.0);
const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin());
+ const com::sun::star::drawing::LineCap aLineCap(getLineAttribute().getLineCap());
for(sal_uInt32 a(0L); a < aHairLinePolyPolygon.count(); a++)
{
// create tube primitives
- const Primitive3DReference xRef(new PolygonTubePrimitive3D(aHairLinePolyPolygon.getB3DPolygon(a), getLineAttribute().getColor(), fRadius, aLineJoin));
+ const Primitive3DReference xRef(
+ new PolygonTubePrimitive3D(
+ aHairLinePolyPolygon.getB3DPolygon(a),
+ getLineAttribute().getColor(),
+ fRadius,
+ aLineJoin,
+ aLineCap));
aRetval[a] = xRef;
}
}
Modified: incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx?rev=1229503&r1=1229502&r2=1229503&view=diff
==============================================================================
--- incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx (original)
+++ incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx Tue Jan 10 11:00:48 2012
@@ -156,6 +156,76 @@ namespace drawinglayer
return aLineCapList;
}
+ Primitive3DSequence getLineCapRoundSegments(
+ sal_uInt32 nSegments,
+ const attribute::MaterialAttribute3D& rMaterial)
+ {
+ // static data for buffered tube primitives
+ static Primitive3DSequence aLineCapRoundList;
+ static sal_uInt32 nLineCapRoundSegments(0);
+ static attribute::MaterialAttribute3D aLineMaterial;
+
+ // may exclusively change static data, use mutex
+ ::osl::Mutex m_mutex;
+
+ if(nSegments != nLineCapRoundSegments || !(rMaterial == aLineMaterial))
+ {
+ nLineCapRoundSegments = nSegments;
+ aLineMaterial = rMaterial;
+ aLineCapRoundList = Primitive3DSequence();
+ }
+
+ if(!aLineCapRoundList.hasElements() && nLineCapRoundSegments)
+ {
+ // calculate new horizontal segments
+ sal_uInt32 nVerSeg(nSegments / 2);
+
+ if(nVerSeg < 1)
+ {
+ nVerSeg = 1;
+ }
+
+ // create half-sphere; upper half of unit sphere
+ basegfx::B3DPolyPolygon aSphere(
+ basegfx::tools::createUnitSphereFillPolyPolygon(
+ nSegments,
+ nVerSeg,
+ true,
+ F_PI2, 0.0,
+ 0.0, F_2PI));
+ const sal_uInt32 nCount(aSphere.count());
+
+ if(nCount)
+ {
+ // rotate to have sphere cap orientned to negative X-Axis; do not
+ // forget to transform normals, too
+ basegfx::B3DHomMatrix aSphereTrans;
+
+ aSphereTrans.rotate(0.0, 0.0, F_PI2);
+ aSphere.transform(aSphereTrans);
+ aSphere.transformNormals(aSphereTrans);
+
+ // realloc for primitives and create based on polygon snippets
+ aLineCapRoundList.realloc(nCount);
+
+ for(sal_uInt32 a(0); a < nCount; a++)
+ {
+ const basegfx::B3DPolygon aPartPolygon(aSphere.getB3DPolygon(a));
+ const basegfx::B3DPolyPolygon aPartPolyPolygon(aPartPolygon);
+
+ // need to create one primitive per Polygon since the primitive
+ // is for planar PolyPolygons which is definitely not the case here
+ aLineCapRoundList[a] = new PolyPolygonMaterialPrimitive3D(
+ aPartPolyPolygon,
+ rMaterial,
+ false);
+ }
+ }
+ }
+
+ return aLineCapRoundList;
+ }
+
Primitive3DSequence getLineJoinSegments(
sal_uInt32 nSegments,
const attribute::MaterialAttribute3D& rMaterial,
@@ -173,7 +243,7 @@ namespace drawinglayer
if(basegfx::B2DLINEJOIN_ROUND == aLineJoin)
{
// calculate new horizontal segments
- const sal_uInt32 nHorSeg((sal_uInt32)((fAngle / F_2PI) * (double)nSegments));
+ const sal_uInt32 nHorSeg(basegfx::fround((fAngle / F_2PI) * (double)nSegments));
if(nHorSeg)
{
@@ -403,100 +473,188 @@ using namespace com::sun::star;
namespace drawinglayer
{
- namespace primitive3d
- {
- Primitive3DSequence PolygonTubePrimitive3D::impCreate3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
- {
- const sal_uInt32 nPointCount(getB3DPolygon().count());
- std::vector< BasePrimitive3D* > aResultVector;
-
- if(0L != nPointCount)
- {
- if(basegfx::fTools::more(getRadius(), 0.0))
- {
- const attribute::MaterialAttribute3D aMaterial(getBColor());
- static sal_uInt32 nSegments(8L); // default for 3d line segments, for more quality just raise this value (in even steps)
- const bool bClosed(getB3DPolygon().isClosed());
- const bool bNoLineJoin(basegfx::B2DLINEJOIN_NONE == getLineJoin());
- const sal_uInt32 nLoopCount(bClosed ? nPointCount : nPointCount - 1L);
- basegfx::B3DPoint aLast(getB3DPolygon().getB3DPoint(nPointCount - 1L));
- basegfx::B3DPoint aCurr(getB3DPolygon().getB3DPoint(0L));
-
- for(sal_uInt32 a(0L); a < nLoopCount; a++)
- {
- // get next data
- const basegfx::B3DPoint aNext(getB3DPolygon().getB3DPoint((a + 1L) % nPointCount));
- const basegfx::B3DVector aForw(aNext - aCurr);
- const double fForwLen(aForw.getLength());
-
- if(basegfx::fTools::more(fForwLen, 0.0))
- {
- // get rotation from vector, this describes rotation from (1, 0, 0) to aForw
- basegfx::B3DHomMatrix aRotVector(getRotationFromVector(aForw));
-
- // create default transformation with scale and rotate
- basegfx::B3DHomMatrix aVectorTrans;
- aVectorTrans.scale(fForwLen, getRadius(), getRadius());
- aVectorTrans *= aRotVector;
- aVectorTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
-
- if(bNoLineJoin || (!bClosed && !a))
- {
- // line start edge, build transformed primitiveVector3D
- TransformPrimitive3D* pNewTransformedA = new TransformPrimitive3D(aVectorTrans, getLineCapSegments(nSegments, aMaterial));
- aResultVector.push_back(pNewTransformedA);
- }
- else
- {
- const basegfx::B3DVector aBack(aCurr - aLast);
- const double fCross(basegfx::cross(aBack, aForw).getLength());
-
- if(!basegfx::fTools::equalZero(fCross))
- {
- // line connect non-parallel, aBack, aForw, use getLineJoin()
- const double fAngle(acos(aBack.scalar(aForw) / (fForwLen * aBack.getLength()))); // 0.0 .. F_PI2
- Primitive3DSequence aNewList(getLineJoinSegments(nSegments, aMaterial, fAngle, getDegreeStepWidth(), getMiterMinimumAngle(), getLineJoin()));
-
- // calculate transformation. First, get angle in YZ between nForw projected on (1, 0, 0) and nBack
- basegfx::B3DHomMatrix aInvRotVector(aRotVector);
- aInvRotVector.invert();
- basegfx::B3DVector aTransBack(aInvRotVector * aBack);
- const double fRotInYZ(atan2(aTransBack.getY(), aTransBack.getZ()));
-
- // create trans by rotating unit sphere with angle 90 degrees around Y, then 180-fRot in X.
- // Also apply usual scaling and translation
- basegfx::B3DHomMatrix aSphereTrans;
- aSphereTrans.rotate(0.0, F_PI2, 0.0);
- aSphereTrans.rotate(F_PI - fRotInYZ, 0.0, 0.0);
- aSphereTrans *= aRotVector;
- aSphereTrans.scale(getRadius(), getRadius(), getRadius());
- aSphereTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
-
- // line start edge, build transformed primitiveVector3D
- TransformPrimitive3D* pNewTransformedB = new TransformPrimitive3D(aSphereTrans, aNewList);
- aResultVector.push_back(pNewTransformedB);
- }
- }
-
- // create line segments, build transformed primitiveVector3D
- TransformPrimitive3D* pNewTransformedC = new TransformPrimitive3D(aVectorTrans, getLineTubeSegments(nSegments, aMaterial));
- aResultVector.push_back(pNewTransformedC);
-
- if(bNoLineJoin || (!bClosed && ((a + 1L) == nLoopCount)))
- {
- // line end edge, first rotate (mirror) and translate, then use use aRotVector
- basegfx::B3DHomMatrix aBackTrans;
- aBackTrans.rotate(0.0, F_PI, 0.0);
- aBackTrans.translate(1.0, 0.0, 0.0);
- aBackTrans.scale(fForwLen, getRadius(), getRadius());
- aBackTrans *= aRotVector;
- aBackTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
-
- // line end edge, build transformed primitiveVector3D
- TransformPrimitive3D* pNewTransformedD = new TransformPrimitive3D(aBackTrans, getLineCapSegments(nSegments, aMaterial));
- aResultVector.push_back(pNewTransformedD);
- }
- }
+ namespace primitive3d
+ {
+ Primitive3DSequence PolygonTubePrimitive3D::impCreate3DDecomposition(const geometry::ViewInformation3D& /*rViewInformation*/) const
+ {
+ const sal_uInt32 nPointCount(getB3DPolygon().count());
+ std::vector< BasePrimitive3D* > aResultVector;
+
+ if(nPointCount)
+ {
+ if(basegfx::fTools::more(getRadius(), 0.0))
+ {
+ const attribute::MaterialAttribute3D aMaterial(getBColor());
+ static sal_uInt32 nSegments(8); // default for 3d line segments, for more quality just raise this value (in even steps)
+ const bool bClosed(getB3DPolygon().isClosed());
+ const bool bNoLineJoin(basegfx::B2DLINEJOIN_NONE == getLineJoin());
+ const sal_uInt32 nLoopCount(bClosed ? nPointCount : nPointCount - 1);
+ basegfx::B3DPoint aLast(getB3DPolygon().getB3DPoint(nPointCount - 1));
+ basegfx::B3DPoint aCurr(getB3DPolygon().getB3DPoint(0));
+
+ for(sal_uInt32 a(0); a < nLoopCount; a++)
+ {
+ // get next data
+ const basegfx::B3DPoint aNext(getB3DPolygon().getB3DPoint((a + 1) % nPointCount));
+ const basegfx::B3DVector aForw(aNext - aCurr);
+ const double fForwLen(aForw.getLength());
+
+ if(basegfx::fTools::more(fForwLen, 0.0))
+ {
+ // find out if linecap is active
+ const bool bFirst(!a);
+ const bool bLast(a + 1 == nLoopCount);
+ const bool bLineCapPossible(!bClosed && (bFirst || bLast));
+ const bool bLineCapRound(bLineCapPossible && com::sun::star::drawing::LineCap_ROUND == getLineCap());
+ const bool bLineCapSquare(bLineCapPossible && com::sun::star::drawing::LineCap_SQUARE == getLineCap());
+
+ // get rotation from vector, this describes rotation from (1, 0, 0) to aForw
+ basegfx::B3DHomMatrix aRotVector(getRotationFromVector(aForw));
+
+ // prepare transformations for tube and cap
+ basegfx::B3DHomMatrix aTubeTrans;
+ basegfx::B3DHomMatrix aCapTrans;
+
+ // cap gets radius size
+ aCapTrans.scale(getRadius(), getRadius(), getRadius());
+
+ if(bLineCapSquare)
+ {
+ // when square line cap just prolong line segment in X, maybe 2 x radius when
+ // first and last (simple line segment)
+ const double fExtraLength(bFirst && bLast ? getRadius() * 2.0 : getRadius());
+
+ aTubeTrans.scale(fForwLen + fExtraLength, getRadius(), getRadius());
+
+ if(bFirst)
+ {
+ // correct start positions for tube and cap when first and square prolonged
+ aTubeTrans.translate(-getRadius(), 0.0, 0.0);
+ aCapTrans.translate(-getRadius(), 0.0, 0.0);
+ }
+ }
+ else
+ {
+ // normal tube size
+ aTubeTrans.scale(fForwLen, getRadius(), getRadius());
+ }
+
+ // rotate and translate tube and cap
+ aTubeTrans *= aRotVector;
+ aTubeTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
+ aCapTrans *= aRotVector;
+ aCapTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
+
+ if(bNoLineJoin || (!bClosed && bFirst))
+ {
+ // line start edge, build transformed primitiveVector3D
+ Primitive3DSequence aSequence;
+
+ if(bLineCapRound && bFirst)
+ {
+ // LineCapRound used
+ aSequence = getLineCapRoundSegments(nSegments, aMaterial);
+ }
+ else
+ {
+ // simple closing cap
+ aSequence = getLineCapSegments(nSegments, aMaterial);
+ }
+
+ TransformPrimitive3D* pNewTransformedA = new TransformPrimitive3D(aCapTrans, aSequence);
+ aResultVector.push_back(pNewTransformedA);
+ }
+ else
+ {
+ const basegfx::B3DVector aBack(aCurr - aLast);
+ const double fCross(basegfx::cross(aBack, aForw).getLength());
+
+ if(!basegfx::fTools::equalZero(fCross))
+ {
+ // line connect non-parallel, aBack, aForw, use getLineJoin()
+ const double fAngle(acos(aBack.scalar(aForw) / (fForwLen * aBack.getLength()))); // 0.0 .. F_PI2
+ Primitive3DSequence aNewList(
+ getLineJoinSegments(
+ nSegments,
+ aMaterial,
+ fAngle,
+ getDegreeStepWidth(),
+ getMiterMinimumAngle(),
+ getLineJoin()));
+
+ // calculate transformation. First, get angle in YZ between nForw projected on (1, 0, 0) and nBack
+ basegfx::B3DHomMatrix aInvRotVector(aRotVector);
+ aInvRotVector.invert();
+ basegfx::B3DVector aTransBack(aInvRotVector * aBack);
+ const double fRotInYZ(atan2(aTransBack.getY(), aTransBack.getZ()));
+
+ // create trans by rotating unit sphere with angle 90 degrees around Y, then 180-fRot in X.
+ // Also apply usual scaling and translation
+ basegfx::B3DHomMatrix aSphereTrans;
+ aSphereTrans.rotate(0.0, F_PI2, 0.0);
+ aSphereTrans.rotate(F_PI - fRotInYZ, 0.0, 0.0);
+ aSphereTrans *= aRotVector;
+ aSphereTrans.scale(getRadius(), getRadius(), getRadius());
+ aSphereTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
+
+ // line start edge, build transformed primitiveVector3D
+ aResultVector.push_back(
+ new TransformPrimitive3D(
+ aSphereTrans,
+ aNewList));
+ }
+ }
+
+ // create line segments, build transformed primitiveVector3D
+ aResultVector.push_back(
+ new TransformPrimitive3D(
+ aTubeTrans,
+ getLineTubeSegments(nSegments, aMaterial)));
+
+ if(bNoLineJoin || (!bClosed && bLast))
+ {
+ // line end edge
+ basegfx::B3DHomMatrix aBackCapTrans;
+
+ // Mirror (line end) and radius scale
+ aBackCapTrans.rotate(0.0, F_PI, 0.0);
+ aBackCapTrans.scale(getRadius(), getRadius(), getRadius());
+
+ if(bLineCapSquare && bLast)
+ {
+ // correct position when square and prolonged
+ aBackCapTrans.translate(fForwLen + getRadius(), 0.0, 0.0);
+ }
+ else
+ {
+ // standard position
+ aBackCapTrans.translate(fForwLen, 0.0, 0.0);
+ }
+
+ // rotate and translate to destination
+ aBackCapTrans *= aRotVector;
+ aBackCapTrans.translate(aCurr.getX(), aCurr.getY(), aCurr.getZ());
+
+ // get primitiveVector3D
+ Primitive3DSequence aSequence;
+
+ if(bLineCapRound && bLast)
+ {
+ // LineCapRound used
+ aSequence = getLineCapRoundSegments(nSegments, aMaterial);
+ }
+ else
+ {
+ // simple closing cap
+ aSequence = getLineCapSegments(nSegments, aMaterial);
+ }
+
+ aResultVector.push_back(
+ new TransformPrimitive3D(
+ aBackCapTrans,
+ aSequence));
+ }
+ }
// prepare next loop step
aLast = aCurr;
@@ -526,6 +684,7 @@ namespace drawinglayer
const basegfx::B3DPolygon& rPolygon,
const basegfx::BColor& rBColor,
double fRadius, basegfx::B2DLineJoin aLineJoin,
+ com::sun::star::drawing::LineCap aLineCap,
double fDegreeStepWidth,
double fMiterMinimumAngle)
: PolygonHairlinePrimitive3D(rPolygon, rBColor),
@@ -533,7 +692,8 @@ namespace drawinglayer
mfRadius(fRadius),
mfDegreeStepWidth(fDegreeStepWidth),
mfMiterMinimumAngle(fMiterMinimumAngle),
- maLineJoin(aLineJoin)
+ maLineJoin(aLineJoin),
+ maLineCap(aLineCap)
{
}
@@ -546,7 +706,8 @@ namespace drawinglayer
return (getRadius() == rCompare.getRadius()
&& getDegreeStepWidth() == rCompare.getDegreeStepWidth()
&& getMiterMinimumAngle() == rCompare.getMiterMinimumAngle()
- && getLineJoin() == rCompare.getLineJoin());
+ && getLineJoin() == rCompare.getLineJoin()
+ && getLineCap() == rCompare.getLineCap());
}
return false;
Modified: incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx?rev=1229503&r1=1229502&r2=1229503&view=diff
==============================================================================
--- incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx (original)
+++ incubator/ooo/branches/alg/linecap/main/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx Tue Jan 10 11:00:48 2012
@@ -150,7 +150,7 @@ namespace drawinglayer
aScaledPolyPolygon.transform(rObjectTransform);
// create line and stroke attribute
- const attribute::LineAttribute aLineAttribute(rLine.getColor(), rLine.getWidth(), rLine.getJoin());
+ const attribute::LineAttribute aLineAttribute(rLine.getColor(), rLine.getWidth(), rLine.getJoin(), rLine.getCap());
const attribute::StrokeAttribute aStrokeAttribute(rLine.getDotDashArray(), rLine.getFullDotDashLen());
// create primitives