xref: /AOO41X/main/filter/source/msfilter/eschesdo.cxx (revision 14a8a9a42ba2fbca77cee2c531e8b255905aff44)
1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_filter.hxx"
26 #include "eschesdo.hxx"
27 #include <svx/svdobj.hxx>
28 #include <svx/unoapi.hxx>
29 #include <svx/svdoashp.hxx>
30 #include <svx/unoshape.hxx>
31 #include <vcl/outdev.hxx>
32 #include <tools/poly.hxx>
33 #include <vcl/bitmapex.hxx>
34 #include <vcl/graph.hxx>
35 #include <tools/debug.hxx>
36 #include <svx/fmdpage.hxx>
37 #include <toolkit/unohlp.hxx>
38 #include <com/sun/star/style/VerticalAlignment.hpp>
39 #include <com/sun/star/awt/Gradient.hpp>
40 #include <com/sun/star/drawing/PointSequence.hpp>
41 #include <com/sun/star/drawing/PointSequenceSequence.hpp>
42 #include <com/sun/star/drawing/PolyPolygonBezierCoords.hpp>
43 #include <com/sun/star/drawing/FlagSequence.hpp>
44 #include <com/sun/star/drawing/TextAdjust.hpp>
45 #include <com/sun/star/drawing/LineDash.hpp>
46 #include <com/sun/star/text/XText.hpp>
47 #include <com/sun/star/drawing/CircleKind.hpp>
48 #include <com/sun/star/drawing/FillStyle.hpp>
49 #include <com/sun/star/task/XStatusIndicator.hpp>
50 #include <comphelper/extract.hxx>
51 #include <svtools/fltcall.hxx>
52 #include <vcl/cvtgrf.hxx>
53 #include <com/sun/star/drawing/HomogenMatrix3.hpp>
54 #include <basegfx/matrix/b2dhommatrix.hxx>
55 #include <basegfx/polygon/b2dpolygontools.hxx>
56 #include <basegfx/polygon/b2dpolygon.hxx>
57 
58 using ::rtl::OUString;
59 using namespace ::com::sun::star;
60 using namespace ::com::sun::star::beans;
61 using namespace ::com::sun::star::container;
62 using namespace ::com::sun::star::uno;
63 using namespace ::com::sun::star::drawing;
64 using namespace ::com::sun::star::text;
65 using namespace ::com::sun::star::task;
66 using namespace ::com::sun::star::style;
67 
68 #define EES_MAP_FRACTION 1440   // 1440 dpi
69 
70 // ===================================================================
71 
ImplEESdrWriter(EscherEx & rEx)72 ImplEESdrWriter::ImplEESdrWriter( EscherEx& rEx )
73         :
74         mpEscherEx              ( &rEx ),
75         maMapModeSrc            ( MAP_100TH_MM ),
76         // PowerPoint: 576 dpi, WinWord: 1440 dpi, Excel: 1440 dpi
77         maMapModeDest( MAP_INCH, Point(), Fraction( 1, EES_MAP_FRACTION ), Fraction( 1, EES_MAP_FRACTION ) ),
78 //      mXStatusIndicator       ( rXStatInd ),
79         mpPicStrm               ( NULL ),
80         mpHostAppData           ( NULL ),
81         mnPagesWritten          ( 0 ),
82         mnShapeMasterTitle      ( 0 ),
83         mnShapeMasterBody       ( 0 ),
84         mbStatusIndicator       ( sal_False ),
85         mbStatus                ( sal_False )
86 {
87 }
88 
89 
90 // -------------------------------------------------------------------
91 
ImplMapPoint(const Point & rPoint)92 Point ImplEESdrWriter::ImplMapPoint( const Point& rPoint )
93 {
94     return OutputDevice::LogicToLogic( rPoint, maMapModeSrc, maMapModeDest );
95 }
96 
97 
98 // -------------------------------------------------------------------
99 
ImplMapSize(const Size & rSize)100 Size ImplEESdrWriter::ImplMapSize( const Size& rSize )
101 {
102     Size aRetSize( OutputDevice::LogicToLogic( rSize, maMapModeSrc, maMapModeDest ) );
103 
104     if ( !aRetSize.Width() )
105         aRetSize.Width()++;
106     if ( !aRetSize.Height() )
107         aRetSize.Height()++;
108     return aRetSize;
109 }
110 
111 // -------------------------------------------------------------------
112 
ImplFlipBoundingBox(ImplEESdrObject & rObj,EscherPropertyContainer & rPropOpt)113 void ImplEESdrWriter::ImplFlipBoundingBox( ImplEESdrObject& rObj, EscherPropertyContainer& rPropOpt )
114 {
115     sal_Int32 nAngle = rObj.GetAngle();
116     Rectangle aRect( rObj.GetRect() );
117 
118     if ( nAngle < 0 )
119         nAngle = ( 36000 + nAngle ) % 36000;
120     else
121         nAngle = ( 36000 - ( nAngle % 36000 ) );
122 
123     double fVal = (double)nAngle * F_PI18000;
124     double  fCos = cos( fVal );
125     double  fSin = sin( fVal );
126 
127     double  nWidthHalf = (double) aRect.GetWidth() / 2;
128     double  nHeightHalf = (double) aRect.GetHeight() / 2;
129 
130     double nXDiff = fCos * nWidthHalf + fSin * (-nHeightHalf);
131     double nYDiff = - ( fSin * nWidthHalf - fCos * ( -nHeightHalf ) );
132 
133     aRect.Move( (sal_Int32)( -( nWidthHalf - nXDiff ) ), (sal_Int32)( - ( nHeightHalf + nYDiff ) ) );
134 
135     nAngle *= 655;
136     nAngle += 0x8000;
137     nAngle &=~0xffff;                                   // nAngle auf volle Gradzahl runden
138     rPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
139 
140     rObj.SetAngle( nAngle );
141     rObj.SetRect( aRect );
142 }
143 
144 //  -----------------------------------------------------------------------
145 
146 #define ADD_SHAPE( nType, nFlags )                              \
147 {                                                               \
148     nShapeType = nType;                                         \
149     nShapeID = mpEscherEx->GenerateShapeId();                   \
150     rObj.SetShapeId( nShapeID );                                \
151     mpEscherEx->AddShape( (sal_uInt32)nType, (sal_uInt32)nFlags, nShapeID );    \
152     rSolverContainer.AddShape( rObj.GetShapeRef(), nShapeID );  \
153 }
154 
155 #define SHAPE_TEXT( bFill )                                         \
156 {                                                                   \
157     mpEscherEx->OpenContainer( ESCHER_SpContainer );                \
158     ADD_SHAPE( ESCHER_ShpInst_TextBox, 0xa00 );                     \
159     if ( bFill )                                                    \
160         aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );  \
161     if( rObj.ImplGetText() )                                        \
162         aPropOpt.CreateTextProperties( rObj.mXPropSet,              \
163             mpEscherEx->QueryTextID( rObj.GetShapeRef(),            \
164                 rObj.GetShapeId() ) );                              \
165 }
166 
167 //Map from twips to export units, generally twips as well, only excel and word
168 //export is happening here, so native units are export units, leave as
169 //placeholder if required in future
MapRect(ImplEESdrObject &)170 void ImplEESdrWriter::MapRect(ImplEESdrObject& /* rObj */ )
171 {
172 }
173 
ImplWriteShape(ImplEESdrObject & rObj,EscherSolverContainer & rSolverContainer,ImplEESdrPageType ePageType)174 sal_uInt32 ImplEESdrWriter::ImplWriteShape( ImplEESdrObject& rObj,
175                                 EscherSolverContainer& rSolverContainer,
176                                 ImplEESdrPageType ePageType )
177 {
178     sal_uInt32 nShapeID = 0;
179     sal_uInt16 nShapeType = 0;
180     sal_Bool bDontWriteText = sal_False;        // if a metafile is written as shape replacement, then the text is already part of the metafile
181     sal_Bool bAdditionalText = sal_False;
182     sal_uInt32 nGrpShapeID = 0;
183 
184     do {
185         mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : 0 );
186         if ( mpHostAppData && mpHostAppData->DontWriteShape() )
187             break;
188 
189         // #i51348# get shape name
190         String aShapeName;
191         if( const SdrObject* pSdrObj = rObj.GetSdrObject() )
192             if( pSdrObj->GetName().Len() > 0 )
193                 aShapeName = pSdrObj->GetName();
194 
195         Point aTextRefPoint;
196 
197         if( rObj.GetType().EqualsAscii( "drawing.Group" ))
198         {
199             Reference< XIndexAccess > xXIndexAccess( rObj.GetShapeRef(), UNO_QUERY );
200 
201             if( xXIndexAccess.is() && 0 != xXIndexAccess->getCount() )
202             {
203                 nShapeID = mpEscherEx->EnterGroup( aShapeName, &rObj.GetRect() );
204                 nShapeType = ESCHER_ShpInst_Min;
205 
206                 for( sal_uInt32 n = 0, nCnt = xXIndexAccess->getCount();
207                         n < nCnt; ++n )
208                 {
209                     ImplEESdrObject aObj( *this, *(Reference< XShape >*)
210                                     xXIndexAccess->getByIndex( n ).getValue() );
211                     if( aObj.IsValid() )
212                         ImplWriteShape( aObj, rSolverContainer, ePageType );
213                 }
214                 mpEscherEx->LeaveGroup();
215             }
216             break;
217         }
218         rObj.SetAngle( rObj.ImplGetInt32PropertyValue( ::rtl::OUString::createFromAscii("RotateAngle") ));
219 
220         if( ( rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("IsFontwork") ) &&
221             ::cppu::any2bool( rObj.GetUsrAny() ) ) ||
222             rObj.GetType().EqualsAscii( "drawing.Measure" ) || rObj.GetType().EqualsAscii( "drawing.Caption" ) )
223         {
224 /*
225             if( rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("BoundRect") ) )
226             {
227                 ::com::sun::star::awt::Rectangle aRect( *(::com::sun::star::awt::Rectangle*)rObj.GetUsrAny().getValue() );
228                 rObj.SetRect( ImplMapPoint( Point( aRect.X, aRect.Y ) ),
229                                 ImplMapSize( Size( aRect.Width, aRect.Height ) ) );
230             }
231 */
232             rObj.SetType( String( RTL_CONSTASCII_STRINGPARAM(
233                                 "drawing.dontknow" ),
234                                 RTL_TEXTENCODING_MS_1252 ));
235         }
236 
237         const ::com::sun::star::awt::Size   aSize100thmm( rObj.GetShapeRef()->getSize() );
238         const ::com::sun::star::awt::Point  aPoint100thmm( rObj.GetShapeRef()->getPosition() );
239         Rectangle   aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
240         if ( !mpPicStrm )
241             mpPicStrm = mpEscherEx->QueryPictureStream();
242         EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm );
243 
244         // #i51348# shape name
245         if( aShapeName.Len() > 0 )
246             aPropOpt.AddOpt( ESCHER_Prop_wzName, aShapeName );
247 
248         if ( rObj.GetType().EqualsAscii( "drawing.Custom" ) )
249         {
250             mpEscherEx->OpenContainer( ESCHER_SpContainer );
251             sal_uInt32 nMirrorFlags;
252 
253             rtl::OUString sCustomShapeType;
254             MSO_SPT eShapeType = aPropOpt.GetCustomShapeType( rObj.GetShapeRef(), nMirrorFlags, sCustomShapeType );
255             if ( sCustomShapeType.equalsAscii( "col-502ad400" ) || sCustomShapeType.equalsAscii( "col-60da8460" ) )
256             {
257                 ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
258                 if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ), sal_False ) )
259                 {
260                     aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
261                     aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );        // no fill
262                     aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );        // no linestyle
263                         SdrObject* pObj = GetSdrObjectFromXShape( rObj.GetShapeRef() );
264                     if ( pObj )
265                     {
266                         Rectangle aBound = pObj->GetCurrentBoundRect();
267                         Point aPosition( ImplMapPoint( aBound.TopLeft() ) );
268                         Size aSize( ImplMapSize( aBound.GetSize() ) );
269                         rObj.SetRect( Rectangle( aPosition, aSize ) );
270                         rObj.SetAngle( 0 );
271                         bDontWriteText = sal_True;
272                     }
273                 }
274             }
275             else
276             {
277                 ADD_SHAPE(
278                     sal::static_int_cast< sal_uInt16 >(eShapeType),
279                     nMirrorFlags | 0xa00 );
280                 aPropOpt.CreateCustomShapeProperties( eShapeType, rObj.GetShapeRef() );
281                 aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
282                 if ( rObj.ImplGetText() )
283                 {
284                     if ( !aPropOpt.IsFontWork() )
285                         aPropOpt.CreateTextProperties( rObj.mXPropSet, mpEscherEx->QueryTextID(
286                             rObj.GetShapeRef(), rObj.GetShapeId() ), sal_True, sal_False );
287                 }
288             }
289         }
290         else if ( rObj.GetType().EqualsAscii( "drawing.Rectangle" ))
291         {
292             mpEscherEx->OpenContainer( ESCHER_SpContainer );
293             sal_Int32 nRadius = (sal_Int32)rObj.ImplGetInt32PropertyValue(
294                                             ::rtl::OUString::createFromAscii("CornerRadius"));
295             if( nRadius )
296             {
297                 nRadius = ImplMapSize( Size( nRadius, 0 )).Width();
298                 ADD_SHAPE( ESCHER_ShpInst_RoundRectangle, 0xa00 );  // Flags: Connector | HasSpt
299                 sal_Int32 nLenght = rObj.GetRect().GetWidth();
300                 if ( nLenght > rObj.GetRect().GetHeight() )
301                     nLenght = rObj.GetRect().GetHeight();
302                 nLenght >>= 1;
303                 if ( nRadius >= nLenght )
304                     nRadius = 0x2a30;                           // 0x2a30 ist PPTs maximum radius
305                 else
306                     nRadius = ( 0x2a30 * nRadius ) / nLenght;
307                 aPropOpt.AddOpt( ESCHER_Prop_adjustValue, nRadius );
308             }
309             else
310             {
311                 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 );           // Flags: Connector | HasSpt
312             }
313             aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
314             if( rObj.ImplGetText() )
315                 aPropOpt.CreateTextProperties( rObj.mXPropSet,
316                     mpEscherEx->QueryTextID( rObj.GetShapeRef(),
317                         rObj.GetShapeId() ), sal_False, sal_False );
318         }
319         else if ( rObj.GetType().EqualsAscii( "drawing.Ellipse" ))
320         {
321             CircleKind  eCircleKind = CircleKind_FULL;
322             PolyStyle   ePolyKind = PolyStyle();
323             if ( rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("CircleKind") ) )
324             {
325                 eCircleKind = *( (CircleKind*)rObj.GetUsrAny().getValue() );
326                 switch ( eCircleKind )
327                 {
328                     case CircleKind_SECTION :
329                     {
330                         ePolyKind = POLY_PIE;
331                     }
332                     break;
333                     case CircleKind_ARC :
334                     {
335                         ePolyKind = POLY_ARC;
336                     }
337                     break;
338 
339                     case CircleKind_CUT :
340                     {
341                         ePolyKind = POLY_CHORD;
342                     }
343                     break;
344 
345                     default:
346                         eCircleKind = CircleKind_FULL;
347                 }
348             }
349             if ( eCircleKind == CircleKind_FULL )
350             {
351                 mpEscherEx->OpenContainer( ESCHER_SpContainer );
352                 ADD_SHAPE( ESCHER_ShpInst_Ellipse, 0xa00 );         // Flags: Connector | HasSpt
353                 aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );;
354             }
355             else
356             {
357                 sal_Int32 nStartAngle, nEndAngle;
358                 if ( !rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("CircleStartAngle") ) )
359                     break;
360                 nStartAngle = *( (sal_Int32*)rObj.GetUsrAny().getValue() );
361                 if( !rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("CircleEndAngle") ) )
362                     break;
363                 nEndAngle = *( (sal_Int32*)rObj.GetUsrAny().getValue() );
364 
365                 Point aStart, aEnd, aCenter;
366                 aStart.X() = (sal_Int32)( ( cos( (double)( nStartAngle *
367                                                 F_PI18000 ) ) * 100.0 ) );
368                 aStart.Y() = - (sal_Int32)( ( sin( (double)( nStartAngle *
369                                                 F_PI18000 ) ) * 100.0 ) );
370                 aEnd.X() = (sal_Int32)( ( cos( (double)( nEndAngle *
371                                                 F_PI18000 ) ) * 100.0 ) );
372                 aEnd.Y() = - (sal_Int32)( ( sin( (double)( nEndAngle *
373                                                 F_PI18000 ) ) * 100.0 ) );
374                 const Rectangle& rRect = aRect100thmm;
375                 aCenter.X() = rRect.Left() + ( rRect.GetWidth() / 2 );
376                 aCenter.Y() = rRect.Top() + ( rRect.GetHeight() / 2 );
377                 aStart.X() += aCenter.X();
378                 aStart.Y() += aCenter.Y();
379                 aEnd.X() += aCenter.X();
380                 aEnd.Y() += aCenter.Y();
381                 Polygon aPolygon( rRect, aStart, aEnd, ePolyKind );
382                 if( rObj.GetAngle() )
383                 {
384                     aPolygon.Rotate( rRect.TopLeft(), (sal_uInt16)( rObj.GetAngle() / 10 ) );
385                     rObj.SetAngle( 0 );
386                 }
387                 mpEscherEx->OpenContainer( ESCHER_SpContainer );
388                 ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 );        // Flags: Connector | HasSpt
389                 ::com::sun::star::awt::Rectangle aNewRect;
390                 switch ( ePolyKind )
391                 {
392                     case POLY_PIE :
393                     case POLY_CHORD :
394                     {
395                         aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_False, aNewRect, &aPolygon );
396                         aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True  );
397                     }
398                     break;
399 
400                     case POLY_ARC :
401                     {
402                         aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_False, aNewRect, &aPolygon );
403                         aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
404                     }
405                     break;
406                 }
407                 rObj.SetRect( Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ),
408                                             ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) );
409             }
410             if ( rObj.ImplGetText() )
411                 aPropOpt.CreateTextProperties( rObj.mXPropSet,
412                     mpEscherEx->QueryTextID( rObj.GetShapeRef(),
413                         rObj.GetShapeId() ), sal_False, sal_False );
414 
415         }
416         else if ( rObj.GetType().EqualsAscii( "drawing.Control" ))
417         {
418             break;
419         }
420         else if ( rObj.GetType().EqualsAscii( "drawing.Connector" ))
421         {
422             sal_uInt16 nSpType, nSpFlags;
423             ::com::sun::star::awt::Rectangle aNewRect;
424             if ( aPropOpt.CreateConnectorProperties( rObj.GetShapeRef(),
425                             rSolverContainer, aNewRect, nSpType, nSpFlags ) == sal_False )
426                 break;
427             rObj.SetRect( Rectangle( ImplMapPoint( Point( aNewRect.X, aNewRect.Y ) ),
428                                         ImplMapSize( Size( aNewRect.Width, aNewRect.Height ) ) ) );
429 
430             mpEscherEx->OpenContainer( ESCHER_SpContainer );
431             ADD_SHAPE( nSpType, nSpFlags );
432         }
433         else if ( rObj.GetType().EqualsAscii( "drawing.Measure" ))
434         {
435 /*
436             if ( ImplGetPropertyValue( L"MeasureKind" ) )
437             {
438                 mpEscherEx->EnterGroup( &maRect );
439                 mpEscherEx->OpenContainer( ESCHER_SpContainer );
440                 ImplWriteAny( ANY_FLAGS_LINE, sal_False );
441                 sal_uInt32 nFlags = 0xa00;                                          // Flags: Connector | HasSpt
442                 if ( maRect.Top() > maRect.Bottom() )
443                     nFlags |= 0x80;                                             // Flags: VertMirror
444                 if ( maRect.Left() > maRect.Right() )
445                     nFlags |= 0x40;                                             // Flags: HorzMirror
446 
447                 ADD_SHAPE( ESCHER_ShpInst_Line, nFlags );
448                 aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
449                 aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
450                 mpEscherEx->EndCount( ESCHER_OPT, 3 );
451                 maRect.Justify();
452                 mpEscherEx->AddClientAnchor( maRect );
453                 mpEscherEx->CloseContainer();           // ESCHER_SpContainer
454 
455                 if ( ImplGetPropertyValue( L"MeasureTextHorizontalPosition" ) )
456                 {
457                 }
458                 if ( ImplGetPropertyValue( L"MeasureTextVerticalPosition" ) )
459                 {
460                 }
461                 if ( ImplGetPropertyValue( L"MeasureLineDistance" ) )
462                 {
463                 }
464                 if ( ImplGetPropertyValue( L"MeasureHelpLineOverhang" ) )
465                 {
466                 }
467                 if ( ImplGetPropertyValue( L"MeasureHelpLineDistance" ) )
468                 {
469                 }
470                 if ( ImplGetPropertyValue( L"MeasureHelpLine1Length" ) )
471                 {
472                 }
473                 if ( ImplGetPropertyValue( L"MeasureHelpLine2Length" ) )
474                 {
475                 }
476                 if ( ImplGetPropertyValue( L"MeasureBelowReferenceEdge" ) )
477                 {
478                 }
479                 if ( ImplGetPropertyValue( L"MeasureTextRotate90" ) )
480                 {
481                 }
482                 if ( ImplGetPropertyValue( L"MeasureTextUpsideDown" ) )
483                 {
484                 }
485                 if ( ImplGetPropertyValue( L"MeasureOverhang" ) )
486                 {
487                 }
488                 if ( ImplGetPropertyValue( L"MeasureUnit" ) )
489                 {
490                 }
491                 if ( ImplGetPropertyValue( L"MeasureScale" ) )
492                 {
493                 }
494                 if ( ImplGetPropertyValue( L"MeasureShowUnit" ) )
495                 {
496                 }
497                 if ( ImplGetPropertyValue( L"MeasureFormatString" ) )
498                 {
499                 }
500                 if ( ImplGetPropertyValue( L"MeasureTextAutoAngle" ) )
501                 {
502                 }
503                 if ( ImplGetPropertyValue( L"MeasureTextAutoAngleView" ) )
504                 {
505                 }
506                 if ( ImplGetPropertyValue( L"MeasureTextIsFixedAngle" ) )
507                 {
508                 }
509                 if ( ImplGetPropertyValue( L"MeasureTextFixedAngle" ) )
510                 {
511                 }
512                 mpEscherEx->LeaveGroup();
513             }
514 */
515             break;
516         }
517         else if ( rObj.GetType().EqualsAscii( "drawing.Line" ))
518         {
519             ::com::sun::star::awt::Rectangle aNewRect;
520             aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_LINE, sal_False, aNewRect, NULL );
521             MapRect(rObj);
522             //i27942: Poly/Lines/Bezier do not support text.
523 
524             mpEscherEx->OpenContainer( ESCHER_SpContainer );
525             sal_uInt32 nFlags = 0xa00;          // Flags: Connector | HasSpt
526             if( aNewRect.Height < 0 )
527                 nFlags |= 0x80;             // Flags: VertMirror
528             if( aNewRect.Width < 0 )
529                 nFlags |= 0x40;             // Flags: HorzMirror
530 
531             ADD_SHAPE( ESCHER_ShpInst_Line, nFlags );
532             aPropOpt.AddOpt( ESCHER_Prop_shapePath, ESCHER_ShapeComplex );
533             aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
534             rObj.SetAngle( 0 );
535         }
536         else if ( rObj.GetType().EqualsAscii( "drawing.PolyPolygon" ))
537         {
538             if( rObj.ImplHasText() )
539             {
540                 nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() );
541                 bAdditionalText = sal_True;
542             }
543             mpEscherEx->OpenContainer( ESCHER_SpContainer );
544             ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 );        // Flags: Connector | HasSpt
545             ::com::sun::star::awt::Rectangle aNewRect;
546             aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_False, aNewRect, NULL );
547             MapRect(rObj);
548             aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
549             rObj.SetAngle( 0 );
550         }
551         else if ( rObj.GetType().EqualsAscii( "drawing.PolyLine" ))
552         {
553             //i27942: Poly/Lines/Bezier do not support text.
554 
555             mpEscherEx->OpenContainer( ESCHER_SpContainer );
556             ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 );        // Flags: Connector | HasSpt
557             ::com::sun::star::awt::Rectangle aNewRect;
558             aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_False, aNewRect, NULL );
559             MapRect(rObj);
560             aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
561             rObj.SetAngle( 0 );
562         }
563         else if ( rObj.GetType().EqualsAscii( "drawing.OpenBezier" ) )
564         {
565             //i27942: Poly/Lines/Bezier do not support text.
566 
567             mpEscherEx->OpenContainer( ESCHER_SpContainer );
568             ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 );        // Flags: Connector | HasSpt
569             ::com::sun::star::awt::Rectangle aNewRect;
570             aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYLINE, sal_True, aNewRect, NULL );
571             MapRect(rObj);
572             aPropOpt.CreateLineProperties( rObj.mXPropSet, sal_False );
573             rObj.SetAngle( 0 );
574         }
575         else if ( rObj.GetType().EqualsAscii( "drawing.ClosedBezier" ) )
576         {
577             if ( rObj.ImplHasText() )
578             {
579                 nGrpShapeID = ImplEnterAdditionalTextGroup( rObj.GetShapeRef(), &rObj.GetRect() );
580                 bAdditionalText = sal_True;
581             }
582             mpEscherEx->OpenContainer( ESCHER_SpContainer );
583             ADD_SHAPE( ESCHER_ShpInst_NotPrimitive, 0xa00 );        // Flags: Connector | HasSpt
584             ::com::sun::star::awt::Rectangle aNewRect;
585             aPropOpt.CreatePolygonProperties( rObj.mXPropSet, ESCHER_CREATEPOLYGON_POLYPOLYGON, sal_True, aNewRect, NULL );
586             MapRect(rObj);
587             aPropOpt.CreateFillProperties( rObj.mXPropSet, sal_True );
588             rObj.SetAngle( 0 );
589         }
590         else if ( rObj.GetType().EqualsAscii( "drawing.GraphicObject" ))
591         {
592             mpEscherEx->OpenContainer( ESCHER_SpContainer );
593 
594             // ein GraphicObject kann auch ein ClickMe Element sein
595             if( rObj.IsEmptyPresObj() && ( ePageType == NORMAL ) )
596             {
597                 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0x220 );               // Flags: HaveAnchor | HaveMaster
598                 sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(),
599                                                         rObj.GetShapeId() );
600                 aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId );
601                 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
602                 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
603                 aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
604             }
605             else
606             {
607                 if( rObj.ImplGetText() )
608                 {
609                     /* SJ #i34951#: because M. documents are not allowing GraphicObjects containing text, we
610                        have to create a simpe Rectangle with fill bitmap instead (while not allowing BitmapMode_Repeat).
611                     */
612                     ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 );           // Flags: Connector | HasSpt
613                     if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), sal_True,  sal_True, sal_False ) )
614                     {
615                         aPropOpt.AddOpt( ESCHER_Prop_WrapText, ESCHER_WrapNone );
616                         aPropOpt.AddOpt( ESCHER_Prop_AnchorText, ESCHER_AnchorMiddle );
617                         aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x140014 );
618                         aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x8000000 );
619                         aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x80000 );
620                         if ( rObj.ImplGetText() )
621                             aPropOpt.CreateTextProperties( rObj.mXPropSet,
622                                 mpEscherEx->QueryTextID( rObj.GetShapeRef(),
623                                     rObj.GetShapeId() ), sal_False, sal_False );
624                     }
625                 }
626                 else
627                 {
628                     ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
629                     if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "GraphicURL" ) ), sal_False, sal_True ) )
630                         aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
631                 }
632             }
633         }
634         else if ( rObj.GetType().EqualsAscii(  "drawing.Text" ))
635         {
636             SHAPE_TEXT( sal_True );
637         }
638         else if ( rObj.GetType().EqualsAscii( "drawing.Page" ))
639         {
640             mpEscherEx->OpenContainer( ESCHER_SpContainer );
641             ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0xa00 );
642             aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x40004 );
643             aPropOpt.AddOpt( ESCHER_Prop_fFillOK, 0x100001 );
644             aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x110011 );
645             aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90008 );
646             aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured, 0x10001 );
647         }
648         else if ( rObj.GetType().EqualsAscii( "drawing.Frame" ))
649         {
650             break;
651         }
652         else if ( rObj.GetType().EqualsAscii( "drawing.OLE2" ))
653         {
654             mpEscherEx->OpenContainer( ESCHER_SpContainer );
655             if( rObj.IsEmptyPresObj() && ( ePageType == NORMAL ) )
656             {
657                 ADD_SHAPE( ESCHER_ShpInst_Rectangle, 0x220 );               // Flags: HaveAnchor | HaveMaster
658                 sal_uInt32 nTxtBxId = mpEscherEx->QueryTextID( rObj.GetShapeRef(),
659                                                         rObj.GetShapeId() );
660                 aPropOpt.AddOpt( ESCHER_Prop_lTxid, nTxtBxId );
661                 aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x10001 );
662                 aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x10001 );
663                 aPropOpt.AddOpt( ESCHER_Prop_hspMaster, mnShapeMasterBody );
664             }
665             else
666             {
667                 //2do: could be made an option in HostAppData whether OLE object should be written or not
668                 sal_Bool bAppOLE = sal_True;
669                 ADD_SHAPE( ESCHER_ShpInst_PictureFrame,
670                     0xa00 | (bAppOLE ? SHAPEFLAG_OLESHAPE : 0) );
671                 if ( aPropOpt.CreateOLEGraphicProperties( rObj.GetShapeRef() ) )
672                 {
673                     if ( bAppOLE )
674                     {   // snooped from Xcl hex dump, nobody knows the trouble I have seen
675                         aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape,    0x00080008 );
676                         aPropOpt.AddOpt( ESCHER_Prop_pictureId,     0x00000001 );
677                         aPropOpt.AddOpt( ESCHER_Prop_fillColor,     0x08000041 );
678                         aPropOpt.AddOpt( ESCHER_Prop_fillBackColor, 0x08000041 );
679                         aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest,    0x00110010 );
680                         aPropOpt.AddOpt( ESCHER_Prop_lineColor,     0x08000040 );
681                         aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash,0x00080008 );
682 //                      aPropOpt.AddOpt( ESCHER_Prop_fshadowObscured,0x00020000 );
683                         aPropOpt.AddOpt( ESCHER_Prop_fPrint,            0x00080000 );
684                     }
685                     aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
686                 }
687             }
688         }
689         else if( '3' == rObj.GetType().GetChar(8 ) &&
690                  'D' == rObj.GetType().GetChar( 9 ) )   // drawing.3D
691         {
692             // SceneObject, CubeObject, SphereObject, LatheObject, ExtrudeObject, PolygonObject
693             if ( !rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("Bitmap") ) )
694                 break;
695 
696             mpEscherEx->OpenContainer( ESCHER_SpContainer );
697             ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
698 
699                 if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "Bitmap" ) ), sal_False ) )
700                 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
701         }
702         else if ( rObj.GetType().EqualsAscii( "drawing.dontknow" ))
703         {
704             rObj.SetAngle( 0 );
705             mpEscherEx->OpenContainer( ESCHER_SpContainer );
706             ADD_SHAPE( ESCHER_ShpInst_PictureFrame, 0xa00 );
707             if ( aPropOpt.CreateGraphicProperties( rObj.mXPropSet, String( RTL_CONSTASCII_USTRINGPARAM( "MetaFile" ) ), sal_False ) )
708                 aPropOpt.AddOpt( ESCHER_Prop_LockAgainstGrouping, 0x800080 );
709         }
710         else
711         {
712             break;
713         }
714         aPropOpt.CreateShadowProperties( rObj.mXPropSet );
715 
716         if( USHRT_MAX != mpEscherEx->GetHellLayerId() &&
717             rObj.ImplGetPropertyValue( ::rtl::OUString::createFromAscii("LayerID") ) &&
718             (*((sal_uInt16*)rObj.GetUsrAny().getValue()) ) == mpEscherEx->GetHellLayerId() )
719         {
720             aPropOpt.AddOpt( ESCHER_Prop_fPrint, 0x200020 );
721         }
722 
723         {
724             Rectangle aRect( rObj.GetRect() );
725             aRect.Justify();
726             rObj.SetRect( aRect );
727         }
728 
729         if( rObj.GetAngle() )
730             ImplFlipBoundingBox( rObj, aPropOpt );
731 
732         aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
733         mpEscherEx->Commit( aPropOpt, rObj.GetRect() );
734         if( mpEscherEx->GetGroupLevel() > 1 )
735             mpEscherEx->AddChildAnchor( rObj.GetRect() );
736 
737         if ( mpHostAppData )
738         {   //! with AdditionalText the App has to control whether these are written or not
739             mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() );
740             mpHostAppData->WriteClientData( *mpEscherEx );
741             if ( !bDontWriteText )
742                 mpHostAppData->WriteClientTextbox( *mpEscherEx );
743         }
744         mpEscherEx->CloseContainer();       // ESCHER_SpContainer
745 
746         if( bAdditionalText )
747         {
748             mpEscherEx->EndShape( nShapeType, nShapeID );
749             ImplWriteAdditionalText( rObj, aTextRefPoint );
750         }
751 
752     } while ( 0 );
753 
754     if ( bAdditionalText )
755         mpEscherEx->EndShape( ESCHER_ShpInst_Min, nGrpShapeID );
756     else
757         mpEscherEx->EndShape( nShapeType, nShapeID );
758     return nShapeID;
759 }
760 
ImplWriteAdditionalText(ImplEESdrObject & rObj,const Point & rTextRefPoint)761 void ImplEESdrWriter::ImplWriteAdditionalText( ImplEESdrObject& rObj,
762                                                 const Point& rTextRefPoint )
763 {
764     sal_uInt32 nShapeID = 0;
765     sal_uInt16 nShapeType = 0;
766     do
767     {
768         mpHostAppData = mpEscherEx->StartShape( rObj.GetShapeRef(), (mpEscherEx->GetGroupLevel() > 1) ? &rObj.GetRect() : 0 );
769         if ( mpHostAppData && mpHostAppData->DontWriteShape() )
770             break;
771 
772         const ::com::sun::star::awt::Size   aSize100thmm( rObj.GetShapeRef()->getSize() );
773         const ::com::sun::star::awt::Point  aPoint100thmm( rObj.GetShapeRef()->getPosition() );
774         Rectangle   aRect100thmm( Point( aPoint100thmm.X, aPoint100thmm.Y ), Size( aSize100thmm.Width, aSize100thmm.Height ) );
775         if ( !mpPicStrm )
776             mpPicStrm = mpEscherEx->QueryPictureStream();
777         EscherPropertyContainer aPropOpt( mpEscherEx->GetGraphicProvider(), mpPicStrm, aRect100thmm );
778         rObj.SetAngle( rObj.ImplGetInt32PropertyValue( ::rtl::OUString::createFromAscii("RotateAngle")));
779         sal_Int32 nAngle = rObj.GetAngle();
780         if( rObj.GetType().EqualsAscii( "drawing.Line" ))
781         {
782 //2do: this does not work right
783             double fDist = hypot( rObj.GetRect().GetWidth(),
784                                     rObj.GetRect().GetHeight() );
785             rObj.SetRect( Rectangle( rTextRefPoint,
786                             Point( (sal_Int32)( rTextRefPoint.X() + fDist ), rTextRefPoint.Y() - 1 ) ) );
787 
788             mpEscherEx->OpenContainer( ESCHER_SpContainer );
789             mpEscherEx->AddShape( ESCHER_ShpInst_TextBox, 0xa00 );
790             if ( rObj.ImplGetText() )
791                 aPropOpt.CreateTextProperties( rObj.mXPropSet,
792                     mpEscherEx->QueryTextID( rObj.GetShapeRef(),
793                         rObj.GetShapeId() ) );
794 
795             aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
796             aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
797             aPropOpt.AddOpt( ESCHER_Prop_FitTextToShape, 0x60006 );     // Size Shape To Fit Text
798             if ( nAngle < 0 )
799                 nAngle = ( 36000 + nAngle ) % 36000;
800             if ( nAngle )
801                 ImplFlipBoundingBox( rObj, aPropOpt );
802         }
803         else
804         {
805             mpEscherEx->OpenContainer( ESCHER_SpContainer );
806             nShapeID = mpEscherEx->GenerateShapeId();
807             mpEscherEx->AddShape( nShapeType = ESCHER_ShpInst_TextBox, 0xa00, nShapeID );
808             if ( rObj.ImplGetText() )
809                 aPropOpt.CreateTextProperties( rObj.mXPropSet,
810                     mpEscherEx->QueryTextID( rObj.GetShapeRef(),
811                         rObj.GetShapeId() ) );
812             aPropOpt.AddOpt( ESCHER_Prop_fNoLineDrawDash, 0x90000 );
813             aPropOpt.AddOpt( ESCHER_Prop_fNoFillHitTest, 0x100000 );
814 
815             if( nAngle < 0 )
816                 nAngle = ( 36000 + nAngle ) % 36000;
817             else
818                 nAngle = ( 36000 - ( nAngle % 36000 ) );
819 
820             nAngle *= 655;
821             nAngle += 0x8000;
822             nAngle &=~0xffff;   // nAngle auf volle Gradzahl runden
823             aPropOpt.AddOpt( ESCHER_Prop_Rotation, nAngle );
824             mpEscherEx->SetGroupSnapRect( mpEscherEx->GetGroupLevel(),
825                                             rObj.GetRect() );
826             mpEscherEx->SetGroupLogicRect( mpEscherEx->GetGroupLevel(),
827                                             rObj.GetRect() );
828         }
829         rObj.SetAngle( nAngle );
830         aPropOpt.CreateShapeProperties( rObj.GetShapeRef() );
831         mpEscherEx->Commit( aPropOpt, rObj.GetRect() );
832 
833         // write the childanchor
834         mpEscherEx->AddChildAnchor( rObj.GetRect() );
835 
836 #if defined EES_WRITE_EPP
837         // ClientAnchor
838         mpEscherEx->AddClientAnchor( maRect );
839         // ClientTextbox
840         mpEscherEx->OpenContainer( ESCHER_ClientTextbox );
841         mpEscherEx->AddAtom( 4, EPP_TextHeaderAtom );
842         *mpStrm << (sal_uInt32)EPP_TEXTTYPE_Other;                              // Text in a Shape
843         ImplWriteTextStyleAtom();
844         mpEscherEx->CloseContainer();   // ESCHER_ClientTextBox
845 #else // !EES_WRITE_EPP
846         if ( mpHostAppData )
847         {   //! the App has to control whether these are written or not
848             mpHostAppData->WriteClientAnchor( *mpEscherEx, rObj.GetRect() );
849             mpHostAppData->WriteClientData( *mpEscherEx );
850             mpHostAppData->WriteClientTextbox( *mpEscherEx );
851         }
852 #endif // EES_WRITE_EPP
853         mpEscherEx->CloseContainer();   // ESCHER_SpContainer
854     } while ( 0 );
855     mpEscherEx->LeaveGroup();
856     mpEscherEx->EndShape( nShapeType, nShapeID );
857 }
858 
859 
860 // -------------------------------------------------------------------
861 
ImplEnterAdditionalTextGroup(const Reference<XShape> & rShape,const Rectangle * pBoundRect)862 sal_uInt32 ImplEESdrWriter::ImplEnterAdditionalTextGroup( const Reference< XShape >& rShape,
863             const Rectangle* pBoundRect )
864 {
865     mpHostAppData = mpEscherEx->EnterAdditionalTextGroup();
866     sal_uInt32 nGrpId = mpEscherEx->EnterGroup( pBoundRect );
867     mpHostAppData = mpEscherEx->StartShape( rShape, pBoundRect );
868     return nGrpId;
869 }
870 
871 
872 // -------------------------------------------------------------------
873 
ImplInitPageValues()874 sal_Bool ImplEESdrWriter::ImplInitPageValues()
875 {
876     mnIndices = 0;
877     mnOutlinerCount = 0;                // die gliederungsobjekte muessen dem layout entsprechen,
878     mnEffectCount = 0;
879     mbIsTitlePossible = sal_True;           // bei mehr als einem title geht powerpoint in die knie
880 
881     return sal_True;
882 }
883 
884 
885 // -------------------------------------------------------------------
886 
ImplWritePage(EscherSolverContainer & rSolverContainer,ImplEESdrPageType ePageType,sal_Bool)887 void ImplEESdrWriter::ImplWritePage(
888             EscherSolverContainer& rSolverContainer,
889             ImplEESdrPageType ePageType, sal_Bool /* bBackGround */ )
890 {
891     ImplInitPageValues();
892 
893     sal_uInt32 nLastPer = 0, nShapes = mXShapes->getCount();
894     for( sal_uInt32 n = 0; n < nShapes; ++n )
895     {
896         sal_uInt32 nPer = ( 5 * n ) / nShapes;
897         if( nPer != nLastPer )
898         {
899             nLastPer = nPer;
900             sal_uInt32 nValue = mnPagesWritten * 5 + nPer;
901             if( nValue > mnStatMaxValue )
902                 nValue = mnStatMaxValue;
903             if( mbStatusIndicator )
904                 mXStatusIndicator->setValue( nValue );
905         }
906 
907         ImplEESdrObject aObj( *this, *(Reference< XShape >*)
908                                     mXShapes->getByIndex( n ).getValue() );
909         if( aObj.IsValid() )
910         {
911             ImplWriteShape( aObj, rSolverContainer, ePageType );
912         }
913     }
914     mnPagesWritten++;
915 }
916 
917 // ===================================================================
918 
ImplEscherExSdr(EscherEx & rEx)919 ImplEscherExSdr::ImplEscherExSdr( EscherEx& rEx )
920         :
921         ImplEESdrWriter( rEx ),
922         mpSdrPage( NULL ),
923         mpSolverContainer( NULL )
924 {
925 }
926 
927 
928 // -------------------------------------------------------------------
929 
~ImplEscherExSdr()930 ImplEscherExSdr::~ImplEscherExSdr()
931 {
932     DBG_ASSERT( !mpSolverContainer, "ImplEscherExSdr::~ImplEscherExSdr: unwritten SolverContainer" );
933     delete mpSolverContainer;
934 }
935 
936 
937 // -------------------------------------------------------------------
938 
ImplInitPage(const SdrPage & rPage)939 bool ImplEscherExSdr::ImplInitPage( const SdrPage& rPage )
940 {
941     do
942     {
943         SvxDrawPage* pSvxDrawPage;
944         if ( mpSdrPage != &rPage || !mXDrawPage.is() )
945         {
946             // eventually write SolverContainer of current page, deletes the Solver
947             ImplFlushSolverContainer();
948 
949             mpSdrPage = NULL;
950             // why not declare a const parameter if the object will not be modified?
951 //          mXDrawPage = pSvxDrawPage = new SvxDrawPage( (SdrPage*) &rPage );
952             mXDrawPage = pSvxDrawPage = new SvxFmDrawPage( (SdrPage*) &rPage );
953             mXShapes = Reference< XShapes >::query( mXDrawPage );
954             if ( !mXShapes.is() )
955                 break;
956             if ( !ImplInitPageValues() )    // ImplEESdrWriter
957                 break;
958             mpSdrPage = &rPage;
959 
960             mpSolverContainer = new EscherSolverContainer;
961         }
962         else
963             pSvxDrawPage = SvxDrawPage::getImplementation(mXDrawPage);
964 
965         return pSvxDrawPage != 0;
966     } while ( 0 );
967 
968     return false;
969 }
970 
971 // -------------------------------------------------------------------
972 
ImplInitUnoShapes(const Reference<XShapes> & rxShapes)973 bool ImplEscherExSdr::ImplInitUnoShapes( const Reference< XShapes >& rxShapes )
974 {
975     // eventually write SolverContainer of current page, deletes the Solver
976     ImplFlushSolverContainer();
977 
978     if( !rxShapes.is() )
979         return false;
980 
981     mpSdrPage = 0;
982     mXDrawPage.clear();
983     mXShapes = rxShapes;
984 
985     if( !ImplInitPageValues() )    // ImplEESdrWriter
986         return false;
987 
988     mpSolverContainer = new EscherSolverContainer;
989     return true;
990 }
991 
992 // -------------------------------------------------------------------
993 
ImplExitPage()994 void ImplEscherExSdr::ImplExitPage()
995 {
996     // close all groups before the solver container is written
997     while( mpEscherEx->GetGroupLevel() )
998         mpEscherEx->LeaveGroup();
999 
1000     ImplFlushSolverContainer();
1001     mpSdrPage = NULL;   // reset page for next init
1002 }
1003 
1004 
1005 // -------------------------------------------------------------------
1006 
ImplFlushSolverContainer()1007 void ImplEscherExSdr::ImplFlushSolverContainer()
1008 {
1009     if ( mpSolverContainer )
1010     {
1011         mpSolverContainer->WriteSolver( mpEscherEx->GetStream() );
1012         delete mpSolverContainer;
1013         mpSolverContainer = NULL;
1014     }
1015 }
1016 
1017 
1018 // -------------------------------------------------------------------
1019 
ImplWriteCurrentPage()1020 void ImplEscherExSdr::ImplWriteCurrentPage()
1021 {
1022     DBG_ASSERT( mpSolverContainer, "ImplEscherExSdr::ImplWriteCurrentPage: no SolverContainer" );
1023     ImplWritePage( *mpSolverContainer, NORMAL );
1024     ImplExitPage();
1025 }
1026 
1027 
1028 // -------------------------------------------------------------------
1029 
ImplWriteTheShape(ImplEESdrObject & rObj)1030 sal_uInt32 ImplEscherExSdr::ImplWriteTheShape( ImplEESdrObject& rObj )
1031 {
1032     DBG_ASSERT( mpSolverContainer, "ImplEscherExSdr::ImplWriteShape: no SolverContainer" );
1033     return ImplWriteShape( rObj, *mpSolverContainer, NORMAL );
1034 }
1035 
1036 
1037 // ===================================================================
1038 
AddSdrPage(const SdrPage & rPage)1039 void EscherEx::AddSdrPage( const SdrPage& rPage )
1040 {
1041     if ( mpImplEscherExSdr->ImplInitPage( rPage ) )
1042         mpImplEscherExSdr->ImplWriteCurrentPage();
1043 }
1044 
1045 // -------------------------------------------------------------------
1046 
AddUnoShapes(const Reference<XShapes> & rxShapes)1047 void EscherEx::AddUnoShapes( const Reference< XShapes >& rxShapes )
1048 {
1049     if ( mpImplEscherExSdr->ImplInitUnoShapes( rxShapes ) )
1050         mpImplEscherExSdr->ImplWriteCurrentPage();
1051 }
1052 
1053 // -------------------------------------------------------------------
1054 
AddSdrObject(const SdrObject & rObj)1055 sal_uInt32 EscherEx::AddSdrObject( const SdrObject& rObj )
1056 {
1057     ImplEESdrObject aObj( *mpImplEscherExSdr, rObj );
1058     if( aObj.IsValid() )
1059         return mpImplEscherExSdr->ImplWriteTheShape( aObj );
1060     return 0;
1061 }
1062 
1063 
1064 // -------------------------------------------------------------------
1065 
EndSdrObjectPage()1066 void EscherEx::EndSdrObjectPage()
1067 {
1068     mpImplEscherExSdr->ImplExitPage();
1069 }
1070 
1071 // -------------------------------------------------------------------
1072 
StartShape(const Reference<XShape> &,const Rectangle *)1073 EscherExHostAppData* EscherEx::StartShape( const Reference< XShape >& /* rShape */, const Rectangle* /*pChildAnchor*/ )
1074 {
1075     return NULL;
1076 }
1077 
1078 // -------------------------------------------------------------------
1079 
EndShape(sal_uInt16,sal_uInt32)1080 void EscherEx::EndShape( sal_uInt16 /* nShapeType */, sal_uInt32 /* nShapeID */ )
1081 {
1082 }
1083 
1084 // -------------------------------------------------------------------
1085 
QueryTextID(const Reference<XShape> &,sal_uInt32)1086 sal_uInt32 EscherEx::QueryTextID( const Reference< XShape >&, sal_uInt32 )
1087 {
1088     return 0;
1089 }
1090 
1091 // -------------------------------------------------------------------
1092 // add an dummy rectangle shape into the escher stream
AddDummyShape()1093 sal_uInt32 EscherEx::AddDummyShape()
1094 {
1095     OpenContainer( ESCHER_SpContainer );
1096     sal_uInt32 nShapeID = GenerateShapeId();
1097     AddShape( ESCHER_ShpInst_Rectangle, 0xa00, nShapeID );
1098 //??    aSolverContainer.AddShape( mXShape, nShapeID );
1099     CloseContainer();
1100 
1101     return nShapeID;
1102 }
1103 
1104 // -------------------------------------------------------------------
1105 
1106 // static
GetSdrObject(const Reference<XShape> & rShape)1107 const SdrObject* EscherEx::GetSdrObject( const Reference< XShape >& rShape )
1108 {
1109     const SdrObject* pRet = 0;
1110     const SvxShape* pSvxShape = SvxShape::getImplementation( rShape );
1111     DBG_ASSERT( pSvxShape, "EscherEx::GetSdrObject: no SvxShape" );
1112     if( pSvxShape )
1113     {
1114         pRet = pSvxShape->GetSdrObject();
1115         DBG_ASSERT( pRet, "EscherEx::GetSdrObject: no SdrObj" );
1116     }
1117     return pRet;
1118 }
1119 
1120 
1121 // -------------------------------------------------------------------
1122 
ImplEESdrObject(ImplEscherExSdr & rEx,const SdrObject & rObj)1123 ImplEESdrObject::ImplEESdrObject( ImplEscherExSdr& rEx,
1124                                     const SdrObject& rObj ) :
1125     mnShapeId( 0 ),
1126     mnTextSize( 0 ),
1127     mnAngle( 0 ),
1128     mbValid( sal_False ),
1129     mbPresObj( sal_False ),
1130     mbEmptyPresObj( sal_False )
1131 {
1132     SdrPage* pPage = rObj.GetPage();
1133     DBG_ASSERT( pPage, "ImplEESdrObject::ImplEESdrObject: no SdrPage" );
1134     if( pPage && rEx.ImplInitPage( *pPage ) )
1135     {
1136         // why not declare a const parameter if the object will
1137         // not be modified?
1138         mXShape = uno::Reference< drawing::XShape >::query( ((SdrObject*)&rObj)->getUnoShape() );;
1139         Init( rEx );
1140     }
1141 }
1142 
ImplEESdrObject(ImplEESdrWriter & rEx,const Reference<XShape> & rShape)1143 ImplEESdrObject::ImplEESdrObject( ImplEESdrWriter& rEx,
1144                                     const Reference< XShape >& rShape ) :
1145     mXShape( rShape ),
1146     mnShapeId( 0 ),
1147     mnTextSize( 0 ),
1148     mnAngle( 0 ),
1149     mbValid( sal_False ),
1150     mbPresObj( sal_False ),
1151     mbEmptyPresObj( sal_False )
1152 {
1153     Init( rEx );
1154 }
1155 
1156 
~ImplEESdrObject()1157 ImplEESdrObject::~ImplEESdrObject()
1158 {
1159 }
1160 
getUnrotatedGroupBoundRange(const Reference<XShape> & rxShape)1161 basegfx::B2DRange getUnrotatedGroupBoundRange(const Reference< XShape >& rxShape)
1162 {
1163     basegfx::B2DRange aRetval;
1164 
1165     try
1166     {
1167         if(rxShape.is())
1168         {
1169             if(rxShape->getShapeType().equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("com.sun.star.drawing.GroupShape")))
1170             {
1171                 // it's a group shape, iterate over children
1172                 const Reference< XIndexAccess > xXIndexAccess(rxShape, UNO_QUERY);
1173 
1174                 if(xXIndexAccess.is())
1175                 {
1176                     for(sal_uInt32 n(0), nCnt = xXIndexAccess->getCount(); n < nCnt; ++n)
1177                     {
1178                         const Reference< XShape > axShape(xXIndexAccess->getByIndex(n), UNO_QUERY);
1179 
1180                         if(axShape.is())
1181                         {
1182                             // we are calculating the bound for a group, correct rotation for sub-objects
1183                             // to get the unrotated bounds for the group
1184                             const basegfx::B2DRange aExtend(getUnrotatedGroupBoundRange(axShape));
1185 
1186                             aRetval.expand(aExtend);
1187                         }
1188                     }
1189                 }
1190             }
1191             else
1192             {
1193                 // iT#s a xShape, get it's transformation
1194                 const Reference< XPropertySet > mXPropSet(rxShape, UNO_QUERY);
1195 
1196                 if(mXPropSet.is())
1197                 {
1198                     const Any aAny = mXPropSet->getPropertyValue(OUString(RTL_CONSTASCII_USTRINGPARAM("Transformation")));
1199 
1200                     if(aAny.hasValue())
1201                     {
1202                         HomogenMatrix3 aMatrix;
1203 
1204                         if(aAny >>= aMatrix)
1205                         {
1206                             basegfx::B2DHomMatrix aHomogenMatrix;
1207 
1208                             aHomogenMatrix.set(0, 0, aMatrix.Line1.Column1);
1209                             aHomogenMatrix.set(0, 1, aMatrix.Line1.Column2);
1210                             aHomogenMatrix.set(0, 2, aMatrix.Line1.Column3);
1211                             aHomogenMatrix.set(1, 0, aMatrix.Line2.Column1);
1212                             aHomogenMatrix.set(1, 1, aMatrix.Line2.Column2);
1213                             aHomogenMatrix.set(1, 2, aMatrix.Line2.Column3);
1214                             aHomogenMatrix.set(2, 0, aMatrix.Line3.Column1);
1215                             aHomogenMatrix.set(2, 1, aMatrix.Line3.Column2);
1216                             aHomogenMatrix.set(2, 2, aMatrix.Line3.Column3);
1217 
1218                             basegfx::B2DVector aScale, aTranslate;
1219                             double fRotate, fShearX;
1220 
1221                             // decopose transformation
1222                             aHomogenMatrix.decompose(aScale, aTranslate, fRotate, fShearX);
1223 
1224                             // check if rotation needs to be corrected
1225                             if(!basegfx::fTools::equalZero(fRotate))
1226                             {
1227                                 // to correct, keep in mind that ppt graphics are rotated around their center
1228                                 const basegfx::B2DPoint aCenter(aHomogenMatrix * basegfx::B2DPoint(0.5, 0.5));
1229 
1230                                 aHomogenMatrix.translate(-aCenter.getX(), -aCenter.getY());
1231                                 aHomogenMatrix.rotate(-fRotate);
1232                                 aHomogenMatrix.translate(aCenter.getX(), aCenter.getY());
1233                             }
1234 
1235 
1236                             // check if shear needs to be corrected (always correct shear,
1237                             // ppt does not know about it)
1238                             if(!basegfx::fTools::equalZero(fShearX))
1239                             {
1240                                 const basegfx::B2DPoint aMinimum(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
1241 
1242                                 aHomogenMatrix.translate(-aMinimum.getX(), -aMinimum.getY());
1243                                 aHomogenMatrix.shearX(-fShearX);
1244                                 aHomogenMatrix.translate(aMinimum.getX(), aMinimum.getY());
1245                             }
1246 
1247                             // create range. It's no longer rotated (or sheared), so use
1248                             // minimum and maximum values
1249                             aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(0.0, 0.0));
1250                             aRetval.expand(aHomogenMatrix * basegfx::B2DPoint(1.0, 1.0));
1251                         }
1252                     }
1253                 }
1254             }
1255         }
1256     }
1257     catch(::com::sun::star::uno::Exception&)
1258     {
1259     }
1260 
1261     return aRetval;
1262 }
1263 
Init(ImplEESdrWriter & rEx)1264 void ImplEESdrObject::Init( ImplEESdrWriter& rEx )
1265 {
1266     mXPropSet = Reference< XPropertySet >::query( mXShape );
1267     if( mXPropSet.is() )
1268     {
1269         static const sal_Char aPrefix[] = "com.sun.star.";
1270         static const xub_StrLen nPrefix = sizeof(aPrefix)-1;
1271 
1272         // detect name first to make below test (is group) work
1273         mType = String( mXShape->getShapeType() );
1274         mType.Erase( 0, nPrefix );  // strip "com.sun.star."
1275         xub_StrLen nPos = mType.SearchAscii( "Shape" );
1276         mType.Erase( nPos, 5 );
1277 
1278         if(GetType().EqualsAscii("drawing.Group"))
1279         {
1280             // if it's a group, the unrotated range is needed for that group
1281             const basegfx::B2DRange aUnroatedRange(getUnrotatedGroupBoundRange(mXShape));
1282             const Point aNewP(basegfx::fround(aUnroatedRange.getMinX()), basegfx::fround(aUnroatedRange.getMinY()));
1283             const Size aNewS(basegfx::fround(aUnroatedRange.getWidth()), basegfx::fround(aUnroatedRange.getHeight()));
1284 
1285             SetRect(rEx.ImplMapPoint(aNewP), rEx.ImplMapSize(aNewS));
1286         }
1287         else
1288         {
1289             // if it's no group, use position and size directly, roated/sheared or not
1290             const Point aOldP(mXShape->getPosition().X, mXShape->getPosition().Y);
1291             const Size aOldS(mXShape->getSize().Width, mXShape->getSize().Height);
1292 
1293             SetRect(rEx.ImplMapPoint(aOldP), rEx.ImplMapSize(aOldS));
1294         }
1295 
1296 
1297         static const OUString sPresStr(rtl::OUString::createFromAscii("IsPresentationObject"));
1298         static const OUString sEmptyPresStr(rtl::OUString::createFromAscii("IsEmptyPresentationObject"));
1299 
1300         if( ImplGetPropertyValue( sPresStr ) )
1301             mbPresObj = ::cppu::any2bool( mAny );
1302 
1303         if( mbPresObj && ImplGetPropertyValue( sEmptyPresStr ) )
1304             mbEmptyPresObj = ::cppu::any2bool( mAny );
1305 
1306         mbValid = sal_True;
1307     }
1308 }
1309 
1310 //sal_Bool ImplEESdrObject::ImplGetPropertyValue( const OUString& rString )
ImplGetPropertyValue(const sal_Unicode * rString)1311 sal_Bool ImplEESdrObject::ImplGetPropertyValue( const sal_Unicode* rString )
1312 {
1313     sal_Bool bRetValue = sal_False;
1314     if( mbValid )
1315     {
1316         try
1317         {
1318             mAny = mXPropSet->getPropertyValue( rString );
1319             if( mAny.hasValue() )
1320                 bRetValue = sal_True;
1321         }
1322         catch( ::com::sun::star::uno::Exception& )
1323         {
1324             bRetValue = sal_False;
1325         }
1326     }
1327     return bRetValue;
1328 }
1329 
1330 #ifdef USED
ImplGetPropertyValue(const Reference<XPropertySet> & rXPropSet,const OUString & rString)1331 sal_Bool ImplEESdrObject::ImplGetPropertyValue( const Reference< XPropertySet >& rXPropSet,
1332                                             const OUString& rString )
1333 {
1334     sal_Bool bRetValue = sal_False;
1335     if( mbValid )
1336     {
1337         try
1338         {
1339             mAny = rXPropSet->getPropertyValue( rString );
1340             if( 0 != mAny.get() )
1341                 bRetValue = sal_True;
1342         }
1343         catch( ::com::sun::star::uno::Exception& )
1344         {
1345             bRetValue = sal_False;
1346         }
1347     }
1348     return bRetValue;
1349 }
1350 #endif
1351 
SetRect(const Point & rPos,const Size & rSz)1352 void ImplEESdrObject::SetRect( const Point& rPos, const Size& rSz )
1353 {
1354     maRect = Rectangle( rPos, rSz );
1355 }
1356 
GetSdrObject() const1357 const SdrObject* ImplEESdrObject::GetSdrObject() const
1358 {
1359     return EscherEx::GetSdrObject( mXShape );
1360 }
1361 
1362 //  laedt und konvertiert text aus shape, ergebnis ist mnTextSize gespeichert
ImplGetText()1363 sal_uInt32 ImplEESdrObject::ImplGetText()
1364 {
1365     Reference< XText > xXText( mXShape, UNO_QUERY );
1366     mnTextSize = 0;
1367     if( xXText.is() )
1368         mnTextSize = xXText->getString().getLength();
1369     return mnTextSize;
1370 }
1371 
ImplHasText() const1372 sal_Bool ImplEESdrObject::ImplHasText() const
1373 {
1374     Reference< XText > xXText( mXShape, UNO_QUERY );
1375     return xXText.is() && xXText->getString().getLength();
1376 }
1377 
1378