Author: alg Date: Tue Aug 13 15:10:34 2013 New Revision: 1513541 URL: http://svn.apache.org/r1513541 Log: i122149 Corrected stuff around polygon-based clip regions, do not use them where nt needed
Modified: openoffice/trunk/main/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx openoffice/trunk/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx openoffice/trunk/main/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx openoffice/trunk/main/basegfx/inc/basegfx/tuple/b2dtuple.hxx openoffice/trunk/main/basegfx/inc/basegfx/tuple/b3dtuple.hxx openoffice/trunk/main/basegfx/source/matrix/b2dhommatrixtools.cxx openoffice/trunk/main/basegfx/source/polygon/b2dpolygon.cxx openoffice/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx openoffice/trunk/main/basegfx/source/polygon/b2dpolypolygoncutter.cxx openoffice/trunk/main/basegfx/source/polygon/b2dpolypolygontools.cxx openoffice/trunk/main/sc/source/ui/inc/output.hxx openoffice/trunk/main/sc/source/ui/view/gridwin.cxx openoffice/trunk/main/sc/source/ui/view/output.cxx openoffice/trunk/main/vcl/source/gdi/region.cxx openoffice/trunk/main/vcl/win/source/gdi/salgdi.cxx Modified: openoffice/trunk/main/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx (original) +++ openoffice/trunk/main/basegfx/inc/basegfx/matrix/b2dhommatrixtools.hxx Tue Aug 13 15:10:34 2013 @@ -27,6 +27,7 @@ #include <sal/types.h> #include <basegfx/matrix/b2dhommatrix.hxx> #include <basegfx/vector/b2dvector.hxx> +#include <basegfx/range/b2drange.hxx> namespace rtl { class OUString; } @@ -131,6 +132,11 @@ namespace basegfx fRadiant); } + /// special for the case to map from source range to target range + B2DHomMatrix createSourceRangeTargetRangeTransform( + const B2DRange& rSourceRange, + const B2DRange& rTargetRange); + } // end of namespace tools } // end of namespace basegfx Modified: openoffice/trunk/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx (original) +++ openoffice/trunk/main/basegfx/inc/basegfx/polygon/b2dpolygontools.hxx Tue Aug 13 15:10:34 2013 @@ -527,6 +527,11 @@ namespace basegfx */ B2DPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolygon& rCandidate); + /** returns true if the Polygon only contains horizontal or vertical edges + so that it could be represented by RegionBands + */ + bool containsOnlyHorizontalAndVerticalEdges(const B2DPolygon& rCandidate); + } // end of namespace tools } // end of namespace basegfx Modified: openoffice/trunk/main/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx (original) +++ openoffice/trunk/main/basegfx/inc/basegfx/polygon/b2dpolypolygontools.hxx Tue Aug 13 15:10:34 2013 @@ -275,7 +275,12 @@ namespace basegfx */ B2DPolyPolygon snapPointsOfHorizontalOrVerticalEdges(const B2DPolyPolygon& rCandidate); - } // end of namespace tools + /** returns true if the Polygon only contains horizontal or vertical edges + so that it could be represented by RegionBands + */ + bool containsOnlyHorizontalAndVerticalEdges(const B2DPolyPolygon& rCandidate); + + } // end of namespace tools } // end of namespace basegfx #endif /* _BGFX_POLYPOLYGON_B2DPOLYGONTOOLS_HXX */ Modified: openoffice/trunk/main/basegfx/inc/basegfx/tuple/b2dtuple.hxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/basegfx/inc/basegfx/tuple/b2dtuple.hxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/basegfx/inc/basegfx/tuple/b2dtuple.hxx (original) +++ openoffice/trunk/main/basegfx/inc/basegfx/tuple/b2dtuple.hxx Tue Aug 13 15:10:34 2013 @@ -220,12 +220,12 @@ namespace basegfx bool operator==( const B2DTuple& rTup ) const { - return equal(rTup); + return mfX == rTup.mfX && mfY == rTup.mfY; } bool operator!=( const B2DTuple& rTup ) const { - return !equal(rTup); + return mfX != rTup.mfX || mfY != rTup.mfY; } B2DTuple& operator=( const B2DTuple& rTup ) Modified: openoffice/trunk/main/basegfx/inc/basegfx/tuple/b3dtuple.hxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/basegfx/inc/basegfx/tuple/b3dtuple.hxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/basegfx/inc/basegfx/tuple/b3dtuple.hxx (original) +++ openoffice/trunk/main/basegfx/inc/basegfx/tuple/b3dtuple.hxx Tue Aug 13 15:10:34 2013 @@ -252,12 +252,12 @@ namespace basegfx bool operator==( const B3DTuple& rTup ) const { - return equal(rTup); + return mfX == rTup.mfX && mfY == rTup.mfY && mfZ == rTup.mfZ; } bool operator!=( const B3DTuple& rTup ) const { - return !equal(rTup); + return mfX != rTup.mfX || mfY != rTup.mfY || mfZ != rTup.mfZ; } B3DTuple& operator=( const B3DTuple& rTup ) Modified: openoffice/trunk/main/basegfx/source/matrix/b2dhommatrixtools.cxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/basegfx/source/matrix/b2dhommatrixtools.cxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/basegfx/source/matrix/b2dhommatrixtools.cxx (original) +++ openoffice/trunk/main/basegfx/source/matrix/b2dhommatrixtools.cxx Tue Aug 13 15:10:34 2013 @@ -390,6 +390,47 @@ namespace basegfx return aRetval; } + + /// special for the case to map from source range to target range + B2DHomMatrix createSourceRangeTargetRangeTransform( + const B2DRange& rSourceRange, + const B2DRange& rTargetRange) + { + B2DHomMatrix aRetval; + + if(&rSourceRange == &rTargetRange) + { + return aRetval; + } + + if(!fTools::equalZero(rSourceRange.getMinX()) || !fTools::equalZero(rSourceRange.getMinY())) + { + aRetval.set(0, 2, -rSourceRange.getMinX()); + aRetval.set(1, 2, -rSourceRange.getMinY()); + } + + const double fSourceW(rSourceRange.getWidth()); + const double fSourceH(rSourceRange.getHeight()); + const bool bDivX(!fTools::equalZero(fSourceW) && !fTools::equal(fSourceW, 1.0)); + const bool bDivY(!fTools::equalZero(fSourceH) && !fTools::equal(fSourceH, 1.0)); + const double fScaleX(bDivX ? rTargetRange.getWidth() / fSourceW : rTargetRange.getWidth()); + const double fScaleY(bDivY ? rTargetRange.getHeight() / fSourceH : rTargetRange.getHeight()); + + if(!fTools::equalZero(fScaleX) || !fTools::equalZero(fScaleY)) + { + aRetval.scale(fScaleX, fScaleY); + } + + if(!fTools::equalZero(rTargetRange.getMinX()) || !fTools::equalZero(rTargetRange.getMinY())) + { + aRetval.translate( + rTargetRange.getMinX(), + rTargetRange.getMinY()); + } + + return aRetval; + } + } // end of namespace tools } // end of namespace basegfx Modified: openoffice/trunk/main/basegfx/source/polygon/b2dpolygon.cxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/basegfx/source/polygon/b2dpolygon.cxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/basegfx/source/polygon/b2dpolygon.cxx (original) +++ openoffice/trunk/main/basegfx/source/polygon/b2dpolygon.cxx Tue Aug 13 15:10:34 2013 @@ -1258,7 +1258,7 @@ namespace basegfx { OSL_ENSURE(nIndex < mpPolygon->count(), "B2DPolygon access outside range (!)"); - if(getB2DPoint(nIndex) != rValue) + if(mpPolygon->getPoint(nIndex) != rValue) { mpPolygon->setPoint(nIndex, rValue); } Modified: openoffice/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx (original) +++ openoffice/trunk/main/basegfx/source/polygon/b2dpolygontools.cxx Tue Aug 13 15:10:34 2013 @@ -3627,7 +3627,40 @@ namespace basegfx } } - } // end of namespace tools + bool containsOnlyHorizontalAndVerticalEdges(const B2DPolygon& rCandidate) + { + if(rCandidate.areControlPointsUsed()) + { + return false; + } + + const sal_uInt32 nPointCount(rCandidate.count()); + + if(nPointCount < 2) + { + return true; + } + + const sal_uInt32 nEdgeCount(rCandidate.isClosed() ? nPointCount + 1 : nPointCount); + basegfx::B2DPoint aLast(rCandidate.getB2DPoint(0)); + + for(sal_uInt32 a(1); a < nEdgeCount; a++) + { + const sal_uInt32 nNextIndex(a % nPointCount); + const basegfx::B2DPoint aCurrent(rCandidate.getB2DPoint(nNextIndex)); + + if(!basegfx::fTools::equal(aLast.getX(), aCurrent.getX()) && !basegfx::fTools::equal(aLast.getY(), aCurrent.getY())) + { + return false; + } + + aLast = aCurrent; + } + + return true; + } + + } // end of namespace tools } // end of namespace basegfx ////////////////////////////////////////////////////////////////////////////// Modified: openoffice/trunk/main/basegfx/source/polygon/b2dpolypolygoncutter.cxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/basegfx/source/polygon/b2dpolypolygoncutter.cxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/basegfx/source/polygon/b2dpolypolygoncutter.cxx (original) +++ openoffice/trunk/main/basegfx/source/polygon/b2dpolypolygoncutter.cxx Tue Aug 13 15:10:34 2013 @@ -110,6 +110,8 @@ namespace basegfx typedef ::std::vector< PN > PNV; typedef ::std::vector< VN > VNV; typedef ::std::vector< SN > SNV; + typedef ::std::pair< basegfx::B2DPoint /*orig*/, basegfx::B2DPoint /*repl*/ > CorrectionPair; + typedef ::std::vector< CorrectionPair > CorrectionTable; ////////////////////////////////////////////////////////////////////////////// @@ -120,6 +122,7 @@ namespace basegfx PNV maPNV; VNV maVNV; SNV maSNV; + CorrectionTable maCorrectionTable; unsigned mbIsCurve : 1; unsigned mbChanged : 1; @@ -462,25 +465,56 @@ namespace basegfx } } - void impSolve() - { - // sort by point to identify common nodes - ::std::sort(maSNV.begin(), maSNV.end()); + void impSolve() + { + // sort by point to identify common nodes easier + ::std::sort(maSNV.begin(), maSNV.end()); - // handle common nodes - const sal_uInt32 nNodeCount(maSNV.size()); + // handle common nodes + const sal_uInt32 nNodeCount(maSNV.size()); + sal_uInt32 a(0); + + // snap unsharp-equal points + if(nNodeCount) + { + basegfx::B2DPoint* pLast(&maSNV[0].mpPN->maPoint); - for(sal_uInt32 a(0); a < nNodeCount - 1; a++) - { - // test a before using it, not after. Also use nPointCount instead of aSortNodes.size() + for(a = 1; a < nNodeCount; a++) + { + basegfx::B2DPoint* pCurrent(&maSNV[a].mpPN->maPoint); + + if(pLast->equal(*pCurrent) && (pLast->getX() != pCurrent->getX() || pLast->getY() != pCurrent->getY())) + { + const basegfx::B2DPoint aMiddle((*pLast + *pCurrent) * 0.5); + + if(pLast->getX() != aMiddle.getX() || pLast->getY() != aMiddle.getY()) + { + maCorrectionTable.push_back(CorrectionPair(*pLast, aMiddle)); + *pLast = aMiddle; + } + + if(pCurrent->getX() != aMiddle.getX() || pCurrent->getY() != aMiddle.getY()) + { + maCorrectionTable.push_back(CorrectionPair(*pCurrent, aMiddle)); + *pCurrent = aMiddle; + } + } + + pLast = pCurrent; + } + } + + for(a = 0; a < nNodeCount - 1; a++) + { + // test a before using it, not after. Also use nPointCount instead of aSortNodes.size() PN& rPNb = *(maSNV[a].mpPN); - for(sal_uInt32 b(a + 1); b < nNodeCount && rPNb.maPoint.equal(maSNV[b].mpPN->maPoint); b++) - { - impHandleCommon(rPNb, *maSNV[b].mpPN); - } - } - } + for(sal_uInt32 b(a + 1); b < nNodeCount && rPNb.maPoint.equal(maSNV[b].mpPN->maPoint); b++) + { + impHandleCommon(rPNb, *maSNV[b].mpPN); + } + } + } public: solver(const B2DPolygon& rOriginal) @@ -638,12 +672,49 @@ namespace basegfx return aRetval; } - else - { - // no change, return original - return maOriginal; - } - } + else + { + const sal_uInt32 nCorrectionSize(maCorrectionTable.size()); + + // no change, return original + if(!nCorrectionSize) + { + return maOriginal; + } + + // apply coordinate corrections to ensure inside/outside correctness after solving + const sal_uInt32 nPolygonCount(maOriginal.count()); + basegfx::B2DPolyPolygon aRetval(maOriginal); + + for(sal_uInt32 a(0); a < nPolygonCount; a++) + { + basegfx::B2DPolygon aTemp(aRetval.getB2DPolygon(a)); + const sal_uInt32 nPointCount(aTemp.count()); + bool bChanged; + + for(sal_uInt32 b(0); b < nPointCount; b++) + { + const basegfx::B2DPoint aCandidate(aTemp.getB2DPoint(b)); + + for(sal_uInt32 c(0); c < nCorrectionSize; c++) + { + if(maCorrectionTable[c].first.getX() == aCandidate.getX() && maCorrectionTable[c].first.getY() == aCandidate.getY()) + { + aTemp.setB2DPoint(b, maCorrectionTable[c].second); + bChanged = true; + } + } + } + + if(bChanged) + { + aRetval.setB2DPolygon(a, aTemp); + } + } + + return aRetval; + } + } }; ////////////////////////////////////////////////////////////////////////////// Modified: openoffice/trunk/main/basegfx/source/polygon/b2dpolypolygontools.cxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/basegfx/source/polygon/b2dpolypolygontools.cxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/basegfx/source/polygon/b2dpolypolygontools.cxx (original) +++ openoffice/trunk/main/basegfx/source/polygon/b2dpolypolygontools.cxx Tue Aug 13 15:10:34 2013 @@ -594,7 +594,24 @@ namespace basegfx return aRetval; } - } // end of namespace tools + bool containsOnlyHorizontalAndVerticalEdges(const B2DPolyPolygon& rCandidate) + { + if(rCandidate.areControlPointsUsed()) + { + return false; + } + + for(sal_uInt32 a(0); a < rCandidate.count(); a++) + { + if(!containsOnlyHorizontalAndVerticalEdges(rCandidate.getB2DPolygon(a))) + { + return false; + } + } + + return true; + } + } // end of namespace tools } // end of namespace basegfx ////////////////////////////////////////////////////////////////////////////// Modified: openoffice/trunk/main/sc/source/ui/inc/output.hxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/sc/source/ui/inc/output.hxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/sc/source/ui/inc/output.hxx (original) +++ openoffice/trunk/main/sc/source/ui/inc/output.hxx Tue Aug 13 15:10:34 2013 @@ -245,7 +245,7 @@ public: void DrawSelectiveObjects(const sal_uInt16 nLayer); sal_Bool SetChangedClip(); // sal_False = nix - PolyPolygon GetChangedArea(); + Region GetChangedAreaRegion(); void FindChanged(); void SetPagebreakMode( ScPageBreakData* pPageData ); Modified: openoffice/trunk/main/sc/source/ui/view/gridwin.cxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/sc/source/ui/view/gridwin.cxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/sc/source/ui/view/gridwin.cxx (original) +++ openoffice/trunk/main/sc/source/ui/view/gridwin.cxx Tue Aug 13 15:10:34 2013 @@ -4449,10 +4449,12 @@ void ScGridWindow::UpdateFormulas() aOutputData.FindChanged(); - PolyPolygon aChangedPoly( aOutputData.GetChangedArea() ); // logic (PixelToLogic) - if ( aChangedPoly.Count() ) + // #122149# do not use old GetChangedArea() which used polygon-based Regions, but use + // the region-band based new version; anyways, only rectangles are added + Region aChangedRegion( aOutputData.GetChangedAreaRegion() ); // logic (PixelToLogic) + if(!aChangedRegion.IsEmpty()) { - Invalidate( aChangedPoly ); + Invalidate(aChangedRegion); } CheckNeedsRepaint(); // #i90362# used to be called via Draw() - still needed here Modified: openoffice/trunk/main/sc/source/ui/view/output.cxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/sc/source/ui/view/output.cxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/sc/source/ui/view/output.cxx (original) +++ openoffice/trunk/main/sc/source/ui/view/output.cxx Tue Aug 13 15:10:34 2013 @@ -1685,42 +1685,46 @@ void ScOutputData::DrawRotatedFrame( con // Drucker -PolyPolygon ScOutputData::GetChangedArea() +Region ScOutputData::GetChangedAreaRegion() { - PolyPolygon aPoly; + Region aRegion; + Rectangle aDrawingRect; + bool bHad(false); + long nPosY = nScrY; + SCSIZE nArrY; - Rectangle aDrawingRect; - aDrawingRect.Left() = nScrX; - aDrawingRect.Right() = nScrX+nScrW-1; + aDrawingRect.Left() = nScrX; + aDrawingRect.Right() = nScrX+nScrW-1; - sal_Bool bHad = sal_False; - long nPosY = nScrY; - SCSIZE nArrY; - for (nArrY=1; nArrY+1<nArrCount; nArrY++) - { - RowInfo* pThisRowInfo = &pRowInfo[nArrY]; + for(nArrY=1; nArrY+1<nArrCount; nArrY++) + { + RowInfo* pThisRowInfo = &pRowInfo[nArrY]; - if ( pThisRowInfo->bChanged ) - { - if (!bHad) - { - aDrawingRect.Top() = nPosY; - bHad = sal_True; - } - aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1; - } - else if (bHad) - { - aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) ); - bHad = sal_False; - } - nPosY += pRowInfo[nArrY].nHeight; - } + if(pThisRowInfo->bChanged) + { + if(!bHad) + { + aDrawingRect.Top() = nPosY; + bHad = true; + } - if (bHad) - aPoly.Insert( Polygon( pDev->PixelToLogic(aDrawingRect) ) ); + aDrawingRect.Bottom() = nPosY + pRowInfo[nArrY].nHeight - 1; + } + else if(bHad) + { + aRegion.Union(pDev->PixelToLogic(aDrawingRect)); + bHad = false; + } + + nPosY += pRowInfo[nArrY].nHeight; + } + + if(bHad) + { + aRegion.Union(pDev->PixelToLogic(aDrawingRect)); + } - return aPoly; + return aRegion; } sal_Bool ScOutputData::SetChangedClip() Modified: openoffice/trunk/main/vcl/source/gdi/region.cxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/vcl/source/gdi/region.cxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/vcl/source/gdi/region.cxx (original) +++ openoffice/trunk/main/vcl/source/gdi/region.cxx Tue Aug 13 15:10:34 2013 @@ -1274,9 +1274,10 @@ Rectangle Region::GetBoundRect() const } else { + // #122149# corrected rounding, no need for ceil() and floor() here return Rectangle( - static_cast<sal_Int32>(floor(aRange.getMinX())), static_cast<sal_Int32>(floor(aRange.getMinY())), - static_cast<sal_Int32>(ceil(aRange.getMaxX())), static_cast<sal_Int32>(ceil(aRange.getMaxY()))); + basegfx::fround(aRange.getMinX()), basegfx::fround(aRange.getMinY()), + basegfx::fround(aRange.getMaxX()), basegfx::fround(aRange.getMaxY())); } } Modified: openoffice/trunk/main/vcl/win/source/gdi/salgdi.cxx URL: http://svn.apache.org/viewvc/openoffice/trunk/main/vcl/win/source/gdi/salgdi.cxx?rev=1513541&r1=1513540&r2=1513541&view=diff ============================================================================== --- openoffice/trunk/main/vcl/win/source/gdi/salgdi.cxx (original) +++ openoffice/trunk/main/vcl/win/source/gdi/salgdi.cxx Tue Aug 13 15:10:34 2013 @@ -26,20 +26,18 @@ #include <stdio.h> #include <string.h> - #include <rtl/strbuf.hxx> - #include <tools/svwin.h> #include <tools/debug.hxx> #include <tools/poly.hxx> - #include <basegfx/polygon/b2dpolygon.hxx> #include <basegfx/polygon/b2dpolygontools.hxx> - +#include <basegfx/polygon/b2dpolypolygontools.hxx> #include <win/wincomp.hxx> #include <win/saldata.hxx> #include <win/salgdi.h> #include <win/salframe.h> +#include <basegfx/matrix/b2dhommatrixtools.hxx> using namespace rtl; @@ -853,15 +851,47 @@ void WinSalGraphics::ResetClipRegion() bool WinSalGraphics::setClipRegion( const Region& i_rClip ) { - if ( mhRegion ) - { - DeleteRegion( mhRegion ); - mhRegion = 0; - } - - if( i_rClip.HasPolyPolygonOrB2DPolyPolygon() ) - { - const basegfx::B2DPolyPolygon aPolyPolygon( i_rClip.GetAsB2DPolyPolygon() ); + if ( mhRegion ) + { + DeleteRegion( mhRegion ); + mhRegion = 0; + } + + bool bUsePolygon(i_rClip.HasPolyPolygonOrB2DPolyPolygon()); + static bool bTryToAvoidPolygon(true); + + // #122149# try to avoid usage of PolyPolygon ClipRegions when PolyPolygon is no curve + // and only contains horizontal/vertical edges. In that case, use the fallback + // in GetRegionRectangles which will use Region::GetAsRegionBand() which will do + // the correct polygon-to-RegionBand transformation. + // Background is that when using the same Rectangle as rectangle or as Polygon + // clip region will lead to different results; the polygon-based one will be + // one pixel less to the right and down (see GDI docu for CreatePolygonRgn). This + // again is because of the polygon-nature and it's classic handling when filling. + // This also means that all cases which use a 'true' polygon-based incarnation of + // a Region should know what they do - it may lead to repaint errors. + if(bUsePolygon && bTryToAvoidPolygon) + { + const basegfx::B2DPolyPolygon aPolyPolygon( i_rClip.GetAsB2DPolyPolygon() ); + + if(!aPolyPolygon.areControlPointsUsed()) + { + if(basegfx::tools::containsOnlyHorizontalAndVerticalEdges(aPolyPolygon)) + { + bUsePolygon = false; + } + } + } + + if(bUsePolygon) + { + // #122149# check the comment above to know that this may lead to potentioal repaint + // problems. It may be solved (if needed) by scaling the polygon by one in X + // and Y. Currently the workaround to only use it if really unavoidable will + // solve most cases. When someone is really using polygon-based Regions he + // should know what he is doing. + // Added code to do that scaling to check if it works, testing it. + const basegfx::B2DPolyPolygon aPolyPolygon( i_rClip.GetAsB2DPolyPolygon() ); const sal_uInt32 nCount(aPolyPolygon.count()); if( nCount ) @@ -869,21 +899,38 @@ bool WinSalGraphics::setClipRegion( cons std::vector< POINT > aPolyPoints; aPolyPoints.reserve( 1024 ); std::vector< INT > aPolyCounts( nCount, 0 ); - + basegfx::B2DHomMatrix aExpand; + static bool bExpandByOneInXandY(true); + + if(bExpandByOneInXandY) + { + const basegfx::B2DRange aRangeS(aPolyPolygon.getB2DRange()); + const basegfx::B2DRange aRangeT(aRangeS.getMinimum(), aRangeS.getMaximum() + basegfx::B2DTuple(1.0, 1.0)); + aExpand = basegfx::B2DHomMatrix(basegfx::tools::createSourceRangeTargetRangeTransform(aRangeS, aRangeT)); + } + for(sal_uInt32 a(0); a < nCount; a++) { - basegfx::B2DPolygon aPoly(aPolyPolygon.getB2DPolygon(a)); - - aPoly = basegfx::tools::adaptiveSubdivideByDistance( aPoly, 1 ); - const sal_uInt32 nPoints = aPoly.count(); + const basegfx::B2DPolygon aPoly( + basegfx::tools::adaptiveSubdivideByDistance( + aPolyPolygon.getB2DPolygon(a), + 1)); + const sal_uInt32 nPoints(aPoly.count()); aPolyCounts[a] = nPoints; - + for( sal_uInt32 b = 0; b < nPoints; b++ ) { - basegfx::B2DPoint aPt( aPoly.getB2DPoint( b ) ); + basegfx::B2DPoint aPt(aPoly.getB2DPoint(b)); + + if(bExpandByOneInXandY) + { + aPt = aExpand * aPt; + } + POINT aPOINT; - aPOINT.x = (LONG)aPt.getX(); - aPOINT.y = (LONG)aPt.getY(); + // #122149# do correct rounding + aPOINT.x = basegfx::fround(aPt.getX()); + aPOINT.y = basegfx::fround(aPt.getY()); aPolyPoints.push_back( aPOINT ); } } @@ -969,53 +1016,6 @@ bool WinSalGraphics::setClipRegion( cons } } - //ImplRegionInfo aInfo; - //long nX, nY, nW, nH; - //bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH ); - //while( bRegionRect ) - //{ - // if ( nW && nH ) - // { - // long nRight = nX + nW; - // long nBottom = nY + nH; - // - // if ( bFirstClipRect ) - // { - // pBoundRect->left = nX; - // pBoundRect->top = nY; - // pBoundRect->right = nRight; - // pBoundRect->bottom = nBottom; - // bFirstClipRect = false; - // } - // else - // { - // if ( nX < pBoundRect->left ) - // pBoundRect->left = (int)nX; - // - // if ( nY < pBoundRect->top ) - // pBoundRect->top = (int)nY; - // - // if ( nRight > pBoundRect->right ) - // pBoundRect->right = (int)nRight; - // - // if ( nBottom > pBoundRect->bottom ) - // pBoundRect->bottom = (int)nBottom; - // } - // - // pNextClipRect->left = (int)nX; - // pNextClipRect->top = (int)nY; - // pNextClipRect->right = (int)nRight; - // pNextClipRect->bottom = (int)nBottom; - // pNextClipRect++; - // } - // else - // { - // mpClipRgnData->rdh.nCount--; - // mpClipRgnData->rdh.nRgnSize -= sizeof( RECT ); - // } - // bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH ); - //} - // create clip region from ClipRgnData if ( mpClipRgnData->rdh.nCount == 1 ) { @@ -1054,7 +1054,16 @@ bool WinSalGraphics::setClipRegion( cons } if( mhRegion ) - SelectClipRgn( getHDC(), mhRegion ); + { + SelectClipRgn( getHDC(), mhRegion ); + + // debug code if you weant to check range of the newly applied ClipRegion + //RECT aBound; + //const int aRegionType = GetRgnBox(mhRegion, &aBound); + // + //bool bBla = true; + } + return mhRegion != 0; }