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