summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--basegfx/source/polygon/b2dlinegeometry.cxx8
-rw-r--r--drawinglayer/source/primitive2d/patternfillprimitive2d.cxx205
-rw-r--r--drawinglayer/source/processor2d/objectinfoextractor2d.cxx20
-rw-r--r--drawinglayer/source/processor2d/vclpixelprocessor2d.cxx10
-rw-r--r--drawinglayer/source/texture/texture.cxx53
-rw-r--r--include/drawinglayer/primitive2d/patternfillprimitive2d.hxx20
-rw-r--r--include/drawinglayer/texture/texture.hxx6
-rw-r--r--vcl/win/gdi/gdiimpl.cxx125
8 files changed, 362 insertions, 85 deletions
diff --git a/basegfx/source/polygon/b2dlinegeometry.cxx b/basegfx/source/polygon/b2dlinegeometry.cxx
index b5163ec1c957..abf80ccc59ce 100644
--- a/basegfx/source/polygon/b2dlinegeometry.cxx
+++ b/basegfx/source/polygon/b2dlinegeometry.cxx
@@ -955,6 +955,14 @@ namespace basegfx
}
}
}
+ else
+ {
+ // point count, but no edge count -> single point
+ aRetval.append(
+ createPolygonFromCircle(
+ aCandidate.getB2DPoint(0),
+ fHalfLineWidth));
+ }
return aRetval;
}
diff --git a/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
index ff3e4452886b..39b695c4be7a 100644
--- a/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/patternfillprimitive2d.cxx
@@ -21,19 +21,144 @@
#include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
#include <drawinglayer/primitive2d/transformprimitive2d.hxx>
#include <drawinglayer/primitive2d/polygonprimitive2d.hxx>
+#include <drawinglayer/primitive2d/bitmapprimitive2d.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/matrix/b2dhommatrixtools.hxx>
#include <drawinglayer/texture/texture.hxx>
#include <drawinglayer/primitive2d/maskprimitive2d.hxx>
-
+#include <drawinglayer/tools/converters.hxx>
+#include <drawinglayer/geometry/viewinformation2d.hxx>
using namespace com::sun::star;
+#define MAXIMUM_SQUARE_LENGTH (164.0)
+#define MINIMUM_SQUARE_LENGTH (32.0)
+#define MINIMUM_TILES_LENGTH (3)
namespace drawinglayer
{
namespace primitive2d
{
+ void PatternFillPrimitive2D::calculateNeededDiscreteBufferSize(
+ sal_uInt32& rWidth,
+ sal_uInt32& rHeight,
+ const geometry::ViewInformation2D& rViewInformation) const
+ {
+ // reset parameters
+ rWidth = rHeight = 0;
+
+ // check if resolution is in the range which may be buffered
+ const basegfx::B2DPolyPolygon& rMaskPolygon = getMask();
+ const basegfx::B2DRange aMaskRange(rMaskPolygon.getB2DRange());
+
+ // get discrete rounded up square size of a single tile
+ const basegfx::B2DHomMatrix aMaskRangeTransformation(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ aMaskRange.getRange(),
+ aMaskRange.getMinimum()));
+ const basegfx::B2DHomMatrix aTransform(
+ rViewInformation.getObjectToViewTransformation() * aMaskRangeTransformation);
+ const basegfx::B2DPoint aTopLeft(aTransform * getReferenceRange().getMinimum());
+ const basegfx::B2DPoint aX(aTransform * basegfx::B2DPoint(getReferenceRange().getMaxX(), getReferenceRange().getMinY()));
+ const basegfx::B2DPoint aY(aTransform * basegfx::B2DPoint(getReferenceRange().getMinX(), getReferenceRange().getMaxY()));
+ const double fW(basegfx::B2DVector(aX - aTopLeft).getLength());
+ const double fH(basegfx::B2DVector(aY - aTopLeft).getLength());
+ const double fSquare(fW * fH);
+
+ if(fSquare > 0.0)
+ {
+ // check if less than a maximum square pixels is used
+ static sal_uInt32 fMaximumSquare(MAXIMUM_SQUARE_LENGTH * MAXIMUM_SQUARE_LENGTH);
+
+ if(fSquare < fMaximumSquare)
+ {
+ // calculate needed number of tiles and check if used more than a minimum count
+ const texture::GeoTexSvxTiled aTiling(getReferenceRange());
+ const sal_uInt32 nTiles(aTiling.getNumberOfTiles());
+ static sal_uInt32 nMinimumTiles(MINIMUM_TILES_LENGTH * MINIMUM_TILES_LENGTH);
+
+ if(nTiles >= nMinimumTiles)
+ {
+ rWidth = basegfx::fround(ceil(fW));
+ rHeight = basegfx::fround(ceil(fH));
+ static sal_uInt32 fMinimumSquare(MINIMUM_SQUARE_LENGTH * MINIMUM_SQUARE_LENGTH);
+
+ if(fSquare < fMinimumSquare)
+ {
+ const double fRel(fW/fH);
+ rWidth = basegfx::fround(sqrt(fMinimumSquare * fRel));
+ rHeight = basegfx::fround(sqrt(fMinimumSquare / fRel));
+ }
+ }
+ }
+ }
+ }
+
+ Primitive2DContainer PatternFillPrimitive2D::createContent(const geometry::ViewInformation2D& rViewInformation) const
+ {
+ Primitive2DContainer aContent;
+
+ // see if buffering is wanted. it is wanted, create buffered content in given resolution
+ if(0 != mnDiscreteWidth && 0 != mnDiscreteHeight)
+ {
+ const geometry::ViewInformation2D aViewInformation2D;
+ const primitive2d::Primitive2DReference xEmbedRef(
+ new primitive2d::TransformPrimitive2D(
+ basegfx::tools::createScaleB2DHomMatrix(mnDiscreteWidth, mnDiscreteHeight),
+ getChildren()));
+ const primitive2d::Primitive2DContainer xEmbedSeq { xEmbedRef };
+
+ const BitmapEx aBitmapEx(
+ tools::convertToBitmapEx(
+ xEmbedSeq,
+ aViewInformation2D,
+ mnDiscreteWidth,
+ mnDiscreteHeight,
+ mnDiscreteWidth * mnDiscreteHeight));
+
+ if(!aBitmapEx.IsEmpty())
+ {
+ const Size& rBmpPix = aBitmapEx.GetSizePixel();
+
+ if(rBmpPix.Width() > 0 && rBmpPix.Height() > 0)
+ {
+ const primitive2d::Primitive2DReference xEmbedRefBitmap(
+ new primitive2d::BitmapPrimitive2D(
+ aBitmapEx,
+ basegfx::B2DHomMatrix()));
+ aContent = primitive2d::Primitive2DContainer { xEmbedRefBitmap };
+ }
+ }
+ }
+
+ if(aContent.empty())
+ {
+ // buffering was not tried or did fail - reset remembered buffered size
+ // in any case
+ PatternFillPrimitive2D* pThat = const_cast< PatternFillPrimitive2D* >(this);
+ pThat->mnDiscreteWidth = pThat->mnDiscreteHeight = 0;
+
+ // use children as default context
+ aContent = getChildren();
+
+ // check if content needs to be clipped
+ const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
+ const basegfx::B2DRange aContentRange(getChildren().getB2DRange(rViewInformation));
+
+ if(!aUnitRange.isInside(aContentRange))
+ {
+ const Primitive2DReference xRef(
+ new MaskPrimitive2D(
+ basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aUnitRange)),
+ aContent));
+
+ aContent = Primitive2DContainer { xRef };
+ }
+ }
+
+ return aContent;
+ }
+
Primitive2DContainer PatternFillPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
{
Primitive2DContainer aRetval;
@@ -52,20 +177,8 @@ namespace drawinglayer
aTiling.appendTransformations(aMatrices);
- // check if content needs to be clipped
- const basegfx::B2DRange aUnitRange(0.0, 0.0, 1.0, 1.0);
- const basegfx::B2DRange aContentRange(getChildren().getB2DRange(rViewInformation));
- Primitive2DContainer aContent(getChildren());
-
- if(!aUnitRange.isInside(aContentRange))
- {
- const Primitive2DReference xRef(
- new MaskPrimitive2D(
- basegfx::B2DPolyPolygon(basegfx::tools::createPolygonFromRect(aUnitRange)),
- aContent));
-
- aContent = Primitive2DContainer { xRef };
- }
+ // create content
+ const Primitive2DContainer aContent(createContent(rViewInformation));
// resize result
aRetval.resize(aMatrices.size());
@@ -117,7 +230,9 @@ namespace drawinglayer
: BufferedDecompositionPrimitive2D(),
maMask(rMask),
maChildren(rChildren),
- maReferenceRange(rReferenceRange)
+ maReferenceRange(rReferenceRange),
+ mnDiscreteWidth(0),
+ mnDiscreteHeight(0)
{
}
@@ -140,6 +255,64 @@ namespace drawinglayer
return getMask().getB2DRange();
}
+ Primitive2DContainer PatternFillPrimitive2D::get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const
+ {
+ if(0 == mnDiscreteWidth || 0 == mnDiscreteHeight)
+ {
+ // Currently no buffering is used. Check if the resulting discrete sizes
+ // in the current situation would be good for buffering from now on
+ PatternFillPrimitive2D* pThat = const_cast< PatternFillPrimitive2D* >(this);
+
+ calculateNeededDiscreteBufferSize(pThat->mnDiscreteWidth, pThat->mnDiscreteHeight, rViewInformation);
+ }
+ else
+ {
+ // The existing bufferd decomposition uses a buffer in the remembered
+ // size. Get new needed sizes which depend on the given ViewInformation
+ sal_uInt32 nW(0);
+ sal_uInt32 nH(0);
+ calculateNeededDiscreteBufferSize(nW, nH, rViewInformation);
+
+ if(0 != nW && 0 != nH)
+ {
+ // buffering is possible - check if reset is needed
+ bool bResetBuffering = false;
+
+ if(nW > mnDiscreteWidth || nH > mnDiscreteHeight)
+ {
+ // Higher resolution is needed than used in the existing buffered
+ // decomposition
+ bResetBuffering = true;
+ }
+ else if(double(nW * nH) / double(mnDiscreteWidth * mnDiscreteHeight) <= 0.5)
+ {
+ // Size has shrunk for 50% or more - it's worth to refresh the buffering
+ bResetBuffering = true;
+ }
+
+ if(bResetBuffering)
+ {
+ PatternFillPrimitive2D* pThat = const_cast< PatternFillPrimitive2D* >(this);
+ pThat->mnDiscreteWidth = nW;
+ pThat->mnDiscreteHeight = nH;
+ pThat->setBuffered2DDecomposition(Primitive2DContainer());
+ }
+ }
+ else
+ {
+ // no buffering wanted or possible - clear decomposition to create a
+ // new, unbuffered one
+ PatternFillPrimitive2D* pThat = const_cast< PatternFillPrimitive2D* >(this);
+ pThat->mnDiscreteWidth = 0;
+ pThat->mnDiscreteHeight = 0;
+ pThat->setBuffered2DDecomposition(Primitive2DContainer());
+ }
+ }
+
+ // call parent
+ return BufferedDecompositionPrimitive2D::get2DDecomposition(rViewInformation);
+ }
+
// provide unique ID
ImplPrimitive2DIDBlock(PatternFillPrimitive2D, PRIMITIVE2D_ID_PATTERNFILLPRIMITIVE2D)
diff --git a/drawinglayer/source/processor2d/objectinfoextractor2d.cxx b/drawinglayer/source/processor2d/objectinfoextractor2d.cxx
index ad26620a1630..7ae806f2890b 100644
--- a/drawinglayer/source/processor2d/objectinfoextractor2d.cxx
+++ b/drawinglayer/source/processor2d/objectinfoextractor2d.cxx
@@ -40,8 +40,24 @@ namespace drawinglayer
}
default :
{
- // process recursively
- process(rCandidate.get2DDecomposition(getViewInformation2D()));
+ // we look for an encapsulated primitive, so do not decompose primitives
+ // based on GroupPrimitive2D, just visit their children. It may be that more
+ // group-like primitives need to be added here, but all primitives with
+ // grouping functionality should be implemented based on the GroupPrimitive2D
+ // class and have their main content accessible as children
+ const primitive2d::GroupPrimitive2D* pGroupPrimitive2D = dynamic_cast< const primitive2d::GroupPrimitive2D* >(&rCandidate);
+
+ if(pGroupPrimitive2D)
+ {
+ // process group children recursively
+ process(pGroupPrimitive2D->getChildren());
+ }
+ else
+ {
+ // do not process recursively, we *only* want to find existing
+ // ObjectInfoPrimitive2D entries
+ }
+
break;
}
}
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
index 2e6bc257b337..1424d8a1f182 100644
--- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx
@@ -182,17 +182,19 @@ namespace drawinglayer
bool VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect(const drawinglayer::primitive2d::PolygonStrokePrimitive2D& rSource, double fTransparency)
{
- basegfx::B2DPolygon aLocalPolygon(rSource.getB2DPolygon());
-
- if(!aLocalPolygon.count())
+ if(!rSource.getB2DPolygon().count())
{
// no geometry, done
return true;
}
- aLocalPolygon = basegfx::tools::simplifyCurveSegments(aLocalPolygon);
+ // get geometry data, prepare hairline data
+ basegfx::B2DPolygon aLocalPolygon(rSource.getB2DPolygon());
basegfx::B2DPolyPolygon aHairLinePolyPolygon;
+ // simplify curve segments
+ aLocalPolygon = basegfx::tools::simplifyCurveSegments(aLocalPolygon);
+
if(rSource.getStrokeAttribute().isDefault() || 0.0 == rSource.getStrokeAttribute().getFullDotDashLen())
{
// no line dashing, just copy
diff --git a/drawinglayer/source/texture/texture.cxx b/drawinglayer/source/texture/texture.cxx
index e205d89c53da..7d53a46e4d29 100644
--- a/drawinglayer/source/texture/texture.cxx
+++ b/drawinglayer/source/texture/texture.cxx
@@ -720,9 +720,20 @@ namespace drawinglayer
&& mfOffsetY == pCompare->mfOffsetY);
}
- void GeoTexSvxTiled::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices)
+ sal_uInt32 GeoTexSvxTiled::getNumberOfTiles() const
+ {
+ return iterateTiles(nullptr);
+ }
+
+ void GeoTexSvxTiled::appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) const
+ {
+ iterateTiles(&rMatrices);
+ }
+
+ sal_Int32 GeoTexSvxTiled::iterateTiles(::std::vector< basegfx::B2DHomMatrix >* pMatrices) const
{
const double fWidth(maRange.getWidth());
+ sal_Int32 nTiles = 0;
if(!basegfx::fTools::equalZero(fWidth))
{
@@ -774,12 +785,19 @@ namespace drawinglayer
for(double fPosY((nPosX % 2) ? fStartY - fHeight + (mfOffsetY * fHeight) : fStartY);
basegfx::fTools::less(fPosY, 1.0); fPosY += fHeight)
{
- rMatrices.push_back(
- basegfx::tools::createScaleTranslateB2DHomMatrix(
- fWidth,
- fHeight,
- fPosX,
- fPosY));
+ if(pMatrices)
+ {
+ pMatrices->push_back(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ fWidth,
+ fHeight,
+ fPosX,
+ fPosY));
+ }
+ else
+ {
+ nTiles++;
+ }
}
}
}
@@ -790,17 +808,26 @@ namespace drawinglayer
for(double fPosX((nPosY % 2) ? fStartX - fWidth + (mfOffsetX * fWidth) : fStartX);
basegfx::fTools::less(fPosX, 1.0); fPosX += fWidth)
{
- rMatrices.push_back(
- basegfx::tools::createScaleTranslateB2DHomMatrix(
- fWidth,
- fHeight,
- fPosX,
- fPosY));
+ if(pMatrices)
+ {
+ pMatrices->push_back(
+ basegfx::tools::createScaleTranslateB2DHomMatrix(
+ fWidth,
+ fHeight,
+ fPosX,
+ fPosY));
+ }
+ else
+ {
+ nTiles++;
+ }
}
}
}
}
}
+
+ return nTiles;
}
} // end of namespace texture
} // end of namespace drawinglayer
diff --git a/include/drawinglayer/primitive2d/patternfillprimitive2d.hxx b/include/drawinglayer/primitive2d/patternfillprimitive2d.hxx
index bdd8bbe35d4a..8e10564251b8 100644
--- a/include/drawinglayer/primitive2d/patternfillprimitive2d.hxx
+++ b/include/drawinglayer/primitive2d/patternfillprimitive2d.hxx
@@ -42,9 +42,24 @@ namespace drawinglayer
{
private:
const basegfx::B2DPolyPolygon maMask;
- const Primitive2DContainer maChildren;
+ const Primitive2DContainer maChildren;
const basegfx::B2DRange maReferenceRange;
+ /// values holding the discrete buffer size
+ sal_uInt32 mnDiscreteWidth;
+ sal_uInt32 mnDiscreteHeight;
+
+ /// helper that is capable to calculate the needed discrete buffer size for
+ /// eventually buffered content
+ void calculateNeededDiscreteBufferSize(
+ sal_uInt32& rWidth,
+ sal_uInt32& rHeight,
+ const geometry::ViewInformation2D& rViewInformation) const;
+
+ /// helper which creates the content - checks if clipping is needed and eventually
+ /// creates buffered content to speed up rendering
+ Primitive2DContainer createContent(const geometry::ViewInformation2D& rViewInformation) const;
+
protected:
/// create local decomposition
virtual Primitive2DContainer create2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const override;
@@ -67,6 +82,9 @@ namespace drawinglayer
/// get range
virtual basegfx::B2DRange getB2DRange(const geometry::ViewInformation2D& rViewInformation) const override;
+ /// overload to react on evtl. buffered content
+ virtual Primitive2DContainer get2DDecomposition(const geometry::ViewInformation2D& rViewInformation) const override;
+
/// provide unique ID
DeclPrimitive2DIDBlock()
};
diff --git a/include/drawinglayer/texture/texture.hxx b/include/drawinglayer/texture/texture.hxx
index bbe620433a00..b4d78ba7a635 100644
--- a/include/drawinglayer/texture/texture.hxx
+++ b/include/drawinglayer/texture/texture.hxx
@@ -324,6 +324,9 @@ namespace drawinglayer
double mfOffsetX;
double mfOffsetY;
+ private:
+ sal_Int32 iterateTiles(::std::vector< basegfx::B2DHomMatrix >* pMatrices) const;
+
public:
GeoTexSvxTiled(
const basegfx::B2DRange& rRange,
@@ -334,7 +337,8 @@ namespace drawinglayer
// compare operator
virtual bool operator==(const GeoTexSvx& rGeoTexSvx) const override;
- void appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices);
+ void appendTransformations(::std::vector< basegfx::B2DHomMatrix >& rMatrices) const;
+ sal_uInt32 getNumberOfTiles() const;
};
} // end of namespace texture
} // end of namespace drawinglayer
diff --git a/vcl/win/gdi/gdiimpl.cxx b/vcl/win/gdi/gdiimpl.cxx
index c5e591a2eaf7..3728755cb756 100644
--- a/vcl/win/gdi/gdiimpl.cxx
+++ b/vcl/win/gdi/gdiimpl.cxx
@@ -1896,9 +1896,10 @@ bool WinSalGraphicsImpl::drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt
}
void impAddB2DPolygonToGDIPlusGraphicsPathReal(
- Gdiplus::GraphicsPath& rGraphicsPath,
+ Gdiplus::GpPath *pPath,
const basegfx::B2DPolygon& rPolygon,
- bool bNoLineJoin)
+ bool bNoLineJoin,
+ const basegfx::B2DVector* pLineWidths)
{
sal_uInt32 nCount(rPolygon.count());
@@ -1908,56 +1909,85 @@ void impAddB2DPolygonToGDIPlusGraphicsPathReal(
const bool bControls(rPolygon.areControlPointsUsed());
basegfx::B2DPoint aCurr(rPolygon.getB2DPoint(0));
- for(sal_uInt32 a(0); a < nEdgeCount; a++)
+ if(nEdgeCount)
{
- const sal_uInt32 nNextIndex((a + 1) % nCount);
- const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex));
- const bool b1stControlPointUsed(bControls && rPolygon.isNextControlPointUsed(a));
- const bool b2ndControlPointUsed(bControls && rPolygon.isPrevControlPointUsed(nNextIndex));
-
- if(b1stControlPointUsed || b2ndControlPointUsed)
+ for(sal_uInt32 a(0); a < nEdgeCount; a++)
{
- basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a));
- basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex));
-
- // tdf#99165 MS Gdiplus cannot handle creating correct extra geometry for fat lines
- // with LineCap or LineJoin when a bezier segment starts or ends trivial, e.g. has
- // no 1st or 2nd control point, despite that these are mathematicaly correct definitions
- // (basegfx can handle that). To solve, create replacement vectors to thre resp. next
- // control point with 1/3rd of length (the default control vector for these cases).
- // Only one of this can happen here, else the is(Next|Prev)ControlPointUsed wopuld have
- // both been false.
- // Caution: This error (and it's correction) might be necessary for other graphical
- // sub-systems in a similar way
- if(!b1stControlPointUsed)
+ const sal_uInt32 nNextIndex((a + 1) % nCount);
+ const basegfx::B2DPoint aNext(rPolygon.getB2DPoint(nNextIndex));
+ const bool b1stControlPointUsed(bControls && rPolygon.isNextControlPointUsed(a));
+ const bool b2ndControlPointUsed(bControls && rPolygon.isPrevControlPointUsed(nNextIndex));
+
+ if(b1stControlPointUsed || b2ndControlPointUsed)
{
- aCa = aCurr + ((aCb - aCurr) * 0.3);
+ basegfx::B2DPoint aCa(rPolygon.getNextControlPoint(a));
+ basegfx::B2DPoint aCb(rPolygon.getPrevControlPoint(nNextIndex));
+
+ // tdf#99165 MS Gdiplus cannot handle creating correct extra geometry for fat lines
+ // with LineCap or LineJoin when a bezier segment starts or ends trivial, e.g. has
+ // no 1st or 2nd control point, despite that these are mathematicaly correct definitions
+ // (basegfx can handle that). To solve, create replacement vectors to thre resp. next
+ // control point with 1/3rd of length (the default control vector for these cases).
+ // Only one of this can happen here, else the is(Next|Prev)ControlPointUsed wopuld have
+ // both been false.
+ // Caution: This error (and it's correction) might be necessary for other graphical
+ // sub-systems in a similar way
+ if(!b1stControlPointUsed)
+ {
+ aCa = aCurr + ((aCb - aCurr) * 0.3);
+ }
+ else if(!b2ndControlPointUsed)
+ {
+ aCb = aNext + ((aCa - aNext) * 0.3);
+ }
+
+ Gdiplus::DllExports::GdipAddPathBezier(
+ pPath,
+ aCurr.getX(), aCurr.getY(),
+ aCa.getX(), aCa.getY(),
+ aCb.getX(), aCb.getY(),
+ aNext.getX(), aNext.getY());
}
- else if(!b2ndControlPointUsed)
+ else
{
- aCb = aNext + ((aCa - aNext) * 0.3);
+ if(pLineWidths && aCurr.equal(aNext))
+ {
+ // For lines with no length Gdiplus unfortunately paints nothing,
+ // independent of LineCaps being set. This differs from e.g. SVG
+ // and other systems. To get geometry created, add some offset,
+ // based on line width to have something relative to current metrics
+ if(!basegfx::fTools::equalZero(pLineWidths->getX()))
+ {
+ Gdiplus::DllExports::GdipAddPathLine(
+ pPath,
+ aCurr.getX(), aCurr.getY(),
+ aNext.getX() + (pLineWidths->getX() * 0.1), aNext.getY());
+ }
+ else
+ {
+ Gdiplus::DllExports::GdipAddPathLine(
+ pPath,
+ aCurr.getX(), aCurr.getY(),
+ aNext.getX(), aNext.getY() + (pLineWidths->getY() * 0.1));
+ }
+ }
+ else
+ {
+ Gdiplus::DllExports::GdipAddPathLine(
+ pPath,
+ aCurr.getX(), aCurr.getY(),
+ aNext.getX(), aNext.getY());
+ }
}
- rGraphicsPath.AddBezier(
- static_cast< Gdiplus::REAL >(aCurr.getX()), static_cast< Gdiplus::REAL >(aCurr.getY()),
- static_cast< Gdiplus::REAL >(aCa.getX()), static_cast< Gdiplus::REAL >(aCa.getY()),
- static_cast< Gdiplus::REAL >(aCb.getX()), static_cast< Gdiplus::REAL >(aCb.getY()),
- static_cast< Gdiplus::REAL >(aNext.getX()), static_cast< Gdiplus::REAL >(aNext.getY()));
- }
- else
- {
- rGraphicsPath.AddLine(
- static_cast< Gdiplus::REAL >(aCurr.getX()), static_cast< Gdiplus::REAL >(aCurr.getY()),
- static_cast< Gdiplus::REAL >(aNext.getX()), static_cast< Gdiplus::REAL >(aNext.getY()));
- }
-
- if(a + 1 < nEdgeCount)
- {
- aCurr = aNext;
-
- if(bNoLineJoin)
+ if(a + 1 < nEdgeCount)
{
- rGraphicsPath.StartFigure();
+ aCurr = aNext;
+
+ if(bNoLineJoin)
+ {
+ Gdiplus::DllExports::GdipStartPathFigure(pPath);
+ }
}
}
}
@@ -1984,9 +2014,8 @@ bool WinSalGraphicsImpl::drawPolyPolygon( const basegfx::B2DPolyPolygon& rPolyPo
aGraphicsPath.StartFigure();
}
- impAddB2DPolygonToGDIPlusGraphicsPathReal(aGraphicsPath, rPolyPolygon.getB2DPolygon(a), false);
-
- aGraphicsPath.CloseFigure();
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(pPath, rPolyPolygon.getB2DPolygon(a), false, 0);
+ Gdiplus::DllExports::GdipClosePathFigure(pPath);
}
if(mrParent.getAntiAliasB2DDraw())
@@ -2098,7 +2127,7 @@ bool WinSalGraphicsImpl::drawPolyLine(
}
}
- impAddB2DPolygonToGDIPlusGraphicsPathReal(aGraphicsPath, rPolygon, bNoLineJoin);
+ impAddB2DPolygonToGDIPlusGraphicsPathReal(pPath, rPolygon, bNoLineJoin, &rLineWidths);
if(rPolygon.isClosed() && !bNoLineJoin)
{