bump product version to 4.1.6.2
[LibreOffice.git] / filter / source / msfilter / eschesdo.cxx
blobd0f3c2b7ff43cb7762536cd6ead8755922f1757f
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "eschesdo.hxx"
21 #include <svx/svdobj.hxx>
22 #include <svx/unoapi.hxx>
23 #include <svx/svdoashp.hxx>
24 #include <svx/unoshape.hxx>
25 #include <vcl/outdev.hxx>
26 #include <tools/poly.hxx>
27 #include <vcl/bitmapex.hxx>
28 #include <vcl/graph.hxx>
29 #include <tools/debug.hxx>
30 #include <svx/fmdpage.hxx>
31 #include <toolkit/unohlp.hxx>
32 #include <com/sun/star/style/VerticalAlignment.hpp>
33 #include <com/sun/star/awt/Gradient.hpp>
34 #include <com/sun/star/drawing/PointSequence.hpp>
35 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
36 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
37 #include <com/sun/star/drawing/FlagSequence.hpp>
38 #include <com/sun/star/drawing/TextAdjust.hpp>
39 #include <com/sun/star/drawing/LineDash.hpp>
40 #include <com/sun/star/text/XText.hpp>
41 #include <com/sun/star/drawing/CircleKind.hpp>
42 #include <com/sun/star/drawing/FillStyle.hpp>
43 #include <com/sun/star/task/XStatusIndicator.hpp>
44 #include <comphelper/extract.hxx>
45 #include <vcl/fltcall.hxx>
46 #include <vcl/cvtgrf.hxx>
47 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
48 #include <basegfx/matrix/b2dhommatrix.hxx>
49 #include <basegfx/polygon/b2dpolygontools.hxx>
50 #include <basegfx/polygon/b2dpolygon.hxx>
52 using namespace ::com::sun::star;
53 using namespace ::com::sun::star::beans;
54 using namespace ::com::sun::star::container;
55 using namespace ::com::sun::star::uno;
56 using namespace ::com::sun::star::drawing;
57 using namespace ::com::sun::star::text;
58 using namespace ::com::sun::star::task;
59 using namespace ::com::sun::star::style;
61 #define EES_MAP_FRACTION 1440 // 1440 dpi
63 ImplEESdrWriter::ImplEESdrWriter( EscherEx& rEx )
65 mpEscherEx ( &rEx ),
66 maMapModeSrc ( MAP_100TH_MM ),
67 // PowerPoint: 576 dpi, WinWord: 1440 dpi, Excel: 1440 dpi
68 maMapModeDest( MAP_INCH, Point(), Fraction( 1, EES_MAP_FRACTION ), Fraction( 1, EES_MAP_FRACTION ) ),
69 mpPicStrm ( NULL ),
70 mpHostAppData ( NULL ),
71 mnPagesWritten ( 0 ),
72 mnShapeMasterTitle ( 0 ),
73 mnShapeMasterBody ( 0 ),
74 mbStatusIndicator ( sal_False ),
75 mbStatus ( sal_False )
80 Point ImplEESdrWriter::ImplMapPoint( const Point& rPoint )
82 return OutputDevice::LogicToLogic( rPoint, maMapModeSrc, maMapModeDest );
85 Size ImplEESdrWriter::ImplMapSize( const Size& rSize )
87 Size aRetSize( OutputDevice::LogicToLogic( rSize, maMapModeSrc, maMapModeDest ) );
89 if ( !aRetSize.Width() )
90 aRetSize.Width()++;
91 if ( !aRetSize.Height() )
92 aRetSize.Height()++;
93 return aRetSize;
96 void ImplEESdrWriter::ImplFlipBoundingBox( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt )
98 sal_Int32 nAngle = rObj.GetAngle();
99 Rectangle aRect( rObj.GetRect() );
101 if ( nAngle < 0 )
102 nAngle = ( 36000 + nAngle ) % 36000;
103 else
104 nAngle = ( 36000 - ( nAngle % 36000 ) );
106 double fVal = (double)nAngle * F_PI18000;
107 double fCos = cos( fVal );
108 double fSin = sin( fVal );
110 double nWidthHalf = (double) aRect.GetWidth() / 2;
111 double nHeightHalf = (double) aRect.GetHeight() / 2;
113 double nXDiff = fCos * nWidthHalf + fSin * (-nHeightHalf);
114 double nYDiff = - ( fSin * nWidthHalf - fCos * ( -nHeightHalf ) );
116 aRect.Move( (sal_Int32)( -( nWidthHalf - nXDiff ) ), (sal_Int32)( - ( nHeightHalf + nYDiff ) ) );
118 nAngle *= 655;
119 nAngle += 0x8000;
120 nAngle &=~0xffff; // nAngle round to full degrees
121 rPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
123 rObj.SetAngle( nAngle );
124 rObj.SetRect( aRect );
127 // -----------------------------------------------------------------------
129 #define ADD_SHAPE( nType, nFlags ) \
131 nShapeType = nType; \
132 nShapeID = mpEscherEx->GenerateShapeId(); \
133 rObj.SetShapeId( nShapeID ); \
134 mpEscherEx->AddShape( (sal_uInt32)nType, (sal_uInt32)nFlags, nShapeID ); \
135 rSolverContainer.AddShape( rObj.GetShapeRef(), nShapeID ); \
138 #define SHAPE_TEXT( bFill ) \
140 mpEscherEx->OpenContainer( ESCHER_SpContainer ); \
141 ADD_SHAPE( ESCHER_ShpInst_TextBox, 0xa00 ); \
142 if ( bFill ) \
143 aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True ); \
144 if( rObj.ImplGetText() ) \
145 aPropOpt.CreateTextProperties( rObj.mXPropSet, \
146 mpEscherEx->QueryTextID( rObj.GetShapeRef(), \
147 rObj.GetShapeId() ) ); \
150 //Map from twips to export units, generally twips as well, only excel and word
151 //export is happening here, so native units are export units, leave as
152 //placeholder if required in future
153 void ImplEESdrWriter::MapRect(ImplEESdrObject& /* rObj */ )
157 sal_uInt32 ImplEESdrWriter::ImplWriteShape( ImplEESdrObject& rObj,
158 EscherSolverContainer& rSolverContainer,
159 ImplEESdrPageType ePageType )
161 sal_uInt32 nShapeID = 0;
162 sal_uInt16 nShapeType = 0;
163 sal_Bool bDontWriteText = sal_False; // if a metafile is written as shape replacement, then the text is already part of the metafile
164 sal_Bool bAdditionalText = sal_False;
165 sal_uInt32 nGrpShapeID = 0;
167 do {
168 mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : 0 );
169 if ( mpHostAppData && mpHostAppData->DontWriteShape() )
170 break;
172 // #i51348# get shape name
173 OUString aShapeName;
174 if( const SdrObject* pSdrObj = rObj.GetSdrObject() )
175 if (!pSdrObj->GetName().isEmpty())
176 aShapeName = pSdrObj->GetName();
178 Point aTextRefPoint;
180 if( rObj.GetType().EqualsAscii( "drawing.Group" ))
182 Reference< XIndexAccess > xXIndexAccess( rObj.GetShapeRef(), UNO_QUERY );
184 if( xXIndexAccess.is() && 0 != xXIndexAccess->getCount() )
186 nShapeID = mpEscherEx->EnterGroup( aShapeName, &rObj.GetRect() );
187 nShapeType = ESCHER_ShpInst_Min;
189 for( sal_uInt32 n = 0, nCnt = xXIndexAccess->getCount();
190 n < nCnt; ++n )
192 ImplEESdrObject aObj( *this, *(Reference< XShape >*)
193 xXIndexAccess->getByIndex( n ).getValue() );
194 if( aObj.IsValid() )
195 ImplWriteShape( aObj, rSolverContainer, ePageType );
197 mpEscherEx->LeaveGroup();
199 break;
201 rObj.SetAngle( rObj.ImplGetInt32PropertyValue( OUString( "RotateAngle" ) ));
203 if( ( rObj.ImplGetPropertyValue( OUString( "IsFontwork" ) ) &&
204 ::cppu::any2bool( rObj.GetUsrAny() ) ) ||
205 rObj.GetType().EqualsAscii( "drawing.Measure" ) )
207 rObj.SetType( String("drawing.dontknow"));
210 const ::com::sun::star::awt::Size aSize100thmm( rObj.GetShapeRef()->getSize() );
211 const ::com::sun::star::awt::Point aPoint100thmm( rObj.GetShapeRef()->getPosition() );
212 Rectangle aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
213 if ( !mpPicStrm )
214 mpPicStrm = mpEscherEx->QueryPictureStream();
215 EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm );
217 // #i51348# shape name
218 if (!aShapeName.isEmpty())
219 aPropOpt.AddOpt( ESCHER_Prop_wzName, aShapeName );
220 if ( InteractionInfo* pInteraction = mpHostAppData ? mpHostAppData->GetInteractionInfo():NULL )
222 SAL_WNODEPRECATED_DECLARATIONS_PUSH
223 const std::auto_ptr< SvMemoryStream >& pMemStrm = pInteraction->getHyperlinkRecord();
224 SAL_WNODEPRECATED_DECLARATIONS_POP
225 if ( pMemStrm.get() )
227 pMemStrm->ObjectOwnsMemory( sal_False );
228 sal_uInt8* pBuf = (sal_uInt8*) pMemStrm->GetData();
229 sal_uInt32 nSize = pMemStrm->Seek( STREAM_SEEK_TO_END );
230 aPropOpt.AddOpt( ESCHER_Prop_pihlShape, sal_False, nSize, pBuf, nSize );
232 if ( pInteraction->hasInteraction() )
233 aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080008 );
236 if ( rObj.GetType().EqualsAscii( "drawing.Custom" ) )
238 mpEscherEx->OpenContainer( ESCHER_SpContainer );
239 sal_uInt32 nMirrorFlags;
241 OUString sCustomShapeType;
242 MSO_SPT eShapeType = aPropOpt.GetCustomShapeType( rObj.GetShapeRef(), nMirrorFlags, sCustomShapeType );
243 if ( sCustomShapeType == "col-502ad400" || sCustomShapeType == "col-60da8460" )
245 ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
246 if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "MetaFile", sal_False ) )
248 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
249 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 ); // no fill
250 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 ); // no linestyle
251 SdrObject* pObj = GetSdrObjectFromXShape( rObj.GetShapeRef() );
252 if ( pObj )
254 Rectangle aBound = pObj->GetCurrentBoundRect();
255 Point aPosition( ImplMapPoint( aBound.TopLeft() ) );
256 Size aSize( ImplMapSize( aBound.GetSize() ) );
257 rObj.SetRect( Rectangle( aPosition, aSize ) );
258 rObj.SetAngle( 0 );
259 bDontWriteText = sal_True;
263 else
265 ADD_SHAPE(
266 sal::static_int_cast< sal_uInt16 >(eShapeType),
267 nMirrorFlags | 0xa00 );
268 aPropOpt.CreateCustomShapeProperties( eShapeType, rObj.GetShapeRef() );
269 aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
270 if ( rObj.ImplGetText() )
272 if ( !aPropOpt.IsFontWork() )
273 aPropOpt.CreateTextProperties( rObj.mXPropSet, mpEscherEx->QueryTextID(
274 rObj.GetShapeRef(), rObj.GetShapeId() ), sal_True, sal_False );
278 else if ( rObj.GetType().EqualsAscii( "drawing.Rectangle" ))
280 mpEscherEx->OpenContainer( ESCHER_SpContainer );
281 sal_Int32 nRadius = (sal_Int32)rObj.ImplGetInt32PropertyValue(
282 OUString( "CornerRadius" ));
283 if( nRadius )
285 nRadius = ImplMapSize( Size( nRadius, 0 )).Width();
286 ADD_SHAPE( ESCHER_ShpInst_RoundRectangle, 0xa00 ); // Flags: Connector | HasSpt
287 sal_Int32 nLenght = rObj.GetRect().GetWidth();
288 if ( nLenght > rObj.GetRect().GetHeight() )
289 nLenght = rObj.GetRect().GetHeight();
290 nLenght >>= 1;
291 if ( nRadius >= nLenght )
292 nRadius = 0x2a30; // 0x2a30 is PPTs maximum radius
293 else
294 nRadius = ( 0x2a30 * nRadius ) / nLenght;
295 aPropOpt.AddOpt( ESCHER_Prop_adjustValue, nRadius );
297 else
299 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 ); // Flags: Connector | HasSpt
301 aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
302 if( rObj.ImplGetText() )
303 aPropOpt.CreateTextProperties( rObj.mXPropSet,
304 mpEscherEx->QueryTextID( rObj.GetShapeRef(),
305 rObj.GetShapeId() ), sal_False, sal_False );
307 else if ( rObj.GetType().EqualsAscii( "drawing.Ellipse" ))
309 CircleKind eCircleKind = CircleKind_FULL;
310 PolyStyle ePolyKind = PolyStyle();
311 if ( rObj.ImplGetPropertyValue( OUString( "CircleKind" ) ) )
313 eCircleKind = *( (CircleKind*)rObj.GetUsrAny().getValue() );
314 switch ( eCircleKind )
316 case CircleKind_SECTION :
318 ePolyKind = POLY_PIE;
320 break;
321 case CircleKind_ARC :
323 ePolyKind = POLY_ARC;
325 break;
327 case CircleKind_CUT :
329 ePolyKind = POLY_CHORD;
331 break;
333 default:
334 eCircleKind = CircleKind_FULL;
337 if ( eCircleKind == CircleKind_FULL )
339 mpEscherEx->OpenContainer( ESCHER_SpContainer );
340 ADD_SHAPE( ESCHER_ShpInst_Ellipse, 0xa00 ); // Flags: Connector | HasSpt
341 aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
343 else
345 sal_Int32 nStartAngle, nEndAngle;
346 if ( !rObj.ImplGetPropertyValue( OUString( "CircleStartAngle" ) ) )
347 break;
348 nStartAngle = *( (sal_Int32*)rObj.GetUsrAny().getValue() );
349 if( !rObj.ImplGetPropertyValue( OUString( "CircleEndAngle" ) ) )
350 break;
351 nEndAngle = *( (sal_Int32*)rObj.GetUsrAny().getValue() );
353 Point aStart, aEnd, aCenter;
354 aStart.X() = (sal_Int32)( ( cos( (double)( nStartAngle *
355 F_PI18000 ) ) * 100.0 ) );
356 aStart.Y() = - (sal_Int32)( ( sin( (double)( nStartAngle *
357 F_PI18000 ) ) * 100.0 ) );
358 aEnd.X() = (sal_Int32)( ( cos( (double)( nEndAngle *
359 F_PI18000 ) ) * 100.0 ) );
360 aEnd.Y() = - (sal_Int32)( ( sin( (double)( nEndAngle *
361 F_PI18000 ) ) * 100.0 ) );
362 const Rectangle& rRect = aRect100thmm;
363 aCenter.X() = rRect.Left() + ( rRect.GetWidth() / 2 );
364 aCenter.Y() = rRect.Top() + ( rRect.GetHeight() / 2 );
365 aStart.X() += aCenter.X();
366 aStart.Y() += aCenter.Y();
367 aEnd.X() += aCenter.X();
368 aEnd.Y() += aCenter.Y();
369 Polygon aPolygon( rRect, aStart, aEnd, ePolyKind );
370 if( rObj.GetAngle() )
372 aPolygon.Rotate( rRect.TopLeft(), (sal_uInt16)( rObj.GetAngle() / 10 ) );
373 rObj.SetAngle( 0 );
375 mpEscherEx->OpenContainer( ESCHER_SpContainer );
376 ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt
377 ::com::sun::star::awt::Rectangle aNewRect;
378 switch ( ePolyKind )
380 case POLY_PIE :
381 case POLY_CHORD :
383 aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_False, aNewRect, &aPolygon );
384 aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
386 break;
388 case POLY_ARC :
390 aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_False, aNewRect, &aPolygon );
391 aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
393 break;
395 rObj.SetRect( Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ),
396 ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) );
398 if ( rObj.ImplGetText() )
399 aPropOpt.CreateTextProperties( rObj.mXPropSet,
400 mpEscherEx->QueryTextID( rObj.GetShapeRef(),
401 rObj.GetShapeId() ), sal_False, sal_False );
404 else if ( rObj.GetType().EqualsAscii( "drawing.Control" ))
406 break;
408 else if ( rObj.GetType().EqualsAscii( "drawing.Connector" ))
410 sal_uInt16 nSpType, nSpFlags;
411 ::com::sun::star::awt::Rectangle aNewRect;
412 if ( aPropOpt.CreateConnectorProperties( rObj.GetShapeRef(),
413 rSolverContainer, aNewRect, nSpType, nSpFlags ) == sal_False )
414 break;
415 rObj.SetRect( Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ),
416 ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) );
418 mpEscherEx->OpenContainer( ESCHER_SpContainer );
419 ADD_SHAPE( nSpType, nSpFlags );
421 else if ( rObj.GetType().EqualsAscii( "drawing.Measure" ))
423 break;
425 else if ( rObj.GetType().EqualsAscii( "drawing.Line" ))
427 ::com::sun::star::awt::Rectangle aNewRect;
428 aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_LINE, sal_False, aNewRect, NULL );
429 MapRect(rObj);
430 //i27942: Poly/Lines/Bezier do not support text.
432 mpEscherEx->OpenContainer( ESCHER_SpContainer );
433 sal_uInt32 nFlags = 0xa00; // Flags: Connector | HasSpt
434 if( aNewRect.Height < 0 )
435 nFlags |= 0x80; // Flags: VertMirror
436 if( aNewRect.Width < 0 )
437 nFlags |= 0x40; // Flags: HorzMirror
439 ADD_SHAPE( ESCHER_ShpInst_Line, nFlags );
440 aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
441 aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
442 rObj.SetAngle( 0 );
444 else if ( rObj.GetType().EqualsAscii( "drawing.PolyPolygon" ))
446 if( rObj.ImplHasText() )
448 nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() );
449 bAdditionalText = sal_True;
451 mpEscherEx->OpenContainer( ESCHER_SpContainer );
452 ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt
453 ::com::sun::star::awt::Rectangle aNewRect;
454 aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_False, aNewRect, NULL );
455 MapRect(rObj);
456 aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
457 rObj.SetAngle( 0 );
459 else if ( rObj.GetType().EqualsAscii( "drawing.PolyLine" ))
461 //i27942: Poly/Lines/Bezier do not support text.
463 mpEscherEx->OpenContainer( ESCHER_SpContainer );
464 ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt
465 ::com::sun::star::awt::Rectangle aNewRect;
466 aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_False, aNewRect, NULL );
467 MapRect(rObj);
468 aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
469 rObj.SetAngle( 0 );
471 else if ( rObj.GetType().EqualsAscii( "drawing.OpenBezier" ) )
473 //i27942: Poly/Lines/Bezier do not support text.
475 mpEscherEx->OpenContainer( ESCHER_SpContainer );
476 ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt
477 ::com::sun::star::awt::Rectangle aNewRect;
478 aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_True, aNewRect, NULL );
479 MapRect(rObj);
480 aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
481 rObj.SetAngle( 0 );
483 else if ( rObj.GetType().EqualsAscii( "drawing.ClosedBezier" ) )
485 if ( rObj.ImplHasText() )
487 nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() );
488 bAdditionalText = sal_True;
490 mpEscherEx->OpenContainer( ESCHER_SpContainer );
491 ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 ); // Flags: Connector | HasSpt
492 ::com::sun::star::awt::Rectangle aNewRect;
493 aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_True, aNewRect, NULL );
494 MapRect(rObj);
495 aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
496 rObj.SetAngle( 0 );
498 else if ( rObj.GetType().EqualsAscii( "drawing.GraphicObject" ))
500 mpEscherEx->OpenContainer( ESCHER_SpContainer );
502 // a GraphicObject can also be a ClickMe element
503 if( rObj.IsEmptyPresObj() && ( ePageType == NORMAL ) )
505 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0x220 ); // Flags: HaveAnchor | HaveMaster
506 sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(),
507 rObj.GetShapeId() );
508 aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId );
509 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
510 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
511 aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
513 else
515 if( rObj.ImplGetText() )
517 /* SJ #i34951#: because M. documents are not allowing GraphicObjects containing text, we
518 have to create a simpe Rectangle with fill bitmap instead (while not allowing BitmapMode_Repeat).
520 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 ); // Flags: Connector | HasSpt
521 if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "GraphicURL", sal_True, sal_True, sal_False ) )
523 aPropOpt.AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
524 aPropOpt.AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
525 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
526 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x8000000 );
527 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
528 if ( rObj.ImplGetText() )
529 aPropOpt.CreateTextProperties( rObj.mXPropSet,
530 mpEscherEx->QueryTextID( rObj.GetShapeRef(),
531 rObj.GetShapeId() ), sal_False, sal_False );
534 else
536 ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
537 if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "GraphicURL", sal_False, sal_True ) )
538 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
542 else if ( rObj.GetType().EqualsAscii( "drawing.Text" ))
544 SHAPE_TEXT( sal_True );
546 else if ( rObj.GetType().EqualsAscii( "drawing.Page" ))
548 mpEscherEx->OpenContainer( ESCHER_SpContainer );
549 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 );
550 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x40004 );
551 aPropOpt.AddOpt( ESCHER_Prop_fFillOK, 0x100001 );
552 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x110011 );
553 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90008 );
554 aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x10001 );
556 else if ( rObj.GetType().EqualsAscii( "drawing.Frame" ))
558 break;
560 else if ( rObj.GetType().EqualsAscii( "drawing.OLE2" ))
562 mpEscherEx->OpenContainer( ESCHER_SpContainer );
563 if( rObj.IsEmptyPresObj() && ( ePageType == NORMAL ) )
565 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0x220 ); // Flags: HaveAnchor | HaveMaster
566 sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(),
567 rObj.GetShapeId() );
568 aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId );
569 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
570 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
571 aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
573 else
575 //2do: could be made an option in HostAppData whether OLE object should be written or not
576 sal_Bool bAppOLE = sal_True;
577 ADD_SHAPE( ESCHER_ShpInst_PictureFrame,
578 0xa00 | (bAppOLE ? SHAPEFLAG_OLESHAPE : 0) );
579 if ( aPropOpt.CreateOLEGraphicProperties( rObj.GetShapeRef() ) )
581 if ( bAppOLE )
582 { // snooped from Xcl hex dump, nobody knows the trouble I have seen
583 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x00080008 );
584 aPropOpt.AddOpt( ESCHER_Prop_pictureId, 0x00000001 );
585 aPropOpt.AddOpt( ESCHER_Prop_fillColor, 0x08000041 );
586 aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x08000041 );
587 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x00110010 );
588 aPropOpt.AddOpt( ESCHER_Prop_lineColor, 0x08000040 );
589 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash,0x00080008 );
590 aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x00080000 );
592 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
596 else if( '3' == rObj.GetType().GetChar(8 ) &&
597 'D' == rObj.GetType().GetChar( 9 ) ) // drawing.3D
599 // SceneObject, CubeObject, SphereObject, LatheObject, ExtrudeObject, PolygonObject
600 if ( !rObj.ImplGetPropertyValue( OUString( "Bitmap" ) ) )
601 break;
603 mpEscherEx->OpenContainer( ESCHER_SpContainer );
604 ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
606 if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "Bitmap", sal_False ) )
607 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
609 else if ( rObj.GetType().EqualsAscii( "drawing.Caption" ))
611 rObj.SetAngle( 0 );
612 mpEscherEx->OpenContainer( ESCHER_SpContainer );
613 ADD_SHAPE( ESCHER_ShpInst_TextBox, 0xa00 );
614 if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "MetaFile", sal_False ) )
615 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
617 else if ( rObj.GetType().EqualsAscii( "drawing.dontknow" ))
619 rObj.SetAngle( 0 );
620 mpEscherEx->OpenContainer( ESCHER_SpContainer );
621 ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
622 if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, "MetaFile", sal_False ) )
623 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
625 else
627 break;
629 aPropOpt.CreateShadowProperties( rObj.mXPropSet );
631 if( USHRT_MAX != mpEscherEx->GetHellLayerId() &&
632 rObj.ImplGetPropertyValue( OUString( "LayerID" ) ) &&
633 (*((sal_uInt16*)rObj.GetUsrAny().getValue()) ) == mpEscherEx->GetHellLayerId() )
635 aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
639 Rectangle aRect( rObj.GetRect() );
640 aRect.Justify();
641 rObj.SetRect( aRect );
644 if( rObj.GetAngle() )
645 ImplFlipBoundingBox( rObj, aPropOpt );
647 aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
648 mpEscherEx->Commit( aPropOpt, rObj.GetRect() );
649 if( mpEscherEx->GetGroupLevel() > 1 )
650 mpEscherEx->AddChildAnchor( rObj.GetRect() );
652 if ( mpHostAppData )
653 { //! with AdditionalText the App has to control whether these are written or not
654 mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() );
655 mpHostAppData->WriteClientData( *mpEscherEx );
656 if ( !bDontWriteText )
657 mpHostAppData->WriteClientTextbox( *mpEscherEx );
659 mpEscherEx->CloseContainer(); // ESCHER_SpContainer
661 if( bAdditionalText )
663 mpEscherEx->EndShape( nShapeType, nShapeID );
664 ImplWriteAdditionalText( rObj, aTextRefPoint );
667 } while ( 0 );
669 if ( bAdditionalText )
670 mpEscherEx->EndShape( ESCHER_ShpInst_Min, nGrpShapeID );
671 else
672 mpEscherEx->EndShape( nShapeType, nShapeID );
673 return nShapeID;
676 void ImplEESdrWriter::ImplWriteAdditionalText( ImplEESdrObject& rObj,
677 const Point& rTextRefPoint )
679 sal_uInt32 nShapeID = 0;
680 sal_uInt16 nShapeType = 0;
683 mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : 0 );
684 if ( mpHostAppData && mpHostAppData->DontWriteShape() )
685 break;
687 const ::com::sun::star::awt::Size aSize100thmm( rObj.GetShapeRef()->getSize() );
688 const ::com::sun::star::awt::Point aPoint100thmm( rObj.GetShapeRef()->getPosition() );
689 Rectangle aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
690 if ( !mpPicStrm )
691 mpPicStrm = mpEscherEx->QueryPictureStream();
692 EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm );
693 rObj.SetAngle( rObj.ImplGetInt32PropertyValue( OUString( "RotateAngle" )));
694 sal_Int32 nAngle = rObj.GetAngle();
695 if( rObj.GetType().EqualsAscii( "drawing.Line" ))
697 //2do: this does not work right
698 double fDist = hypot( rObj.GetRect().GetWidth(),
699 rObj.GetRect().GetHeight() );
700 rObj.SetRect( Rectangle( rTextRefPoint,
701 Point( (sal_Int32)( rTextRefPoint.X() + fDist ), rTextRefPoint.Y() - 1 ) ) );
703 mpEscherEx->OpenContainer( ESCHER_SpContainer );
704 mpEscherEx->AddShape( ESCHER_ShpInst_TextBox, 0xa00 );
705 if ( rObj.ImplGetText() )
706 aPropOpt.CreateTextProperties( rObj.mXPropSet,
707 mpEscherEx->QueryTextID( rObj.GetShapeRef(),
708 rObj.GetShapeId() ) );
710 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
711 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
712 aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x60006 ); // Size Shape To Fit Text
713 if ( nAngle < 0 )
714 nAngle = ( 36000 + nAngle ) % 36000;
715 if ( nAngle )
716 ImplFlipBoundingBox( rObj, aPropOpt );
718 else
720 mpEscherEx->OpenContainer( ESCHER_SpContainer );
721 nShapeID = mpEscherEx->GenerateShapeId();
722 mpEscherEx->AddShape( nShapeType = ESCHER_ShpInst_TextBox, 0xa00, nShapeID );
723 if ( rObj.ImplGetText() )
724 aPropOpt.CreateTextProperties( rObj.mXPropSet,
725 mpEscherEx->QueryTextID( rObj.GetShapeRef(),
726 rObj.GetShapeId() ) );
727 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
728 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
730 if( nAngle < 0 )
731 nAngle = ( 36000 + nAngle ) % 36000;
732 else
733 nAngle = ( 36000 - ( nAngle % 36000 ) );
735 nAngle *= 655;
736 nAngle += 0x8000;
737 nAngle &=~0xffff; // nAngle round to full degrees
738 aPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
739 mpEscherEx->SetGroupSnapRect( mpEscherEx->GetGroupLevel(),
740 rObj.GetRect() );
741 mpEscherEx->SetGroupLogicRect( mpEscherEx->GetGroupLevel(),
742 rObj.GetRect() );
744 rObj.SetAngle( nAngle );
745 aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
746 mpEscherEx->Commit( aPropOpt, rObj.GetRect() );
748 // write the childanchor
749 mpEscherEx->AddChildAnchor( rObj.GetRect() );
751 #if defined EES_WRITE_EPP
752 // ClientAnchor
753 mpEscherEx->AddClientAnchor( maRect );
754 // ClientTextbox
755 mpEscherEx->OpenContainer( ESCHER_ClientTextbox );
756 mpEscherEx->AddAtom( 4, EPP_TextHeaderAtom );
757 *mpStrm << (sal_uInt32)EPP_TEXTTYPE_Other; // Text in a Shape
758 ImplWriteTextStyleAtom();
759 mpEscherEx->CloseContainer(); // ESCHER_ClientTextBox
760 #else // !EES_WRITE_EPP
761 if ( mpHostAppData )
762 { //! the App has to control whether these are written or not
763 mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() );
764 mpHostAppData->WriteClientData( *mpEscherEx );
765 mpHostAppData->WriteClientTextbox( *mpEscherEx );
767 #endif // EES_WRITE_EPP
768 mpEscherEx->CloseContainer(); // ESCHER_SpContainer
769 } while ( 0 );
770 mpEscherEx->LeaveGroup();
771 mpEscherEx->EndShape( nShapeType, nShapeID );
775 sal_uInt32 ImplEESdrWriter::ImplEnterAdditionalTextGroup( const Reference< XShape >& rShape,
776 const Rectangle* pBoundRect )
778 mpHostAppData = mpEscherEx->EnterAdditionalTextGroup();
779 sal_uInt32 nGrpId = mpEscherEx->EnterGroup( pBoundRect );
780 mpHostAppData = mpEscherEx->StartShape( rShape, pBoundRect );
781 return nGrpId;
785 sal_Bool ImplEESdrWriter::ImplInitPageValues()
787 mnIndices = 0;
788 mnOutlinerCount = 0; // die outline objects must be in accordance with the layout.
789 mnEffectCount = 0;
790 mbIsTitlePossible = sal_True; // With more than one title PowerPoint will fail.
792 return sal_True;
795 void ImplEESdrWriter::ImplWritePage(
796 EscherSolverContainer& rSolverContainer,
797 ImplEESdrPageType ePageType, sal_Bool /* bBackGround */ )
799 ImplInitPageValues();
801 sal_uInt32 nLastPer = 0, nShapes = mXShapes->getCount();
802 for( sal_uInt32 n = 0; n < nShapes; ++n )
804 sal_uInt32 nPer = ( 5 * n ) / nShapes;
805 if( nPer != nLastPer )
807 nLastPer = nPer;
808 sal_uInt32 nValue = mnPagesWritten * 5 + nPer;
809 if( nValue > mnStatMaxValue )
810 nValue = mnStatMaxValue;
811 if( mbStatusIndicator )
812 mXStatusIndicator->setValue( nValue );
815 ImplEESdrObject aObj( *this, *(Reference< XShape >*)
816 mXShapes->getByIndex( n ).getValue() );
817 if( aObj.IsValid() )
819 ImplWriteShape( aObj, rSolverContainer, ePageType );
822 mnPagesWritten++;
825 ImplEscherExSdr::ImplEscherExSdr( EscherEx& rEx )
827 ImplEESdrWriter( rEx ),
828 mpSdrPage( NULL ),
829 mpSolverContainer( NULL )
834 ImplEscherExSdr::~ImplEscherExSdr()
836 DBG_ASSERT( !mpSolverContainer, "ImplEscherExSdr::~ImplEscherExSdr: unwritten SolverContainer" );
837 delete mpSolverContainer;
841 bool ImplEscherExSdr::ImplInitPage( const SdrPage& rPage )
845 SvxDrawPage* pSvxDrawPage;
846 if ( mpSdrPage != &rPage || !mXDrawPage.is() )
848 // eventually write SolverContainer of current page, deletes the Solver
849 ImplFlushSolverContainer();
851 mpSdrPage = NULL;
852 mXDrawPage = pSvxDrawPage = new SvxFmDrawPage( (SdrPage*) &rPage );
853 mXShapes = Reference< XShapes >::query( mXDrawPage );
854 if ( !mXShapes.is() )
855 break;
856 if ( !ImplInitPageValues() ) // ImplEESdrWriter
857 break;
858 mpSdrPage = &rPage;
860 mpSolverContainer = new EscherSolverContainer;
862 else
863 pSvxDrawPage = SvxDrawPage::getImplementation(mXDrawPage);
865 return pSvxDrawPage != 0;
866 } while ( 0 );
868 return false;
871 bool ImplEscherExSdr::ImplInitUnoShapes( const Reference< XShapes >& rxShapes )
873 // eventually write SolverContainer of current page, deletes the Solver
874 ImplFlushSolverContainer();
876 if( !rxShapes.is() )
877 return false;
879 mpSdrPage = 0;
880 mXDrawPage.clear();
881 mXShapes = rxShapes;
883 if( !ImplInitPageValues() ) // ImplEESdrWriter
884 return false;
886 mpSolverContainer = new EscherSolverContainer;
887 return true;
890 void ImplEscherExSdr::ImplExitPage()
892 // close all groups before the solver container is written
893 while( mpEscherEx->GetGroupLevel() )
894 mpEscherEx->LeaveGroup();
896 ImplFlushSolverContainer();
897 mpSdrPage = NULL; // reset page for next init
901 void ImplEscherExSdr::ImplFlushSolverContainer()
903 if ( mpSolverContainer )
905 mpSolverContainer->WriteSolver( mpEscherEx->GetStream() );
906 delete mpSolverContainer;
907 mpSolverContainer = NULL;
912 void ImplEscherExSdr::ImplWriteCurrentPage()
914 DBG_ASSERT( mpSolverContainer, "ImplEscherExSdr::ImplWriteCurrentPage: no SolverContainer" );
915 ImplWritePage( *mpSolverContainer, NORMAL );
916 ImplExitPage();
920 sal_uInt32 ImplEscherExSdr::ImplWriteTheShape( ImplEESdrObject& rObj )
922 DBG_ASSERT( mpSolverContainer, "ImplEscherExSdr::ImplWriteShape: no SolverContainer" );
923 return ImplWriteShape( rObj, *mpSolverContainer, NORMAL );
927 void EscherEx::AddSdrPage( const SdrPage& rPage )
929 if ( mpImplEscherExSdr->ImplInitPage( rPage ) )
930 mpImplEscherExSdr->ImplWriteCurrentPage();
933 void EscherEx::AddUnoShapes( const Reference< XShapes >& rxShapes )
935 if ( mpImplEscherExSdr->ImplInitUnoShapes( rxShapes ) )
936 mpImplEscherExSdr->ImplWriteCurrentPage();
939 sal_uInt32 EscherEx::AddSdrObject( const SdrObject& rObj )
941 ImplEESdrObject aObj( *mpImplEscherExSdr, rObj );
942 if( aObj.IsValid() )
943 return mpImplEscherExSdr->ImplWriteTheShape( aObj );
944 return 0;
948 void EscherEx::EndSdrObjectPage()
950 mpImplEscherExSdr->ImplExitPage();
953 EscherExHostAppData* EscherEx::StartShape( const Reference< XShape >& /* rShape */, const Rectangle* /*pChildAnchor*/ )
955 return NULL;
958 void EscherEx::EndShape( sal_uInt16 /* nShapeType */, sal_uInt32 /* nShapeID */ )
962 sal_uInt32 EscherEx::QueryTextID( const Reference< XShape >&, sal_uInt32 )
964 return 0;
967 // add an dummy rectangle shape into the escher stream
968 sal_uInt32 EscherEx::AddDummyShape()
970 OpenContainer( ESCHER_SpContainer );
971 sal_uInt32 nShapeID = GenerateShapeId();
972 AddShape( ESCHER_ShpInst_Rectangle, 0xa00, nShapeID );
973 CloseContainer();
975 return nShapeID;
978 // static
979 const SdrObject* EscherEx::GetSdrObject( const Reference< XShape >& rShape )
981 const SdrObject* pRet = 0;
982 const SvxShape* pSvxShape = SvxShape::getImplementation( rShape );
983 DBG_ASSERT( pSvxShape, "EscherEx::GetSdrObject: no SvxShape" );
984 if( pSvxShape )
986 pRet = pSvxShape->GetSdrObject();
987 DBG_ASSERT( pRet, "EscherEx::GetSdrObject: no SdrObj" );
989 return pRet;
993 ImplEESdrObject::ImplEESdrObject( ImplEscherExSdr& rEx,
994 const SdrObject& rObj ) :
995 mnShapeId( 0 ),
996 mnTextSize( 0 ),
997 mnAngle( 0 ),
998 mbValid( sal_False ),
999 mbPresObj( sal_False ),
1000 mbEmptyPresObj( sal_False )
1002 SdrPage* pPage = rObj.GetPage();
1003 DBG_ASSERT( pPage, "ImplEESdrObject::ImplEESdrObject: no SdrPage" );
1004 if( pPage && rEx.ImplInitPage( *pPage ) )
1006 // why not declare a const parameter if the object will
1007 // not be modified?
1008 mXShape = uno::Reference< drawing::XShape >::query( ((SdrObject*)&rObj)->getUnoShape() );
1009 Init( rEx );
1013 ImplEESdrObject::ImplEESdrObject( ImplEESdrWriter& rEx,
1014 const Reference< XShape >& rShape ) :
1015 mXShape( rShape ),
1016 mnShapeId( 0 ),
1017 mnTextSize( 0 ),
1018 mnAngle( 0 ),
1019 mbValid( sal_False ),
1020 mbPresObj( sal_False ),
1021 mbEmptyPresObj( sal_False )
1023 Init( rEx );
1027 ImplEESdrObject::~ImplEESdrObject()
1031 basegfx::B2DRange getUnrotatedGroupBoundRange(const Reference< XShape >& rxShape)
1033 basegfx::B2DRange aRetval;
1037 if(rxShape.is())
1039 if(rxShape->getShapeType().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.GroupShape")))
1041 // it's a group shape, iterate over children
1042 const Reference< XIndexAccess > xXIndexAccess(rxShape, UNO_QUERY);
1044 if(xXIndexAccess.is())
1046 for(sal_uInt32 n(0), nCnt = xXIndexAccess->getCount(); n < nCnt; ++n)
1048 const Reference< XShape > axShape(xXIndexAccess->getByIndex(n), UNO_QUERY);
1050 if(axShape.is())
1052 // we are calculating the bound for a group, correct rotation for sub-objects
1053 // to get the unrotated bounds for the group
1054 const basegfx::B2DRange aExtend(getUnrotatedGroupBoundRange(axShape));
1056 aRetval.expand(aExtend);
1061 else
1063 // iT#s a xShape, get it's transformation
1064 const Reference< XPropertySet > mXPropSet(rxShape, UNO_QUERY);
1066 if(mXPropSet.is())
1068 const Any aAny = mXPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")));
1070 if(aAny.hasValue())
1072 HomogenMatrix3 aMatrix;
1074 if(aAny >>= aMatrix)
1076 basegfx::B2DHomMatrix aHomogenMatrix;
1078 aHomogenMatrix.set(0, 0, aMatrix.Line1.Column1);
1079 aHomogenMatrix.set(0, 1, aMatrix.Line1.Column2);
1080 aHomogenMatrix.set(0, 2, aMatrix.Line1.Column3);
1081 aHomogenMatrix.set(1, 0, aMatrix.Line2.Column1);
1082 aHomogenMatrix.set(1, 1, aMatrix.Line2.Column2);
1083 aHomogenMatrix.set(1, 2, aMatrix.Line2.Column3);
1084 aHomogenMatrix.set(2, 0, aMatrix.Line3.Column1);
1085 aHomogenMatrix.set(2, 1, aMatrix.Line3.Column2);
1086 aHomogenMatrix.set(2, 2, aMatrix.Line3.Column3);
1088 basegfx::B2DVector aScale, aTranslate;
1089 double fRotate, fShearX;
1091 // decopose transformation
1092 aHomogenMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
1094 // check if rotation needs to be corrected
1095 if(!basegfx::fTools::equalZero(fRotate))
1097 // to correct, keep in mind that ppt graphics are rotated around their center
1098 const basegfx::B2DPoint aCenter(aHomogenMatrix * basegfx::B2DPoint(0.5, 0.5));
1100 aHomogenMatrix.translate(-aCenter.getX(), -aCenter.getY());
1101 aHomogenMatrix.rotate(-fRotate);
1102 aHomogenMatrix.translate(aCenter.getX(), aCenter.getY());
1106 // check if shear needs to be corrected (always correct shear,
1107 // ppt does not know about it)
1108 if(!basegfx::fTools::equalZero(fShearX))
1110 const basegfx::B2DPoint aMinimum(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
1112 aHomogenMatrix.translate(-aMinimum.getX(), -aMinimum.getY());
1113 aHomogenMatrix.shearX(-fShearX);
1114 aHomogenMatrix.translate(aMinimum.getX(), aMinimum.getY());
1117 // create range. It's no longer rotated (or sheared), so use
1118 // minimum and maximum values
1119 aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
1120 aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(1.0, 1.0));
1127 catch(::com::sun::star::uno::Exception&)
1131 return aRetval;
1134 void ImplEESdrObject::Init( ImplEESdrWriter& rEx )
1136 mXPropSet = Reference< XPropertySet >::query( mXShape );
1137 if( mXPropSet.is() )
1139 static const sal_Char aPrefix[] = "com.sun.star.";
1140 static const xub_StrLen nPrefix = sizeof(aPrefix)-1;
1142 // detect name first to make below test (is group) work
1143 mType = String( mXShape->getShapeType() );
1144 mType.Erase( 0, nPrefix ); // strip "com.sun.star."
1145 xub_StrLen nPos = mType.SearchAscii( "Shape" );
1146 mType.Erase( nPos, 5 );
1148 if(GetType().EqualsAscii("drawing.Group"))
1150 // if it's a group, the unrotated range is needed for that group
1151 const basegfx::B2DRange aUnroatedRange(getUnrotatedGroupBoundRange(mXShape));
1152 const Point aNewP(basegfx::fround(aUnroatedRange.getMinX()), basegfx::fround(aUnroatedRange.getMinY()));
1153 const Size aNewS(basegfx::fround(aUnroatedRange.getWidth()), basegfx::fround(aUnroatedRange.getHeight()));
1155 SetRect(rEx.ImplMapPoint(aNewP), rEx.ImplMapSize(aNewS));
1157 else
1159 // if it's no group, use position and size directly, roated/sheared or not
1160 const Point aOldP(mXShape->getPosition().X, mXShape->getPosition().Y);
1161 const Size aOldS(mXShape->getSize().Width, mXShape->getSize().Height);
1163 SetRect(rEx.ImplMapPoint(aOldP), rEx.ImplMapSize(aOldS));
1166 if( ImplGetPropertyValue( OUString("IsPresentationObject")) )
1167 mbPresObj = ::cppu::any2bool( mAny );
1169 if( mbPresObj && ImplGetPropertyValue( OUString("IsEmptyPresentationObject") ) )
1170 mbEmptyPresObj = ::cppu::any2bool( mAny );
1172 mbValid = sal_True;
1176 sal_Bool ImplEESdrObject::ImplGetPropertyValue( const sal_Unicode* rString )
1178 sal_Bool bRetValue = sal_False;
1179 if( mbValid )
1183 mAny = mXPropSet->getPropertyValue( rString );
1184 if( mAny.hasValue() )
1185 bRetValue = sal_True;
1187 catch( const ::com::sun::star::uno::Exception& )
1189 bRetValue = sal_False;
1192 return bRetValue;
1195 #ifdef USED
1196 sal_Bool ImplEESdrObject::ImplGetPropertyValue( const Reference< XPropertySet >& rXPropSet,
1197 const OUString& rString )
1199 sal_Bool bRetValue = sal_False;
1200 if( mbValid )
1204 mAny = rXPropSet->getPropertyValue( rString );
1205 if( 0 != mAny.get() )
1206 bRetValue = sal_True;
1208 catch( const ::com::sun::star::uno::Exception& )
1210 bRetValue = sal_False;
1213 return bRetValue;
1215 #endif
1217 void ImplEESdrObject::SetRect( const Point& rPos, const Size& rSz )
1219 maRect = Rectangle( rPos, rSz );
1222 const SdrObject* ImplEESdrObject::GetSdrObject() const
1224 return EscherEx::GetSdrObject( mXShape );
1227 // loads and converts text from shape, result is being saved in mnTextSize respeichert
1228 sal_uInt32 ImplEESdrObject::ImplGetText()
1230 Reference< XText > xXText( mXShape, UNO_QUERY );
1231 mnTextSize = 0;
1232 if( xXText.is() )
1233 mnTextSize = xXText->getString().getLength();
1234 return mnTextSize;
1237 sal_Bool ImplEESdrObject::ImplHasText() const
1239 Reference< XText > xXText( mXShape, UNO_QUERY );
1240 return xXText.is() && !xXText->getString().isEmpty();
1243 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */