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/11/23 18:14:32 UTC

svn commit: r1412988 [3/3] - in /incubator/ooo/branches/alg/aw080/main: basegfx/inc/basegfx/matrix/ filter/inc/filter/msfilter/ filter/source/msfilter/ sd/source/filter/eppt/ svx/source/svdraw/ vcl/source/gdi/

Modified: incubator/ooo/branches/alg/aw080/main/filter/source/msfilter/eschesdo.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/aw080/main/filter/source/msfilter/eschesdo.cxx?rev=1412988&r1=1412987&r2=1412988&view=diff
==============================================================================
--- incubator/ooo/branches/alg/aw080/main/filter/source/msfilter/eschesdo.cxx (original)
+++ incubator/ooo/branches/alg/aw080/main/filter/source/msfilter/eschesdo.cxx Fri Nov 23 17:14:30 2012
@@ -85,8 +85,8 @@ ImplEESdrWriter::ImplEESdrWriter( Escher
 		mnPagesWritten			( 0 ),
 		mnShapeMasterTitle		( 0 ),
 		mnShapeMasterBody		( 0 ),
-		mbStatusIndicator		( sal_False ),
-		mbStatus				( sal_False )
+		mbStatusIndicator		( false ),
+		mbStatus				( false )
 {
 }
 
@@ -95,29 +95,27 @@ ImplEESdrWriter::ImplEESdrWriter( Escher
 
 void ImplEESdrWriter::implPrepareLogicToLogic()
 {
-	if(maLogicToLogic.isIdentity())
-	{
-		maLogicToLogic = Application::GetDefaultDevice()->GetViewTransformation(maMapModeSrc);
-		maLogicToLogic.invert();
-		maLogicToLogic = Application::GetDefaultDevice()->GetViewTransformation(maMapModeDest) * maLogicToLogic;
-	}
+    if(maLogicToLogic.isIdentity())
+    {
+        maLogicToLogic = Application::GetDefaultDevice()->GetTransformLogicToLogic(maMapModeSrc, maMapModeDest);
+    }
 }
 
 // -------------------------------------------------------------------
-// TTTT not needed?
-//basegfx::B2DPoint ImplEESdrWriter::ImplMapB2DPoint( const basegfx::B2DPoint& rB2DPoint )
-//{
-//	if(maMapModeSrc == maMapModeDest)
-//	{
-//		return rB2DPoint;
-//	}
-//	else
-//	{
-//		implPrepareLogicToLogic();
-//
-//		return maLogicToLogic * rB2DPoint;
-//	}
-//}
+
+basegfx::B2DPoint ImplEESdrWriter::ImplMapB2DPoint( const basegfx::B2DPoint& rB2DPoint )
+{
+	if(maMapModeSrc == maMapModeDest)
+	{
+		return rB2DPoint;
+	}
+	else
+	{
+		implPrepareLogicToLogic();
+
+		return maLogicToLogic * rB2DPoint;
+	}
+}
 
 // -------------------------------------------------------------------
 
@@ -156,34 +154,56 @@ basegfx::B2DRange ImplEESdrWriter::ImplM
 
 // -------------------------------------------------------------------
 
-void ImplEESdrWriter::ImplFlipBoundingBox( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt )
+void ImplEESdrWriter::ImplHandleRotation( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt )
 {
-	sal_Int32 nAngle = rObj.GetAngle();
+    if(rObj.GetAngle())
+    {
+        const basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose& rMat(rObj.getTransform());
 
-	if ( nAngle < 0 )
-		nAngle = ( 36000 + nAngle ) % 36000;
-	else
-		nAngle = ( 36000 - ( nAngle % 36000 ) );
+        // rObj.getObjectRange() is already mapped, while rMat is not. Thus, adapt aCurrentCenter, too.
+        // MS shape format rotates around the object center, so adapt adapt ObjectRange
+        // to be centered at the center of the original shape to do this
+        const basegfx::B2DPoint aCurrentCenter(ImplMapB2DPoint(rMat.getB2DHomMatrix() * basegfx::B2DPoint(0.5, 0.5)));
+        const basegfx::B2DPoint aObjectRangeCenter(rObj.getObjectRange().getCenter());
+        basegfx::B2DRange aObjectRange(rObj.getObjectRange());
+        bool bChanged(false);
+
+        if(!aCurrentCenter.equal(aObjectRangeCenter))
+        {
+            const basegfx::B2DHomMatrix aAdaptToCenterRotation(
+                basegfx::tools::createTranslateB2DHomMatrix(
+                    aCurrentCenter - aObjectRangeCenter));
+
+            aObjectRange.transform(aAdaptToCenterRotation);
+            bChanged = true;
+        }
+
+        // do use inverted rotation here: The old model format (in which the value is here)
+        // was wrongly oriented. PPT uses the correct mathematical orientation, so invert
+        sal_Int32 nAngle(36000 - rObj.GetAngle());
+
+        // adapt angle to MS format
+        nAngle *= 655;
+        nAngle += 0x8000;
+        nAngle &=~0xffff; // round to full degrees
+        rPropOpt.AddOpt(ESCHER_Prop_Rotation, nAngle);
+        rObj.SetAngle( nAngle );
 
-	double fVal = (double)nAngle * F_PI18000;
-	double	fCos = cos( fVal );
-	double	fSin = sin( fVal );
-
-    basegfx::B2DPoint aPoint(rObj.getObjectRange().getMinimum());
-    const basegfx::B2DVector aScale(rObj.getObjectRange().getRange());
-	const basegfx::B2DVector aHalfScale(aScale * 0.5);
-	const double nXDiff(fCos * aHalfScale.getX() + fSin * (-aHalfScale.getY()));
-	const double nYDiff(-( fSin * aHalfScale.getX() - fCos * ( -aHalfScale.getY())));
-
-    aPoint -= basegfx::B2DPoint(aHalfScale.getX() - nXDiff, aHalfScale.getY() + nYDiff);
-
-	nAngle *= 655;
-	nAngle += 0x8000;
-	nAngle &=~0xffff;									// nAngle auf volle Gradzahl runden
-	rPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
+        if((nAngle >= (45 << 16) && nAngle < (135 << 16)) || (nAngle >= (225 << 16) && nAngle < (315 << 16)))
+        {
+            // in this region of rotation the ObjectRange is already rotated,
+            // so do this here, too
+            const basegfx::B2DHomMatrix aMirrorDiagonal(
+                basegfx::tools::createRotateAroundPoint(
+                    aObjectRange.getCenter(),
+                    F_PI2));
+
+            aObjectRange.transform(aMirrorDiagonal);
+            bChanged = true;
+        }
 
-	rObj.SetAngle( nAngle );
-	rObj.setObjectRange(basegfx::B2DRange(aPoint, aPoint + aScale));
+        rObj.setObjectRange(aObjectRange);
+    }
 }
 
 //	-----------------------------------------------------------------------
@@ -202,7 +222,7 @@ void ImplEESdrWriter::ImplFlipBoundingBo
 	mpEscherEx->OpenContainer( ESCHER_SpContainer );				\
 	ADD_SHAPE( ESCHER_ShpInst_TextBox, 0xa00 );						\
 	if ( bFill )													\
-		aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );	\
+		aPropOpt.CreateFillProperties( rObj.mXPropSet, true );	    \
 	if( rObj.ImplGetText() )										\
 		aPropOpt.CreateTextProperties( rObj.mXPropSet,				\
 			mpEscherEx->QueryTextID( rObj.GetShapeRef(),			\
@@ -222,8 +242,8 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 {
 	sal_uInt32 nShapeID = 0;
 	sal_uInt16 nShapeType = 0;
-	sal_Bool bDontWriteText = sal_False;		// if a metafile is written as shape replacement, then the text is already part of the metafile
-	sal_Bool bAdditionalText = sal_False;
+	bool bDontWriteText(false);		// if a metafile is written as shape replacement, then the text is already part of the metafile
+	bool bAdditionalText(false);
 	sal_uInt32 nGrpShapeID = 0;
 
 	do {
@@ -261,7 +281,9 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 			}
 			break;
 		}
-		rObj.SetAngle( rObj.ImplGetInt32PropertyValue( ::rtl::OUString::createFromAscii("RotateAngle") ));
+
+        // TTTT: Moved to below (at transformation)
+        // rObj.SetAngle( rObj.ImplGetInt32PropertyValue( ::rtl::OUString::createFromAscii("RotateAngle") ));
 
 		if( ( rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("IsFontwork") ) &&
 			::cppu::any2bool( rObj.GetUsrAny() ) ) ||
@@ -285,26 +307,46 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
         basegfx::B2DRange aObjectRange(0.0, 0.0, 1.0, 1.0);
         sal_uInt32 nMirrorFlags(0);
 
-		if(rObj.ImplGetPropertyValue(::rtl::OUString::createFromAscii("Transformation")))
         {
-		    drawing::HomogenMatrix3 aMatrix;
-            rObj.GetUsrAny() >>= aMatrix;
-            const basegfx::tools::B2DHomMatrixBufferedDecompose aMat(basegfx::tools::UnoHomogenMatrix3ToB2DHomMatrix(aMatrix));
-            // do not use absolute value of scale, it is WANTED
-            // that the range is really covering the unrotated, unmirrored shape
+            const basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose& rMat(rObj.getTransform());
+            
+            // Use translation and scale to create range. Use signed scale
+            // to get the unrotated SnapRect
             aObjectRange = basegfx::B2DRange(
-                aMat.getTranslate(), 
-                aMat.getTranslate() + aMat.getScale()); 
+                rMat.getTranslate(), 
+                rMat.getTranslate() + rMat.getScale());
+
+            double fObjectRotation(rMat.getRotate());
+            bool bMirroredX(rMat.getScale().getX() < 0.0);
+            bool bMirroredY(rMat.getScale().getY() < 0.0);
+
+            // if mirror is X and Y, replace with 180 degree rotation. Prefer
+            // rotation export over mirror export.
+            if(bMirroredX && bMirroredY)
+            {
+                bMirroredX = bMirroredY = false;
+                fObjectRotation += F_PI;
+            }
 
-            if(aMat.getScale().getX() < 0.0)
+            if(bMirroredX)
             {
                 nMirrorFlags |= SHAPEFLAG_FLIPH;
             }
 
-            if(aMat.getScale().getY() < 0.0)
+            if(bMirroredY)
             {
                 nMirrorFlags |= SHAPEFLAG_FLIPV;
             }
+
+            if(bMirroredX != bMirroredY)
+            {
+                // if one axis is mirrored, invert the rotation
+                fObjectRotation = -fObjectRotation;
+            }
+
+            // convert rotation to old coordinate system and set
+            const double fSnappedRotation(basegfx::snapToZeroRange(-fObjectRotation / F_PI18000, 36000.0));
+            rObj.SetAngle(basegfx::fround(fSnappedRotation));
         }
 
         if ( !mpPicStrm )
@@ -328,7 +370,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 				ADD_SHAPE( 
                     ESCHER_ShpInst_PictureFrame,
                     0xa00 ); // TTTT: no mirroring, metafile export version
-				if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ), sal_False ) )
+				if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ), false ) )
 				{
 					aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
 					aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );		// no fill
