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/17 18:54:06 UTC

svn commit: r1232507 [1/3] - in /incubator/ooo/trunk: ./ main/basegfx/inc/basegfx/polygon/ main/basegfx/source/polygon/ main/canvas/source/vcl/ main/cppcanvas/source/mtfrenderer/ main/cui/source/inc/ main/cui/source/tabpages/ main/drawinglayer/inc/draw...

Author: alg
Date: Tue Jan 17 17:54:04 2012
New Revision: 1232507

URL: http://svn.apache.org/viewvc?rev=1232507&view=rev
Log:
linecap: Reintegrating finished LineCap feature, kudos to Regina Henschel for doing the basic implementation and offering it under apache license

Added:
    incubator/ooo/trunk/main/offapi/com/sun/star/drawing/LineCap.idl
      - copied unchanged from r1232461, incubator/ooo/branches/alg/linecap/main/offapi/com/sun/star/drawing/LineCap.idl
    incubator/ooo/trunk/main/svx/inc/svx/xlncapit.hxx
      - copied unchanged from r1232461, incubator/ooo/branches/alg/linecap/main/svx/inc/svx/xlncapit.hxx
Modified:
    incubator/ooo/trunk/   (props changed)
    incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dlinegeometry.hxx
    incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx
    incubator/ooo/trunk/main/basegfx/source/polygon/b2dlinegeometry.cxx
    incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx
    incubator/ooo/trunk/main/basegfx/source/polygon/b3dpolygontools.cxx
    incubator/ooo/trunk/main/basegfx/source/polygon/b3dpolypolygontools.cxx
    incubator/ooo/trunk/main/canvas/source/vcl/canvashelper.cxx
    incubator/ooo/trunk/main/cppcanvas/source/mtfrenderer/implrenderer.cxx
    incubator/ooo/trunk/main/cui/source/inc/cuitabline.hxx
    incubator/ooo/trunk/main/cui/source/tabpages/tabline.hrc
    incubator/ooo/trunk/main/cui/source/tabpages/tabline.src
    incubator/ooo/trunk/main/cui/source/tabpages/tpline.cxx
    incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/attribute/lineattribute.hxx
    incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/attribute/sdrlineattribute.hxx
    incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx
    incubator/ooo/trunk/main/drawinglayer/source/attribute/lineattribute.cxx
    incubator/ooo/trunk/main/drawinglayer/source/attribute/sdrlineattribute.cxx
    incubator/ooo/trunk/main/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
    incubator/ooo/trunk/main/drawinglayer/source/primitive2d/polygonprimitive2d.cxx
    incubator/ooo/trunk/main/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
    incubator/ooo/trunk/main/drawinglayer/source/primitive3d/polygontubeprimitive3d.cxx
    incubator/ooo/trunk/main/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
    incubator/ooo/trunk/main/drawinglayer/source/processor2d/canvasprocessor.cxx
    incubator/ooo/trunk/main/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx
    incubator/ooo/trunk/main/editeng/inc/editeng/unoprnms.hxx
    incubator/ooo/trunk/main/filter/source/graphicfilter/eps/eps.cxx
    incubator/ooo/trunk/main/filter/source/msfilter/escherex.cxx
    incubator/ooo/trunk/main/filter/source/msfilter/msdffimp.cxx
    incubator/ooo/trunk/main/filter/source/svg/svgwriter.cxx
    incubator/ooo/trunk/main/filter/source/svg/svgwriter.hxx
    incubator/ooo/trunk/main/offapi/com/sun/star/drawing/LineProperties.idl
    incubator/ooo/trunk/main/offapi/com/sun/star/drawing/makefile.mk
    incubator/ooo/trunk/main/svgio/source/svgreader/svgstyleattributes.cxx
    incubator/ooo/trunk/main/svx/Package_inc.mk
    incubator/ooo/trunk/main/svx/inc/svx/dialogs.hrc
    incubator/ooo/trunk/main/svx/inc/svx/unoshprp.hxx
    incubator/ooo/trunk/main/svx/inc/svx/xattr.hxx
    incubator/ooo/trunk/main/svx/inc/svx/xdef.hxx
    incubator/ooo/trunk/main/svx/source/dialog/sdstring.src
    incubator/ooo/trunk/main/svx/source/sdr/attribute/sdrformtextattribute.cxx
    incubator/ooo/trunk/main/svx/source/sdr/primitive2d/sdrattributecreator.cxx
    incubator/ooo/trunk/main/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx
    incubator/ooo/trunk/main/svx/source/svdraw/svdfmtf.cxx
    incubator/ooo/trunk/main/svx/source/svdraw/svdfmtf.hxx
    incubator/ooo/trunk/main/svx/source/xoutdev/xattr2.cxx
    incubator/ooo/trunk/main/svx/source/xoutdev/xpool.cxx
    incubator/ooo/trunk/main/vcl/aqua/source/gdi/salgdi.cxx
    incubator/ooo/trunk/main/vcl/inc/aqua/salgdi.h
    incubator/ooo/trunk/main/vcl/inc/os2/salgdi.h
    incubator/ooo/trunk/main/vcl/inc/salgdi.hxx
    incubator/ooo/trunk/main/vcl/inc/unx/pspgraphics.h
    incubator/ooo/trunk/main/vcl/inc/unx/salgdi.h
    incubator/ooo/trunk/main/vcl/inc/vcl/cvtsvm.hxx
    incubator/ooo/trunk/main/vcl/inc/vcl/lineinfo.hxx
    incubator/ooo/trunk/main/vcl/inc/vcl/outdev.hxx
    incubator/ooo/trunk/main/vcl/inc/vcl/print.hxx
    incubator/ooo/trunk/main/vcl/inc/win/salgdi.h
    incubator/ooo/trunk/main/vcl/source/gdi/cvtsvm.cxx
    incubator/ooo/trunk/main/vcl/source/gdi/lineinfo.cxx
    incubator/ooo/trunk/main/vcl/source/gdi/outdev.cxx
    incubator/ooo/trunk/main/vcl/source/gdi/outdev6.cxx
    incubator/ooo/trunk/main/vcl/source/gdi/pdfwriter_impl.cxx
    incubator/ooo/trunk/main/vcl/source/gdi/salgdilayout.cxx
    incubator/ooo/trunk/main/vcl/unx/generic/gdi/pspgraphics.cxx
    incubator/ooo/trunk/main/vcl/unx/generic/gdi/salgdi.cxx
    incubator/ooo/trunk/main/vcl/unx/headless/svpgdi.cxx
    incubator/ooo/trunk/main/vcl/unx/headless/svpgdi.hxx
    incubator/ooo/trunk/main/vcl/unx/headless/svppspgraphics.cxx
    incubator/ooo/trunk/main/vcl/unx/headless/svppspgraphics.hxx
    incubator/ooo/trunk/main/vcl/win/source/gdi/salgdi_gdiplus.cxx
    incubator/ooo/trunk/main/xmloff/inc/xmloff/xmltoken.hxx
    incubator/ooo/trunk/main/xmloff/source/core/xmltoken.cxx
    incubator/ooo/trunk/main/xmloff/source/draw/sdpropls.cxx
    incubator/ooo/trunk/main/xmloff/source/draw/sdpropls.hxx

Propchange: incubator/ooo/trunk/
------------------------------------------------------------------------------
--- svn:mergeinfo (original)
+++ svn:mergeinfo Tue Jan 17 17:54:04 2012
@@ -1 +1,2 @@
+/incubator/ooo/branches/alg/linecap:1226811-1232461
 /incubator/ooo/branches/alg/svgreplacement:1205420-1220782

Modified: incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dlinegeometry.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dlinegeometry.hxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dlinegeometry.hxx (original)
+++ incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dlinegeometry.hxx Tue Jan 17 17:54:04 2012
@@ -28,6 +28,7 @@
 #include <basegfx/numeric/ftools.hxx>
 #include <basegfx/polygon/b2dpolypolygon.hxx>
 #include <basegfx/polygon/b2dpolygon.hxx>
+#include <com/sun/star/drawing/LineCap.hpp>
 
 //////////////////////////////////////////////////////////////////////////////
 
@@ -101,6 +102,9 @@ namespace basegfx
             The LineJoin if the edges meeting in a point do not have a C1
             or C2 continuity
 
+            @param eCap
+            The kind of cap, which is added to the line.
+
             @param fMaxAllowedAngle
             Allows to hand over the maximum allowed angle between an edge and
             it's control vectors. The smaller, the more subdivisions will be
@@ -128,6 +132,7 @@ namespace basegfx
             const B2DPolygon& rCandidate, 
             double fHalfLineWidth, 
             B2DLineJoin eJoin = B2DLINEJOIN_ROUND, 
+            com::sun::star::drawing::LineCap eCap = com::sun::star::drawing::LineCap_BUTT,
             double fMaxAllowedAngle = (12.5 * F_PI180), 
 			double fMaxPartOfEdge = 0.4,
             double fMiterMinimumAngle = (15.0 * F_PI180));

Modified: incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx (original)
+++ incubator/ooo/trunk/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx Tue Jan 17 17:54:04 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/trunk/main/basegfx/source/polygon/b2dlinegeometry.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/source/polygon/b2dlinegeometry.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/basegfx/source/polygon/b2dlinegeometry.cxx (original)
+++ incubator/ooo/trunk/main/basegfx/source/polygon/b2dlinegeometry.cxx Tue Jan 17 17:54:04 2012
@@ -34,6 +34,7 @@
 #include <basegfx/matrix/b2dhommatrix.hxx>
 #include <basegfx/curve/b2dcubicbezier.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
+#include <com/sun/star/drawing/LineCap.hpp>
 
 //////////////////////////////////////////////////////////////////////////////
 
@@ -338,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
@@ -347,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);
@@ -387,31 +461,69 @@ namespace basegfx
                     }
                 }
 
-                // append original in-between point
-                aBezierPolygon.append(rEdge.getEndPoint());
+                // create right edge
+                if(bEndRound || bEndSquare)
+                {
+                    basegfx::B2DPolygon aEndPolygon;
+
+                    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));
 
-                // create lower edge. 
+                        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);
@@ -423,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;
-                
-                // create upper edge
-                aEdgePolygon.append(rEdge.getStartPoint() - aPerpendEdgeVector);
-                aEdgePolygon.append(rEdge.getEndPoint() - aPerpendEdgeVector);
+                // Get start and  end point, create tangent and set to needed length
+                B2DVector aTangent(rEdge.getEndPoint() - rEdge.getStartPoint());
+                aTangent.setLength(fHalfLineWidth);
                 
-                // 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);
 
-                // create lower edge
-                aEdgePolygon.append(rEdge.getEndPoint() + aPerpendEdgeVector);
-                aEdgePolygon.append(rEdge.getStartPoint() + aPerpendEdgeVector);
+                        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);
+                    }
+                }
 
-                // append original in-between point
-                aEdgePolygon.append(rEdge.getStartPoint());
+                // create right vertical
+                if(bEndRound)
+                {
+                    basegfx::B2DPolygon aEndPolygon(tools::createHalfUnitCircle());
+
+                    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);
             }
         }
 
@@ -574,6 +755,7 @@ namespace basegfx
             const B2DPolygon& rCandidate, 
             double fHalfLineWidth, 
             B2DLineJoin eJoin, 
+            com::sun::star::drawing::LineCap eCap,
             double fMaxAllowedAngle, 
 			double fMaxPartOfEdge,
             double fMiterMinimumAngle)
@@ -619,6 +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 bLineCap(!bIsClosed && com::sun::star::drawing::LineCap_BUTT != eCap);
 
                 if(nEdgeCount)
                 {
@@ -649,72 +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)
                         {
-                            aPrev = aEdge;
+                            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
+                        {
+                            aRetval.append(
+                                createAreaGeometryForEdge(
+                                    aEdge, 
+                                    fHalfLineWidth,
+                                    false,
+                                    false,
+                                    false,
+                                    false));
+                        }
+
+                        // prepare next step
+                        if(!bLast)
+                        {
+                            if(bEventuallyCreateLineJoin)
+                            {
+                                aPrev = aEdge;
+                            }
 
-                        aEdge.setStartPoint(aEdge.getEndPoint());
+                            aEdge.setStartPoint(aEdge.getEndPoint());
+                        }
                     }
                 }
 
                 return aRetval;
-			}
+            }
             else
             {
                 return B2DPolyPolygon(rCandidate);
             }
-		}
-	} // end of namespace tools
+        }
+    } // end of namespace tools
 } // end of namespace basegfx
 
 //////////////////////////////////////////////////////////////////////////////

