blob: 884cd66cb755956a3cdc74f10493e238fc6eb238 [file] [log] [blame]
/**************************************************************
*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*************************************************************/
// MARKER(update_precomp.py): autogen include statement, do not remove
#include "precompiled_filter.hxx"
#include "eschesdo.hxx"
#include <svx/svdobj.hxx>
#include <svx/unoapi.hxx>
#include <svx/svdoashp.hxx>
#include <svx/unoshape.hxx>
#include <vcl/outdev.hxx>
#include <tools/poly.hxx>
#include <vcl/bitmapex.hxx>
#include <vcl/graph.hxx>
#include <tools/debug.hxx>
#include <svx/fmdpage.hxx>
#include <toolkit/unohlp.hxx>
#include <com/sun/star/style/VerticalAlignment.hpp>
#include <com/sun/star/awt/Gradient.hpp>
#include <com/sun/star/drawing/PointSequence.hpp>
#include <com/sun/star/drawing/PointSequenceSequence.hpp>
#include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
#include <com/sun/star/drawing/FlagSequence.hpp>
#include <com/sun/star/drawing/TextAdjust.hpp>
#include <com/sun/star/drawing/LineDash.hpp>
#include <com/sun/star/text/XText.hpp>
#include <com/sun/star/drawing/CircleKind.hpp>
#include <com/sun/star/drawing/FillStyle.hpp>
#include <com/sun/star/task/XStatusIndicator.hpp>
#include <comphelper/extract.hxx>
#include <svtools/fltcall.hxx>
#include <vcl/cvtgrf.hxx>
#include <com/sun/star/drawing/HomogenMatrix3.hpp>
#include <basegfx/matrix/b2dhommatrix.hxx>
#include <basegfx/polygon/b2dpolygontools.hxx>
#include <basegfx/polygon/b2dpolygon.hxx>
using ::rtl::OUString;
using namespace ::com::sun::star;
using namespace ::com::sun::star::beans;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::uno;
using namespace ::com::sun::star::drawing;
using namespace ::com::sun::star::text;
using namespace ::com::sun::star::task;
using namespace ::com::sun::star::style;
#define EES_MAP_FRACTION 1440 // 1440 dpi
// ===================================================================
ImplEESdrWriter::ImplEESdrWriter( EscherEx& rEx )
:
mpEscherEx ( &rEx ),
maMapModeSrc ( MAP_100TH_MM ),
// PowerPoint: 576 dpi, WinWord: 1440 dpi, Excel: 1440 dpi
maMapModeDest( MAP_INCH, Point(), Fraction( 1, EES_MAP_FRACTION ), Fraction( 1, EES_MAP_FRACTION ) ),
// mXStatusIndicator ( rXStatInd ),
mpPicStrm ( NULL ),
mpHostAppData ( NULL ),
mnPagesWritten ( 0 ),
mnShapeMasterTitle ( 0 ),
mnShapeMasterBody ( 0 ),
mbStatusIndicator ( sal_False ),
mbStatus ( sal_False )
{
}
// -------------------------------------------------------------------
Point ImplEESdrWriter::ImplMapPoint( const Point& rPoint )
{
return OutputDevice::LogicToLogic( rPoint, maMapModeSrc, maMapModeDest );
}
// -------------------------------------------------------------------
Size ImplEESdrWriter::ImplMapSize( const Size& rSize )
{
Size aRetSize( OutputDevice::LogicToLogic( rSize, maMapModeSrc, maMapModeDest ) );
if ( !aRetSize.Width() )
aRetSize.Width()++;
if ( !aRetSize.Height() )
aRetSize.Height()++;
return aRetSize;
}
// -------------------------------------------------------------------
void ImplEESdrWriter::ImplFlipBoundingBox( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt )
{
sal_Int32 nAngle = rObj.GetAngle();
Rectangle aRect( rObj.GetRect() );
if ( nAngle < 0 )
nAngle = ( 36000 + nAngle ) % 36000;
else
nAngle = ( 36000 - ( nAngle % 36000 ) );
double fVal = (double)nAngle * F_PI18000;
double fCos = cos( fVal );
double fSin = sin( fVal );
double nWidthHalf = (double) aRect.GetWidth() / 2;
double nHeightHalf = (double) aRect.GetHeight() / 2;
double nXDiff = fCos * nWidthHalf + fSin * (-nHeightHalf);
double nYDiff = - ( fSin * nWidthHalf - fCos * ( -nHeightHalf ) );
aRect.Move( (sal_Int32)( -( nWidthHalf - nXDiff ) ), (sal_Int32)( - ( nHeightHalf + nYDiff ) ) );
nAngle *= 655;
nAngle += 0x8000;
nAngle &=~0xffff; // nAngle auf volle Gradzahl runden
rPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
rObj.SetAngle( nAngle );
rObj.SetRect( aRect );
}
// -----------------------------------------------------------------------
#define ADD_SHAPE( nType, nFlags ) \
{ \
nShapeType = nType; \
nShapeID = mpEscherEx->GenerateShapeId(); \
rObj.SetShapeId( nShapeID ); \
mpEscherEx->AddShape( (sal_uInt32)nType, (sal_uInt32)nFlags, nShapeID ); \
rSolverContainer.AddShape( rObj.GetShapeRef(), nShapeID ); \
}
#define SHAPE_TEXT( bFill ) \
{ \
mpEscherEx->OpenContainer( ESCHER_SpContainer ); \
ADD_SHAPE( ESCHER_ShpInst_TextBox, 0xa00 ); \
if ( bFill ) \
aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True ); \
if( rObj.ImplGetText() ) \
aPropOpt.CreateTextProperties( rObj.mXPropSet, \
mpEscherEx->QueryTextID( rObj.GetShapeRef(), \
rObj.GetShapeId() ) ); \
}
//Map from twips to export units, generally twips as well, only excel and word
//export is happening here, so native units are export units, leave as
//placeholder if required in future
void ImplEESdrWriter::MapRect(ImplEESdrObject& /* rObj */ )
{
}
sal_uInt32 ImplEESdrWriter::ImplWriteShape( ImplEESdrObject& rObj,
EscherSolverContainer& rSolverContainer,
ImplEESdrPageType ePageType )
{
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;
sal_uInt32 nGrpShapeID = 0;
do {
mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : 0 );
if ( mpHostAppData && mpHostAppData->DontWriteShape() )
break;
// #i51348# get shape name
String aShapeName;
if( const SdrObject* pSdrObj = rObj.GetSdrObject() )
if( pSdrObj->GetName().Len() > 0 )
aShapeName = pSdrObj->GetName();
Point aTextRefPoint;
if( rObj.GetType().EqualsAscii( "drawing.Group" ))
{
Reference< XIndexAccess > xXIndexAccess( rObj.GetShapeRef(), UNO_QUERY );
if( xXIndexAccess.is() && 0 != xXIndexAccess->getCount() )
{
nShapeID = mpEscherEx->EnterGroup( aShapeName, &rObj.GetRect() );
nShapeType = ESCHER_ShpInst_Min;
for( sal_uInt32 n = 0, nCnt = xXIndexAccess->getCount();
n < nCnt; ++n )
{
ImplEESdrObject aObj( *this, *(Reference< XShape >*)
xXIndexAccess->getByIndex( n ).getValue() );
if( aObj.IsValid() )
ImplWriteShape( aObj, rSolverContainer, ePageType );
}
mpEscherEx->LeaveGroup();
}
break;
}
rObj.SetAngle( rObj.ImplGetInt32PropertyValue( ::rtl::OUString::createFromAscii("RotateAngle") ));
if( ( rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("IsFontwork") ) &&
::cppu::any2bool( rObj.GetUsrAny() ) ) ||
rObj.GetType().EqualsAscii( "drawing.Measure" ) || rObj.GetType().EqualsAscii( "drawing.Caption" ) )
{
/*
if( rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("BoundRect") ) )
{
::com::sun::star::awt::Rectangle aRect( *(::com::sun::star::awt::Rectangle*)rObj.GetUsrAny().getValue() );
rObj.SetRect( ImplMapPoint( Point( aRect.X, aRect.Y ) ),
ImplMapSize( Size( aRect.Width, aRect.Height ) ) );
}
*/
rObj.SetType( String( RTL_CONSTASCII_STRINGPARAM(
"drawing.dontknow" ),
RTL_TEXTENCODING_MS_1252 ));
}
const ::com::sun::star::awt::Size aSize100thmm( rObj.GetShapeRef()->getSize() );
const ::com::sun::star::awt::Point aPoint100thmm( rObj.GetShapeRef()->getPosition() );
Rectangle aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
if ( !mpPicStrm )
mpPicStrm = mpEscherEx->QueryPictureStream();
EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm );
// #i51348# shape name
if( aShapeName.Len() > 0 )
aPropOpt.AddOpt( ESCHER_Prop_wzName, aShapeName );
if ( rObj.GetType().EqualsAscii( "drawing.Custom" ) )
{
mpEscherEx->OpenContainer( ESCHER_SpContainer );
sal_uInt32 nMirrorFlags;
rtl::OUString sCustomShapeType;
MSO_SPT eShapeType = aPropOpt.GetCustomShapeType( rObj.GetShapeRef(), nMirrorFlags, sCustomShapeType );
if ( sCustomShapeType.equalsAscii( "col-502ad400" ) || sCustomShapeType.equalsAscii( "col-60da8460" ) )
{
ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ), sal_False ) )
{
aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 ); // no fill
aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 ); // no linestyle
SdrObject* pObj = GetSdrObjectFromXShape( rObj.GetShapeRef() );
if ( pObj )
{
Rectangle aBound = pObj->GetCurrentBoundRect();
Point aPosition( ImplMapPoint( aBound.TopLeft() ) );
Size aSize( ImplMapSize( aBound.GetSize() ) );
rObj.SetRect( Rectangle( aPosition, aSize ) );
rObj.SetAngle( 0 );
bDontWriteText = sal_True;
}
}
}
else
{
ADD_SHAPE(
sal::static_int_cast< sal_uInt16 >(eShapeType),
nMirrorFlags | 0xa00 );
aPropOpt.CreateCustomShapeProperties( eShapeType, rObj.GetShapeRef() );
aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
if ( rObj.ImplGetText() )
{
if ( !aPropOpt.IsFontWork() )
aPropOpt.CreateTextProperties( rObj.mXPropSet, mpEscherEx->QueryTextID(
rObj.GetShapeRef(), rObj.GetShapeId() ), sal_True, sal_False );
}
}
}
else if ( rObj.GetType().EqualsAscii( "drawing.Rectangle" ))
{
mpEscherEx->OpenContainer( ESCHER_SpContainer );
sal_Int32 nRadius = (sal_Int32)rObj.ImplGetInt32PropertyValue(
::rtl::OUString::createFromAscii("CornerRadius"));
if( nRadius )
{
nRadius = ImplMapSize( Size( nRadius, 0 )).Width();
ADD_SHAPE( ESCHER_ShpInst_RoundRectangle, 0xa00 ); // Flags: Connector | HasSpt
sal_Int32 nLenght = rObj.GetRect().GetWidth();
if ( nLenght > rObj.GetRect().GetHeight() )
nLenght = rObj.GetRect().GetHeight();
nLenght >>= 1;
if ( nRadius >= nLenght )
nRadius = 0x2a30; // 0x2a30 ist PPTs maximum radius
else
nRadius = ( 0x2a30 * nRadius ) / nLenght;
aPropOpt.AddOpt( ESCHER_Prop_adjustValue, nRadius );
}
else
{
ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 ); // Flags: Connector | HasSpt
}
aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
if( rObj.ImplGetText() )
aPropOpt.CreateTextProperties( rObj.mXPropSet,
mpEscherEx->QueryTextID( rObj.GetShapeRef(),
rObj.GetShapeId() ), sal_False, sal_False );
}
else if ( rObj.GetType().EqualsAscii( "drawing.Ellipse" ))
{
CircleKind eCircleKind = CircleKind_FULL;
PolyStyle ePolyKind = PolyStyle();
if ( rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("CircleKind") ) )
{
eCircleKind = *( (CircleKind*)rObj.GetUsrAny().getValue() );
switch ( eCircleKind )
{
case CircleKind_SECTION :
{
ePolyKind = POLY_PIE;
}
break;
case CircleKind_ARC :
{
ePolyKind = POLY_ARC;
}
break;
case CircleKind_CUT :
{
ePolyKind = POLY_CHORD;
}
break;
default:
eCircleKind = CircleKind_FULL;
}
}
if ( eCircleKind == CircleKind_FULL )
{
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ADD_SHAPE( ESCHER_ShpInst_Ellipse, 0xa00 ); // Flags: Connector | HasSpt
aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );;
}
else
{
sal_Int32 nStartAngle, nEndAngle;
if ( !rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("CircleStartAngle") ) )
break;
nStartAngle = *( (sal_Int32*)rObj.GetUsrAny().getValue() );
if( !rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("CircleEndAngle") ) )
break;
nEndAngle = *( (sal_Int32*)rObj.GetUsrAny().getValue() );
Point aStart, aEnd, aCenter;
aStart.X() = (sal_Int32)( ( cos( (double)( nStartAngle *
F_PI18000 ) ) * 100.0 ) );
aStart.Y() = - (sal_Int32)( ( sin( (double)( nStartAngle *
F_PI18000 ) ) * 100.0 ) );
aEnd.X() = (sal_Int32)( ( cos( (double)( nEndAngle *
F_PI18000 ) ) * 100.0 ) );
aEnd.Y() = - (sal_Int32)( ( sin( (double)( nEndAngle *
F_PI18000 ) ) * 100.0 ) );
const Rectangle& rRect = aRect100thmm;
aCenter.X() = rRect.Left() + ( rRect.GetWidth() / 2 );
aCenter.Y() = rRect.Top() + ( rRect.GetHeight() / 2 );
aStart.X() += aCenter.X();
aStart.Y() += aCenter.Y();
aEnd.X() += aCenter.X();
aEnd.Y() += aCenter.Y();
Polygon aPolygon( rRect, aStart, aEnd, ePolyKind );
if( rObj.GetAngle() )
{
aPolygon.Rotate( rRect.TopLeft(), (sal_uInt16)( rObj.GetAngle() / 10 ) );
rObj.SetAngle( 0 );
}
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt
::com::sun::star::awt::Rectangle aNewRect;
switch ( ePolyKind )
{
case POLY_PIE :
case POLY_CHORD :
{
aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_False, aNewRect, &aPolygon );
aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
}
break;
case POLY_ARC :
{
aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_False, aNewRect, &aPolygon );
aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
}
break;
}
rObj.SetRect( Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ),
ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) );
}
if ( rObj.ImplGetText() )
aPropOpt.CreateTextProperties( rObj.mXPropSet,
mpEscherEx->QueryTextID( rObj.GetShapeRef(),
rObj.GetShapeId() ), sal_False, sal_False );
}
else if ( rObj.GetType().EqualsAscii( "drawing.Control" ))
{
break;
}
else if ( rObj.GetType().EqualsAscii( "drawing.Connector" ))
{
sal_uInt16 nSpType, nSpFlags;
::com::sun::star::awt::Rectangle aNewRect;
if ( aPropOpt.CreateConnectorProperties( rObj.GetShapeRef(),
rSolverContainer, aNewRect, nSpType, nSpFlags ) == sal_False )
break;
rObj.SetRect( Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ),
ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) );
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ADD_SHAPE( nSpType, nSpFlags );
}
else if ( rObj.GetType().EqualsAscii( "drawing.Measure" ))
{
/*
if ( ImplGetPropertyValue( L"MeasureKind" ) )
{
mpEscherEx->EnterGroup( &maRect );
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ImplWriteAny( ANY_FLAGS_LINE, sal_False );
sal_uInt32 nFlags = 0xa00; // Flags: Connector | HasSpt
if ( maRect.Top() > maRect.Bottom() )
nFlags |= 0x80; // Flags: VertMirror
if ( maRect.Left() > maRect.Right() )
nFlags |= 0x40; // Flags: HorzMirror
ADD_SHAPE( ESCHER_ShpInst_Line, nFlags );
aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
mpEscherEx->EndCount( ESCHER_OPT, 3 );
maRect.Justify();
mpEscherEx->AddClientAnchor( maRect );
mpEscherEx->CloseContainer(); // ESCHER_SpContainer
if ( ImplGetPropertyValue( L"MeasureTextHorizontalPosition" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureTextVerticalPosition" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureLineDistance" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureHelpLineOverhang" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureHelpLineDistance" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureHelpLine1Length" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureHelpLine2Length" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureBelowReferenceEdge" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureTextRotate90" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureTextUpsideDown" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureOverhang" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureUnit" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureScale" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureShowUnit" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureFormatString" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureTextAutoAngle" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureTextAutoAngleView" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureTextIsFixedAngle" ) )
{
}
if ( ImplGetPropertyValue( L"MeasureTextFixedAngle" ) )
{
}
mpEscherEx->LeaveGroup();
}
*/
break;
}
else if ( rObj.GetType().EqualsAscii( "drawing.Line" ))
{
::com::sun::star::awt::Rectangle aNewRect;
aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_LINE, sal_False, aNewRect, NULL );
MapRect(rObj);
//i27942: Poly/Lines/Bezier do not support text.
mpEscherEx->OpenContainer( ESCHER_SpContainer );
sal_uInt32 nFlags = 0xa00; // Flags: Connector | HasSpt
if( aNewRect.Height < 0 )
nFlags |= 0x80; // Flags: VertMirror
if( aNewRect.Width < 0 )
nFlags |= 0x40; // Flags: HorzMirror
ADD_SHAPE( ESCHER_ShpInst_Line, nFlags );
aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
rObj.SetAngle( 0 );
}
else if ( rObj.GetType().EqualsAscii( "drawing.PolyPolygon" ))
{
if( rObj.ImplHasText() )
{
nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() );
bAdditionalText = sal_True;
}
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt
::com::sun::star::awt::Rectangle aNewRect;
aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_False, aNewRect, NULL );
MapRect(rObj);
aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
rObj.SetAngle( 0 );
}
else if ( rObj.GetType().EqualsAscii( "drawing.PolyLine" ))
{
//i27942: Poly/Lines/Bezier do not support text.
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt
::com::sun::star::awt::Rectangle aNewRect;
aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_False, aNewRect, NULL );
MapRect(rObj);
aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
rObj.SetAngle( 0 );
}
else if ( rObj.GetType().EqualsAscii( "drawing.OpenBezier" ) )
{
//i27942: Poly/Lines/Bezier do not support text.
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt
::com::sun::star::awt::Rectangle aNewRect;
aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_True, aNewRect, NULL );
MapRect(rObj);
aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
rObj.SetAngle( 0 );
}
else if ( rObj.GetType().EqualsAscii( "drawing.ClosedBezier" ) )
{
if ( rObj.ImplHasText() )
{
nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() );
bAdditionalText = sal_True;
}
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt
::com::sun::star::awt::Rectangle aNewRect;
aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_True, aNewRect, NULL );
MapRect(rObj);
aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
rObj.SetAngle( 0 );
}
else if ( rObj.GetType().EqualsAscii( "drawing.GraphicObject" ))
{
mpEscherEx->OpenContainer( ESCHER_SpContainer );
// ein GraphicObject kann auch ein ClickMe Element sein
if( rObj.IsEmptyPresObj() && ( ePageType == NORMAL ) )
{
ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0x220 ); // Flags: HaveAnchor | HaveMaster
sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(),
rObj.GetShapeId() );
aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId );
aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
}
else
{
if( rObj.ImplGetText() )
{
/* SJ #i34951#: because M. documents are not allowing GraphicObjects containing text, we
have to create a simpe Rectangle with fill bitmap instead (while not allowing BitmapMode_Repeat).
*/
ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 ); // Flags: Connector | HasSpt
if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), sal_True, sal_True, sal_False ) )
{
aPropOpt.AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
aPropOpt.AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x8000000 );
aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
if ( rObj.ImplGetText() )
aPropOpt.CreateTextProperties( rObj.mXPropSet,
mpEscherEx->QueryTextID( rObj.GetShapeRef(),
rObj.GetShapeId() ), sal_False, sal_False );
}
}
else
{
ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), sal_False, sal_True ) )
aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
}
}
}
else if ( rObj.GetType().EqualsAscii( "drawing.Text" ))
{
SHAPE_TEXT( sal_True );
}
else if ( rObj.GetType().EqualsAscii( "drawing.Page" ))
{
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 );
aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x40004 );
aPropOpt.AddOpt( ESCHER_Prop_fFillOK, 0x100001 );
aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x110011 );
aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90008 );
aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x10001 );
}
else if ( rObj.GetType().EqualsAscii( "drawing.Frame" ))
{
break;
}
else if ( rObj.GetType().EqualsAscii( "drawing.OLE2" ))
{
mpEscherEx->OpenContainer( ESCHER_SpContainer );
if( rObj.IsEmptyPresObj() && ( ePageType == NORMAL ) )
{
ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0x220 ); // Flags: HaveAnchor | HaveMaster
sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(),
rObj.GetShapeId() );
aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId );
aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
}
else
{
//2do: could be made an option in HostAppData whether OLE object should be written or not
sal_Bool bAppOLE = sal_True;
ADD_SHAPE( ESCHER_ShpInst_PictureFrame,
0xa00 | (bAppOLE ? SHAPEFLAG_OLESHAPE : 0) );
if ( aPropOpt.CreateOLEGraphicProperties( rObj.GetShapeRef() ) )
{
if ( bAppOLE )
{ // snooped from Xcl hex dump, nobody knows the trouble I have seen
aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 );
aPropOpt.AddOpt( ESCHER_Prop_pictureId, 0x00000001 );
aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x08000041 );
aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x08000041 );
aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 );
aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x08000040 );
aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash,0x00080008 );
// aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured,0x00020000 );
aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080000 );
}
aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
}
}
}
else if( '3' == rObj.GetType().GetChar(8 ) &&
'D' == rObj.GetType().GetChar( 9 ) ) // drawing.3D
{
// SceneObject, CubeObject, SphereObject, LatheObject, ExtrudeObject, PolygonObject
if ( !rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("Bitmap") ) )
break;
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Bitmap" ) ), sal_False ) )
aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
}
else if ( rObj.GetType().EqualsAscii( "drawing.dontknow" ))
{
rObj.SetAngle( 0 );
mpEscherEx->OpenContainer( ESCHER_SpContainer );
ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ), sal_False ) )
aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
}
else
{
break;
}
aPropOpt.CreateShadowProperties( rObj.mXPropSet );
if( USHRT_MAX != mpEscherEx->GetHellLayerId() &&
rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("LayerID") ) &&
(*((sal_uInt16*)rObj.GetUsrAny().getValue()) ) == mpEscherEx->GetHellLayerId() )
{
aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
}
{
Rectangle aRect( rObj.GetRect() );
aRect.Justify();
rObj.SetRect( aRect );
}
if( rObj.GetAngle() )
ImplFlipBoundingBox( rObj, aPropOpt );
aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
mpEscherEx->Commit( aPropOpt, rObj.GetRect() );
if( mpEscherEx->GetGroupLevel() > 1 )
mpEscherEx->AddChildAnchor( rObj.GetRect() );
if ( mpHostAppData )
{ //! with AdditionalText the App has to control whether these are written or not
mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() );
mpHostAppData->WriteClientData( *mpEscherEx );
if ( !bDontWriteText )
mpHostAppData->WriteClientTextbox( *mpEscherEx );
}
mpEscherEx->CloseContainer(); // ESCHER_SpContainer
if( bAdditionalText )
{
mpEscherEx->EndShape( nShapeType, nShapeID );
ImplWriteAdditionalText( rObj, aTextRefPoint );
}
} while ( 0 );
if ( bAdditionalText )
mpEscherEx->EndShape( ESCHER_ShpInst_Min, nGrpShapeID );
else
mpEscherEx->EndShape( nShapeType, nShapeID );
return nShapeID;
}
void ImplEESdrWriter::ImplWriteAdditionalText( ImplEESdrObject& rObj,
const Point& rTextRefPoint )
{
sal_uInt32 nShapeID = 0;
sal_uInt16 nShapeType = 0;
do
{
mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : 0 );
if ( mpHostAppData && mpHostAppData->DontWriteShape() )
break;
const ::com::sun::star::awt::Size aSize100thmm( rObj.GetShapeRef()->getSize() );
const ::com::sun::star::awt::Point aPoint100thmm( rObj.GetShapeRef()->getPosition() );
Rectangle aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
if ( !mpPicStrm )
mpPicStrm = mpEscherEx->QueryPictureStream();
EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm );
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
double fDist = hypot( rObj.GetRect().GetWidth(),
rObj.GetRect().GetHeight() );
rObj.SetRect( Rectangle( rTextRefPoint,
Point( (sal_Int32)( rTextRefPoint.X() + fDist ), rTextRefPoint.Y() - 1 ) ) );
mpEscherEx->OpenContainer( ESCHER_SpContainer );
mpEscherEx->AddShape( ESCHER_ShpInst_TextBox, 0xa00 );
if ( rObj.ImplGetText() )
aPropOpt.CreateTextProperties( rObj.mXPropSet,
mpEscherEx->QueryTextID( rObj.GetShapeRef(),
rObj.GetShapeId() ) );
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 )
nAngle = ( 36000 + nAngle ) % 36000;
if ( nAngle )
ImplFlipBoundingBox( rObj, aPropOpt );
}
else
{
mpEscherEx->OpenContainer( ESCHER_SpContainer );
nShapeID = mpEscherEx->GenerateShapeId();
mpEscherEx->AddShape( nShapeType = ESCHER_ShpInst_TextBox, 0xa00, nShapeID );
if ( rObj.ImplGetText() )
aPropOpt.CreateTextProperties( rObj.mXPropSet,
mpEscherEx->QueryTextID( rObj.GetShapeRef(),
rObj.GetShapeId() ) );
aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
if( nAngle < 0 )
nAngle = ( 36000 + nAngle ) % 36000;
else
nAngle = ( 36000 - ( nAngle % 36000 ) );
nAngle *= 655;
nAngle += 0x8000;
nAngle &=~0xffff; // nAngle auf volle Gradzahl runden
aPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
mpEscherEx->SetGroupSnapRect( mpEscherEx->GetGroupLevel(),
rObj.GetRect() );
mpEscherEx->SetGroupLogicRect( mpEscherEx->GetGroupLevel(),
rObj.GetRect() );
}
rObj.SetAngle( nAngle );
aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
mpEscherEx->Commit( aPropOpt, rObj.GetRect() );
// write the childanchor
mpEscherEx->AddChildAnchor( rObj.GetRect() );
#if defined EES_WRITE_EPP
// ClientAnchor
mpEscherEx->AddClientAnchor( maRect );
// ClientTextbox
mpEscherEx->OpenContainer( ESCHER_ClientTextbox );
mpEscherEx->AddAtom( 4, EPP_TextHeaderAtom );
*mpStrm << (sal_uInt32)EPP_TEXTTYPE_Other; // Text in a Shape
ImplWriteTextStyleAtom();
mpEscherEx->CloseContainer(); // ESCHER_ClientTextBox
#else // !EES_WRITE_EPP
if ( mpHostAppData )
{ //! the App has to control whether these are written or not
mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() );
mpHostAppData->WriteClientData( *mpEscherEx );
mpHostAppData->WriteClientTextbox( *mpEscherEx );
}
#endif // EES_WRITE_EPP
mpEscherEx->CloseContainer(); // ESCHER_SpContainer
} while ( 0 );
mpEscherEx->LeaveGroup();
mpEscherEx->EndShape( nShapeType, nShapeID );
}
// -------------------------------------------------------------------
sal_uInt32 ImplEESdrWriter::ImplEnterAdditionalTextGroup( const Reference< XShape >& rShape,
const Rectangle* pBoundRect )
{
mpHostAppData = mpEscherEx->EnterAdditionalTextGroup();
sal_uInt32 nGrpId = mpEscherEx->EnterGroup( pBoundRect );
mpHostAppData = mpEscherEx->StartShape( rShape, pBoundRect );
return nGrpId;
}
// -------------------------------------------------------------------
sal_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
return sal_True;
}
// -------------------------------------------------------------------
void ImplEESdrWriter::ImplWritePage(
EscherSolverContainer& rSolverContainer,
ImplEESdrPageType ePageType, sal_Bool /* bBackGround */ )
{
ImplInitPageValues();
sal_uInt32 nLastPer = 0, nShapes = mXShapes->getCount();
for( sal_uInt32 n = 0; n < nShapes; ++n )
{
sal_uInt32 nPer = ( 5 * n ) / nShapes;
if( nPer != nLastPer )
{
nLastPer = nPer;
sal_uInt32 nValue = mnPagesWritten * 5 + nPer;
if( nValue > mnStatMaxValue )
nValue = mnStatMaxValue;
if( mbStatusIndicator )
mXStatusIndicator->setValue( nValue );
}
ImplEESdrObject aObj( *this, *(Reference< XShape >*)
mXShapes->getByIndex( n ).getValue() );
if( aObj.IsValid() )
{
ImplWriteShape( aObj, rSolverContainer, ePageType );
}
}
mnPagesWritten++;
}
// ===================================================================
ImplEscherExSdr::ImplEscherExSdr( EscherEx& rEx )
:
ImplEESdrWriter( rEx ),
mpSdrPage( NULL ),
mpSolverContainer( NULL )
{
}
// -------------------------------------------------------------------
ImplEscherExSdr::~ImplEscherExSdr()
{
DBG_ASSERT( !mpSolverContainer, "ImplEscherExSdr::~ImplEscherExSdr: unwritten SolverContainer" );
delete mpSolverContainer;
}
// -------------------------------------------------------------------
bool ImplEscherExSdr::ImplInitPage( const SdrPage& rPage )
{
do
{
SvxDrawPage* pSvxDrawPage;
if ( mpSdrPage != &rPage || !mXDrawPage.is() )
{
// eventually write SolverContainer of current page, deletes the Solver
ImplFlushSolverContainer();
mpSdrPage = NULL;
// why not declare a const parameter if the object will not be modified?
// mXDrawPage = pSvxDrawPage = new SvxDrawPage( (SdrPage*) &rPage );
mXDrawPage = pSvxDrawPage = new SvxFmDrawPage( (SdrPage*) &rPage );
mXShapes = Reference< XShapes >::query( mXDrawPage );
if ( !mXShapes.is() )
break;
if ( !ImplInitPageValues() ) // ImplEESdrWriter
break;
mpSdrPage = &rPage;
mpSolverContainer = new EscherSolverContainer;
}
else
pSvxDrawPage = SvxDrawPage::getImplementation(mXDrawPage);
return pSvxDrawPage != 0;
} while ( 0 );
return false;
}
// -------------------------------------------------------------------
bool ImplEscherExSdr::ImplInitUnoShapes( const Reference< XShapes >& rxShapes )
{
// eventually write SolverContainer of current page, deletes the Solver
ImplFlushSolverContainer();
if( !rxShapes.is() )
return false;
mpSdrPage = 0;
mXDrawPage.clear();
mXShapes = rxShapes;
if( !ImplInitPageValues() ) // ImplEESdrWriter
return false;
mpSolverContainer = new EscherSolverContainer;
return true;
}
// -------------------------------------------------------------------
void ImplEscherExSdr::ImplExitPage()
{
// close all groups before the solver container is written
while( mpEscherEx->GetGroupLevel() )
mpEscherEx->LeaveGroup();
ImplFlushSolverContainer();
mpSdrPage = NULL; // reset page for next init
}
// -------------------------------------------------------------------
void ImplEscherExSdr::ImplFlushSolverContainer()
{
if ( mpSolverContainer )
{
mpSolverContainer->WriteSolver( mpEscherEx->GetStream() );
delete mpSolverContainer;
mpSolverContainer = NULL;
}
}
// -------------------------------------------------------------------
void ImplEscherExSdr::ImplWriteCurrentPage()
{
DBG_ASSERT( mpSolverContainer, "ImplEscherExSdr::ImplWriteCurrentPage: no SolverContainer" );
ImplWritePage( *mpSolverContainer, NORMAL );
ImplExitPage();
}
// -------------------------------------------------------------------
sal_uInt32 ImplEscherExSdr::ImplWriteTheShape( ImplEESdrObject& rObj )
{
DBG_ASSERT( mpSolverContainer, "ImplEscherExSdr::ImplWriteShape: no SolverContainer" );
return ImplWriteShape( rObj, *mpSolverContainer, NORMAL );
}
// ===================================================================
void EscherEx::AddSdrPage( const SdrPage& rPage )
{
if ( mpImplEscherExSdr->ImplInitPage( rPage ) )
mpImplEscherExSdr->ImplWriteCurrentPage();
}
// -------------------------------------------------------------------
void EscherEx::AddUnoShapes( const Reference< XShapes >& rxShapes )
{
if ( mpImplEscherExSdr->ImplInitUnoShapes( rxShapes ) )
mpImplEscherExSdr->ImplWriteCurrentPage();
}
// -------------------------------------------------------------------
sal_uInt32 EscherEx::AddSdrObject( const SdrObject& rObj )
{
ImplEESdrObject aObj( *mpImplEscherExSdr, rObj );
if( aObj.IsValid() )
return mpImplEscherExSdr->ImplWriteTheShape( aObj );
return 0;
}
// -------------------------------------------------------------------
void EscherEx::EndSdrObjectPage()
{
mpImplEscherExSdr->ImplExitPage();
}
// -------------------------------------------------------------------
EscherExHostAppData* EscherEx::StartShape( const Reference< XShape >& /* rShape */, const Rectangle* /*pChildAnchor*/ )
{
return NULL;
}
// -------------------------------------------------------------------
void EscherEx::EndShape( sal_uInt16 /* nShapeType */, sal_uInt32 /* nShapeID */ )
{
}
// -------------------------------------------------------------------
sal_uInt32 EscherEx::QueryTextID( const Reference< XShape >&, sal_uInt32 )
{
return 0;
}
// -------------------------------------------------------------------
// add an dummy rectangle shape into the escher stream
sal_uInt32 EscherEx::AddDummyShape()
{
OpenContainer( ESCHER_SpContainer );
sal_uInt32 nShapeID = GenerateShapeId();
AddShape( ESCHER_ShpInst_Rectangle, 0xa00, nShapeID );
//?? aSolverContainer.AddShape( mXShape, nShapeID );
CloseContainer();
return nShapeID;
}
// -------------------------------------------------------------------
// static
const SdrObject* EscherEx::GetSdrObject( const Reference< XShape >& rShape )
{
const SdrObject* pRet = 0;
const SvxShape* pSvxShape = SvxShape::getImplementation( rShape );
DBG_ASSERT( pSvxShape, "EscherEx::GetSdrObject: no SvxShape" );
if( pSvxShape )
{
pRet = pSvxShape->GetSdrObject();
DBG_ASSERT( pRet, "EscherEx::GetSdrObject: no SdrObj" );
}
return pRet;
}
// -------------------------------------------------------------------
ImplEESdrObject::ImplEESdrObject( ImplEscherExSdr& rEx,
const SdrObject& rObj ) :
mnShapeId( 0 ),
mnTextSize( 0 ),
mnAngle( 0 ),
mbValid( sal_False ),
mbPresObj( sal_False ),
mbEmptyPresObj( sal_False )
{
SdrPage* pPage = rObj.GetPage();
DBG_ASSERT( pPage, "ImplEESdrObject::ImplEESdrObject: no SdrPage" );
if( pPage && rEx.ImplInitPage( *pPage ) )
{
// why not declare a const parameter if the object will
// not be modified?
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 )
{
Init( rEx );
}
ImplEESdrObject::~ImplEESdrObject()
{
}
basegfx::B2DRange getUnrotatedGroupBoundRange(const Reference< XShape >& rxShape)
{
basegfx::B2DRange aRetval;
try
{
if(rxShape.is())
{
if(rxShape->getShapeType().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.GroupShape")))
{
// it's a group shape, iterate over children
const Reference< XIndexAccess > xXIndexAccess(rxShape, UNO_QUERY);
if(xXIndexAccess.is())
{
for(sal_uInt32 n(0), nCnt = xXIndexAccess->getCount(); n < nCnt; ++n)
{
const Reference< XShape > axShape(xXIndexAccess->getByIndex(n), UNO_QUERY);
if(axShape.is())
{
// we are calculating the bound for a group, correct rotation for sub-objects
// to get the unrotated bounds for the group
const basegfx::B2DRange aExtend(getUnrotatedGroupBoundRange(axShape));
aRetval.expand(aExtend);
}
}
}
}
else
{
// iT#s a xShape, get it's transformation
const Reference< XPropertySet > mXPropSet(rxShape, UNO_QUERY);
if(mXPropSet.is())
{
const Any aAny = mXPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")));
if(aAny.hasValue())
{
HomogenMatrix3 aMatrix;
if(aAny >>= aMatrix)
{
basegfx::B2DHomMatrix aHomogenMatrix;
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));
}
}
}
}
}
}
catch(::com::sun::star::uno::Exception&)
{
}
return aRetval;
}
void ImplEESdrObject::Init( ImplEESdrWriter& rEx )
{
mXPropSet = Reference< XPropertySet >::query( mXShape );
if( mXPropSet.is() )
{
static const sal_Char aPrefix[] = "com.sun.star.";
static const xub_StrLen nPrefix = sizeof(aPrefix)-1;
// detect name first to make below test (is group) work
mType = String( mXShape->getShapeType() );
mType.Erase( 0, nPrefix ); // strip "com.sun.star."
xub_StrLen nPos = mType.SearchAscii( "Shape" );
mType.Erase( nPos, 5 );
if(GetType().EqualsAscii("drawing.Group"))
{
// if it's a group, the unrotated range is needed for that group
const basegfx::B2DRange aUnroatedRange(getUnrotatedGroupBoundRange(mXShape));
const Point aNewP(basegfx::fround(aUnroatedRange.getMinX()), basegfx::fround(aUnroatedRange.getMinY()));
const Size aNewS(basegfx::fround(aUnroatedRange.getWidth()), basegfx::fround(aUnroatedRange.getHeight()));
SetRect(rEx.ImplMapPoint(aNewP), rEx.ImplMapSize(aNewS));
}
else
{
// if it's no group, use position and size directly, roated/sheared or not
const Point aOldP(mXShape->getPosition().X, mXShape->getPosition().Y);
const Size aOldS(mXShape->getSize().Width, mXShape->getSize().Height);
SetRect(rEx.ImplMapPoint(aOldP), rEx.ImplMapSize(aOldS));
}
static const OUString sPresStr(rtl::OUString::createFromAscii("IsPresentationObject"));
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;
}
}
//sal_Bool ImplEESdrObject::ImplGetPropertyValue( const OUString& rString )
sal_Bool ImplEESdrObject::ImplGetPropertyValue( const sal_Unicode* rString )
{
sal_Bool bRetValue = sal_False;
if( mbValid )
{
try
{
mAny = mXPropSet->getPropertyValue( rString );
if( mAny.hasValue() )
bRetValue = sal_True;
}
catch( ::com::sun::star::uno::Exception& )
{
bRetValue = sal_False;
}
}
return bRetValue;
}
#ifdef USED
sal_Bool ImplEESdrObject::ImplGetPropertyValue( const Reference< XPropertySet >& rXPropSet,
const OUString& rString )
{
sal_Bool bRetValue = sal_False;
if( mbValid )
{
try
{
mAny = rXPropSet->getPropertyValue( rString );
if( 0 != mAny.get() )
bRetValue = sal_True;
}
catch( ::com::sun::star::uno::Exception& )
{
bRetValue = sal_False;
}
}
return bRetValue;
}
#endif
void ImplEESdrObject::SetRect( const Point& rPos, const Size& rSz )
{
maRect = Rectangle( rPos, rSz );
}
const SdrObject* ImplEESdrObject::GetSdrObject() const
{
return EscherEx::GetSdrObject( mXShape );
}
// laedt und konvertiert text aus shape, ergebnis ist mnTextSize gespeichert
sal_uInt32 ImplEESdrObject::ImplGetText()
{
Reference< XText > xXText( mXShape, UNO_QUERY );
mnTextSize = 0;
if( xXText.is() )
mnTextSize = xXText->getString().getLength();
return mnTextSize;
}
sal_Bool ImplEESdrObject::ImplHasText() const
{
Reference< XText > xXText( mXShape, UNO_QUERY );
return xXText.is() && xXText->getString().getLength();
}