@@ -340,7 +382,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 						
 						rObj.setObjectRange(aRange);
 						rObj.SetAngle( 0 );
-						bDontWriteText = sal_True;
+						bDontWriteText = true;
 					}
 				}
 			}
@@ -350,12 +392,12 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
                     sal::static_int_cast< sal_uInt16 >(eShapeType),
                     nMirrorFlags | 0xa00 ); // Flags: mirror | Connector | HasSpt
 				aPropOpt.CreateCustomShapeProperties( eShapeType, rObj.GetShapeRef() );
-				aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
+				aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
 				if ( rObj.ImplGetText() )
 				{
 					if ( !aPropOpt.IsFontWork() )
 						aPropOpt.CreateTextProperties( rObj.mXPropSet, mpEscherEx->QueryTextID(
-							rObj.GetShapeRef(),	rObj.GetShapeId() ), sal_True, sal_False );
+							rObj.GetShapeRef(),	rObj.GetShapeId() ), true, false );
 				}
 			}
 		}
@@ -383,11 +425,11 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
                     ESCHER_ShpInst_Rectangle, 
                     nMirrorFlags | 0xa00 );			// Flags: mirror | Connector | HasSpt
 			}
-			aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
+			aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
 			if( rObj.ImplGetText() )
 				aPropOpt.CreateTextProperties( rObj.mXPropSet,
 					mpEscherEx->QueryTextID( rObj.GetShapeRef(),
-						rObj.GetShapeId() ), sal_False, sal_False );
+						rObj.GetShapeId() ), false, false );
 		}
 		else if ( rObj.GetType().EqualsAscii( "drawing.Ellipse" ))
 		{
@@ -405,7 +447,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 				ADD_SHAPE( 
                     ESCHER_ShpInst_Ellipse, 
                     nMirrorFlags | 0xa00 );			// Flags: mirror | Connector | HasSpt
-				aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );;
+				aPropOpt.CreateFillProperties( rObj.mXPropSet, true );;
             }
 			else
 			{
@@ -431,13 +473,13 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 
                 if(aOutline.isClosed())
                 {
-					aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_False, aNewRect, &aPolygon );
-					aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True  );
+					aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, false, aNewRect, &aPolygon );
+					aPropOpt.CreateFillProperties( rObj.mXPropSet, true  );
                 }
                 else
                 {
-					aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_False, aNewRect, &aPolygon );
-					aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
+					aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, false, aNewRect, &aPolygon );
+					aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
                 }
 				
                 const basegfx::B2DRange aRange(ImplMapB2DRange(basegfx::B2DRange(aNewRect.X, aNewRect.Y, aNewRect.X + aNewRect.Width, aNewRect.Y + aNewRect.Height)));
@@ -447,7 +489,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 			if ( rObj.ImplGetText() )
 				aPropOpt.CreateTextProperties( rObj.mXPropSet,
 					mpEscherEx->QueryTextID( rObj.GetShapeRef(),
-						rObj.GetShapeId() ), sal_False, sal_False );
+						rObj.GetShapeId() ), false, false );
 
 		}
 		else if ( rObj.GetType().EqualsAscii( "drawing.Control" ))
