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