Modified: incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx (original)
+++ incubator/ooo/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx Tue Jan 17 17:54:04 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/trunk/main/basegfx/source/polygon/b3dpolygontools.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/source/polygon/b3dpolygontools.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/basegfx/source/polygon/b3dpolygontools.cxx (original)
+++ incubator/ooo/trunk/main/basegfx/source/polygon/b3dpolygontools.cxx Tue Jan 17 17:54:04 2012
@@ -407,68 +407,71 @@ namespace basegfx
                 sal_uInt32 nDotDashIndex(0);
                 bool bIsLine(true);
                 double fDotDashMovingLength(rDotDashArray[0]);
-				B3DPolygon aSnippet;
+                B3DPolygon aSnippet;
 
-				// iterate over all edges
+                // iterate over all edges
                 for(sal_uInt32 a(0); a < nEdgeCount; a++)
                 {
                     // update current edge
-					double fLastDotDashMovingLength(0.0);
+                    double fLastDotDashMovingLength(0.0);
                     const sal_uInt32 nNextIndex((a + 1) % nPointCount);
-					const B3DPoint aNextPoint(rCandidate.getB3DPoint(nNextIndex));
-					const double fEdgeLength(B3DVector(aNextPoint - aCurrentPoint).getLength());
+                    const B3DPoint aNextPoint(rCandidate.getB3DPoint(nNextIndex));
+                    const double fEdgeLength(B3DVector(aNextPoint - aCurrentPoint).getLength());
 
-					while(fTools::less(fDotDashMovingLength, fEdgeLength))
-					{
-						// new split is inside edge, create and append snippet [fLastDotDashMovingLength, fDotDashMovingLength]
-						const bool bHandleLine(bIsLine && pLineTarget);
-						const bool bHandleGap(!bIsLine && pGapTarget);
+                    if(!fTools::equalZero(fEdgeLength))
+                    {
+                        while(fTools::less(fDotDashMovingLength, fEdgeLength))
+                        {
+                            // new split is inside edge, create and append snippet [fLastDotDashMovingLength, fDotDashMovingLength]
+                            const bool bHandleLine(bIsLine && pLineTarget);
+                            const bool bHandleGap(!bIsLine && pGapTarget);
+                            
+                            if(bHandleLine || bHandleGap)
+                            {
+                                if(!aSnippet.count())
+                                {
+                                    aSnippet.append(interpolate(aCurrentPoint, aNextPoint, fLastDotDashMovingLength / fEdgeLength));
+                                }
+
+                                aSnippet.append(interpolate(aCurrentPoint, aNextPoint, fDotDashMovingLength / fEdgeLength));
+
+                                if(bHandleLine)
+                                {
+                                    pLineTarget->append(aSnippet);
+                                }
+                                else
+                                {
+                                    pGapTarget->append(aSnippet);
+                                }
+
+                                aSnippet.clear();
+                            }
+
+                            // prepare next DotDashArray step and flip line/gap flag
+                            fLastDotDashMovingLength = fDotDashMovingLength;
+                            fDotDashMovingLength += rDotDashArray[(++nDotDashIndex) % nDotDashCount];
+                            bIsLine = !bIsLine;
+                        }
 
+                        // append snippet [fLastDotDashMovingLength, fEdgeLength]
+                        const bool bHandleLine(bIsLine && pLineTarget);
+                        const bool bHandleGap(!bIsLine && pGapTarget);
+                                       
                         if(bHandleLine || bHandleGap)
                         {
-							if(!aSnippet.count())
-							{
-								aSnippet.append(interpolate(aCurrentPoint, aNextPoint, fLastDotDashMovingLength / fEdgeLength));
-							}
+                            if(!aSnippet.count())
+                            {
+                                aSnippet.append(interpolate(aCurrentPoint, aNextPoint, fLastDotDashMovingLength / fEdgeLength));
+                            }
 
-							aSnippet.append(interpolate(aCurrentPoint, aNextPoint, fDotDashMovingLength / fEdgeLength));
-
-							if(bHandleLine)
-							{
-								pLineTarget->append(aSnippet);
-							}
-							else
-							{
-								pGapTarget->append(aSnippet);
-							}
-
-							aSnippet.clear();
-						}
-						
-						// prepare next DotDashArray step and flip line/gap flag
-						fLastDotDashMovingLength = fDotDashMovingLength;
-                        fDotDashMovingLength += rDotDashArray[(++nDotDashIndex) % nDotDashCount];
-                        bIsLine = !bIsLine;
-					}
+                            aSnippet.append(aNextPoint);
+                        }
 
-					// append snippet [fLastDotDashMovingLength, fEdgeLength]
-					const bool bHandleLine(bIsLine && pLineTarget);
-					const bool bHandleGap(!bIsLine && pGapTarget);
-                    
-					if(bHandleLine || bHandleGap)
-                    {
-						if(!aSnippet.count())
-						{
-							aSnippet.append(interpolate(aCurrentPoint, aNextPoint, fLastDotDashMovingLength / fEdgeLength));
-						}
+                        // prepare move to next edge
+                        fDotDashMovingLength -= fEdgeLength;
+                    }
 
-						aSnippet.append(aNextPoint);
-					}
-					
-					// prepare move to next edge
-					fDotDashMovingLength -= fEdgeLength;
-					
-					// prepare next edge step (end point gets new start point)
+                    // prepare next edge step (end point gets new start point)
                     aCurrentPoint = aNextPoint;
                 }
 

Modified: incubator/ooo/trunk/main/basegfx/source/polygon/b3dpolypolygontools.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/source/polygon/b3dpolypolygontools.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/basegfx/source/polygon/b3dpolypolygontools.cxx (original)
+++ incubator/ooo/trunk/main/basegfx/source/polygon/b3dpolypolygontools.cxx Tue Jan 17 17:54:04 2012
@@ -34,6 +34,11 @@
 #include <osl/mutex.hxx>
 
 //////////////////////////////////////////////////////////////////////////////
+// predefines
+#define nMinSegments sal_uInt32(1)
+#define nMaxSegments sal_uInt32(512)
+
+//////////////////////////////////////////////////////////////////////////////
 
 namespace basegfx
 {
@@ -268,20 +273,16 @@ namespace basegfx
 				nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
 			}
 
-			if(!nHorSeg)
-			{
-				nHorSeg = 1L;
-			}
+            // min/max limitations
+            nHorSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nHorSeg));
 
 			if(!nVerSeg)
 			{
 				nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
 			}
 