@@ -459,7 +501,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 			sal_uInt16 nSpType, nSpFlags;
 			::com::sun::star::awt::Rectangle aNewRect;
 			if ( aPropOpt.CreateConnectorProperties( rObj.GetShapeRef(),
-							rSolverContainer, aNewRect, nSpType, nSpFlags ) == sal_False )
+							rSolverContainer, aNewRect, nSpType, nSpFlags ) == false )
 				break;
 
             const basegfx::B2DRange aRange(ImplMapB2DRange(basegfx::B2DRange(aNewRect.X, aNewRect.Y, aNewRect.X + aNewRect.Width, aNewRect.Y + aNewRect.Height)));
@@ -477,7 +519,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 			{
 				mpEscherEx->EnterGroup( &maRect );
 				mpEscherEx->OpenContainer( ESCHER_SpContainer );
-				ImplWriteAny( ANY_FLAGS_LINE, sal_False );
+				ImplWriteAny( ANY_FLAGS_LINE, false );
 				sal_uInt32 nFlags = 0xa00;											// Flags: Connector | HasSpt
 				if ( maRect.Top() > maRect.Bottom() )
 					nFlags |= 0x80;												// Flags: VertMirror
@@ -488,7 +530,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
                     ESCHER_ShpInst_Line, 
                     nMirrorFlags | nFlags ); // Flags: mirror | nFlags
 				aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
-				aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
+				aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
 				mpEscherEx->EndCount( ESCHER_OPT, 3 );
 				maRect.Justify();
 				mpEscherEx->AddClientAnchor( maRect );
@@ -559,7 +601,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 		else if ( rObj.GetType().EqualsAscii( "drawing.Line" ))
 		{
 			::com::sun::star::awt::Rectangle aNewRect;
-			aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_LINE, sal_False, aNewRect, NULL );
+			aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_LINE, false, aNewRect, NULL );
             MapRect(rObj);
 			//i27942: Poly/Lines/Bezier do not support text.
 
@@ -576,7 +618,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
                 ESCHER_ShpInst_Line, 
                 nMirrorFlags ); // Flags: mirror
 			aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
-			aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
+			aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
 			rObj.SetAngle( 0 );
 		}
 		else if ( rObj.GetType().EqualsAscii( "drawing.PolyPolygon" ))
@@ -584,16 +626,16 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 			if( rObj.ImplHasText() )
 			{
 				nGrpShapeID = ImplEnterAdditionalTextGroup(	rObj.GetShapeRef(), &rObj.getObjectRange() );
-				bAdditionalText = sal_True;
+				bAdditionalText = true;
 			}
 			mpEscherEx->OpenContainer( ESCHER_SpContainer );
 			ADD_SHAPE( 
                 ESCHER_ShpInst_NotPrimitive, 
                 nMirrorFlags | 0xa00 );		// Flags: mirror | Connector | HasSpt
 			::com::sun::star::awt::Rectangle aNewRect;
-			aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_False, aNewRect, NULL );
+			aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, false, aNewRect, NULL );
             MapRect(rObj);
-			aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
+			aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
 			rObj.SetAngle( 0 );
 		}
 		else if ( rObj.GetType().EqualsAscii( "drawing.PolyLine" ))
@@ -605,9 +647,9 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
                 ESCHER_ShpInst_NotPrimitive, 
                 nMirrorFlags | 0xa00 );		// Flags: mirror | Connector | HasSpt
 			::com::sun::star::awt::Rectangle aNewRect;
-			aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_False, aNewRect, NULL );
+			aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, false, aNewRect, NULL );
             MapRect(rObj);
-			aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
+			aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
 			rObj.SetAngle( 0 );
 		}
 		else if ( rObj.GetType().EqualsAscii( "drawing.OpenBezier" ) )
@@ -619,9 +661,9 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
                 ESCHER_ShpInst_NotPrimitive, 
                 nMirrorFlags | 0xa00 );		// Flags: mirror | Connector | HasSpt
 			::com::sun::star::awt::Rectangle aNewRect;
-			aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_True, aNewRect, NULL );
+			aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, true, aNewRect, NULL );
             MapRect(rObj);
-			aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
+			aPropOpt.CreateLineProperties( rObj.mXPropSet, false );
 			rObj.SetAngle( 0 );
 		}
 		else if ( rObj.GetType().EqualsAscii( "drawing.ClosedBezier" ) )
@@ -629,16 +671,16 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 			if ( rObj.ImplHasText() )
 			{
 				nGrpShapeID = ImplEnterAdditionalTextGroup(	rObj.GetShapeRef(), &rObj.getObjectRange() );
-				bAdditionalText = sal_True;
+				bAdditionalText = true;
 			}
 			mpEscherEx->OpenContainer( ESCHER_SpContainer );
 			ADD_SHAPE( 
                 ESCHER_ShpInst_NotPrimitive, 
                 nMirrorFlags | 0xa00 );		// Flags: mirror | Connector | HasSpt
 			::com::sun::star::awt::Rectangle aNewRect;
-			aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_True, aNewRect, NULL );
+			aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, true, aNewRect, NULL );
             MapRect(rObj);
-			aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
+			aPropOpt.CreateFillProperties( rObj.mXPropSet, true );
 			rObj.SetAngle( 0 );
 		}
 		else if ( rObj.GetType().EqualsAscii( "drawing.GraphicObject" ))
@@ -668,7 +710,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 					ADD_SHAPE( 
                         ESCHER_ShpInst_Rectangle, 
                         nMirrorFlags | 0xa00 );			// Flags: mirror | Connector | HasSpt
-					if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), sal_True,  sal_True, sal_False ) )
+					if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), true,  true, false ) )
 					{
 						aPropOpt.AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
 						aPropOpt.AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
@@ -678,7 +720,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 						if ( rObj.ImplGetText() )
 							aPropOpt.CreateTextProperties( rObj.mXPropSet,
 								mpEscherEx->QueryTextID( rObj.GetShapeRef(),
-									rObj.GetShapeId() ), sal_False, sal_False );
+									rObj.GetShapeId() ), false, false );
 					}
 				}
 				else
@@ -686,14 +728,14 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 					ADD_SHAPE( 
                         ESCHER_ShpInst_PictureFrame, 
                         nMirrorFlags | 0xa00 ); // Flags: mirror | Connector | HasSpt
-					if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), sal_False, sal_True ) )
+					if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), false, true ) )
 						aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
 				}
 			}
 		}
 		else if ( rObj.GetType().EqualsAscii(  "drawing.Text" ))
 		{
-			SHAPE_TEXT( sal_True );
+			SHAPE_TEXT( true );
 		}
 		else if ( rObj.GetType().EqualsAscii( "drawing.Page" ))
 		{
@@ -729,7 +771,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 			else
 			{
 				//2do: could be made an option in HostAppData whether OLE object should be written or not
-				sal_Bool bAppOLE = sal_True;
+				bool bAppOLE(true);
 				ADD_SHAPE( 
                     ESCHER_ShpInst_PictureFrame,
 					nMirrorFlags | 0xa00 | (bAppOLE ? SHAPEFLAG_OLESHAPE : 0) ); // Flags: mirror | Connector | HasSpt | OLE
@@ -763,7 +805,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
                 nMirrorFlags | ESCHER_ShpInst_PictureFrame, // TTTT: Probably nor mirror needed, check
                 0xa00 ); // Flags: Connector | HasSpt
 
-                if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Bitmap" ) ), sal_False ) )
+                if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Bitmap" ) ), false ) )
 				aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
 		}
 		else if ( rObj.GetType().EqualsAscii( "drawing.dontknow" ))
