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/helper/vclunohelper.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