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