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