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