-			if(!nVerSeg)
-			{
-				nVerSeg = 1L;
-			}
+            // min/max limitations
+            nVerSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nVerSeg));
 
 			// create constants
 			const double fVerDiffPerStep((fVerStop - fVerStart) / (double)nVerSeg);
@@ -371,20 +372,16 @@ namespace basegfx
 				nHorSeg = fround(fabs(fHorStop - fHorStart) / (F_2PI / 24.0));
 			}
 
-			if(!nHorSeg)
-			{
-				nHorSeg = 1L;
-			}
+            // min/max limitations
+            nHorSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nHorSeg));
 
 			if(!nVerSeg)
 			{
 				nVerSeg = fround(fabs(fVerStop - fVerStart) / (F_2PI / 24.0));
 			}
 
-			if(!nVerSeg)
-			{
-				nVerSeg = 1L;
-			}
+            // min/max limitations
+            nVerSeg = ::std::min(nMaxSegments, ::std::max(nMinSegments, nVerSeg));
 
 			// vertical loop
 			for(sal_uInt32 a(0L); a < nVerSeg; a++)

Modified: incubator/ooo/trunk/main/canvas/source/vcl/canvashelper.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/canvas/source/vcl/canvashelper.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/canvas/source/vcl/canvashelper.cxx (original)
+++ incubator/ooo/trunk/main/canvas/source/vcl/canvashelper.cxx Tue Jan 17 17:54:04 2012
@@ -35,6 +35,7 @@
 #include <com/sun/star/rendering/TexturingMode.hpp>
 #include <com/sun/star/rendering/PathCapType.hpp>
 #include <com/sun/star/rendering/PathJoinType.hpp>
+#include <com/sun/star/drawing/LineCap.hpp>
 
 #include <tools/poly.hxx>
 #include <vcl/window.hxx>
@@ -94,6 +95,26 @@ namespace vclcanvas
 
             return basegfx::B2DLINEJOIN_NONE;
         }
+
+        drawing::LineCap unoCapeFromCap( sal_Int8 nCapType)
+        {
+            switch ( nCapType)
+            {
+                case rendering::PathCapType::BUTT:
+                    return drawing::LineCap_BUTT;
+
+                case rendering::PathCapType::ROUND:
+                    return drawing::LineCap_ROUND;
+
+                case rendering::PathCapType::SQUARE:
+                    return drawing::LineCap_SQUARE;
+
+                default:
+                    ENSURE_OR_THROW( false,
+                                      "unoCapeFromCap(): Unexpected cap type" );
+            }
+            return drawing::LineCap_BUTT;
+        }
     }
 
     CanvasHelper::CanvasHelper() :
@@ -384,7 +405,10 @@ namespace vclcanvas
 
                     // AW: New interface, will create bezier polygons now
                     aStrokedPolyPoly.append(basegfx::tools::createAreaGeometry(
-                        aPolyPoly.getB2DPolygon(i), strokeAttributes.StrokeWidth*0.5, b2DJoineFromJoin(strokeAttributes.JoinType)));
+                        aPolyPoly.getB2DPolygon(i), 
+                        strokeAttributes.StrokeWidth*0.5, 
+                        b2DJoineFromJoin(strokeAttributes.JoinType),
+                        unoCapeFromCap(strokeAttributes.StartCapType)));
                     //aStrokedPolyPoly.append( 
                     //    ::basegfx::tools::createAreaGeometryForPolygon( aPolyPoly.getB2DPolygon(i),
                     //                                                    strokeAttributes.StrokeWidth*0.5,

Modified: incubator/ooo/trunk/main/cppcanvas/source/mtfrenderer/implrenderer.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/cppcanvas/source/mtfrenderer/implrenderer.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/cppcanvas/source/mtfrenderer/implrenderer.cxx (original)
+++ incubator/ooo/trunk/main/cppcanvas/source/mtfrenderer/implrenderer.cxx Tue Jan 17 17:54:04 2012
@@ -289,6 +289,28 @@ namespace
                 break;
         }
 
+        switch(rLineInfo.GetLineCap())
+        {
+            default: /* com::sun::star::drawing::LineCap_BUTT */
+            {
+                o_rStrokeAttributes.StartCapType = rendering::PathCapType::BUTT;
+                o_rStrokeAttributes.EndCapType   = rendering::PathCapType::BUTT;
+                break;
+            }
+            case com::sun::star::drawing::LineCap_ROUND:
+            {
+                o_rStrokeAttributes.StartCapType = rendering::PathCapType::ROUND;
+                o_rStrokeAttributes.EndCapType   = rendering::PathCapType::ROUND;
+                break;
+            }
+            case com::sun::star::drawing::LineCap_SQUARE:
+            {
+                o_rStrokeAttributes.StartCapType = rendering::PathCapType::SQUARE;
+                o_rStrokeAttributes.EndCapType   = rendering::PathCapType::SQUARE;
+                break;
+            }
+        }
+
         if( LINE_DASH == rLineInfo.GetStyle() )
         {
             const ::cppcanvas::internal::OutDevState& rState( getState( rParms.mrStates ) );

Modified: incubator/ooo/trunk/main/cui/source/inc/cuitabline.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/cui/source/inc/cuitabline.hxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/cui/source/inc/cuitabline.hxx (original)
+++ incubator/ooo/trunk/main/cui/source/inc/cuitabline.hxx Tue Jan 17 17:54:04 2012
@@ -127,7 +127,11 @@ private:
 	FixedText           maFTEdgeStyle;
 	LineEndLB           maLBEdgeStyle;
 
-	//#58425# Symbole auf einer Linie (z.B. StarChart) ->
+     // LineCaps
+     FixedText          maFTCapStyle;
+     LineEndLB          maLBCapStyle;
+
+    //#58425# Symbole auf einer Linie (z.B. StarChart) ->
     SdrObjList*         pSymbolList; //a list of symbols to be shown in menu. Symbol at position SID_ATTR_SYMBOLTYPE is to be shown in preview. The list position is to be used cyclic.
 	bool				bNewSize;
 	Graphic				aAutoSymbolGraphic; //a graphic to be displayed in the preview in case that an automatic symbol is choosen
@@ -197,6 +201,9 @@ private:
 	// #116827#
 	DECL_LINK( ChangeEdgeStyleHdl_Impl, void * );
 
+     // LineCaps
+     DECL_LINK ( ChangeCapStyleHdl_Impl, void * );
+
 	sal_Bool FillXLSet_Impl();
 #endif
 

Modified: incubator/ooo/trunk/main/cui/source/tabpages/tabline.hrc
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/cui/source/tabpages/tabline.hrc?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/cui/source/tabpages/tabline.hrc (original)
+++ incubator/ooo/trunk/main/cui/source/tabpages/tabline.hrc Tue Jan 17 17:54:04 2012
@@ -97,6 +97,12 @@
 #define FT_EDGE_STYLE 13
 #define LB_EDGE_STYLE 5
 
+// since LO3.6
+#define FT_CAP_STYLE 14
+#define LB_CAP_STYLE 6
+// not sure about IAccessibility2, add it nevertheless
+#define STR_LB_CAP_STYLE 42
+
 //Symbole (fuer StarChart)
 #define FT_SYMBOL_WIDTH		20
 #define FT_SYMBOL_HEIGHT	21

Modified: incubator/ooo/trunk/main/cui/source/tabpages/tabline.src
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/cui/source/tabpages/tabline.src?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/cui/source/tabpages/tabline.src (original)
+++ incubator/ooo/trunk/main/cui/source/tabpages/tabline.src Tue Jan 17 17:54:04 2012
@@ -235,13 +235,13 @@ TabPage RID_SVXPAGE_LINE
 	{
 		Pos = MAP_APPFONT ( 124 , 3 + (16 * 6) - 4 ) ;
 		Size = MAP_APPFONT ( 130 , 8 ) ;
-		Text [ en-US ] = "Corner style" ;
+		Text [ en-US ] = "Corner and cap styles" ;
 	};
 	FixedText FT_EDGE_STYLE
 	{
 		Pos = MAP_APPFONT ( 130 , 14 + (16 * 6) - 4 ) ;
 		Size = MAP_APPFONT ( 118 , 8 ) ;
-		Text [ en-US ] = "Sty~le" ;
+		Text [ en-US ] = "~Corner style" ;
 	};
 	ListBox LB_EDGE_STYLE
 	{
@@ -259,6 +259,27 @@ TabPage RID_SVXPAGE_LINE
 			< "Beveled" ; > ;
 		};
 	};
