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