@@ -773,7 +815,7 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 			ADD_SHAPE( 
                 ESCHER_ShpInst_PictureFrame, 
                 nMirrorFlags | 0xa00 ); // Flags: mirror | Connector | HasSpt
-			if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ), sal_False ) )
+			if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ), false ) )
 				aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
 		}
 		else
@@ -790,7 +832,9 @@ sal_uInt32 ImplEESdrWriter::ImplWriteSha
 		}
 
 		if( rObj.GetAngle() )
-			ImplFlipBoundingBox( rObj, aPropOpt );
+        {
+			ImplHandleRotation( rObj, aPropOpt );
+        }
 
 		aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
 		mpEscherEx->Commit( aPropOpt, rObj.getObjectRange() );
@@ -835,22 +879,53 @@ void ImplEESdrWriter::ImplWriteAdditiona
 
         // TTTT: adapted to transformation
         basegfx::B2DRange aObjectRange(0.0, 0.0, 1.0, 1.0);
+        sal_uInt32 nMirrorFlags(0);
 
-		if(rObj.ImplGetPropertyValue(::rtl::OUString::createFromAscii("Transformation")))
         {
-		    drawing::HomogenMatrix3 aMatrix;
-            rObj.GetUsrAny() >>= aMatrix;
-            const basegfx::tools::B2DHomMatrixBufferedDecompose aMat(basegfx::tools::UnoHomogenMatrix3ToB2DHomMatrix(aMatrix));
-            aObjectRange = basegfx::B2DRange(aMat.getTranslate(), aMat.getTranslate() + basegfx::absolute(aMat.getScale()));
+            const basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose& rMat(rObj.getTransform());
+
+            // Use translation and scale to create range. Use signed scale
+            // to get the unrotated SnapRect
+            aObjectRange = basegfx::B2DRange(
+                rMat.getTranslate(), 
+                rMat.getTranslate() + rMat.getScale());
+
+            double fObjectRotation(rMat.getRotate());
+            bool bMirroredX(rMat.getScale().getX() < 0.0);
+            bool bMirroredY(rMat.getScale().getY() < 0.0);
+
+            // if mirror is X and Y, replace with 180 degree rotation. Prefer
+            // rotation export over mirror export.
+            if(bMirroredX && bMirroredY)
+            {
+                bMirroredX = bMirroredY = false;
+                fObjectRotation += F_PI;
+            }
+
+            if(bMirroredX)
+            {
+                nMirrorFlags |= SHAPEFLAG_FLIPH;
+            }
+
+            if(bMirroredY)
+            {
+                nMirrorFlags |= SHAPEFLAG_FLIPV;
+            }
+
+            // convert rotation to old coordinate system and set
+            const double fSnappedRotation(basegfx::snapToZeroRange(-fObjectRotation / F_PI18000, 36000.0));
+            rObj.SetAngle(basegfx::fround(fSnappedRotation));
         }
-		
+
         if ( !mpPicStrm )
             mpPicStrm = mpEscherEx->QueryPictureStream();
         
         EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aObjectRange );
 