+    FixedText FT_CAP_STYLE
+    {
+        Pos = MAP_APPFONT ( 191 , 14 + (16 * 6) - 4 ) ;
+        Size = MAP_APPFONT ( 118 , 8 ) ;
+        Text [ en-US ] = "Ca~p style" ;
+    };
+    ListBox LB_CAP_STYLE
+    {
+        HelpID = "cui:ListBox:RID_SVXPAGE_LINE:LB_CAP_STYLE";
+        Border = TRUE ;
+        Pos = MAP_APPFONT ( 191 , 25 + (16 * 6) - 4 ) ;
+        Size = MAP_APPFONT ( 57 , 99 ) ;
+        TabStop = TRUE ;
+        DropDown = TRUE ;
+        StringList [ en-US ] =
+        {
+            < "Flat" ; Default ; > ; // Same string as in Excel
+            < "Round" ; > ;
+            < "Square" ; > ;
+        };
+    };
 
 	//////////////////////////////////////////////////////////////////////////////
 

Modified: incubator/ooo/trunk/main/cui/source/tabpages/tpline.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/cui/source/tabpages/tpline.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/cui/source/tabpages/tpline.cxx (original)
+++ incubator/ooo/trunk/main/cui/source/tabpages/tpline.cxx Tue Jan 17 17:54:04 2012
@@ -129,6 +129,10 @@ SvxLineTabPage::SvxLineTabPage
     maFTEdgeStyle       ( this, CUI_RES( FT_EDGE_STYLE ) ),
     maLBEdgeStyle       ( this, CUI_RES( LB_EDGE_STYLE ) ),
     
+    // LineCaps
+    maFTCapStyle        ( this, CUI_RES( FT_CAP_STYLE ) ),
+    maLBCapStyle        ( this, CUI_RES( LB_CAP_STYLE ) ),
+
     pSymbolList(NULL),
     bNewSize(false),
     nNumMenuGalleryItems(0),
@@ -234,6 +238,10 @@ SvxLineTabPage::SvxLineTabPage
 	Link aEdgeStyle = LINK( this, SvxLineTabPage, ChangeEdgeStyleHdl_Impl );
 	maLBEdgeStyle.SetSelectHdl( aEdgeStyle );
 
+    // LineCaps
+    Link aCapStyle = LINK( this, SvxLineTabPage, ChangeCapStyleHdl_Impl );
+    maLBCapStyle.SetSelectHdl( aCapStyle );
+
 	//#58425# Symbole auf einer Linie (z.B. StarChart) , MB-Handler setzen
 	aSymbolMB.SetSelectHdl(LINK(this, SvxLineTabPage, GraphicHdl_Impl));
     aSymbolMB.SetActivateHdl(LINK(this, SvxLineTabPage, MenuCreateHdl_Impl));
@@ -484,6 +492,10 @@ void SvxLineTabPage::ActivatePage( const
 		maFLEdgeStyle.Hide();
 		maFTEdgeStyle.Hide();
 		maLBEdgeStyle.Hide();
+
+        // LineCaps
+        maFTCapStyle.Hide();
+        maLBCapStyle.Hide();
 	}
 }
 
@@ -751,6 +763,45 @@ sal_Bool SvxLineTabPage::FillItemSet( Sf
 		}
 	}
 
+    // LineCaps
+    nPos = maLBCapStyle.GetSelectEntryPos();
+    if( LISTBOX_ENTRY_NOTFOUND != nPos && nPos != maLBCapStyle.GetSavedValue() )
+    {
+        XLineCapItem* pNew = 0L;
+
+        switch(nPos)
+        {
+            case 0: // Butt (=Flat), default
+            {
+                pNew = new XLineCapItem(com::sun::star::drawing::LineCap_BUTT);
+                break;
+            }
+            case 1: // Round
+            {
+                pNew = new XLineCapItem(com::sun::star::drawing::LineCap_ROUND);
+                break;
+            }
+            case 2: // Square
+            {
+                pNew = new XLineCapItem(com::sun::star::drawing::LineCap_SQUARE);
+                break;
+            }
+        }
+
+        if(pNew)
+        {
+            pOld = GetOldItem( rAttrs, XATTR_LINECAP );
+
+            if(!pOld || !(*(const XLineCapItem*)pOld == *pNew))
+            {
+                rAttrs.Put( *pNew );
+                bModified = sal_True;
+            }
+
+            delete pNew;
+        }
+    }
+
 	if(nSymbolType!=SVX_SYMBOLTYPE_UNKNOWN || bNewSize)
 	{
 		//wurde also per Auswahl gesetzt oder Gr��e ist anders
@@ -866,6 +917,30 @@ sal_Bool SvxLineTabPage::FillXLSet_Impl(
 		}
 	}
 
