1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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
)
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
) ),
70 mpHostAppData ( NULL
),
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() )
91 if ( !aRetSize
.Height() )
96 void ImplEESdrWriter::ImplFlipBoundingBox( ImplEESdrObject
& rObj
, EscherPropertyContainer
& rPropOpt
)
98 sal_Int32 nAngle
= rObj
.GetAngle();
99 Rectangle
aRect( rObj
.GetRect() );
102 nAngle
= ( 36000 + nAngle
) % 36000;
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
) ) );
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 ); \
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;
168 mpHostAppData
= mpEscherEx
->StartShape( rObj
.GetShapeRef(), (mpEscherEx
->GetGroupLevel() > 1) ? &rObj
.GetRect() : 0 );
169 if ( mpHostAppData
&& mpHostAppData
->DontWriteShape() )
172 // #i51348# get shape name
174 if( const SdrObject
* pSdrObj
= rObj
.GetSdrObject() )
175 if (!pSdrObj
->GetName().isEmpty())
176 aShapeName
= pSdrObj
->GetName();
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();
192 ImplEESdrObject
aObj( *this, *(Reference
< XShape
>*)
193 xXIndexAccess
->getByIndex( n
).getValue() );
195 ImplWriteShape( aObj
, rSolverContainer
, ePageType
);
197 mpEscherEx
->LeaveGroup();
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
) );
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() );
254 Rectangle aBound
= pObj
->GetCurrentBoundRect();
255 Point
aPosition( ImplMapPoint( aBound
.TopLeft() ) );
256 Size
aSize( ImplMapSize( aBound
.GetSize() ) );
257 rObj
.SetRect( Rectangle( aPosition
, aSize
) );
259 bDontWriteText
= sal_True
;
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" ));
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();
291 if ( nRadius
>= nLenght
)
292 nRadius
= 0x2a30; // 0x2a30 is PPTs maximum radius
294 nRadius
= ( 0x2a30 * nRadius
) / nLenght
;
295 aPropOpt
.AddOpt( ESCHER_Prop_adjustValue
, nRadius
);
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
;
321 case CircleKind_ARC
:
323 ePolyKind
= POLY_ARC
;
327 case CircleKind_CUT
:
329 ePolyKind
= POLY_CHORD
;
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
);
345 sal_Int32 nStartAngle
, nEndAngle
;
346 if ( !rObj
.ImplGetPropertyValue( OUString( "CircleStartAngle" ) ) )
348 nStartAngle
= *( (sal_Int32
*)rObj
.GetUsrAny().getValue() );
349 if( !rObj
.ImplGetPropertyValue( OUString( "CircleEndAngle" ) ) )
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 ) );
375 mpEscherEx
->OpenContainer( ESCHER_SpContainer
);
376 ADD_SHAPE( ESCHER_ShpInst_NotPrimitive
, 0xa00 ); // Flags: Connector | HasSpt
377 ::com::sun::star::awt::Rectangle aNewRect
;
383 aPropOpt
.CreatePolygonProperties( rObj
.mXPropSet
, ESCHER_CREATEPOLYGON_POLYPOLYGON
, sal_False
, aNewRect
, &aPolygon
);
384 aPropOpt
.CreateFillProperties( rObj
.mXPropSet
, sal_True
);
390 aPropOpt
.CreatePolygonProperties( rObj
.mXPropSet
, ESCHER_CREATEPOLYGON_POLYLINE
, sal_False
, aNewRect
, &aPolygon
);
391 aPropOpt
.CreateLineProperties( rObj
.mXPropSet
, sal_False
);
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" ))
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
)
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" ))
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
);
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
);
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
);
456 aPropOpt
.CreateFillProperties( rObj
.mXPropSet
, sal_True
);
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
);
468 aPropOpt
.CreateLineProperties( rObj
.mXPropSet
, sal_False
);
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
);
480 aPropOpt
.CreateLineProperties( rObj
.mXPropSet
, sal_False
);
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
);
495 aPropOpt
.CreateFillProperties( rObj
.mXPropSet
, sal_True
);
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(),
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
);
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
);
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" ))
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(),
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
);
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() ) )
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" ) ) )
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" ))
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" ))
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 );
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() );
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() );
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
);
669 if ( bAdditionalText
)
670 mpEscherEx
->EndShape( ESCHER_ShpInst_Min
, nGrpShapeID
);
672 mpEscherEx
->EndShape( nShapeType
, 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() )
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
) );
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
714 nAngle
= ( 36000 + nAngle
) % 36000;
716 ImplFlipBoundingBox( rObj
, aPropOpt
);
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 );
731 nAngle
= ( 36000 + nAngle
) % 36000;
733 nAngle
= ( 36000 - ( nAngle
% 36000 ) );
737 nAngle
&=~0xffff; // nAngle round to full degrees
738 aPropOpt
.AddOpt( ESCHER_Prop_Rotation
, nAngle
);
739 mpEscherEx
->SetGroupSnapRect( mpEscherEx
->GetGroupLevel(),
741 mpEscherEx
->SetGroupLogicRect( mpEscherEx
->GetGroupLevel(),
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
753 mpEscherEx
->AddClientAnchor( maRect
);
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
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
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
);
785 sal_Bool
ImplEESdrWriter::ImplInitPageValues()
788 mnOutlinerCount
= 0; // die outline objects must be in accordance with the layout.
790 mbIsTitlePossible
= sal_True
; // With more than one title PowerPoint will fail.
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
)
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() );
819 ImplWriteShape( aObj
, rSolverContainer
, ePageType
);
825 ImplEscherExSdr::ImplEscherExSdr( EscherEx
& rEx
)
827 ImplEESdrWriter( rEx
),
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();
852 mXDrawPage
= pSvxDrawPage
= new SvxFmDrawPage( (SdrPage
*) &rPage
);
853 mXShapes
= Reference
< XShapes
>::query( mXDrawPage
);
854 if ( !mXShapes
.is() )
856 if ( !ImplInitPageValues() ) // ImplEESdrWriter
860 mpSolverContainer
= new EscherSolverContainer
;
863 pSvxDrawPage
= SvxDrawPage::getImplementation(mXDrawPage
);
865 return pSvxDrawPage
!= 0;
871 bool ImplEscherExSdr::ImplInitUnoShapes( const Reference
< XShapes
>& rxShapes
)
873 // eventually write SolverContainer of current page, deletes the Solver
874 ImplFlushSolverContainer();
883 if( !ImplInitPageValues() ) // ImplEESdrWriter
886 mpSolverContainer
= new EscherSolverContainer
;
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
);
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
);
943 return mpImplEscherExSdr
->ImplWriteTheShape( aObj
);
948 void EscherEx::EndSdrObjectPage()
950 mpImplEscherExSdr
->ImplExitPage();
953 EscherExHostAppData
* EscherEx::StartShape( const Reference
< XShape
>& /* rShape */, const Rectangle
* /*pChildAnchor*/ )
958 void EscherEx::EndShape( sal_uInt16
/* nShapeType */, sal_uInt32
/* nShapeID */ )
962 sal_uInt32
EscherEx::QueryTextID( const Reference
< XShape
>&, sal_uInt32
)
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
);
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" );
986 pRet
= pSvxShape
->GetSdrObject();
987 DBG_ASSERT( pRet
, "EscherEx::GetSdrObject: no SdrObj" );
993 ImplEESdrObject::ImplEESdrObject( ImplEscherExSdr
& rEx
,
994 const SdrObject
& rObj
) :
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
1008 mXShape
= uno::Reference
< drawing::XShape
>::query( ((SdrObject
*)&rObj
)->getUnoShape() );
1013 ImplEESdrObject::ImplEESdrObject( ImplEESdrWriter
& rEx
,
1014 const Reference
< XShape
>& rShape
) :
1019 mbValid( sal_False
),
1020 mbPresObj( sal_False
),
1021 mbEmptyPresObj( sal_False
)
1027 ImplEESdrObject::~ImplEESdrObject()
1031 basegfx::B2DRange
getUnrotatedGroupBoundRange(const Reference
< XShape
>& rxShape
)
1033 basegfx::B2DRange aRetval
;
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
);
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
);
1063 // iT#s a xShape, get it's transformation
1064 const Reference
< XPropertySet
> mXPropSet(rxShape
, UNO_QUERY
);
1068 const Any aAny
= mXPropSet
->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")));
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
&)
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
));
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
);
1176 sal_Bool
ImplEESdrObject::ImplGetPropertyValue( const sal_Unicode
* rString
)
1178 sal_Bool bRetValue
= sal_False
;
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
;
1196 sal_Bool
ImplEESdrObject::ImplGetPropertyValue( const Reference
< XPropertySet
>& rXPropSet
,
1197 const OUString
& rString
)
1199 sal_Bool bRetValue
= sal_False
;
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
;
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
);
1233 mnTextSize
= xXText
->getString().getLength();
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: */