Commits

ihi  committed 03958e9

CWS-TOOLING: integrate CWS aw066_DEV300
2009-03-19 17:20:55 +0100 aw r269762 : #i99662# enhanced MetaFile paint by avoiding single pixel scalings due to MapMode errors
2009-03-19 17:20:18 +0100 aw r269761 : #i99662# enhanced 3D AA by using the SnapHorVerLinesToDiscrete options flag to unify the hor/ver hairlines

  • Participants
  • Parent commits 0c603f7

Comments (0)

Files changed (5)

File basegfx/inc/basegfx/polygon/b3dpolygontools.hxx

 		bool equal(const B3DPolygon& rCandidateA, const B3DPolygon& rCandidateB, const double& rfSmallValue);
 		bool equal(const B3DPolygon& rCandidateA, const B3DPolygon& rCandidateB);
 
+		/** snap some polygon coordinates to discrete coordinates
+
+			This method allows to snap some polygon points to discrete (integer) values
+			which equals e.g. a snap to discrete coordinates. It will snap points of 
+			horizontal and vertical edges
+
+			@param rCandidate
+			The source polygon
+
+			@return
+			The modified version of the source polygon
+		*/
+		B3DPolygon snapPointsOfHorizontalOrVerticalEdges(const B3DPolygon& rCandidate);
+
 	} // end of namespace tools
 } // end of namespace basegfx
 

File basegfx/source/polygon/b3dpolygontools.cxx

 #include <basegfx/matrix/b3dhommatrix.hxx>
 #include <basegfx/polygon/b2dpolygon.hxx>
 #include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/tuple/b3ituple.hxx>
 #include <numeric>
 
 //////////////////////////////////////////////////////////////////////////////
 			return equal(rCandidateA, rCandidateB, fSmallValue);
 		}
 
+		// snap points of horizontal or vertical edges to discrete values
+		B3DPolygon snapPointsOfHorizontalOrVerticalEdges(const B3DPolygon& rCandidate)
+		{
+			const sal_uInt32 nPointCount(rCandidate.count());
+
+			if(nPointCount > 1)
+			{
+				// Start by copying the source polygon to get a writeable copy. The closed state is 
+				// copied by aRetval's initialisation, too, so no need to copy it in this method
+				B3DPolygon aRetval(rCandidate);
+
+				// prepare geometry data. Get rounded from original
+                B3ITuple aPrevTuple(basegfx::fround(rCandidate.getB3DPoint(nPointCount - 1)));
+				B3DPoint aCurrPoint(rCandidate.getB3DPoint(0));
+				B3ITuple aCurrTuple(basegfx::fround(aCurrPoint));
+
+				// loop over all points. This will also snap the implicit closing edge
+				// even when not closed, but that's no problem here
+				for(sal_uInt32 a(0); a < nPointCount; a++)
+				{
+					// get next point. Get rounded from original
+                    const bool bLastRun(a + 1 == nPointCount);
+                    const sal_uInt32 nNextIndex(bLastRun ? 0 : a + 1);
+					const B3DPoint aNextPoint(rCandidate.getB3DPoint(nNextIndex));
+					const B3ITuple aNextTuple(basegfx::fround(aNextPoint));
+
+					// get the states
+					const bool bPrevVertical(aPrevTuple.getX() == aCurrTuple.getX());
+					const bool bNextVertical(aNextTuple.getX() == aCurrTuple.getX());
+					const bool bPrevHorizontal(aPrevTuple.getY() == aCurrTuple.getY());
+					const bool bNextHorizontal(aNextTuple.getY() == aCurrTuple.getY());
+					const bool bSnapX(bPrevVertical || bNextVertical);
+					const bool bSnapY(bPrevHorizontal || bNextHorizontal);
+
+					if(bSnapX || bSnapY)
+					{
+						const B3DPoint aSnappedPoint(
+							bSnapX ? aCurrTuple.getX() : aCurrPoint.getX(),
+							bSnapY ? aCurrTuple.getY() : aCurrPoint.getY(),
+							aCurrPoint.getZ());
+
+						aRetval.setB3DPoint(a, aSnappedPoint);
+					}
+
+					// prepare next point
+                    if(!bLastRun)
+                    {
+    					aPrevTuple = aCurrTuple;
+	    				aCurrPoint = aNextPoint;
+		    			aCurrTuple = aNextTuple;
+                    }
+				}
+
+				return aRetval;
+			}
+			else
+			{
+				return rCandidate;
+			}
+		}
+
 	} // end of namespace tools
 } // end of namespace basegfx
 

File drawinglayer/inc/drawinglayer/processor3d/defaultprocessor3d.hxx

 #include <basegfx/matrix/b3dhommatrix.hxx>
 #include <basegfx/range/b2drange.hxx>
 #include <basegfx/color/bcolormodifier.hxx>
+#include <svtools/optionsdrawinglayer.hxx>
 
 //////////////////////////////////////////////////////////////////////////////
 // predefines
 			// the current active transparence texture
 			texture::GeoTexSvx*									mpTransparenceGeoTexSvx;
 
+			// SvtOptionsDrawinglayer incarnation to react on diverse settings
+            const SvtOptionsDrawinglayer						maDrawinglayerOpt;
+
 			// bitfield
 			unsigned											mbModulate : 1;
 			unsigned											mbFilter : 1;
 			bool getModulate() const { return mbModulate; }
 			bool getFilter() const { return mbFilter; }
 			bool getSimpleTextureActive() const { return mbSimpleTextureActive; }
+			
+			// access to Drawinglayer configuration options
+			const SvtOptionsDrawinglayer& getOptionsDrawinglayer() const { return maDrawinglayerOpt; }
 		};
 	} // end of namespace processor3d
 } // end of namespace drawinglayer

File drawinglayer/source/processor2d/vclprocessor2d.cxx

 				(sal_Int32)ceil(aOutlineRange.getMinX()), (sal_Int32)ceil(aOutlineRange.getMinY()),
 				(sal_Int32)floor(aOutlineRange.getMaxX()), (sal_Int32)floor(aOutlineRange.getMaxY()));
 
-			if(aDestRectView.Right() > aDestRectView.Left())
-			{
-				aDestRectView.Right()--;
-			}
-
-			if(aDestRectView.Bottom() > aDestRectView.Top())
-			{
-				aDestRectView.Bottom()--;
-			}
-
 			// get metafile (copy it)
 			GDIMetaFile aMetaFile;
 
 				aMetaFile.Rotate((sal_uInt16)(fRotation));
 			}
 
-			// paint it
-			aMetaFile.WindStart();
-			aMetaFile.Play(mpOutputDevice, aDestRectView.TopLeft(), aDestRectView.GetSize());
+			// Prepare target output size
+			Size aDestSize(aDestRectView.GetSize());
+
+			if(aDestSize.getWidth() && aDestSize.getHeight())
+			{
+				// Get preferred Metafile output size. When it's very equal to the output size, it's probably
+				// a rounding error somewhere, so correct it to get a 1:1 output without single pixel scalings
+				// of the Metafile (esp. for contaned Bitmaps, e.g 3D charts)
+				const Size aPrefSize(mpOutputDevice->LogicToPixel(aMetaFile.GetPrefSize(), aMetaFile.GetPrefMapMode()));
+
+				if(aPrefSize.getWidth() && (aPrefSize.getWidth() - 1 == aDestSize.getWidth() || aPrefSize.getWidth() + 1 == aDestSize.getWidth()))
+				{
+					aDestSize.setWidth(aPrefSize.getWidth());
+				}
+
+				if(aPrefSize.getHeight() && (aPrefSize.getHeight() - 1 == aDestSize.getHeight() || aPrefSize.getHeight() + 1 == aDestSize.getHeight()))
+				{
+					aDestSize.setHeight(aPrefSize.getHeight());
+				}
+
+				// paint it
+				aMetaFile.WindStart();
+				aMetaFile.Play(mpOutputDevice, aDestRectView.TopLeft(), aDestSize);
+			}
 		}
 
 		// mask group. Force output to VDev and create mask from given mask

File drawinglayer/source/processor3d/zbufferprocessor3d.cxx

 #include <drawinglayer/primitive3d/polygonprimitive3d.hxx>
 #include <drawinglayer/primitive3d/polypolygonprimitive3d.hxx>
 #include <drawinglayer/geometry/viewinformation2d.hxx>
+#include <basegfx/polygon/b3dpolygontools.hxx>
 
 //////////////////////////////////////////////////////////////////////////////
 
 			if(mpBZPixelRaster)
 			{
                 mpZBufferRasterConverter3D->setCurrentMaterial(rMaterial);
-				mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize ? mnAntiAlialize : 1);
+
+				if(mnAntiAlialize > 1)
+				{
+                    const bool bForceLineSnap(getOptionsDrawinglayer().IsAntiAliasing() && getOptionsDrawinglayer().IsSnapHorVerLinesToDiscrete());
+
+					if(bForceLineSnap)
+					{
+						basegfx::B3DHomMatrix aTransform;
+						basegfx::B3DPolygon aSnappedHairline(rHairline);
+						const double fScaleDown(1.0 / mnAntiAlialize);
+						const double fScaleUp(mnAntiAlialize);
+
+						// take oversampling out
+						aTransform.scale(fScaleDown, fScaleDown, 1.0);
+						aSnappedHairline.transform(aTransform);
+
+						// snap to integer
+						aSnappedHairline = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges(aSnappedHairline);
+
+						// add oversampling again
+						aTransform.identity();
+						aTransform.scale(fScaleUp, fScaleUp, 1.0);
+
+						if(false)
+						{
+							// when really want to go to single pixel lines, move to center.
+							// Without this translation, all hor/ver hairlines will be centered exactly
+							// between two pixel lines (which looks best)
+							const double fTranslateToCenter(mnAntiAlialize * 0.5);
+							aTransform.translate(fTranslateToCenter, fTranslateToCenter, 0.0);
+						}
+
+						aSnappedHairline.transform(aTransform);
+
+						mpZBufferRasterConverter3D->rasterconvertB3DPolygon(aSnappedHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize);
+					}
+					else
+					{
+						mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), mnAntiAlialize);
+					}
+				}
+				else
+				{
+					mpZBufferRasterConverter3D->rasterconvertB3DPolygon(rHairline, 0, mpBZPixelRaster->getHeight(), 1);
+				}
 			}
 		}