-        rObj.SetAngle( rObj.ImplGetInt32PropertyValue( ::rtl::OUString::createFromAscii("RotateAngle")));
-		sal_Int32 nAngle = rObj.GetAngle();
+        // TTTT: Done above, see transformation
+        // rObj.SetAngle( rObj.ImplGetInt32PropertyValue( ::rtl::OUString::createFromAscii("RotateAngle")));
+
+        sal_Int32 nAngle = rObj.GetAngle();
 		if( rObj.GetType().EqualsAscii( "drawing.Line" ))
 		{
 //2do: this does not work right
@@ -859,7 +934,9 @@ void ImplEESdrWriter::ImplWriteAdditiona
             
             rObj.setObjectRange(aRange);
 			mpEscherEx->OpenContainer( ESCHER_SpContainer );
-			mpEscherEx->AddShape( ESCHER_ShpInst_TextBox, 0xa00 );
+			mpEscherEx->AddShape( 
+                ESCHER_ShpInst_TextBox, 
+                nMirrorFlags | 0xa00 ); // Flags: mirror | Connector | HasSpt
 			
             if ( rObj.ImplGetText() )
 				aPropOpt.CreateTextProperties( rObj.mXPropSet,
@@ -869,16 +946,25 @@ void ImplEESdrWriter::ImplWriteAdditiona
 			aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
 			aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
 			aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x60006 );		// Size Shape To Fit Text
-			if ( nAngle < 0 )
+			
+            if ( nAngle < 0 )
+            {
 				nAngle = ( 36000 + nAngle ) % 36000;
+            }
+
 			if ( nAngle )
-				ImplFlipBoundingBox( rObj, aPropOpt );
+            {
+				ImplHandleRotation( rObj, aPropOpt );
+            }
 		}
 		else
 		{
 			mpEscherEx->OpenContainer( ESCHER_SpContainer );
             nShapeID = mpEscherEx->GenerateShapeId();
-			mpEscherEx->AddShape( nShapeType = ESCHER_ShpInst_TextBox, 0xa00, nShapeID );
+			mpEscherEx->AddShape( 
+                nShapeType = ESCHER_ShpInst_TextBox, 
+                nMirrorFlags | 0xa00, // Flags: mirror | Connector | HasSpt
+                nShapeID );
 			if ( rObj.ImplGetText() )
 				aPropOpt.CreateTextProperties( rObj.mXPropSet,
 					mpEscherEx->QueryTextID( rObj.GetShapeRef(),
@@ -898,7 +984,8 @@ void ImplEESdrWriter::ImplWriteAdditiona
 			mpEscherEx->SetGroupSnapPositionAndScale( mpEscherEx->GetGroupLevel(), rObj.getObjectRange() );
 			mpEscherEx->SetGroupLogicPositionAndScale( mpEscherEx->GetGroupLevel(), rObj.getObjectRange() );
 		}
-		rObj.SetAngle( nAngle );
+
+        rObj.SetAngle( nAngle );
 		aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
 		mpEscherEx->Commit( aPropOpt, rObj.getObjectRange() );
 
@@ -944,14 +1031,14 @@ sal_uInt32 ImplEESdrWriter::ImplEnterAdd
 
 // -------------------------------------------------------------------
 
-sal_Bool ImplEESdrWriter::ImplInitPageValues()
+bool ImplEESdrWriter::ImplInitPageValues()
 {
 	mnIndices = 0;
 	mnOutlinerCount = 0;				// die gliederungsobjekte muessen dem layout entsprechen,
 	mnEffectCount = 0;
-	mbIsTitlePossible = sal_True;			// bei mehr als einem title geht powerpoint in die knie
+	mbIsTitlePossible = true;			// bei mehr als einem title geht powerpoint in die knie
 
-	return sal_True;
+	return true;
 }
 
 
@@ -959,7 +1046,7 @@ sal_Bool ImplEESdrWriter::ImplInitPageVa
 
 void ImplEESdrWriter::ImplWritePage(
 			EscherSolverContainer& rSolverContainer,
-			ImplEESdrPageType ePageType, sal_Bool /* bBackGround */ )
+			ImplEESdrPageType ePageType, bool /* bBackGround */ )
 {
 	ImplInitPageValues();
 
@@ -1195,14 +1282,18 @@ const SdrObject* EscherEx::GetSdrObject(
 
 // -------------------------------------------------------------------
 
-ImplEESdrObject::ImplEESdrObject( ImplEscherExSdr& rEx,
-									const SdrObject& rObj ) :
-	mnShapeId( 0 ),
-	mnTextSize( 0 ),
-	mnAngle( 0 ),
-	mbValid( sal_False ),
-	mbPresObj( sal_False ),
-	mbEmptyPresObj( sal_False )
+ImplEESdrObject::ImplEESdrObject( ImplEscherExSdr& rEx, const SdrObject& rObj ) 
+:   mXShape(),
+    mAny(),
+    maObjectRange(),
+    maObjTrans(),
+    mType(),
+	mnShapeId(0),
+	mnTextSize(0),
+	mnAngle(0),
+	mbValid(false),
+	mbPresObj(false),
+	mbEmptyPresObj( false)
 {
 	SdrPage* pPage = rObj.getSdrPageFromSdrObject();
 	DBG_ASSERT( pPage, "ImplEESdrObject::ImplEESdrObject: no SdrPage" );
@@ -1210,20 +1301,23 @@ ImplEESdrObject::ImplEESdrObject( ImplEs
     {
         // why not declare a const parameter if the object will
         // not be modified?
-        mXShape = uno::Reference< drawing::XShape >::query( ((SdrObject*)&rObj)->getUnoShape() );;
+        mXShape = uno::Reference< drawing::XShape >::query( ((SdrObject*)&rObj)->getUnoShape() );
         Init( rEx );
     }
 }
 
-ImplEESdrObject::ImplEESdrObject( ImplEESdrWriter& rEx,
-									const Reference< XShape >& rShape ) :
-	mXShape( rShape ),
-	mnShapeId( 0 ),
-	mnTextSize( 0 ),
-	mnAngle( 0 ),
-	mbValid( sal_False ),
-	mbPresObj( sal_False ),
-	mbEmptyPresObj( sal_False )
+ImplEESdrObject::ImplEESdrObject( ImplEESdrWriter& rEx, const Reference< XShape >& rShape ) 
+:   mXShape(rShape),
+    mAny(),
+    maObjectRange(),
+    maObjTrans(),
+    mType(),
+	mnShapeId(0),
+	mnTextSize(0),
+	mnAngle(0),
+	mbValid(false),
+	mbPresObj(false),
+	mbEmptyPresObj(false)
 {
 	Init( rEx );
 }
@@ -1271,59 +1365,44 @@ basegfx::B2DRange getUnrotatedGroupBound
                 if(mXPropSet.is())
                 {
                     const Any aAny = mXPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")));
-                    
-                    if(aAny.hasValue())
+                    HomogenMatrix3 aMatrix;
+
+                    if(aAny.hasValue() && (aAny >>= aMatrix))
                     {
-                        HomogenMatrix3 aMatrix;
+                        basegfx::B2DHomMatrix aHomogenMatrix(
+                            basegfx::tools::UnoHomogenMatrix3ToB2DHomMatrix(aMatrix));
+                        basegfx::B2DVector aScale, aTranslate;
+                        double fRotate, fShearX;
+
+                        // decopose transformation
+                        aHomogenMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
+
+                        // check if rotation needs to be corrected
+                        if(!basegfx::fTools::equalZero(fRotate))
+                        {
+                            // to correct, keep in mind that ppt graphics are rotated around their center
+                            const basegfx::B2DPoint aCenter(aHomogenMatrix * basegfx::B2DPoint(0.5, 0.5));
+
+                            aHomogenMatrix.translate(-aCenter.getX(), -aCenter.getY());
+                            aHomogenMatrix.rotate(-fRotate);
+                            aHomogenMatrix.translate(aCenter.getX(), aCenter.getY());
+                        }
 
-                        if(aAny >>= aMatrix)
+                        // check if shear needs to be corrected (always correct shear,
+                        // ppt does not know about it)
+                        if(!basegfx::fTools::equalZero(fShearX))
                         {
-                            basegfx::B2DHomMatrix aHomogenMatrix;
+                            const basegfx::B2DPoint aMinimum(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
 
-                            aHomogenMatrix.set(0, 0, aMatrix.Line1.Column1);
-                            aHomogenMatrix.set(0, 1, aMatrix.Line1.Column2);
-                            aHomogenMatrix.set(0, 2, aMatrix.Line1.Column3);
-                            aHomogenMatrix.set(1, 0, aMatrix.Line2.Column1);
-                            aHomogenMatrix.set(1, 1, aMatrix.Line2.Column2);
-                            aHomogenMatrix.set(1, 2, aMatrix.Line2.Column3);
-                            aHomogenMatrix.set(2, 0, aMatrix.Line3.Column1);
-                            aHomogenMatrix.set(2, 1, aMatrix.Line3.Column2);
-                            aHomogenMatrix.set(2, 2, aMatrix.Line3.Column3);
-
-                            basegfx::B2DVector aScale, aTranslate;
-                            double fRotate, fShearX;
-
-                            // decopose transformation
-                            aHomogenMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
-
-                            // check if rotation needs to be corrected
-                            if(!basegfx::fTools::equalZero(fRotate))
-                            {
-                                // to correct, keep in mind that ppt graphics are rotated around their center
-                                const basegfx::B2DPoint aCenter(aHomogenMatrix * basegfx::B2DPoint(0.5, 0.5));
-
-                                aHomogenMatrix.translate(-aCenter.getX(), -aCenter.getY());
-                                aHomogenMatrix.rotate(-fRotate);
-                                aHomogenMatrix.translate(aCenter.getX(), aCenter.getY());
-                            }
-
-
-                            // check if shear needs to be corrected (always correct shear,
-                            // ppt does not know about it)
-                            if(!basegfx::fTools::equalZero(fShearX))
-                            {
-                                const basegfx::B2DPoint aMinimum(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
-
-                                aHomogenMatrix.translate(-aMinimum.getX(), -aMinimum.getY());
-                                aHomogenMatrix.shearX(-fShearX);
-                                aHomogenMatrix.translate(aMinimum.getX(), aMinimum.getY());
-                            }
-
-                            // create range. It's no longer rotated (or sheared), so use
-                            // minimum and maximum values
-                            aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
-                            aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(1.0, 1.0));
+                            aHomogenMatrix.translate(-aMinimum.getX(), -aMinimum.getY());
+                            aHomogenMatrix.shearX(-fShearX);
+                            aHomogenMatrix.translate(aMinimum.getX(), aMinimum.getY());
                         }
+
+                        // create range. It's no longer rotated (or sheared), so use
+                        // minimum and maximum values
+                        aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
+                        aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(1.0, 1.0));
                     }
                 }
             }
@@ -1360,12 +1439,34 @@ void ImplEESdrObject::Init( ImplEESdrWri
         else
         {
             // if it's no group, use position and size directly, roated/sheared or not
-            const ::com::sun::star::awt::Point aPoint(mXShape->getPosition());
-            const ::com::sun::star::awt::Size aSize(mXShape->getSize());
-            const basegfx::B2DRange aRange(
-                basegfx::B2DRange(
+            const Any aAny = mXPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")));
+            drawing::HomogenMatrix3 aMatrix;
+            basegfx::B2DRange aRange;
+
+            if(aAny.hasValue() && (aAny >>= aMatrix))
+            {
+                maObjTrans = basegfx::tools::UnoHomogenMatrix3ToB2DHomMatrix(aMatrix);
+
+                // Use translation and scale to create range. Use signed scale
+                // to get the unrotated SnapRect
+                aRange = basegfx::B2DRange(
+                    maObjTrans.getTranslate(), 
+                    maObjTrans.getTranslate() + maObjTrans.getScale());
+            }
+            else
+            {
+                // fallback to getPosition/getSize(), but will miss mirrorings
+                // and should not be necessary
+                const ::com::sun::star::awt::Point aPoint(mXShape->getPosition());
+                const ::com::sun::star::awt::Size aSize(mXShape->getSize());
+
+                maObjTrans = basegfx::tools::createScaleTranslateB2DHomMatrix(
+                    aSize.Width, aSize.Height,
+                    aPoint.X, aPoint.Y);
+                aRange = basegfx::B2DRange(
                     aPoint.X, aPoint.Y, 
-                    aPoint.X + aSize.Width, aPoint.Y + aSize.Height));
+                    aPoint.X + aSize.Width, aPoint.Y + aSize.Height);
+            }
 
             setObjectRange(rEx.ImplMapB2DRange(aRange));
         }
@@ -1374,51 +1475,55 @@ void ImplEESdrObject::Init( ImplEESdrWri
 		static const OUString sEmptyPresStr(rtl::OUString::createFromAscii("IsEmptyPresentationObject"));
 
 		if( ImplGetPropertyValue( sPresStr ) )
+        {
 			mbPresObj = ::cppu::any2bool( mAny );
+        }
 
 		if( mbPresObj && ImplGetPropertyValue( sEmptyPresStr ) )
+        {
 			mbEmptyPresObj = ::cppu::any2bool( mAny );
+        }
 
-		mbValid = sal_True;
+		mbValid = true;
 	}
 }
 
-//sal_Bool ImplEESdrObject::ImplGetPropertyValue( const OUString& rString )
-sal_Bool ImplEESdrObject::ImplGetPropertyValue( const sal_Unicode* rString )
+//bool ImplEESdrObject::ImplGetPropertyValue( const OUString& rString )
+bool ImplEESdrObject::ImplGetPropertyValue( const sal_Unicode* rString )
 {
-	sal_Bool bRetValue = sal_False;
+	bool bRetValue(false);
 	if( mbValid )
 	{
 		try
 		{
 			mAny = mXPropSet->getPropertyValue( rString );
 			if( mAny.hasValue() )
-				bRetValue = sal_True;
+				bRetValue = true;
 		}
 		catch( ::com::sun::star::uno::Exception& )
 		{
-			bRetValue = sal_False;
+			bRetValue = false;
 		}
 	}
 	return bRetValue;
 }
 
 #ifdef USED
-sal_Bool ImplEESdrObject::ImplGetPropertyValue( const Reference< XPropertySet >& rXPropSet,
+bool ImplEESdrObject::ImplGetPropertyValue( const Reference< XPropertySet >& rXPropSet,
 											const OUString& rString )
 {
-	sal_Bool bRetValue = sal_False;
+	bool bRetValue(false);
 	if( mbValid )
 	{
 		try
 		{
 			mAny = rXPropSet->getPropertyValue( rString );
 			if( 0 != mAny.get() )
-				bRetValue = sal_True;
+				bRetValue = true;
 		}
 		catch( ::com::sun::star::uno::Exception& )
 		{
-			bRetValue = sal_False;
+			bRetValue = false;
 		}
 	}
 	return bRetValue;
@@ -1440,9 +1545,10 @@ sal_uInt32 ImplEESdrObject::ImplGetText(
 	return mnTextSize;
 }
 
-sal_Bool ImplEESdrObject::ImplHasText() const
+bool ImplEESdrObject::ImplHasText() const
 {
 	Reference< XText > xXText( mXShape, UNO_QUERY );
 	return xXText.is() && xXText->getString().getLength();
 }
 
+// eof

Modified: incubator/ooo/branches/alg/aw080/main/filter/source/msfilter/eschesdo.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/aw080/main/filter/source/msfilter/eschesdo.hxx?rev=1412988&r1=1412987&r2=1412988&view=diff
==============================================================================
--- incubator/ooo/branches/alg/aw080/main/filter/source/msfilter/eschesdo.hxx (original)
+++ incubator/ooo/branches/alg/aw080/main/filter/source/msfilter/eschesdo.hxx Fri Nov 23 17:14:30 2012
@@ -37,20 +37,24 @@ class ImplEscherExSdr;
 
 class ImplEESdrObject
 {
+private:
 	::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >			mXShape;
 //	XTextRef			mXText;	// TextRef des globalen Text
 	::com::sun::star::uno::Any				mAny;
 	
     // the object range, split in pos and scale to keep the evtl. negative size (mirroring)
     basegfx::B2DRange   maObjectRange;
+    basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose   maObjTrans;
 
     String				mType;
-	sal_uInt32				mnShapeId;
-	sal_uInt32				mnTextSize;
-	sal_Int32				mnAngle;
-	sal_Bool 				mbValid : 1;
-	sal_Bool				mbPresObj : 1;
-	sal_Bool				mbEmptyPresObj : 1;
+	sal_uInt32			mnShapeId;
+	sal_uInt32			mnTextSize;
+	sal_Int32			mnAngle;
+
+    /// bitfield
+	bool                mbValid : 1;
+	bool                mbPresObj : 1;
+	bool                mbEmptyPresObj : 1;
 
 	void Init( ImplEESdrWriter& rEx );
 public:
@@ -60,7 +64,7 @@ public:
 	ImplEESdrObject( ImplEESdrWriter& rEx, const ::com::sun::star::uno::Reference< ::com::sun::star::drawing::XShape >& rShape );
 	~ImplEESdrObject();
 
-	sal_Bool ImplGetPropertyValue( const sal_Unicode* pString );
+	bool ImplGetPropertyValue( const sal_Unicode* pString );
 
 	sal_Int32 ImplGetInt32PropertyValue( const sal_Unicode* pStr, sal_uInt32 nDef = 0 )
 	{ return ImplGetPropertyValue( pStr ) ? *(sal_Int32*)mAny.getValue() : nDef; }
@@ -78,16 +82,18 @@ public:
 
 	sal_uInt32				GetTextSize() const 	{ return mnTextSize; }
 
-	sal_Bool 				IsValid() const 		{ return mbValid; }
-	sal_Bool				IsPresObj() const 		{ return mbPresObj; }
-	sal_Bool				IsEmptyPresObj() const 	{ return mbEmptyPresObj; }
+	bool 				IsValid() const 		{ return mbValid; }
+	bool				IsPresObj() const 		{ return mbPresObj; }
+	bool				IsEmptyPresObj() const 	{ return mbEmptyPresObj; }
 	sal_uInt32				GetShapeId() const 		{ return mnShapeId; }
 	void 				SetShapeId( sal_uInt32 nVal ) { mnShapeId = nVal; }
 
 	const SdrObject*	GetSdrObject() const;
 
 	sal_uInt32 				ImplGetText();
-	sal_Bool 				ImplHasText() const;
+	bool 				ImplHasText() const;
+
+    basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose& getTransform() { return maObjTrans; }
 };
 
 
@@ -141,26 +147,27 @@ protected:
 
 		sal_uInt16				mnEffectCount;
 
-		sal_Bool				mbIsTitlePossible;
-		sal_Bool				mbStatusIndicator;
-		sal_Bool				mbStatus;
+        /// bitfield
+		bool				mbIsTitlePossible : 1;
+		bool				mbStatusIndicator : 1;
+		bool				mbStatus : 1;
 
 
 								ImplEESdrWriter( EscherEx& rEx );
 
-			sal_Bool				ImplInitPageValues();
+			bool				ImplInitPageValues();
 
 			void				ImplWritePage(
 									EscherSolverContainer& rSolver,
 									ImplEESdrPageType ePageType,
-									sal_Bool bBackGround = sal_False );
+									bool bBackGround = false );
 
 			sal_uInt32				ImplWriteShape( ImplEESdrObject& rObj,
 									EscherSolverContainer& rSolver,
 									ImplEESdrPageType ePageType );	// returns ShapeID
 
-			void				ImplFlipBoundingBox( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt );
-			sal_Bool				ImplGetText( ImplEESdrObject& rObj );
+			void				ImplHandleRotation( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt );
+			bool				ImplGetText( ImplEESdrObject& rObj );
 			void				ImplWriteAdditionalText(
 												ImplEESdrObject& rObj,
 												const Point& rTextRefPoint );
@@ -170,7 +177,7 @@ protected:
 
 
 public:
-//			basegfx::B2DPoint ImplMapB2DPoint( const basegfx::B2DPoint& rPoint );
+			basegfx::B2DPoint ImplMapB2DPoint( const basegfx::B2DPoint& rPoint );
 			basegfx::B2DVector ImplMapB2DVector( const basegfx::B2DVector& rScale );
 			basegfx::B2DRange ImplMapB2DRange(const basegfx::B2DRange& rRange);
 

Modified: incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/eppt.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/eppt.cxx?rev=1412988&r1=1412987&r2=1412988&view=diff
==============================================================================
--- incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/eppt.cxx (original)
+++ incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/eppt.cxx Fri Nov 23 17:14:30 2012
@@ -150,6 +150,7 @@ PPTWriter::PPTWriter( const std::vector<
     mXCursorPropSet(),
     mXTextField(),
     maObjectRange(),
+    maObjTrans(),
     mnMirrorFlags(0),
     mfObjectRotation(0.0),
     mType(),

Modified: incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/eppt.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/eppt.hxx?rev=1412988&r1=1412987&r2=1412988&view=diff
==============================================================================
--- incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/eppt.hxx (original)
+++ incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/eppt.hxx Fri Nov 23 17:14:30 2012
@@ -709,6 +709,7 @@ class PPTWriter : public GroupTable, pub
 		
         // the object range, split in pos and scale to keep the evtl. negative size (mirroring)
         basegfx::B2DRange               maObjectRange;
+        basegfx::tools::B2DHomMatrixBufferedOnDemandDecompose   maObjTrans;
 //        basegfx::B2DRange               maObjectRange; // TTTT mirrored needed here ?!?
         sal_uInt32                      mnMirrorFlags;
 //        bool                            mbMirroredX;

Modified: incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/epptso.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/epptso.cxx?rev=1412988&r1=1412987&r2=1412988&view=diff
==============================================================================
--- incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/epptso.cxx (original)
+++ incubator/ooo/branches/alg/aw080/main/sd/source/filter/eppt/epptso.cxx Fri Nov 23 17:14:30 2012
@@ -1138,40 +1138,56 @@ bool PPTWriter::ImplGetShapeByIndex( sal
             break;
         
         // get object transformation
-        basegfx::tools::B2DHomMatrixBufferedDecompose aObjTrans(ImplGetObjectTransformation());
+        maObjTrans = ImplGetObjectTransformation();
 
         // map to PPt metrics
-        aObjTrans = basegfx::tools::B2DHomMatrixBufferedDecompose(
-            basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix(
-                maMap100thMmToMs* aObjTrans.getScale(),
-                aObjTrans.getShearX(),
-                aObjTrans.getRotate(),
-                maMap100thMmToMs * aObjTrans.getTranslate()));
-
-        // Use translation and scale to create range.
-        // Do not use absolute value of scale, it is WANTED
-        // that the range is really covering the unrotated, unmirrored shape
+        maObjTrans.setScale(maMap100thMmToMs* maObjTrans.getScale());
+        maObjTrans.setTranslate(maMap100thMmToMs * maObjTrans.getTranslate());
+
+        // Use translation and scale to create range. Use signed scale
+        // to get the unrotated SnapRect
         maObjectRange = basegfx::B2DRange(
-            aObjTrans.getTranslate(), 
-            aObjTrans.getTranslate() + aObjTrans.getScale());
+            maObjTrans.getTranslate(), 
+            maObjTrans.getTranslate() + maObjTrans.getScale());
+
+        // check mirroring
+        bool bMirroredX(maObjTrans.getScale().getX() < 0.0);
+        bool bMirroredY(maObjTrans.getScale().getY() < 0.0);
 
-        // use scale to detect mirrorings
-        if(aObjTrans.getScale().getX() < 0.0)
+        // get rotation
+        mfObjectRotation = maObjTrans.getRotate();
+
+        // if mirror is X and Y, replace with 180 degree rotation. Prefer
+        // rotation export over mirror export.
+        if(bMirroredX && bMirroredY)
+        {
+            bMirroredX = bMirroredY = false;
+            mfObjectRotation += F_PI;
+        }
+
+        // reset mirror flags
+        mnMirrorFlags = 0;
+
+        // set mirror flags
+        if(bMirroredX)
         {
             mnMirrorFlags |= SHAPEFLAG_FLIPH;
         }
 
-        if(aObjTrans.getScale().getY() < 0.0)
+        if(bMirroredY)
         {
             mnMirrorFlags |= SHAPEFLAG_FLIPV;
         }
 
+        if(bMirroredX != bMirroredY)
+        {
+            // if one axis is mirrored, invert the rotation
+            mfObjectRotation = -mfObjectRotation;
+        }
+
 //        mbMirroredX = aObjTrans.getScale().getX() < 0.0;
 //        mbMirroredY = aObjTrans.getScale().getY() < 0.0;
 
-        // get rotation
-        mfObjectRotation = aObjTrans.getRotate();
-
         // mbMirroredX and mbMirroredY are new aspects to handle. The text
         // in offices before transformation ignored mirrorX and used a 180
         // deg rotation for mirrorY. To get close to the old behaviour, use
@@ -1188,7 +1204,7 @@ bool PPTWriter::ImplGetShapeByIndex( sal
 //        }
 
         // assert shear (not supported yet)
-        if(!basegfx::fTools::equalZero(aObjTrans.getShearX()))
+        if(!basegfx::fTools::equalZero(maObjTrans.getShearX()))
         {
             OSL_ENSURE(false, "PPt export: shear is not supported (!)");
         }
@@ -1754,39 +1770,39 @@ void PPTWriter::ImplHandleRotation( Esch
 {
     if(!basegfx::fTools::equalZero(mfObjectRotation))
     {
-        sal_Int32 nAngle(basegfx::fround(basegfx::snapToZeroRange(-mfObjectRotation / F_PI18000, 36000.0)));
-        
-        nAngle = ( 36000 - ( nAngle % 36000 ) );
-
-        double  fCos = cos( (double)nAngle * F_PI18000 );
-        double  fSin = sin( (double)nAngle * F_PI18000 );
+        // MS shape format rotates around the object center, so adapt adapt ObjectRange
+        // to be centered at the center of the original shape to do this
+        const basegfx::B2DPoint aCurrentCenter(maObjTrans.getB2DHomMatrix() * basegfx::B2DPoint(0.5, 0.5));
+        const basegfx::B2DPoint aObjectRangeCenter(maObjectRange.getCenter());
 
-        const double fWidthHalf(maObjectRange.getWidth() * 0.5);
-        const double fHeightHalf(maObjectRange.getHeight() * 0.5);
+        if(!aCurrentCenter.equal(aObjectRangeCenter))
+        {
+            const basegfx::B2DHomMatrix aAdaptToCenterRotation(
+                basegfx::tools::createTranslateB2DHomMatrix(
+                    aCurrentCenter - aObjectRangeCenter));
 
-        double  fXDiff = fCos * fWidthHalf + fSin * (-fHeightHalf);
-        double  fYDiff = - ( fSin * fWidthHalf - fCos * ( -fHeightHalf ) );
+            maObjectRange.transform(aAdaptToCenterRotation);
+        }
 
-        maObjectRange.transform(
-            basegfx::tools::createTranslateB2DHomMatrix(
-                -(fWidthHalf - fXDiff),
-                -(fHeightHalf + fYDiff)));
+        // do not use negative mfObjectRotation here, PPT uses the correct orientation, too
+        sal_Int32 nAngle(basegfx::fround(basegfx::snapToZeroRange(mfObjectRotation / F_PI18000, 36000.0)));
 
+        // adapt angle to MS format
         nAngle *= 655;
         nAngle += 0x8000;
-        nAngle &=~0xffff;                                  // nAngle auf volle Gradzahl runden
-        rPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
+        nAngle &=~0xffff; // round to full degrees
+        rPropOpt.AddOpt(ESCHER_Prop_Rotation, nAngle);
 
-        if ( ( nAngle >= ( 45 << 16 ) && nAngle < ( 135 << 16 ) ) ||
-                ( nAngle >= ( 225 << 16 ) && nAngle < ( 315 << 16 ) ) )
+        if((nAngle >= (45 << 16) && nAngle < (135 << 16)) || (nAngle >= (225 << 16) && nAngle < (315 << 16)))
         {
-            // In diesen beiden Bereichen steht in PPT gemeinerweise die
-            // BoundingBox bereits senkrecht. Daher muss diese VOR
-            // DER ROTATION flachgelegt werden.
-            const basegfx::B2DPoint aPoint(maObjectRange.getMinX() + fWidthHalf - fHeightHalf, maObjectRange.getMinY() + fHeightHalf - fWidthHalf);
-            const basegfx::B2DVector aScale(maObjectRange.getHeight(), maObjectRange.getWidth());
+            // in this region of rotation the ObjectRange is already rotated,
+            // so do this here, too
+            const basegfx::B2DHomMatrix aMirrorDiagonal(
+                basegfx::tools::createRotateAroundPoint(
+                    maObjectRange.getCenter(),
+                    F_PI2));
 
-            maObjectRange = basegfx::B2DRange(aPoint, aPoint + aScale);
+            maObjectRange.transform(aMirrorDiagonal);
         }
     }
 }
@@ -4503,7 +4519,7 @@ void PPTWriter::ImplWritePage( const PHL
 				}
 				else
 				{
-	                ImplCreateShape( eShapeType, /*nMirrorFlags | */0xa00, aSolverContainer );
+	                ImplCreateShape( eShapeType, /*nMirrorFlags | */0xa00, aSolverContainer ); // Flags: Connector | HasSpt
 					aPropOpt.CreateCustomShapeProperties( eShapeType, mXShape );
 					aPropOpt.CreateFillProperties( mXPropSet, true, mXShape);
 					if ( ImplGetText() )

Modified: incubator/ooo/branches/alg/aw080/main/svx/source/svdraw/svdlegacy.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/aw080/main/svx/source/svdraw/svdlegacy.cxx?rev=1412988&r1=1412987&r2=1412988&view=diff
==============================================================================
--- incubator/ooo/branches/alg/aw080/main/svx/source/svdraw/svdlegacy.cxx (original)
+++ incubator/ooo/branches/alg/aw080/main/svx/source/svdraw/svdlegacy.cxx Fri Nov 23 17:14:30 2012
@@ -290,7 +290,7 @@ namespace sdr
 			if(rObject.isRotated())
 			{
 				const double fRotate(rObject.getSdrObjectRotate());
-                const double fSnapped(basegfx::snapToNearestMultiple(-fRotate / F_PI18000, 360000.0));
+                const double fSnapped(basegfx::snapToZeroRange(-fRotate / F_PI18000, 36000.0));
 
                 return basegfx::fround(fSnapped);
 			}

Modified: incubator/ooo/branches/alg/aw080/main/vcl/source/gdi/outmap.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/branches/alg/aw080/main/vcl/source/gdi/outmap.cxx?rev=1412988&r1=1412987&r2=1412988&view=diff
==============================================================================
--- incubator/ooo/branches/alg/aw080/main/vcl/source/gdi/outmap.cxx (original)
+++ incubator/ooo/branches/alg/aw080/main/vcl/source/gdi/outmap.cxx Fri Nov 23 17:14:30 2012
@@ -2508,9 +2508,11 @@ basegfx::B2DHomMatrix OutputDevice::GetT
 
 	if(rMapModeSource != rMapModeDest)
 	{
-		aRetval = GetViewTransformation(rMapModeSource);
+        // GetViewTransformation converts from unit to pixel, thus it's [inv(rMapModeDest) * rMapModeSource]
+        // read right to left
+		aRetval = GetViewTransformation(rMapModeDest);
 		aRetval.invert();
-		aRetval = GetViewTransformation(rMapModeDest) * aRetval;
+		aRetval = aRetval * GetViewTransformation(rMapModeSource);
 	}
 
 	return aRetval;