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;