+    // LineCaps
+    nPos = maLBCapStyle.GetSelectEntryPos();
+    if(LISTBOX_ENTRY_NOTFOUND != nPos)
+    {
+        switch(nPos)
+        {
+            case 0: // Butt (=Flat), default
+            {
+                rXLSet.Put(XLineCapItem(com::sun::star::drawing::LineCap_BUTT));
+                break;
+            }
+            case 1: // Round
+            {
+                rXLSet.Put(XLineCapItem(com::sun::star::drawing::LineCap_ROUND));
+                break;
+            }
+            case 2: // Square
+            {
+                rXLSet.Put(XLineCapItem(com::sun::star::drawing::LineCap_SQUARE));
+                break;
+            }
+        }
+    }
+
 	rXLSet.Put( XLineStartWidthItem( GetCoreValue( aMtrStartWidth, ePoolUnit ) ) );
 	rXLSet.Put( XLineEndWidthItem( GetCoreValue( aMtrEndWidth, ePoolUnit ) ) );
 
@@ -1284,6 +1359,28 @@ void SvxLineTabPage::Reset( const SfxIte
 	}
 	*/
 
+    // fdo#43209
+    if(bObjSelected && SFX_ITEM_DEFAULT == rAttrs.GetItemState(XATTR_LINECAP))
+    {
+        maFTCapStyle.Disable();
+        maLBCapStyle.Disable();
+    }
+    else if(SFX_ITEM_DONTCARE != rAttrs.GetItemState(XATTR_LINECAP))
+    {
+        const com::sun::star::drawing::LineCap eLineCap(((const XLineCapItem&)(rAttrs.Get(XATTR_LINECAP))).GetValue());
+
+        switch(eLineCap)
+        {
+            case com::sun::star::drawing::LineCap_ROUND: maLBCapStyle.SelectEntryPos(1); break;
+            case com::sun::star::drawing::LineCap_SQUARE : maLBCapStyle.SelectEntryPos(2); break;
+            default /*com::sun::star::drawing::LineCap_BUTT*/: maLBCapStyle.SelectEntryPos(0); break;
+        }
+    }
+    else
+    {
+        maLBCapStyle.SetNoSelection();
+    }
+
 	// Werte sichern
 	aLbLineStyle.SaveValue();
 	aMtrLineWidth.SaveValue();
@@ -1299,6 +1396,9 @@ void SvxLineTabPage::Reset( const SfxIte
 	// #116827#
 	maLBEdgeStyle.SaveValue();
 
+    // LineCaps
+    maLBCapStyle.SaveValue();
+
 	ClickInvisibleHdl_Impl( this );
 	//ClickMeasuringHdl_Impl( this );
 	//aCtlPosition.Reset();
@@ -1416,6 +1516,15 @@ IMPL_LINK( SvxLineTabPage, ChangeEdgeSty
 }
 
 //------------------------------------------------------------------------
+// fdo#43209
+
+IMPL_LINK( SvxLineTabPage, ChangeCapStyleHdl_Impl, void *, EMPTYARG )
+{
+    ChangePreviewHdl_Impl( this );
+
+    return( 0L );
+}
+//------------------------------------------------------------------------
 
 IMPL_LINK( SvxLineTabPage, ClickInvisibleHdl_Impl, void *, EMPTYARG )
 {
@@ -1442,6 +1551,10 @@ IMPL_LINK( SvxLineTabPage, ClickInvisibl
 			// #116827#
 			maFTEdgeStyle.Disable();
 			maLBEdgeStyle.Disable();
+
+            // LineCaps
+            maFTCapStyle.Disable();
+            maLBCapStyle.Disable();
 		}
 	}
 	else
@@ -1466,6 +1579,10 @@ IMPL_LINK( SvxLineTabPage, ClickInvisibl
 			// #116827#
 			maFTEdgeStyle.Enable();
 			maLBEdgeStyle.Enable();
+
+            // LineCaps
+            maFTCapStyle.Enable();
+            maLBCapStyle.Enable();
 		}
 	}
 	ChangePreviewHdl_Impl( NULL );

Modified: incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/attribute/lineattribute.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/attribute/lineattribute.hxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/attribute/lineattribute.hxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/attribute/lineattribute.hxx Tue Jan 17 17:54:04 2012
@@ -26,6 +26,7 @@
 
 #include <drawinglayer/drawinglayerdllapi.h>
 #include <basegfx/vector/b2enums.hxx>
+#include <com/sun/star/drawing/LineCap.hpp>
 
 //////////////////////////////////////////////////////////////////////////////
 // predefines
@@ -54,7 +55,8 @@ namespace drawinglayer
 			LineAttribute(
 				const basegfx::BColor& rColor,
 				double fWidth = 0.0,
-				basegfx::B2DLineJoin aB2DLineJoin = basegfx::B2DLINEJOIN_ROUND);
+				basegfx::B2DLineJoin aB2DLineJoin = basegfx::B2DLINEJOIN_ROUND,
+                com::sun::star::drawing::LineCap aLineCap = com::sun::star::drawing::LineCap_BUTT);
 			LineAttribute();
 			LineAttribute(const LineAttribute& rCandidate);
 			LineAttribute& operator=(const LineAttribute& rCandidate);
@@ -70,6 +72,7 @@ namespace drawinglayer
 			const basegfx::BColor& getColor() const;
 			double getWidth() const;
 			basegfx::B2DLineJoin getLineJoin() const;
+            com::sun::star::drawing::LineCap getLineCap() const;
 		};
 	} // end of namespace attribute
 } // end of namespace drawinglayer

Modified: incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/attribute/sdrlineattribute.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/attribute/sdrlineattribute.hxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/attribute/sdrlineattribute.hxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/attribute/sdrlineattribute.hxx Tue Jan 17 17:54:04 2012
@@ -38,6 +38,7 @@
 
 #include <drawinglayer/drawinglayerdllapi.h>
 #include <basegfx/vector/b2enums.hxx>
