xref: /core/filter/source/msfilter/msdffimp.cxx (revision 979aed6b)
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 <com/sun/star/embed/Aspects.hpp>
21 #include <com/sun/star/embed/XEmbeddedObject.hpp>
22 
23 #include <math.h>
24 #include <limits.h>
25 #include <vector>
26 #include <osl/endian.h>
27 #include <osl/file.hxx>
28 #include <tools/solar.h>
29 #include <rtl/math.hxx>
30 #include <sal/log.hxx>
31 
32 #include <comphelper/classids.hxx>
33 #include <toolkit/helper/vclunohelper.hxx>
34 #include <unotools/configmgr.hxx>
35 #include <unotools/streamwrap.hxx>
36 #include <comphelper/processfactory.hxx>
37 #include <comphelper/string.hxx>
38 #include <comphelper/seqstream.hxx>
39 #include <comphelper/storagehelper.hxx>
40 #include <comphelper/sequence.hxx>
41 #include <sot/exchange.hxx>
42 #include <sot/storinfo.hxx>
43 #include <vcl/cvtgrf.hxx>
44 #include <vcl/wmf.hxx>
45 #include <vcl/settings.hxx>
46 #include <vcl/vclptr.hxx>
47 #include <vcl/BitmapTools.hxx>
48 #include "viscache.hxx"
49 
50 // SvxItem-Mapping. Is needed to successfully include the SvxItem-Header
51 #include <editeng/eeitem.hxx>
52 #include <editeng/editdata.hxx>
53 #include <svl/urihelper.hxx>
54 #include <tools/stream.hxx>
55 #include <tools/debug.hxx>
56 #include <tools/zcodec.hxx>
57 #include <unotools/ucbstreamhelper.hxx>
58 #include <filter/msfilter/escherex.hxx>
59 #include <basegfx/range/b2drange.hxx>
60 #include <com/sun/star/container/XIdentifierContainer.hpp>
61 #include <com/sun/star/drawing/XGluePointsSupplier.hpp>
62 #include <com/sun/star/drawing/Position3D.hpp>
63 #include <com/sun/star/drawing/Direction3D.hpp>
64 #include <com/sun/star/drawing/GluePoint2.hpp>
65 #include <com/sun/star/drawing/XShapes.hpp>
66 #include <editeng/charscaleitem.hxx>
67 #include <editeng/kernitem.hxx>
68 #include <vcl/graphicfilter.hxx>
69 #include <tools/urlobj.hxx>
70 #include <vcl/virdev.hxx>
71 #include <vcl/bitmapaccess.hxx>
72 #include <sot/storage.hxx>
73 #include <sfx2/docfac.hxx>
74 #include <sfx2/docfilt.hxx>
75 #include <sfx2/docfile.hxx>
76 #include <sfx2/fcontnr.hxx>
77 #include <sfx2/module.hxx>
78 #include <svx/sdgcpitm.hxx>
79 #include <svx/sdgmoitm.hxx>
80 #include <editeng/tstpitem.hxx>
81 #include <svx/fmmodel.hxx>
82 #include <svx/svdmodel.hxx>
83 #include <svx/svdobj.hxx>
84 #include <svx/svdpage.hxx>
85 #include <svx/svdogrp.hxx>
86 #include <svx/svdograf.hxx>
87 #include <svx/svdotext.hxx>
88 #include <svx/svdorect.hxx>
89 #include <svx/svdocapt.hxx>
90 #include <svx/svdoedge.hxx>
91 #include <svx/svdocirc.hxx>
92 #include <svx/svdoutl.hxx>
93 #include <svx/svdoole2.hxx>
94 #include <svx/svdopath.hxx>
95 #include <editeng/frmdir.hxx>
96 #include <editeng/frmdiritem.hxx>
97 #include <svx/svdtrans.hxx>
98 #include <svx/sxenditm.hxx>
99 #include <svx/sdgluitm.hxx>
100 #include <editeng/fhgtitem.hxx>
101 #include <editeng/wghtitem.hxx>
102 #include <editeng/postitem.hxx>
103 #include <editeng/udlnitem.hxx>
104 #include <editeng/crossedoutitem.hxx>
105 #include <editeng/shdditem.hxx>
106 #include <editeng/fontitem.hxx>
107 #include <editeng/colritem.hxx>
108 #include <svx/sxekitm.hxx>
109 #include <editeng/bulletitem.hxx>
110 #include <svx/extrud3d.hxx>
111 #include <svx/svditer.hxx>
112 #include <svx/xpoly.hxx>
113 #include <svx/xattr.hxx>
114 #include <filter/msfilter/classids.hxx>
115 #include <filter/msfilter/msdffimp.hxx>
116 #include <editeng/outliner.hxx>
117 #include <editeng/outlobj.hxx>
118 #include <editeng/editobj.hxx>
119 #include <editeng/editeng.hxx>
120 #include <svx/gallery.hxx>
121 #include <com/sun/star/drawing/ShadeMode.hpp>
122 #include <svl/itempool.hxx>
123 #include <vcl/dibtools.hxx>
124 #include <vcl/svapp.hxx>
125 #include <svx/svx3ditems.hxx>
126 #include <svx/svdoashp.hxx>
127 #include <svx/EnhancedCustomShapeTypeNames.hxx>
128 #include <svx/EnhancedCustomShapeGeometry.hxx>
129 #include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
130 #include <com/sun/star/drawing/EnhancedCustomShapeParameterType.hpp>
131 #include <com/sun/star/drawing/EnhancedCustomShapeSegment.hpp>
132 #include <com/sun/star/drawing/EnhancedCustomShapeGluePointType.hpp>
133 #include <com/sun/star/drawing/EnhancedCustomShapeSegmentCommand.hpp>
134 #include <com/sun/star/drawing/EnhancedCustomShapeTextFrame.hpp>
135 #include <com/sun/star/drawing/EnhancedCustomShapeAdjustmentValue.hpp>
136 #include <com/sun/star/drawing/EnhancedCustomShapeTextPathMode.hpp>
137 #include <com/sun/star/beans/PropertyValues.hpp>
138 #include <com/sun/star/drawing/ProjectionMode.hpp>
139 #include <svx/EnhancedCustomShape2d.hxx>
140 #include <svx/xbitmap.hxx>
141 #include <rtl/strbuf.hxx>
142 #include <rtl/ustring.hxx>
143 #include <svtools/embedhlp.hxx>
144 #include <memory>
145 
146 using namespace ::com::sun::star    ;
147 using namespace ::com::sun::star::drawing;
148 using namespace uno                 ;
149 using namespace beans               ;
150 using namespace drawing             ;
151 using namespace container           ;
152 
153 // static counter for OLE-Objects
154 static sal_uInt32 nMSOleObjCntr = 0;
155 #define MSO_OLE_Obj "MSO_OLE_Obj"
156 
157 struct SvxMSDffBLIPInfo
158 {
159     sal_uLong  nFilePos;    ///< offset of the BLIP in data strem
160     explicit SvxMSDffBLIPInfo(sal_uLong nFPos)
161         : nFilePos(nFPos)
162     {
163     }
164 };
165 
166 /// the following will be sorted by the order of their appearance:
167 struct SvxMSDffBLIPInfos : public std::vector<SvxMSDffBLIPInfo> {};
168 
169 /************************************************************************/
170 void Impl_OlePres::Write( SvStream & rStm )
171 {
172     WriteClipboardFormat( rStm, SotClipboardFormatId::GDIMETAFILE );
173     rStm.WriteInt32( 4 );       // a TargetDevice that's always empty
174     rStm.WriteUInt32( nAspect );
175     rStm.WriteInt32( -1 );      //L-Index always -1
176     rStm.WriteInt32( nAdvFlags );
177     rStm.WriteInt32( 0 );       //Compression
178     rStm.WriteInt32( aSize.Width() );
179     rStm.WriteInt32( aSize.Height() );
180     sal_uLong nPos = rStm.Tell();
181     rStm.WriteInt32( 0 );
182 
183     if( nFormat == SotClipboardFormatId::GDIMETAFILE && pMtf )
184     {
185         // Always to 1/100 mm, until Mtf-Solution found
186         // Assumption (no scaling, no origin translation)
187         DBG_ASSERT( pMtf->GetPrefMapMode().GetScaleX() == Fraction( 1, 1 ),
188                     "x-scale in the Mtf is wrong" );
189         DBG_ASSERT( pMtf->GetPrefMapMode().GetScaleY() == Fraction( 1, 1 ),
190                     "y-scale in the Mtf is wrong" );
191         DBG_ASSERT( pMtf->GetPrefMapMode().GetOrigin() == Point(),
192                     "origin-shift in the Mtf is wrong" );
193         MapUnit nMU = pMtf->GetPrefMapMode().GetMapUnit();
194         if( MapUnit::Map100thMM != nMU )
195         {
196             Size aPrefS( pMtf->GetPrefSize() );
197             Size aS( aPrefS );
198             aS = OutputDevice::LogicToLogic(aS, MapMode(nMU), MapMode(MapUnit::Map100thMM));
199 
200             pMtf->Scale( Fraction( aS.Width(), aPrefS.Width() ),
201                          Fraction( aS.Height(), aPrefS.Height() ) );
202             pMtf->SetPrefMapMode(MapMode(MapUnit::Map100thMM));
203             pMtf->SetPrefSize( aS );
204         }
205         WriteWindowMetafileBits( rStm, *pMtf );
206     }
207     else
208     {
209         OSL_FAIL( "unknown format" );
210     }
211     sal_uLong nEndPos = rStm.Tell();
212     rStm.Seek( nPos );
213     rStm.WriteUInt32( nEndPos - nPos - 4 );
214     rStm.Seek( nEndPos );
215 }
216 
217 DffPropertyReader::DffPropertyReader( const SvxMSDffManager& rMan )
218     : rManager(rMan)
219     , mnFix16Angle(0)
220     , mbRotateGranientFillWithAngle(false)
221 {
222     InitializePropSet( DFF_msofbtOPT );
223 }
224 
225 void DffPropertyReader::SetDefaultPropSet( SvStream& rStCtrl, sal_uInt32 nOffsDgg ) const
226 {
227     const_cast<DffPropertyReader*>(this)->pDefaultPropSet.reset();
228     sal_uInt32 nMerk = rStCtrl.Tell();
229     bool bOk = checkSeek(rStCtrl, nOffsDgg);
230     DffRecordHeader aRecHd;
231     if (bOk)
232         bOk = ReadDffRecordHeader( rStCtrl, aRecHd );
233     if (bOk && aRecHd.nRecType == DFF_msofbtDggContainer)
234     {
235         if ( SvxMSDffManager::SeekToRec( rStCtrl, DFF_msofbtOPT, aRecHd.GetRecEndFilePos() ) )
236         {
237             const_cast<DffPropertyReader*>(this)->pDefaultPropSet.reset( new DffPropSet );
238             ReadDffPropSet( rStCtrl, *pDefaultPropSet );
239         }
240     }
241     rStCtrl.Seek( nMerk );
242 }
243 
244 #ifdef DBG_CUSTOMSHAPE
245 void DffPropertyReader::ReadPropSet( SvStream& rIn, SvxMSDffClientData* pClientData, sal_uInt32 nShapeId ) const
246 #else
247 void DffPropertyReader::ReadPropSet( SvStream& rIn, SvxMSDffClientData* pClientData ) const
248 #endif
249 {
250     sal_uLong nFilePos = rIn.Tell();
251     ReadDffPropSet( rIn, const_cast<DffPropertyReader&>(*this) );
252 
253     if ( IsProperty( DFF_Prop_hspMaster ) )
254     {
255         if ( rManager.SeekToShape( rIn, pClientData, GetPropertyValue( DFF_Prop_hspMaster, 0 ) ) )
256         {
257             DffRecordHeader aRecHd;
258             bool bOk = ReadDffRecordHeader(rIn, aRecHd);
259             if (bOk && SvxMSDffManager::SeekToRec(rIn, DFF_msofbtOPT, aRecHd.GetRecEndFilePos()))
260             {
261                 rIn |= const_cast<DffPropertyReader&>(*this);
262             }
263         }
264     }
265 
266     const_cast<DffPropertyReader*>(this)->mnFix16Angle = Fix16ToAngle( GetPropertyValue( DFF_Prop_Rotation, 0 ) );
267 
268 #ifdef DBG_CUSTOMSHAPE
269 
270     OUString aURLStr;
271 
272     if( osl::FileBase::getFileURLFromSystemPath( OUString("d:\\ashape.dbg"), aURLStr ) == osl::FileBase::E_None )
273     {
274         std::unique_ptr<SvStream> xOut(::utl::UcbStreamHelper::CreateStream( aURLStr, StreamMode::WRITE ));
275 
276         if( xOut )
277         {
278             xOut->Seek( STREAM_SEEK_TO_END );
279 
280             if ( IsProperty( DFF_Prop_adjustValue ) || IsProperty( DFF_Prop_pVertices ) )
281             {
282                 xOut->WriteLine( "" );
283                 OString aString("ShapeId: " + OString::number(nShapeId));
284                 xOut->WriteLine(aString);
285             }
286             for ( sal_uInt32 i = DFF_Prop_adjustValue; i <= DFF_Prop_adjust10Value; i++ )
287             {
288                 if ( IsProperty( i ) )
289                 {
290                     OString aString("Prop_adjustValue" + OString::number( ( i - DFF_Prop_adjustValue ) + 1 ) +
291                                     ":" + OString::number(GetPropertyValue(i)) );
292                     xOut->WriteLine(aString);
293                 }
294             }
295             sal_Int32 i;
296             for ( i = 320; i < 383; i++ )
297             {
298                 if ( ( i >= DFF_Prop_adjustValue ) && ( i <= DFF_Prop_adjust10Value ) )
299                     continue;
300                 if ( IsProperty( i ) )
301                 {
302                     if ( SeekToContent( i, rIn ) )
303                     {
304                         sal_Int32 nLen = (sal_Int32)GetPropertyValue( i );
305                         if ( nLen )
306                         {
307                             xOut->WriteLine( "" );
308                             OStringBuffer aDesc("Property:" + OString::number(i) +
309                                                 "  Size:" + OString::number(nLen));
310                             xOut->WriteLine(aDesc.makeStringAndClear());
311                             sal_Int16   nNumElem, nNumElemMem, nNumSize;
312                             rIn >> nNumElem >> nNumElemMem >> nNumSize;
313                             aDesc.append("Entries: " + OString::number(nNumElem) +
314                                          "  Size:" + OString::number(nNumSize));
315                             xOut->WriteLine(aDesc.makeStringAndClear());
316                             if ( nNumSize < 0 )
317                                 nNumSize = ( ( -nNumSize ) >> 2 );
318                             if ( !nNumSize )
319                                 nNumSize = 16;
320                             nLen -= 6;
321                             while ( nLen > 0 )
322                             {
323                                 for ( sal_uInt32 j = 0; nLen && ( j < ( nNumSize >> 1 ) ); j++ )
324                                 {
325                                     for ( sal_uInt32 k = 0; k < 2; k++ )
326                                     {
327                                         if ( nLen )
328                                         {
329                                             sal_uInt8 nVal;
330                                             rIn >> nVal;
331                                             if ( ( nVal >> 4 ) > 9 )
332                                                 *xOut << (sal_uInt8)( ( nVal >> 4 ) + 'A' - 10 );
333                                             else
334                                                 *xOut << (sal_uInt8)( ( nVal >> 4 ) + '0' );
335 
336                                             if ( ( nVal & 0xf ) > 9 )
337                                                 *xOut << (sal_uInt8)( ( nVal & 0xf ) + 'A' - 10 );
338                                             else
339                                                 *xOut << (sal_uInt8)( ( nVal & 0xf ) + '0' );
340 
341                                             nLen--;
342                                         }
343                                     }
344                                     *xOut << (char)( ' ' );
345                                 }
346                                 xOut->WriteLine( OString() );
347                             }
348                         }
349                     }
350                     else
351                     {
352                         OString aString("Property" + OString::number(i) +
353                                         ":" + OString::number(GetPropertyValue(i)));
354                         xOut->WriteLine(aString);
355                     }
356                 }
357             }
358         }
359     }
360 
361 #endif
362 
363     rIn.Seek( nFilePos );
364 }
365 
366 
367 sal_Int32 DffPropertyReader::Fix16ToAngle( sal_Int32 nContent )
368 {
369     sal_Int32 nAngle = 0;
370     if ( nContent )
371     {
372         nAngle = ( static_cast<sal_Int16>( nContent >> 16) * 100L ) + ( ( ( nContent & 0x0000ffff) * 100L ) >> 16 );
373         nAngle = NormAngle36000( -nAngle );
374     }
375     return nAngle;
376 }
377 
378 DffPropertyReader::~DffPropertyReader()
379 {
380 }
381 
382 
383 static SvStream& operator>>( SvStream& rIn, SvxMSDffConnectorRule& rRule )
384 {
385     sal_uInt32 nRuleId;
386     rIn.ReadUInt32( nRuleId )
387        .ReadUInt32( rRule.nShapeA )
388        .ReadUInt32( rRule.nShapeB )
389        .ReadUInt32( rRule.nShapeC )
390        .ReadUInt32( rRule.ncptiA )
391        .ReadUInt32( rRule.ncptiB );
392 
393     return rIn;
394 }
395 
396 SvxMSDffSolverContainer::SvxMSDffSolverContainer()
397 {
398 }
399 
400 SvxMSDffSolverContainer::~SvxMSDffSolverContainer()
401 {
402 }
403 
404 SvStream& ReadSvxMSDffSolverContainer( SvStream& rIn, SvxMSDffSolverContainer& rContainer )
405 {
406     DffRecordHeader aHd;
407     bool bOk = ReadDffRecordHeader( rIn, aHd );
408     if (bOk && aHd.nRecType == DFF_msofbtSolverContainer)
409     {
410         DffRecordHeader aCRule;
411         auto nEndPos = DffPropSet::SanitizeEndPos(rIn, aHd.GetRecEndFilePos());
412         while ( rIn.good() && ( rIn.Tell() < nEndPos ) )
413         {
414             if (!ReadDffRecordHeader(rIn, aCRule))
415                 break;
416             if ( aCRule.nRecType == DFF_msofbtConnectorRule )
417             {
418                 std::unique_ptr<SvxMSDffConnectorRule> pRule(new SvxMSDffConnectorRule);
419                 rIn >> *pRule;
420                 rContainer.aCList.push_back( std::move(pRule) );
421             }
422             if (!aCRule.SeekToEndOfRecord(rIn))
423                 break;
424         }
425     }
426     return rIn;
427 }
428 
429 void SvxMSDffManager::SolveSolver( const SvxMSDffSolverContainer& rSolver )
430 {
431     size_t i, nCnt;
432     for ( i = 0, nCnt = rSolver.aCList.size(); i < nCnt; i++ )
433     {
434         SvxMSDffConnectorRule* pPtr = rSolver.aCList[ i ].get();
435         if ( pPtr->pCObj )
436         {
437             for ( int nN = 0; nN < 2; nN++ )
438             {
439                 SdrObject*  pO;
440                 sal_uInt32  nC;
441                 ShapeFlag   nSpFlags;
442                 if ( !nN )
443                 {
444                     pO = pPtr->pAObj;
445                     nC = pPtr->ncptiA;
446                     nSpFlags = pPtr->nSpFlagsA;
447                 }
448                 else
449                 {
450                     pO = pPtr->pBObj;
451                     nC = pPtr->ncptiB;
452                     nSpFlags = pPtr->nSpFlagsB;
453                 }
454                 if ( pO )
455                 {
456                     SdrGluePoint aGluePoint;
457                     Reference< XShape > aXShape( pO->getUnoShape(), UNO_QUERY );
458                     Reference< XShape > aXConnector( pPtr->pCObj->getUnoShape(), UNO_QUERY );
459                     SdrGluePointList* pList = pO->ForceGluePointList();
460 
461                     sal_Int32 nId = nC;
462                     SdrInventor nInventor = pO->GetObjInventor();
463 
464                     if( nInventor == SdrInventor::Default )
465                     {
466                         bool bValidGluePoint = false;
467                         sal_uInt32 nObjId = pO->GetObjIdentifier();
468                         switch( nObjId )
469                         {
470                             case OBJ_GRUP :
471                             case OBJ_GRAF :
472                             case OBJ_RECT :
473                             case OBJ_TEXT :
474                             case OBJ_PAGE :
475                             case OBJ_TITLETEXT :
476                             case OBJ_OUTLINETEXT :
477                             {
478                                 if ( nC & 1 )
479                                 {
480                                     if ( nSpFlags & ShapeFlag::FlipH )
481                                         nC ^= 2;    // 1 <-> 3
482                                 }
483                                 else
484                                 {
485                                     if ( nSpFlags & ShapeFlag::FlipV )
486                                         nC ^= 1;    // 0 <-> 2
487                                 }
488                                 switch( nC )
489                                 {
490                                     case 0 :
491                                         nId = 0;    // SdrAlign::VERT_TOP;
492                                     break;
493                                     case 1 :
494                                         nId = 3;    // SdrAlign::HORZ_RIGHT;
495                                     break;
496                                     case 2 :
497                                         nId = 2;    // SdrAlign::VERT_BOTTOM;
498                                     break;
499                                     case 3 :
500                                         nId = 1; // SdrAlign::HORZ_LEFT;
501                                     break;
502                                 }
503                                 if ( nId <= 3 )
504                                     bValidGluePoint = true;
505                             }
506                             break;
507                             case OBJ_POLY :
508                             case OBJ_PLIN :
509                             case OBJ_LINE :
510                             case OBJ_PATHLINE :
511                             case OBJ_PATHFILL :
512                             case OBJ_FREELINE :
513                             case OBJ_FREEFILL :
514                             case OBJ_SPLNLINE :
515                             case OBJ_SPLNFILL :
516                             case OBJ_PATHPOLY :
517                             case OBJ_PATHPLIN :
518                             {
519                                 if (pList)
520                                 {
521                                     if (pList->GetCount() > nC )
522                                     {
523                                         bValidGluePoint = true;
524                                         nId = static_cast<sal_Int32>((*pList)[ static_cast<sal_uInt16>(nC)].GetId() + 3 );
525                                     }
526                                     else
527                                     {
528                                         bool bNotFound = true;
529 
530                                         tools::PolyPolygon aPolyPoly( EscherPropertyContainer::GetPolyPolygon( aXShape ) );
531                                         sal_uInt16 k, j, nPolySize = aPolyPoly.Count();
532                                         if ( nPolySize )
533                                         {
534                                             tools::Rectangle aBoundRect( aPolyPoly.GetBoundRect() );
535                                             if ( aBoundRect.GetWidth() && aBoundRect.GetHeight() )
536                                             {
537                                                 sal_uInt32  nPointCount = 0;
538                                                 for ( k = 0; bNotFound && ( k < nPolySize ); k++ )
539                                                 {
540                                                     const tools::Polygon& rPolygon = aPolyPoly.GetObject( k );
541                                                     for ( j = 0; bNotFound && ( j < rPolygon.GetSize() ); j++ )
542                                                     {
543                                                         PolyFlags eFlags = rPolygon.GetFlags( j );
544                                                         if ( eFlags == PolyFlags::Normal )
545                                                         {
546                                                             if ( nC == nPointCount )
547                                                             {
548                                                                 const Point& rPoint = rPolygon.GetPoint( j );
549                                                                 double fXRel = rPoint.X() - aBoundRect.Left();
550                                                                 double fYRel = rPoint.Y() - aBoundRect.Top();
551                                                                 sal_Int32 nWidth = aBoundRect.GetWidth();
552                                                                 if ( !nWidth )
553                                                                     nWidth = 1;
554                                                                 sal_Int32 nHeight= aBoundRect.GetHeight();
555                                                                 if ( !nHeight )
556                                                                     nHeight = 1;
557                                                                 fXRel /= static_cast<double>(nWidth);
558                                                                 fXRel *= 10000;
559                                                                 fYRel /= static_cast<double>(nHeight);
560                                                                 fYRel *= 10000;
561                                                                 aGluePoint.SetPos( Point( static_cast<sal_Int32>(fXRel), static_cast<sal_Int32>(fYRel) ) );
562                                                                 aGluePoint.SetPercent( true );
563                                                                 aGluePoint.SetAlign( SdrAlign::VERT_TOP | SdrAlign::HORZ_LEFT );
564                                                                 aGluePoint.SetEscDir( SdrEscapeDirection::SMART );
565                                                                 nId = static_cast<sal_Int32>((*pList)[ pList->Insert( aGluePoint ) ].GetId() + 3 );
566                                                                 bNotFound = false;
567                                                             }
568                                                             nPointCount++;
569                                                         }
570                                                     }
571                                                 }
572                                             }
573                                         }
574                                         if ( !bNotFound )
575                                         {
576                                             bValidGluePoint = true;
577                                         }
578                                     }
579                                 }
580                             }
581                             break;
582 
583                             case OBJ_CUSTOMSHAPE :
584                             {
585                                 const SfxPoolItem& aCustomShape =  static_cast<SdrObjCustomShape*>(pO)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY );
586                                 SdrCustomShapeGeometryItem aGeometryItem( static_cast<const SdrCustomShapeGeometryItem&>(aCustomShape) );
587                                 const OUString sPath( "Path" );
588                                 const OUString sGluePointType( "GluePointType" );
589                                 sal_Int16 nGluePointType = EnhancedCustomShapeGluePointType::SEGMENTS;
590                                 css::uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sPath, sGluePointType );
591                                 if ( pAny )
592                                     *pAny >>= nGluePointType;
593                                 else
594                                 {
595                                     const OUString sType( "Type" );
596                                     OUString sShapeType;
597                                     pAny = aGeometryItem.GetPropertyValueByName( sType );
598                                     if ( pAny )
599                                         *pAny >>= sShapeType;
600                                     MSO_SPT eSpType = EnhancedCustomShapeTypeNames::Get( sShapeType );
601                                     nGluePointType = GetCustomShapeConnectionTypeDefault( eSpType );
602                                 }
603                                 if ( nGluePointType == EnhancedCustomShapeGluePointType::CUSTOM )
604                                 {
605                                     if ( pList && ( pList->GetCount() > nC ) )
606                                     {
607                                         bValidGluePoint = true;
608                                         nId = static_cast<sal_Int32>((*pList)[ static_cast<sal_uInt16>(nC)].GetId() + 3 );
609                                     }
610                                 }
611                                 else if ( nGluePointType == EnhancedCustomShapeGluePointType::RECT )
612                                 {
613                                     if ( nC & 1 )
614                                     {
615                                         if ( nSpFlags & ShapeFlag::FlipH )
616                                             nC ^= 2;    // 1 <-> 3
617                                     }
618                                     else
619                                     {
620                                         if ( nSpFlags & ShapeFlag::FlipV )
621                                             nC ^= 1;    // 0 <-> 2
622                                     }
623                                     switch( nC )
624                                     {
625                                         case 0 :
626                                             nId = 0;    // SdrAlign::VERT_TOP;
627                                         break;
628                                         case 1 :
629                                             nId = 3;    // SdrAlign::HORZ_RIGHT;
630                                         break;
631                                         case 2 :
632                                             nId = 2;    // SdrAlign::VERT_BOTTOM;
633                                         break;
634                                         case 3 :
635                                             nId = 1; // SdrAlign::HORZ_LEFT;
636                                         break;
637                                     }
638                                     if ( nId <= 3 )
639                                         bValidGluePoint = true;
640                                 }
641                                 else if ( nGluePointType == EnhancedCustomShapeGluePointType::SEGMENTS )
642                                 {
643                                     const OUString sSegments( "Segments" );
644                                     const OUString sCoordinates( "Coordinates" );
645 
646                                     sal_uInt32 k, nPt = nC;
647                                     css::uno::Sequence< css::drawing::EnhancedCustomShapeSegment > aSegments;
648                                     pAny = aGeometryItem.GetPropertyValueByName( sPath, sSegments );
649                                     if ( pAny && (*pAny >>= aSegments) )
650                                     {
651                                         for ( nPt = 0, k = 1; nC && ( k < static_cast<sal_uInt32>(aSegments.getLength()) ); k++ )
652                                         {
653                                             sal_Int16 j, nCnt2 = aSegments[ k ].Count;
654                                             if ( aSegments[ k ].Command != EnhancedCustomShapeSegmentCommand::UNKNOWN )
655                                             {
656                                                 for ( j = 0; nC && ( j < nCnt2 ); j++ )
657                                                 {
658                                                     switch( aSegments[ k ].Command )
659                                                     {
660                                                         case EnhancedCustomShapeSegmentCommand::ENDSUBPATH :
661                                                         case EnhancedCustomShapeSegmentCommand::CLOSESUBPATH :
662                                                         case EnhancedCustomShapeSegmentCommand::LINETO :
663                                                         case EnhancedCustomShapeSegmentCommand::MOVETO :
664                                                         {
665                                                             nC--;
666                                                             nPt++;
667                                                         }
668                                                         break;
669                                                         case EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX :
670                                                         case EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY :
671                                                         break;
672 
673                                                         case EnhancedCustomShapeSegmentCommand::CURVETO :
674                                                         {
675                                                             nC--;
676                                                             nPt += 3;
677                                                         }
678                                                         break;
679 
680                                                         case EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO :
681                                                         case EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE :
682                                                         {
683                                                             nC--;
684                                                             nPt += 3;
685                                                         }
686                                                         break;
687                                                         case EnhancedCustomShapeSegmentCommand::ARCTO :
688                                                         case EnhancedCustomShapeSegmentCommand::ARC :
689                                                         case EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO :
690                                                         case EnhancedCustomShapeSegmentCommand::CLOCKWISEARC :
691                                                         {
692                                                             nC--;
693                                                             nPt += 4;
694                                                         }
695                                                         break;
696                                                     }
697                                                 }
698                                             }
699                                         }
700                                     }
701                                     pAny = aGeometryItem.GetPropertyValueByName( sPath, sCoordinates );
702                                     if ( pAny )
703                                     {
704                                         css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
705                                         *pAny >>= aCoordinates;
706                                         if ( nPt < static_cast<sal_uInt32>(aCoordinates.getLength()) )
707                                         {
708                                             nId = 4;
709                                             css::drawing::EnhancedCustomShapeParameterPair& rPara = aCoordinates[ nPt ];
710                                             sal_Int32 nX = 0, nY = 0;
711                                             if ( ( rPara.First.Value >>= nX ) && ( rPara.Second.Value >>= nY ) )
712                                             {
713                                                 const OUString sGluePoints( "GluePoints" );
714                                                 css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aGluePoints;
715                                                 pAny = aGeometryItem.GetPropertyValueByName( sPath, sGluePoints );
716                                                 if ( pAny )
717                                                     *pAny >>= aGluePoints;
718                                                 sal_Int32 nGluePoints = aGluePoints.getLength();
719                                                 aGluePoints.realloc( nGluePoints + 1 );
720                                                 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ nGluePoints ].First, nX );
721                                                 EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ nGluePoints ].Second, nY );
722                                                 PropertyValue aProp;
723                                                 aProp.Name = sGluePoints;
724                                                 aProp.Value <<= aGluePoints;
725                                                 aGeometryItem.SetPropertyValue( sPath, aProp );
726                                                 bValidGluePoint = true;
727                                                 static_cast<SdrObjCustomShape*>(pO)->SetMergedItem( aGeometryItem );
728                                                 SdrGluePointList* pLst = pO->ForceGluePointList();
729                                                 if ( pLst->GetCount() > nGluePoints )
730                                                     nId = static_cast<sal_Int32>((*pLst)[ static_cast<sal_uInt16>(nGluePoints) ].GetId() + 3 );
731                                             }
732                                         }
733                                     }
734                                 }
735                             }
736                             break;
737                         }
738                         if ( bValidGluePoint )
739                         {
740                             Reference< XPropertySet > xPropSet( aXConnector, UNO_QUERY );
741                             if ( xPropSet.is() )
742                             {
743                                 if ( nN )
744                                 {
745                                     OUString aPropName( "EndShape" );
746                                     SetPropValue( Any(aXShape), xPropSet, aPropName );
747                                     aPropName = "EndGluePointIndex";
748                                     SetPropValue( Any(nId), xPropSet, aPropName );
749                                 }
750                                 else
751                                 {
752                                     OUString aPropName( "StartShape" );
753                                     SetPropValue( Any(aXShape), xPropSet, aPropName );
754                                     aPropName = "StartGluePointIndex";
755                                     SetPropValue( Any(nId), xPropSet, aPropName );
756                                 }
757 
758                                 // Not sure what this is good for, repaint or broadcast of object change.
759                                 //( Thus I am adding repaint here
760                                 pO->SetChanged();
761                                 pO->BroadcastObjectChange();
762                             }
763                         }
764                     }
765                 }
766             }
767         }
768     }
769 }
770 
771 
772 static basegfx::B2DPolyPolygon GetLineArrow( const sal_Int32 nLineWidth, const MSO_LineEnd eLineEnd,
773     const MSO_LineEndWidth eLineWidth, const MSO_LineEndLength eLineLength,
774     sal_Int32& rnArrowWidth, bool& rbArrowCenter,
775     OUString& rsArrowName, bool bScaleArrow )
776 {
777     basegfx::B2DPolyPolygon aRetPolyPoly;
778     // 70 100mm = 2pt = 40 twip. In MS, line width less than 2pt has the same size arrow as 2pt
779     //If the unit is twip. Make all use this unit especially the critical value 70/40.
780     sal_Int32   nLineWidthCritical = bScaleArrow ? 40 : 70;
781     double      fLineWidth = nLineWidth < nLineWidthCritical ? nLineWidthCritical : nLineWidth;
782 
783     double      fLengthMul, fWidthMul;
784     sal_Int32   nLineNumber;
785     switch( eLineLength )
786     {
787         default :
788         case mso_lineMediumLenArrow     : fLengthMul = 3.0; nLineNumber = 2; break;
789         case mso_lineShortArrow         : fLengthMul = 2.0; nLineNumber = 1; break;
790         case mso_lineLongArrow          : fLengthMul = 5.0; nLineNumber = 3; break;
791     }
792     switch( eLineWidth )
793     {
794         default :
795         case mso_lineMediumWidthArrow   : fWidthMul = 3.0; nLineNumber += 3; break;
796         case mso_lineNarrowArrow        : fWidthMul = 2.0; break;
797         case mso_lineWideArrow          : fWidthMul = 5.0; nLineNumber += 6; break;
798     }
799 
800     rbArrowCenter = false;
801     OUStringBuffer aArrowName;
802     switch ( eLineEnd )
803     {
804         case mso_lineArrowEnd :
805         {
806             basegfx::B2DPolygon aTriangle;
807             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50, 0.0 ));
808             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth, fLengthMul * fLineWidth ));
809             aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth ));
810             aTriangle.setClosed(true);
811             aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
812             aArrowName.append("msArrowEnd ");
813         }
814         break;
815 
816         case mso_lineArrowOpenEnd :
817         {
818             switch( eLineLength )
819             {
820                 default :
821                 case mso_lineMediumLenArrow     : fLengthMul = 4.5; break;
822                 case mso_lineShortArrow         : fLengthMul = 3.5; break;
823                 case mso_lineLongArrow          : fLengthMul = 6.0; break;
824             }
825             switch( eLineWidth )
826             {
827                 default :
828                 case mso_lineMediumWidthArrow   : fWidthMul = 4.5; break;
829                 case mso_lineNarrowArrow        : fWidthMul = 3.5; break;
830                 case mso_lineWideArrow          : fWidthMul = 6.0; break;
831             }
832             basegfx::B2DPolygon aTriangle;
833             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 ));
834             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth, fLengthMul * fLineWidth * 0.91 ));
835             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.85, fLengthMul * fLineWidth ));
836             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50, fLengthMul * fLineWidth * 0.36 ));
837             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.15, fLengthMul * fLineWidth ));
838             aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth * 0.91 ));
839             aTriangle.setClosed(true);
840             aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
841             aArrowName.append("msArrowOpenEnd ");
842         }
843         break;
844         case mso_lineArrowStealthEnd :
845         {
846             basegfx::B2DPolygon aTriangle;
847             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 ));
848             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth , fLengthMul * fLineWidth ));
849             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , fLengthMul * fLineWidth * 0.60 ));
850             aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth ));
851             aTriangle.setClosed(true);
852             aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
853             aArrowName.append("msArrowStealthEnd ");
854         }
855         break;
856         case mso_lineArrowDiamondEnd :
857         {
858             basegfx::B2DPolygon aTriangle;
859             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , 0.0 ));
860             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth , fLengthMul * fLineWidth * 0.50 ));
861             aTriangle.append(basegfx::B2DPoint( fWidthMul * fLineWidth * 0.50 , fLengthMul * fLineWidth ));
862             aTriangle.append(basegfx::B2DPoint( 0.0, fLengthMul * fLineWidth * 0.50 ));
863             aTriangle.setClosed(true);
864             aRetPolyPoly = basegfx::B2DPolyPolygon(aTriangle);
865             rbArrowCenter = true;
866             aArrowName.append("msArrowDiamondEnd ");
867         }
868         break;
869         case mso_lineArrowOvalEnd :
870         {
871             aRetPolyPoly = basegfx::B2DPolyPolygon( XPolygon( Point( static_cast<sal_Int32>( fWidthMul * fLineWidth * 0.50 ), 0 ),
872                                 static_cast<sal_Int32>( fWidthMul * fLineWidth * 0.50 ),
873                                     static_cast<sal_Int32>( fLengthMul * fLineWidth * 0.50 ), 0, 3600 ).getB2DPolygon() );
874             rbArrowCenter = true;
875             aArrowName.append("msArrowOvalEnd ");
876         }
877         break;
878         default: break;
879     }
880     aArrowName.append(nLineNumber);
881     rsArrowName = aArrowName.makeStringAndClear();
882     rnArrowWidth = static_cast<sal_Int32>( fLineWidth * fWidthMul );
883 
884     return aRetPolyPoly;
885 }
886 
887 void DffPropertyReader::ApplyLineAttributes( SfxItemSet& rSet, const MSO_SPT eShapeType ) const // #i28269#
888 {
889     sal_uInt32 nLineFlags(GetPropertyValue( DFF_Prop_fNoLineDrawDash, 0 ));
890 
891     if(!IsHardAttribute( DFF_Prop_fLine ) && !IsCustomShapeStrokedByDefault( eShapeType ))
892     {
893         nLineFlags &= ~0x08;
894     }
895 
896     if ( nLineFlags & 8 )
897     {
898         // Line Attributes
899         sal_Int32 nLineWidth = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_lineWidth, 9525 ));
900 
901         // support LineCap
902         const MSO_LineCap eLineCap(static_cast<MSO_LineCap>(GetPropertyValue(DFF_Prop_lineEndCapStyle, mso_lineEndCapSquare)));
903 
904         switch(eLineCap)
905         {
906             default: /* case mso_lineEndCapFlat */
907             {
908                 // no need to set, it is the default. If this changes, this needs to be activated
909                 // rSet.Put(XLineCapItem(css::drawing::LineCap_BUTT));
910                 break;
911             }
912             case mso_lineEndCapRound:
913             {
914                 rSet.Put(XLineCapItem(css::drawing::LineCap_ROUND));
915                 break;
916             }
917             case mso_lineEndCapSquare:
918             {
919                 rSet.Put(XLineCapItem(css::drawing::LineCap_SQUARE));
920                 break;
921             }
922         }
923 
924         MSO_LineDashing eLineDashing = static_cast<MSO_LineDashing>(GetPropertyValue( DFF_Prop_lineDashing, mso_lineSolid ));
925         if (eLineDashing == mso_lineSolid || nLineWidth < 0)
926             rSet.Put(XLineStyleItem( drawing::LineStyle_SOLID ) );
927         else
928         {
929             sal_uInt16  nDots = 1;
930             sal_uInt32  nDotLen = nLineWidth / 360;
931             sal_uInt16  nDashes = 0;
932             const bool bHugeWidth = static_cast<sal_uInt32>(nLineWidth) >= SAL_MAX_UINT32/8U; //then rougher approx is fine
933             sal_uInt32  nDashLen = bHugeWidth ? (nDotLen * 8U) : ((8U * nLineWidth) / 360);
934             sal_uInt32  nDistance = bHugeWidth ? (nDotLen * 3U) : ((3U * nLineWidth) / 360);
935 
936             switch ( eLineDashing )
937             {
938                 default:
939                 case mso_lineDotSys :
940                 {
941                     nDots = 1;
942                     nDashes = 0;
943                     nDistance = nDotLen;
944                 }
945                 break;
946 
947                 case mso_lineDashGEL :
948                 {
949                     nDots = 0;
950                     nDashes = 1;
951                     nDashLen = bHugeWidth ? (nDotLen * 4U) : ((4U * nLineWidth) / 360);
952                 }
953                 break;
954 
955                 case mso_lineDashDotGEL :
956                 {
957                     nDots = 1;
958                     nDashes = 1;
959                     nDashLen = bHugeWidth ? (nDotLen * 4U) : ((4U * nLineWidth) / 360);
960                 }
961                 break;
962 
963                 case mso_lineLongDashGEL :
964                 {
965                     nDots = 0;
966                     nDashes = 1;
967                 }
968                 break;
969 
970                 case mso_lineLongDashDotGEL :
971                 {
972                     nDots = 1;
973                     nDashes = 1;
974                 }
975                 break;
976 
977                 case mso_lineLongDashDotDotGEL:
978                 {
979                     nDots = 2;
980                     nDashes = 1;
981                 }
982                 break;
983             }
984 
985             rSet.Put( XLineDashItem( OUString(), XDash( css::drawing::DashStyle_RECT, nDots, nDotLen, nDashes, nDashLen, nDistance ) ) );
986             rSet.Put( XLineStyleItem( drawing::LineStyle_DASH ) );
987         }
988         rSet.Put( XLineColorItem( OUString(), rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_lineColor, 0 ) ) ) );
989         if ( IsProperty( DFF_Prop_lineOpacity ) )
990         {
991             double nTrans = GetPropertyValue(DFF_Prop_lineOpacity, 0x10000);
992             nTrans = (nTrans * 100) / 65536;
993             rSet.Put(XLineTransparenceItem(
994                 sal_uInt16(100 - ::rtl::math::round(nTrans))));
995         }
996 
997         rManager.ScaleEmu( nLineWidth );
998         rSet.Put( XLineWidthItem( nLineWidth ) );
999 
1000         // SJ: LineJoint (setting each time a line is set, because our internal joint type has another default)
1001         MSO_LineJoin eLineJointDefault = mso_lineJoinMiter;
1002         if ( eShapeType == mso_sptMin )
1003             eLineJointDefault = mso_lineJoinRound;
1004         MSO_LineJoin eLineJoint = static_cast<MSO_LineJoin>(GetPropertyValue( DFF_Prop_lineJoinStyle, eLineJointDefault ));
1005         css::drawing::LineJoint eXLineJoint( css::drawing::LineJoint_MITER );
1006         if ( eLineJoint == mso_lineJoinBevel )
1007             eXLineJoint = css::drawing::LineJoint_BEVEL;
1008         else if ( eLineJoint == mso_lineJoinRound )
1009             eXLineJoint = css::drawing::LineJoint_ROUND;
1010         rSet.Put( XLineJointItem( eXLineJoint ) );
1011 
1012         if ( nLineFlags & 0x10 )
1013         {
1014             bool bScaleArrows = rManager.pSdrModel->GetScaleUnit() == MapUnit::MapTwip;
1015 
1016             // LineStart
1017 
1018             if ( IsProperty( DFF_Prop_lineStartArrowhead ) )
1019             {
1020                 MSO_LineEnd         eLineEnd = static_cast<MSO_LineEnd>(GetPropertyValue( DFF_Prop_lineStartArrowhead, 0 ));
1021                 MSO_LineEndWidth    eWidth = static_cast<MSO_LineEndWidth>(GetPropertyValue( DFF_Prop_lineStartArrowWidth, mso_lineMediumWidthArrow ));
1022                 MSO_LineEndLength   eLength = static_cast<MSO_LineEndLength>(GetPropertyValue( DFF_Prop_lineStartArrowLength, mso_lineMediumLenArrow ));
1023 
1024                 sal_Int32   nArrowWidth;
1025                 bool        bArrowCenter;
1026                 OUString    aArrowName;
1027                 basegfx::B2DPolyPolygon aPolyPoly(GetLineArrow( nLineWidth, eLineEnd, eWidth, eLength, nArrowWidth, bArrowCenter, aArrowName, bScaleArrows ));
1028 
1029                 rSet.Put( XLineStartWidthItem( nArrowWidth ) );
1030                 rSet.Put( XLineStartItem( aArrowName, aPolyPoly) );
1031                 rSet.Put( XLineStartCenterItem( bArrowCenter ) );
1032             }
1033 
1034             // LineEnd
1035 
1036             if ( IsProperty( DFF_Prop_lineEndArrowhead ) )
1037             {
1038                 MSO_LineEnd         eLineEnd = static_cast<MSO_LineEnd>(GetPropertyValue( DFF_Prop_lineEndArrowhead, 0 ));
1039                 MSO_LineEndWidth    eWidth = static_cast<MSO_LineEndWidth>(GetPropertyValue( DFF_Prop_lineEndArrowWidth, mso_lineMediumWidthArrow ));
1040                 MSO_LineEndLength   eLength = static_cast<MSO_LineEndLength>(GetPropertyValue( DFF_Prop_lineEndArrowLength, mso_lineMediumLenArrow ));
1041 
1042                 sal_Int32   nArrowWidth;
1043                 bool        bArrowCenter;
1044                 OUString    aArrowName;
1045                 basegfx::B2DPolyPolygon aPolyPoly(GetLineArrow( nLineWidth, eLineEnd, eWidth, eLength, nArrowWidth, bArrowCenter, aArrowName, bScaleArrows ));
1046 
1047                 rSet.Put( XLineEndWidthItem( nArrowWidth ) );
1048                 rSet.Put( XLineEndItem( aArrowName, aPolyPoly ) );
1049                 rSet.Put( XLineEndCenterItem( bArrowCenter ) );
1050             }
1051         }
1052     }
1053     else
1054         rSet.Put( XLineStyleItem( drawing::LineStyle_NONE ) );
1055 }
1056 
1057 struct ShadeColor
1058 {
1059     Color       aColor;
1060     double      fDist;
1061 
1062     ShadeColor( const Color& rC, double fR ) : aColor( rC ), fDist( fR ) {};
1063 };
1064 
1065 static void GetShadeColors( const SvxMSDffManager& rManager, const DffPropertyReader& rProperties, SvStream& rIn, std::vector< ShadeColor >& rShadeColors )
1066 {
1067     sal_uInt32 nPos = rIn.Tell();
1068     if ( rProperties.IsProperty( DFF_Prop_fillShadeColors ) )
1069     {
1070         sal_uInt16 i = 0, nNumElem = 0, nNumElemReserved = 0, nSize = 0;
1071         bool bOk = false;
1072         if (rProperties.SeekToContent(DFF_Prop_fillShadeColors, rIn))
1073         {
1074             rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemReserved ).ReadUInt16( nSize );
1075             //sanity check that the stream is long enough to fulfill nNumElem * 2 sal_Int32s
1076             bOk = rIn.remainingSize() / (2*sizeof(sal_Int32)) >= nNumElem;
1077         }
1078         if (bOk)
1079         {
1080             for ( ; i < nNumElem; i++ )
1081             {
1082                 sal_Int32 nColor(0);
1083                 sal_Int32 nDist(0);
1084 
1085                 rIn.ReadInt32( nColor ).ReadInt32( nDist );
1086                 rShadeColors.emplace_back( rManager.MSO_CLR_ToColor( nColor, DFF_Prop_fillColor ), 1.0 - ( nDist / 65536.0 ) );
1087             }
1088         }
1089     }
1090     if ( rShadeColors.empty() )
1091     {
1092         rShadeColors.emplace_back( rManager.MSO_CLR_ToColor( rProperties.GetPropertyValue( DFF_Prop_fillBackColor, sal_uInt32(COL_WHITE) ), DFF_Prop_fillBackColor ), 0 );
1093         rShadeColors.emplace_back( rManager.MSO_CLR_ToColor( rProperties.GetPropertyValue( DFF_Prop_fillColor, sal_uInt32(COL_WHITE) ), DFF_Prop_fillColor ), 1 );
1094     }
1095     rIn.Seek( nPos );
1096 }
1097 
1098 static void ApplyRectangularGradientAsBitmap( const SvxMSDffManager& rManager, SvStream& rIn, SfxItemSet& rSet, const std::vector< ShadeColor >& rShadeColors, const DffObjData& rObjData, sal_Int32 nFix16Angle )
1099 {
1100     Size aBitmapSizePixel( static_cast< sal_Int32 >( ( rObjData.aBoundRect.GetWidth() / 2540.0 ) * 90.0 ),      // we will create a bitmap with 90 dpi
1101                            static_cast< sal_Int32 >( ( rObjData.aBoundRect.GetHeight() / 2540.0 ) * 90.0 ) );
1102     if (aBitmapSizePixel.Width() > 0 && aBitmapSizePixel.Height() > 0 &&
1103         aBitmapSizePixel.Width() <= 1024 && aBitmapSizePixel.Height() <= 1024)
1104     {
1105         double fFocusX = rManager.GetPropertyValue( DFF_Prop_fillToRight, 0 ) / 65536.0;
1106         double fFocusY = rManager.GetPropertyValue( DFF_Prop_fillToBottom, 0 ) / 65536.0;
1107 
1108         vcl::bitmap::RawBitmap aBitmap(aBitmapSizePixel, 24);
1109 
1110         for ( long nY = 0; nY < aBitmapSizePixel.Height(); nY++ )
1111         {
1112             for ( long nX = 0; nX < aBitmapSizePixel.Width(); nX++ )
1113             {
1114                 double fX = static_cast< double >( nX ) / aBitmapSizePixel.Width();
1115                 double fY = static_cast< double >( nY ) / aBitmapSizePixel.Height();
1116 
1117                 double fD, fDist;
1118                 if ( fX < fFocusX )
1119                 {
1120                     if ( fY < fFocusY )
1121                     {
1122                         if ( fX > fY )
1123                         {
1124                             fDist = fY;
1125                             fD = fFocusY;
1126                         }
1127                         else
1128                         {
1129                             fDist = fX;
1130                             fD = fFocusX;
1131                         }
1132                     }
1133                     else
1134                     {
1135                         if ( fX > ( 1 - fY ) )
1136                         {
1137                             fDist = 1 - fY;
1138                             fD = 1 - fFocusY;
1139                         }
1140                         else
1141                         {
1142                             fDist = fX;
1143                             fD = fFocusX;
1144                         }
1145                     }
1146                 }
1147                 else
1148                 {
1149                     if ( fY < fFocusY )
1150                     {
1151                         if ( ( 1 - fX ) > fY )
1152                         {
1153                             fDist = fY;
1154                             fD = fFocusY;
1155                         }
1156                         else
1157                         {
1158                             fDist = 1 - fX;
1159                             fD = 1 - fFocusX;
1160                         }
1161                     }
1162                     else
1163                     {
1164                         if ( ( 1 - fX ) > ( 1 - fY ) )
1165                         {
1166                             fDist = 1 - fY;
1167                             fD = 1 - fFocusY;
1168                         }
1169                         else
1170                         {
1171                             fDist = 1 - fX;
1172                             fD = 1 - fFocusX;
1173                         }
1174                     }
1175                 }
1176                 if ( fD != 0.0 )
1177                     fDist /= fD;
1178 
1179                 std::vector< ShadeColor >::const_iterator aIter( rShadeColors.begin() );
1180                 double fA = 0.0;
1181                 Color aColorA = aIter->aColor;
1182                 double fB = 1.0;
1183                 Color aColorB( aColorA );
1184                 while ( aIter != rShadeColors.end() )
1185                 {
1186                     if ( aIter->fDist <= fDist )
1187                     {
1188                         if ( aIter->fDist >= fA )
1189                         {
1190                             fA = aIter->fDist;
1191                             aColorA = aIter->aColor;
1192                         }
1193                     }
1194                     if ( aIter->fDist > fDist )
1195                     {
1196                         if ( aIter->fDist <= fB )
1197                         {
1198                             fB = aIter->fDist;
1199                             aColorB = aIter->aColor;
1200                         }
1201                     }
1202                     ++aIter;
1203                 }
1204                 double fRed = aColorA.GetRed(), fGreen = aColorA.GetGreen(), fBlue = aColorA.GetBlue();
1205                 double fD1 = fB - fA;
1206                 if ( fD1 != 0.0 )
1207                 {
1208                     fRed   += ( ( ( fDist - fA ) * ( aColorB.GetRed() - aColorA.GetRed() ) ) / fD1 );       // + aQuantErrCurrScan[ nX ].fRed;
1209                     fGreen += ( ( ( fDist - fA ) * ( aColorB.GetGreen() - aColorA.GetGreen() ) ) / fD1 );   // + aQuantErrCurrScan[ nX ].fGreen;
1210                     fBlue  += ( ( ( fDist - fA ) * ( aColorB.GetBlue() - aColorA.GetBlue() ) ) / fD1 );     // + aQuantErrCurrScan[ nX ].fBlue;
1211                 }
1212                 sal_Int16 nRed   = static_cast< sal_Int16 >( fRed   + 0.5 );
1213                 sal_Int16 nGreen = static_cast< sal_Int16 >( fGreen + 0.5 );
1214                 sal_Int16 nBlue  = static_cast< sal_Int16 >( fBlue  + 0.5 );
1215                 if ( nRed < 0 )
1216                     nRed = 0;
1217                 if ( nRed > 255 )
1218                     nRed = 255;
1219                 if ( nGreen < 0 )
1220                     nGreen = 0;
1221                 if ( nGreen > 255 )
1222                     nGreen = 255;
1223                 if ( nBlue < 0 )
1224                     nBlue = 0;
1225                 if ( nBlue > 255 )
1226                     nBlue = 255;
1227 
1228                 aBitmap.SetPixel(nY, nX, Color(static_cast<sal_Int8>(nRed), static_cast<sal_Int8>(nGreen), static_cast<sal_Int8>(nBlue)));
1229             }
1230         }
1231         BitmapEx aBitmapEx = vcl::bitmap::CreateFromData( std::move(aBitmap) );
1232 
1233         if ( nFix16Angle )
1234         {
1235             bool bRotateWithShape = true;   // sal_True seems to be default
1236             sal_uInt32 nPos = rIn.Tell();
1237             if ( const_cast< SvxMSDffManager& >( rManager ).maShapeRecords.SeekToContent( rIn, DFF_msofbtUDefProp, SEEK_FROM_CURRENT_AND_RESTART ) )
1238             {
1239                 const_cast< SvxMSDffManager& >( rManager ).maShapeRecords.Current()->SeekToBegOfRecord( rIn );
1240                 DffPropertyReader aSecPropSet( rManager );
1241                 aSecPropSet.ReadPropSet( rIn, nullptr );
1242                 sal_Int32 nSecFillProperties = aSecPropSet.GetPropertyValue( DFF_Prop_fNoFillHitTest, 0x200020 );
1243                 bRotateWithShape = ( nSecFillProperties & 0x0020 );
1244             }
1245             rIn.Seek( nPos );
1246             if ( bRotateWithShape )
1247             {
1248                 aBitmapEx.Rotate( nFix16Angle / 10, rShadeColors[ 0 ].aColor );
1249 
1250                 BmpMirrorFlags nMirrorFlags = BmpMirrorFlags::NONE;
1251                 if ( rObjData.nSpFlags & ShapeFlag::FlipV )
1252                     nMirrorFlags |= BmpMirrorFlags::Vertical;
1253                 if ( rObjData.nSpFlags & ShapeFlag::FlipH )
1254                     nMirrorFlags |= BmpMirrorFlags::Horizontal;
1255                 if ( nMirrorFlags != BmpMirrorFlags::NONE )
1256                     aBitmapEx.Mirror( nMirrorFlags );
1257             }
1258         }
1259 
1260         rSet.Put(XFillBmpTileItem(false));
1261         rSet.Put(XFillBitmapItem(OUString(), Graphic(aBitmapEx)));
1262     }
1263 }
1264 
1265 void DffPropertyReader::ApplyFillAttributes( SvStream& rIn, SfxItemSet& rSet, const DffObjData& rObjData ) const
1266 {
1267     sal_uInt32 nFillFlags(GetPropertyValue( DFF_Prop_fNoFillHitTest, 0 ));
1268 
1269     std::vector< ShadeColor > aShadeColors;
1270     GetShadeColors( rManager, *this, rIn, aShadeColors );
1271 
1272     if(!IsHardAttribute( DFF_Prop_fFilled ) && !IsCustomShapeFilledByDefault( rObjData.eShapeType ))
1273     {
1274         nFillFlags &= ~0x10;
1275     }
1276 
1277     if ( nFillFlags & 0x10 )
1278     {
1279         MSO_FillType eMSO_FillType = static_cast<MSO_FillType>(GetPropertyValue( DFF_Prop_fillType, mso_fillSolid ));
1280         drawing::FillStyle eXFill = drawing::FillStyle_NONE;
1281         switch( eMSO_FillType )
1282         {
1283             case mso_fillSolid :            // Fill with a solid color
1284                 eXFill = drawing::FillStyle_SOLID;
1285             break;
1286             case mso_fillPattern :          // Fill with a pattern (bitmap)
1287             case mso_fillTexture :          // A texture (pattern with its own color map)
1288             case mso_fillPicture :          // Center a picture in the shape
1289                 eXFill = drawing::FillStyle_BITMAP;
1290             break;
1291             case mso_fillShadeCenter :      // Shade from bounding rectangle to end point
1292             {
1293                 //If it is imported as a bitmap, it will not work well with transparency especially 100
1294                 //But the gradient look well comparing with imported as gradient. And rotate with shape
1295                 //also works better. So here just keep it.
1296                 if ( rObjData.aBoundRect.IsEmpty() )// size of object needed to be able
1297                     eXFill = drawing::FillStyle_GRADIENT;        // to create a bitmap substitution
1298                 else
1299                     eXFill = drawing::FillStyle_BITMAP;
1300             }
1301             break;
1302             case mso_fillShade :            // Shade from start to end points
1303             case mso_fillShadeShape :       // Shade from shape outline to end point
1304             case mso_fillShadeScale :       // Similar to mso_fillShade, but the fillAngle
1305             case mso_fillShadeTitle :       // special type - shade to title ---  for PP
1306                 eXFill = drawing::FillStyle_GRADIENT;
1307             break;
1308 //          case mso_fillBackground :       // Use the background fill color/pattern
1309             default: break;
1310         }
1311         rSet.Put( XFillStyleItem( eXFill ) );
1312 
1313         double dTrans  = 1.0;
1314         double dBackTrans = 1.0;
1315         if (IsProperty(DFF_Prop_fillOpacity))
1316         {
1317             dTrans = GetPropertyValue(DFF_Prop_fillOpacity, 0) / 65536.0;
1318             if ( eXFill != drawing::FillStyle_GRADIENT )
1319             {
1320                 dTrans = dTrans * 100;
1321                 rSet.Put(XFillTransparenceItem(
1322                     sal_uInt16(100 - ::rtl::math::round(dTrans))));
1323             }
1324         }
1325 
1326         if ( IsProperty(DFF_Prop_fillBackOpacity) )
1327             dBackTrans = GetPropertyValue(DFF_Prop_fillBackOpacity, 0) / 65536.0;
1328 
1329         if ( ( eMSO_FillType == mso_fillShadeCenter ) && ( eXFill == drawing::FillStyle_BITMAP ) )
1330         {
1331             ApplyRectangularGradientAsBitmap( rManager, rIn, rSet, aShadeColors, rObjData, mnFix16Angle );
1332         }
1333         else if ( eXFill == drawing::FillStyle_GRADIENT )
1334         {
1335             ImportGradientColor ( rSet, eMSO_FillType, dTrans , dBackTrans );
1336         }
1337         else if ( eXFill == drawing::FillStyle_BITMAP )
1338         {
1339             if( IsProperty( DFF_Prop_fillBlip ) )
1340             {
1341                 Graphic aGraf;
1342                 // first try to get BLIP from cache
1343                 bool bOK = const_cast<SvxMSDffManager&>(rManager).GetBLIP( GetPropertyValue( DFF_Prop_fillBlip, 0 ), aGraf );
1344                 // then try directly from stream (i.e. Excel chart hatches/bitmaps)
1345                 if ( !bOK )
1346                     bOK = SeekToContent( DFF_Prop_fillBlip, rIn ) && SvxMSDffManager::GetBLIPDirect( rIn, aGraf );
1347                 if ( bOK )
1348                 {
1349                     if ( eMSO_FillType == mso_fillPattern )
1350                     {
1351                         Bitmap aBmp( aGraf.GetBitmapEx().GetBitmap() );
1352                         if( aBmp.GetSizePixel().Width() == 8 && aBmp.GetSizePixel().Height() == 8 && aBmp.GetColorCount() == 2)
1353                         {
1354                             Color aCol1( COL_WHITE ), aCol2( COL_WHITE );
1355 
1356                             if ( IsProperty( DFF_Prop_fillColor ) )
1357                                 aCol1 = rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor, 0 ), DFF_Prop_fillColor );
1358 
1359                             if ( IsProperty( DFF_Prop_fillBackColor ) )
1360                                 aCol2 = rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillBackColor, 0 ), DFF_Prop_fillBackColor );
1361 
1362                             // Create a bitmap for the pattern with expected colors
1363                             vcl::bitmap::RawBitmap aResult(Size(8, 8), 24);
1364                             {
1365                                 Bitmap::ScopedReadAccess pRead(aBmp);
1366 
1367                                 for (long y = 0; y < aResult.Height(); ++y)
1368                                 {
1369                                     Scanline pScanlineRead = pRead->GetScanline( y );
1370                                     for (long x = 0; x < aResult.Width(); ++x)
1371                                     {
1372                                         Color aReadColor;
1373                                         if (pRead->HasPalette())
1374                                             aReadColor = pRead->GetPaletteColor(pRead->GetIndexFromData(pScanlineRead, x)).GetColor();
1375                                         else
1376                                             aReadColor = pRead->GetPixelFromData(pScanlineRead, x).GetColor();
1377 
1378                                         if (aReadColor == Color(0))
1379                                             aResult.SetPixel(y, x, aCol2);
1380                                         else
1381                                             aResult.SetPixel(y, x, aCol1);
1382                                     }
1383                                 }
1384                             }
1385                             aGraf = Graphic(vcl::bitmap::CreateFromData(std::move(aResult)));
1386                         }
1387 
1388                         rSet.Put(XFillBitmapItem(OUString(), aGraf));
1389                     }
1390                     else if ( eMSO_FillType == mso_fillTexture )
1391                     {
1392                         rSet.Put(XFillBmpTileItem(true));
1393                         rSet.Put(XFillBitmapItem(OUString(), aGraf));
1394                         rSet.Put(XFillBmpSizeXItem(GetPropertyValue(DFF_Prop_fillWidth, 0) / 360));
1395                         rSet.Put(XFillBmpSizeYItem(GetPropertyValue(DFF_Prop_fillHeight, 0) / 360));
1396                         rSet.Put(XFillBmpSizeLogItem(true));
1397                     }
1398                     else
1399                     {
1400                         rSet.Put(XFillBitmapItem(OUString(), aGraf));
1401                         rSet.Put(XFillBmpTileItem(false));
1402                     }
1403                 }
1404             }
1405         }
1406     }
1407     else
1408         rSet.Put( XFillStyleItem( drawing::FillStyle_NONE ) );
1409 }
1410 
1411 void DffPropertyReader::ApplyCustomShapeTextAttributes( SfxItemSet& rSet ) const
1412 {
1413     bool  bVerticalText = false;
1414     sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 25 * 3600 ) / 360;     // 0.25 cm (emu)
1415     sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 25 * 3600 ) / 360;   // 0.25 cm (emu)
1416     sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 13 * 3600 ) / 360;       // 0.13 cm (emu)
1417     sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 13 * 3600 ) /360;  // 0.13 cm (emu)
1418 
1419     SdrTextVertAdjust eTVA;
1420     SdrTextHorzAdjust eTHA;
1421 
1422     if ( IsProperty( DFF_Prop_txflTextFlow ) )
1423     {
1424         MSO_TextFlow eTextFlow = static_cast<MSO_TextFlow>( GetPropertyValue( DFF_Prop_txflTextFlow, 0 ) & 0xFFFF );
1425         switch( eTextFlow )
1426         {
1427             case mso_txflTtoBA :    /* #68110# */   // Top to Bottom @-font, oben -> unten
1428             case mso_txflTtoBN :                    // Top to Bottom non-@, oben -> unten
1429             case mso_txflVertN :                    // Vertical, non-@, oben -> unten
1430                 bVerticalText = true;           // nTextRotationAngle += 27000;
1431             break;
1432             default: break;
1433         }
1434     }
1435     sal_Int32 nFontDirection = GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 );
1436     if ( ( nFontDirection == 1 ) || ( nFontDirection == 3 ) )
1437         bVerticalText = !bVerticalText;
1438 
1439     if ( bVerticalText )
1440     {
1441         eTHA = SDRTEXTHORZADJUST_CENTER;
1442 
1443         // read text anchor
1444         sal_uInt32 eTextAnchor = GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop );
1445 
1446         switch( eTextAnchor )
1447         {
1448             case mso_anchorTop:
1449             case mso_anchorTopCentered:
1450             case mso_anchorTopBaseline:
1451             case mso_anchorTopCenteredBaseline:
1452                 eTHA = SDRTEXTHORZADJUST_RIGHT;
1453             break;
1454 
1455             case mso_anchorMiddle :
1456             case mso_anchorMiddleCentered:
1457                 eTHA = SDRTEXTHORZADJUST_CENTER;
1458             break;
1459 
1460             case mso_anchorBottom:
1461             case mso_anchorBottomCentered:
1462             case mso_anchorBottomBaseline:
1463             case mso_anchorBottomCenteredBaseline:
1464                 eTHA = SDRTEXTHORZADJUST_LEFT;
1465             break;
1466         }
1467         // if there is a 100% use of following attributes, the textbox can been aligned also in vertical direction
1468         switch ( eTextAnchor )
1469         {
1470             case mso_anchorTopCentered :
1471             case mso_anchorMiddleCentered :
1472             case mso_anchorBottomCentered :
1473             case mso_anchorTopCenteredBaseline:
1474             case mso_anchorBottomCenteredBaseline:
1475                 eTVA = SDRTEXTVERTADJUST_CENTER;
1476             break;
1477 
1478             default :
1479                 eTVA = SDRTEXTVERTADJUST_TOP;
1480             break;
1481         }
1482     }
1483     else
1484     {
1485         eTVA = SDRTEXTVERTADJUST_CENTER;
1486 
1487         // read text anchor
1488         sal_uInt32 eTextAnchor = GetPropertyValue( DFF_Prop_anchorText, mso_anchorTop );
1489 
1490         switch( eTextAnchor )
1491         {
1492             case mso_anchorTop:
1493             case mso_anchorTopCentered:
1494             case mso_anchorTopBaseline:
1495             case mso_anchorTopCenteredBaseline:
1496                 eTVA = SDRTEXTVERTADJUST_TOP;
1497             break;
1498 
1499             case mso_anchorMiddle :
1500             case mso_anchorMiddleCentered:
1501                 eTVA = SDRTEXTVERTADJUST_CENTER;
1502             break;
1503 
1504             case mso_anchorBottom:
1505             case mso_anchorBottomCentered:
1506             case mso_anchorBottomBaseline:
1507             case mso_anchorBottomCenteredBaseline:
1508                 eTVA = SDRTEXTVERTADJUST_BOTTOM;
1509             break;
1510         }
1511         // if there is a 100% usage of following attributes, the textbox can be aligned also in horizontal direction
1512         switch ( eTextAnchor )
1513         {
1514             case mso_anchorTopCentered :
1515             case mso_anchorMiddleCentered :
1516             case mso_anchorBottomCentered :
1517             case mso_anchorTopCenteredBaseline:
1518             case mso_anchorBottomCenteredBaseline:
1519                 eTHA = SDRTEXTHORZADJUST_CENTER;    // the text has to be displayed using the full width;
1520             break;
1521 
1522             default :
1523                 eTHA = SDRTEXTHORZADJUST_LEFT;
1524             break;
1525         }
1526     }
1527     rSet.Put( SvxFrameDirectionItem( bVerticalText ? SvxFrameDirection::Vertical_RL_TB : SvxFrameDirection::Horizontal_LR_TB, EE_PARA_WRITINGDIR ) );
1528 
1529     rSet.Put( SdrTextVertAdjustItem( eTVA ) );
1530     rSet.Put( SdrTextHorzAdjustItem( eTHA ) );
1531 
1532     rSet.Put( makeSdrTextLeftDistItem( nTextLeft ) );
1533     rSet.Put( makeSdrTextRightDistItem( nTextRight ) );
1534     rSet.Put( makeSdrTextUpperDistItem( nTextTop ) );
1535     rSet.Put( makeSdrTextLowerDistItem( nTextBottom ) );
1536 
1537     rSet.Put( makeSdrTextWordWrapItem( static_cast<MSO_WrapMode>(GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare )) != mso_wrapNone ) );
1538     rSet.Put( makeSdrTextAutoGrowHeightItem( ( GetPropertyValue( DFF_Prop_FitTextToShape, 0 ) & 2 ) != 0 ) );
1539 }
1540 
1541 void DffPropertyReader::ApplyCustomShapeGeometryAttributes( SvStream& rIn, SfxItemSet& rSet, const DffObjData& rObjData ) const
1542 {
1543 
1544     sal_uInt32 nAdjustmentsWhichNeedsToBeConverted = 0;
1545 
1546 
1547     // creating SdrCustomShapeGeometryItem
1548 
1549     typedef std::vector< beans::PropertyValue > PropVec;
1550 
1551     // aPropVec will be filled with all PropertyValues
1552     PropVec aPropVec;
1553     PropertyValue aProp;
1554 
1555 
1556     // "Type" property, including the predefined CustomShape type name
1557 
1558     const OUString sType( "Type" );
1559     aProp.Name  = sType;
1560     aProp.Value <<= EnhancedCustomShapeTypeNames::Get( rObjData.eShapeType );
1561     aPropVec.push_back( aProp );
1562 
1563 
1564     // "ViewBox"
1565 
1566 
1567     sal_Int32 nCoordWidth = 21600;  // needed to replace handle type center with absolute value
1568     sal_Int32 nCoordHeight= 21600;
1569     if ( IsProperty( DFF_Prop_geoLeft ) || IsProperty( DFF_Prop_geoTop ) || IsProperty( DFF_Prop_geoRight ) || IsProperty( DFF_Prop_geoBottom ) )
1570     {
1571         css::awt::Rectangle aViewBox;
1572         const OUString sViewBox( "ViewBox" );
1573         aViewBox.X = GetPropertyValue( DFF_Prop_geoLeft, 0 );
1574         aViewBox.Y = GetPropertyValue( DFF_Prop_geoTop, 0 );
1575         aViewBox.Width = nCoordWidth = o3tl::saturating_sub<sal_Int32>(GetPropertyValue(DFF_Prop_geoRight, 21600), aViewBox.X);
1576         aViewBox.Height = nCoordHeight = o3tl::saturating_sub<sal_Int32>(GetPropertyValue(DFF_Prop_geoBottom, 21600), aViewBox.Y);
1577         aProp.Name = sViewBox;
1578         aProp.Value <<= aViewBox;
1579         aPropVec.push_back( aProp );
1580     }
1581 
1582     // TextRotateAngle
1583 
1584     if ( IsProperty( DFF_Prop_txflTextFlow ) || IsProperty( DFF_Prop_cdirFont ) )
1585     {
1586         sal_Int32 nTextRotateAngle = 0;
1587         MSO_TextFlow eTextFlow = static_cast<MSO_TextFlow>( GetPropertyValue( DFF_Prop_txflTextFlow, 0 ) & 0xFFFF );
1588 
1589         if ( eTextFlow == mso_txflBtoT )    // Bottom to Top non-@
1590             nTextRotateAngle += 90;
1591         switch( GetPropertyValue( DFF_Prop_cdirFont, mso_cdir0 ) )  // SJ: mso_cdir90 and mso_cdir270 will be simulated by
1592         {                                                           // activating vertical writing for the text objects
1593             case mso_cdir90 :
1594             {
1595                 if ( eTextFlow == mso_txflTtoBA )
1596                     nTextRotateAngle -= 180;
1597             }
1598             break;
1599             case mso_cdir180: nTextRotateAngle -= 180; break;
1600             case mso_cdir270:
1601             {
1602                 if ( eTextFlow != mso_txflTtoBA )
1603                     nTextRotateAngle -= 180;
1604             }
1605             break;
1606             default: break;
1607         }
1608         if ( nTextRotateAngle )
1609         {
1610             double fTextRotateAngle = nTextRotateAngle;
1611             const OUString sTextRotateAngle( "TextRotateAngle" );
1612             aProp.Name = sTextRotateAngle;
1613             aProp.Value <<= fTextRotateAngle;
1614             aPropVec.push_back( aProp );
1615         }
1616     }
1617 
1618     // "Extrusion" PropertySequence element
1619 
1620     bool bExtrusionOn = ( GetPropertyValue( DFF_Prop_fc3DLightFace, 0 ) & 8 ) != 0;
1621     if ( bExtrusionOn )
1622     {
1623         PropVec aExtrusionPropVec;
1624 
1625         // "Extrusion"
1626         const OUString sExtrusionOn( "Extrusion" );
1627         aProp.Name = sExtrusionOn;
1628         aProp.Value <<= bExtrusionOn;
1629         aExtrusionPropVec.push_back( aProp );
1630 
1631         // "Brightness"
1632         if ( IsProperty( DFF_Prop_c3DAmbientIntensity ) )
1633         {
1634             const OUString sExtrusionBrightness( "Brightness" );
1635             double fBrightness = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DAmbientIntensity, 0 ));
1636             fBrightness /= 655.36;
1637             aProp.Name = sExtrusionBrightness;
1638             aProp.Value <<= fBrightness;
1639             aExtrusionPropVec.push_back( aProp );
1640         }
1641         // "Depth" in 1/100mm
1642         if ( IsProperty( DFF_Prop_c3DExtrudeBackward ) || IsProperty( DFF_Prop_c3DExtrudeForward ) )
1643         {
1644             const OUString sDepth( "Depth" );
1645             double fBackDepth = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DExtrudeBackward, 1270 * 360 ))) / 360.0;
1646             double fForeDepth = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DExtrudeForward, 0 ))) / 360.0;
1647             double fDepth = fBackDepth + fForeDepth;
1648             double fFraction = fDepth != 0.0 ? fForeDepth / fDepth : 0;
1649             EnhancedCustomShapeParameterPair aDepthParaPair;
1650             aDepthParaPair.First.Value <<= fDepth;
1651             aDepthParaPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
1652             aDepthParaPair.Second.Value <<= fFraction;
1653             aDepthParaPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
1654             aProp.Name = sDepth;
1655             aProp.Value <<= aDepthParaPair;
1656             aExtrusionPropVec.push_back( aProp );
1657         }
1658         // "Diffusion"
1659         if ( IsProperty( DFF_Prop_c3DDiffuseAmt ) )
1660         {
1661             const OUString sExtrusionDiffusion( "Diffusion" );
1662             double fDiffusion = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DDiffuseAmt, 0 ));
1663             fDiffusion /= 655.36;
1664             aProp.Name = sExtrusionDiffusion;
1665             aProp.Value <<= fDiffusion;
1666             aExtrusionPropVec.push_back( aProp );
1667         }
1668         // "NumberOfLineSegments"
1669         if ( IsProperty( DFF_Prop_c3DTolerance ) )
1670         {
1671             const OUString sExtrusionNumberOfLineSegments( "NumberOfLineSegments" );
1672             aProp.Name = sExtrusionNumberOfLineSegments;
1673             aProp.Value <<= static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DTolerance, 0 ));
1674             aExtrusionPropVec.push_back( aProp );
1675         }
1676         // "LightFace"
1677         const OUString sExtrusionLightFace( "LightFace" );
1678         bool bExtrusionLightFace = ( GetPropertyValue( DFF_Prop_fc3DLightFace, 0 ) & 1 ) != 0;
1679         aProp.Name = sExtrusionLightFace;
1680         aProp.Value <<= bExtrusionLightFace;
1681         aExtrusionPropVec.push_back( aProp );
1682         // "FirstLightHarsh"
1683         const OUString sExtrusionFirstLightHarsh( "FirstLightHarsh" );
1684         bool bExtrusionFirstLightHarsh = ( GetPropertyValue( DFF_Prop_fc3DFillHarsh, 0 ) & 2 ) != 0;
1685         aProp.Name = sExtrusionFirstLightHarsh;
1686         aProp.Value <<= bExtrusionFirstLightHarsh;
1687         aExtrusionPropVec.push_back( aProp );
1688         // "SecondLightHarsh"
1689         const OUString sExtrusionSecondLightHarsh( "SecondLightHarsh" );
1690         bool bExtrusionSecondLightHarsh = ( GetPropertyValue( DFF_Prop_fc3DFillHarsh, 0 ) & 1 ) != 0;
1691         aProp.Name = sExtrusionSecondLightHarsh;
1692         aProp.Value <<= bExtrusionSecondLightHarsh;
1693         aExtrusionPropVec.push_back( aProp );
1694         // "FirstLightLevel"
1695         if ( IsProperty( DFF_Prop_c3DKeyIntensity ) )
1696         {
1697             const OUString sExtrusionFirstLightLevel( "FirstLightLevel" );
1698             double fFirstLightLevel = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyIntensity, 0 ));
1699             fFirstLightLevel /= 655.36;
1700             aProp.Name = sExtrusionFirstLightLevel;
1701             aProp.Value <<= fFirstLightLevel;
1702             aExtrusionPropVec.push_back( aProp );
1703         }
1704         // "SecondLightLevel"
1705         if ( IsProperty( DFF_Prop_c3DFillIntensity ) )
1706         {
1707             const OUString sExtrusionSecondLightLevel( "SecondLightLevel" );
1708             double fSecondLightLevel = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillIntensity, 0 ));
1709             fSecondLightLevel /= 655.36;
1710             aProp.Name = sExtrusionSecondLightLevel;
1711             aProp.Value <<= fSecondLightLevel;
1712             aExtrusionPropVec.push_back( aProp );
1713         }
1714         // "FirtstLightDirection"
1715         if ( IsProperty( DFF_Prop_c3DKeyX ) || IsProperty( DFF_Prop_c3DKeyY ) || IsProperty( DFF_Prop_c3DKeyZ ) )
1716         {
1717             double fLightX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyX, 50000 )));
1718             double fLightY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyY, 0 )));
1719             double fLightZ = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DKeyZ, 10000 )));
1720             css::drawing::Direction3D aExtrusionFirstLightDirection( fLightX, fLightY, fLightZ );
1721             const OUString sExtrusionFirstLightDirection( "FirstLightDirection" );
1722             aProp.Name = sExtrusionFirstLightDirection;
1723             aProp.Value <<= aExtrusionFirstLightDirection;
1724             aExtrusionPropVec.push_back( aProp );
1725         }
1726         // "SecondLightDirection"
1727         if ( IsProperty( DFF_Prop_c3DFillX ) || IsProperty( DFF_Prop_c3DFillY ) || IsProperty( DFF_Prop_c3DFillZ ) )
1728         {
1729             double fLight2X = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillX, sal_uInt32(-50000) )));
1730             double fLight2Y = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillY, 0 )));
1731             double fLight2Z = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DFillZ, 10000 )));
1732             css::drawing::Direction3D aExtrusionSecondLightDirection( fLight2X, fLight2Y, fLight2Z );
1733             const OUString sExtrusionSecondLightDirection( "SecondLightDirection" );
1734             aProp.Name = sExtrusionSecondLightDirection;
1735             aProp.Value <<= aExtrusionSecondLightDirection;
1736             aExtrusionPropVec.push_back( aProp );
1737         }
1738 
1739         // "Metal"
1740         const OUString sExtrusionMetal( "Metal" );
1741         bool bExtrusionMetal = ( GetPropertyValue( DFF_Prop_fc3DLightFace, 0 ) & 4 ) != 0;
1742         aProp.Name = sExtrusionMetal;
1743         aProp.Value <<= bExtrusionMetal;
1744         aExtrusionPropVec.push_back( aProp );
1745         // "ShadeMode"
1746         if ( IsProperty( DFF_Prop_c3DRenderMode ) )
1747         {
1748             const OUString sExtrusionShadeMode( "ShadeMode" );
1749             sal_uInt32 nExtrusionRenderMode = GetPropertyValue( DFF_Prop_c3DRenderMode, 0 );
1750             css::drawing::ShadeMode eExtrusionShadeMode( css::drawing::ShadeMode_FLAT );
1751             if ( nExtrusionRenderMode == mso_Wireframe )
1752                 eExtrusionShadeMode = css::drawing::ShadeMode_DRAFT;
1753 
1754             aProp.Name = sExtrusionShadeMode;
1755             aProp.Value <<= eExtrusionShadeMode;
1756             aExtrusionPropVec.push_back( aProp );
1757         }
1758         // "RotateAngle" in Grad
1759         if ( IsProperty( DFF_Prop_c3DXRotationAngle ) || IsProperty( DFF_Prop_c3DYRotationAngle ) )
1760         {
1761             const OUString sExtrusionAngle( "RotateAngle" );
1762             double fAngleX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DXRotationAngle, 0 ))) / 65536.0;
1763             double fAngleY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DYRotationAngle, 0 ))) / 65536.0;
1764             EnhancedCustomShapeParameterPair aRotateAnglePair;
1765             aRotateAnglePair.First.Value <<= fAngleX;
1766             aRotateAnglePair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
1767             aRotateAnglePair.Second.Value <<= fAngleY;
1768             aRotateAnglePair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
1769             aProp.Name = sExtrusionAngle;
1770             aProp.Value <<= aRotateAnglePair;
1771             aExtrusionPropVec.push_back( aProp );
1772         }
1773 
1774         // "AutoRotationCenter"
1775         if ( ( GetPropertyValue( DFF_Prop_fc3DFillHarsh, 0 ) & 8 ) == 0 )
1776         {
1777             // "RotationCenter"
1778             if ( IsProperty( DFF_Prop_c3DRotationCenterX ) || IsProperty( DFF_Prop_c3DRotationCenterY ) || IsProperty( DFF_Prop_c3DRotationCenterZ ) )
1779             {
1780                 css::drawing::Direction3D aRotationCenter(
1781                     static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DRotationCenterX, 0 ))) / 360.0,
1782                     static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DRotationCenterY, 0 ))) / 360.0,
1783                     static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DRotationCenterZ, 0 ))) / 360.0 );
1784 
1785                 const OUString sExtrusionRotationCenter( "RotationCenter" );
1786                 aProp.Name = sExtrusionRotationCenter;
1787                 aProp.Value <<= aRotationCenter;
1788                 aExtrusionPropVec.push_back( aProp );
1789             }
1790         }
1791         // "Shininess"
1792         if ( IsProperty( DFF_Prop_c3DShininess ) )
1793         {
1794             const OUString sExtrusionShininess( "Shininess" );
1795             double fShininess = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DShininess, 0 ));
1796             fShininess /= 655.36;
1797             aProp.Name = sExtrusionShininess;
1798             aProp.Value <<= fShininess;
1799             aExtrusionPropVec.push_back( aProp );
1800         }
1801         // "Skew"
1802         if ( IsProperty( DFF_Prop_c3DSkewAmount ) || IsProperty( DFF_Prop_c3DSkewAngle ) )
1803         {
1804             const OUString sExtrusionSkew( "Skew" );
1805             double fSkewAmount = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DSkewAmount, 50 ));
1806             double fSkewAngle = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DSkewAngle, sal::static_int_cast< sal_uInt32 >(-135 * 65536) ))) / 65536.0;
1807 
1808             EnhancedCustomShapeParameterPair aSkewPair;
1809             aSkewPair.First.Value <<= fSkewAmount;
1810             aSkewPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
1811             aSkewPair.Second.Value <<= fSkewAngle;
1812             aSkewPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
1813             aProp.Name = sExtrusionSkew;
1814             aProp.Value <<= aSkewPair;
1815             aExtrusionPropVec.push_back( aProp );
1816         }
1817         // "Specularity"
1818         if ( IsProperty( DFF_Prop_c3DSpecularAmt ) )
1819         {
1820             const OUString sExtrusionSpecularity( "Specularity" );
1821             double fSpecularity = static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DSpecularAmt, 0 ));
1822             fSpecularity /= 1333;
1823             aProp.Name = sExtrusionSpecularity;
1824             aProp.Value <<= fSpecularity;
1825             aExtrusionPropVec.push_back( aProp );
1826         }
1827         // "ProjectionMode"
1828         const OUString sExtrusionProjectionMode( "ProjectionMode" );
1829         ProjectionMode eProjectionMode = (GetPropertyValue( DFF_Prop_fc3DFillHarsh, 0 ) & 4) ? ProjectionMode_PARALLEL : ProjectionMode_PERSPECTIVE;
1830         aProp.Name = sExtrusionProjectionMode;
1831         aProp.Value <<= eProjectionMode;
1832         aExtrusionPropVec.push_back( aProp );
1833 
1834         // "ViewPoint" in 1/100mm
1835         if ( IsProperty( DFF_Prop_c3DXViewpoint ) || IsProperty( DFF_Prop_c3DYViewpoint ) || IsProperty( DFF_Prop_c3DZViewpoint ) )
1836         {
1837             double fViewX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DXViewpoint, 1250000 ))) / 360.0;
1838             double fViewY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DYViewpoint, sal_uInt32(-1250000) )))/ 360.0;
1839             double fViewZ = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DZViewpoint, 9000000 ))) / 360.0;
1840             css::drawing::Position3D aExtrusionViewPoint( fViewX, fViewY, fViewZ );
1841             const OUString sExtrusionViewPoint( "ViewPoint" );
1842             aProp.Name = sExtrusionViewPoint;
1843             aProp.Value <<= aExtrusionViewPoint;
1844             aExtrusionPropVec.push_back( aProp );
1845         }
1846         // "Origin"
1847         if ( IsProperty( DFF_Prop_c3DOriginX ) || IsProperty( DFF_Prop_c3DOriginY ) )
1848         {
1849             const OUString sExtrusionOrigin( "Origin" );
1850             double fOriginX = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DOriginX, 32768 )));
1851             double fOriginY = static_cast<double>(static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_c3DOriginY, sal_uInt32(-32768) )));
1852             fOriginX /= 65536;
1853             fOriginY /= 65536;
1854             EnhancedCustomShapeParameterPair aOriginPair;
1855             aOriginPair.First.Value <<= fOriginX;
1856             aOriginPair.First.Type = EnhancedCustomShapeParameterType::NORMAL;
1857             aOriginPair.Second.Value <<= fOriginY;
1858             aOriginPair.Second.Type = EnhancedCustomShapeParameterType::NORMAL;
1859             aProp.Name = sExtrusionOrigin;
1860             aProp.Value <<= aOriginPair;
1861             aExtrusionPropVec.push_back( aProp );
1862         }
1863         // "ExtrusionColor"
1864         const OUString sExtrusionColor( "Color" );
1865         bool bExtrusionColor = IsProperty( DFF_Prop_c3DExtrusionColor );    // ( GetPropertyValue( DFF_Prop_fc3DLightFace ) & 2 ) != 0;
1866         aProp.Name = sExtrusionColor;
1867         aProp.Value <<= bExtrusionColor;
1868         aExtrusionPropVec.push_back( aProp );
1869         if ( IsProperty( DFF_Prop_c3DExtrusionColor ) )
1870             rSet.Put( XSecondaryFillColorItem( OUString(), rManager.MSO_CLR_ToColor(
1871                 GetPropertyValue( DFF_Prop_c3DExtrusionColor, 0 ), DFF_Prop_c3DExtrusionColor ) ) );
1872         // pushing the whole Extrusion element
1873         aProp.Name = "Extrusion";
1874         aProp.Value <<= comphelper::containerToSequence(aExtrusionPropVec);
1875         aPropVec.push_back( aProp );
1876     }
1877 
1878 
1879     // "Equations" PropertySequence element
1880 
1881     if ( IsProperty( DFF_Prop_pFormulas ) )
1882     {
1883         sal_uInt16 nNumElem = 0;
1884 
1885         if ( SeekToContent( DFF_Prop_pFormulas, rIn ) )
1886         {
1887             sal_uInt16 nNumElemMem = 0;
1888             sal_uInt16 nElemSize = 8;
1889             rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemMem ).ReadUInt16( nElemSize );
1890         }
1891         if ( nNumElem <= 128 )
1892         {
1893             uno::Sequence< OUString > aEquations( nNumElem );
1894             for ( sal_uInt16 i = 0; i < nNumElem; i++ )
1895             {
1896                 sal_Int16 nP1(0), nP2(0), nP3(0);
1897                 sal_uInt16 nFlags(0);
1898                 rIn.ReadUInt16( nFlags ).ReadInt16( nP1 ).ReadInt16( nP2 ).ReadInt16( nP3 );
1899                 aEquations[ i ] = EnhancedCustomShape2d::GetEquation( nFlags, nP1, nP2, nP3 );
1900             }
1901             // pushing the whole Equations element
1902             const OUString sEquations( "Equations" );
1903             aProp.Name = sEquations;
1904             aProp.Value <<= aEquations;
1905             aPropVec.push_back( aProp );
1906         }
1907     }
1908 
1909 
1910     // "Handles" PropertySequence element
1911 
1912     if ( IsProperty( DFF_Prop_Handles ) )
1913     {
1914         sal_uInt16 nNumElem = 0;
1915         sal_uInt16 nElemSize = 36;
1916 
1917         if ( SeekToContent( DFF_Prop_Handles, rIn ) )
1918         {
1919             sal_uInt16 nNumElemMem = 0;
1920             rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemMem ).ReadUInt16( nElemSize );
1921         }
1922         bool bImport = false;
1923         if (nElemSize == 36)
1924         {
1925             //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
1926             bImport = rIn.remainingSize() / nElemSize >= nNumElem;
1927         }
1928         if (bImport)
1929         {
1930             uno::Sequence< beans::PropertyValues > aHandles( nNumElem );
1931             for (sal_uInt32 i = 0; i < nNumElem; ++i)
1932             {
1933                 PropVec aHandlePropVec;
1934                 sal_uInt32 nFlagsTmp(0);
1935                 sal_Int32  nPositionX(0), nPositionY(0), nCenterX(0), nCenterY(0), nRangeXMin(0), nRangeXMax(0), nRangeYMin(0), nRangeYMax(0);
1936                 rIn.ReadUInt32( nFlagsTmp )
1937                    .ReadInt32( nPositionX )
1938                    .ReadInt32( nPositionY )
1939                    .ReadInt32( nCenterX )
1940                    .ReadInt32( nCenterY )
1941                    .ReadInt32( nRangeXMin )
1942                    .ReadInt32( nRangeXMax )
1943                    .ReadInt32( nRangeYMin )
1944                    .ReadInt32( nRangeYMax );
1945                 SvxMSDffHandleFlags nFlags = static_cast<SvxMSDffHandleFlags>(nFlagsTmp);
1946                 if ( nPositionX == 2 )  // replacing center position with absolute value
1947                     nPositionX = nCoordWidth / 2;
1948                 if ( nPositionY == 2 )
1949                     nPositionY = nCoordHeight / 2;
1950                 EnhancedCustomShapeParameterPair aPosition;
1951                 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.First,  nPositionX, true, true  );
1952                 EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPosition.Second, nPositionY, true, false );
1953                 const OUString sHandlePosition( "Position" );
1954                 aProp.Name = sHandlePosition;
1955                 aProp.Value <<= aPosition;
1956                 aHandlePropVec.push_back( aProp );
1957 
1958                 if ( nFlags & SvxMSDffHandleFlags::MIRRORED_X )
1959                 {
1960                     const OUString sHandleMirroredX( "MirroredX" );
1961                     aProp.Name = sHandleMirroredX;
1962                     aProp.Value <<= true;
1963                     aHandlePropVec.push_back( aProp );
1964                 }
1965                 if ( nFlags & SvxMSDffHandleFlags::MIRRORED_Y )
1966                 {
1967                     const OUString sHandleMirroredY( "MirroredY" );
1968                     aProp.Name = sHandleMirroredY;
1969                     aProp.Value <<= true;
1970                     aHandlePropVec.push_back( aProp );
1971                 }
1972                 if ( nFlags & SvxMSDffHandleFlags::SWITCHED )
1973                 {
1974                     const OUString sHandleSwitched( "Switched" );
1975                     aProp.Name = sHandleSwitched;
1976                     aProp.Value <<= true;
1977                     aHandlePropVec.push_back( aProp );
1978                 }
1979                 if ( nFlags & SvxMSDffHandleFlags::POLAR )
1980                 {
1981                     if ( nCenterX == 2 )
1982                         nCenterX = nCoordWidth / 2;
1983                     if ( nCenterY == 2 )
1984                         nCenterY = nCoordHeight / 2;
1985                     if ((nPositionY >= 0x256 || nPositionY <= 0x107) && i < sizeof(sal_uInt32) * 8)   // position y
1986                         nAdjustmentsWhichNeedsToBeConverted |= ( 1U << i );
1987                     EnhancedCustomShapeParameterPair aPolar;
1988                     EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPolar.First,  nCenterX, bool( nFlags & SvxMSDffHandleFlags::CENTER_X_IS_SPECIAL ), true  );
1989                     EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aPolar.Second, nCenterY, bool( nFlags & SvxMSDffHandleFlags::CENTER_Y_IS_SPECIAL ), false );
1990                     const OUString sHandlePolar( "Polar" );
1991                     aProp.Name = sHandlePolar;
1992                     aProp.Value <<= aPolar;
1993                     aHandlePropVec.push_back( aProp );
1994                 }
1995                 if ( nFlags & SvxMSDffHandleFlags::MAP )
1996                 {
1997                     if ( nCenterX == 2 )
1998                         nCenterX = nCoordWidth / 2;
1999                     if ( nCenterY == 2 )
2000                         nCenterY = nCoordHeight / 2;
2001                     EnhancedCustomShapeParameterPair aMap;
2002                     EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aMap.First,  nCenterX, bool( nFlags & SvxMSDffHandleFlags::CENTER_X_IS_SPECIAL ), true  );
2003                     EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aMap.Second, nCenterY, bool( nFlags & SvxMSDffHandleFlags::CENTER_Y_IS_SPECIAL ), false );
2004                     const OUString sHandleMap( "Map" );
2005                     aProp.Name = sHandleMap;
2006                     aProp.Value <<= aMap;
2007                     aHandlePropVec.push_back( aProp );
2008                 }
2009                 if ( nFlags & SvxMSDffHandleFlags::RANGE )
2010                 {
2011                     if ( static_cast<sal_uInt32>(nRangeXMin) != 0x80000000 )
2012                     {
2013                         if ( nRangeXMin == 2 )
2014                             nRangeXMin = nCoordWidth / 2;
2015                         EnhancedCustomShapeParameter aRangeXMinimum;
2016                         EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMinimum,  nRangeXMin,
2017                             bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL ), true  );
2018                         const OUString sHandleRangeXMinimum( "RangeXMinimum" );
2019                         aProp.Name = sHandleRangeXMinimum;
2020                         aProp.Value <<= aRangeXMinimum;
2021                         aHandlePropVec.push_back( aProp );
2022                     }
2023                     if ( static_cast<sal_uInt32>(nRangeXMax) != 0x7fffffff )
2024                     {
2025                         if ( nRangeXMax == 2 )
2026                             nRangeXMax = nCoordWidth / 2;
2027                         EnhancedCustomShapeParameter aRangeXMaximum;
2028                         EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeXMaximum, nRangeXMax,
2029                             bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL ), false );
2030                         const OUString sHandleRangeXMaximum( "RangeXMaximum" );
2031                         aProp.Name = sHandleRangeXMaximum;
2032                         aProp.Value <<= aRangeXMaximum;
2033                         aHandlePropVec.push_back( aProp );
2034                     }
2035                     if ( static_cast<sal_uInt32>(nRangeYMin) != 0x80000000 )
2036                     {
2037                         if ( nRangeYMin == 2 )
2038                             nRangeYMin = nCoordHeight / 2;
2039                         EnhancedCustomShapeParameter aRangeYMinimum;
2040                         EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMinimum, nRangeYMin,
2041                             bool( nFlags & SvxMSDffHandleFlags::RANGE_Y_MIN_IS_SPECIAL ), true );
2042                         const OUString sHandleRangeYMinimum( "RangeYMinimum" );
2043                         aProp.Name = sHandleRangeYMinimum;
2044                         aProp.Value <<= aRangeYMinimum;
2045                         aHandlePropVec.push_back( aProp );
2046                     }
2047                     if ( static_cast<sal_uInt32>(nRangeYMax) != 0x7fffffff )
2048                     {
2049                         if ( nRangeYMax == 2 )
2050                             nRangeYMax = nCoordHeight / 2;
2051                         EnhancedCustomShapeParameter aRangeYMaximum;
2052                         EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRangeYMaximum, nRangeYMax,
2053                             bool( nFlags & SvxMSDffHandleFlags::RANGE_Y_MAX_IS_SPECIAL ), false );
2054                         const OUString sHandleRangeYMaximum( "RangeYMaximum" );
2055                         aProp.Name = sHandleRangeYMaximum;
2056                         aProp.Value <<= aRangeYMaximum;
2057                         aHandlePropVec.push_back( aProp );
2058                     }
2059                 }
2060                 if ( nFlags & SvxMSDffHandleFlags::RADIUS_RANGE )
2061                 {
2062                     if ( static_cast<sal_uInt32>(nRangeXMin) != 0x7fffffff )
2063                     {
2064                         if ( nRangeXMin == 2 )
2065                             nRangeXMin = nCoordWidth / 2;
2066                         EnhancedCustomShapeParameter aRadiusRangeMinimum;
2067                         EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMinimum, nRangeXMin,
2068                             bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MIN_IS_SPECIAL ), true  );
2069                         const OUString sHandleRadiusRangeMinimum( "RadiusRangeMinimum" );
2070                         aProp.Name = sHandleRadiusRangeMinimum;
2071                         aProp.Value <<= aRadiusRangeMinimum;
2072                         aHandlePropVec.push_back( aProp );
2073                     }
2074                     if ( static_cast<sal_uInt32>(nRangeXMax) != 0x80000000 )
2075                     {
2076                         if ( nRangeXMax == 2 )
2077                             nRangeXMax = nCoordWidth / 2;
2078                         EnhancedCustomShapeParameter aRadiusRangeMaximum;
2079                         EnhancedCustomShape2d::SetEnhancedCustomShapeHandleParameter( aRadiusRangeMaximum, nRangeXMax,
2080                             bool( nFlags & SvxMSDffHandleFlags::RANGE_X_MAX_IS_SPECIAL ), false );
2081                         const OUString sHandleRadiusRangeMaximum( "RadiusRangeMaximum" );
2082                         aProp.Name = sHandleRadiusRangeMaximum;
2083                         aProp.Value <<= aRadiusRangeMaximum;
2084                         aHandlePropVec.push_back( aProp );
2085                     }
2086                 }
2087                 if ( !aHandlePropVec.empty() )
2088                 {
2089                     aHandles[ i ] = comphelper::containerToSequence(aHandlePropVec);
2090                 }
2091             }
2092             // pushing the whole Handles element
2093             aProp.Name = "Handles";
2094             aProp.Value <<= aHandles;
2095             aPropVec.push_back( aProp );
2096         }
2097     }
2098     else
2099     {
2100         const mso_CustomShape* pDefCustomShape = GetCustomShapeContent( rObjData.eShapeType );
2101         if ( pDefCustomShape && pDefCustomShape->nHandles && pDefCustomShape->pHandles )
2102         {
2103             sal_uInt32 i, nCnt = pDefCustomShape->nHandles;
2104             const SvxMSDffHandle* pData = pDefCustomShape->pHandles;
2105             for ( i = 0; i < nCnt; i++, pData++ )
2106             {
2107                 if ( pData->nFlags & SvxMSDffHandleFlags::POLAR )
2108                 {
2109                     if ( ( pData->nPositionY >= 0x256 ) || ( pData->nPositionY <= 0x107 ) )
2110                         nAdjustmentsWhichNeedsToBeConverted |= ( 1U << i );
2111                 }
2112             }
2113         }
2114     }
2115 
2116     // "Path" PropertySequence element
2117 
2118     {
2119         PropVec aPathPropVec;
2120 
2121         // "Path/ExtrusionAllowed"
2122         if ( IsHardAttribute( DFF_Prop_f3DOK ) )
2123         {
2124             const OUString sExtrusionAllowed( "ExtrusionAllowed" );
2125             bool bExtrusionAllowed = ( GetPropertyValue( DFF_Prop_fFillOK, 0 ) & 16 ) != 0;
2126             aProp.Name = sExtrusionAllowed;
2127             aProp.Value <<= bExtrusionAllowed;
2128             aPathPropVec.push_back( aProp );
2129         }
2130         // "Path/ConcentricGradientFillAllowed"
2131         if ( IsHardAttribute( DFF_Prop_fFillShadeShapeOK ) )
2132         {
2133             const OUString sConcentricGradientFillAllowed( "ConcentricGradientFillAllowed" );
2134             bool bConcentricGradientFillAllowed = ( GetPropertyValue( DFF_Prop_fFillOK, 0 ) & 2 ) != 0;
2135             aProp.Name = sConcentricGradientFillAllowed;
2136             aProp.Value <<= bConcentricGradientFillAllowed;
2137             aPathPropVec.push_back( aProp );
2138         }
2139         // "Path/TextPathAllowed"
2140         if ( IsHardAttribute( DFF_Prop_fGtextOK ) || ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x4000 ) )
2141         {
2142             const OUString sTextPathAllowed( "TextPathAllowed" );
2143             bool bTextPathAllowed = ( GetPropertyValue( DFF_Prop_fFillOK, 0 ) & 4 ) != 0;
2144             aProp.Name = sTextPathAllowed;
2145             aProp.Value <<= bTextPathAllowed;
2146             aPathPropVec.push_back( aProp );
2147         }
2148         // Path/Coordinates
2149         if ( IsProperty( DFF_Prop_pVertices ) )
2150         {
2151             css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aCoordinates;
2152             sal_uInt16 nNumElemVert = 0;
2153             sal_uInt16 nElemSizeVert = 8;
2154 
2155             if ( SeekToContent( DFF_Prop_pVertices, rIn ) )
2156             {
2157                 sal_uInt16 nNumElemMemVert = 0;
2158                 rIn.ReadUInt16( nNumElemVert ).ReadUInt16( nNumElemMemVert ).ReadUInt16( nElemSizeVert );
2159                 // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
2160                 // low-order bytes are recorded
2161                 if (nElemSizeVert == 0xFFF0)
2162                     nElemSizeVert = 4;
2163             }
2164             //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
2165             bool bImport = nElemSizeVert && (rIn.remainingSize() / nElemSizeVert >= nNumElemVert);
2166             if (bImport)
2167             {
2168                 aCoordinates.realloc( nNumElemVert );
2169                 for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
2170                 {
2171                     sal_Int32 nX(0), nY(0);
2172 
2173                     if ( nElemSizeVert == 8 )
2174                     {
2175                         rIn.ReadInt32( nX )
2176                            .ReadInt32( nY );
2177                     }
2178                     else
2179                     {
2180                         sal_Int16 nTmpA(0), nTmpB(0);
2181                         rIn.ReadInt16( nTmpA )
2182                            .ReadInt16( nTmpB );
2183 
2184                         nX = nTmpA;
2185                         nY = nTmpB;
2186                     }
2187                     EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aCoordinates[ i ].First, nX );
2188                     EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aCoordinates[ i ].Second, nY );
2189                 }
2190             }
2191             const OUString sCoordinates( "Coordinates" );
2192             aProp.Name = sCoordinates;
2193             aProp.Value <<= aCoordinates;
2194             aPathPropVec.push_back( aProp );
2195         }
2196         // Path/Segments
2197         if ( IsProperty( DFF_Prop_pSegmentInfo ) )
2198         {
2199             css::uno::Sequence< css::drawing::EnhancedCustomShapeSegment > aSegments;
2200 
2201             sal_uInt16 nNumElemSeg = 0;
2202 
2203             if ( SeekToContent( DFF_Prop_pSegmentInfo, rIn ) )
2204             {
2205                 sal_uInt16 nNumElemMemSeg = 0;
2206                 sal_uInt16 nElemSizeSeg = 2;
2207                 rIn.ReadUInt16( nNumElemSeg ).ReadUInt16( nNumElemMemSeg ).ReadUInt16( nElemSizeSeg );
2208             }
2209             std::size_t nMaxEntriesPossible = rIn.remainingSize() / sizeof(sal_uInt16);
2210             if (nNumElemSeg > nMaxEntriesPossible)
2211             {
2212                 SAL_WARN("filter.ms", "NumElem list is longer than remaining bytes, ppt or parser is wrong");
2213                 nNumElemSeg = nMaxEntriesPossible;
2214             }
2215             if ( nNumElemSeg )
2216             {
2217                 aSegments.realloc( nNumElemSeg );
2218                 for (sal_uInt16 i = 0; i < nNumElemSeg; ++i)
2219                 {
2220                     sal_uInt16 nTmp(0);
2221                     rIn.ReadUInt16( nTmp );
2222                     sal_Int16 nCommand = EnhancedCustomShapeSegmentCommand::UNKNOWN;
2223                     sal_Int16 nCnt = static_cast<sal_Int16>( nTmp & 0x1fff );//Last 13 bits for segment points number
2224                     switch( nTmp >> 13 )//First 3 bits for command type
2225                     {
2226                         case 0x0:
2227                             nCommand = EnhancedCustomShapeSegmentCommand::LINETO;
2228                             if ( !nCnt ) nCnt = 1;
2229                             break;
2230                         case 0x1:
2231                             nCommand = EnhancedCustomShapeSegmentCommand::CURVETO;
2232                             if ( !nCnt ) nCnt = 1;
2233                             break;
2234                         case 0x2:
2235                             nCommand = EnhancedCustomShapeSegmentCommand::MOVETO;
2236                             if ( !nCnt ) nCnt = 1;
2237                             break;
2238                         case 0x3:
2239                             nCommand = EnhancedCustomShapeSegmentCommand::CLOSESUBPATH;
2240                             nCnt = 0;
2241                             break;
2242                         case 0x4:
2243                             nCommand = EnhancedCustomShapeSegmentCommand::ENDSUBPATH;
2244                             nCnt = 0;
2245                             break;
2246                         case 0x5:
2247                         case 0x6:
2248                         {
2249                             switch ( ( nTmp >> 8 ) & 0x1f )//5 bits next to command type is for path escape type
2250                             {
2251                                 case 0x0:
2252                                 {
2253                                     //It is msopathEscapeExtension which is transformed into LINETO.
2254                                     //If issue happens, I think this part can be comment so that it will be taken as unknown command.
2255                                     //When export, origin data will be export without any change.
2256                                     nCommand = EnhancedCustomShapeSegmentCommand::LINETO;
2257                                     if ( !nCnt )
2258                                         nCnt = 1;
2259                                 }
2260                                 break;
2261                                 case 0x1:
2262                                 {
2263                                     nCommand = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSETO;
2264                                     nCnt = ( nTmp & 0xff ) / 3;
2265                                 }
2266                                 break;
2267                                 case 0x2:
2268                                 {
2269                                     nCommand = EnhancedCustomShapeSegmentCommand::ANGLEELLIPSE;
2270                                     nCnt = ( nTmp & 0xff ) / 3;
2271                                 }
2272                                 break;
2273                                 case 0x3:
2274                                 {
2275                                     nCommand = EnhancedCustomShapeSegmentCommand::ARCTO;
2276                                     nCnt = ( nTmp & 0xff ) >> 2;
2277                                 };
2278                                 break;
2279                                 case 0x4:
2280                                 {
2281                                     nCommand = EnhancedCustomShapeSegmentCommand::ARC;
2282                                     nCnt = ( nTmp & 0xff ) >> 2;
2283                                 }
2284                                 break;
2285                                 case 0x5:
2286                                 {
2287                                     nCommand = EnhancedCustomShapeSegmentCommand::CLOCKWISEARCTO;
2288                                     nCnt = ( nTmp & 0xff ) >> 2;
2289                                 }
2290                                 break;
2291                                 case 0x6:
2292                                 {
2293                                     nCommand = EnhancedCustomShapeSegmentCommand::CLOCKWISEARC;
2294                                     nCnt = ( nTmp & 0xff ) >> 2;
2295                                 }
2296                                 break;
2297                                 case 0x7:
2298                                 {
2299                                     nCommand = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTX;
2300                                     nCnt = nTmp & 0xff;
2301                                 }
2302                                 break;
2303                                 case 0x8:
2304                                 {
2305                                     nCommand = EnhancedCustomShapeSegmentCommand::ELLIPTICALQUADRANTY;
2306                                     nCnt = nTmp & 0xff;
2307                                 }
2308                                 break;
2309                                 case 0xa: nCommand = EnhancedCustomShapeSegmentCommand::NOFILL; nCnt = 0; break;
2310                                 case 0xb: nCommand = EnhancedCustomShapeSegmentCommand::NOSTROKE; nCnt = 0; break;
2311                             }
2312                         }
2313                         break;
2314                     }
2315                     // if the command is unknown, we will store all the data in nCnt, so it will be possible to export without loss
2316                     if ( nCommand == EnhancedCustomShapeSegmentCommand::UNKNOWN )
2317                         nCnt = static_cast<sal_Int16>(nTmp);
2318                     aSegments[ i ].Command = nCommand;
2319                     aSegments[ i ].Count = nCnt;
2320                 }
2321             }
2322             const OUString sSegments( "Segments" );
2323             aProp.Name = sSegments;
2324             aProp.Value <<= aSegments;
2325             aPathPropVec.push_back( aProp );
2326         }
2327         // Path/StretchX
2328         if ( IsProperty( DFF_Prop_stretchPointX ) )
2329         {
2330             const OUString sStretchX( "StretchX" );
2331             sal_Int32 nStretchX = GetPropertyValue( DFF_Prop_stretchPointX, 0 );
2332             aProp.Name = sStretchX;
2333             aProp.Value <<= nStretchX;
2334             aPathPropVec.push_back( aProp );
2335         }
2336         // Path/StretchX
2337         if ( IsProperty( DFF_Prop_stretchPointY ) )
2338         {
2339             const OUString sStretchY( "StretchY" );
2340             sal_Int32 nStretchY = GetPropertyValue( DFF_Prop_stretchPointY, 0 );
2341             aProp.Name = sStretchY;
2342             aProp.Value <<= nStretchY;
2343             aPathPropVec.push_back( aProp );
2344         }
2345         // Path/TextFrames
2346         if ( IsProperty( DFF_Prop_textRectangles ) )
2347         {
2348             sal_uInt16 nNumElem = 0;
2349             sal_uInt16 nElemSize = 16;
2350 
2351             if ( SeekToContent( DFF_Prop_textRectangles, rIn ) )
2352             {
2353                 sal_uInt16 nNumElemMem = 0;
2354                 rIn.ReadUInt16( nNumElem ).ReadUInt16( nNumElemMem ).ReadUInt16( nElemSize );
2355             }
2356             bool bImport = false;
2357             if (nElemSize == 16)
2358             {
2359                 //sanity check that the stream is long enough to fulfill nNumElem * nElemSize;
2360                 bImport = rIn.remainingSize() / nElemSize >= nNumElem;
2361             }
2362             if (bImport)
2363             {
2364                 css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > aTextFrames( nNumElem );
2365                 for (sal_uInt16 i = 0; i < nNumElem; ++i)
2366                 {
2367                     sal_Int32 nLeft(0), nTop(0), nRight(0), nBottom(0);
2368 
2369                     rIn.ReadInt32( nLeft )
2370                        .ReadInt32( nTop )
2371                        .ReadInt32( nRight )
2372                        .ReadInt32( nBottom );
2373 
2374                     EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].TopLeft.First,  nLeft );
2375                     EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].TopLeft.Second, nTop  );
2376                     EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].BottomRight.First,  nRight );
2377                     EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrames[ i ].BottomRight.Second, nBottom);
2378                 }
2379                 const OUString sTextFrames( "TextFrames" );
2380                 aProp.Name = sTextFrames;
2381                 aProp.Value <<= aTextFrames;
2382                 aPathPropVec.push_back( aProp );
2383             }
2384         }
2385         //Path/GluePoints
2386         if ( IsProperty( DFF_Prop_connectorPoints ) )
2387         {
2388             css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair > aGluePoints;
2389             sal_uInt16 nNumElemVert = 0;
2390             sal_uInt16 nNumElemMemVert = 0;
2391             sal_uInt16 nElemSizeVert = 8;
2392 
2393             if ( SeekToContent( DFF_Prop_connectorPoints, rIn ) )
2394             {
2395                 rIn.ReadUInt16( nNumElemVert ).ReadUInt16( nNumElemMemVert ).ReadUInt16( nElemSizeVert );
2396                 // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
2397                 // low-order bytes are recorded
2398                 if (nElemSizeVert == 0xFFF0)
2399                     nElemSizeVert = 4;
2400             }
2401 
2402             // sanity check that the stream is long enough to fulfill nNumElemVert * nElemSizeVert;
2403             bool bImport = nElemSizeVert && (rIn.remainingSize() / nElemSizeVert >= nNumElemVert);
2404             if (bImport)
2405             {
2406                 aGluePoints.realloc( nNumElemVert );
2407                 for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
2408                 {
2409                     sal_Int32 nX(0), nY(0);
2410                     if ( nElemSizeVert == 8 )
2411                     {
2412                         rIn.ReadInt32( nX )
2413                            .ReadInt32( nY );
2414                     }
2415                     else
2416                     {
2417                         sal_Int16 nTmpA(0), nTmpB(0);
2418 
2419                         rIn.ReadInt16( nTmpA )
2420                            .ReadInt16( nTmpB );
2421 
2422                         nX = nTmpA;
2423                         nY = nTmpB;
2424                     }
2425                     EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ i ].First,  nX );
2426                     EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aGluePoints[ i ].Second, nY );
2427                 }
2428             }
2429             const OUString sGluePoints( "GluePoints" );
2430             aProp.Name = sGluePoints;
2431             aProp.Value <<= aGluePoints;
2432             aPathPropVec.push_back( aProp );
2433         }
2434         if ( IsProperty( DFF_Prop_connectorType ) )
2435         {
2436             sal_Int16 nGluePointType = static_cast<sal_uInt16>(GetPropertyValue( DFF_Prop_connectorType, 0 ));
2437             const OUString sGluePointType( "GluePointType" );
2438             aProp.Name = sGluePointType;
2439             aProp.Value <<= nGluePointType;
2440             aPathPropVec.push_back( aProp );
2441         }
2442         // pushing the whole Path element
2443         if ( !aPathPropVec.empty() )
2444         {
2445             aProp.Name = "Path";
2446             aProp.Value <<= comphelper::containerToSequence(aPathPropVec);
2447             aPropVec.push_back( aProp );
2448         }
2449     }
2450 
2451     // "TextPath" PropertySequence element
2452 
2453     bool bTextPathOn = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x4000 ) != 0;
2454     if ( bTextPathOn )
2455     {
2456         PropVec aTextPathPropVec;
2457 
2458         // TextPath
2459         const OUString sTextPathOn( "TextPath" );
2460         aProp.Name = sTextPathOn;
2461         aProp.Value <<= bTextPathOn;
2462         aTextPathPropVec.push_back( aProp );
2463 
2464         // TextPathMode
2465         const OUString sTextPathMode( "TextPathMode" );
2466         bool bTextPathFitPath = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x100 ) != 0;
2467 
2468         bool bTextPathFitShape;
2469         if ( IsHardAttribute( DFF_Prop_gtextFStretch ) )
2470             bTextPathFitShape = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x400 ) != 0;
2471         else
2472         {
2473             bTextPathFitShape = true;
2474             switch( rObjData.eShapeType )
2475             {
2476                 case mso_sptTextArchUpCurve :
2477                 case mso_sptTextArchDownCurve :
2478                 case mso_sptTextCircleCurve :
2479                 case mso_sptTextButtonCurve :
2480                     bTextPathFitShape = false;
2481                     break;
2482                 default : break;
2483             }
2484         }
2485         EnhancedCustomShapeTextPathMode eTextPathMode( EnhancedCustomShapeTextPathMode_NORMAL );
2486         if ( bTextPathFitShape )
2487             eTextPathMode = EnhancedCustomShapeTextPathMode_SHAPE;
2488         else if ( bTextPathFitPath )
2489             eTextPathMode = EnhancedCustomShapeTextPathMode_PATH;
2490         aProp.Name = sTextPathMode;
2491         aProp.Value <<= eTextPathMode;
2492         aTextPathPropVec.push_back( aProp );
2493 
2494         // ScaleX
2495         const OUString sTextPathScaleX( "ScaleX" );
2496         bool bTextPathScaleX = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x40 ) != 0;
2497         aProp.Name = sTextPathScaleX;
2498         aProp.Value <<= bTextPathScaleX;
2499         aTextPathPropVec.push_back( aProp );
2500         // SameLetterHeights
2501         const OUString sSameLetterHeight( "SameLetterHeights" );
2502         bool bSameLetterHeight = ( GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 ) & 0x80 ) != 0;
2503         aProp.Name = sSameLetterHeight;
2504         aProp.Value <<= bSameLetterHeight;
2505         aTextPathPropVec.push_back( aProp );
2506 
2507         // pushing the whole TextPath element
2508         aProp.Name = "TextPath";
2509         aProp.Value <<= comphelper::containerToSequence(aTextPathPropVec);
2510         aPropVec.push_back( aProp );
2511     }
2512 
2513     // "AdjustmentValues" // The AdjustmentValues are imported at last, because depending to the type of the
2514     //////////////////////// handle (POLAR) we will convert the adjustment value from a fixed float to double
2515 
2516     // checking the last used adjustment handle, so we can determine how many handles are to allocate
2517     sal_uInt32 i = DFF_Prop_adjust10Value;
2518     while ( ( i >= DFF_Prop_adjustValue ) && !IsProperty( i ) )
2519         i--;
2520     sal_Int32 nAdjustmentValues = ( i - DFF_Prop_adjustValue ) + 1;
2521     if ( nAdjustmentValues )
2522     {
2523         uno::Sequence< css::drawing::EnhancedCustomShapeAdjustmentValue > aAdjustmentSeq( nAdjustmentValues );
2524         while( --nAdjustmentValues >= 0 )
2525         {
2526             sal_Int32 nValue = 0;
2527             beans::PropertyState ePropertyState = beans::PropertyState_DEFAULT_VALUE;
2528             if ( IsProperty( i ) )
2529             {
2530                 nValue = GetPropertyValue( i, 0 );
2531                 ePropertyState = beans::PropertyState_DIRECT_VALUE;
2532             }
2533             if ( nAdjustmentsWhichNeedsToBeConverted & ( 1 << ( i - DFF_Prop_adjustValue ) ) )
2534             {
2535                 double fValue = nValue;
2536                 fValue /= 65536;
2537                 aAdjustmentSeq[ nAdjustmentValues ].Value <<= fValue;
2538             }
2539             else
2540                 aAdjustmentSeq[ nAdjustmentValues ].Value <<= nValue;
2541             aAdjustmentSeq[ nAdjustmentValues ].State = ePropertyState;
2542             i--;
2543         }
2544         const OUString sAdjustmentValues( "AdjustmentValues" );
2545         aProp.Name = sAdjustmentValues;
2546         aProp.Value <<= aAdjustmentSeq;
2547         aPropVec.push_back( aProp );
2548     }
2549 
2550     // creating the whole property set
2551     rSet.Put( SdrCustomShapeGeometryItem( comphelper::containerToSequence(aPropVec) ) );
2552 }
2553 
2554 void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet ) const
2555 {
2556     DffRecordHeader aHdTemp;
2557     DffObjData aDffObjTemp( aHdTemp, tools::Rectangle(), 0 );
2558     ApplyAttributes( rIn, rSet, aDffObjTemp );
2559 }
2560 
2561 void DffPropertyReader::ApplyAttributes( SvStream& rIn, SfxItemSet& rSet, DffObjData const & rObjData ) const
2562 {
2563     bool bHasShadow = false;
2564     bool bNonZeroShadowOffset = false;
2565 
2566     if ( IsProperty( DFF_Prop_gtextSize ) )
2567         rSet.Put( SvxFontHeightItem( rManager.ScalePt( GetPropertyValue( DFF_Prop_gtextSize, 0 ) ), 100, EE_CHAR_FONTHEIGHT ) );
2568     sal_uInt32 nFontAttributes = GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 );
2569     if ( nFontAttributes & 0x20 )
2570         rSet.Put( SvxWeightItem( (nFontAttributes & 0x20) ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) );
2571     if ( nFontAttributes & 0x10 )
2572         rSet.Put( SvxPostureItem( (nFontAttributes & 0x10) ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) );
2573     if ( nFontAttributes & 0x08 )
2574         rSet.Put( SvxUnderlineItem( (nFontAttributes & 0x08) ? LINESTYLE_SINGLE : LINESTYLE_NONE, EE_CHAR_UNDERLINE ) );
2575     if ( nFontAttributes & 0x40 )
2576         rSet.Put( SvxShadowedItem( (nFontAttributes & 0x40) != 0, EE_CHAR_SHADOW ) );
2577 //    if ( nFontAttributes & 0x02 )
2578 //        rSet.Put( SvxCaseMapItem( nFontAttributes & 0x02 ? SvxCaseMap::SmallCaps : SvxCaseMap::NotMapped ) );
2579     if ( nFontAttributes & 0x01 )
2580         rSet.Put( SvxCrossedOutItem( (nFontAttributes & 0x01) ? STRIKEOUT_SINGLE : STRIKEOUT_NONE, EE_CHAR_STRIKEOUT ) );
2581     if ( IsProperty( DFF_Prop_fillColor ) )
2582         rSet.Put( XFillColorItem( OUString(), rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor, 0 ), DFF_Prop_fillColor ) ) );
2583     if ( IsProperty( DFF_Prop_shadowColor ) )
2584         rSet.Put( makeSdrShadowColorItem( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_shadowColor, 0 ), DFF_Prop_shadowColor ) ) );
2585     else
2586     {
2587         //The default value for this property is 0x00808080
2588         rSet.Put( makeSdrShadowColorItem( rManager.MSO_CLR_ToColor( 0x00808080, DFF_Prop_shadowColor ) ) );
2589     }
2590     if ( IsProperty( DFF_Prop_shadowOpacity ) )
2591         rSet.Put( makeSdrShadowTransparenceItem( static_cast<sal_uInt16>( ( 0x10000 - GetPropertyValue( DFF_Prop_shadowOpacity, 0 ) ) / 655 ) ) );
2592     if ( IsProperty( DFF_Prop_shadowOffsetX ) )
2593     {
2594         sal_Int32 nVal = static_cast< sal_Int32 >( GetPropertyValue( DFF_Prop_shadowOffsetX, 0 ) );
2595         rManager.ScaleEmu( nVal );
2596         rSet.Put( makeSdrShadowXDistItem( nVal ) );
2597         bNonZeroShadowOffset = ( nVal > 0 );
2598     }
2599     if ( IsProperty( DFF_Prop_shadowOffsetY ) )
2600     {
2601         sal_Int32 nVal = static_cast< sal_Int32 >( GetPropertyValue( DFF_Prop_shadowOffsetY, 0 ) );
2602         rManager.ScaleEmu( nVal );
2603         rSet.Put( makeSdrShadowYDistItem( nVal ) );
2604         bNonZeroShadowOffset = ( nVal > 0 );
2605     }
2606     if ( IsProperty( DFF_Prop_fshadowObscured ) )
2607     {
2608         bHasShadow = ( GetPropertyValue( DFF_Prop_fshadowObscured, 0 ) & 2 ) != 0;
2609         if ( bHasShadow )
2610         {
2611             if ( !IsProperty( DFF_Prop_shadowOffsetX ) )
2612                 rSet.Put( makeSdrShadowXDistItem( 35 ) );
2613             if ( !IsProperty( DFF_Prop_shadowOffsetY ) )
2614                 rSet.Put( makeSdrShadowYDistItem( 35 ) );
2615         }
2616     }
2617     if ( IsProperty( DFF_Prop_shadowType ) )
2618     {
2619         MSO_ShadowType eShadowType = static_cast< MSO_ShadowType >( GetPropertyValue( DFF_Prop_shadowType, 0 ) );
2620         if( eShadowType != mso_shadowOffset && !bNonZeroShadowOffset )
2621         {
2622             //0.12" == 173 twip == 302 100mm
2623             sal_uInt32 nDist = rManager.pSdrModel->GetScaleUnit() == MapUnit::MapTwip ? 173: 302;
2624             rSet.Put( makeSdrShadowXDistItem( nDist ) );
2625             rSet.Put( makeSdrShadowYDistItem( nDist ) );
2626         }
2627     }
2628     if ( bHasShadow )
2629     {
2630         static bool bCheckShadow(false);
2631 
2632         // #i124477# Found no reason not to set shadow, esp. since it is applied to evtl. existing text
2633         // and will lead to an error if in PPT someone used text and added the object shadow to the
2634         // object carrying that text. I found no cases where this leads to problems (the old bugtracker
2635         // task #160376# from sj is unfortunately no longer available). Keeping the code for now
2636         // to allow easy fallback when this shows problems in the future
2637         if(bCheckShadow)
2638         {
2639             // #160376# sj: activating shadow only if fill and or linestyle is used
2640             // this is required because of the latest drawing layer core changes.
2641             // #i104085# is related to this.
2642             sal_uInt32 nLineFlags(GetPropertyValue( DFF_Prop_fNoLineDrawDash, 0 ));
2643             if(!IsHardAttribute( DFF_Prop_fLine ) && !IsCustomShapeStrokedByDefault( rObjData.eShapeType ))
2644                 nLineFlags &= ~0x08;
2645             sal_uInt32 nFillFlags(GetPropertyValue( DFF_Prop_fNoFillHitTest, 0 ));
2646             if(!IsHardAttribute( DFF_Prop_fFilled ) && !IsCustomShapeFilledByDefault( rObjData.eShapeType ))
2647                 nFillFlags &= ~0x10;
2648             if ( nFillFlags & 0x10 )
2649             {
2650                 MSO_FillType eMSO_FillType = static_cast<MSO_FillType>(GetPropertyValue( DFF_Prop_fillType, mso_fillSolid ));
2651                 switch( eMSO_FillType )
2652                 {
2653                     case mso_fillSolid :
2654                     case mso_fillPattern :
2655                     case mso_fillTexture :
2656                     case mso_fillPicture :
2657                     case mso_fillShade :
2658                     case mso_fillShadeCenter :
2659                     case mso_fillShadeShape :
2660                     case mso_fillShadeScale :
2661                     case mso_fillShadeTitle :
2662                     break;
2663                     default:
2664                         nFillFlags &=~0x10;         // no fillstyle used
2665                     break;
2666                 }
2667             }
2668             if ( ( ( nLineFlags & 0x08 ) == 0 ) && ( ( nFillFlags & 0x10 ) == 0 ) && ( rObjData.eShapeType != mso_sptPictureFrame ))    // if there is no fillstyle and linestyle
2669                 bHasShadow = false;                                             // we are turning shadow off.
2670         }
2671 
2672         if ( bHasShadow )
2673             rSet.Put( makeSdrShadowItem( bHasShadow ) );
2674     }
2675     ApplyLineAttributes( rSet, rObjData.eShapeType ); // #i28269#
2676     ApplyFillAttributes( rIn, rSet, rObjData );
2677     if ( rObjData.eShapeType != mso_sptNil || IsProperty( DFF_Prop_pVertices ) )
2678     {
2679         ApplyCustomShapeGeometryAttributes( rIn, rSet, rObjData );
2680         ApplyCustomShapeTextAttributes( rSet );
2681         if ( rManager.GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL )
2682         {
2683             if ( mnFix16Angle || ( rObjData.nSpFlags & ShapeFlag::FlipV ) )
2684                 CheckAndCorrectExcelTextRotation( rIn, rSet, rObjData );
2685         }
2686     }
2687 }
2688 
2689 void DffPropertyReader::CheckAndCorrectExcelTextRotation( SvStream& rIn, SfxItemSet& rSet, DffObjData const & rObjData ) const
2690 {
2691     bool bRotateTextWithShape = rObjData.bRotateTextWithShape;
2692     if ( rObjData.bOpt2 )        // sj: #158494# is the second property set available ? if then we have to check the xml data of
2693     {                            // the shape, because the textrotation of Excel 2003 and greater versions is stored there
2694                                 // (upright property of the textbox)
2695         if ( rManager.pSecPropSet->SeekToContent( DFF_Prop_metroBlob, rIn ) )
2696         {
2697             sal_uInt32 nLen = rManager.pSecPropSet->GetPropertyValue( DFF_Prop_metroBlob, 0 );
2698             if ( nLen )
2699             {
2700                 css::uno::Sequence< sal_Int8 > aXMLDataSeq( nLen );
2701                 rIn.ReadBytes(aXMLDataSeq.getArray(), nLen);
2702                 css::uno::Reference< css::io::XInputStream > xInputStream
2703                     ( new ::comphelper::SequenceInputStream( aXMLDataSeq ) );
2704                 try
2705                 {
2706                     css::uno::Reference< css::uno::XComponentContext > xContext( ::comphelper::getProcessComponentContext() );
2707                     css::uno::Reference< css::embed::XStorage > xStorage
2708                         ( ::comphelper::OStorageHelper::GetStorageOfFormatFromInputStream(
2709                             OFOPXML_STORAGE_FORMAT_STRING, xInputStream, xContext, true ) );
2710                     if ( xStorage.is() )
2711                     {
2712                         const OUString sDRS( "drs" );
2713                         css::uno::Reference< css::embed::XStorage >
2714                             xStorageDRS( xStorage->openStorageElement( sDRS, css::embed::ElementModes::SEEKABLEREAD ) );
2715                         if ( xStorageDRS.is() )
2716                         {
2717                             const OUString sShapeXML( "shapexml.xml" );
2718                             css::uno::Reference< css::io::XStream > xShapeXMLStream( xStorageDRS->openStreamElement( sShapeXML, css::embed::ElementModes::SEEKABLEREAD ) );
2719                             if ( xShapeXMLStream.is() )
2720                             {
2721                                 css::uno::Reference< css::io::XInputStream > xShapeXMLInputStream( xShapeXMLStream->getInputStream() );
2722                                 if ( xShapeXMLInputStream.is() )
2723                                 {
2724                                     css::uno::Sequence< sal_Int8 > aSeq;
2725                                     sal_Int32 nBytesRead = xShapeXMLInputStream->readBytes( aSeq, 0x7fffffff );
2726                                     if ( nBytesRead )
2727                                     {    // for only one property I spare to use a XML parser at this point, this
2728                                         // should be enhanced if needed
2729 
2730                                         bRotateTextWithShape = true;    // using the correct xml default
2731                                         const char* pArry = reinterpret_cast< char* >( aSeq.getArray() );
2732                                         const char* const pUpright = "upright=";
2733                                         const char* pEnd = pArry + nBytesRead;
2734                                         const char* pPtr = pArry;
2735                                         while( ( pPtr + 12 ) < pEnd )
2736                                         {
2737                                             if ( !memcmp( pUpright, pPtr, 8 ) )
2738                                             {
2739                                                 bRotateTextWithShape = ( pPtr[ 9 ] != '1' ) && ( pPtr[ 9 ] != 't' );
2740                                                 break;
2741                                             }
2742                                             else
2743                                                 pPtr++;
2744                                         }
2745                                     }
2746                                 }
2747                             }
2748                         }
2749                     }
2750                 }
2751                 catch( css::uno::Exception& )
2752                 {
2753                 }
2754             }
2755         }
2756     }
2757     if ( !bRotateTextWithShape )
2758     {
2759         const css::uno::Any* pAny;
2760         SdrCustomShapeGeometryItem aGeometryItem(rSet.Get( SDRATTR_CUSTOMSHAPE_GEOMETRY ));
2761         const OUString sTextRotateAngle( "TextRotateAngle" );
2762         pAny = aGeometryItem.GetPropertyValueByName( sTextRotateAngle );
2763         double fExtraTextRotateAngle = 0.0;
2764         if ( pAny )
2765             *pAny >>= fExtraTextRotateAngle;
2766 
2767         if ( rManager.mnFix16Angle )
2768             fExtraTextRotateAngle += mnFix16Angle / 100.0;
2769         if ( rObjData.nSpFlags & ShapeFlag::FlipV )
2770             fExtraTextRotateAngle -= 180.0;
2771 
2772         css::beans::PropertyValue aTextRotateAngle;
2773         aTextRotateAngle.Name = sTextRotateAngle;
2774         aTextRotateAngle.Value <<= fExtraTextRotateAngle;
2775         aGeometryItem.SetPropertyValue( aTextRotateAngle );
2776         rSet.Put( aGeometryItem );
2777     }
2778 }
2779 
2780 
2781 void DffPropertyReader::ImportGradientColor( SfxItemSet& aSet,MSO_FillType eMSO_FillType, double dTrans , double dBackTrans) const
2782 {
2783     //MS Focus prop will impact the start and end color position. And AOO does not
2784     //support this prop. So need some swap for the two color to keep fidelity with AOO and MS shape.
2785     //So below var is defined.
2786     sal_Int32 nChgColors = 0;
2787     sal_Int32 nAngle = GetPropertyValue( DFF_Prop_fillAngle, 0 );
2788     sal_Int32 nRotateAngle = 0;
2789     if(nAngle >= 0)
2790         nChgColors ^= 1;
2791 
2792     //Translate a MS clockwise(+) or count clockwise angle(-) into a AOO count clock wise angle
2793     nAngle=3600 - ( ( Fix16ToAngle(nAngle) + 5 ) / 10 );
2794     //Make sure this angle belongs to 0~3600
2795     while ( nAngle >= 3600 ) nAngle -= 3600;
2796     while ( nAngle < 0 ) nAngle += 3600;
2797 
2798     //Rotate angle
2799     if ( mbRotateGranientFillWithAngle )
2800     {
2801         nRotateAngle = GetPropertyValue( DFF_Prop_Rotation, 0 );
2802         if(nRotateAngle)//fixed point number
2803             nRotateAngle = ( static_cast<sal_Int16>( nRotateAngle >> 16) * 100L ) + ( ( ( nRotateAngle & 0x0000ffff) * 100L ) >> 16 );
2804         nRotateAngle = ( nRotateAngle + 5 ) / 10 ;//round up
2805         //nAngle is a clockwise angle. If nRotateAngle is a clockwise angle, then gradient need be rotated a little less
2806         //Or it need be rotated a little more
2807         nAngle -=  nRotateAngle;
2808     }
2809     while ( nAngle >= 3600 ) nAngle -= 3600;
2810     while ( nAngle < 0 ) nAngle += 3600;
2811 
2812     css::awt::GradientStyle eGrad = css::awt::GradientStyle_LINEAR;
2813 
2814     sal_Int32 nFocus = GetPropertyValue( DFF_Prop_fillFocus, 0 );
2815     if ( !nFocus )
2816         nChgColors ^= 1;
2817     else if ( nFocus < 0 )//If it is a negative focus, the color will be swapped
2818     {
2819         nFocus = o3tl::saturating_toggle_sign(nFocus);
2820         nChgColors ^= 1;
2821     }
2822 
2823     if( nFocus > 40 && nFocus < 60 )
2824     {
2825         eGrad = css::awt::GradientStyle_AXIAL;//A axial gradient other than linear
2826         nChgColors ^= 1;
2827     }
2828     //if the type is linear or axial, just save focus to nFocusX and nFocusY for export
2829     //Core function does no need them. They serves for rect gradient(CenterXY).
2830     sal_uInt16 nFocusX = static_cast<sal_uInt16>(nFocus);
2831     sal_uInt16 nFocusY = static_cast<sal_uInt16>(nFocus);
2832 
2833     switch( eMSO_FillType )
2834     {
2835     case mso_fillShadeShape :
2836         {
2837             eGrad = css::awt::GradientStyle_RECT;
2838             nFocusY = nFocusX = 50;
2839             nChgColors ^= 1;
2840         }
2841         break;
2842     case mso_fillShadeCenter :
2843         {
2844             eGrad = css::awt::GradientStyle_RECT;
2845             //A MS fillTo prop specifies the relative position of the left boundary
2846             //of the center rectangle in a concentric shaded fill. Use 100 or 0 to keep fidelity
2847             nFocusX=(GetPropertyValue( DFF_Prop_fillToRight, 0 )==0x10000) ? 100 : 0;
2848             nFocusY=(GetPropertyValue( DFF_Prop_fillToBottom,0 )==0x10000) ? 100 : 0;
2849             nChgColors ^= 1;
2850         }
2851         break;
2852         default: break;
2853     }
2854 
2855     Color aCol1( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillColor, sal_uInt32(COL_WHITE) ), DFF_Prop_fillColor ) );
2856     Color aCol2( rManager.MSO_CLR_ToColor( GetPropertyValue( DFF_Prop_fillBackColor, sal_uInt32(COL_WHITE) ), DFF_Prop_fillBackColor ) );
2857     if ( nChgColors )
2858     {
2859         //Swap start and end color
2860         Color aZwi( aCol1 );
2861         aCol1 = aCol2;
2862         aCol2 = aZwi;
2863         //Swap two colors' transparency
2864         double dTemp = dTrans;
2865         dTrans = dBackTrans;
2866         dBackTrans = dTemp;
2867     }
2868 
2869     //Construct gradient item
2870     XGradient aGrad( aCol2, aCol1, eGrad, nAngle, nFocusX, nFocusY );
2871     //Intensity has been merged into color. So here just set is as 100
2872     aGrad.SetStartIntens( 100 );
2873     aGrad.SetEndIntens( 100 );
2874     aSet.Put( XFillGradientItem( OUString(), aGrad ) );
2875     //Construct tranparency item. This item can coordinate with both solid and gradient.
2876     if ( dTrans < 1.0 || dBackTrans < 1.0 )
2877     {
2878         sal_uInt8 nStartCol = static_cast<sal_uInt8>( (1 - dTrans )* 255 );
2879         sal_uInt8 nEndCol = static_cast<sal_uInt8>( ( 1- dBackTrans ) * 255 );
2880         aCol1 = Color(nStartCol, nStartCol, nStartCol);
2881         aCol2 = Color(nEndCol, nEndCol, nEndCol);
2882 
2883         XGradient aGrad2( aCol2 ,  aCol1 , eGrad, nAngle, nFocusX, nFocusY );
2884         aSet.Put( XFillFloatTransparenceItem( OUString(), aGrad2 ) );
2885     }
2886 }
2887 
2888 
2889 //- Record Manager ----------------------------------------------------------
2890 
2891 
2892 DffRecordList::DffRecordList( DffRecordList* pList ) :
2893     nCount                  ( 0 ),
2894     nCurrent                ( 0 ),
2895     pPrev                   ( pList )
2896 {
2897     if ( pList )
2898         pList->pNext.reset( this );
2899 }
2900 
2901 DffRecordList::~DffRecordList()
2902 {
2903 }
2904 
2905 DffRecordManager::DffRecordManager() :
2906     DffRecordList   ( nullptr ),
2907     pCList          ( static_cast<DffRecordList*>(this) )
2908 {
2909 }
2910 
2911 DffRecordManager::DffRecordManager( SvStream& rIn ) :
2912     DffRecordList   ( nullptr ),
2913     pCList          ( static_cast<DffRecordList*>(this) )
2914 {
2915     Consume( rIn );
2916 }
2917 
2918 void DffRecordManager::Consume( SvStream& rIn, sal_uInt32 nStOfs )
2919 {
2920     Clear();
2921     sal_uInt32 nOldPos = rIn.Tell();
2922     if ( !nStOfs )
2923     {
2924         DffRecordHeader aHd;
2925         bool bOk = ReadDffRecordHeader( rIn, aHd );
2926         if (bOk && aHd.nRecVer == DFF_PSFLAG_CONTAINER)
2927             nStOfs = aHd.GetRecEndFilePos();
2928     }
2929     if ( nStOfs )
2930     {
2931         pCList = static_cast<DffRecordList*>(this);
2932         while ( pCList->pNext )
2933             pCList = pCList->pNext.get();
2934         while (rIn.good() && ( ( rIn.Tell() + 8 ) <=  nStOfs ))
2935         {
2936             if ( pCList->nCount == DFF_RECORD_MANAGER_BUF_SIZE )
2937                 pCList = new DffRecordList( pCList );
2938             if (!ReadDffRecordHeader(rIn, pCList->mHd[ pCList->nCount ]))
2939                 break;
2940             bool bSeekSucceeded = pCList->mHd[ pCList->nCount++ ].SeekToEndOfRecord(rIn);
2941             if (!bSeekSucceeded)
2942                 break;
2943         }
2944         rIn.Seek( nOldPos );
2945     }
2946 }
2947 
2948 void DffRecordManager::Clear()
2949 {
2950     pCList = static_cast<DffRecordList*>(this);
2951     pNext.reset();
2952     nCurrent = 0;
2953     nCount = 0;
2954 }
2955 
2956 DffRecordHeader* DffRecordManager::Current()
2957 {
2958     DffRecordHeader* pRet = nullptr;
2959     if ( pCList->nCurrent < pCList->nCount )
2960         pRet = &pCList->mHd[ pCList->nCurrent ];
2961     return pRet;
2962 }
2963 
2964 DffRecordHeader* DffRecordManager::First()
2965 {
2966     DffRecordHeader* pRet = nullptr;
2967     pCList = static_cast<DffRecordList*>(this);
2968     if ( pCList->nCount )
2969     {
2970         pCList->nCurrent = 0;
2971         pRet = &pCList->mHd[ 0 ];
2972     }
2973     return pRet;
2974 }
2975 
2976 DffRecordHeader* DffRecordManager::Next()
2977 {
2978     DffRecordHeader* pRet = nullptr;
2979     sal_uInt32 nC = pCList->nCurrent + 1;
2980     if ( nC < pCList->nCount )
2981     {
2982         pCList->nCurrent++;
2983         pRet = &pCList->mHd[ nC ];
2984     }
2985     else if ( pCList->pNext )
2986     {
2987         pCList = pCList->pNext.get();
2988         pCList->nCurrent = 0;
2989         pRet = &pCList->mHd[ 0 ];
2990     }
2991     return pRet;
2992 }
2993 
2994 DffRecordHeader* DffRecordManager::Prev()
2995 {
2996     DffRecordHeader* pRet = nullptr;
2997     sal_uInt32 nCur = pCList->nCurrent;
2998     if ( !nCur && pCList->pPrev )
2999     {
3000         pCList = pCList->pPrev;
3001         nCur = pCList->nCount;
3002     }
3003     if ( nCur-- )
3004     {
3005         pCList->nCurrent = nCur;
3006         pRet = &pCList->mHd[ nCur ];
3007     }
3008     return pRet;
3009 }
3010 
3011 DffRecordHeader* DffRecordManager::Last()
3012 {
3013     DffRecordHeader* pRet = nullptr;
3014     while ( pCList->pNext )
3015         pCList = pCList->pNext.get();
3016     sal_uInt32 nCnt = pCList->nCount;
3017     if ( nCnt-- )
3018     {
3019         pCList->nCurrent = nCnt;
3020         pRet = &pCList->mHd[ nCnt ];
3021     }
3022     return pRet;
3023 }
3024 
3025 bool DffRecordManager::SeekToContent( SvStream& rIn, sal_uInt16 nRecId, DffSeekToContentMode eMode )
3026 {
3027     DffRecordHeader* pHd = GetRecordHeader( nRecId, eMode );
3028     if ( pHd )
3029     {
3030         pHd->SeekToContent( rIn );
3031         return true;
3032     }
3033     else
3034         return false;
3035 }
3036 
3037 DffRecordHeader* DffRecordManager::GetRecordHeader( sal_uInt16 nRecId, DffSeekToContentMode eMode )
3038 {
3039     sal_uInt32 nOldCurrent = pCList->nCurrent;
3040     DffRecordList* pOldList = pCList;
3041     DffRecordHeader* pHd;
3042 
3043     if ( eMode == SEEK_FROM_BEGINNING )
3044         pHd = First();
3045     else
3046         pHd = Next();
3047 
3048     while ( pHd )
3049     {
3050         if ( pHd->nRecType == nRecId )
3051             break;
3052         pHd = Next();
3053     }
3054     if ( !pHd && eMode == SEEK_FROM_CURRENT_AND_RESTART )
3055     {
3056         DffRecordHeader* pBreak = &pOldList->mHd[ nOldCurrent ];
3057         pHd = First();
3058         if ( pHd )
3059         {
3060             while ( pHd != pBreak )
3061             {
3062                 if ( pHd->nRecType == nRecId )
3063                     break;
3064                 pHd = Next();
3065             }
3066             if ( pHd->nRecType != nRecId )
3067                 pHd = nullptr;
3068         }
3069     }
3070     if ( !pHd )
3071     {
3072         pCList = pOldList;
3073         pOldList->nCurrent = nOldCurrent;
3074     }
3075     return pHd;
3076 }
3077 
3078 
3079 //  private methods
3080 
3081 
3082 bool CompareSvxMSDffShapeInfoById::operator() (
3083     std::shared_ptr<SvxMSDffShapeInfo> const& lhs,
3084     std::shared_ptr<SvxMSDffShapeInfo> const& rhs) const
3085 {
3086     return lhs->nShapeId < rhs->nShapeId;
3087 }
3088 
3089 bool CompareSvxMSDffShapeInfoByTxBxComp::operator() (
3090     std::shared_ptr<SvxMSDffShapeInfo> const& lhs,
3091     std::shared_ptr<SvxMSDffShapeInfo> const& rhs) const
3092 {
3093     return lhs->nTxBxComp < rhs->nTxBxComp;
3094 }
3095 
3096 void SvxMSDffManager::Scale( sal_Int32& rVal ) const
3097 {
3098     if ( bNeedMap )
3099         rVal = BigMulDiv( rVal, nMapMul, nMapDiv );
3100 }
3101 
3102 void SvxMSDffManager::Scale( Point& rPos ) const
3103 {
3104     rPos.AdjustX(nMapXOfs );
3105     rPos.AdjustY(nMapYOfs );
3106     if ( bNeedMap )
3107     {
3108         rPos.setX( BigMulDiv( rPos.X(), nMapMul, nMapDiv ) );
3109         rPos.setY( BigMulDiv( rPos.Y(), nMapMul, nMapDiv ) );
3110     }
3111 }
3112 
3113 void SvxMSDffManager::Scale( Size& rSiz ) const
3114 {
3115     if ( bNeedMap )
3116     {
3117         rSiz.setWidth( BigMulDiv( rSiz.Width(), nMapMul, nMapDiv ) );
3118         rSiz.setHeight( BigMulDiv( rSiz.Height(), nMapMul, nMapDiv ) );
3119     }
3120 }
3121 
3122 void SvxMSDffManager::ScaleEmu( sal_Int32& rVal ) const
3123 {
3124     rVal = BigMulDiv( rVal, nEmuMul, nEmuDiv );
3125 }
3126 
3127 sal_uInt32 SvxMSDffManager::ScalePt( sal_uInt32 nVal ) const
3128 {
3129     MapUnit eMap = pSdrModel->GetScaleUnit();
3130     Fraction aFact( GetMapFactor( MapUnit::MapPoint, eMap ).X() );
3131     long aMul = aFact.GetNumerator();
3132     long aDiv = aFact.GetDenominator() * 65536;
3133     aFact = Fraction( aMul, aDiv ); // try again to shorten it
3134     return BigMulDiv( nVal, aFact.GetNumerator(), aFact.GetDenominator() );
3135 }
3136 
3137 sal_Int32 SvxMSDffManager::ScalePoint( sal_Int32 nVal ) const
3138 {
3139     return BigMulDiv( nVal, nPntMul, nPntDiv );
3140 };
3141 
3142 void SvxMSDffManager::SetModel(SdrModel* pModel, long nApplicationScale)
3143 {
3144     pSdrModel = pModel;
3145     if( pModel && (0 < nApplicationScale) )
3146     {
3147         // PPT works in units of 576DPI
3148         // WW on the other side uses twips, i.e. 1440DPI.
3149         MapUnit eMap = pSdrModel->GetScaleUnit();
3150         Fraction aFact( GetMapFactor(MapUnit::MapInch, eMap).X() );
3151         long nMul=aFact.GetNumerator();
3152         long nDiv=aFact.GetDenominator()*nApplicationScale;
3153         aFact=Fraction(nMul,nDiv); // try again to shorten it
3154         // For 100TH_MM -> 2540/576=635/144
3155         // For Twip     -> 1440/576=5/2
3156         nMapMul  = aFact.GetNumerator();
3157         nMapDiv  = aFact.GetDenominator();
3158         bNeedMap = nMapMul!=nMapDiv;
3159 
3160         // MS-DFF-Properties are mostly given in EMU (English Metric Units)
3161         // 1mm=36000emu, 1twip=635emu
3162         aFact=GetMapFactor(MapUnit::Map100thMM,eMap).X();
3163         nMul=aFact.GetNumerator();
3164         nDiv=aFact.GetDenominator()*360;
3165         aFact=Fraction(nMul,nDiv); // try again to shorten it
3166         // For 100TH_MM ->                            1/360
3167         // For Twip     -> 14,40/(25,4*360)=144/91440=1/635
3168         nEmuMul=aFact.GetNumerator();
3169         nEmuDiv=aFact.GetDenominator();
3170 
3171         // And something for typographic Points
3172         aFact=GetMapFactor(MapUnit::MapPoint,eMap).X();
3173         nPntMul=aFact.GetNumerator();
3174         nPntDiv=aFact.GetDenominator();
3175     }
3176     else
3177     {
3178         pModel = nullptr;
3179         nMapMul = nMapDiv = nMapXOfs = nMapYOfs = nEmuMul = nEmuDiv = nPntMul = nPntDiv = 0;
3180         bNeedMap = false;
3181     }
3182 }
3183 
3184 bool SvxMSDffManager::SeekToShape( SvStream& rSt, SvxMSDffClientData* /* pClientData */, sal_uInt32 nId ) const
3185 {
3186     bool bRet = false;
3187     if ( !maFidcls.empty() )
3188     {
3189         sal_uInt32 nMerk = rSt.Tell();
3190         sal_uInt32 nSec = ( nId >> 10 ) - 1;
3191         if ( nSec < mnIdClusters )
3192         {
3193             OffsetMap::const_iterator it = maDgOffsetTable.find( maFidcls[ nSec ].dgid );
3194             if ( it != maDgOffsetTable.end() )
3195             {
3196                 sal_IntPtr nOfs = it->second;
3197                 rSt.Seek( nOfs );
3198                 DffRecordHeader aEscherF002Hd;
3199                 bool bOk = ReadDffRecordHeader( rSt, aEscherF002Hd );
3200                 sal_uLong nEscherF002End = bOk ? aEscherF002Hd.GetRecEndFilePos() : 0;
3201                 while (rSt.good() && rSt.Tell() < nEscherF002End)
3202                 {
3203                     DffRecordHeader aEscherObjListHd;
3204                     if (!ReadDffRecordHeader(rSt, aEscherObjListHd))
3205                         break;
3206                     if ( aEscherObjListHd.nRecVer != 0xf )
3207                     {
3208                         bool bSeekSuccess = aEscherObjListHd.SeekToEndOfRecord(rSt);
3209                         if (!bSeekSuccess)
3210                             break;
3211                     }
3212                     else if ( aEscherObjListHd.nRecType == DFF_msofbtSpContainer )
3213                     {
3214                         DffRecordHeader aShapeHd;
3215                         if ( SeekToRec( rSt, DFF_msofbtSp, aEscherObjListHd.GetRecEndFilePos(), &aShapeHd ) )
3216                         {
3217                             sal_uInt32 nShapeId(0);
3218                             rSt.ReadUInt32( nShapeId );
3219                             if ( nId == nShapeId )
3220                             {
3221                                 aEscherObjListHd.SeekToBegOfRecord( rSt );
3222                                 bRet = true;
3223                                 break;
3224                             }
3225                         }
3226                         bool bSeekSuccess = aEscherObjListHd.SeekToEndOfRecord(rSt);
3227                         if (!bSeekSuccess)
3228                             break;
3229                     }
3230                 }
3231             }
3232         }
3233         if ( !bRet )
3234             rSt.Seek( nMerk );
3235     }
3236     return bRet;
3237 }
3238 
3239 bool SvxMSDffManager::SeekToRec( SvStream& rSt, sal_uInt16 nRecId, sal_uLong nMaxFilePos, DffRecordHeader* pRecHd, sal_uLong nSkipCount )
3240 {
3241     bool bRet = false;
3242     sal_uLong nFPosMerk = rSt.Tell(); // store FilePos to restore it later if necessary
3243     do
3244     {
3245         DffRecordHeader aHd;
3246         if (!ReadDffRecordHeader(rSt, aHd))
3247             break;
3248         if (aHd.nRecLen > nMaxLegalDffRecordLength)
3249             break;
3250         if ( aHd.nRecType == nRecId )
3251         {
3252             if ( nSkipCount )
3253                 nSkipCount--;
3254             else
3255             {
3256                 bRet = true;
3257                 if ( pRecHd != nullptr )
3258                     *pRecHd = aHd;
3259                 else
3260                 {
3261                     bool bSeekSuccess = aHd.SeekToBegOfRecord(rSt);
3262                     if (!bSeekSuccess)
3263                     {
3264                         bRet = false;
3265                         break;
3266                     }
3267                 }
3268             }
3269         }
3270         if ( !bRet )
3271         {
3272             bool bSeekSuccess = aHd.SeekToEndOfRecord(rSt);
3273             if (!bSeekSuccess)
3274                 break;
3275         }
3276     }
3277     while ( rSt.good() && rSt.Tell() < nMaxFilePos && !bRet );
3278     if ( !bRet )
3279         rSt.Seek( nFPosMerk );  // restore original FilePos
3280     return bRet;
3281 }
3282 
3283 bool SvxMSDffManager::SeekToRec2( sal_uInt16 nRecId1, sal_uInt16 nRecId2, sal_uLong nMaxFilePos ) const
3284 {
3285     bool bRet = false;
3286     sal_uLong nFPosMerk = rStCtrl.Tell();   // remember FilePos for conditionally later restoration
3287     do
3288     {
3289         DffRecordHeader aHd;
3290         if (!ReadDffRecordHeader(rStCtrl, aHd))
3291             break;
3292         if ( aHd.nRecType == nRecId1 || aHd.nRecType == nRecId2 )
3293         {
3294             bRet = true;
3295             bool bSeekSuccess = aHd.SeekToBegOfRecord(rStCtrl);
3296             if (!bSeekSuccess)
3297             {
3298                 bRet = false;
3299                 break;
3300             }
3301         }
3302         if ( !bRet )
3303         {
3304             bool bSeekSuccess = aHd.SeekToEndOfRecord(rStCtrl);
3305             if (!bSeekSuccess)
3306                 break;
3307         }
3308     }
3309     while ( rStCtrl.good() && rStCtrl.Tell() < nMaxFilePos && !bRet );
3310     if ( !bRet )
3311         rStCtrl.Seek( nFPosMerk ); // restore FilePos
3312     return bRet;
3313 }
3314 
3315 
3316 bool SvxMSDffManager::GetColorFromPalette( sal_uInt16 /* nNum */, Color& rColor ) const
3317 {
3318     // This method has to be overwritten in the class
3319     // derived for the excel export
3320     rColor = COL_WHITE;
3321     return true;
3322 }
3323 
3324 // sj: the documentation is not complete, especially in ppt the normal rgb for text
3325 // color is written as 0xfeRRGGBB, this can't be explained by the documentation, nearly
3326 // every bit in the upper code is set -> so there seems to be a special handling for
3327 // ppt text colors, i decided not to fix this in MSO_CLR_ToColor because of possible
3328 // side effects, instead MSO_TEXT_CLR_ToColor is called for PPT text colors, to map
3329 // the color code to something that behaves like the other standard color codes used by
3330 // fill and line color
3331 Color SvxMSDffManager::MSO_TEXT_CLR_ToColor( sal_uInt32 nColorCode ) const
3332 {
3333     // for text colors: Header is 0xfeRRGGBB
3334     if ( ( nColorCode & 0xfe000000 ) == 0xfe000000 )
3335         nColorCode &= 0x00ffffff;
3336     else
3337     {
3338         // for colorscheme colors the color index are the lower three bits of the upper byte
3339         if ( ( nColorCode & 0xf8000000 ) == 0 ) // this must be a colorscheme index
3340         {
3341             nColorCode >>= 24;
3342             nColorCode |= 0x8000000;
3343         }
3344     }
3345     return MSO_CLR_ToColor( nColorCode );
3346 }
3347 
3348 Color SvxMSDffManager::MSO_CLR_ToColor( sal_uInt32 nColorCode, sal_uInt16 nContentProperty ) const
3349 {
3350     Color aColor( mnDefaultColor );
3351 
3352     // for text colors: Header is 0xfeRRGGBB
3353     if ( ( nColorCode & 0xfe000000 ) == 0xfe000000 )    // sj: it needs to be checked if 0xfe is used in
3354         nColorCode &= 0x00ffffff;                       // other cases than ppt text -> if not this code can be removed
3355 
3356     sal_uInt8 nUpper = static_cast<sal_uInt8>( nColorCode >> 24 );
3357 
3358     // sj: below change from 0x1b to 0x19 was done because of i84812 (0x02 -> rgb color),
3359     // now I have some problems to fix i104685 (there the color value is 0x02000000 which requires
3360     // a 0x2 scheme color to be displayed properly), the color docu seems to be incomplete
3361     if( nUpper & 0x19 )      // if( nUpper & 0x1f )
3362     {
3363         if( ( nUpper & 0x08 ) || ( ( nUpper & 0x10 ) == 0 ) )
3364         {
3365             // SCHEMECOLOR
3366             if ( !GetColorFromPalette( ( nUpper & 8 ) ? static_cast<sal_uInt16>(nColorCode) : nUpper, aColor ) )
3367             {
3368                 switch( nContentProperty )
3369                 {
3370                     case DFF_Prop_pictureTransparent :
3371                     case DFF_Prop_shadowColor :
3372                     case DFF_Prop_fillBackColor :
3373                     case DFF_Prop_fillColor :
3374                         aColor = COL_WHITE;
3375                     break;
3376                     case DFF_Prop_lineColor :
3377                     {
3378                         aColor = COL_BLACK;
3379                     }
3380                     break;
3381                 }
3382             }
3383         }
3384         else    // SYSCOLOR
3385         {
3386             const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
3387 
3388             sal_uInt16 nParameter = sal_uInt16(( nColorCode >> 16 ) & 0x00ff);  // the HiByte of nParameter is not zero, an exclusive AND is helping :o
3389             sal_uInt16 nFunctionBits = static_cast<sal_uInt16>( ( nColorCode & 0x00000f00 ) >> 8 );
3390             sal_uInt16 nAdditionalFlags = static_cast<sal_uInt16>( ( nColorCode & 0x0000f000) >> 8 );
3391             sal_uInt16 nColorIndex = sal_uInt16(nColorCode & 0x00ff);
3392             sal_uInt32 nPropColor = 0;
3393 
3394             sal_uInt16  nCProp = 0;
3395 
3396             switch ( nColorIndex )
3397             {
3398                 case mso_syscolorButtonFace :           aColor = rStyleSettings.GetFaceColor(); break;
3399                 case mso_syscolorWindowText :           aColor = rStyleSettings.GetWindowTextColor(); break;
3400                 case mso_syscolorMenu :                 aColor = rStyleSettings.GetMenuColor(); break;
3401                 case mso_syscolor3DLight :
3402                 case mso_syscolorButtonHighlight :
3403                 case mso_syscolorHighlight :            aColor = rStyleSettings.GetHighlightColor(); break;
3404                 case mso_syscolorHighlightText :        aColor = rStyleSettings.GetHighlightTextColor(); break;
3405                 case mso_syscolorCaptionText :          aColor = rStyleSettings.GetMenuTextColor(); break;
3406                 case mso_syscolorActiveCaption :        aColor = rStyleSettings.GetHighlightColor(); break;
3407                 case mso_syscolorButtonShadow :         aColor = rStyleSettings.GetShadowColor(); break;
3408                 case mso_syscolorButtonText :           aColor = rStyleSettings.GetButtonTextColor(); break;
3409                 case mso_syscolorGrayText :             aColor = rStyleSettings.GetDeactiveColor(); break;
3410                 case mso_syscolorInactiveCaption :      aColor = rStyleSettings.GetDeactiveColor(); break;
3411                 case mso_syscolorInactiveCaptionText :  aColor = rStyleSettings.GetDeactiveColor(); break;
3412                 case mso_syscolorInfoBackground :       aColor = rStyleSettings.GetFaceColor(); break;
3413                 case mso_syscolorInfoText :             aColor = rStyleSettings.GetLabelTextColor(); break;
3414                 case mso_syscolorMenuText :             aColor = rStyleSettings.GetMenuTextColor(); break;
3415                 case mso_syscolorScrollbar :            aColor = rStyleSettings.GetFaceColor(); break;
3416                 case mso_syscolorWindow :               aColor = rStyleSettings.GetWindowColor(); break;
3417                 case mso_syscolorWindowFrame :          aColor = rStyleSettings.GetWindowColor(); break;
3418 
3419                 case mso_colorFillColor :
3420                 {
3421                     nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff );
3422                     nCProp = DFF_Prop_fillColor;
3423                 }
3424                 break;
3425                 case mso_colorLineOrFillColor :     // ( use the line color only if there is a line )
3426                 {
3427                     if ( GetPropertyValue( DFF_Prop_fNoLineDrawDash, 0 ) & 8 )
3428                     {
3429                         nPropColor = GetPropertyValue( DFF_Prop_lineColor, 0 );
3430                         nCProp = DFF_Prop_lineColor;
3431                     }
3432                     else
3433                     {
3434                         nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff );
3435                         nCProp = DFF_Prop_fillColor;
3436                     }
3437                 }
3438                 break;
3439                 case mso_colorLineColor :
3440                 {
3441                     nPropColor = GetPropertyValue( DFF_Prop_lineColor, 0 );
3442                     nCProp = DFF_Prop_lineColor;
3443                 }
3444                 break;
3445                 case mso_colorShadowColor :
3446                 {
3447                     nPropColor = GetPropertyValue( DFF_Prop_shadowColor, 0x808080 );
3448                     nCProp = DFF_Prop_shadowColor;
3449                 }
3450                 break;
3451                 case mso_colorThis :                // ( use this color ... )
3452                 {
3453                     nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff );  //?????????????
3454                     nCProp = DFF_Prop_fillColor;
3455                 }
3456                 break;
3457                 case mso_colorFillBackColor :
3458                 {
3459                     nPropColor = GetPropertyValue( DFF_Prop_fillBackColor, 0xffffff );
3460                     nCProp = DFF_Prop_fillBackColor;
3461                 }
3462                 break;
3463                 case mso_colorLineBackColor :
3464                 {
3465                     nPropColor = GetPropertyValue( DFF_Prop_lineBackColor, 0xffffff );
3466                     nCProp = DFF_Prop_lineBackColor;
3467                 }
3468                 break;
3469                 case mso_colorFillThenLine :        // ( use the fillcolor unless no fill and line )
3470                 {
3471                     nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff );  //?????????????
3472                     nCProp = DFF_Prop_fillColor;
3473                 }
3474                 break;
3475                 case mso_colorIndexMask :           // ( extract the color index ) ?
3476                 {
3477                     nPropColor = GetPropertyValue( DFF_Prop_fillColor, 0xffffff );  //?????????????
3478                     nCProp = DFF_Prop_fillColor;
3479                 }
3480                 break;
3481             }
3482             if ( nCProp && ( nPropColor & 0x10000000 ) == 0 )       // beware of looping recursive
3483                 aColor = MSO_CLR_ToColor( nPropColor, nCProp );
3484 
3485             if( nAdditionalFlags & 0x80 )           // make color gray
3486             {
3487                 sal_uInt8 nZwi = aColor.GetLuminance();
3488                 aColor = Color( nZwi, nZwi, nZwi );
3489             }
3490             switch( nFunctionBits )
3491             {
3492                 case 0x01 :     // darken color by parameter
3493                 {
3494                     aColor.SetRed( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetRed() ) >> 8 ) );
3495                     aColor.SetGreen( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetGreen() ) >> 8 ) );
3496                     aColor.SetBlue( sal::static_int_cast< sal_uInt8 >( ( nParameter * aColor.GetBlue() ) >> 8 ) );
3497                 }
3498                 break;
3499                 case 0x02 :     // lighten color by parameter
3500                 {
3501                     sal_uInt16 nInvParameter = ( 0x00ff - nParameter ) * 0xff;
3502                     aColor.SetRed( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetRed() ) ) >> 8 ) );
3503                     aColor.SetGreen( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetGreen() ) ) >> 8 ) );
3504                     aColor.SetBlue( sal::static_int_cast< sal_uInt8 >( ( nInvParameter + ( nParameter * aColor.GetBlue() ) ) >> 8 ) );
3505                 }
3506                 break;
3507                 case 0x03 :     // add grey level RGB(p,p,p)
3508                 {
3509                     sal_Int16 nR = static_cast<sal_Int16>(aColor.GetRed()) + static_cast<sal_Int16>(nParameter);
3510                     sal_Int16 nG = static_cast<sal_Int16>(aColor.GetGreen()) + static_cast<sal_Int16>(nParameter);
3511                     sal_Int16 nB = static_cast<sal_Int16>(aColor.GetBlue()) + static_cast<sal_Int16>(nParameter);
3512                     if ( nR > 0x00ff )
3513                         nR = 0x00ff;
3514                     if ( nG > 0x00ff )
3515                         nG = 0x00ff;
3516                     if ( nB > 0x00ff )
3517                         nB = 0x00ff;
3518                     aColor = Color( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
3519                 }
3520                 break;
3521                 case 0x04 :     // subtract grey level RGB(p,p,p)
3522                 {
3523                     sal_Int16 nR = static_cast<sal_Int16>(aColor.GetRed()) - static_cast<sal_Int16>(nParameter);
3524                     sal_Int16 nG = static_cast<sal_Int16>(aColor.GetGreen()) - static_cast<sal_Int16>(nParameter);
3525                     sal_Int16 nB = static_cast<sal_Int16>(aColor.GetBlue()) - static_cast<sal_Int16>(nParameter);
3526                     if ( nR < 0 )
3527                         nR = 0;
3528                     if ( nG < 0 )
3529                         nG = 0;
3530                     if ( nB < 0 )
3531                         nB = 0;
3532                     aColor = Color( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
3533                 }
3534                 break;
3535                 case 0x05 :     // subtract from gray level RGB(p,p,p)
3536                 {
3537                     sal_Int16 nR = static_cast<sal_Int16>(nParameter) - static_cast<sal_Int16>(aColor.GetRed());
3538                     sal_Int16 nG = static_cast<sal_Int16>(nParameter) - static_cast<sal_Int16>(aColor.GetGreen());
3539                     sal_Int16 nB = static_cast<sal_Int16>(nParameter) - static_cast<sal_Int16>(aColor.GetBlue());
3540                     if ( nR < 0 )
3541                         nR = 0;
3542                     if ( nG < 0 )
3543                         nG = 0;
3544                     if ( nB < 0 )
3545                         nB = 0;
3546                     aColor = Color( static_cast<sal_uInt8>(nR), static_cast<sal_uInt8>(nG), static_cast<sal_uInt8>(nB) );
3547                 }
3548                 break;
3549                 case 0x06 :     // per component: black if < p, white if >= p
3550                 {
3551                     aColor.SetRed( aColor.GetRed() < nParameter ? 0x00 : 0xff );
3552                     aColor.SetGreen( aColor.GetGreen() < nParameter ? 0x00 : 0xff );
3553                     aColor.SetBlue( aColor.GetBlue() < nParameter ? 0x00 : 0xff );
3554                 }
3555                 break;
3556             }
3557             if ( nAdditionalFlags & 0x40 )                  // top-bit invert
3558                 aColor = Color( aColor.GetRed() ^ 0x80, aColor.GetGreen() ^ 0x80, aColor.GetBlue() ^ 0x80 );
3559 
3560             if ( nAdditionalFlags & 0x20 )                  // invert color
3561                 aColor = Color(0xff - aColor.GetRed(), 0xff - aColor.GetGreen(), 0xff - aColor.GetBlue());
3562         }
3563     }
3564     else if ( ( nUpper & 4 ) && ( ( nColorCode & 0xfffff8 ) == 0 ) )
3565     {   // case of nUpper == 4 powerpoint takes this as argument for a colorschemecolor
3566         GetColorFromPalette( nUpper, aColor );
3567     }
3568     else    // attributed hard, maybe with hint to SYSTEMRGB
3569         aColor = Color( static_cast<sal_uInt8>(nColorCode), static_cast<sal_uInt8>( nColorCode >> 8 ), static_cast<sal_uInt8>( nColorCode >> 16 ) );
3570     return aColor;
3571 }
3572 
3573 void SvxMSDffManager::ReadObjText( SvStream& rStream, SdrObject* pObj )
3574 {
3575     DffRecordHeader aRecHd;
3576     if (!ReadDffRecordHeader(rStream, aRecHd))
3577         return;
3578     if( aRecHd.nRecType == DFF_msofbtClientTextbox || aRecHd.nRecType == 0x1022 )
3579     {
3580         while (rStream.good() && rStream.Tell() < aRecHd.GetRecEndFilePos())
3581         {
3582             DffRecordHeader aHd;
3583             if (!ReadDffRecordHeader(rStream, aHd))
3584                 break;
3585             switch( aHd.nRecType )
3586             {
3587                 case DFF_PST_TextBytesAtom:
3588                 case DFF_PST_TextCharsAtom:
3589                     {
3590                         bool bUniCode = ( aHd.nRecType == DFF_PST_TextCharsAtom );
3591                         sal_uInt32 nBytes = aHd.nRecLen;
3592                         OUString aStr = MSDFFReadZString( rStream, nBytes, bUniCode );
3593                         ReadObjText( aStr, pObj );
3594                     }
3595                     break;
3596                 default:
3597                     break;
3598             }
3599             bool bSeekSuccess = aHd.SeekToEndOfRecord(rStream);
3600             if (!bSeekSuccess)
3601                 break;
3602         }
3603     }
3604 }
3605 
3606 // sj: I just want to set a string for a text object that may contain multiple
3607 // paragraphs. If I now take a look at the following code I get the impression that
3608 // our outliner is too complicate to be used properly,
3609 void SvxMSDffManager::ReadObjText( const OUString& rText, SdrObject* pObj )
3610 {
3611     SdrTextObj* pText = dynamic_cast<SdrTextObj*>( pObj  );
3612     if ( pText )
3613     {
3614         SdrOutliner& rOutliner = pText->ImpGetDrawOutliner();
3615         rOutliner.Init( OutlinerMode::TextObject );
3616 
3617         bool bOldUpdateMode = rOutliner.GetUpdateMode();
3618         rOutliner.SetUpdateMode( false );
3619         rOutliner.SetVertical( pText->IsVerticalWriting() );
3620 
3621         sal_Int32 nParaIndex = 0;
3622         sal_Int32 nParaSize;
3623         const sal_Unicode* pBuf = rText.getStr();
3624         const sal_Unicode* pEnd = rText.getStr() + rText.getLength();
3625 
3626         while( pBuf < pEnd )
3627         {
3628             const sal_Unicode* pCurrent = pBuf;
3629 
3630             for ( nParaSize = 0; pBuf < pEnd; )
3631             {
3632                 sal_Unicode nChar = *pBuf++;
3633                 if ( nChar == 0xa )
3634                 {
3635                     if ( ( pBuf < pEnd ) && ( *pBuf == 0xd ) )
3636                         pBuf++;
3637                     break;
3638                 }
3639                 else if ( nChar == 0xd )
3640                 {
3641                     if ( ( pBuf < pEnd ) && ( *pBuf == 0xa ) )
3642                         pBuf++;
3643                     break;
3644                 }
3645                 else
3646                     ++nParaSize;
3647             }
3648             ESelection aSelection( nParaIndex, 0, nParaIndex, 0 );
3649             OUString aParagraph( pCurrent, nParaSize );
3650             if ( !nParaIndex && aParagraph.isEmpty() )              // SJ: we are crashing if the first paragraph is empty ?
3651                 aParagraph += " ";                   // otherwise these two lines can be removed.
3652             rOutliner.Insert( aParagraph, nParaIndex );
3653             rOutliner.SetParaAttribs( nParaIndex, rOutliner.GetEmptyItemSet() );
3654 
3655             SfxItemSet aParagraphAttribs( rOutliner.GetEmptyItemSet() );
3656             if ( !aSelection.nStartPos )
3657                 aParagraphAttribs.Put( SfxBoolItem( EE_PARA_BULLETSTATE, false ) );
3658             aSelection.nStartPos = 0;
3659             rOutliner.QuickSetAttribs( aParagraphAttribs, aSelection );
3660             nParaIndex++;
3661         }
3662         std::unique_ptr<OutlinerParaObject> pNewText = rOutliner.CreateParaObject();
3663         rOutliner.Clear();
3664         rOutliner.SetUpdateMode( bOldUpdateMode );
3665         pText->SetOutlinerParaObject( std::move(pNewText) );
3666     }
3667 }
3668 
3669 //static
3670 OUString SvxMSDffManager::MSDFFReadZString(SvStream& rIn,
3671     sal_uInt32 nLen, bool bUniCode)
3672 {
3673     if (!nLen)
3674         return OUString();
3675 
3676     OUString sBuf;
3677 
3678     if( bUniCode )
3679         sBuf = read_uInt16s_ToOUString(rIn, nLen/2);
3680     else
3681         sBuf = read_uInt8s_ToOUString(rIn, nLen, RTL_TEXTENCODING_MS_1252);
3682 
3683     return comphelper::string::stripEnd(sBuf, 0);
3684 }
3685 
3686 static Size lcl_GetPrefSize(const Graphic& rGraf, const MapMode& aWanted)
3687 {
3688     MapMode aPrefMapMode(rGraf.GetPrefMapMode());
3689     if (aPrefMapMode == aWanted)
3690         return rGraf.GetPrefSize();
3691     Size aRetSize;
3692     if (aPrefMapMode.GetMapUnit() == MapUnit::MapPixel)
3693     {
3694         aRetSize = Application::GetDefaultDevice()->PixelToLogic(
3695             rGraf.GetPrefSize(), aWanted);
3696     }
3697     else
3698     {
3699         aRetSize = OutputDevice::LogicToLogic(
3700             rGraf.GetPrefSize(), rGraf.GetPrefMapMode(), aWanted);
3701     }
3702     return aRetSize;
3703 }
3704 
3705 // sj: if the parameter pSet is null, then the resulting crop bitmap will be stored in rGraf,
3706 // otherwise rGraf is untouched and pSet is used to store the corresponding SdrGrafCropItem
3707 static void lcl_ApplyCropping( const DffPropSet& rPropSet, SfxItemSet* pSet, Graphic& rGraf )
3708 {
3709     sal_Int32 nCropTop      = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromTop, 0 ));
3710     sal_Int32 nCropBottom   = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromBottom, 0 ));
3711     sal_Int32 nCropLeft     = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromLeft, 0 ));
3712     sal_Int32 nCropRight    = static_cast<sal_Int32>(rPropSet.GetPropertyValue( DFF_Prop_cropFromRight, 0 ));
3713 
3714     if( nCropTop || nCropBottom || nCropLeft || nCropRight )
3715     {
3716         double      fFactor;
3717         Size        aCropSize;
3718         BitmapEx    aCropBitmap;
3719         sal_uInt32  nTop( 0 ),  nBottom( 0 ), nLeft( 0 ), nRight( 0 );
3720 
3721         // Cropping has to be applied on a loaded graphic.
3722         rGraf.makeAvailable();
3723 
3724         if ( pSet ) // use crop attributes ?
3725             aCropSize = lcl_GetPrefSize(rGraf, MapMode(MapUnit::Map100thMM));
3726         else
3727         {
3728             aCropBitmap = rGraf.GetBitmapEx();
3729             aCropSize = aCropBitmap.GetSizePixel();
3730         }
3731         if ( nCropTop )
3732         {
3733             fFactor = static_cast<double>(nCropTop) / 65536.0;
3734             nTop = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Height() + 1 ) * fFactor ) + 0.5 );
3735         }
3736         if ( nCropBottom )
3737         {
3738             fFactor = static_cast<double>(nCropBottom) / 65536.0;
3739             nBottom = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Height() + 1 ) * fFactor ) + 0.5 );
3740         }
3741         if ( nCropLeft )
3742         {
3743             fFactor = static_cast<double>(nCropLeft) / 65536.0;
3744             nLeft = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Width() + 1 ) * fFactor ) + 0.5 );
3745         }
3746         if ( nCropRight )
3747         {
3748             fFactor = static_cast<double>(nCropRight) / 65536.0;
3749             nRight = static_cast<sal_uInt32>( ( static_cast<double>( aCropSize.Width() + 1 ) * fFactor ) + 0.5 );
3750         }
3751         if ( pSet ) // use crop attributes ?
3752             pSet->Put( SdrGrafCropItem( nLeft, nTop, nRight, nBottom ) );
3753         else
3754         {
3755             tools::Rectangle aCropRect( nLeft, nTop, aCropSize.Width() - nRight, aCropSize.Height() - nBottom );
3756             aCropBitmap.Crop( aCropRect );
3757             rGraf = aCropBitmap;
3758         }
3759     }
3760 }
3761 
3762 SdrObject* SvxMSDffManager::ImportGraphic( SvStream& rSt, SfxItemSet& rSet, const DffObjData& rObjData )
3763 {
3764     SdrObject*  pRet = nullptr;
3765     OUString    aFileName;
3766     OUString    aLinkFileName, aLinkFilterName;
3767     tools::Rectangle   aVisArea;
3768 
3769     MSO_BlipFlags eFlags = static_cast<MSO_BlipFlags>(GetPropertyValue( DFF_Prop_pibFlags, mso_blipflagDefault ));
3770     sal_uInt32 nBlipId = GetPropertyValue( DFF_Prop_pib, 0 );
3771     bool bGrfRead = false,
3772 
3773     // Graphic linked
3774     bLinkGrf = 0 != ( eFlags & mso_blipflagLinkToFile );
3775     {
3776         Graphic aGraf;  // be sure this graphic is deleted before swapping out
3777         if( SeekToContent( DFF_Prop_pibName, rSt ) )
3778             aFileName = MSDFFReadZString( rSt, GetPropertyValue( DFF_Prop_pibName, 0 ), true );
3779 
3780         //   AND, OR the following:
3781         if( !( eFlags & mso_blipflagDoNotSave ) ) // Graphic embedded
3782         {
3783             bGrfRead = GetBLIP( nBlipId, aGraf, &aVisArea );
3784             if ( !bGrfRead )
3785             {
3786                 /*
3787                 Still no luck, lets look at the end of this record for a FBSE pool,
3788                 this fallback is a specific case for how word does it sometimes
3789                 */
3790                 bool bOk = rObjData.rSpHd.SeekToEndOfRecord( rSt );
3791                 DffRecordHeader aHd;
3792                 if (bOk)
3793                 {
3794                     bOk = ReadDffRecordHeader(rSt, aHd);
3795                 }
3796                 if (bOk && DFF_msofbtBSE == aHd.nRecType)
3797                 {
3798                     const sal_uLong nSkipBLIPLen = 20;
3799                     const sal_uLong nSkipShapePos = 4;
3800                     const sal_uLong nSkipBLIP = 4;
3801                     const sal_uLong nSkip =
3802                         nSkipBLIPLen + 4 + nSkipShapePos + 4 + nSkipBLIP;
3803 
3804                     if (nSkip <= aHd.nRecLen)
3805                     {
3806                         rSt.SeekRel(nSkip);
3807                         if (ERRCODE_NONE == rSt.GetError())
3808                             bGrfRead = GetBLIPDirect( rSt, aGraf, &aVisArea );
3809                     }
3810                 }
3811             }
3812         }
3813         if ( bGrfRead )
3814         {
3815             // the writer is doing its own cropping, so this part affects only impress and calc,
3816             // unless we're inside a group, in which case writer doesn't crop either
3817             if (( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_CROP_BITMAPS ) || rObjData.nCalledByGroup != 0 )
3818                 lcl_ApplyCropping( *this, !bool( rObjData.nSpFlags & ShapeFlag::OLEShape ) ? &rSet : nullptr, aGraf );
3819 
3820             if ( IsProperty( DFF_Prop_pictureTransparent ) )
3821             {
3822                 sal_uInt32 nTransColor = GetPropertyValue( DFF_Prop_pictureTransparent, 0 );
3823 
3824                 if ( aGraf.GetType() == GraphicType::Bitmap )
3825                 {
3826                     BitmapEx aBitmapEx( aGraf.GetBitmapEx() );
3827                     aBitmapEx.CombineMaskOr( MSO_CLR_ToColor( nTransColor, DFF_Prop_pictureTransparent ), 9 );
3828                     aGraf = aBitmapEx;
3829                 }
3830             }
3831 
3832             sal_Int32 nContrast = GetPropertyValue( DFF_Prop_pictureContrast, 0x10000 );
3833             /*
3834             0x10000 is msoffice 50%
3835             < 0x10000 is in units of 1/50th of 0x10000 per 1%
3836             > 0x10000 is in units where
3837             a msoffice x% is stored as 50/(100-x) * 0x10000
3838 
3839             plus, a (ui) microsoft % ranges from 0 to 100, OOO
3840             from -100 to 100, so also normalize into that range
3841             */
3842             if ( nContrast > 0x10000 )
3843             {
3844                 double fX = nContrast;
3845                 fX /= 0x10000;
3846                 fX /= 51;   // 50 + 1 to round
3847                 fX = 1/fX;
3848                 nContrast = static_cast<sal_Int32>(fX);
3849                 nContrast -= 100;
3850                 nContrast = -nContrast;
3851                 nContrast = (nContrast-50)*2;
3852             }
3853             else if ( nContrast == 0x10000 )
3854                 nContrast = 0;
3855             else
3856             {
3857                 if (o3tl::checked_multiply<sal_Int32>(nContrast, 101, nContrast))  //100 + 1 to round
3858                 {
3859                     SAL_WARN("filter.ms", "bad Contrast value:" << nContrast);
3860                     nContrast = 0;
3861                 }
3862                 else
3863                 {
3864                     nContrast /= 0x10000;
3865                     nContrast -= 100;
3866                 }
3867             }
3868             sal_Int16   nBrightness     = static_cast<sal_Int16>( static_cast<sal_Int32>(GetPropertyValue( DFF_Prop_pictureBrightness, 0 )) / 327 );
3869             sal_Int32   nGamma          = GetPropertyValue( DFF_Prop_pictureGamma, 0x10000 );
3870             GraphicDrawMode eDrawMode   = GraphicDrawMode::Standard;
3871             switch ( GetPropertyValue( DFF_Prop_pictureActive, 0 ) & 6 )
3872             {
3873                 case 4 : eDrawMode = GraphicDrawMode::Greys; break;
3874                 case 6 : eDrawMode = GraphicDrawMode::Mono; break;
3875                 case 0 :
3876                 {
3877                     //office considers the converted values of (in OOo) 70 to be the
3878                     //"watermark" values, which can vary slightly due to rounding from the
3879                     //above values
3880                     if (( nContrast == -70 ) && ( nBrightness == 70 ))
3881                     {
3882                         nContrast = 0;
3883                         nBrightness = 0;
3884                         eDrawMode = GraphicDrawMode::Watermark;
3885                     };
3886                 }
3887                 break;
3888             }
3889 
3890             if ( nContrast || nBrightness || ( nGamma != 0x10000 ) || ( eDrawMode != GraphicDrawMode::Standard ) )
3891             {
3892                 // MSO uses a different algorithm for contrast+brightness, LO applies contrast before brightness,
3893                 // while MSO apparently applies half of brightness before contrast and half after. So if only
3894                 // contrast or brightness need to be altered, the result is the same, but if both are involved,
3895                 // there's no way to map that, so just force a conversion of the image.
3896                 bool needsConversion = nContrast != 0 && nBrightness != 0;
3897                 if ( !bool(rObjData.nSpFlags & ShapeFlag::OLEShape) && !needsConversion )
3898                 {
3899                     if ( nBrightness )
3900                         rSet.Put( SdrGrafLuminanceItem( nBrightness ) );
3901                     if ( nContrast )
3902                         rSet.Put( SdrGrafContrastItem( static_cast<sal_Int16>(nContrast) ) );
3903                     if ( nGamma != 0x10000 )
3904                         rSet.Put( SdrGrafGamma100Item( nGamma / 655 ) );
3905                     if ( eDrawMode != GraphicDrawMode::Standard )
3906                         rSet.Put( SdrGrafModeItem( eDrawMode ) );
3907                 }
3908                 else
3909                 {
3910                     if ( eDrawMode == GraphicDrawMode::Watermark )
3911                     {
3912                         nContrast = 60;
3913                         nBrightness = 70;
3914                         eDrawMode = GraphicDrawMode::Standard;
3915                     }
3916                     switch ( aGraf.GetType() )
3917                     {
3918                         case GraphicType::Bitmap :
3919                         {
3920                             BitmapEx    aBitmapEx( aGraf.GetBitmapEx() );
3921                             if ( nBrightness || nContrast || ( nGamma != 0x10000 ) )
3922                                 aBitmapEx.Adjust( nBrightness, static_cast<sal_Int16>(nContrast), 0, 0, 0, static_cast<double>(nGamma) / 0x10000, false, true );
3923                             if ( eDrawMode == GraphicDrawMode::Greys )
3924                                 aBitmapEx.Convert( BmpConversion::N8BitGreys );
3925                             else if ( eDrawMode == GraphicDrawMode::Mono )
3926                                 aBitmapEx.Convert( BmpConversion::N1BitThreshold );
3927                             aGraf = aBitmapEx;
3928 
3929                         }
3930                         break;
3931 
3932                         case GraphicType::GdiMetafile :
3933                         {
3934                             GDIMetaFile aGdiMetaFile( aGraf.GetGDIMetaFile() );
3935                             if ( nBrightness || nContrast || ( nGamma != 0x10000 ) )
3936                                 aGdiMetaFile.Adjust( nBrightness, static_cast<sal_Int16>(nContrast), 0, 0, 0, static_cast<double>(nGamma) / 0x10000, false, true );
3937                             if ( eDrawMode == GraphicDrawMode::Greys )
3938                                 aGdiMetaFile.Convert( MtfConversion::N8BitGreys );
3939                             else if ( eDrawMode == GraphicDrawMode::Mono )
3940                                 aGdiMetaFile.Convert( MtfConversion::N1BitThreshold );
3941                             aGraf = aGdiMetaFile;
3942                         }
3943                         break;
3944                         default: break;
3945                     }
3946                 }
3947             }
3948         }
3949 
3950         // should it be an OLE object?
3951         if( bGrfRead && !bLinkGrf && IsProperty( DFF_Prop_pictureId ) )
3952         {
3953             // TODO/LATER: in future probably the correct aspect should be provided here
3954             // #i32596# - pass <nCalledByGroup> to method
3955             pRet = ImportOLE( GetPropertyValue( DFF_Prop_pictureId, 0 ), aGraf, rObjData.aBoundRect, aVisArea, rObjData.nCalledByGroup );
3956         }
3957         if( !pRet )
3958         {
3959             pRet = new SdrGrafObj(*pSdrModel);
3960             if( bGrfRead )
3961                 static_cast<SdrGrafObj*>(pRet)->SetGraphic( aGraf );
3962 
3963             if( bLinkGrf && !bGrfRead )     // sj: #i55484# if the graphic was embedded ( bGrfRead == true ) then
3964             {                               // we do not need to set a link. TODO: not to lose the information where the graphic is linked from
3965                 INetURLObject aAbsURL;
3966                 if ( !INetURLObject( maBaseURL ).GetNewAbsURL( aFileName, &aAbsURL ) )
3967                 {
3968                     OUString aValidURL;
3969                     if( osl::FileBase::getFileURLFromSystemPath( aFileName, aValidURL ) == osl::FileBase::E_None )
3970                         aAbsURL = INetURLObject( aValidURL );
3971                 }
3972                 if( aAbsURL.GetProtocol() != INetProtocol::NotValid )
3973                 {
3974                     GraphicFilter &rGrfFilter = GraphicFilter::GetGraphicFilter();
3975                     aLinkFilterName = rGrfFilter.GetImportFormatName(
3976                         rGrfFilter.GetImportFormatNumberForShortName( aAbsURL.getExtension() ) );
3977                     aLinkFileName = aAbsURL.GetMainURL( INetURLObject::DecodeMechanism::ToIUri );
3978                 }
3979                 else
3980                     aLinkFileName = aFileName;
3981             }
3982         }
3983 
3984         // set the size from BLIP if there is one
3985         if ( bGrfRead && !aVisArea.IsEmpty() )
3986             pRet->SetBLIPSizeRectangle( aVisArea );
3987 
3988         if (pRet->GetName().isEmpty())                   // SJ 22.02.00 : PPT OLE IMPORT:
3989         {                                                // name is already set in ImportOLE !!
3990             // JP 01.12.99: SetName before SetModel - because in the other order the Bug 70098 is active
3991             if ( ( eFlags & mso_blipflagType ) != mso_blipflagComment )
3992             {
3993                 INetURLObject aURL;
3994                 aURL.SetSmartURL( aFileName );
3995                 pRet->SetName( aURL.getBase() );
3996             }
3997             else
3998                 pRet->SetName( aFileName );
3999         }
4000     }
4001     pRet->SetLogicRect( rObjData.aBoundRect );
4002 
4003     if ( dynamic_cast<const SdrGrafObj* >(pRet) !=  nullptr )
4004     {
4005         if( aLinkFileName.getLength() )
4006         {
4007             static_cast<SdrGrafObj*>(pRet)->SetGraphicLink( aLinkFileName, ""/*TODO?*/, aLinkFilterName );
4008             Graphic aGraphic(static_cast<SdrGrafObj*>(pRet)->GetGraphic());
4009             aGraphic.setOriginURL(aLinkFileName);
4010         }
4011 
4012         if ( bLinkGrf && !bGrfRead )
4013         {
4014             Graphic aGraf(static_cast<SdrGrafObj*>(pRet)->GetGraphic());
4015             lcl_ApplyCropping( *this, &rSet, aGraf );
4016         }
4017     }
4018 
4019     return pRet;
4020 }
4021 
4022 // PptSlidePersistEntry& rPersistEntry, SdPage* pPage
4023 SdrObject* SvxMSDffManager::ImportObj( SvStream& rSt, SvxMSDffClientData& rClientData,
4024     tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect, int nCalledByGroup, sal_Int32* pShapeId )
4025 {
4026     SdrObject* pRet = nullptr;
4027     DffRecordHeader aObjHd;
4028     bool bOk = ReadDffRecordHeader(rSt, aObjHd);
4029     if (bOk && aObjHd.nRecType == DFF_msofbtSpgrContainer)
4030     {
4031         pRet = ImportGroup( aObjHd, rSt, rClientData, rClientRect, rGlobalChildRect, nCalledByGroup, pShapeId );
4032     }
4033     else if (bOk && aObjHd.nRecType == DFF_msofbtSpContainer)
4034     {
4035         pRet = ImportShape( aObjHd, rSt, rClientData, rClientRect, rGlobalChildRect, nCalledByGroup, pShapeId );
4036     }
4037     aObjHd.SeekToBegOfRecord( rSt );    // restore FilePos
4038     return pRet;
4039 }
4040 
4041 SdrObject* SvxMSDffManager::ImportGroup( const DffRecordHeader& rHd, SvStream& rSt, SvxMSDffClientData& rClientData,
4042                                             tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect,
4043                                                 int nCalledByGroup, sal_Int32* pShapeId )
4044 {
4045     SdrObject* pRet = nullptr;
4046 
4047     if( pShapeId )
4048         *pShapeId = 0;
4049 
4050     if (!rHd.SeekToContent(rSt))
4051         return pRet;
4052 
4053     DffRecordHeader aRecHd;     // the first atom has to be the SpContainer for the GroupObject
4054     bool bOk = ReadDffRecordHeader(rSt, aRecHd);
4055     if (bOk && aRecHd.nRecType == DFF_msofbtSpContainer)
4056     {
4057         mnFix16Angle = 0;
4058         if (!aRecHd.SeekToBegOfRecord(rSt))
4059             return pRet;
4060         pRet = ImportObj( rSt, rClientData, rClientRect, rGlobalChildRect, nCalledByGroup + 1, pShapeId );
4061         if ( pRet )
4062         {
4063             sal_Int32 nGroupRotateAngle = 0;
4064             ShapeFlag nSpFlags = nGroupShapeFlags;
4065             nGroupRotateAngle = mnFix16Angle;
4066 
4067             tools::Rectangle aClientRect( rClientRect );
4068 
4069             tools::Rectangle aGlobalChildRect;
4070             if ( !nCalledByGroup || rGlobalChildRect.IsEmpty() )
4071                 aGlobalChildRect = GetGlobalChildAnchor( rHd, rSt, aClientRect );
4072             else
4073                 aGlobalChildRect = rGlobalChildRect;
4074 
4075             if ( ( nGroupRotateAngle > 4500 && nGroupRotateAngle <= 13500 )
4076                 || ( nGroupRotateAngle > 22500 && nGroupRotateAngle <= 31500 ) )
4077             {
4078                 sal_Int32 nHalfWidth = ( aClientRect.GetWidth() + 1 ) >> 1;
4079                 sal_Int32 nHalfHeight = ( aClientRect.GetHeight() + 1 ) >> 1;
4080                 Point aTopLeft( aClientRect.Left() + nHalfWidth - nHalfHeight,
4081                                 aClientRect.Top() + nHalfHeight - nHalfWidth );
4082                 const long nRotatedWidth = aClientRect.GetHeight();
4083                 const long nRotatedHeight = aClientRect.GetWidth();
4084                 Size aNewSize(nRotatedWidth, nRotatedHeight);
4085                 tools::Rectangle aNewRect( aTopLeft, aNewSize );
4086                 aClientRect = aNewRect;
4087             }
4088 
4089             // now importing the inner objects of the group
4090             if (!aRecHd.SeekToEndOfRecord(rSt))
4091                 return pRet;
4092 
4093             while (rSt.good() && ( rSt.Tell() < rHd.GetRecEndFilePos()))
4094             {
4095                 DffRecordHeader aRecHd2;
4096                 if (!ReadDffRecordHeader(rSt, aRecHd2))
4097                     break;
4098                 if ( aRecHd2.nRecType == DFF_msofbtSpgrContainer )
4099                 {
4100                     tools::Rectangle aGroupClientAnchor, aGroupChildAnchor;
4101                     GetGroupAnchors( aRecHd2, rSt, aGroupClientAnchor, aGroupChildAnchor, aClientRect, aGlobalChildRect );
4102                     if (!aRecHd2.SeekToBegOfRecord(rSt))
4103                         return pRet;
4104                     sal_Int32 nShapeId;
4105                     SdrObject* pTmp = ImportGroup( aRecHd2, rSt, rClientData, aGroupClientAnchor, aGroupChildAnchor, nCalledByGroup + 1, &nShapeId );
4106                     if (pTmp)
4107                     {
4108                         SdrObjGroup* pGroup = dynamic_cast<SdrObjGroup*>(pRet);
4109                         if (pGroup && pGroup->GetSubList())
4110                         {
4111                             pGroup->GetSubList()->NbcInsertObject(pTmp);
4112                             if (nShapeId)
4113                                 insertShapeId(nShapeId, pTmp);
4114                         }
4115                         else
4116                             FreeObj(rClientData, pTmp);
4117                     }
4118                 }
4119                 else if ( aRecHd2.nRecType == DFF_msofbtSpContainer )
4120                 {
4121                     if (!aRecHd2.SeekToBegOfRecord(rSt))
4122                         return pRet;
4123                     sal_Int32 nShapeId;
4124                     SdrObject* pTmp = ImportShape( aRecHd2, rSt, rClientData, aClientRect, aGlobalChildRect, nCalledByGroup + 1, &nShapeId );
4125                     if (pTmp)
4126                     {
4127                         SdrObjGroup* pGroup = dynamic_cast<SdrObjGroup*>(pRet);
4128                         if (pGroup && pGroup->GetSubList())
4129                         {
4130                             pGroup->GetSubList()->NbcInsertObject(pTmp);
4131                             if (nShapeId)
4132                                 insertShapeId(nShapeId, pTmp);
4133                         }
4134                         else
4135                             FreeObj(rClientData, pTmp);
4136                     }
4137                 }
4138                 if (!aRecHd2.SeekToEndOfRecord(rSt))
4139                     return pRet;
4140             }
4141 
4142             if ( nGroupRotateAngle )
4143             {
4144                 double a = nGroupRotateAngle * nPi180;
4145                 pRet->NbcRotate( aClientRect.Center(), nGroupRotateAngle, sin( a ), cos( a ) );
4146             }
4147             if ( nSpFlags & ShapeFlag::FlipV )
4148             {   // BoundRect in aBoundRect
4149                 Point aLeft( aClientRect.Left(), ( aClientRect.Top() + aClientRect.Bottom() ) >> 1 );
4150                 Point aRight( aLeft.X() + 1000, aLeft.Y() );
4151                 pRet->NbcMirror( aLeft, aRight );
4152             }
4153             if ( nSpFlags & ShapeFlag::FlipH )
4154             {   // BoundRect in aBoundRect
4155                 Point aTop( ( aClientRect.Left() + aClientRect.Right() ) >> 1, aClientRect.Top() );
4156                 Point aBottom( aTop.X(), aTop.Y() + 1000 );
4157                 pRet->NbcMirror( aTop, aBottom );
4158             }
4159         }
4160     }
4161     if (size_t(nCalledByGroup) < maPendingGroupData.size())
4162     {
4163         // finalization for this group is pending, do it now
4164         pRet = FinalizeObj(maPendingGroupData.back().first, pRet);
4165         maPendingGroupData.pop_back();
4166     }
4167     return pRet;
4168 }
4169 
4170 SdrObject* SvxMSDffManager::ImportShape( const DffRecordHeader& rHd, SvStream& rSt, SvxMSDffClientData& rClientData,
4171                                             tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect,
4172                                             int nCalledByGroup, sal_Int32* pShapeId )
4173 {
4174     SdrObject* pRet = nullptr;
4175 
4176     if( pShapeId )
4177         *pShapeId = 0;
4178 
4179     if (!rHd.SeekToBegOfRecord(rSt))
4180         return pRet;
4181 
4182     DffObjData aObjData( rHd, rClientRect, nCalledByGroup );
4183 
4184     aObjData.bRotateTextWithShape = ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_EXCEL ) == 0;
4185     maShapeRecords.Consume( rSt );
4186     if( maShapeRecords.SeekToContent( rSt,
4187         DFF_msofbtUDefProp ) )
4188     {
4189         sal_uInt32  nBytesLeft = maShapeRecords.Current()->nRecLen;
4190         while( 5 < nBytesLeft )
4191         {
4192             sal_uInt16 nPID(0);
4193             rSt.ReadUInt16(nPID);
4194             if (!rSt.good())
4195                 break;
4196             sal_uInt32 nUDData(0);
4197             rSt.ReadUInt32(nUDData);
4198             if (!rSt.good())
4199                 break;
4200             if (nPID == 447)
4201             {
4202                 mbRotateGranientFillWithAngle = nUDData & 0x20;
4203                 break;
4204             }
4205             nBytesLeft  -= 6;
4206         }
4207     }
4208     aObjData.bShapeType = maShapeRecords.SeekToContent( rSt, DFF_msofbtSp );
4209     if ( aObjData.bShapeType )
4210     {
4211         sal_uInt32 temp;
4212         rSt.ReadUInt32( aObjData.nShapeId )
4213            .ReadUInt32( temp );
4214         aObjData.nSpFlags = ShapeFlag(temp);
4215         aObjData.eShapeType = static_cast<MSO_SPT>(maShapeRecords.Current()->nRecInstance);
4216     }
4217     else
4218     {
4219         aObjData.nShapeId = 0;
4220         aObjData.nSpFlags = ShapeFlag::NONE;
4221         aObjData.eShapeType = mso_sptNil;
4222     }
4223 
4224     if( pShapeId )
4225         *pShapeId = aObjData.nShapeId;
4226 
4227     aObjData.bOpt = maShapeRecords.SeekToContent( rSt, DFF_msofbtOPT, SEEK_FROM_CURRENT_AND_RESTART );
4228     if ( aObjData.bOpt )
4229     {
4230         if (!maShapeRecords.Current()->SeekToBegOfRecord(rSt))
4231             return pRet;
4232 #ifdef DBG_AUTOSHAPE
4233         ReadPropSet( rSt, &rClientData, (sal_uInt32)aObjData.eShapeType );
4234 #else
4235         ReadPropSet( rSt, &rClientData );
4236 #endif
4237     }
4238     else
4239     {
4240         InitializePropSet( DFF_msofbtOPT ); // get the default PropSet
4241         static_cast<DffPropertyReader*>(this)->mnFix16Angle = 0;
4242     }
4243 
4244     aObjData.bOpt2 = maShapeRecords.SeekToContent( rSt, DFF_msofbtUDefProp, SEEK_FROM_CURRENT_AND_RESTART );
4245     if ( aObjData.bOpt2 )
4246     {
4247         maShapeRecords.Current()->SeekToBegOfRecord( rSt );
4248         pSecPropSet.reset( new DffPropertyReader( *this ) );
4249         pSecPropSet->ReadPropSet( rSt, nullptr );
4250     }
4251 
4252     aObjData.bChildAnchor = maShapeRecords.SeekToContent( rSt, DFF_msofbtChildAnchor, SEEK_FROM_CURRENT_AND_RESTART );
4253     if ( aObjData.bChildAnchor )
4254     {
4255         sal_Int32 l(0), o(0), r(0), u(0);
4256         rSt.ReadInt32( l ).ReadInt32( o ).ReadInt32( r ).ReadInt32( u );
4257         Scale( l );
4258         Scale( o );
4259         Scale( r );
4260         Scale( u );
4261         aObjData.aChildAnchor = tools::Rectangle( l, o, r, u );
4262         sal_Int32 nWidth, nHeight;
4263         if (!rGlobalChildRect.IsEmpty() && !rClientRect.IsEmpty() && rGlobalChildRect.GetWidth() && rGlobalChildRect.GetHeight() &&
4264             !o3tl::checked_sub(r, l, nWidth) && !o3tl::checked_sub(u, o, nHeight))
4265         {
4266             double fXScale = static_cast<double>(rClientRect.GetWidth()) / static_cast<double>(rGlobalChildRect.GetWidth());
4267             double fYScale = static_cast<double>(rClientRect.GetHeight()) / static_cast<double>(rGlobalChildRect.GetHeight());
4268             double fl = ( ( l - rGlobalChildRect.Left() ) * fXScale ) + rClientRect.Left();
4269             double fo = ( ( o - rGlobalChildRect.Top()  ) * fYScale ) + rClientRect.Top();
4270             double fWidth = nWidth * fXScale;
4271             double fHeight = nHeight * fYScale;
4272             aObjData.aChildAnchor = tools::Rectangle( Point( static_cast<sal_Int32>(fl), static_cast<sal_Int32>(fo) ), Size( static_cast<sal_Int32>( fWidth + 1 ), static_cast<sal_Int32>( fHeight + 1 ) ) );
4273         }
4274     }
4275 
4276     aObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt, DFF_msofbtClientAnchor, SEEK_FROM_CURRENT_AND_RESTART );
4277     if ( aObjData.bClientAnchor )
4278         ProcessClientAnchor2( rSt, *maShapeRecords.Current(), rClientData, aObjData );
4279 
4280     if ( aObjData.bChildAnchor )
4281         aObjData.aBoundRect = aObjData.aChildAnchor;
4282 
4283     if ( aObjData.nSpFlags & ShapeFlag::Background )
4284         aObjData.aBoundRect = tools::Rectangle( Point(), Size( 1, 1 ) );
4285 
4286     tools::Rectangle aTextRect;
4287     if ( !aObjData.aBoundRect.IsEmpty() )
4288     {   // apply rotation to the BoundingBox BEFORE an object has been generated
4289         if( mnFix16Angle )
4290         {
4291             long nAngle = mnFix16Angle;
4292             if ( ( nAngle > 4500 && nAngle <= 13500 ) || ( nAngle > 22500 && nAngle <= 31500 ) )
4293             {
4294                 sal_Int32 nHalfWidth = ( aObjData.aBoundRect.GetWidth() + 1 ) >> 1;
4295                 sal_Int32 nHalfHeight = ( aObjData.aBoundRect.GetHeight() + 1 ) >> 1;
4296                 Point aTopLeft( aObjData.aBoundRect.Left() + nHalfWidth - nHalfHeight,
4297                                 aObjData.aBoundRect.Top() + nHalfHeight - nHalfWidth );
4298                 Size aNewSize( aObjData.aBoundRect.GetHeight(), aObjData.aBoundRect.GetWidth() );
4299                 tools::Rectangle aNewRect( aTopLeft, aNewSize );
4300                 aObjData.aBoundRect = aNewRect;
4301             }
4302         }
4303         aTextRect = aObjData.aBoundRect;
4304         bool bGraphic = IsProperty( DFF_Prop_pib ) ||
4305                             IsProperty( DFF_Prop_pibName ) ||
4306                             IsProperty( DFF_Prop_pibFlags );
4307 
4308         if ( aObjData.nSpFlags & ShapeFlag::Group )
4309         {
4310             pRet = new SdrObjGroup(*pSdrModel);
4311             /*  After CWS aw033 has been integrated, an empty group object
4312                 cannot store its resulting bounding rectangle anymore. We have
4313                 to return this rectangle via rClientRect now, but only, if
4314                 caller has not passed an own bounding ractangle. */
4315             if ( rClientRect.IsEmpty() )
4316                  rClientRect = aObjData.aBoundRect;
4317             nGroupShapeFlags = aObjData.nSpFlags;
4318         }
4319         else if ( ( aObjData.eShapeType != mso_sptNil ) || IsProperty( DFF_Prop_pVertices ) || bGraphic )
4320         {
4321             SfxItemSet  aSet( pSdrModel->GetItemPool() );
4322 
4323             bool    bIsConnector = ( ( aObjData.eShapeType >= mso_sptStraightConnector1 ) && ( aObjData.eShapeType <= mso_sptCurvedConnector5 ) );
4324             sal_Int32   nObjectRotation = mnFix16Angle;
4325             ShapeFlag   nSpFlags = aObjData.nSpFlags;
4326 
4327             if ( bGraphic )
4328             {
4329                 if (!mbSkipImages) {
4330                     pRet = ImportGraphic( rSt, aSet, aObjData );        // SJ: #68396# is no longer true (fixed in ppt2000)
4331                     ApplyAttributes( rSt, aSet, aObjData );
4332                     pRet->SetMergedItemSet(aSet);
4333                 }
4334             }
4335             else if ( aObjData.eShapeType == mso_sptLine && !( GetPropertyValue( DFF_Prop_fc3DLightFace, 0 ) & 8 ) )
4336             {
4337                 basegfx::B2DPolygon aPoly;
4338                 aPoly.append(basegfx::B2DPoint(aObjData.aBoundRect.Left(), aObjData.aBoundRect.Top()));
4339                 aPoly.append(basegfx::B2DPoint(aObjData.aBoundRect.Right(), aObjData.aBoundRect.Bottom()));
4340                 pRet = new SdrPathObj(
4341                     *pSdrModel,
4342                     OBJ_LINE,
4343                     basegfx::B2DPolyPolygon(aPoly));
4344                 ApplyAttributes( rSt, aSet, aObjData );
4345                 pRet->SetMergedItemSet(aSet);
4346             }
4347             else
4348             {
4349                 if ( GetCustomShapeContent( aObjData.eShapeType ) || IsProperty( DFF_Prop_pVertices ) )
4350                 {
4351 
4352                     ApplyAttributes( rSt, aSet, aObjData );
4353 
4354                     pRet = new SdrObjCustomShape(*pSdrModel);
4355 
4356                     sal_uInt32 ngtextFStrikethrough = GetPropertyValue( DFF_Prop_gtextFStrikethrough, 0 );
4357                     bool bIsFontwork = ( ngtextFStrikethrough & 0x4000 ) != 0;
4358 
4359                     // in case of a FontWork, the text is set by the escher import
4360                     if ( bIsFontwork )
4361                     {
4362                         OUString            aObjectText;
4363                         OUString            aFontName;
4364                         MSO_GeoTextAlign    eGeoTextAlign;
4365 
4366                         if ( SeekToContent( DFF_Prop_gtextFont, rSt ) )
4367                         {
4368                             SvxFontItem aLatin(EE_CHAR_FONTINFO), aAsian(EE_CHAR_FONTINFO_CJK), aComplex(EE_CHAR_FONTINFO_CTL);
4369                             GetDefaultFonts( aLatin, aAsian, aComplex );
4370 
4371                             aFontName = MSDFFReadZString( rSt, GetPropertyValue( DFF_Prop_gtextFont, 0 ), true );
4372                             aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(),
4373                                         PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO ));
4374                             aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(),
4375                                         PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO_CJK ) );
4376                             aSet.Put( SvxFontItem( aLatin.GetFamily(), aFontName, aLatin.GetStyleName(),
4377                                         PITCH_DONTKNOW, RTL_TEXTENCODING_DONTKNOW, EE_CHAR_FONTINFO_CTL ) );
4378                         }
4379 
4380                         // SJ: applying fontattributes for Fontwork :
4381                         if ( IsHardAttribute( DFF_Prop_gtextFItalic ) )
4382                             aSet.Put( SvxPostureItem( ( ngtextFStrikethrough & 0x0010 ) != 0 ? ITALIC_NORMAL : ITALIC_NONE, EE_CHAR_ITALIC ) );
4383 
4384                         if ( IsHardAttribute( DFF_Prop_gtextFBold ) )
4385                             aSet.Put( SvxWeightItem( ( ngtextFStrikethrough & 0x0020 ) != 0 ? WEIGHT_BOLD : WEIGHT_NORMAL, EE_CHAR_WEIGHT ) );
4386 
4387                         // SJ TODO: Vertical Writing is not correct, instead
4388                         // this should be replaced through "CharacterRotation"
4389                         // by 90 degrees, therefore a new Item has to be
4390                         // supported by svx core, api and xml file format
4391                         static_cast<SdrObjCustomShape*>(pRet)->SetVerticalWriting( ( ngtextFStrikethrough & 0x2000 ) != 0 );
4392 
4393                         if ( SeekToContent( DFF_Prop_gtextUNICODE, rSt ) )
4394                         {
4395                             aObjectText = MSDFFReadZString( rSt, GetPropertyValue( DFF_Prop_gtextUNICODE, 0 ), true );
4396                             ReadObjText( aObjectText, pRet );
4397                         }
4398 
4399                         eGeoTextAlign = static_cast<MSO_GeoTextAlign>(GetPropertyValue( DFF_Prop_gtextAlign, mso_alignTextCenter ));
4400                         {
4401                             SdrTextHorzAdjust eHorzAdjust;
4402                             switch( eGeoTextAlign )
4403                             {
4404                                 case mso_alignTextLetterJust :
4405                                 case mso_alignTextWordJust :
4406                                 case mso_alignTextStretch : eHorzAdjust = SDRTEXTHORZADJUST_BLOCK; break;
4407                                 default:
4408                                 case mso_alignTextInvalid :
4409                                 case mso_alignTextCenter : eHorzAdjust = SDRTEXTHORZADJUST_CENTER; break;
4410                                 case mso_alignTextLeft : eHorzAdjust = SDRTEXTHORZADJUST_LEFT; break;
4411                                 case mso_alignTextRight : eHorzAdjust = SDRTEXTHORZADJUST_RIGHT; break;
4412                             }
4413                             aSet.Put( SdrTextHorzAdjustItem( eHorzAdjust ) );
4414 
4415                             drawing::TextFitToSizeType eFTS = drawing::TextFitToSizeType_NONE;
4416                             if ( eGeoTextAlign == mso_alignTextStretch )
4417                                 eFTS = drawing::TextFitToSizeType_ALLLINES;
4418                             aSet.Put( SdrTextFitToSizeTypeItem( eFTS ) );
4419                         }
4420                         if ( IsProperty( DFF_Prop_gtextSpacing ) )
4421                         {
4422                             sal_Int32 nTextWidth = GetPropertyValue( DFF_Prop_gtextSpacing, 1 << 16 ) / 655;
4423                             if ( nTextWidth != 100 )
4424                                 aSet.Put( SvxCharScaleWidthItem( static_cast<sal_uInt16>(nTextWidth), EE_CHAR_FONTWIDTH ) );
4425                         }
4426                         if ( ngtextFStrikethrough & 0x1000 ) // SJ: Font Kerning On ?
4427                             aSet.Put( SvxKerningItem( 1, EE_CHAR_KERNING ) );
4428 
4429                         // #i119496# the resize autoshape to fit text attr of word art in MS PPT is always false
4430                         aSet.Put(makeSdrTextAutoGrowHeightItem(false));
4431                         aSet.Put(makeSdrTextAutoGrowWidthItem(false));
4432 
4433                         bool bWithPadding = !( ngtextFStrikethrough & use_gtextFBestFit
4434                                             && ngtextFStrikethrough & use_gtextFShrinkFit
4435                                             && ngtextFStrikethrough & use_gtextFStretch
4436                                             && ngtextFStrikethrough & gtextFBestFit
4437                                             && ngtextFStrikethrough & gtextFShrinkFit
4438                                             && ngtextFStrikethrough & gtextFStretch );
4439 
4440                         if ( bWithPadding )
4441                         {
4442                             // trim, remove additional space
4443                             VclPtr<VirtualDevice> pDevice = VclPtr<VirtualDevice>::Create();
4444                             vcl::Font aFont = pDevice->GetFont();
4445                             aFont.SetFamilyName( aFontName );
4446                             aFont.SetFontSize( Size( 0, 96 ) );
4447                             pDevice->SetFont( aFont );
4448 
4449                             auto nTextWidth = pDevice->GetTextWidth( aObjectText );
4450                             OUString aObjName = GetPropertyString( DFF_Prop_wzName, rSt );
4451                             if ( nTextWidth && aObjData.eShapeType == mso_sptTextPlainText
4452                                 && aObjName.match( "PowerPlusWaterMarkObject" ) )
4453                             {
4454                                 double fRatio = static_cast<double>(pDevice->GetTextHeight()) / nTextWidth;
4455                                 sal_Int32 nNewHeight = fRatio * aObjData.aBoundRect.getWidth();
4456                                 sal_Int32 nPaddingY = aObjData.aBoundRect.getHeight() - nNewHeight;
4457 
4458                                 if ( nPaddingY > 0 )
4459                                     aObjData.aBoundRect.setHeight( nNewHeight );
4460                             }
4461                         }
4462                     }
4463                     pRet->SetMergedItemSet( aSet );
4464 
4465                     // sj: taking care of rtl, ltr. In case of fontwork mso. seems not to be able to set
4466                     // proper text directions, instead the text default is depending to the string.
4467                     // so we have to calculate the a text direction from string:
4468                     if ( bIsFontwork )
4469                     {
4470                         OutlinerParaObject* pParaObj = static_cast<SdrObjCustomShape*>(pRet)->GetOutlinerParaObject();
4471                         if ( pParaObj )
4472                         {
4473                             SdrOutliner& rOutliner = static_cast<SdrObjCustomShape*>(pRet)->ImpGetDrawOutliner();
4474                             bool bOldUpdateMode = rOutliner.GetUpdateMode();
4475                             rOutliner.SetStyleSheetPool(static_cast< SfxStyleSheetPool* >(pRet->getSdrModelFromSdrObject().GetStyleSheetPool()));
4476                             rOutliner.SetUpdateMode( false );
4477                             rOutliner.SetText( *pParaObj );
4478                             ScopedVclPtrInstance< VirtualDevice > pVirDev(DeviceFormat::BITMASK);
4479                             pVirDev->SetMapMode(MapMode(MapUnit::Map100thMM));
4480                             sal_Int32 i, nParagraphs = rOutliner.GetParagraphCount();
4481                             if ( nParagraphs )
4482                             {
4483                                 bool bCreateNewParaObject = false;
4484                                 for ( i = 0; i < nParagraphs; i++ )
4485                                 {
4486                                     OUString aString(rOutliner.GetText(rOutliner.GetParagraph(i)));
4487                                     bool bIsRTL = pVirDev->GetTextIsRTL(aString, 0, aString.getLength());
4488                                     if ( bIsRTL )
4489                                     {
4490                                         SfxItemSet aSet2( rOutliner.GetParaAttribs( i ) );
4491                                         aSet2.Put( SvxFrameDirectionItem( SvxFrameDirection::Horizontal_RL_TB, EE_PARA_WRITINGDIR ) );
4492                                         rOutliner.SetParaAttribs( i, aSet2 );
4493                                         bCreateNewParaObject = true;
4494                                     }
4495                                 }
4496                                 if  ( bCreateNewParaObject )
4497                                 {
4498                                     std::unique_ptr<OutlinerParaObject> pNewText = rOutliner.CreateParaObject();
4499                                     rOutliner.Init( OutlinerMode::TextObject );
4500                                     static_cast<SdrObjCustomShape*>(pRet)->NbcSetOutlinerParaObject( std::move(pNewText) );
4501                                 }
4502                             }
4503                             rOutliner.Clear();
4504                             rOutliner.SetUpdateMode( bOldUpdateMode );
4505                         }
4506                     }
4507 
4508                     // mso_sptArc special treating:
4509                     // sj: since we actually can't render the arc because of its weird SnapRect settings,
4510                     // we will create a new CustomShape, that can be saved/loaded without problems.
4511                     // We will change the shape type, so this code applies only if importing arcs from msoffice.
4512                     if ( aObjData.eShapeType == mso_sptArc )
4513                     {
4514                         const OUString sAdjustmentValues( "AdjustmentValues" );
4515                         const OUString sCoordinates( "Coordinates" );
4516                         const OUString sHandles( "Handles" );
4517                         const OUString sEquations( "Equations" );
4518                         const OUString sViewBox( "ViewBox" );
4519                         const OUString sPath( "Path" );
4520                         const OUString sTextFrames( "TextFrames" );
4521                         SdrCustomShapeGeometryItem aGeometryItem( static_cast<SdrObjCustomShape*>(pRet)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
4522                         css::uno::Sequence< css::drawing::EnhancedCustomShapeParameterPair> seqCoordinates;
4523                         css::uno::Sequence< css::drawing::EnhancedCustomShapeAdjustmentValue > seqAdjustmentValues;
4524 
4525                         // before clearing the GeometryItem we have to store the current Coordinates
4526                         const uno::Any* pAny = aGeometryItem.GetPropertyValueByName( sPath, sCoordinates );
4527                         tools::Rectangle aPolyBoundRect;
4528                         Point aStartPt( 0,0 );
4529                         if ( pAny && ( *pAny >>= seqCoordinates ) && ( seqCoordinates.getLength() >= 4 ) )
4530                         {
4531                             sal_Int32 nPtNum, nNumElemVert = seqCoordinates.getLength();
4532                             XPolygon aXP( static_cast<sal_uInt16>(nNumElemVert) );
4533                             for ( nPtNum = 0; nPtNum < nNumElemVert; nPtNum++ )
4534                             {
4535                                 Point aP;
4536                                 sal_Int32 nX = 0, nY = 0;
4537                                 seqCoordinates[ nPtNum ].First.Value >>= nX;
4538                                 seqCoordinates[ nPtNum ].Second.Value >>= nY;
4539                                 aP.setX( nX );
4540                                 aP.setY( nY );
4541                                 aXP[ static_cast<sal_uInt16>(nPtNum) ] = aP;
4542                             }
4543                             aPolyBoundRect = aXP.GetBoundRect();
4544                             if ( nNumElemVert >= 3 )
4545                             { // arc first command is always wr -- clockwise arc
4546                                 // the parameters are : (left,top),(right,bottom),start(x,y),end(x,y)
4547                                 aStartPt = aXP[2];
4548                             }
4549                         }
4550                         else
4551                             aPolyBoundRect = tools::Rectangle( -21600, 0, 21600, 43200 );  // defaulting
4552 
4553                         // clearing items, so MergeDefaultAttributes will set the corresponding defaults from EnhancedCustomShapeGeometry
4554                         aGeometryItem.ClearPropertyValue( sHandles );
4555                         aGeometryItem.ClearPropertyValue( sEquations );
4556                         aGeometryItem.ClearPropertyValue( sViewBox );
4557                         aGeometryItem.ClearPropertyValue( sPath );
4558 
4559                         sal_Int32 nEndAngle = 9000;
4560                         sal_Int32 nStartAngle = 0;
4561                         pAny = aGeometryItem.GetPropertyValueByName( sAdjustmentValues );
4562                         if ( pAny && ( *pAny >>= seqAdjustmentValues ) && seqAdjustmentValues.getLength() > 1 )
4563                         {
4564                             if ( seqAdjustmentValues[ 0 ].State == css::beans::PropertyState_DIRECT_VALUE )
4565                             {
4566                                 double fNumber;
4567                                 seqAdjustmentValues[ 0 ].Value >>= fNumber;
4568                                 sal_Int32 nValue;
4569                                 bool bFail = o3tl::checked_multiply<sal_Int32>(fNumber, 100, nValue);
4570                                 if (bFail)
4571                                     SAL_WARN("filter.ms", "nEndAngle too large: " << fNumber);
4572                                 else
4573                                     nEndAngle = NormAngle36000(-nValue);
4574                             }
4575                             else
4576                             {
4577                                 //normal situation:if endAngle != 90,there will be a direct_value,but for damaged curve,the endAngle need to recalculate.
4578                                 Point cent = aPolyBoundRect.Center();
4579                                 double fNumber;
4580                                 if ( aStartPt.Y() == cent.Y() )
4581                                     fNumber = ( aStartPt.X() >= cent.X() ) ? 0:180.0;
4582                                 else if ( aStartPt.X() == cent.X() )
4583                                     fNumber = ( aStartPt.Y() >= cent.Y() ) ? 90.0: 270.0;
4584                                 else
4585                                 {
4586                                     fNumber
4587                                         = basegfx::rad2deg(atan2(double(aStartPt.X() - cent.X()),
4588                                                                  double(aStartPt.Y() - cent.Y()))
4589                                                            + F_PI); // 0..360.0
4590                                 }
4591                                 nEndAngle = NormAngle36000( - static_cast<sal_Int32>(fNumber) * 100 );
4592                                 seqAdjustmentValues[ 0 ].Value <<= fNumber;
4593                                 seqAdjustmentValues[ 0 ].State = css::beans::PropertyState_DIRECT_VALUE;     // so this value will properly be stored
4594                             }
4595 
4596                             if ( seqAdjustmentValues[ 1 ].State == css::beans::PropertyState_DIRECT_VALUE )
4597                             {
4598                                 double fNumber;
4599                                 seqAdjustmentValues[ 1 ].Value >>= fNumber;
4600                                 nStartAngle = NormAngle36000( - static_cast<sal_Int32>(fNumber) * 100 );
4601                             }
4602                             else
4603                             {
4604                                 seqAdjustmentValues[ 1 ].Value <<= 0.0;
4605                                 seqAdjustmentValues[ 1 ].State = css::beans::PropertyState_DIRECT_VALUE;
4606                             }
4607 
4608                             PropertyValue aPropVal;
4609                             aPropVal.Name = sAdjustmentValues;
4610                             aPropVal.Value <<= seqAdjustmentValues;
4611                             aGeometryItem.SetPropertyValue( aPropVal );     // storing the angle attribute
4612                         }
4613                         if ( nStartAngle != nEndAngle )
4614                         {
4615                             XPolygon aXPoly( aPolyBoundRect.Center(), aPolyBoundRect.GetWidth() / 2, aPolyBoundRect.GetHeight() / 2,
4616                                 static_cast<sal_uInt16>(nStartAngle) / 10, static_cast<sal_uInt16>(nEndAngle) / 10, true );
4617                             tools::Rectangle aPolyPieRect( aXPoly.GetBoundRect() );
4618 
4619                             double  fYScale = 0.0, fXScale = 0.0;
4620                             double  fYOfs, fXOfs;
4621 
4622                             Point aP( aObjData.aBoundRect.Center() );
4623                             Size aS( aObjData.aBoundRect.GetSize() );
4624                             aP.AdjustX( -(aS.Width() / 2) );
4625                             aP.AdjustY( -(aS.Height() / 2) );
4626                             tools::Rectangle aLogicRect( aP, aS );
4627 
4628                             fYOfs = fXOfs = 0.0;
4629 
4630                             if ( aPolyBoundRect.GetWidth() && aPolyPieRect.GetWidth() )
4631                             {
4632                                 fXScale = static_cast<double>(aLogicRect.GetWidth()) / static_cast<double>(aPolyPieRect.GetWidth());
4633                                 if ( nSpFlags & ShapeFlag::FlipH )
4634                                     fXOfs = ( static_cast<double>(aPolyPieRect.Right()) - static_cast<double>(aPolyBoundRect.Right()) ) * fXScale;
4635                                 else
4636                                     fXOfs = ( static_cast<double>(aPolyBoundRect.Left()) - static_cast<double>(aPolyPieRect.Left()) ) * fXScale;
4637                             }
4638                             if ( aPolyBoundRect.GetHeight() && aPolyPieRect.GetHeight() )
4639                             {
4640                                 fYScale = static_cast<double>(aLogicRect.GetHeight()) / static_cast<double>(aPolyPieRect.GetHeight());
4641                                 if ( nSpFlags & ShapeFlag::FlipV )
4642                                     fYOfs = ( static_cast<double>(aPolyPieRect.Bottom()) - static_cast<double>(aPolyBoundRect.Bottom()) ) * fYScale;
4643                                 else
4644                                     fYOfs = (static_cast<double>(aPolyBoundRect.Top()) - static_cast<double>(aPolyPieRect.Top()) ) * fYScale;
4645                             }
4646 
4647                             if ( aPolyPieRect.GetWidth() )
4648                                 fXScale = static_cast<double>(aPolyBoundRect.GetWidth()) / static_cast<double>(aPolyPieRect.GetWidth());
4649                             if ( aPolyPieRect.GetHeight() )
4650                                 fYScale = static_cast<double>(aPolyBoundRect.GetHeight()) / static_cast<double>(aPolyPieRect.GetHeight());
4651 
4652                             tools::Rectangle aOldBoundRect( aObjData.aBoundRect );
4653                             aObjData.aBoundRect = tools::Rectangle( Point( aLogicRect.Left() + static_cast<sal_Int32>(fXOfs), aLogicRect.Top() + static_cast<sal_Int32>(fYOfs) ),
4654                                  Size( static_cast<sal_Int32>( aLogicRect.GetWidth() * fXScale ), static_cast<sal_Int32>( aLogicRect.GetHeight() * fYScale ) ) );
4655 
4656                             // creating the text frame -> scaling into (0,0),(21600,21600) destination coordinate system
4657                             double fTextFrameScaleX = 0.0;
4658                             double fTextFrameScaleY = 0.0;
4659                             if (aPolyBoundRect.GetWidth())
4660                                 fTextFrameScaleX = double(21600) / static_cast<double>(aPolyBoundRect.GetWidth());
4661                             if (aPolyBoundRect.GetHeight())
4662                                 fTextFrameScaleY = double(21600) / static_cast<double>(aPolyBoundRect.GetHeight());
4663 
4664                             sal_Int32 nLeft  = static_cast<sal_Int32>(( aPolyPieRect.Left()  - aPolyBoundRect.Left() ) * fTextFrameScaleX );
4665                             sal_Int32 nTop   = static_cast<sal_Int32>(( aPolyPieRect.Top()   - aPolyBoundRect.Top() )  * fTextFrameScaleY );
4666                             sal_Int32 nRight = static_cast<sal_Int32>(( aPolyPieRect.Right() - aPolyBoundRect.Left() ) * fTextFrameScaleX );
4667                             sal_Int32 nBottom= static_cast<sal_Int32>(( aPolyPieRect.Bottom()- aPolyBoundRect.Top() )  * fTextFrameScaleY );
4668                             css::uno::Sequence< css::drawing::EnhancedCustomShapeTextFrame > aTextFrame( 1 );
4669                             EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].TopLeft.First,     nLeft );
4670                             EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].TopLeft.Second,    nTop );
4671                             EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].BottomRight.First, nRight );
4672                             EnhancedCustomShape2d::SetEnhancedCustomShapeParameter( aTextFrame[ 0 ].BottomRight.Second,nBottom );
4673                             PropertyValue aProp;
4674                             aProp.Name = sTextFrames;
4675                             aProp.Value <<= aTextFrame;
4676                             aGeometryItem.SetPropertyValue( sPath, aProp );
4677 
4678                             // sj: taking care of the different rotation points, since the new arc is having a bigger snaprect
4679                             if ( mnFix16Angle )
4680                             {
4681                                 sal_Int32 nAngle = mnFix16Angle;
4682                                 if ( nSpFlags & ShapeFlag::FlipH )
4683                                     nAngle = 36000 - nAngle;
4684                                 if ( nSpFlags & ShapeFlag::FlipV )
4685                                     nAngle = -nAngle;
4686                                 double a = nAngle * F_PI18000;
4687                                 double ss = sin( a );
4688                                 double cc = cos( a );
4689                                 Point aP1( aOldBoundRect.TopLeft() );
4690                                 Point aC1( aObjData.aBoundRect.Center() );
4691                                 Point aP2( aOldBoundRect.TopLeft() );
4692                                 Point aC2( aOldBoundRect.Center() );
4693                                 RotatePoint( aP1, aC1, ss, cc );
4694                                 RotatePoint( aP2, aC2, ss, cc );
4695                                 aObjData.aBoundRect.Move( aP2.X() - aP1.X(), aP2.Y() - aP1.Y() );
4696                             }
4697                         }
4698                         static_cast<SdrObjCustomShape*>(pRet)->SetMergedItem( aGeometryItem );
4699                         static_cast<SdrObjCustomShape*>(pRet)->MergeDefaultAttributes();
4700 
4701                         // now setting a new name, so the above correction is only done once when importing from ms
4702                         SdrCustomShapeGeometryItem aGeoName( static_cast<SdrObjCustomShape*>(pRet)->GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) );
4703                         const OUString sType( "Type" );
4704                         const OUString sName( "mso-spt100" );
4705                         PropertyValue aPropVal;
4706                         aPropVal.Name = sType;
4707                         aPropVal.Value <<= sName;
4708                         aGeoName.SetPropertyValue( aPropVal );
4709                         static_cast<SdrObjCustomShape*>(pRet)->SetMergedItem( aGeoName );
4710                     }
4711                     else
4712                         static_cast<SdrObjCustomShape*>(pRet)->MergeDefaultAttributes();
4713 
4714                     pRet->SetSnapRect( aObjData.aBoundRect );
4715                     EnhancedCustomShape2d aCustomShape2d(static_cast<SdrObjCustomShape&>(*pRet));
4716                     aTextRect = aCustomShape2d.GetTextRect();
4717 
4718                     if( bIsConnector )
4719                     {
4720                         if( nObjectRotation )
4721                         {
4722                             double a = nObjectRotation * nPi180;
4723                             pRet->NbcRotate( aObjData.aBoundRect.Center(), nObjectRotation, sin( a ), cos( a ) );
4724                         }
4725                         // mirrored horizontally?
4726                         if ( nSpFlags & ShapeFlag::FlipH )
4727                         {
4728                             tools::Rectangle aBndRect( pRet->GetSnapRect() );
4729                             Point aTop( ( aBndRect.Left() + aBndRect.Right() ) >> 1, aBndRect.Top() );
4730                             Point aBottom( aTop.X(), aTop.Y() + 1000 );
4731                             pRet->NbcMirror( aTop, aBottom );
4732                         }
4733                         // mirrored vertically?
4734                         if ( nSpFlags & ShapeFlag::FlipV )
4735                         {
4736                             tools::Rectangle aBndRect( pRet->GetSnapRect() );
4737                             Point aLeft( aBndRect.Left(), ( aBndRect.Top() + aBndRect.Bottom() ) >> 1 );
4738                             Point aRight( aLeft.X() + 1000, aLeft.Y() );
4739                             pRet->NbcMirror( aLeft, aRight );
4740                         }
4741                         basegfx::B2DPolyPolygon aPoly( static_cast<SdrObjCustomShape*>(pRet)->GetLineGeometry( true ) );
4742                         SdrObject::Free( pRet );
4743 
4744                         pRet = new SdrEdgeObj(*pSdrModel);
4745                         ApplyAttributes( rSt, aSet, aObjData );
4746                         pRet->SetLogicRect( aObjData.aBoundRect );
4747                         pRet->SetMergedItemSet(aSet);
4748 
4749                         // connectors
4750                         MSO_ConnectorStyle eConnectorStyle = static_cast<MSO_ConnectorStyle>(GetPropertyValue( DFF_Prop_cxstyle, mso_cxstyleStraight ));
4751 
4752                         static_cast<SdrEdgeObj*>(pRet)->ConnectToNode(true, nullptr);
4753                         static_cast<SdrEdgeObj*>(pRet)->ConnectToNode(false, nullptr);
4754 
4755                         Point aPoint1( aObjData.aBoundRect.TopLeft() );
4756                         Point aPoint2( aObjData.aBoundRect.BottomRight() );
4757 
4758                         // pay attention to the rotations
4759                         if ( nObjectRotation )
4760                         {
4761                             double a = nObjectRotation * nPi180;
4762                             Point aCenter( aObjData.aBoundRect.Center() );
4763                             double ss = sin(a);
4764                             double cc = cos(a);
4765 
4766                             RotatePoint(aPoint1, aCenter, ss, cc);
4767                             RotatePoint(aPoint2, aCenter, ss, cc);
4768 
4769                             // #i120437# reset rotation, it is part of the path and shall not be applied again
4770                             nObjectRotation = 0;
4771                         }
4772 
4773                         // rotate/mirror line within the area as we need it
4774                         if ( nSpFlags & ShapeFlag::FlipH )
4775                         {
4776                             sal_Int32 n = aPoint1.X();
4777                             aPoint1.setX( aPoint2.X() );
4778                             aPoint2.setX( n );
4779 
4780                             // #i120437# reset hor filp
4781                             nSpFlags &= ~ShapeFlag::FlipH;
4782                         }
4783                         if ( nSpFlags & ShapeFlag::FlipV )
4784                         {
4785                             sal_Int32 n = aPoint1.Y();
4786                             aPoint1.setY( aPoint2.Y() );
4787                             aPoint2.setY( n );
4788 
4789                             // #i120437# reset ver filp
4790                             nSpFlags &= ~ShapeFlag::FlipV;
4791                         }
4792 
4793                         pRet->NbcSetPoint(aPoint1, 0); // start point
4794                         pRet->NbcSetPoint(aPoint2, 1); // endpoint
4795 
4796                         sal_Int32 n1HorzDist, n1VertDist, n2HorzDist, n2VertDist;
4797                         n1HorzDist = n1VertDist = n2HorzDist = n2VertDist = 0;
4798                         switch( eConnectorStyle )
4799                         {
4800                             case mso_cxstyleBent:
4801                             {
4802                                 aSet.Put( SdrEdgeKindItem( SdrEdgeKind::OrthoLines ) );
4803                                 n1HorzDist = n1VertDist = n2HorzDist = n2VertDist = 630;
4804                             }
4805                             break;
4806                             case mso_cxstyleCurved:
4807                                 aSet.Put( SdrEdgeKindItem( SdrEdgeKind::Bezier ) );
4808                             break;
4809                             default: // mso_cxstyleStraight || mso_cxstyleNone
4810                                 aSet.Put( SdrEdgeKindItem( SdrEdgeKind::OneLine ) );
4811                             break;
4812                         }
4813                         aSet.Put( SdrEdgeNode1HorzDistItem( n1HorzDist ) );
4814                         aSet.Put( SdrEdgeNode1VertDistItem( n1VertDist ) );
4815                         aSet.Put( SdrEdgeNode2HorzDistItem( n2HorzDist ) );
4816                         aSet.Put( SdrEdgeNode2VertDistItem( n2VertDist ) );
4817 
4818                         static_cast<SdrEdgeObj*>(pRet)->SetEdgeTrackPath( aPoly );
4819                         pRet->SetMergedItemSet( aSet );
4820                     }
4821                     if ( aObjData.eShapeType == mso_sptLine )
4822                     {
4823                         pRet->SetMergedItemSet(aSet);
4824                         static_cast<SdrObjCustomShape*>(pRet)->MergeDefaultAttributes();
4825                     }
4826                 }
4827             }
4828 
4829             if ( pRet )
4830             {
4831                 if( nObjectRotation )
4832                 {
4833                     double a = nObjectRotation * nPi180;
4834                     pRet->NbcRotate( aObjData.aBoundRect.Center(), nObjectRotation, sin( a ), cos( a ) );
4835                 }
4836                 // mirrored horizontally?
4837                 if ( nSpFlags & ShapeFlag::FlipH )
4838                 {
4839                     tools::Rectangle aBndRect( pRet->GetSnapRect() );
4840                     Point aTop( ( aBndRect.Left() + aBndRect.Right() ) >> 1, aBndRect.Top() );
4841                     Point aBottom( aTop.X(), aTop.Y() + 1000 );
4842                     pRet->NbcMirror( aTop, aBottom );
4843                 }
4844                 // mirrored vertically?
4845                 if ( nSpFlags & ShapeFlag::FlipV )
4846                 {
4847                     tools::Rectangle aBndRect( pRet->GetSnapRect() );
4848                     Point aLeft( aBndRect.Left(), ( aBndRect.Top() + aBndRect.Bottom() ) >> 1 );
4849                     Point aRight( aLeft.X() + 1000, aLeft.Y() );
4850                     pRet->NbcMirror( aLeft, aRight );
4851                 }
4852             }
4853         }
4854     }
4855 
4856     // #i51348# #118052# name of the shape
4857     if( pRet )
4858     {
4859         OUString aObjName = GetPropertyString( DFF_Prop_wzName, rSt );
4860         if( !aObjName.isEmpty() )
4861             pRet->SetName( aObjName );
4862     }
4863 
4864     pRet =
4865         ProcessObj( rSt, aObjData, rClientData, aTextRect, pRet);
4866 
4867     if ( pRet )
4868     {
4869         sal_Int32 nGroupProperties( GetPropertyValue( DFF_Prop_fPrint, 0 ) );
4870         const bool bVisible = ( ( nGroupProperties & 2 ) == 0 );
4871         pRet->SetVisible( bVisible );
4872         // In Excel hidden means not printed
4873         if ( !bVisible )
4874         {
4875             pRet->SetPrintable( false );
4876         }
4877         else
4878         {
4879             // This property isn't used in Excel anymore, leaving it for legacy reasons
4880             pRet->SetPrintable( ( nGroupProperties & 1 ) != 0 );
4881         }
4882     }
4883 
4884     //Import alt text as description
4885     if ( pRet && SeekToContent( DFF_Prop_wzDescription, rSt ) )
4886     {
4887         OUString aAltText = MSDFFReadZString(rSt, GetPropertyValue(DFF_Prop_wzDescription, 0), true);
4888         pRet->SetDescription( aAltText );
4889     }
4890 
4891     // If this shape opens a new group, push back its object data because
4892     // finalization will be called when nested objects have been imported;
4893     // otherwise, just finalize here
4894     if (size_t(nCalledByGroup) > maPendingGroupData.size())
4895     {
4896         std::shared_ptr<DffRecordHeader> rHdClone(new DffRecordHeader(aObjData.rSpHd));
4897         maPendingGroupData.emplace_back(DffObjData(rHdClone, aObjData), rHdClone );
4898     }
4899     else
4900     {
4901         pRet = FinalizeObj(aObjData, pRet);
4902     }
4903     return pRet;
4904 }
4905 
4906 tools::Rectangle SvxMSDffManager::GetGlobalChildAnchor( const DffRecordHeader& rHd, SvStream& rSt, tools::Rectangle& aClientRect )
4907 {
4908     tools::Rectangle aChildAnchor;
4909     if (!rHd.SeekToContent(rSt))
4910         return aChildAnchor;
4911 
4912     bool bIsClientRectRead = false;
4913     while ( ( rSt.GetError() == ERRCODE_NONE ) && ( rSt.Tell() < rHd.GetRecEndFilePos() ) )
4914     {
4915         DffRecordHeader aShapeHd;
4916         if (!ReadDffRecordHeader(rSt, aShapeHd))
4917             break;
4918         if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer ) ||
4919                 ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) )
4920         {
4921             DffRecordHeader aShapeHd2( aShapeHd );
4922             if ( aShapeHd.nRecType == DFF_msofbtSpgrContainer )
4923                 ReadDffRecordHeader( rSt, aShapeHd2 );
4924             while (rSt.good() && rSt.Tell() < aShapeHd2.GetRecEndFilePos())
4925             {
4926                 DffRecordHeader aShapeAtom;
4927                 if (!ReadDffRecordHeader(rSt, aShapeAtom))
4928                     break;
4929 
4930                 if ( aShapeAtom.nRecType == DFF_msofbtClientAnchor )
4931                 {
4932                     if ( GetSvxMSDffSettings() & SVXMSDFF_SETTINGS_IMPORT_PPT )
4933                     {
4934                         sal_Int32 l(0), t(0), r(0), b(0);
4935                         if ( aShapeAtom.nRecLen == 16 )
4936                         {
4937                             rSt.ReadInt32( l ).ReadInt32( t ).ReadInt32( r ).ReadInt32( b );
4938                         }
4939                         else
4940                         {
4941                             sal_Int16 ls(0), ts(0), rs(0), bs(0);
4942                             rSt.ReadInt16( ts ).ReadInt16( ls ).ReadInt16( rs ).ReadInt16( bs ); // the order of coordinates is a bit strange...
4943                             l = ls;
4944                             t = ts;
4945                             r = rs;
4946                             b = bs;
4947                         }
4948                         Scale( l );
4949                         Scale( t );
4950                         Scale( r );
4951                         Scale( b );
4952                         if ( bIsClientRectRead )
4953                         {
4954                             tools::Rectangle aChild( l, t, r, b );
4955                             aChildAnchor.Union( aChild );
4956                         }
4957                         else
4958                         {
4959                             aClientRect = tools::Rectangle( l, t, r, b );
4960                             bIsClientRectRead = true;
4961                         }
4962                     }
4963                     break;
4964                 }
4965                 else if ( aShapeAtom.nRecType == DFF_msofbtChildAnchor )
4966                 {
4967                     sal_Int32 l(0), o(0), r(0), u(0);
4968                     rSt.ReadInt32( l ).ReadInt32( o ).ReadInt32( r ).ReadInt32( u );
4969                     Scale( l );
4970                     Scale( o );
4971                     Scale( r );
4972                     Scale( u );
4973                     tools::Rectangle aChild( l, o, r, u );
4974                     aChildAnchor.Union( aChild );
4975                     break;
4976                 }
4977                 if (!aShapeAtom.SeekToEndOfRecord(rSt))
4978                     break;
4979             }
4980         }
4981         if (!aShapeHd.SeekToEndOfRecord(rSt))
4982             break;
4983     }
4984     return aChildAnchor;
4985 }
4986 
4987 void SvxMSDffManager::GetGroupAnchors( const DffRecordHeader& rHd, SvStream& rSt,
4988                             tools::Rectangle& rGroupClientAnchor, tools::Rectangle& rGroupChildAnchor,
4989                                 const tools::Rectangle& rClientRect, const tools::Rectangle& rGlobalChildRect )
4990 {
4991     if (!rHd.SeekToContent(rSt))
4992         return;
4993 
4994     bool bFirst = true;
4995     DffRecordHeader aShapeHd;
4996     while (rSt.good() && rSt.Tell() < rHd.GetRecEndFilePos())
4997     {
4998         if (!ReadDffRecordHeader(rSt, aShapeHd))
4999             break;
5000         if ( ( aShapeHd.nRecType == DFF_msofbtSpContainer ) ||
5001                 ( aShapeHd.nRecType == DFF_msofbtSpgrContainer ) )
5002         {
5003             DffRecordHeader aShapeHd2( aShapeHd );
5004             if ( aShapeHd.nRecType == DFF_msofbtSpgrContainer )
5005                 ReadDffRecordHeader( rSt, aShapeHd2 );
5006             while (rSt.good() && rSt.Tell() < aShapeHd2.GetRecEndFilePos())
5007             {
5008                 DffRecordHeader aShapeAtom;
5009                 if (!ReadDffRecordHeader(rSt, aShapeAtom))
5010                     break;
5011                 if ( aShapeAtom.nRecType == DFF_msofbtChildAnchor )
5012                 {
5013                     sal_Int32 l(0), o(0), r(0), u(0);
5014                     rSt.ReadInt32( l ).ReadInt32( o ).ReadInt32( r ).ReadInt32( u );
5015                     Scale( l );
5016                     Scale( o );
5017                     Scale( r );
5018                     Scale( u );
5019                     tools::Rectangle aChild( l, o, r, u );
5020 
5021                     if ( bFirst )
5022                     {
5023                         if ( !rGlobalChildRect.IsEmpty() && !rClientRect.IsEmpty() && rGlobalChildRect.GetWidth() && rGlobalChildRect.GetHeight() )
5024                         {
5025                             double fWidth = o3tl::saturating_sub(r, l);
5026                             double fHeight= o3tl::saturating_sub(u, o);
5027                             double fXScale = static_cast<double>(rClientRect.GetWidth()) / static_cast<double>(rGlobalChildRect.GetWidth());
5028                             double fYScale = static_cast<double>(rClientRect.GetHeight()) / static_cast<double>(rGlobalChildRect.GetHeight());
5029                             double fl = ( ( l - rGlobalChildRect.Left() ) * fXScale ) + rClientRect.Left();
5030                             double fo = ( ( o - rGlobalChildRect.Top()  ) * fYScale ) + rClientRect.Top();
5031                             fWidth *= fXScale;
5032                             fHeight *= fYScale;
5033                             rGroupClientAnchor = tools::Rectangle( Point( static_cast<sal_Int32>(fl), static_cast<sal_Int32>(fo) ), Size( static_cast<sal_Int32>( fWidth + 1 ), static_cast<sal_Int32>( fHeight + 1 ) ) );
5034                         }
5035                         bFirst = false;
5036                     }
5037                     else
5038                         rGroupChildAnchor.Union( aChild );
5039                     break;
5040                 }
5041                 if (!aShapeAtom.SeekToEndOfRecord(rSt))
5042                     break;
5043             }
5044         }
5045         if (!aShapeHd.SeekToEndOfRecord(rSt))
5046             break;
5047     }
5048 }
5049 
5050 SvxMSDffImportRec* SvxMSDffImportData::find(const SdrObject* pObj)
5051 {
5052     auto it = m_ObjToRecMap.find(pObj);
5053     if (it != m_ObjToRecMap.end())
5054         return it->second;
5055     return nullptr;
5056 }
5057 
5058 void SvxMSDffImportData::insert(std::unique_ptr<SvxMSDffImportRec> pImpRec)
5059 {
5060     m_ObjToRecMap[pImpRec->pObj] = pImpRec.get();
5061     m_Records.insert(std::move(pImpRec));
5062 }
5063 
5064 void SvxMSDffImportData::NotifyFreeObj(SdrObject* pObj)
5065 {
5066     if (SvxMSDffImportRec* pRecord = find(pObj))
5067     {
5068         unmap(pObj);
5069         pRecord->pObj = nullptr;
5070     }
5071 }
5072 
5073 void SvxMSDffManager::NotifyFreeObj(SvxMSDffClientData& rData, SdrObject* pObj)
5074 {
5075     if (SdrObjGroup* pGroup = dynamic_cast<SdrObjGroup*>(pObj))
5076     {
5077         SdrObjList* pSubList = pGroup->GetSubList();
5078         size_t nObjCount = pSubList->GetObjCount();
5079         for (size_t i = 0; i < nObjCount; ++i)
5080             NotifyFreeObj(rData, pSubList->GetObj(i));
5081     }
5082 
5083     rData.NotifyFreeObj(pObj);
5084 }
5085 
5086 void SvxMSDffManager::FreeObj(SvxMSDffClientData& rData, SdrObject* pObj)
5087 {
5088     NotifyFreeObj(rData, pObj);
5089     SdrObject::Free(pObj);
5090 }
5091 
5092 SdrObject* SvxMSDffManager::ProcessObj(SvStream& rSt,
5093                                        DffObjData& rObjData,
5094                                        SvxMSDffClientData& rData,
5095                                        tools::Rectangle& rTextRect,
5096                                        SdrObject* pObj
5097                                        )
5098 {
5099     if( !rTextRect.IsEmpty() )
5100     {
5101         SvxMSDffImportData& rImportData = static_cast<SvxMSDffImportData&>(rData);
5102         SvxMSDffImportRec* pImpRec = new SvxMSDffImportRec;
5103         bool bDeleteImpRec = true;
5104         SvxMSDffImportRec* pTextImpRec = pImpRec;
5105         bool bDeleteTextImpRec = false;
5106 
5107         // fill Import Record with data
5108         pImpRec->nShapeId   = rObjData.nShapeId;
5109         pImpRec->eShapeType = rObjData.eShapeType;
5110 
5111         MSO_WrapMode eWrapMode( static_cast<MSO_WrapMode>(GetPropertyValue(
5112                                                             DFF_Prop_WrapText,
5113                                                             mso_wrapSquare )) );
5114         rObjData.bClientAnchor = maShapeRecords.SeekToContent( rSt,
5115                                             DFF_msofbtClientAnchor,
5116                                             SEEK_FROM_CURRENT_AND_RESTART );
5117         if( rObjData.bClientAnchor )
5118             ProcessClientAnchor( rSt,
5119                     maShapeRecords.Current()->nRecLen,
5120                     pImpRec->pClientAnchorBuffer, pImpRec->nClientAnchorLen );
5121 
5122         rObjData.bClientData = maShapeRecords.SeekToContent( rSt,
5123                                             DFF_msofbtClientData,
5124                                             SEEK_FROM_CURRENT_AND_RESTART );
5125         if( rObjData.bClientData )
5126             ProcessClientData( rSt,
5127                     maShapeRecords.Current()->nRecLen,
5128                     pImpRec->pClientDataBuffer, pImpRec->nClientDataLen );
5129 
5130 
5131         // process user (== Winword) defined parameters in 0xF122 record
5132         if(    maShapeRecords.SeekToContent( rSt,
5133                                              DFF_msofbtUDefProp,
5134                                              SEEK_FROM_CURRENT_AND_RESTART )
5135             && maShapeRecords.Current()->nRecLen )
5136         {
5137             sal_uInt32  nBytesLeft = maShapeRecords.Current()->nRecLen;
5138             while( 5 < nBytesLeft )
5139             {
5140                 sal_uInt16 nPID(0);
5141                 rSt.ReadUInt16(nPID);
5142                 if (!rSt.good())
5143                     break;
5144                 sal_uInt32 nUDData(0);
5145                 rSt.ReadUInt32(nUDData);
5146                 switch (nPID)
5147                 {
5148                     case 0x038F: pImpRec->nXAlign = nUDData; break;
5149                     case 0x0390:
5150                         pImpRec->nXRelTo = nUDData;
5151                         break;
5152                     case 0x0391: pImpRec->nYAlign = nUDData; break;
5153                     case 0x0392:
5154                         pImpRec->nYRelTo = nUDData;
5155                         break;
5156                     case 0x03BF: pImpRec->nLayoutInTableCell = nUDData; break;
5157                     case 0x0393:
5158                     // This seems to correspond to o:hrpct from .docx (even including
5159                     // the difference that it's in 0.1% even though the .docx spec
5160                     // says it's in 1%).
5161                         pImpRec->relativeHorizontalWidth = nUDData;
5162                         break;
5163                     case 0x0394:
5164                     // And this is really just a guess, but a mere presence of this
5165                     // flag makes a horizontal rule be as wide as the page (unless
5166                     // overridden by something), so it probably matches o:hr from .docx.
5167                         pImpRec->isHorizontalRule = true;
5168                         break;
5169                 }
5170                 if (!rSt.good())
5171                     break;
5172                 nBytesLeft  -= 6;
5173             }
5174         }
5175 
5176         //  text frame, also Title or Outline
5177         SdrObject*  pOrgObj  = pObj;
5178         SdrRectObj* pTextObj = nullptr;
5179         sal_uInt32 nTextId = GetPropertyValue( DFF_Prop_lTxid, 0 );
5180         if( nTextId )
5181         {
5182             SfxItemSet aSet( pSdrModel->GetItemPool() );
5183 
5184             //Originally anything that as a mso_sptTextBox was created as a
5185             //textbox, this was changed for #88277# to be created as a simple
5186             //rect to keep impress happy. For the rest of us we'd like to turn
5187             //it back into a textbox again.
5188             bool bTextFrame = (pImpRec->eShapeType == mso_sptTextBox);
5189             if (!bTextFrame)
5190             {
5191                 //Either
5192                 //a) it's a simple text object or
5193                 //b) it's a rectangle with text and square wrapping.
5194                 bTextFrame =
5195                 (
5196                     (pImpRec->eShapeType == mso_sptTextSimple) ||
5197                     (
5198                         (pImpRec->eShapeType == mso_sptRectangle)
5199                         && (eWrapMode == mso_wrapSquare)
5200                         && ShapeHasText(pImpRec->nShapeId, rObjData.rSpHd.GetRecBegFilePos() )
5201                     )
5202                 );
5203             }
5204 
5205             if (bTextFrame)
5206             {
5207                 SdrObject::Free( pObj );
5208                 pObj = pOrgObj = nullptr;
5209             }
5210 
5211             // Distance of Textbox to its surrounding Customshape
5212             sal_Int32 nTextLeft = GetPropertyValue( DFF_Prop_dxTextLeft, 91440L);
5213             sal_Int32 nTextRight = GetPropertyValue( DFF_Prop_dxTextRight, 91440L );
5214             sal_Int32 nTextTop = GetPropertyValue( DFF_Prop_dyTextTop, 45720L  );
5215             sal_Int32 nTextBottom = GetPropertyValue( DFF_Prop_dyTextBottom, 45720L );
5216 
5217             ScaleEmu( nTextLeft );
5218             ScaleEmu( nTextRight );
5219             ScaleEmu( nTextTop );
5220             ScaleEmu( nTextBottom );
5221 
5222             sal_Int32 nTextRotationAngle=0;
5223             bool bVerticalText = false;
5224             if ( IsProperty( DFF_Prop_txflTextFlow ) )
5225             {
5226                 MSO_TextFlow eTextFlow = static_cast<MSO_TextFlow>(GetPropertyValue(
5227                     DFF_Prop_txflTextFlow, 0) & 0xFFFF);
5228                 switch( eTextFlow )
5229                 {
5230                     case mso_txflBtoT:
5231                         nTextRotationAngle = 9000;
5232                     break;
5233                     case mso_txflVertN:
5234                     case mso_txflTtoBN:
5235                         nTextRotationAngle = 27000;
5236                         break;
5237                     case mso_txflTtoBA:
5238                         bVerticalText = true;
5239                     break;
5240                     case mso_txflHorzA:
5241                         bVerticalText = true;
5242                         nTextRotationAngle = 9000;
5243                     break;
5244                     case mso_txflHorzN:
5245                     default :
5246                         break;
5247                 }
5248             }
5249 
5250             if (nTextRotationAngle)
5251             {
5252                 switch (nTextRotationAngle)
5253                 {
5254                     case 9000:
5255                         {
5256                             long nWidth = rTextRect.GetWidth();
5257                             rTextRect.SetRight( rTextRect.Left() + rTextRect.GetHeight() );
5258                             rTextRect.SetBottom( rTextRect.Top() + nWidth );
5259 
5260                             sal_Int32 nOldTextLeft = nTextLeft;
5261                             sal_Int32 nOldTextRight = nTextRight;
5262                             sal_Int32 nOldTextTop = nTextTop;
5263                             sal_Int32 nOldTextBottom = nTextBottom;
5264 
5265                             nTextLeft = nOldTextBottom;
5266                             nTextRight = nOldTextTop;
5267                             nTextTop = nOldTextLeft;
5268                             nTextBottom = nOldTextRight;
5269                         }
5270                         break;
5271                     case 27000:
5272                         {
5273                             long nWidth = rTextRect.GetWidth();
5274                             rTextRect.SetRight( rTextRect.Left() + rTextRect.GetHeight() );
5275                             rTextRect.SetBottom( rTextRect.Top() + nWidth );
5276 
5277                             sal_Int32 nOldTextLeft = nTextLeft;
5278                             sal_Int32 nOldTextRight = nTextRight;
5279                             sal_Int32 nOldTextTop = nTextTop;
5280                             sal_Int32 nOldTextBottom = nTextBottom;
5281 
5282                             nTextLeft = nOldTextTop;
5283                             nTextRight = nOldTextBottom;
5284                             nTextTop = nOldTextRight;
5285                             nTextBottom = nOldTextLeft;
5286                         }
5287                         break;
5288                 }
5289             }
5290 
5291             pTextObj = new SdrRectObj(
5292                 *pSdrModel,
5293                 OBJ_TEXT,
5294                 rTextRect);
5295             pTextImpRec = new SvxMSDffImportRec(*pImpRec);
5296             bDeleteTextImpRec = true;
5297 
5298             // the vertical paragraph indents are part of the BoundRect,
5299             // here we 'remove' them by calculating
5300             tools::Rectangle aNewRect(rTextRect);
5301             aNewRect.AdjustBottom( -(nTextTop + nTextBottom) );
5302             aNewRect.AdjustRight( -(nTextLeft + nTextRight) );
5303 
5304             // Only if it's a simple textbox may Writer replace
5305             // the object with a frame, otherwise
5306             if( bTextFrame )
5307             {
5308                 std::shared_ptr<SvxMSDffShapeInfo> const pTmpRec(
5309                     new SvxMSDffShapeInfo(0, pImpRec->nShapeId));
5310 
5311                 SvxMSDffShapeInfos_ById::const_iterator const it =
5312                     m_xShapeInfosById->find(pTmpRec);
5313                 if (it != m_xShapeInfosById->end())
5314                 {
5315                     SvxMSDffShapeInfo& rInfo = **it;
5316                     pTextImpRec->bReplaceByFly   = rInfo.bReplaceByFly;
5317                 }
5318             }
5319 
5320             if( !pObj )
5321                 ApplyAttributes( rSt, aSet, rObjData );
5322 
5323             bool bFitText = false;
5324             if (GetPropertyValue(DFF_Prop_FitTextToShape, 0) & 2)
5325             {
5326                 aSet.Put( makeSdrTextAutoGrowHeightItem( true ) );
5327                 aSet.Put( makeSdrTextMinFrameHeightItem(
5328                     aNewRect.Bottom() - aNewRect.Top() ) );
5329                 aSet.Put( makeSdrTextMinFrameWidthItem(
5330                     aNewRect.Right() - aNewRect.Left() ) );
5331                 bFitText = true;
5332             }
5333             else
5334             {
5335                 aSet.Put( makeSdrTextAutoGrowHeightItem( false ) );
5336                 aSet.Put( makeSdrTextAutoGrowWidthItem( false ) );
5337             }
5338 
5339             switch ( static_cast<MSO_WrapMode>(GetPropertyValue( DFF_Prop_WrapText, mso_wrapSquare )) )
5340             {
5341                 case mso_wrapNone :
5342                     aSet.Put( makeSdrTextAutoGrowWidthItem( true ) );
5343                     if (bFitText)
5344                     {
5345                         //can't do autowidth in flys #i107184#
5346                         pTextImpRec->bReplaceByFly = false;
5347                     }
5348                 break;
5349                 case mso_wrapByPoints :
5350                     aSet.Put( makeSdrTextContourFrameItem( true ) );
5351                 break;
5352                 default: break;
5353             }
5354 
5355             // set margins at the border of the textbox
5356             aSet.Put( makeSdrTextLeftDistItem( nTextLeft ) );
5357             aSet.Put( makeSdrTextRightDistItem( nTextRight ) );
5358             aSet.Put( makeSdrTextUpperDistItem( nTextTop ) );
5359             aSet.Put( makeSdrTextLowerDistItem( nTextBottom ) );
5360             pTextImpRec->nDxTextLeft    = nTextLeft;
5361             pTextImpRec->nDyTextTop     = nTextTop;
5362             pTextImpRec->nDxTextRight   = nTextRight;
5363             pTextImpRec->nDyTextBottom  = nTextBottom;
5364 
5365             // read text anchor
5366             if ( IsProperty( DFF_Prop_anchorText ) )
5367             {
5368                 MSO_Anchor eTextAnchor =
5369                     static_cast<MSO_Anchor>(GetPropertyValue( DFF_Prop_anchorText, 0 ));
5370 
5371                 SdrTextVertAdjust eTVA = SDRTEXTVERTADJUST_CENTER;
5372                 bool bTVASet(false);
5373                 bool bTHASet(false);
5374 
5375                 switch( eTextAnchor )
5376                 {
5377                     case mso_anchorTop:
5378                     {
5379                         eTVA = SDRTEXTVERTADJUST_TOP;
5380                         bTVASet = true;
5381                     }
5382                     break;
5383                     case mso_anchorTopCentered:
5384                     {
5385                         eTVA = SDRTEXTVERTADJUST_TOP;
5386                         bTVASet = true;
5387                         bTHASet = true;
5388                     }
5389                     break;
5390 
5391                     case mso_anchorMiddle:
5392                         bTVASet = true;
5393                     break;
5394                     case mso_anchorMiddleCentered:
5395                     {
5396                         bTVASet = true;
5397                         bTHASet = true;
5398                     }
5399                     break;
5400                     case mso_anchorBottom:
5401                     {
5402                         eTVA = SDRTEXTVERTADJUST_BOTTOM;
5403                         bTVASet = true;
5404                     }
5405                     break;
5406                     case mso_anchorBottomCentered:
5407                     {
5408                         eTVA = SDRTEXTVERTADJUST_BOTTOM;
5409                         bTVASet = true;
5410                         bTHASet = true;
5411                     }
5412                     break;
5413                     default : break;
5414                 }
5415                 // insert
5416                 if ( bTVASet )
5417                     aSet.Put( SdrTextVertAdjustItem( eTVA ) );
5418                 if ( bTHASet )
5419                     aSet.Put( SdrTextHorzAdjustItem( SDRTEXTHORZADJUST_CENTER ) );
5420             }
5421 
5422             pTextObj->SetMergedItemSet(aSet);
5423 
5424             if (bVerticalText)
5425                 pTextObj->SetVerticalWriting(true);
5426 
5427             if (nTextRotationAngle)
5428             {
5429                 long nMinWH = rTextRect.GetWidth() < rTextRect.GetHeight() ?
5430                     rTextRect.GetWidth() : rTextRect.GetHeight();
5431                 nMinWH /= 2;
5432                 Point aPivot(rTextRect.TopLeft());
5433                 aPivot.AdjustX(nMinWH );
5434                 aPivot.AdjustY(nMinWH );
5435                 double a = nTextRotationAngle * nPi180;
5436                 pTextObj->NbcRotate(aPivot, nTextRotationAngle, sin(a), cos(a));
5437             }
5438 
5439             // rotate text with shape?
5440             if ( mnFix16Angle )
5441             {
5442                 double a = mnFix16Angle * nPi180;
5443                 pTextObj->NbcRotate( rObjData.aBoundRect.Center(), mnFix16Angle,
5444                     sin( a ), cos( a ) );
5445             }
5446 
5447             if( !pObj )
5448             {
5449                 pObj = pTextObj;
5450             }
5451             else
5452             {
5453                 if( pTextObj != pObj )
5454                 {
5455                     SdrObject* pGroup = new SdrObjGroup(*pSdrModel);
5456                     pGroup->GetSubList()->NbcInsertObject( pObj );
5457                     pGroup->GetSubList()->NbcInsertObject( pTextObj );
5458                     if (pOrgObj == pObj)
5459                         pOrgObj = pGroup;
5460                     else
5461                         pOrgObj = pObj;
5462                     pObj = pGroup;
5463                 }
5464             }
5465         }
5466         else if( !pObj )
5467         {
5468             // simple rectangular objects are ignored by ImportObj()  :-(
5469             // this is OK for Draw but not for Calc and Writer
5470             // cause here these objects have a default border
5471             pObj = new SdrRectObj(
5472                 *pSdrModel,
5473                 rTextRect);
5474 
5475             pOrgObj = pObj;
5476             SfxItemSet aSet( pSdrModel->GetItemPool() );
5477             ApplyAttributes( rSt, aSet, rObjData );
5478 
5479             const SfxPoolItem* pPoolItem=nullptr;
5480             SfxItemState eState = aSet.GetItemState( XATTR_FILLCOLOR,
5481                                                      false, &pPoolItem );
5482             if( SfxItemState::DEFAULT == eState )
5483                 aSet.Put( XFillColorItem( OUString(), mnDefaultColor ) );
5484             pObj->SetMergedItemSet(aSet);
5485         }
5486 
5487         //Means that fBehindDocument is set
5488         if (GetPropertyValue(DFF_Prop_fPrint, 0) & 0x20)
5489             pImpRec->bDrawHell = true;
5490         else
5491             pImpRec->bDrawHell = false;
5492         if (GetPropertyValue(DFF_Prop_fPrint, 0) & 0x02)
5493             pImpRec->bHidden = true;
5494         pTextImpRec->bDrawHell  = pImpRec->bDrawHell;
5495         pTextImpRec->bHidden = pImpRec->bHidden;
5496         pImpRec->nNextShapeId   = GetPropertyValue( DFF_Prop_hspNext, 0 );
5497         pTextImpRec->nNextShapeId=pImpRec->nNextShapeId;
5498 
5499         if ( nTextId )
5500         {
5501             pTextImpRec->aTextId.nTxBxS = static_cast<sal_uInt16>( nTextId >> 16 );
5502             pTextImpRec->aTextId.nSequence = static_cast<sal_uInt16>(nTextId);
5503         }
5504 
5505         pTextImpRec->nDxWrapDistLeft = GetPropertyValue(
5506                                     DFF_Prop_dxWrapDistLeft, 114935L ) / 635L;
5507         pTextImpRec->nDyWrapDistTop = GetPropertyValue(
5508                                     DFF_Prop_dyWrapDistTop, 0 ) / 635L;
5509         pTextImpRec->nDxWrapDistRight = GetPropertyValue(
5510                                     DFF_Prop_dxWrapDistRight, 114935L ) / 635L;
5511         pTextImpRec->nDyWrapDistBottom = GetPropertyValue(
5512                                     DFF_Prop_dyWrapDistBottom, 0 ) / 635L;
5513         // 16.16 fraction times total image width or height, as appropriate.
5514 
5515         if (SeekToContent(DFF_Prop_pWrapPolygonVertices, rSt))
5516         {
5517             pTextImpRec->pWrapPolygon.reset();
5518             sal_uInt16 nNumElemVert(0), nNumElemMemVert(0), nElemSizeVert(8);
5519             rSt.ReadUInt16( nNumElemVert ).ReadUInt16( nNumElemMemVert ).ReadUInt16( nElemSizeVert );
5520             // If this value is 0xFFF0 then this record is an array of truncated 8 byte elements. Only the 4
5521             // low-order bytes are recorded
5522             if (nElemSizeVert == 0xFFF0)
5523                 nElemSizeVert = 4;
5524 
5525             // sanity check that the stream is long enough to fulfill nNumElemVert * nElemSizeVert;
5526             bool bOk = nElemSizeVert && (rSt.remainingSize() / nElemSizeVert >= nNumElemVert);
5527             if (bOk)
5528             {
5529                 pTextImpRec->pWrapPolygon.reset(new tools::Polygon(nNumElemVert));
5530                 for (sal_uInt16 i = 0; i < nNumElemVert; ++i)
5531                 {
5532                     sal_Int32 nX(0), nY(0);
5533                     if (nElemSizeVert == 8)
5534                         rSt.ReadInt32( nX ).ReadInt32( nY );
5535                     else
5536                     {
5537                         sal_Int16 nSmallX(0), nSmallY(0);
5538                         rSt.ReadInt16( nSmallX ).ReadInt16( nSmallY );
5539                         nX = nSmallX;
5540                         nY = nSmallY;
5541                     }
5542                     (*(pTextImpRec->pWrapPolygon))[i].setX( nX );
5543                     (*(pTextImpRec->pWrapPolygon))[i].setY( nY );
5544                 }
5545             }
5546         }
5547 
5548         pImpRec->nCropFromTop = GetPropertyValue(
5549                                     DFF_Prop_cropFromTop, 0 );
5550         pImpRec->nCropFromBottom = GetPropertyValue(
5551                                     DFF_Prop_cropFromBottom, 0 );
5552         pImpRec->nCropFromLeft = GetPropertyValue(
5553                                     DFF_Prop_cropFromLeft, 0 );
5554         pImpRec->nCropFromRight = GetPropertyValue(
5555                                     DFF_Prop_cropFromRight, 0 );
5556 
5557         pImpRec->bVFlip = bool(rObjData.nSpFlags & ShapeFlag::FlipV);
5558         pImpRec->bHFlip = bool(rObjData.nSpFlags & ShapeFlag::FlipH);
5559 
5560         sal_uInt32 nLineFlags = GetPropertyValue( DFF_Prop_fNoLineDrawDash, 0 );
5561         pImpRec->eLineStyle = (nLineFlags & 8)
5562                             ? static_cast<MSO_LineStyle>(GetPropertyValue(
5563                                                 DFF_Prop_lineStyle,
5564                                                 mso_lineSimple ))
5565                             : MSO_LineStyle_NONE;
5566         pTextImpRec->eLineStyle = pImpRec->eLineStyle;
5567 
5568         pImpRec->eLineDashing = static_cast<MSO_LineDashing>(GetPropertyValue(
5569                 DFF_Prop_lineDashing, mso_lineSolid ));
5570         pTextImpRec->eLineDashing = pImpRec->eLineDashing;
5571 
5572         if( pImpRec->nShapeId )
5573         {
5574             // amend the import record list
5575             if( pOrgObj )
5576             {
5577                 pImpRec->pObj = pOrgObj;
5578                 rImportData.insert(std::unique_ptr<SvxMSDffImportRec>(pImpRec));
5579                 bDeleteImpRec = false;
5580                 if (pImpRec == pTextImpRec)
5581                     bDeleteTextImpRec = false;
5582             }
5583 
5584             if( pTextObj && (pOrgObj != pTextObj) )
5585             {
5586                 // Modify ShapeId (must be unique)
5587                 pImpRec->nShapeId |= 0x8000000;
5588                 pTextImpRec->pObj = pTextObj;
5589                 rImportData.insert(std::unique_ptr<SvxMSDffImportRec>(pTextImpRec));
5590                 bDeleteTextImpRec = false;
5591                 if (pTextImpRec == pImpRec)
5592                     bDeleteImpRec = false;
5593             }
5594 
5595             // entry in the z-order-list in order to complement the pointer to this object
5596             /*Only store objects which are not deep inside the tree*/
5597             if( ( rObjData.nCalledByGroup == 0 )
5598                 ||
5599                 ( (rObjData.nSpFlags & ShapeFlag::Group)
5600                  && (rObjData.nCalledByGroup < 2) )
5601               )
5602                 StoreShapeOrder( pImpRec->nShapeId,
5603                                 ( static_cast<sal_uLong>(pImpRec->aTextId.nTxBxS) << 16 )
5604                                     + pImpRec->aTextId.nSequence, pObj );
5605         }
5606 
5607         if (bDeleteImpRec)
5608             delete pImpRec;
5609 
5610         if (bDeleteTextImpRec)
5611             delete pTextImpRec;
5612     }
5613 
5614     return pObj;
5615 };
5616 
5617 SdrObject* SvxMSDffManager::FinalizeObj(DffObjData& /* rObjData */, SdrObject* pObj)
5618 {
5619     return pObj;
5620 }
5621 
5622 
5623 void SvxMSDffManager::StoreShapeOrder(sal_uLong         nId,
5624                                       sal_uLong         nTxBx,
5625                                       SdrObject*    pObject,
5626                                       SwFlyFrameFormat*  pFly) const
5627 {
5628     for (const auto& pOrder : m_aShapeOrders)
5629     {
5630         if (pOrder->nShapeId == nId)
5631         {
5632             pOrder->nTxBxComp = nTxBx;
5633             pOrder->pObj = pObject;
5634             pOrder->pFly = pFly;
5635         }
5636     }
5637 }
5638 
5639 
5640 void SvxMSDffManager::ExchangeInShapeOrder( SdrObject const * pOldObject,
5641                                             sal_uLong    nTxBx,
5642                                             SdrObject*   pObject) const
5643 {
5644     for (const auto& pOrder : m_aShapeOrders)
5645     {
5646         if (pOrder->pObj == pOldObject)
5647         {
5648             pOrder->pFly = nullptr;
5649             pOrder->pObj = pObject;
5650             pOrder->nTxBxComp = nTxBx;
5651         }
5652     }
5653 }
5654 
5655 
5656 void SvxMSDffManager::RemoveFromShapeOrder( SdrObject const * pObject ) const
5657 {
5658     for (const auto& pOrder : m_aShapeOrders)
5659     {
5660         if (pOrder->pObj == pObject)
5661         {
5662             pOrder->pObj = nullptr;
5663             pOrder->pFly = nullptr;
5664             pOrder->nTxBxComp = 0;
5665         }
5666     }
5667 }
5668 
5669 
5670 //  exported class: Public Methods
5671 
5672 SvxMSDffManager::SvxMSDffManager(SvStream& rStCtrl_,
5673                                  const OUString& rBaseURL,
5674                                  sal_uInt32 nOffsDgg_,
5675                                  SvStream* pStData_,
5676                                  SdrModel* pSdrModel_,// see SetModel() below
5677                                  long      nApplicationScale,
5678                                  Color     mnDefaultColor_,
5679                                  SvStream* pStData2_,
5680                                  bool bSkipImages )
5681     :DffPropertyReader( *this ),
5682      m_pBLIPInfos( new SvxMSDffBLIPInfos ),
5683      m_xShapeInfosByTxBxComp( new SvxMSDffShapeInfos_ByTxBxComp ),
5684      nOffsDgg( nOffsDgg_ ),
5685      nBLIPCount(  USHRT_MAX ),              // initialize with error, since we first check if the
5686      nGroupShapeFlags(ShapeFlag::NONE),     // ensure initialization here, as some corrupted
5687                                             // files may yield to this being uninitialized
5688      maBaseURL( rBaseURL ),
5689      mnIdClusters(0),
5690      rStCtrl(  rStCtrl_  ),
5691      pStData(  pStData_  ),
5692      pStData2( pStData2_ ),
5693      nSvxMSDffSettings( 0 ),
5694      nSvxMSDffOLEConvFlags( 0 ),
5695      mnDefaultColor( mnDefaultColor_),
5696      mbSkipImages (bSkipImages)
5697 {
5698     SetModel( pSdrModel_, nApplicationScale );
5699 
5700     // remember FilePos of the stream(s)
5701     sal_uLong nOldPosCtrl = rStCtrl.Tell();
5702     sal_uLong nOldPosData = pStData ? pStData->Tell() : nOldPosCtrl;
5703 
5704     // if no data stream is given we assume that the BLIPs
5705     // are in the control stream
5706     if( !pStData )
5707         pStData = &rStCtrl;
5708 
5709     SetDefaultPropSet( rStCtrl, nOffsDgg );
5710 
5711     // read control stream, if successful set nBLIPCount
5712     GetCtrlData( nOffsDgg );
5713 
5714     // check Text-Box-Story-Chain-Infos
5715     CheckTxBxStoryChain();
5716 
5717     // restore old FilePos of the stream(s)
5718     rStCtrl.Seek( nOldPosCtrl );
5719     if( &rStCtrl != pStData )
5720         pStData->Seek( nOldPosData );
5721 }
5722 
5723 SvxMSDffManager::SvxMSDffManager( SvStream& rStCtrl_, const OUString& rBaseURL )
5724     :DffPropertyReader( *this ),
5725      m_pBLIPInfos( new SvxMSDffBLIPInfos ),
5726      m_xShapeInfosByTxBxComp( new SvxMSDffShapeInfos_ByTxBxComp ),
5727      nOffsDgg( 0 ),
5728      nBLIPCount(  USHRT_MAX ),              // initialize with error, since we first have to check
5729      nGroupShapeFlags(ShapeFlag::NONE),
5730      maBaseURL( rBaseURL ),
5731      mnIdClusters(0),
5732      rStCtrl(  rStCtrl_  ),
5733      pStData( nullptr ),
5734      pStData2( nullptr ),
5735      nSvxMSDffSettings( 0 ),
5736      nSvxMSDffOLEConvFlags( 0 ),
5737      mnDefaultColor( COL_DEFAULT ),
5738      mbSkipImages(false)
5739 {
5740     SetModel( nullptr, 0 );
5741 }
5742 
5743 SvxMSDffManager::~SvxMSDffManager()
5744 {
5745 }
5746 
5747 void SvxMSDffManager::InitSvxMSDffManager( sal_uInt32 nOffsDgg_, SvStream* pStData_, sal_uInt32 nOleConvFlags )
5748 {
5749     nOffsDgg = nOffsDgg_;
5750     pStData = pStData_;
5751     nSvxMSDffOLEConvFlags = nOleConvFlags;
5752 
5753     // remember FilePos of the stream(s)
5754     sal_uLong nOldPosCtrl = rStCtrl.Tell();
5755 
5756     SetDefaultPropSet( rStCtrl, nOffsDgg );
5757 
5758     // insert fidcl cluster table
5759     GetFidclData( nOffsDgg );
5760 
5761     // read control stream, if successful, set nBLIPCount
5762     GetCtrlData( nOffsDgg );
5763 
5764     // check Text-Box-Story-Chain-Infos
5765     CheckTxBxStoryChain();
5766 
5767     // restore old FilePos of the stream(s)
5768     rStCtrl.Seek( nOldPosCtrl );
5769 }
5770 
5771 void SvxMSDffManager::SetDgContainer( SvStream& rSt )
5772 {
5773     sal_uInt32 nFilePos = rSt.Tell();
5774     DffRecordHeader aDgContHd;
5775     bool bOk = ReadDffRecordHeader(rSt, aDgContHd);
5776     // insert this container only if there is also a DggAtom
5777     if (bOk && SeekToRec(rSt, DFF_msofbtDg, aDgContHd.GetRecEndFilePos()))
5778     {
5779         DffRecordHeader aRecHd;
5780         if (ReadDffRecordHeader(rSt, aRecHd))
5781         {
5782             sal_uInt32 nDrawingId = aRecHd.nRecInstance;
5783             maDgOffsetTable[nDrawingId] = nFilePos;
5784         }
5785     }
5786     rSt.Seek(nFilePos);
5787 }
5788 
5789 void SvxMSDffManager::GetFidclData( sal_uInt32 nOffsDggL )
5790 {
5791     if (!nOffsDggL)
5792         return;
5793 
5794     sal_uInt32 nDummy, nMerk = rStCtrl.Tell();
5795 
5796     if (nOffsDggL == rStCtrl.Seek(nOffsDggL))
5797     {
5798         DffRecordHeader aRecHd;
5799         bool bOk = ReadDffRecordHeader(rStCtrl, aRecHd);
5800 
5801         DffRecordHeader aDggAtomHd;
5802         if (bOk && SeekToRec(rStCtrl, DFF_msofbtDgg, aRecHd.GetRecEndFilePos(), &aDggAtomHd))
5803         {
5804             aDggAtomHd.SeekToContent( rStCtrl );
5805             sal_uInt32 nCurMaxShapeId;
5806             rStCtrl.ReadUInt32( nCurMaxShapeId )
5807                    .ReadUInt32( mnIdClusters )
5808                    .ReadUInt32( nDummy )
5809                    .ReadUInt32( nDummy ); // nDrawingsSaved
5810 
5811             if ( mnIdClusters-- > 2 )
5812             {
5813                 const std::size_t nFIDCLsize = sizeof(sal_uInt32) * 2;
5814                 if ( aDggAtomHd.nRecLen == ( mnIdClusters * nFIDCLsize + 16 ) )
5815                 {
5816                     std::size_t nMaxEntriesPossible = rStCtrl.remainingSize() / nFIDCLsize;
5817                     SAL_WARN_IF(nMaxEntriesPossible < mnIdClusters,
5818                         "filter.ms", "FIDCL list longer than remaining bytes, ppt or parser is wrong");
5819                     mnIdClusters = std::min(nMaxEntriesPossible, static_cast<std::size_t>(mnIdClusters));
5820 
5821                     maFidcls.resize(mnIdClusters);
5822                     for (sal_uInt32 i = 0; i < mnIdClusters; ++i)
5823                     {
5824                         sal_uInt32  cspidCur;   ///< number of SPIDs used so far
5825                         rStCtrl.ReadUInt32( maFidcls[ i ].dgid )
5826                                .ReadUInt32( cspidCur );
5827                     }
5828                 }
5829             }
5830         }
5831     }
5832     rStCtrl.Seek( nMerk );
5833 }
5834 
5835 void SvxMSDffManager::CheckTxBxStoryChain()
5836 {
5837     m_xShapeInfosById.reset(new SvxMSDffShapeInfos_ById);
5838     // mangle old Info array, sorted by nTxBxComp
5839     sal_uLong nChain    = ULONG_MAX;
5840     bool bSetReplaceFALSE = false;
5841     for (SvxMSDffShapeInfos_ByTxBxComp::iterator iter =
5842                 m_xShapeInfosByTxBxComp->begin(),
5843             mark = m_xShapeInfosByTxBxComp->begin();
5844          iter != m_xShapeInfosByTxBxComp->end(); ++iter)
5845     {
5846         std::shared_ptr<SvxMSDffShapeInfo> const pObj = *iter;
5847         if( pObj->nTxBxComp )
5848         {
5849             // group change?
5850             // the text id also contains an internal drawing container id
5851             // to distinguish between text id of drawing objects in different
5852             // drawing containers.
5853             if( nChain != pObj->nTxBxComp )
5854             {
5855                 // reset mark and helper flag
5856                 mark = iter;
5857                 nChain = pObj->nTxBxComp;
5858                 bSetReplaceFALSE = !pObj->bReplaceByFly;
5859             }
5860             else if( !pObj->bReplaceByFly )
5861             {
5862                 // object that must NOT be replaced by frame?
5863                 bSetReplaceFALSE = true;
5864                 // maybe reset flags in start of group
5865                 for (SvxMSDffShapeInfos_ByTxBxComp::iterator itemp = mark;
5866                         itemp != iter; ++itemp)
5867                 {
5868                     (*itemp)->bReplaceByFly = false;
5869                 }
5870             }
5871 
5872             if( bSetReplaceFALSE )
5873             {
5874                 pObj->bReplaceByFly = false;
5875             }
5876         }
5877         // copy all Shape Info objects to m_xShapeInfosById, sorted by nShapeId
5878         pObj->nTxBxComp = pObj->nTxBxComp & 0xFFFF0000;
5879         m_xShapeInfosById->insert( pObj );
5880     }
5881     // free original array but don't free its elements
5882     m_xShapeInfosByTxBxComp.reset();
5883 }
5884 
5885 
5886 /*****************************************************************************
5887 
5888     Reading the Shape-Infos in the Ctor:
5889     ---------------------------------
5890     remembering the Shape-Ids and the associated Blip-Numbers and TextBox-Infos
5891                     =========                    ============     =============
5892     and remembering the File-Offsets for each Blip
5893                        ============
5894 ******************************************************************************/
5895 void SvxMSDffManager::GetCtrlData(sal_uInt32 nOffsDggL)
5896 {
5897     // position control stream
5898     if (!checkSeek(rStCtrl, nOffsDggL))
5899         return;
5900 
5901     sal_uInt8   nVer;
5902     sal_uInt16 nInst;
5903     sal_uInt16 nFbt;
5904     sal_uInt32  nLength;
5905     if( !ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength ) ) return;
5906 
5907     sal_uLong nPos = nOffsDggL + DFF_COMMON_RECORD_HEADER_SIZE;
5908 
5909     // case A: first Drawing Group Container, then n times Drawing Container
5910     if( DFF_msofbtDggContainer == nFbt )
5911     {
5912         bool bOk;
5913         GetDrawingGroupContainerData( rStCtrl, nLength );
5914 
5915         sal_uInt32 nMaxStrPos = rStCtrl.TellEnd();
5916 
5917         nPos += nLength;
5918         sal_uInt16 nDrawingContainerId = 1;
5919         do
5920         {
5921             if (!checkSeek(rStCtrl, nPos))
5922                 break;
5923 
5924             bOk = ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength ) && ( DFF_msofbtDgContainer == nFbt );
5925 
5926             if( !bOk )
5927             {
5928                 nPos++;                // ????????? TODO: trying to get an one-hit wonder, this code should be rewritten...
5929                 if (nPos != rStCtrl.Seek(nPos))
5930                     break;
5931                 bOk = ReadCommonRecordHeader( rStCtrl, nVer, nInst, nFbt, nLength )
5932                         && ( DFF_msofbtDgContainer == nFbt );
5933             }
5934             if( bOk )
5935             {
5936                 GetDrawingContainerData( rStCtrl, nLength, nDrawingContainerId );
5937             }
5938             nPos += DFF_COMMON_RECORD_HEADER_SIZE + nLength;
5939             ++nDrawingContainerId;
5940         }
5941         while( ( rStCtrl.GetError() == ERRCODE_NONE ) && ( nPos < nMaxStrPos ) && bOk );
5942     }
5943 }
5944 
5945 
5946 // from here on: Drawing Group Container  i.e. document-wide valid data
5947 
5948 void SvxMSDffManager::GetDrawingGroupContainerData( SvStream& rSt, sal_uLong nLenDgg )
5949 {
5950     sal_uInt8   nVer;
5951     sal_uInt16 nInst;
5952     sal_uInt16 nFbt;
5953     sal_uInt32 nLength;
5954 
5955     sal_uLong nLenBStoreCont = 0, nLenFBSE = 0, nRead = 0;
5956 
5957     // search for a  BStore Container
5958     bool bOk = true;
5959     do
5960     {
5961         if (!ReadCommonRecordHeader(rSt, nVer, nInst, nFbt, nLength))
5962             return;
5963         nRead += DFF_COMMON_RECORD_HEADER_SIZE + nLength;
5964         if (DFF_msofbtBstoreContainer == nFbt)
5965         {
5966             nLenBStoreCont = nLength;
5967             break;
5968         }
5969         bOk = checkSeek(rSt, rSt.Tell() + nLength);
5970     }
5971     while (bOk && nRead < nLenDgg);
5972 
5973     if (!bOk || !nLenBStoreCont)
5974         return;
5975 
5976     // Read all atoms of the containers from the BStore container and store all
5977     // relevant data of all contained FBSEs in out pointer array.
5978     // We also count all found FBSEs in member nBLIPCount.
5979 
5980     const sal_uLong nSkipBLIPLen = 20;  // skip to get to the nBLIPLen
5981     const sal_uLong nSkipBLIPPos =  4;  // thereafter skip up to nBLIPPos
5982 
5983     sal_uInt32 nBLIPLen = 0, nBLIPPos = 0;
5984 
5985     nRead = 0;
5986     do
5987     {
5988         if(!ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength)) return;
5989         nRead += DFF_COMMON_RECORD_HEADER_SIZE + nLength;
5990         if( DFF_msofbtBSE == nFbt && /* magic value from spec */ 0x2 == nVer )
5991         {
5992             nLenFBSE = nLength;
5993             // is FBSE big enough for our data
5994             bOk = ( nSkipBLIPLen + 4 + nSkipBLIPPos + 4 <= nLenFBSE );
5995 
5996             if (bOk)
5997             {
5998                 rSt.SeekRel( nSkipBLIPLen );
5999                 rSt.ReadUInt32( nBLIPLen );
6000                 rSt.SeekRel( nSkipBLIPPos );
6001                 rSt.ReadUInt32( nBLIPPos );
6002                 bOk = rSt.GetError() == ERRCODE_NONE;
6003 
6004                 nLength -= nSkipBLIPLen+ 4 + nSkipBLIPPos + 4;
6005             }
6006 
6007             if (bOk)
6008             {
6009                 // specialty:
6010                 // If nBLIPLen is less than nLenFBSE AND nBLIPPos is NULL,
6011                 // then we assume, that the image is in FBSE!
6012                 if( (!nBLIPPos) && (nBLIPLen < nLenFBSE) )
6013                     nBLIPPos = rSt.Tell() + 4;
6014 
6015                 if( USHRT_MAX == nBLIPCount )
6016                     nBLIPCount = 1;
6017                 else
6018                     nBLIPCount++;
6019 
6020                 // now save the info for later access
6021                 m_pBLIPInfos->push_back(SvxMSDffBLIPInfo(nBLIPPos));
6022             }
6023             if (!checkSeek(rSt, rSt.Tell() + nLength))
6024                 return; // invalid offset
6025         }
6026         else return; // invalid input
6027     }
6028     while( nRead < nLenBStoreCont );
6029 }
6030 
6031 
6032 // from now on: Drawing Container  which means Pages (Sheet, Slide) - wide valid data
6033 //                      =================               ======
6034 
6035 void SvxMSDffManager::GetDrawingContainerData( SvStream& rSt, sal_uLong nLenDg,
6036                                                sal_uInt16 nDrawingContainerId )
6037 {
6038     sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength;
6039 
6040     sal_uLong nReadDg = 0;
6041 
6042     // We are now in a drawing container (one per each page) and
6043     // we now have to iterate through all contained shape group containers
6044     do
6045     {
6046         if (!ReadCommonRecordHeader(rSt, nVer, nInst, nFbt, nLength))
6047             return;
6048         nReadDg += DFF_COMMON_RECORD_HEADER_SIZE;
6049         // Patriarch found (the upmost shape group container) ?
6050         if (DFF_msofbtSpgrContainer == nFbt)
6051         {
6052             if (!GetShapeGroupContainerData(rSt, nLength, true, nDrawingContainerId))
6053                 return;
6054         }
6055         // empty Shape Container ? (outside of shape group container)
6056         else if (DFF_msofbtSpContainer == nFbt)
6057         {
6058             if (!GetShapeContainerData(rSt, nLength, ULONG_MAX, nDrawingContainerId))
6059                 return;
6060         }
6061         else
6062         {
6063             if (!checkSeek(rSt, rSt.Tell() + nLength))
6064                 return;
6065         }
6066         nReadDg += nLength;
6067     }
6068     while( nReadDg < nLenDg );
6069 }
6070 
6071 bool SvxMSDffManager::GetShapeGroupContainerData( SvStream& rSt,
6072                                                   sal_uLong nLenShapeGroupCont,
6073                                                   bool bPatriarch,
6074                                                   sal_uInt16 nDrawingContainerId )
6075 {
6076     sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength;
6077     long nStartShapeGroupCont = rSt.Tell();
6078     // We are now in a shape group container (conditionally multiple per page)
6079     // and we now have to iterate through all contained shape containers
6080     bool  bFirst = !bPatriarch;
6081     sal_uLong nReadSpGrCont = 0;
6082     do
6083     {
6084         if( !ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength ) )
6085             return false;
6086         nReadSpGrCont += DFF_COMMON_RECORD_HEADER_SIZE;
6087         // Shape Container?
6088         if( DFF_msofbtSpContainer == nFbt )
6089         {
6090             sal_uLong nGroupOffs = bFirst ? nStartShapeGroupCont - DFF_COMMON_RECORD_HEADER_SIZE : ULONG_MAX;
6091             if ( !GetShapeContainerData( rSt, nLength, nGroupOffs, nDrawingContainerId ) )
6092                 return false;
6093             bFirst = false;
6094         }
6095         // nested shape group container ?
6096         else if( DFF_msofbtSpgrContainer == nFbt )
6097         {
6098             if ( !GetShapeGroupContainerData( rSt, nLength, false, nDrawingContainerId ) )
6099                 return false;
6100         }
6101         else
6102         {
6103             if (!checkSeek(rSt, rSt.Tell() + nLength))
6104                 return false;
6105         }
6106         nReadSpGrCont += nLength;
6107     }
6108     while( nReadSpGrCont < nLenShapeGroupCont );
6109     // position the stream correctly
6110     rSt.Seek( nStartShapeGroupCont + nLenShapeGroupCont );
6111     return true;
6112 }
6113 
6114 bool SvxMSDffManager::GetShapeContainerData( SvStream& rSt,
6115                                              sal_uLong nLenShapeCont,
6116                                              sal_uLong nPosGroup,
6117                                              sal_uInt16 nDrawingContainerId )
6118 {
6119     sal_uInt8 nVer;sal_uInt16 nInst;sal_uInt16 nFbt;sal_uInt32 nLength;
6120     long  nStartShapeCont = rSt.Tell();
6121 
6122     // We are in a shape container (possibly more than one per shape group) and we now
6123     // have to fetch the shape id and file position (to be able to access them again later)
6124     // and the first BStore reference (if present).
6125     sal_uLong nLenShapePropTbl = 0;
6126     sal_uLong nReadSpCont = 0;
6127 
6128     // Store file offset of the shape containers or respectively the group(!).
6129     sal_uLong nStartOffs = (ULONG_MAX > nPosGroup) ?
6130                             nPosGroup : nStartShapeCont - DFF_COMMON_RECORD_HEADER_SIZE;
6131     SvxMSDffShapeInfo aInfo( nStartOffs );
6132 
6133     // Can the shape be replaced with a frame?
6134     // (provided that it is a TextBox and the text is not rotated)
6135     bool bCanBeReplaced = nPosGroup >= ULONG_MAX;
6136 
6137     // we don't know yet whether it's a TextBox
6138     MSO_SPT         eShapeType      = mso_sptNil;
6139 
6140     // analyze Shape
6141 
6142     do
6143     {
6144         if(!ReadCommonRecordHeader( rSt, nVer, nInst, nFbt, nLength)) return false;
6145         nReadSpCont += DFF_COMMON_RECORD_HEADER_SIZE;
6146         // FSP ?
6147         if( ( DFF_msofbtSp == nFbt ) && ( 4 <= nLength ) )
6148         {
6149             // we've found the FSP: note Shape Type and Id!
6150             eShapeType = static_cast<MSO_SPT>(nInst);
6151             rSt.ReadUInt32( aInfo.nShapeId );
6152             rSt.SeekRel( nLength - 4 );
6153             nReadSpCont += nLength;
6154         }
6155         else if( DFF_msofbtOPT == nFbt ) // Shape Property Table ?
6156         {
6157             // We've found the Property Table:
6158             // search for the Blip Property!
6159             sal_uLong  nPropRead = 0;
6160             nLenShapePropTbl = nLength;
6161             long nStartShapePropTbl = rSt.Tell();
6162             do
6163             {
6164                 sal_uInt16 nPropId(0);
6165                 sal_uInt32 nPropVal(0);
6166 
6167                 rSt.ReadUInt16( nPropId )
6168                    .ReadUInt32( nPropVal );
6169                 nPropRead += 6;
6170 
6171                 switch( nPropId )
6172                 {
6173                     case DFF_Prop_txflTextFlow :
6174                         //Writer can now handle vertical textflows in its
6175                         //native frames, to only need to do this for the
6176                         //other two formats
6177 
6178                         //Writer will handle all textflow except BtoT
6179                         if (GetSvxMSDffSettings() &
6180                             (SVXMSDFF_SETTINGS_IMPORT_PPT |
6181                              SVXMSDFF_SETTINGS_IMPORT_EXCEL))
6182                         {
6183                             if( 0 != nPropVal )
6184                                 bCanBeReplaced = false;
6185                         }
6186                         else if (
6187                             (nPropVal != mso_txflHorzN) &&
6188                             (nPropVal != mso_txflTtoBA)
6189                                 )
6190                         {
6191                             bCanBeReplaced = false;
6192                         }
6193                     break;
6194                     case DFF_Prop_cdirFont :
6195                         //Writer can now handle right to left and left
6196                         //to right in its native frames, so only do
6197                         //this for the other two formats.
6198                         if (GetSvxMSDffSettings() &
6199                             (SVXMSDFF_SETTINGS_IMPORT_PPT |
6200                              SVXMSDFF_SETTINGS_IMPORT_EXCEL))
6201                         {
6202                             if( 0 != nPropVal )
6203                                 bCanBeReplaced = false;
6204                         }
6205                     break;
6206                     case DFF_Prop_Rotation :
6207                         if( 0 != nPropVal )
6208                             bCanBeReplaced = false;
6209                     break;
6210 
6211                     case DFF_Prop_gtextFStrikethrough :
6212                         if( ( 0x20002000 & nPropVal )  == 0x20002000 )
6213                             bCanBeReplaced = false;
6214                     break;
6215 
6216                     case DFF_Prop_fc3DLightFace :
6217                         if( ( 0x00080008 & nPropVal ) == 0x00080008 )
6218                             bCanBeReplaced = false;
6219                     break;
6220 
6221                     case DFF_Prop_WrapText :
6222                         //TODO: eWrapMode = (MSO_WrapMode)nPropVal;
6223                     break;
6224 
6225                     default:
6226                     {
6227                         // is the Bit set and valid?
6228                         if( 0x4000 == ( nPropId & 0xC000 ) )
6229                         {
6230                             // Blip Property found: remember BStore Idx!
6231                             nPropRead = nLenShapePropTbl;
6232                         }
6233                         else if( 0x8000 & nPropId )
6234                         {
6235                             // complex Prop found:
6236                             // Length is always 6. The length of the appended extra data
6237                             // after the actual prop table is of different size.
6238                             nPropVal = 6;
6239                         }
6240                     }
6241                     break;
6242                 }
6243             }
6244             while( nPropRead < nLenShapePropTbl );
6245             rSt.Seek( nStartShapePropTbl + nLenShapePropTbl );
6246             nReadSpCont += nLenShapePropTbl;
6247         }
6248         else if( ( DFF_msofbtClientTextbox == nFbt ) && ( 4 == nLength ) )  // Text-Box-Story-Entry found
6249         {
6250             rSt.ReadUInt32( aInfo.nTxBxComp );
6251             // Add internal drawing container id to text id.
6252             // Note: The text id uses the first two bytes, while the internal
6253             // drawing container id used the second two bytes.
6254             aInfo.nTxBxComp = ( aInfo.nTxBxComp & 0xFFFF0000 ) +
6255                               nDrawingContainerId;
6256             DBG_ASSERT( (aInfo.nTxBxComp & 0x0000FFFF) == nDrawingContainerId,
6257                         "<SvxMSDffManager::GetShapeContainerData(..)> - internal drawing container Id could not be correctly merged into DFF_msofbtClientTextbox value." );
6258         }
6259         else
6260         {
6261             if (!checkSeek(rSt, rSt.Tell() + nLength))
6262             {
6263                 SAL_WARN("filter.ms", "remaining record longer than available data, ppt or parser is wrong");
6264                 break;
6265             }
6266             nReadSpCont += nLength;
6267         }
6268     }
6269     while( nReadSpCont < nLenShapeCont );
6270 
6271 
6272     // Now possibly store the information for subsequent accesses to the shape
6273 
6274     if( aInfo.nShapeId )
6275     {
6276         // Possibly allow replacement of textboxes with frames
6277         if(     bCanBeReplaced
6278              && aInfo.nTxBxComp
6279              && (
6280                     ( eShapeType == mso_sptTextSimple )
6281                  || ( eShapeType == mso_sptTextBox    )
6282                  || ( eShapeType == mso_sptRectangle  )
6283                  || ( eShapeType == mso_sptRoundRectangle )
6284                 ) )
6285         {
6286             aInfo.bReplaceByFly = true;
6287         }
6288         m_xShapeInfosByTxBxComp->insert(std::make_shared<SvxMSDffShapeInfo>(
6289                     aInfo));
6290         m_aShapeOrders.push_back(std::make_unique<SvxMSDffShapeOrder>(
6291                     aInfo.nShapeId ));
6292     }
6293 
6294     // and position the Stream correctly again
6295     rSt.Seek( nStartShapeCont + nLenShapeCont );
6296     return true;
6297 }
6298 
6299 
6300 /*****************************************************************************
6301 
6302     Access to a shape at runtime (via the Shape-Id)
6303     ----------------------------
6304 ******************************************************************************/
6305 bool SvxMSDffManager::GetShape(sal_uLong nId, SdrObject*&         rpShape,
6306                                           SvxMSDffImportData& rData)
6307 {
6308     std::shared_ptr<SvxMSDffShapeInfo> const pTmpRec(
6309         new SvxMSDffShapeInfo(0, nId));
6310 
6311     SvxMSDffShapeInfos_ById::const_iterator const it =
6312         m_xShapeInfosById->find(pTmpRec);
6313     if (it != m_xShapeInfosById->end())
6314     {
6315         // Possibly delete old error flag.
6316         if( rStCtrl.GetError() )
6317             rStCtrl.ResetError();
6318         // store FilePos of the stream(s)
6319         sal_uLong nOldPosCtrl = rStCtrl.Tell();
6320         sal_uLong nOldPosData = pStData ? pStData->Tell() : nOldPosCtrl;
6321         // jump to the shape in the control stream
6322         sal_uLong const nFilePos((*it)->nFilePos);
6323         bool bSeeked = (nFilePos == rStCtrl.Seek(nFilePos));
6324 
6325         // if it failed, reset error statusF
6326         if (!bSeeked || rStCtrl.GetError())
6327             rStCtrl.ResetError();
6328         else
6329             rpShape = ImportObj( rStCtrl, rData, rData.aParentRect, rData.aParentRect, /*nCalledByGroup*/0, /*pShapeId*/nullptr );
6330 
6331         // restore old FilePos of the stream(s)
6332         rStCtrl.Seek( nOldPosCtrl );
6333         if( &rStCtrl != pStData && pStData )
6334             pStData->Seek( nOldPosData );
6335         return ( nullptr != rpShape );
6336     }
6337     return false;
6338 }
6339 
6340 
6341 /** Access to a BLIP at runtime (if the Blip-Number is already known)
6342  */
6343 bool SvxMSDffManager::GetBLIP( sal_uLong nIdx_, Graphic& rGraphic, tools::Rectangle* pVisArea )
6344 {
6345     if (!pStData)
6346         return false;
6347 
6348     bool bOk = false;       // initialize result variable
6349 
6350     // check if a graphic for this blipId is already imported
6351     if (nIdx_)
6352     {
6353         auto iter = aEscherBlipCache.find(nIdx_);
6354 
6355         if (iter != aEscherBlipCache.end())
6356         {
6357             /* if this entry is available */
6358             rGraphic = iter->second;
6359             if (rGraphic.GetType() != GraphicType::NONE)
6360                 bOk = true;
6361             else
6362                 aEscherBlipCache.erase(iter);
6363         }
6364     }
6365 
6366     if (!bOk)
6367     {
6368         sal_uInt16 nIdx = sal_uInt16( nIdx_ );
6369         if (!nIdx || (m_pBLIPInfos->size() < nIdx))
6370             return false;
6371 
6372         // possibly delete old error flag(s)
6373         if( rStCtrl.GetError() )
6374             rStCtrl.ResetError();
6375         if(    ( &rStCtrl != pStData )
6376             && pStData->GetError() )
6377             pStData->ResetError();
6378 
6379         // remember FilePos of the stream(s)
6380         sal_uLong nOldPosCtrl = rStCtrl.Tell();
6381         sal_uLong nOldPosData = pStData->Tell();
6382 
6383         // fetch matching info struct out of the pointer array
6384         SvxMSDffBLIPInfo& rInfo = (*m_pBLIPInfos)[ nIdx-1 ];
6385         // jump to the BLIP atom in the data stream
6386         bOk = checkSeek(*pStData, rInfo.nFilePos);
6387         // possibly reset error status
6388         if (!bOk || pStData->GetError())
6389             pStData->ResetError();
6390         else
6391             bOk = GetBLIPDirect( *pStData, rGraphic, pVisArea );
6392         if( pStData2 && !bOk )
6393         {
6394             // Error, but the is a second chance: There is a second
6395             //         data stream in which the graphic could be stored!
6396             if( pStData2->GetError() )
6397                 pStData2->ResetError();
6398             sal_uLong nOldPosData2 = pStData2->Tell();
6399             // jump to the BLIP atom in the second data stream
6400             bOk = checkSeek(*pStData2, rInfo.nFilePos);
6401             // reset error status if necessary
6402             if (!bOk || pStData2->GetError())
6403                 pStData2->ResetError();
6404             else
6405                 bOk = GetBLIPDirect( *pStData2, rGraphic, pVisArea );
6406             // restore of FilePos of the second data stream
6407             pStData2->Seek( nOldPosData2 );
6408         }
6409         // restore old FilePos of the stream(s)
6410         rStCtrl.Seek( nOldPosCtrl );
6411         if( &rStCtrl != pStData )
6412           pStData->Seek( nOldPosData );
6413 
6414         if (bOk)
6415         {
6416             // create new BlipCacheEntry for this graphic
6417             aEscherBlipCache.insert(std::make_pair(nIdx_, rGraphic));
6418         }
6419     }
6420 
6421     return bOk;
6422 }
6423 
6424 /*      access to a BLIP at runtime (with correctly positioned stream)
6425     ---------------------------------
6426 ******************************************************************************/
6427 bool SvxMSDffManager::GetBLIPDirect( SvStream& rBLIPStream, Graphic& rData, tools::Rectangle* pVisArea )
6428 {
6429     sal_uLong nOldPos = rBLIPStream.Tell();
6430 
6431     ErrCode nRes = ERRCODE_GRFILTER_OPENERROR;  // initialize error variable
6432 
6433     // check whether it's really a BLIP
6434     sal_uInt32 nLength;
6435     sal_uInt16 nInst, nFbt( 0 );
6436     sal_uInt8   nVer;
6437     if( ReadCommonRecordHeader( rBLIPStream, nVer, nInst, nFbt, nLength) && ( 0xF018 <= nFbt ) && ( 0xF117 >= nFbt ) )
6438     {
6439         Size        aMtfSize100;
6440         bool        bMtfBLIP = false;
6441         bool        bZCodecCompression = false;
6442         // now position it exactly at the beginning of the embedded graphic
6443         sal_uLong nSkip = ( nInst & 0x0001 ) ? 32 : 16;
6444 
6445         switch( nInst & 0xFFFE )
6446         {
6447             case 0x216 :            // Metafile header then compressed WMF
6448             case 0x3D4 :            // Metafile header then compressed EMF
6449             case 0x542 :            // Metafile hd. then compressed PICT
6450             {
6451                 rBLIPStream.SeekRel( nSkip + 20 );
6452 
6453                 // read in size of metafile in EMUS
6454                 sal_Int32 width(0), height(0);
6455                 rBLIPStream.ReadInt32( width ).ReadInt32( height );
6456                 aMtfSize100.setWidth( width );
6457                 aMtfSize100.setHeight( height );
6458 
6459                 // scale to 1/100mm
6460                 aMtfSize100.setWidth( aMtfSize100.Width() / 360 );
6461                 aMtfSize100.setHeight( aMtfSize100.Height() / 360 );
6462 
6463                 if ( pVisArea )     // seem that we currently are skipping the visarea position
6464                     *pVisArea = tools::Rectangle( Point(), aMtfSize100 );
6465 
6466                 // skip rest of header
6467                 nSkip = 6;
6468                 bMtfBLIP = bZCodecCompression = true;
6469             }
6470             break;
6471             case 0x46A :            // One byte tag then JPEG (= JFIF) data
6472             case 0x6E0 :            // One byte tag then PNG data
6473             case 0x6E2 :            // One byte tag then JPEG in CMYK color space
6474             case 0x7A8 :
6475                 nSkip += 1;         // One byte tag then DIB data
6476             break;
6477         }
6478         rBLIPStream.SeekRel( nSkip );
6479 
6480         SvStream* pGrStream = &rBLIPStream;
6481         std::unique_ptr<SvMemoryStream> xOut;
6482         if( bZCodecCompression )
6483         {
6484             xOut.reset(new SvMemoryStream( 0x8000, 0x4000 ));
6485             ZCodec aZCodec( 0x8000, 0x8000 );
6486             aZCodec.BeginCompression();
6487             aZCodec.Decompress( rBLIPStream, *xOut );
6488             aZCodec.EndCompression();
6489             xOut->Seek( STREAM_SEEK_TO_BEGIN );
6490             xOut->SetResizeOffset( 0 ); // sj: #i102257# setting ResizeOffset of 0 prevents from seeking
6491                                         // behind the stream end (allocating too much memory)
6492             pGrStream = xOut.get();
6493         }
6494 
6495 #ifdef DEBUG_FILTER_MSDFFIMP
6496         // extract graphics from ole storage into "dbggfxNNN.*"
6497         static sal_Int32 nGrfCount;
6498 
6499         OUString aFileName = "dbggfx" + OUString::number( nGrfCount++ );
6500         switch( nInst &~ 1 )
6501         {
6502             case 0x216 : aFileName += ".wmf"; break;
6503             case 0x3d4 : aFileName += ".emf"; break;
6504             case 0x542 : aFileName += ".pct"; break;
6505             case 0x46a : aFileName += ".jpg"; break;
6506             case 0x6e0 : aFileName += ".png"; break;
6507             case 0x6e2 : aFileName += ".jpg"; break;
6508             case 0x7a8 : aFileName += ".bmp"; break;
6509         }
6510 
6511         OUString aURLStr;
6512         if( osl::FileBase::getFileURLFromSystemPath( Application::GetAppFileName(), aURLStr ) == osl::FileBase::E_None )
6513         {
6514             INetURLObject aURL( aURLStr );
6515 
6516             aURL.removeSegment();
6517             aURL.removeFinalSlash();
6518             aURL.Append( aFileName );
6519 
6520             aURLStr = aURL.GetMainURL( INetURLObject::DecodeMechanism::NONE );
6521 
6522             SAL_INFO("filter.ms", "dumping " << aURLStr);
6523 
6524             std::unique_ptr<SvStream> pDbgOut(::utl::UcbStreamHelper::CreateStream(aURLStr, StreamMode::TRUNC | StreamMode::WRITE));
6525 
6526             if( pDbgOut )
6527             {
6528                 if ( bZCodecCompression )
6529                 {
6530                     pDbgOut->WriteBytes(xOut->GetData(), xOut->TellEnd());
6531                     xOut->Seek(STREAM_SEEK_TO_BEGIN);
6532                 }
6533                 else
6534                 {
6535                     sal_Int32 nDbgLen = nLength - nSkip;
6536                     if ( nDbgLen )
6537                     {
6538                         std::vector<sal_Char> aData(nDbgLen);
6539                         pGrStream->ReadBytes(aData.data(), nDbgLen);
6540                         pDbgOut->WriteBytes(aData.data(), nDbgLen);
6541                         pGrStream->SeekRel(-nDbgLen);
6542                     }
6543                 }
6544             }
6545         }
6546 #endif
6547 
6548         if( ( nInst & 0xFFFE ) == 0x7A8 )
6549         {   // getting the DIBs immediately
6550             Bitmap aNew;
6551             if( ReadDIB(aNew, *pGrStream, false) )
6552             {
6553                 rData = Graphic( aNew );
6554                 nRes = ERRCODE_NONE;
6555             }
6556         }
6557         else
6558         {   // and unleash our filter
6559             GraphicFilter& rGF = GraphicFilter::GetGraphicFilter();
6560             Graphic aGraphic = rGF.ImportUnloadedGraphic(*pGrStream);
6561             if (aGraphic)
6562             {
6563                 rData = aGraphic;
6564                 nRes = ERRCODE_NONE;
6565             }
6566             else
6567                 nRes = rGF.ImportGraphic( rData, "", *pGrStream );
6568 
6569             // SJ: I40472, sometimes the aspect ratio (aMtfSize100) does not match and we get scaling problems,
6570             // then it is better to use the prefsize that is stored within the metafile. Bug #72846# for what the
6571             // scaling has been implemented does not happen anymore.
6572             //
6573             // For pict graphics we will furthermore scale the metafile, because font scaling leads to error if the
6574             // dxarray is empty (this has been solved in wmf/emf but not for pict)
6575             if( bMtfBLIP && ( ERRCODE_NONE == nRes ) && ( rData.GetType() == GraphicType::GdiMetafile ) && ( ( nInst & 0xFFFE ) == 0x542 ) )
6576             {
6577                 if ( ( aMtfSize100.Width() >= 1000 ) && ( aMtfSize100.Height() >= 1000 ) )
6578                 {   // #75956#, scaling does not work properly, if the graphic is less than 1cm
6579                     GDIMetaFile aMtf( rData.GetGDIMetaFile() );
6580                     const Size  aOldSize( aMtf.GetPrefSize() );
6581 
6582                     if( aOldSize.Width() && ( aOldSize.Width() != aMtfSize100.Width() ) &&
6583                         aOldSize.Height() && ( aOldSize.Height() != aMtfSize100.Height() ) )
6584                     {
6585                         aMtf.Scale( static_cast<double>(aMtfSize100.Width()) / aOldSize.Width(),
6586                                     static_cast<double>(aMtfSize100.Height()) / aOldSize.Height() );
6587                         aMtf.SetPrefSize( aMtfSize100 );
6588                         aMtf.SetPrefMapMode(MapMode(MapUnit::Map100thMM));
6589                         rData = aMtf;
6590                     }
6591                 }
6592             }
6593         }
6594         // reset error status if necessary
6595         if ( ERRCODE_IO_PENDING == pGrStream->GetError() )
6596           pGrStream->ResetError();
6597     }
6598     rBLIPStream.Seek( nOldPos );    // restore old FilePos of the strem
6599 
6600     return ( ERRCODE_NONE == nRes ); // return result
6601 }
6602 
6603 /* also static */
6604 bool SvxMSDffManager::ReadCommonRecordHeader(SvStream& rSt,
6605     sal_uInt8& rVer, sal_uInt16& rInst, sal_uInt16& rFbt, sal_uInt32& rLength)
6606 {
6607     sal_uInt16 nTmp(0);
6608     rSt.ReadUInt16( nTmp ).ReadUInt16( rFbt ).ReadUInt32( rLength );
6609     rVer = sal::static_int_cast< sal_uInt8 >(nTmp & 15);
6610     rInst = nTmp >> 4;
6611     if (!rSt.good())
6612         return false;
6613     if (rLength > nMaxLegalDffRecordLength)
6614         return false;
6615     return true;
6616 }
6617 
6618 void SvxMSDffManager::ProcessClientAnchor(SvStream& rStData, sal_uInt32 nDatLen,
6619                                           std::unique_ptr<char[]>& rpBuff, sal_uInt32& rBuffLen )
6620 {
6621     if( nDatLen )
6622     {
6623         rBuffLen = std::min(rStData.remainingSize(), static_cast<sal_uInt64>(nDatLen));
6624         rpBuff.reset( new char[rBuffLen] );
6625         rBuffLen = rStData.ReadBytes(rpBuff.get(), rBuffLen);
6626     }
6627 }
6628 
6629 void SvxMSDffManager::ProcessClientData(SvStream& rStData, sal_uInt32 nDatLen,
6630                                         std::unique_ptr<char[]>& rpBuff, sal_uInt32& rBuffLen )
6631 {
6632     if( nDatLen )
6633     {
6634         rBuffLen = std::min(rStData.remainingSize(), static_cast<sal_uInt64>(nDatLen));
6635         rpBuff.reset( new char[rBuffLen] );
6636         rBuffLen = rStData.ReadBytes(rpBuff.get(), rBuffLen);
6637     }
6638 }
6639 
6640 
6641 void SvxMSDffManager::ProcessClientAnchor2( SvStream& /* rSt */, DffRecordHeader& /* rHd */ , SvxMSDffClientData& /* rData */, DffObjData& /* rObj */ )
6642 {
6643     // will be overridden by SJ in Draw
6644 }
6645 
6646 bool SvxMSDffManager::GetOLEStorageName( sal_uInt32, OUString&, tools::SvRef<SotStorage>&, uno::Reference < embed::XStorage >& ) const
6647 {
6648     return false;
6649 }
6650 
6651 bool SvxMSDffManager::ShapeHasText( sal_uLong /* nShapeId */, sal_uLong /* nFilePos */ ) const
6652 {
6653     return true;
6654 }
6655 
6656 // #i32596# - add new parameter <_nCalledByGroup>
6657 SdrObject* SvxMSDffManager::ImportOLE( sal_uInt32 nOLEId,
6658                                        const Graphic& rGrf,
6659                                        const tools::Rectangle& rBoundRect,
6660                                        const tools::Rectangle& rVisArea,
6661                                        const int /* _nCalledByGroup */ ) const
6662 {
6663     SdrObject* pRet = nullptr;
6664     OUString sStorageName;
6665     tools::SvRef<SotStorage> xSrcStg;
6666     ErrCode nError = ERRCODE_NONE;
6667     uno::Reference < embed::XStorage > xDstStg;
6668     if( GetOLEStorageName( nOLEId, sStorageName, xSrcStg, xDstStg ))
6669         pRet = CreateSdrOLEFromStorage(
6670             *GetModel(),
6671             sStorageName,
6672             xSrcStg,
6673             xDstStg,
6674             rGrf,
6675             rBoundRect,
6676             rVisArea,
6677             pStData,
6678             nError,
6679             nSvxMSDffOLEConvFlags,
6680             embed::Aspects::MSOLE_CONTENT,
6681             maBaseURL);
6682     return pRet;
6683 }
6684 
6685 bool SvxMSDffManager::MakeContentStream( SotStorage * pStor, const GDIMetaFile & rMtf )
6686 {
6687     tools::SvRef<SotStorageStream> xStm = pStor->OpenSotStream(SVEXT_PERSIST_STREAM);
6688     xStm->SetVersion( pStor->GetVersion() );
6689     xStm->SetBufferSize( 8192 );
6690 
6691     Impl_OlePres aEle;
6692     // Convert the size in 1/100 mm
6693     // If a not applicable MapUnit (device dependent) is used,
6694     // SV tries to guess a best match for the right value
6695     Size aSize = rMtf.GetPrefSize();
6696     const MapMode& aMMSrc = rMtf.GetPrefMapMode();
6697     MapMode aMMDst( MapUnit::Map100thMM );
6698     aSize = OutputDevice::LogicToLogic( aSize, aMMSrc, aMMDst );
6699     aEle.SetSize( aSize );
6700     aEle.SetAspect( ASPECT_CONTENT );
6701     aEle.SetAdviseFlags( 2 );
6702     aEle.SetMtf( rMtf );
6703     aEle.Write( *xStm );
6704 
6705     xStm->SetBufferSize( 0 );
6706     return xStm->GetError() == ERRCODE_NONE;
6707 }
6708 
6709 struct ClsIDs {
6710     sal_uInt32      nId;
6711     const sal_Char* pSvrName;
6712     const sal_Char* pDspName;
6713 };
6714 static const ClsIDs aClsIDs[] = {
6715 
6716     { 0x000212F0, "MSWordArt",          "Microsoft Word Art"            },
6717     { 0x000212F0, "MSWordArt.2",        "Microsoft Word Art 2.0"        },
6718 
6719     // MS Apps
6720     { 0x00030000, "ExcelWorksheet",     "Microsoft Excel Worksheet"     },
6721     { 0x00030001, "ExcelChart",         "Microsoft Excel Chart"         },
6722     { 0x00030002, "ExcelMacrosheet",    "Microsoft Excel Macro"         },
6723     { 0x00030003, "WordDocument",       "Microsoft Word Document"       },
6724     { 0x00030004, "MSPowerPoint",       "Microsoft PowerPoint"          },
6725     { 0x00030005, "MSPowerPointSho",    "Microsoft PowerPoint Slide Show"},
6726     { 0x00030006, "MSGraph",            "Microsoft Graph"               },
6727     { 0x00030007, "MSDraw",             "Microsoft Draw"                },
6728     { 0x00030008, "Note-It",            "Microsoft Note-It"             },
6729     { 0x00030009, "WordArt",            "Microsoft Word Art"            },
6730     { 0x0003000a, "PBrush",             "Microsoft PaintBrush Picture"  },
6731     { 0x0003000b, "Equation",           "Microsoft Equation Editor"     },
6732     { 0x0003000c, "Package",            "Package"                       },
6733     { 0x0003000d, "SoundRec",           "Sound"                         },
6734     { 0x0003000e, "MPlayer",            "Media Player"                  },
6735     // MS Demos
6736     { 0x0003000f, "ServerDemo",         "OLE 1.0 Server Demo"           },
6737     { 0x00030010, "Srtest",             "OLE 1.0 Test Demo"             },
6738     { 0x00030011, "SrtInv",             "OLE 1.0 Inv Demo"              },
6739     { 0x00030012, "OleDemo",            "OLE 1.0 Demo"                  },
6740 
6741     // Coromandel / Dorai Swamy / 718-793-7963
6742     { 0x00030013, "CoromandelIntegra",  "Coromandel Integra"            },
6743     { 0x00030014, "CoromandelObjServer","Coromandel Object Server"      },
6744 
6745     // 3-d Visions Corp / Peter Hirsch / 310-325-1339
6746     { 0x00030015, "StanfordGraphics",   "Stanford Graphics"             },
6747 
6748     // Deltapoint / Nigel Hearne / 408-648-4000
6749     { 0x00030016, "DGraphCHART",        "DeltaPoint Graph Chart"        },
6750     { 0x00030017, "DGraphDATA",         "DeltaPoint Graph Data"         },
6751 
6752     // Corel / Richard V. Woodend / 613-728-8200 x1153
6753     { 0x00030018, "PhotoPaint",         "Corel PhotoPaint"              },
6754     { 0x00030019, "CShow",              "Corel Show"                    },
6755     { 0x0003001a, "CorelChart",         "Corel Chart"                   },
6756     { 0x0003001b, "CDraw",              "Corel Draw"                    },
6757 
6758     // Inset Systems / Mark Skiba / 203-740-2400
6759     { 0x0003001c, "HJWIN1.0",           "Inset Systems"                 },
6760 
6761     // Mark V Systems / Mark McGraw / 818-995-7671
6762     { 0x0003001d, "ObjMakerOLE",        "MarkV Systems Object Maker"    },
6763 
6764     // IdentiTech / Mike Gilger / 407-951-9503
6765     { 0x0003001e, "FYI",                "IdentiTech FYI"                },
6766     { 0x0003001f, "FYIView",            "IdentiTech FYI Viewer"         },
6767 
6768     // Inventa Corporation / Balaji Varadarajan / 408-987-0220
6769     { 0x00030020, "Stickynote",         "Inventa Sticky Note"           },
6770 
6771     // ShapeWare Corp. / Lori Pearce / 206-467-6723
6772     { 0x00030021, "ShapewareVISIO10",   "Shapeware Visio 1.0"           },
6773     { 0x00030022, "ImportServer",       "Spaheware Import Server"       },
6774 
6775     // test app SrTest
6776     { 0x00030023, "SrvrTest",           "OLE 1.0 Server Test"           },
6777 
6778     // test app ClTest.  Doesn't really work as a server but is in reg db
6779     { 0x00030025, "Cltest",             "OLE 1.0 Client Test"           },
6780 
6781     // Microsoft ClipArt Gallery   Sherry Larsen-Holmes
6782     { 0x00030026, "MS_ClipArt_Gallery", "Microsoft ClipArt Gallery"     },
6783     // Microsoft Project  Cory Reina
6784     { 0x00030027, "MSProject",          "Microsoft Project"             },
6785 
6786     // Microsoft Works Chart
6787     { 0x00030028, "MSWorksChart",       "Microsoft Works Chart"         },
6788 
6789     // Microsoft Works Spreadsheet
6790     { 0x00030029, "MSWorksSpreadsheet", "Microsoft Works Spreadsheet"   },
6791 
6792     // AFX apps - Dean McCrory
6793     { 0x0003002A, "MinSvr",             "AFX Mini Server"               },
6794     { 0x0003002B, "HierarchyList",      "AFX Hierarchy List"            },
6795     { 0x0003002C, "BibRef",             "AFX BibRef"                    },
6796     { 0x0003002D, "MinSvrMI",           "AFX Mini Server MI"            },
6797     { 0x0003002E, "TestServ",           "AFX Test Server"               },
6798 
6799     // Ami Pro
6800     { 0x0003002F, "AmiProDocument",     "Ami Pro Document"              },
6801 
6802     // WordPerfect Presentations For Windows
6803     { 0x00030030, "WPGraphics",         "WordPerfect Presentation"      },
6804     { 0x00030031, "WPCharts",           "WordPerfect Chart"             },
6805 
6806     // MicroGrafx Charisma
6807     { 0x00030032, "Charisma",           "MicroGrafx Charisma"           },
6808     { 0x00030033, "Charisma_30",        "MicroGrafx Charisma 3.0"       },
6809     { 0x00030034, "CharPres_30",        "MicroGrafx Charisma 3.0 Pres"  },
6810     // MicroGrafx Draw
6811     { 0x00030035, "Draw",               "MicroGrafx Draw"               },
6812     // MicroGrafx Designer
6813     { 0x00030036, "Designer_40",        "MicroGrafx Designer 4.0"       },
6814 
6815     // STAR DIVISION
6816     { 0x00043AD2, "FontWork",           "Star FontWork"                 },
6817 
6818     { 0, "", "" } };
6819 
6820 
6821 bool SvxMSDffManager::ConvertToOle2( SvStream& rStm, sal_uInt32 nReadLen,
6822                     const GDIMetaFile * pMtf, const tools::SvRef<SotStorage>& rDest )
6823 {
6824     bool bMtfRead = false;
6825     tools::SvRef<SotStorageStream> xOle10Stm = rDest->OpenSotStream( "\1Ole10Native",
6826                                                     StreamMode::WRITE| StreamMode::SHARE_DENYALL );
6827     if( xOle10Stm->GetError() )
6828         return false;
6829 
6830     OUString   aSvrName;
6831     sal_uInt32 nDummy0;
6832     sal_uInt32 nDummy1;
6833     sal_uInt32 nBytesRead = 0;
6834     do
6835     {
6836         sal_uInt32 nType(0);
6837         sal_uInt32 nRecType(0);
6838         sal_uInt32 nStrLen(0);
6839 
6840         rStm.ReadUInt32( nType );
6841         rStm.ReadUInt32( nRecType );
6842         rStm.ReadUInt32( nStrLen );
6843         if( nStrLen )
6844         {
6845             if( 0x10000L > nStrLen )
6846             {
6847                 std::unique_ptr<sal_Char[]> pBuf(new sal_Char[ nStrLen ]);
6848                 rStm.ReadBytes(pBuf.get(), nStrLen);
6849                 aSvrName = OUString( pBuf.get(), static_cast<sal_uInt16>(nStrLen)-1, osl_getThreadTextEncoding() );
6850             }
6851             else
6852                 break;
6853         }
6854         rStm.ReadUInt32( nDummy0 );
6855         rStm.ReadUInt32( nDummy1 );
6856         sal_uInt32 nDataLen(0);
6857         rStm.ReadUInt32( nDataLen );
6858 
6859         nBytesRead += 6 * sizeof( sal_uInt32 ) + nStrLen + nDataLen;
6860 
6861         if (rStm.good() && nReadLen > nBytesRead && nDataLen)
6862         {
6863             if( xOle10Stm.is() )
6864             {
6865                 std::unique_ptr<sal_uInt8[]> pData(new sal_uInt8[ nDataLen ]);
6866                 rStm.ReadBytes(pData.get(), nDataLen);
6867 
6868                 // write to ole10 stream
6869                 xOle10Stm->WriteUInt32( nDataLen );
6870                 xOle10Stm->WriteBytes(pData.get(), nDataLen);
6871                 xOle10Stm = tools::SvRef<SotStorageStream>();
6872 
6873                 // set the compobj stream
6874                 const ClsIDs* pIds;
6875                 for( pIds = aClsIDs; pIds->nId; pIds++ )
6876                 {
6877                     if( aSvrName == OUString::createFromAscii(pIds->pSvrName) )
6878                         break;
6879                 }
6880 
6881                 if( pIds->nId )
6882                 {
6883                     // found!
6884                     SotClipboardFormatId nCbFmt = SotExchange::RegisterFormatName( aSvrName );
6885                     rDest->SetClass( SvGlobalName( pIds->nId, 0, 0, 0xc0,0,0,0,0,0,0,0x46 ), nCbFmt,
6886                                     OUString::createFromAscii( pIds->pDspName ) );
6887                 }
6888                 else
6889                 {
6890                     SotClipboardFormatId nCbFmt = SotExchange::RegisterFormatName( aSvrName );
6891                     rDest->SetClass( SvGlobalName(), nCbFmt, aSvrName );
6892                 }
6893             }
6894             else if( nRecType == 5 && !pMtf )
6895             {
6896                 sal_uLong nPos = rStm.Tell();
6897                 sal_uInt16 sz[4];
6898                 rStm.ReadBytes( sz, 8 );
6899                 Graphic aGraphic;
6900                 if( ERRCODE_NONE == GraphicConverter::Import( rStm, aGraphic ) && aGraphic.GetType() != GraphicType::NONE )
6901                 {
6902                     const GDIMetaFile& rMtf = aGraphic.GetGDIMetaFile();
6903                     MakeContentStream( rDest.get(), rMtf );
6904                     bMtfRead = true;
6905                 }
6906                 // set behind the data
6907                 rStm.Seek( nPos + nDataLen );
6908             }
6909             else
6910                 rStm.SeekRel( nDataLen );
6911         }
6912     } while (rStm.good() && nReadLen >= nBytesRead);
6913 
6914     if( !bMtfRead && pMtf )
6915     {
6916         MakeContentStream( rDest.get(), *pMtf );
6917         return true;
6918     }
6919 
6920     return false;
6921 }
6922 
6923 static const char* GetInternalServerName_Impl( const SvGlobalName& aGlobName )
6924 {
6925     if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_60 )
6926       || aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
6927         return "swriter";
6928     else if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_60 )
6929       || aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
6930         return "scalc";
6931     else if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_60 )
6932       || aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
6933         return "simpress";
6934     else if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_60 )
6935       || aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
6936         return "sdraw";
6937     else if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_60 )
6938       || aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
6939         return "smath";
6940     else if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_60 )
6941       || aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
6942         return "schart";
6943     return nullptr;
6944 }
6945 
6946 OUString SvxMSDffManager::GetFilterNameFromClassID( const SvGlobalName& aGlobName )
6947 {
6948     if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_60 ) )
6949         return OUString( "StarOffice XML (Writer)" );
6950 
6951     if ( aGlobName == SvGlobalName( SO3_SW_OLE_EMBED_CLASSID_8 ) )
6952         return OUString( "writer8" );
6953 
6954     if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_60 ) )
6955         return OUString( "StarOffice XML (Calc)" );
6956 
6957     if ( aGlobName == SvGlobalName( SO3_SC_OLE_EMBED_CLASSID_8 ) )
6958         return OUString( "calc8" );
6959 
6960     if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_60 ) )
6961         return OUString( "StarOffice XML (Impress)" );
6962 
6963     if ( aGlobName == SvGlobalName( SO3_SIMPRESS_OLE_EMBED_CLASSID_8 ) )
6964         return OUString( "impress8" );
6965 
6966     if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_60 ) )
6967         return OUString( "StarOffice XML (Draw)" );
6968 
6969     if ( aGlobName == SvGlobalName( SO3_SDRAW_OLE_EMBED_CLASSID_8 ) )
6970         return OUString( "draw8" );
6971 
6972     if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_60 ) )
6973         return OUString( "StarOffice XML (Math)" );
6974 
6975     if ( aGlobName == SvGlobalName( SO3_SM_OLE_EMBED_CLASSID_8 ) )
6976         return OUString( "math8" );
6977 
6978     if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_60 ) )
6979         return OUString( "StarOffice XML (Chart)" );
6980 
6981     if ( aGlobName == SvGlobalName( SO3_SCH_OLE_EMBED_CLASSID_8 ) )
6982         return OUString( "chart8" );
6983 
6984     return OUString();
6985 }
6986 
6987 void SvxMSDffManager::ExtractOwnStream(SotStorage& rSrcStg, SvMemoryStream& rMemStream)
6988 {
6989     tools::SvRef<SotStorageStream> xStr
6990         = rSrcStg.OpenSotStream("package_stream", StreamMode::STD_READ);
6991     xStr->ReadStream(rMemStream);
6992 }
6993 
6994 css::uno::Reference < css::embed::XEmbeddedObject >  SvxMSDffManager::CheckForConvertToSOObj( sal_uInt32 nConvertFlags,
6995                         SotStorage& rSrcStg, const uno::Reference < embed::XStorage >& rDestStorage,
6996                         const Graphic& rGrf,
6997                         const tools::Rectangle& rVisArea, OUString const& rBaseURL)
6998 {
6999     uno::Reference < embed::XEmbeddedObject > xObj;
7000     SvGlobalName aStgNm = rSrcStg.GetClassName();
7001     const char* pName = GetInternalServerName_Impl( aStgNm );
7002     OUString sStarName;
7003     if ( pName )
7004         sStarName = OUString::createFromAscii( pName );
7005     else if ( nConvertFlags )
7006     {
7007         static struct ObjImpType
7008         {
7009             sal_uInt32 nFlag;
7010             const char* pFactoryNm;
7011             // GlobalNameId
7012             sal_uInt32 n1;
7013             sal_uInt16 n2, n3;
7014             sal_uInt8 b8, b9, b10, b11, b12, b13, b14, b15;
7015         } const aArr[] = {
7016             { OLE_MATHTYPE_2_STARMATH, "smath", MSO_EQUATION3_CLASSID },
7017             { OLE_MATHTYPE_2_STARMATH, "smath", MSO_EQUATION2_CLASSID },
7018             { OLE_WINWORD_2_STARWRITER, "swriter", MSO_WW8_CLASSID },
7019             // Excel table
7020             { OLE_EXCEL_2_STARCALC, "scalc", MSO_EXCEL5_CLASSID },
7021             { OLE_EXCEL_2_STARCALC, "scalc", MSO_EXCEL8_CLASSID },
7022             // 114465: additional Excel OLE chart classId to above.
7023             { OLE_EXCEL_2_STARCALC, "scalc", MSO_EXCEL8_CHART_CLASSID },
7024             // PowerPoint presentation
7025             { OLE_POWERPOINT_2_STARIMPRESS, "simpress", MSO_PPT8_CLASSID },
7026             // PowerPoint slide
7027             { OLE_POWERPOINT_2_STARIMPRESS, "simpress", MSO_PPT8_SLIDE_CLASSID },
7028             { 0, nullptr,
7029               0, 0, 0,
7030               0, 0, 0, 0, 0, 0, 0, 0 }
7031         };
7032 
7033         for( const ObjImpType* pArr = aArr; pArr->nFlag; ++pArr )
7034         {
7035             if( nConvertFlags & pArr->nFlag )
7036             {
7037                 SvGlobalName aTypeName( pArr->n1, pArr->n2, pArr->n3,
7038                                 pArr->b8, pArr->b9, pArr->b10, pArr->b11,
7039                                 pArr->b12, pArr->b13, pArr->b14, pArr->b15 );
7040 
7041                 if ( aStgNm == aTypeName )
7042                 {
7043                     sStarName = OUString::createFromAscii( pArr->pFactoryNm );
7044                     break;
7045                 }
7046             }
7047         }
7048     }
7049 
7050     if ( sStarName.getLength() )
7051     {
7052         //TODO/MBA: check if (and when) storage and stream will be destroyed!
7053         std::shared_ptr<const SfxFilter> pFilter;
7054         std::unique_ptr<SvMemoryStream> xMemStream (new SvMemoryStream);
7055         if ( pName )
7056         {
7057             // TODO/LATER: perhaps we need to retrieve VisArea and Metafile from the storage also
7058             SvxMSDffManager::ExtractOwnStream(rSrcStg, *xMemStream);
7059         }
7060         else
7061         {
7062             SfxFilterMatcher aMatch( sStarName );
7063             tools::SvRef<SotStorage> xStorage = new SotStorage( false, *xMemStream );
7064             rSrcStg.CopyTo( xStorage.get() );
7065             xStorage->Commit();
7066             xStorage.clear();
7067             OUString aType = SfxFilter::GetTypeFromStorage( rSrcStg );
7068             if (aType.getLength() && !utl::ConfigManager::IsFuzzing())
7069                 pFilter = aMatch.GetFilter4EA( aType );
7070         }
7071 
7072 #ifdef DEBUG_FILTER_MSFILTER
7073         // extract embedded ole streams into "/tmp/embedded_stream_NNN"
7074         static sal_Int32 nOleCount(0);
7075         OUString aTmpName("/tmp/embedded_stream_");
7076         aTmpName += OUString::number(nOleCount++);
7077         aTmpName += ".bin";
7078         SvFileStream aTmpStream(aTmpName,StreamMode::READ|StreamMode::WRITE|StreamMode::TRUNC);
7079         xMemStream->Seek(0);
7080         aTmpStream.WriteStream(*xMemStream);
7081         aTmpStream.Close();
7082 #endif
7083         if ( pName || pFilter )
7084         {
7085             //Reuse current ole name
7086             OUString aDstStgName(MSO_OLE_Obj);
7087             aDstStgName += OUString::number(nMSOleObjCntr);
7088 
7089             OUString aFilterName;
7090             if ( pFilter )
7091                 aFilterName = pFilter->GetName();
7092             else
7093                 aFilterName = SvxMSDffManager::GetFilterNameFromClassID( aStgNm );
7094 
7095             uno::Sequence<beans::PropertyValue> aMedium(aFilterName.isEmpty() ? 3 : 4);
7096             aMedium[0].Name = "InputStream";
7097             uno::Reference < io::XInputStream > xStream = new ::utl::OSeekableInputStreamWrapper( *xMemStream );
7098             aMedium[0].Value <<= xStream;
7099             aMedium[1].Name = "URL";
7100             aMedium[1].Value <<= OUString( "private:stream" );
7101             aMedium[2].Name = "DocumentBaseURL";
7102             aMedium[2].Value <<= rBaseURL;
7103 
7104             if ( !aFilterName.isEmpty() )
7105             {
7106                 aMedium[3].Name = "FilterName";
7107                 aMedium[3].Value <<= aFilterName;
7108             }
7109 
7110             OUString aName( aDstStgName );
7111             comphelper::EmbeddedObjectContainer aCnt( rDestStorage );
7112             xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &rBaseURL);
7113 
7114             if ( !xObj.is() )
7115             {
7116                 if( !aFilterName.isEmpty() )
7117                 {
7118                     // throw the filter parameter away as workaround
7119                     aMedium.realloc( 2 );
7120                     xObj = aCnt.InsertEmbeddedObject(aMedium, aName, &rBaseURL);
7121                 }
7122 
7123                 if ( !xObj.is() )
7124                      return xObj;
7125             }
7126 
7127             // TODO/LATER: ViewAspect must be passed from outside!
7128             sal_Int64 nViewAspect = embed::Aspects::MSOLE_CONTENT;
7129 
7130             // JP 26.10.2001: Bug 93374 / 91928 the writer
7131             // objects need the correct visarea needs the
7132             // correct visarea, but this is not true for
7133             // PowerPoint (see bugdoc 94908b)
7134             // SJ: 19.11.2001 bug 94908, also chart objects
7135             // needs the correct visarea
7136 
7137             // If pName is set this is an own embedded object, it should have the correct size internally
7138             // TODO/LATER: it might make sense in future to set the size stored in internal object
7139             if( !pName && ( sStarName == "swriter" || sStarName == "scalc" ) )
7140             {
7141                 MapMode aMapMode( VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nViewAspect ) ) );
7142                 Size aSz;
7143                 if ( rVisArea.IsEmpty() )
7144                     aSz = lcl_GetPrefSize(rGrf, aMapMode );
7145                 else
7146                 {
7147                     aSz = rVisArea.GetSize();
7148                     aSz = OutputDevice::LogicToLogic( aSz, MapMode( MapUnit::Map100thMM ), aMapMode );
7149                 }
7150 
7151                 // don't modify the object
7152                 //TODO/LATER: remove those hacks, that needs to be done differently!
7153                 //xIPObj->EnableSetModified( sal_False );
7154                 awt::Size aSize;
7155                 aSize.Width = aSz.Width();
7156                 aSize.Height = aSz.Height();
7157                 xObj->setVisualAreaSize( nViewAspect, aSize );
7158                 //xIPObj->EnableSetModified( sal_True );
7159             }
7160             else if ( sStarName == "smath" )
7161             {   // SJ: force the object to recalc its visarea
7162                 //TODO/LATER: wait for PrinterChangeNotification
7163                 //xIPObj->OnDocumentPrinterChanged( NULL );
7164             }
7165         }
7166     }
7167 
7168     return xObj;
7169 }
7170 
7171 // TODO/MBA: code review and testing!
7172 SdrOle2Obj* SvxMSDffManager::CreateSdrOLEFromStorage(
7173     SdrModel& rSdrModel,
7174     const OUString& rStorageName,
7175     tools::SvRef<SotStorage> const & rSrcStorage,
7176     const uno::Reference < embed::XStorage >& xDestStorage,
7177     const Graphic& rGrf,
7178     const tools::Rectangle& rBoundRect,
7179     const tools::Rectangle& rVisArea,
7180     SvStream* pDataStrm,
7181     ErrCode& rError,
7182     sal_uInt32 nConvertFlags,
7183     sal_Int64 nRecommendedAspect,
7184     OUString const& rBaseURL)
7185 {
7186     sal_Int64 nAspect = nRecommendedAspect;
7187     SdrOle2Obj* pRet = nullptr;
7188     if( rSrcStorage.is() && xDestStorage.is() && rStorageName.getLength() )
7189     {
7190         comphelper::EmbeddedObjectContainer aCnt( xDestStorage );
7191         // does the 01Ole-Stream exist at all?
7192         // (that's not the case for e.g. Fontwork )
7193         // If that's not the case -> include it as graphic
7194         bool bValidStorage = false;
7195         OUString aDstStgName(MSO_OLE_Obj);
7196 
7197         aDstStgName += OUString::number( ++nMSOleObjCntr );
7198 
7199         {
7200             tools::SvRef<SotStorage> xObjStg = rSrcStorage->OpenSotStorage( rStorageName );
7201             if( xObjStg.is()  )
7202             {
7203                 {
7204                     sal_uInt8 aTestA[10];   // exist the \1CompObj-Stream ?
7205                     tools::SvRef<SotStorageStream> xSrcTst = xObjStg->OpenSotStream( "\1CompObj" );
7206                     bValidStorage = xSrcTst.is() && sizeof( aTestA ) ==
7207                                     xSrcTst->ReadBytes(aTestA, sizeof(aTestA));
7208                     if( !bValidStorage )
7209                     {
7210                         // or the \1Ole-Stream ?
7211                         xSrcTst = xObjStg->OpenSotStream( "\1Ole" );
7212                         bValidStorage = xSrcTst.is() && sizeof(aTestA) ==
7213                                     xSrcTst->ReadBytes(aTestA, sizeof(aTestA));
7214                     }
7215                 }
7216 
7217                 if( bValidStorage )
7218                 {
7219                     if ( nAspect != embed::Aspects::MSOLE_ICON )
7220                     {
7221                         // check whether the object is iconified one
7222                         // usually this information is already known, the only exception
7223                         // is a kind of embedded objects in Word documents
7224                         // TODO/LATER: should the caller be notified if the aspect changes in future?
7225 
7226                         tools::SvRef<SotStorageStream> xObjInfoSrc = xObjStg->OpenSotStream(
7227                             "\3ObjInfo", StreamMode::STD_READ );
7228                         if ( xObjInfoSrc.is() && !xObjInfoSrc->GetError() )
7229                         {
7230                             sal_uInt8 nByte = 0;
7231                             xObjInfoSrc->ReadUChar( nByte );
7232                             if ( ( nByte >> 4 ) & embed::Aspects::MSOLE_ICON )
7233                                 nAspect = embed::Aspects::MSOLE_ICON;
7234                         }
7235                     }
7236 
7237                     uno::Reference < embed::XEmbeddedObject > xObj( CheckForConvertToSOObj(
7238                             nConvertFlags, *xObjStg, xDestStorage, rGrf,
7239                             rVisArea, rBaseURL));
7240                     if ( xObj.is() )
7241                     {
7242                         // remember file name to use in the title bar
7243                         INetURLObject aURL(rBaseURL);
7244                         xObj->setContainerName(aURL.GetLastName(INetURLObject::DecodeMechanism::WithCharset));
7245 
7246                         svt::EmbeddedObjectRef aObj( xObj, nAspect );
7247 
7248                         // TODO/LATER: need MediaType
7249                         aObj.SetGraphic( rGrf, OUString() );
7250 
7251                         // TODO/MBA: check setting of PersistName
7252                         pRet = new SdrOle2Obj(
7253                             rSdrModel,
7254                             aObj,
7255                             OUString(),
7256                             rBoundRect);
7257 
7258                         // we have the Object, don't create another
7259                         bValidStorage = false;
7260                     }
7261                 }
7262             }
7263         }
7264 
7265         if( bValidStorage )
7266         {
7267             // object is not an own object
7268             tools::SvRef<SotStorage> xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName, StreamMode::READWRITE );
7269 
7270             if ( xObjStor.is() )
7271             {
7272                 tools::SvRef<SotStorage> xSrcStor = rSrcStorage->OpenSotStorage( rStorageName, StreamMode::READ );
7273                 xSrcStor->CopyTo( xObjStor.get() );
7274 
7275                 if( !xObjStor->GetError() )
7276                     xObjStor->Commit();
7277 
7278                 if( xObjStor->GetError() )
7279                 {
7280                     rError = xObjStor->GetError();
7281                     bValidStorage = false;
7282                 }
7283                 else if( !xObjStor.is() )
7284                     bValidStorage = false;
7285             }
7286         }
7287         else if( pDataStrm )
7288         {
7289             sal_uInt32 nLen(0), nDummy(0);
7290             pDataStrm->ReadUInt32( nLen ).ReadUInt32( nDummy );
7291             if( ERRCODE_NONE != pDataStrm->GetError() ||
7292                 // Id in BugDoc - exist there other Ids?
7293                 // The ConvertToOle2 - does not check for consistent
7294                 0x30008 != nDummy )
7295                 bValidStorage = false;
7296             else
7297             {
7298                 // or is it an OLE-1 Stream in the DataStream?
7299                 tools::SvRef<SotStorage> xObjStor = SotStorage::OpenOLEStorage( xDestStorage, aDstStgName );
7300                 //TODO/MBA: remove metafile conversion from ConvertToOle2
7301                 //when is this code used?!
7302                 GDIMetaFile aMtf;
7303                 bValidStorage = ConvertToOle2( *pDataStrm, nLen, &aMtf, xObjStor );
7304                 xObjStor->Commit();
7305             }
7306         }
7307 
7308         if( bValidStorage )
7309         {
7310             uno::Reference < embed::XEmbeddedObject > xObj = aCnt.GetEmbeddedObject( aDstStgName );
7311             if( xObj.is() )
7312             {
7313                 // remember file name to use in the title bar
7314                 INetURLObject aURL( rBaseURL );
7315                 xObj->setContainerName( aURL.GetLastName( INetURLObject::DecodeMechanism::WithCharset ) );
7316 
7317                 // the visual area must be retrieved from the metafile (object doesn't know it so far)
7318 
7319                 if ( nAspect != embed::Aspects::MSOLE_ICON )
7320                 {
7321                     // working with visual area can switch the object to running state
7322                     awt::Size aAwtSz;
7323                     try
7324                     {
7325                         // the provided visual area should be used, if there is any
7326                         if ( rVisArea.IsEmpty() )
7327                         {
7328                             MapUnit aMapUnit = VCLUnoHelper::UnoEmbed2VCLMapUnit( xObj->getMapUnit( nAspect ) );
7329                             Size aSz(lcl_GetPrefSize(rGrf, MapMode(aMapUnit)));
7330                             aAwtSz.Width = aSz.Width();
7331                             aAwtSz.Height = aSz.Height();
7332                         }
7333                         else
7334                         {
7335                             aAwtSz.Width = rVisArea.GetWidth();
7336                             aAwtSz.Height = rVisArea.GetHeight();
7337                         }
7338                         //xInplaceObj->EnableSetModified( sal_False );
7339                         xObj->setVisualAreaSize( nAspect, aAwtSz );
7340                         //xInplaceObj->EnableSetModified( sal_True );
7341                     }
7342                     catch( const uno::Exception& )
7343                     {
7344                         OSL_FAIL( "Could not set visual area of the object!" );
7345                     }
7346                 }
7347 
7348                 svt::EmbeddedObjectRef aObj( xObj, nAspect );
7349 
7350                 // TODO/LATER: need MediaType
7351                 aObj.SetGraphic( rGrf, OUString() );
7352 
7353                 pRet = new SdrOle2Obj(
7354                     rSdrModel,
7355                     aObj,
7356                     aDstStgName,
7357                     rBoundRect);
7358             }
7359         }
7360     }
7361 
7362     return pRet;
7363 }
7364 
7365 bool SvxMSDffManager::SetPropValue( const uno::Any& rAny, const uno::Reference< css::beans::XPropertySet > & rXPropSet,
7366             const OUString& rPropName )
7367 {
7368     bool bRetValue = false;
7369     try
7370     {
7371         uno::Reference< beans::XPropertySetInfo >
7372             aXPropSetInfo( rXPropSet->getPropertySetInfo() );
7373         if ( aXPropSetInfo.is() )
7374             bRetValue = aXPropSetInfo->hasPropertyByName( rPropName );
7375     }
7376     catch( const uno::Exception& )
7377     {
7378         bRetValue = false;
7379     }
7380     if ( bRetValue )
7381     {
7382         try
7383         {
7384             rXPropSet->setPropertyValue( rPropName, rAny );
7385             bRetValue = true;
7386         }
7387         catch( const uno::Exception& )
7388         {
7389             bRetValue = false;
7390         }
7391     }
7392     return bRetValue;
7393 }
7394 
7395 SvxMSDffImportRec::SvxMSDffImportRec()
7396     : pObj( nullptr ),
7397       nClientAnchorLen(  0 ),
7398       nClientDataLen(    0 ),
7399       nXAlign( 0 ), // position n cm from left
7400       nYAlign( 0 ), // position n cm below
7401       nLayoutInTableCell( 0 ), // element is laid out in table cell
7402       nFlags( ShapeFlag::NONE ),
7403       nDxTextLeft( 144 ),
7404       nDyTextTop( 72 ),
7405       nDxTextRight( 144 ),
7406       nDyTextBottom( 72 ),
7407       nDxWrapDistLeft( 0 ),
7408       nDyWrapDistTop( 0 ),
7409       nDxWrapDistRight( 0 ),
7410       nDyWrapDistBottom(0 ),
7411       nCropFromTop( 0 ),
7412       nCropFromBottom( 0 ),
7413       nCropFromLeft( 0 ),
7414       nCropFromRight( 0 ),
7415       aTextId(),
7416       nNextShapeId( 0 ),
7417       nShapeId( 0 ),
7418       eShapeType( mso_sptNil ),
7419       relativeHorizontalWidth( -1 ),
7420       isHorizontalRule( false )
7421 {
7422       eLineStyle      = mso_lineSimple; // GPF-Bug #66227#
7423       eLineDashing    = mso_lineSolid;
7424       bDrawHell       = false;
7425       bHidden         = false;
7426 
7427       bReplaceByFly   = false;
7428       bVFlip          = false;
7429       bHFlip          = false;
7430       bAutoWidth      = false;
7431 }
7432 
7433 SvxMSDffImportRec::SvxMSDffImportRec(const SvxMSDffImportRec& rCopy)
7434     : pObj( rCopy.pObj ),
7435       nXAlign( rCopy.nXAlign ),
7436       nXRelTo( rCopy.nXRelTo ),
7437       nYAlign( rCopy.nYAlign ),
7438       nYRelTo( rCopy.nYRelTo ),
7439       nLayoutInTableCell( rCopy.nLayoutInTableCell ),
7440       nFlags( rCopy.nFlags ),
7441       nDxTextLeft( rCopy.nDxTextLeft    ),
7442       nDyTextTop( rCopy.nDyTextTop ),
7443       nDxTextRight( rCopy.nDxTextRight ),
7444       nDyTextBottom( rCopy.nDyTextBottom ),
7445       nDxWrapDistLeft( rCopy.nDxWrapDistLeft ),
7446       nDyWrapDistTop( rCopy.nDyWrapDistTop ),
7447       nDxWrapDistRight( rCopy.nDxWrapDistRight ),
7448       nDyWrapDistBottom(rCopy.nDyWrapDistBottom ),
7449       nCropFromTop( rCopy.nCropFromTop ),
7450       nCropFromBottom( rCopy.nCropFromBottom ),
7451       nCropFromLeft( rCopy.nCropFromLeft ),
7452       nCropFromRight( rCopy.nCropFromRight ),
7453       aTextId( rCopy.aTextId ),
7454       nNextShapeId( rCopy.nNextShapeId ),
7455       nShapeId( rCopy.nShapeId ),
7456       eShapeType( rCopy.eShapeType ),
7457       relativeHorizontalWidth( rCopy.relativeHorizontalWidth ),
7458       isHorizontalRule( rCopy.isHorizontalRule )
7459 {
7460     eLineStyle       = rCopy.eLineStyle; // GPF-Bug #66227#
7461     eLineDashing     = rCopy.eLineDashing;
7462     bDrawHell        = rCopy.bDrawHell;
7463     bHidden          = rCopy.bHidden;
7464     bReplaceByFly    = rCopy.bReplaceByFly;
7465     bAutoWidth       = rCopy.bAutoWidth;
7466     bVFlip = rCopy.bVFlip;
7467     bHFlip = rCopy.bHFlip;
7468     nClientAnchorLen = rCopy.nClientAnchorLen;
7469     if( rCopy.nClientAnchorLen )
7470     {
7471         pClientAnchorBuffer.reset( new char[ nClientAnchorLen ] );
7472         memcpy( pClientAnchorBuffer.get(),
7473                 rCopy.pClientAnchorBuffer.get(),
7474                 nClientAnchorLen );
7475     }
7476     else
7477         pClientAnchorBuffer = nullptr;
7478 
7479     nClientDataLen = rCopy.nClientDataLen;
7480     if( rCopy.nClientDataLen )
7481     {
7482         pClientDataBuffer.reset( new char[ nClientDataLen ] );
7483         memcpy( pClientDataBuffer.get(),
7484                 rCopy.pClientDataBuffer.get(),
7485                 nClientDataLen );
7486     }
7487     else
7488         pClientDataBuffer = nullptr;
7489 
7490     if (rCopy.pWrapPolygon)
7491         pWrapPolygon.reset( new tools::Polygon(*rCopy.pWrapPolygon) );
7492 }
7493 
7494 SvxMSDffImportRec::~SvxMSDffImportRec()
7495 {
7496 }
7497 
7498 void SvxMSDffManager::insertShapeId( sal_Int32 nShapeId, SdrObject* pShape )
7499 {
7500     maShapeIdContainer[nShapeId] = pShape;
7501 }
7502 
7503 void SvxMSDffManager::removeShapeId( SdrObject const * pShape )
7504 {
7505     SvxMSDffShapeIdContainer::iterator aIter( maShapeIdContainer.begin() );
7506     const SvxMSDffShapeIdContainer::iterator aEnd( maShapeIdContainer.end() );
7507     while( aIter != aEnd )
7508     {
7509         if( (*aIter).second == pShape )
7510         {
7511             maShapeIdContainer.erase( aIter );
7512             break;
7513         }
7514         ++aIter;
7515     }
7516 }
7517 
7518 SdrObject* SvxMSDffManager::getShapeForId( sal_Int32 nShapeId )
7519 {
7520     SvxMSDffShapeIdContainer::iterator aIter( maShapeIdContainer.find(nShapeId) );
7521     return aIter != maShapeIdContainer.end() ? (*aIter).second : nullptr;
7522 }
7523 
7524 SvxMSDffImportData::SvxMSDffImportData(const tools::Rectangle& rParentRect)
7525     : aParentRect(rParentRect)
7526 {
7527 }
7528 
7529 SvxMSDffImportData::~SvxMSDffImportData()
7530 {
7531 }
7532 
7533 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
7534