+#include <com/sun/star/drawing/LineCap.hpp>
 #include <vector>
 
 //////////////////////////////////////////////////////////////////////////////
@@ -68,7 +69,8 @@ namespace drawinglayer
 				basegfx::B2DLineJoin eJoin, 
                 double fWidth, 
                 double fTransparence, 
-                const basegfx::BColor& rColor, 
+                const basegfx::BColor& rColor,
+                com::sun::star::drawing::LineCap eCap,
 				const ::std::vector< double >& rDotDashArray, 
                 double fFullDotDashLen);
             SdrLineAttribute(const basegfx::BColor& rColor);
@@ -90,6 +92,7 @@ namespace drawinglayer
 			const basegfx::BColor& getColor() const;
 			const ::std::vector< double >& getDotDashArray() const;
 			double getFullDotDashLen() const;
+            com::sun::star::drawing::LineCap getCap() const;
 
 			// bool access
 			bool isDashed() const;

Modified: incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/inc/drawinglayer/primitive3d/polygontubeprimitive3d.hxx Tue Jan 17 17:54:04 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/trunk/main/drawinglayer/source/attribute/lineattribute.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/attribute/lineattribute.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/source/attribute/lineattribute.cxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/source/attribute/lineattribute.cxx Tue Jan 17 17:54:04 2012
@@ -43,15 +43,18 @@ namespace drawinglayer
 			basegfx::BColor							maColor;				// color
 			double									mfWidth;				// absolute line width
 			basegfx::B2DLineJoin					meLineJoin;				// type of LineJoin
+            com::sun::star::drawing::LineCap        meLineCap;              // BUTT, ROUND, or SQUARE
 
 			ImpLineAttribute(
                 const basegfx::BColor& rColor,
 				double fWidth,
-				basegfx::B2DLineJoin aB2DLineJoin)
+				basegfx::B2DLineJoin aB2DLineJoin,
+                com::sun::star::drawing::LineCap aLineCap)
 			:	mnRefCount(0),
                 maColor(rColor),
                 mfWidth(fWidth),
-                meLineJoin(aB2DLineJoin)
+                meLineJoin(aB2DLineJoin),
+                meLineCap(aLineCap)
 			{
 			}
 
@@ -59,12 +62,14 @@ namespace drawinglayer
 			const basegfx::BColor& getColor() const { return maColor; }
 			double getWidth() const { return mfWidth; }
 			basegfx::B2DLineJoin getLineJoin() const { return meLineJoin; }
+            com::sun::star::drawing::LineCap getLineCap() const { return meLineCap; }
 
 			bool operator==(const ImpLineAttribute& rCandidate) const
 			{
 				return (getColor() == rCandidate.getColor()
 					&& getWidth() == rCandidate.getWidth()
-					&& getLineJoin() == rCandidate.getLineJoin());
+					&& getLineJoin() == rCandidate.getLineJoin()
+                    && getLineCap() == rCandidate.getLineCap());
 			}
 
             static ImpLineAttribute* get_global_default()
@@ -76,7 +81,8 @@ namespace drawinglayer
                     pDefault = new ImpLineAttribute(
                         basegfx::BColor(),
                         0.0,
-                        basegfx::B2DLINEJOIN_ROUND);
+                        basegfx::B2DLINEJOIN_ROUND,
+                        com::sun::star::drawing::LineCap_BUTT);
 
                     // never delete; start with RefCount 1, not 0
     			    pDefault->mnRefCount++;
@@ -89,9 +95,14 @@ namespace drawinglayer
         LineAttribute::LineAttribute(
             const basegfx::BColor& rColor,
 			double fWidth,
-			basegfx::B2DLineJoin aB2DLineJoin)
-		:	mpLineAttribute(new ImpLineAttribute(
-                rColor, fWidth, aB2DLineJoin))
+			basegfx::B2DLineJoin aB2DLineJoin,
+            com::sun::star::drawing::LineCap aLineCap)
+		:	mpLineAttribute(
+                new ImpLineAttribute(
+                    rColor, 
+                    fWidth, 
+                    aB2DLineJoin,
+                    aLineCap))
 		{
 		}
 
@@ -174,6 +185,11 @@ namespace drawinglayer
             return mpLineAttribute->getLineJoin(); 
         }
 
+        com::sun::star::drawing::LineCap LineAttribute::getLineCap() const
+        {
+            return mpLineAttribute->getLineCap();
+        }
+
     } // end of namespace attribute
 } // end of namespace drawinglayer
 

Modified: incubator/ooo/trunk/main/drawinglayer/source/attribute/sdrlineattribute.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/attribute/sdrlineattribute.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/source/attribute/sdrlineattribute.cxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/source/attribute/sdrlineattribute.cxx Tue Jan 17 17:54:04 2012
@@ -56,6 +56,7 @@ namespace drawinglayer
 			double									mfWidth;			// 1/100th mm, 0.0==hair
 			double									mfTransparence;		// [0.0 .. 1.0], 0.0==no transp.
 			basegfx::BColor							maColor;			// color of line
+            com::sun::star::drawing::LineCap        meCap;              // BUTT, ROUND, or SQUARE
 			::std::vector< double >					maDotDashArray;		// array of double which defines the dot-dash pattern
 			double									mfFullDotDashLen;	// sum of maDotDashArray (for convenience)
 
@@ -64,6 +65,7 @@ namespace drawinglayer
                 double fWidth, 
                 double fTransparence, 
                 const basegfx::BColor& rColor, 
+                com::sun::star::drawing::LineCap eCap,
 				const ::std::vector< double >& rDotDashArray, 
                 double fFullDotDashLen)
 			:	mnRefCount(0),
@@ -71,6 +73,7 @@ namespace drawinglayer
 			    mfWidth(fWidth),
 			    mfTransparence(fTransparence),
 			    maColor(rColor),
+                meCap(eCap),
 			    maDotDashArray(rDotDashArray),
 			    mfFullDotDashLen(fFullDotDashLen)
 		    {
@@ -82,6 +85,7 @@ namespace drawinglayer
 			    mfWidth(0.0),
 			    mfTransparence(0.0),
 			    maColor(rColor),
+                meCap(com::sun::star::drawing::LineCap_BUTT),
 			    maDotDashArray(),
 			    mfFullDotDashLen(0.0)
             {
@@ -92,6 +96,7 @@ namespace drawinglayer
 			double getWidth() const { return mfWidth; }
 			double getTransparence() const { return mfTransparence; }
 			const basegfx::BColor& getColor() const { return maColor; }
+            com::sun::star::drawing::LineCap getCap() const { return meCap; }
 			const ::std::vector< double >& getDotDashArray() const { return maDotDashArray; }
 			double getFullDotDashLen() const { return mfFullDotDashLen; }
 
@@ -101,6 +106,7 @@ namespace drawinglayer
 				    && getWidth() == rCandidate.getWidth()
 				    && getTransparence() == rCandidate.getTransparence()
 				    && getColor() == rCandidate.getColor()
+                    && getCap() == rCandidate.getCap()
 				    && getDotDashArray() == rCandidate.getDotDashArray());
 		    }
 
@@ -115,6 +121,7 @@ namespace drawinglayer
                         0.0, 
                         0.0, 
                         basegfx::BColor(),
+                        com::sun::star::drawing::LineCap_BUTT,
 			            std::vector< double >(), 
                         0.0);
 
@@ -131,16 +138,26 @@ namespace drawinglayer
             double fWidth, 
             double fTransparence, 
             const basegfx::BColor& rColor, 
+            com::sun::star::drawing::LineCap eCap,
 			const ::std::vector< double >& rDotDashArray, 
             double fFullDotDashLen)
-		:	mpSdrLineAttribute(new ImpSdrLineAttribute(
-                eJoin, fWidth, fTransparence, rColor, rDotDashArray, fFullDotDashLen))
+		:	mpSdrLineAttribute(
+                new ImpSdrLineAttribute(
+                    eJoin, 
+                    fWidth, 
+                    fTransparence, 
+                    rColor, 
+                    eCap,
+                    rDotDashArray, 
+                    fFullDotDashLen))
 		{
 		}
 
         SdrLineAttribute::SdrLineAttribute(
             const basegfx::BColor& rColor)
-		:	mpSdrLineAttribute(new ImpSdrLineAttribute(rColor))
+		:	mpSdrLineAttribute(
+                new ImpSdrLineAttribute(
+                    rColor))
         {
         }
 
@@ -243,6 +260,11 @@ namespace drawinglayer
             return (0L != getDotDashArray().size()); 
         }
 
+        com::sun::star::drawing::LineCap SdrLineAttribute::getCap() const
+        {
+            return mpSdrLineAttribute->getCap();
+        }
+
     } // end of namespace attribute
 } // end of namespace drawinglayer
 

Modified: incubator/ooo/trunk/main/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/primitive2d/metafileprimitive2d.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/source/primitive2d/metafileprimitive2d.cxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/source/primitive2d/metafileprimitive2d.cxx Tue Jan 17 17:54:04 2012
@@ -706,7 +706,8 @@ namespace
 				const drawinglayer::attribute::LineAttribute aLineAttribute(
 					rProperties.getLineColor(),
 					bWidthUsed ? rLineInfo.GetWidth() : 0.0,
-					rLineInfo.GetLineJoin());
+					rLineInfo.GetLineJoin(),
+                    rLineInfo.GetLineCap());
 
 				if(bDashDotUsed)
 				{

Modified: incubator/ooo/trunk/main/drawinglayer/source/primitive2d/polygonprimitive2d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/primitive2d/polygonprimitive2d.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/source/primitive2d/polygonprimitive2d.cxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/source/primitive2d/polygonprimitive2d.cxx Tue Jan 17 17:54:04 2012
@@ -32,6 +32,7 @@
 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
 #include <drawinglayer/geometry/viewinformation2d.hxx>
 #include <basegfx/polygon/b2dlinegeometry.hxx>
+#include <com/sun/star/drawing/LineCap.hpp>
 
 //////////////////////////////////////////////////////////////////////////////
 
@@ -252,13 +253,17 @@ namespace drawinglayer
                     // create fat line data
 					const double fHalfLineWidth(getLineAttribute().getWidth() / 2.0);
 					const basegfx::B2DLineJoin aLineJoin(getLineAttribute().getLineJoin());
+                    const com::sun::star::drawing::LineCap aLineCap(getLineAttribute().getLineCap());
 					basegfx::B2DPolyPolygon aAreaPolyPolygon;
 
 					for(sal_uInt32 a(0L); a < nCount; a++)
 					{
                         // New version of createAreaGeometry; now creates bezier polygons
                         aAreaPolyPolygon.append(basegfx::tools::createAreaGeometry(
-							aHairLinePolyPolygon.getB2DPolygon(a), fHalfLineWidth, aLineJoin));
+							aHairLinePolyPolygon.getB2DPolygon(a), 
+                            fHalfLineWidth, 
+                            aLineJoin,
+                            aLineCap));
 					}
 
 					// prepare return value
@@ -339,11 +344,29 @@ namespace drawinglayer
 
             if(getLineAttribute().getWidth())
             {
+                bool bUseDecomposition(false);
+
                 if(basegfx::B2DLINEJOIN_MITER == getLineAttribute().getLineJoin())
                 {
                     // if line is mitered, use parent call since mitered line
                     // geometry may use more space than the geometry grown by half line width
-            		aRetval = BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
+                    bUseDecomposition = true;
+                }
+
+                if(!bUseDecomposition && com::sun::star::drawing::LineCap_SQUARE == getLineAttribute().getLineCap())
+                {
+                    // when drawing::LineCap_SQUARE is used the below method to grow the polygon
+                    // range by half line width will not work, so use decomposition. Interestingly,
+                    // the grow method below works perfectly for LineCap_ROUND since the grow is in
+                    // all directions and the rounded cap needs the same grow in all directions independent
+                    // from it's orientation. Unfortunately this is not the case for drawing::LineCap_SQUARE
+                    bUseDecomposition = true;
+                }
+
+                if(bUseDecomposition)
+                {
+                    // get correct range by using the decomposition fallback, reasons see above cases
+                    aRetval = BufferedDecompositionPrimitive2D::getB2DRange(rViewInformation);
                 }
                 else
                 {

Modified: incubator/ooo/trunk/main/drawinglayer/source/primitive3d/polygonprimitive3d.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/primitive3d/polygonprimitive3d.cxx?rev=1232507&r1=1232506&r2=1232507&view=diff
==============================================================================
--- incubator/ooo/trunk/main/drawinglayer/source/primitive3d/polygonprimitive3d.cxx (original)
+++ incubator/ooo/trunk/main/drawinglayer/source/primitive3d/polygonprimitive3d.cxx Tue Jan 17 17:54:04 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;
 					}
 				}